blob: dbade230072fc066e0b98d31e66fdedb39031a1b [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:
koder aka kdanilov3f356262015-02-13 08:06:14 -080052 time.sleep(1)
koder aka kdanilov4643fd62015-02-10 16:20:13 -080053 sstate = getattr(server, 'OS-EXT-STS:vm_state').lower()
54
55 if sstate == 'active':
56 return True
57
koder aka kdanilov4643fd62015-02-10 16:20:13 -080058 if sstate == 'error':
59 return False
60
61 if time.time() - t > timeout:
62 return False
63
64 server = nova.servers.get(server)
65
66
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080067class Allocate(object):
68 pass
69
70
71def get_floating_ips(nova, pool, amount):
koder aka kdanilov4643fd62015-02-10 16:20:13 -080072 ip_list = nova.floating_ips.list()
73
74 if pool is not None:
75 ip_list = [ip for ip in ip_list if ip.pool == pool]
76
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080077 return [ip for ip in ip_list if ip.instance_id is None][:amount]
koder aka kdanilov4643fd62015-02-10 16:20:13 -080078
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080079
80def create_vms_mt(nova, amount, keypair_name, img_name,
81 flavor_name, vol_sz=None, network_zone_name=None,
82 flt_ip_pool=None, name_templ='ceph-test-{}',
83 scheduler_hints=None):
84
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080085 with ThreadPoolExecutor(max_workers=16) as executor:
koder aka kdanilov97644f92015-02-13 11:11:08 -080086 if network_zone_name is not None:
87 network_future = executor.submit(nova.networks.find,
88 label=network_zone_name)
89 else:
90 network_future = None
91
92 fl_future = executor.submit(nova.flavors.find, name=flavor_name)
93 img_future = executor.submit(nova.images.find, name=img_name)
94
95 if flt_ip_pool is not None:
96 ips_future = executor.submit(get_floating_ips,
97 nova, flt_ip_pool, amount)
98 else:
99 ips_future = None
100
101 if ips_future is not None:
102 ips = ips_future.result()
103 ips += [Allocate] * (amount - len(ips))
104 else:
105 ips = [None] * amount
106
107 fl = fl_future.result()
108 img = img_future.result()
109
110 if network_future is not None:
111 nics = [{'net-id': network_future.result().id}]
112 else:
113 nics = None
114
115 print "Try to start {0} servers".format(amount)
116 names = map(name_templ.format, range(amount))
117
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800118 futures = []
119 for name, flt_ip in zip(names, ips):
120 params = (nova, name, keypair_name, img, fl,
121 nics, vol_sz, flt_ip, scheduler_hints,
122 flt_ip_pool)
123
124 futures.append(executor.submit(create_vm, *params))
125 return [future.result() for future in futures]
126
127
128def create_vm(nova, name, keypair_name, img,
129 fl, nics, vol_sz=None,
130 flt_ip=False,
131 scheduler_hints=None,
132 pool=None):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800133 for i in range(3):
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800134 srv = nova.servers.create(name,
135 flavor=fl, image=img, nics=nics,
136 key_name=keypair_name,
137 scheduler_hints=scheduler_hints)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800138
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800139 if not wait_for_server_active(nova, srv):
140 msg = "Server {0} fails to start. Kill it and try again"
141 print msg.format(srv.name)
142 nova.servers.delete(srv)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800143
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800144 while True:
koder aka kdanilov3f356262015-02-13 08:06:14 -0800145 # print "wait till server deleted"
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800146 all_id = set(alive_srv.id for alive_srv in nova.servers.list())
147 if srv.id not in all_id:
148 break
149 time.sleep(1)
150 else:
151 break
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800152
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800153 if vol_sz is not None:
koder aka kdanilov3f356262015-02-13 08:06:14 -0800154 # print "creating volume"
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800155 vol = create_volume(vol_sz, name)
koder aka kdanilov3f356262015-02-13 08:06:14 -0800156 # print "attach volume to server"
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800157 nova.volumes.create_server_volume(srv.id, vol.id, None)
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800158
159 if flt_ip is Allocate:
160 flt_ip = nova.floating_ips.create(pool)
161
162 if flt_ip is not None:
koder aka kdanilov3f356262015-02-13 08:06:14 -0800163 # print "attaching ip to server"
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800164 srv.add_floating_ip(flt_ip)
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800165 return (flt_ip.ip, srv)
166 else:
167 return (None, srv)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800168
169
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800170def clear_all(nova, name_templ="ceph-test-{}"):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800171 deleted_srvs = set()
172 for srv in nova.servers.list():
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800173 if re.match(name_templ.format("\\d+"), srv.name):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800174 print "Deleting server", srv.name
175 nova.servers.delete(srv)
176 deleted_srvs.add(srv.id)
177
178 while deleted_srvs != set():
179 print "Waiting till all servers are actually deleted"
180 all_id = set(srv.id for srv in nova.servers.list())
181 if all_id.intersection(deleted_srvs) == set():
182 print "Done, deleting volumes"
183 break
184 time.sleep(1)
185
186 # wait till vm actually deleted
187
188 cinder = c_client(*ostack_get_creds())
189 for vol in cinder.volumes.list():
190 if isinstance(vol.display_name, basestring):
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800191 if re.match(name_templ.format("\\d+"), vol.display_name):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800192 if vol.status in ('available', 'error'):
193 print "Deleting volume", vol.display_name
194 cinder.volumes.delete(vol)
195
196 print "Clearing done (yet some volumes may still deleting)"
197
198
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800199# def prepare_host(key_file, ip, fio_path, dst_fio_path, user='cirros'):
200# print "Wait till ssh ready...."
201# wait_ssh_ready(ip, user, key_file)
202
203# print "Preparing host >"
204# print " Coping fio"
205# copy_fio(key_file, ip, fio_path, user, dst_fio_path)
206
207# key_opts = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
208# args = (key_file, user, ip, key_opts)
209# cmd_format = "ssh {3} -i {0} {1}@{2} '{{0}}'".format(*args).format
210
211# def exec_on_host(cmd):
212# print " " + cmd
213# subprocess.check_call(cmd_format(cmd), shell=True)
214
215# exec_on_host("sudo /usr/sbin/mkfs.ext4 /dev/vdb")
216# exec_on_host("sudo /bin/mkdir /media/ceph")
217# exec_on_host("sudo /bin/mount /dev/vdb /media/ceph")
218# exec_on_host("sudo /bin/chmod a+rwx /media/ceph")
219
220
221def main():
222 image_name = 'TestVM'
223 flavor_name = 'ceph'
224 vol_sz = 50
225 network_zone_name = 'net04'
226 amount = 10
227 keypair_name = 'ceph-test'
228
229 nova = nova_connect()
230 clear_all(nova)
231
232 try:
233 ips = []
234 params = dict(vol_sz=vol_sz)
235 params['image_name'] = image_name
236 params['flavor_name'] = flavor_name
237 params['network_zone_name'] = network_zone_name
238 params['amount'] = amount
239 params['keypair_name'] = keypair_name
240
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800241 for ip, host in create_vms(nova, **params):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800242 ips.append(ip)
243
244 print "All setup done! Ips =", " ".join(ips)
245 print "Starting tests"
246 finally:
247 clear_all(nova)
248
249if __name__ == "__main__":
250 exit(main())