Browse code

add worlddump tool to devstack

when we exit poorly, start building a tool for doing a capture
as to why. This tool is expected to be consumed directly from
grenade as well.

Change-Id: Ia1bc1c2e259587035ca7252baceec25fa464cb82

Sean Dague authored on 2014/06/17 06:24:14
Showing 2 changed files
... ...
@@ -622,6 +622,11 @@ function exit_trap {
622 622
     # Kill the last spinner process
623 623
     kill_spinner
624 624
 
625
+    if [[ $r -ne 0 ]]; then
626
+        echo "Error on exit"
627
+        ./tools/worlddump.py -d $LOGDIR
628
+    fi
629
+
625 630
     exit $r
626 631
 }
627 632
 
628 633
new file mode 100755
... ...
@@ -0,0 +1,88 @@
0
+#!/usr/bin/env python
1
+#
2
+# Copyright 2014 Hewlett-Packard Development Company, L.P.
3
+#
4
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+# not use this file except in compliance with the License. You may obtain
6
+# a copy of the License at
7
+#
8
+#      http://www.apache.org/licenses/LICENSE-2.0
9
+#
10
+# Unless required by applicable law or agreed to in writing, software
11
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+# License for the specific language governing permissions and limitations
14
+# under the License.
15
+
16
+"""Dump the state of the world for post mortem."""
17
+
18
+import argparse
19
+import datetime
20
+import os
21
+import os.path
22
+import sys
23
+
24
+
25
+def get_options():
26
+    parser = argparse.ArgumentParser(
27
+        description='Dump world state for debugging')
28
+    parser.add_argument('-d', '--dir',
29
+                        default='.',
30
+                        help='Output directory for worlddump')
31
+    return parser.parse_args()
32
+
33
+
34
+def filename(dirname):
35
+    now = datetime.datetime.utcnow()
36
+    return os.path.join(dirname, now.strftime("worlddump-%Y-%m-%d-%H%M%S.txt"))
37
+
38
+
39
+def warn(msg):
40
+    print "WARN: %s" % msg
41
+
42
+
43
+def disk_space():
44
+    # the df output
45
+    print """
46
+File System Summary
47
+===================
48
+"""
49
+    dfraw = os.popen("df -Ph").read()
50
+    df = [s.split() for s in dfraw.splitlines()]
51
+    for fs in df:
52
+        try:
53
+            if int(fs[4][:-1]) > 95:
54
+                warn("Device %s (%s) is %s full, might be an issue" % (
55
+                    fs[0], fs[5], fs[4]))
56
+        except ValueError:
57
+            # if it doesn't look like an int, that's fine
58
+            pass
59
+
60
+    print dfraw
61
+
62
+
63
+def process_list():
64
+    print """
65
+Process Listing
66
+===============
67
+"""
68
+    psraw = os.popen("ps auxw").read()
69
+    print psraw
70
+
71
+
72
+def main():
73
+    opts = get_options()
74
+    fname = filename(opts.dir)
75
+    print "World dumping... see %s for details" % fname
76
+    sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
77
+    with open(fname, 'w') as f:
78
+        os.dup2(f.fileno(), sys.stdout.fileno())
79
+        disk_space()
80
+        process_list()
81
+
82
+
83
+if __name__ == '__main__':
84
+    try:
85
+        sys.exit(main())
86
+    except KeyboardInterrupt:
87
+        sys.exit(1)