~ubuntu-branches/ubuntu/quantal/nova/quantal-proposed

« back to all changes in this revision

Viewing changes to tools/xenserver/stress_test.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-08-16 14:04:11 UTC
  • mto: This revision was merged to the branch mainline in revision 84.
  • Revision ID: package-import@ubuntu.com-20120816140411-0mr4n241wmk30t9l
Tags: upstream-2012.2~f3
ImportĀ upstreamĀ versionĀ 2012.2~f3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""
 
2
This script concurrently builds and migrates instances. This can be useful when
 
3
troubleshooting race-conditions in virt-layer code.
 
4
 
 
5
Expects:
 
6
 
 
7
    novarc to be sourced in the environment
 
8
 
 
9
Helper Script for Xen Dom0:
 
10
 
 
11
    # cat /tmp/destroy_cache_vdis
 
12
    #!/bin/bash
 
13
    xe vdi-list | grep "Glance Image" -C1 | grep "^uuid" | awk '{print $5}' |
 
14
        xargs -n1 -I{} xe vdi-destroy uuid={}
 
15
"""
 
16
import argparse
 
17
import contextlib
 
18
import multiprocessing
 
19
import subprocess
 
20
import sys
 
21
import time
 
22
 
 
23
DOM0_CLEANUP_SCRIPT = "/tmp/destroy_cache_vdis"
 
24
 
 
25
 
 
26
def run(cmd):
 
27
    ret = subprocess.call(cmd, shell=True)
 
28
    if ret != 0:
 
29
        print >> sys.stderr, "Command exited non-zero: %s" % cmd
 
30
 
 
31
 
 
32
@contextlib.contextmanager
 
33
def server_built(server_name, image_name, flavor=1, cleanup=True):
 
34
    run("nova boot --image=%(image_name)s --flavor=%(flavor)s"
 
35
        " --poll %(server_name)s" % locals())
 
36
    try:
 
37
        yield
 
38
    finally:
 
39
        if cleanup:
 
40
            run("nova delete %(server_name)s" % locals())
 
41
 
 
42
 
 
43
@contextlib.contextmanager
 
44
def snapshot_taken(server_name, snapshot_name, cleanup=True):
 
45
    run("nova image-create %(server_name)s %(snapshot_name)s"
 
46
        " --poll" % locals())
 
47
    try:
 
48
        yield
 
49
    finally:
 
50
        if cleanup:
 
51
            run("nova image-delete %(snapshot_name)s" % locals())
 
52
 
 
53
 
 
54
def migrate_server(server_name):
 
55
    run("nova migrate %(server_name)s --poll" % locals())
 
56
 
 
57
    cmd = "nova list | grep %(server_name)s | awk '{print $6}'" % locals()
 
58
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
 
59
    stdout, stderr = proc.communicate()
 
60
    status = stdout.strip()
 
61
    if status.upper() != 'VERIFY_RESIZE':
 
62
        print >> sys.stderr, "Server %(server_name)s failed to rebuild"\
 
63
                             % locals()
 
64
        return False
 
65
 
 
66
    # Confirm the resize
 
67
    run("nova resize-confirm %(server_name)s" % locals())
 
68
    return True
 
69
 
 
70
 
 
71
def test_migrate(context):
 
72
    count, args = context
 
73
    server_name = "server%d" % count
 
74
    cleanup = args.cleanup
 
75
    with server_built(server_name, args.image, cleanup=cleanup):
 
76
        # Migrate A -> B
 
77
        result = migrate_server(server_name)
 
78
        if not result:
 
79
            return False
 
80
 
 
81
        # Migrate B -> A
 
82
        return migrate_server(server_name)
 
83
 
 
84
 
 
85
def rebuild_server(server_name, snapshot_name):
 
86
    run("nova rebuild %(server_name)s %(snapshot_name)s --poll" % locals())
 
87
 
 
88
    cmd = "nova list | grep %(server_name)s | awk '{print $6}'" % locals()
 
89
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
 
90
    stdout, stderr = proc.communicate()
 
91
    status = stdout.strip()
 
92
    if status != 'ACTIVE':
 
93
        print >> sys.stderr, "Server %(server_name)s failed to rebuild"\
 
94
                             % locals()
 
95
        return False
 
96
 
 
97
    return True
 
98
 
 
99
 
 
100
def test_rebuild(context):
 
101
    count, args = context
 
102
    server_name = "server%d" % count
 
103
    snapshot_name = "snap%d" % count
 
104
    cleanup = args.cleanup
 
105
    with server_built(server_name, args.image, cleanup=cleanup):
 
106
        with snapshot_taken(server_name, snapshot_name, cleanup=cleanup):
 
107
            return rebuild_server(server_name, snapshot_name)
 
108
 
 
109
 
 
110
def _parse_args():
 
111
    parser = argparse.ArgumentParser(
 
112
            description='Test Nova for Race Conditions.')
 
113
 
 
114
    parser.add_argument('tests', metavar='TESTS', type=str, nargs='*',
 
115
                        default=['rebuild', 'migrate'],
 
116
                        help='tests to run: [rebuilt|migrate]')
 
117
 
 
118
    parser.add_argument('-i', '--image', help="image to build from",
 
119
                        required=True)
 
120
    parser.add_argument('-n', '--num-runs', type=int, help="number of runs",
 
121
                        default=1)
 
122
    parser.add_argument('-c', '--concurrency', type=int, default=5,
 
123
                        help="number of concurrent processes")
 
124
    parser.add_argument('--no-cleanup', action='store_false', dest="cleanup",
 
125
                        default=True)
 
126
    parser.add_argument('-d', '--dom0-ips',
 
127
                        help="IP of dom0's to run cleanup script")
 
128
 
 
129
    return parser.parse_args()
 
130
 
 
131
 
 
132
def main():
 
133
    dom0_cleanup_script = DOM0_CLEANUP_SCRIPT
 
134
    args = _parse_args()
 
135
 
 
136
    if args.dom0_ips:
 
137
        dom0_ips = args.dom0_ips.split(',')
 
138
    else:
 
139
        dom0_ips = []
 
140
 
 
141
    start_time = time.time()
 
142
    batch_size = min(args.num_runs, args.concurrency)
 
143
    pool = multiprocessing.Pool(processes=args.concurrency)
 
144
 
 
145
    results = []
 
146
    for test in args.tests:
 
147
        test_func = globals().get("test_%s" % test)
 
148
        if not test_func:
 
149
            print >> sys.stderr, "test '%s' not found" % test
 
150
            sys.exit(1)
 
151
 
 
152
        contexts = [(x, args) for x in range(args.num_runs)]
 
153
 
 
154
        try:
 
155
            results += pool.map(test_func, contexts)
 
156
        finally:
 
157
            if args.cleanup:
 
158
                for dom0_ip in dom0_ips:
 
159
                    run("ssh root@%(dom0_ip)s %(dom0_cleanup_script)s"
 
160
                        % locals())
 
161
 
 
162
    success = all(results)
 
163
    result = "SUCCESS" if success else "FAILED"
 
164
 
 
165
    duration = time.time() - start_time
 
166
    print "%s, finished in %.2f secs" % (result, duration)
 
167
 
 
168
    sys.exit(0 if success else 1)
 
169
 
 
170
 
 
171
if __name__ == "__main__":
 
172
    main()