blob: b52c2d5e4bf6e920014928a4d0b36bafdc3f3228 [file] [log] [blame]
koder aka kdanilov4643fd62015-02-10 16:20:13 -08001import re
2import os
3import time
4
5import paramiko
6from novaclient.client import Client as n_client
7from cinderclient.v1.client import Client as c_client
8
9
10def ostack_get_creds():
11 env = os.environ.get
12 name = env('OS_USERNAME')
13 passwd = env('OS_PASSWORD')
14 tenant = env('OS_TENANT_NAME')
15 auth_url = env('OS_AUTH_URL')
16 return name, passwd, tenant, auth_url
17
18
19def nova_connect():
20 return n_client('1.1', *ostack_get_creds())
21
22
23def create_keypair(nova, name, key_path):
24 with open(key_path) as key:
25 return nova.keypairs.create(name, key.read())
26
27
28def create_volume(size, name=None, volid=[0]):
29 cinder = c_client(*ostack_get_creds())
30 name = 'ceph-test-{0}'.format(volid[0])
31 volid[0] = volid[0] + 1
32 vol = cinder.volumes.create(size=size, display_name=name)
33 err_count = 0
34 while vol.status != 'available':
35 if vol.status == 'error':
36 if err_count == 3:
37 print "Fail to create volume"
38 raise RuntimeError("Fail to create volume")
39 else:
40 err_count += 1
41 cinder.volumes.delete(vol)
42 time.sleep(1)
43 vol = cinder.volumes.create(size=size, display_name=name)
44 continue
45 time.sleep(1)
46 vol = cinder.volumes.get(vol.id)
47 return vol
48
49
50def wait_for_server_active(nova, server, timeout=240):
51 t = time.time()
52 while True:
53 time.sleep(5)
54 sstate = getattr(server, 'OS-EXT-STS:vm_state').lower()
55
56 if sstate == 'active':
57 return True
58
59 print "Curr state is", sstate, "waiting for active"
60
61 if sstate == 'error':
62 return False
63
64 if time.time() - t > timeout:
65 return False
66
67 server = nova.servers.get(server)
68
69
70def get_or_create_floating_ip(nova, pool, used_ip):
71 ip_list = nova.floating_ips.list()
72
73 if pool is not None:
74 ip_list = [ip for ip in ip_list if ip.pool == pool]
75
76 ip_list = [ip for ip in ip_list if ip.instance_id is None]
77 ip_list = [ip for ip in ip_list if ip.ip not in used_ip]
78
79 if len(ip_list) > 0:
80 return ip_list[0]
81 else:
82 return nova.floating_ips.create(pool)
83
84
85def create_vms(nova, amount, keypair_name, img_name,
86 flavor_name, vol_sz, network_zone_name=None):
87
88 network = nova.networks.find(label=network_zone_name)
89 nics = [{'net-id': network.id}]
90 fl = nova.flavors.find(name=flavor_name)
91 img = nova.images.find(name=img_name)
92 srvs = []
93 counter = 0
94
95 for i in range(3):
96 amount_left = amount - len(srvs)
97
98 new_srvs = []
99 for i in range(amount_left):
100 print "creating server"
101 srv = nova.servers.create("ceph-test-{0}".format(counter),
102 flavor=fl, image=img, nics=nics,
103 key_name=keypair_name)
104 counter += 1
105 new_srvs.append(srv)
106 print srv
107
108 deleted_servers = []
109 for srv in new_srvs:
110 if not wait_for_server_active(nova, srv):
111 print "Server", srv.name, "fails to start. Kill it and",
112 print " try again"
113
114 nova.servers.delete(srv)
115 deleted_servers.append(srv)
116 else:
117 srvs.append(srv)
118
119 if len(deleted_servers) != 0:
120 time.sleep(5)
121
122 if len(srvs) != amount:
123 print "ERROR: can't start required amount of servers. Exit"
124 raise RuntimeError("Fail to create {0} servers".format(amount))
125
126 result = {}
127 for srv in srvs:
128 print "wait till server be ready"
129 wait_for_server_active(nova, srv)
130 print "creating volume"
131 vol = create_volume(vol_sz)
132 print "attach volume to server"
133 nova.volumes.create_server_volume(srv.id, vol.id, None)
134 print "create floating ip"
135 flt_ip = get_or_create_floating_ip(nova, 'net04_ext', result.keys())
136 print "attaching ip to server"
137 srv.add_floating_ip(flt_ip)
138 result[flt_ip.ip] = srv
139
140 return result
141
142
143def clear_all(nova):
144 deleted_srvs = set()
145 for srv in nova.servers.list():
146 if re.match(r"ceph-test-\d+", srv.name):
147 print "Deleting server", srv.name
148 nova.servers.delete(srv)
149 deleted_srvs.add(srv.id)
150
151 while deleted_srvs != set():
152 print "Waiting till all servers are actually deleted"
153 all_id = set(srv.id for srv in nova.servers.list())
154 if all_id.intersection(deleted_srvs) == set():
155 print "Done, deleting volumes"
156 break
157 time.sleep(1)
158
159 # wait till vm actually deleted
160
161 cinder = c_client(*ostack_get_creds())
162 for vol in cinder.volumes.list():
163 if isinstance(vol.display_name, basestring):
164 if re.match(r'ceph-test-\d+', vol.display_name):
165 if vol.status in ('available', 'error'):
166 print "Deleting volume", vol.display_name
167 cinder.volumes.delete(vol)
168
169 print "Clearing done (yet some volumes may still deleting)"
170
171
172def wait_ssh_ready(host, user, key_file, retry_count=10, timeout=5):
173 ssh = paramiko.SSHClient()
174 ssh.load_host_keys('/dev/null')
175 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
176 ssh.known_hosts = None
177
178 for i in range(retry_count):
179 try:
180 ssh.connect(host, username=user, key_filename=key_file,
181 look_for_keys=False)
182 break
183 except:
184 if i == retry_count - 1:
185 raise
186 time.sleep(timeout)
187
188
189# def prepare_host(key_file, ip, fio_path, dst_fio_path, user='cirros'):
190# print "Wait till ssh ready...."
191# wait_ssh_ready(ip, user, key_file)
192
193# print "Preparing host >"
194# print " Coping fio"
195# copy_fio(key_file, ip, fio_path, user, dst_fio_path)
196
197# key_opts = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
198# args = (key_file, user, ip, key_opts)
199# cmd_format = "ssh {3} -i {0} {1}@{2} '{{0}}'".format(*args).format
200
201# def exec_on_host(cmd):
202# print " " + cmd
203# subprocess.check_call(cmd_format(cmd), shell=True)
204
205# exec_on_host("sudo /usr/sbin/mkfs.ext4 /dev/vdb")
206# exec_on_host("sudo /bin/mkdir /media/ceph")
207# exec_on_host("sudo /bin/mount /dev/vdb /media/ceph")
208# exec_on_host("sudo /bin/chmod a+rwx /media/ceph")
209
210
211def main():
212 image_name = 'TestVM'
213 flavor_name = 'ceph'
214 vol_sz = 50
215 network_zone_name = 'net04'
216 amount = 10
217 keypair_name = 'ceph-test'
218
219 nova = nova_connect()
220 clear_all(nova)
221
222 try:
223 ips = []
224 params = dict(vol_sz=vol_sz)
225 params['image_name'] = image_name
226 params['flavor_name'] = flavor_name
227 params['network_zone_name'] = network_zone_name
228 params['amount'] = amount
229 params['keypair_name'] = keypair_name
230
231 for ip, host in create_vms(nova, **params).items():
232 ips.append(ip)
233
234 print "All setup done! Ips =", " ".join(ips)
235 print "Starting tests"
236 finally:
237 clear_all(nova)
238
239if __name__ == "__main__":
240 exit(main())