blob: 9a00b3412429b72b87d3ed87acd0a53e9427f1c0 [file] [log] [blame]
koder aka kdanilov4643fd62015-02-10 16:20:13 -08001import re
2import os
3import time
4
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -08005from concurrent.futures import ThreadPoolExecutor
6
koder aka kdanilov4643fd62015-02-10 16:20:13 -08007from novaclient.client import Client as n_client
8from cinderclient.v1.client import Client as c_client
9
10
11def ostack_get_creds():
12 env = os.environ.get
13 name = env('OS_USERNAME')
14 passwd = env('OS_PASSWORD')
15 tenant = env('OS_TENANT_NAME')
16 auth_url = env('OS_AUTH_URL')
17 return name, passwd, tenant, auth_url
18
19
20def nova_connect():
21 return n_client('1.1', *ostack_get_creds())
22
23
24def create_keypair(nova, name, key_path):
25 with open(key_path) as key:
26 return nova.keypairs.create(name, key.read())
27
28
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080029def create_volume(size, name):
koder aka kdanilov4643fd62015-02-10 16:20:13 -080030 cinder = c_client(*ostack_get_creds())
koder aka kdanilov4643fd62015-02-10 16:20:13 -080031 vol = cinder.volumes.create(size=size, display_name=name)
32 err_count = 0
33 while vol.status != 'available':
34 if vol.status == 'error':
35 if err_count == 3:
36 print "Fail to create volume"
37 raise RuntimeError("Fail to create volume")
38 else:
39 err_count += 1
40 cinder.volumes.delete(vol)
41 time.sleep(1)
42 vol = cinder.volumes.create(size=size, display_name=name)
43 continue
44 time.sleep(1)
45 vol = cinder.volumes.get(vol.id)
46 return vol
47
48
49def wait_for_server_active(nova, server, timeout=240):
50 t = time.time()
51 while True:
52 time.sleep(5)
53 sstate = getattr(server, 'OS-EXT-STS:vm_state').lower()
54
55 if sstate == 'active':
56 return True
57
58 print "Curr state is", sstate, "waiting for active"
59
60 if sstate == 'error':
61 return False
62
63 if time.time() - t > timeout:
64 return False
65
66 server = nova.servers.get(server)
67
68
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080069class Allocate(object):
70 pass
71
72
73def get_floating_ips(nova, pool, amount):
koder aka kdanilov4643fd62015-02-10 16:20:13 -080074 ip_list = nova.floating_ips.list()
75
76 if pool is not None:
77 ip_list = [ip for ip in ip_list if ip.pool == pool]
78
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080079 return [ip for ip in ip_list if ip.instance_id is None][:amount]
koder aka kdanilov4643fd62015-02-10 16:20:13 -080080
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080081
82def create_vms_mt(nova, amount, keypair_name, img_name,
83 flavor_name, vol_sz=None, network_zone_name=None,
84 flt_ip_pool=None, name_templ='ceph-test-{}',
85 scheduler_hints=None):
86
87 if network_zone_name is not None:
88 network = nova.networks.find(label=network_zone_name)
89 nics = [{'net-id': network.id}]
koder aka kdanilov4643fd62015-02-10 16:20:13 -080090 else:
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080091 nics = None
koder aka kdanilov4643fd62015-02-10 16:20:13 -080092
koder aka kdanilov4643fd62015-02-10 16:20:13 -080093 fl = nova.flavors.find(name=flavor_name)
94 img = nova.images.find(name=img_name)
koder aka kdanilov4643fd62015-02-10 16:20:13 -080095
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080096 if flt_ip_pool is not None:
97 ips = get_floating_ips(nova, flt_ip_pool, amount)
98 ips += [Allocate] * (amount - len(ips))
99 else:
100 ips = [None] * amount
101
102 print "Try to start {0} servers".format(amount)
103 names = map(name_templ.format, range(amount))
104
105 with ThreadPoolExecutor(max_workers=16) as executor:
106 futures = []
107 for name, flt_ip in zip(names, ips):
108 params = (nova, name, keypair_name, img, fl,
109 nics, vol_sz, flt_ip, scheduler_hints,
110 flt_ip_pool)
111
112 futures.append(executor.submit(create_vm, *params))
113 return [future.result() for future in futures]
114
115
116def create_vm(nova, name, keypair_name, img,
117 fl, nics, vol_sz=None,
118 flt_ip=False,
119 scheduler_hints=None,
120 pool=None):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800121 for i in range(3):
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800122 srv = nova.servers.create(name,
123 flavor=fl, image=img, nics=nics,
124 key_name=keypair_name,
125 scheduler_hints=scheduler_hints)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800126
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800127 if not wait_for_server_active(nova, srv):
128 msg = "Server {0} fails to start. Kill it and try again"
129 print msg.format(srv.name)
130 nova.servers.delete(srv)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800131
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800132 while True:
133 print "wait till server deleted"
134 all_id = set(alive_srv.id for alive_srv in nova.servers.list())
135 if srv.id not in all_id:
136 break
137 time.sleep(1)
138 else:
139 break
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800140
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800141 if vol_sz is not None:
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800142 print "creating volume"
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800143 vol = create_volume(vol_sz, name)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800144 print "attach volume to server"
145 nova.volumes.create_server_volume(srv.id, vol.id, None)
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800146
147 if flt_ip is Allocate:
148 flt_ip = nova.floating_ips.create(pool)
149
150 if flt_ip is not None:
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800151 print "attaching ip to server"
152 srv.add_floating_ip(flt_ip)
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800153 return (flt_ip.ip, srv)
154 else:
155 return (None, srv)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800156
157
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800158def clear_all(nova, name_templ="ceph-test-{}"):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800159 deleted_srvs = set()
160 for srv in nova.servers.list():
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800161 if re.match(name_templ.format("\\d+"), srv.name):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800162 print "Deleting server", srv.name
163 nova.servers.delete(srv)
164 deleted_srvs.add(srv.id)
165
166 while deleted_srvs != set():
167 print "Waiting till all servers are actually deleted"
168 all_id = set(srv.id for srv in nova.servers.list())
169 if all_id.intersection(deleted_srvs) == set():
170 print "Done, deleting volumes"
171 break
172 time.sleep(1)
173
174 # wait till vm actually deleted
175
176 cinder = c_client(*ostack_get_creds())
177 for vol in cinder.volumes.list():
178 if isinstance(vol.display_name, basestring):
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800179 if re.match(name_templ.format("\\d+"), vol.display_name):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800180 if vol.status in ('available', 'error'):
181 print "Deleting volume", vol.display_name
182 cinder.volumes.delete(vol)
183
184 print "Clearing done (yet some volumes may still deleting)"
185
186
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800187# def prepare_host(key_file, ip, fio_path, dst_fio_path, user='cirros'):
188# print "Wait till ssh ready...."
189# wait_ssh_ready(ip, user, key_file)
190
191# print "Preparing host >"
192# print " Coping fio"
193# copy_fio(key_file, ip, fio_path, user, dst_fio_path)
194
195# key_opts = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
196# args = (key_file, user, ip, key_opts)
197# cmd_format = "ssh {3} -i {0} {1}@{2} '{{0}}'".format(*args).format
198
199# def exec_on_host(cmd):
200# print " " + cmd
201# subprocess.check_call(cmd_format(cmd), shell=True)
202
203# exec_on_host("sudo /usr/sbin/mkfs.ext4 /dev/vdb")
204# exec_on_host("sudo /bin/mkdir /media/ceph")
205# exec_on_host("sudo /bin/mount /dev/vdb /media/ceph")
206# exec_on_host("sudo /bin/chmod a+rwx /media/ceph")
207
208
209def main():
210 image_name = 'TestVM'
211 flavor_name = 'ceph'
212 vol_sz = 50
213 network_zone_name = 'net04'
214 amount = 10
215 keypair_name = 'ceph-test'
216
217 nova = nova_connect()
218 clear_all(nova)
219
220 try:
221 ips = []
222 params = dict(vol_sz=vol_sz)
223 params['image_name'] = image_name
224 params['flavor_name'] = flavor_name
225 params['network_zone_name'] = network_zone_name
226 params['amount'] = amount
227 params['keypair_name'] = keypair_name
228
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800229 for ip, host in create_vms(nova, **params):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800230 ips.append(ip)
231
232 print "All setup done! Ips =", " ".join(ips)
233 print "Starting tests"
234 finally:
235 clear_all(nova)
236
237if __name__ == "__main__":
238 exit(main())