blob: 3c41dd9971847e1e4763399e1a92b1f562fbdbb4 [file] [log] [blame]
Sean Dague655e0af2014-05-29 09:00:22 -04001#!/usr/bin/env python
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15"""Javelin makes resources that should survive an upgrade.
16
17Javelin is a tool for creating, verifying, and deleting a small set of
18resources in a declarative way.
19
20"""
21
Matthew Treinish96e9e882014-06-09 18:37:19 -040022import argparse
Chris Dent878f3782014-06-30 17:04:15 +010023import datetime
Sean Dague655e0af2014-05-29 09:00:22 -040024import os
25import sys
26import unittest
Sean Dague655e0af2014-05-29 09:00:22 -040027
Matthew Treinish96e9e882014-06-09 18:37:19 -040028import yaml
Sean Dague655e0af2014-05-29 09:00:22 -040029
30import tempest.auth
Joe Gordon28a84ae2014-07-17 15:38:28 +000031from tempest import config
Sean Dague655e0af2014-05-29 09:00:22 -040032from tempest import exceptions
Joe Gordon915eb8e2014-07-17 11:25:46 +020033from tempest.openstack.common import log as logging
Chris Dent878f3782014-06-30 17:04:15 +010034from tempest.openstack.common import timeutils
Sean Dague655e0af2014-05-29 09:00:22 -040035from tempest.services.compute.json import flavors_client
36from tempest.services.compute.json import servers_client
37from tempest.services.identity.json import identity_client
38from tempest.services.image.v2.json import image_client
39from tempest.services.object_storage import container_client
40from tempest.services.object_storage import object_client
Chris Dent878f3782014-06-30 17:04:15 +010041from tempest.services.telemetry.json import telemetry_client
Emilien Macchi626b4f82014-06-15 21:44:29 +020042from tempest.services.volume.json import volumes_client
Sean Dague655e0af2014-05-29 09:00:22 -040043
44OPTS = {}
45USERS = {}
46RES = {}
47
48LOG = None
49
Chris Dent878f3782014-06-30 17:04:15 +010050JAVELIN_START = datetime.datetime.utcnow()
51
Sean Dague655e0af2014-05-29 09:00:22 -040052
53class OSClient(object):
54 _creds = None
55 identity = None
56 servers = None
57
58 def __init__(self, user, pw, tenant):
59 _creds = tempest.auth.KeystoneV2Credentials(
60 username=user,
61 password=pw,
62 tenant_name=tenant)
63 _auth = tempest.auth.KeystoneV2AuthProvider(_creds)
64 self.identity = identity_client.IdentityClientJSON(_auth)
65 self.servers = servers_client.ServersClientJSON(_auth)
66 self.objects = object_client.ObjectClient(_auth)
67 self.containers = container_client.ContainerClient(_auth)
68 self.images = image_client.ImageClientV2JSON(_auth)
69 self.flavors = flavors_client.FlavorsClientJSON(_auth)
Chris Dent878f3782014-06-30 17:04:15 +010070 self.telemetry = telemetry_client.TelemetryClientJSON(_auth)
Emilien Macchi626b4f82014-06-15 21:44:29 +020071 self.volumes = volumes_client.VolumesClientJSON(_auth)
Sean Dague655e0af2014-05-29 09:00:22 -040072
73
74def load_resources(fname):
75 """Load the expected resources from a yaml flie."""
76 return yaml.load(open(fname, 'r'))
77
78
79def keystone_admin():
80 return OSClient(OPTS.os_username, OPTS.os_password, OPTS.os_tenant_name)
81
82
83def client_for_user(name):
84 LOG.debug("Entering client_for_user")
85 if name in USERS:
86 user = USERS[name]
87 LOG.debug("Created client for user %s" % user)
88 return OSClient(user['name'], user['pass'], user['tenant'])
89 else:
90 LOG.error("%s not found in USERS: %s" % (name, USERS))
91
92###################
93#
94# TENANTS
95#
96###################
97
98
99def create_tenants(tenants):
100 """Create tenants from resource definition.
101
102 Don't create the tenants if they already exist.
103 """
104 admin = keystone_admin()
105 _, body = admin.identity.list_tenants()
106 existing = [x['name'] for x in body]
107 for tenant in tenants:
108 if tenant not in existing:
109 admin.identity.create_tenant(tenant)
110 else:
111 LOG.warn("Tenant '%s' already exists in this environment" % tenant)
112
Emilien Macchibb71e072014-07-05 19:18:52 +0200113
114def destroy_tenants(tenants):
115 admin = keystone_admin()
116 for tenant in tenants:
117 tenant_id = admin.identity.get_tenant_by_name(tenant)['id']
118 r, body = admin.identity.delete_tenant(tenant_id)
119
Sean Dague655e0af2014-05-29 09:00:22 -0400120##############
121#
122# USERS
123#
124##############
125
126
127def _users_for_tenant(users, tenant):
128 u_for_t = []
129 for user in users:
130 for n in user:
131 if user[n]['tenant'] == tenant:
132 u_for_t.append(user[n])
133 return u_for_t
134
135
136def _tenants_from_users(users):
137 tenants = set()
138 for user in users:
139 for n in user:
140 tenants.add(user[n]['tenant'])
141 return tenants
142
143
144def _assign_swift_role(user):
145 admin = keystone_admin()
146 resp, roles = admin.identity.list_roles()
147 role = next(r for r in roles if r['name'] == 'Member')
148 LOG.debug(USERS[user])
149 try:
150 admin.identity.assign_user_role(
151 USERS[user]['tenant_id'],
152 USERS[user]['id'],
153 role['id'])
154 except exceptions.Conflict:
155 # don't care if it's already assigned
156 pass
157
158
159def create_users(users):
160 """Create tenants from resource definition.
161
162 Don't create the tenants if they already exist.
163 """
164 global USERS
165 LOG.info("Creating users")
166 admin = keystone_admin()
167 for u in users:
168 try:
169 tenant = admin.identity.get_tenant_by_name(u['tenant'])
170 except exceptions.NotFound:
171 LOG.error("Tenant: %s - not found" % u['tenant'])
172 continue
173 try:
174 admin.identity.get_user_by_username(tenant['id'], u['name'])
175 LOG.warn("User '%s' already exists in this environment"
176 % u['name'])
177 except exceptions.NotFound:
178 admin.identity.create_user(
179 u['name'], u['pass'], tenant['id'],
180 "%s@%s" % (u['name'], tenant['id']),
181 enabled=True)
182
183
Emilien Macchibb71e072014-07-05 19:18:52 +0200184def destroy_users(users):
185 admin = keystone_admin()
186 for user in users:
Emilien Macchi436de862014-09-30 17:09:50 -0400187 tenant_id = admin.identity.get_tenant_by_name(user['tenant'])['id']
188 user_id = admin.identity.get_user_by_username(tenant_id,
189 user['name'])['id']
Emilien Macchibb71e072014-07-05 19:18:52 +0200190 r, body = admin.identity.delete_user(user_id)
191
192
Sean Dague655e0af2014-05-29 09:00:22 -0400193def collect_users(users):
194 global USERS
Joe Gordon618c9fb2014-07-16 15:40:01 +0200195 LOG.info("Collecting users")
Sean Dague655e0af2014-05-29 09:00:22 -0400196 admin = keystone_admin()
197 for u in users:
198 tenant = admin.identity.get_tenant_by_name(u['tenant'])
199 u['tenant_id'] = tenant['id']
200 USERS[u['name']] = u
201 body = admin.identity.get_user_by_username(tenant['id'], u['name'])
202 USERS[u['name']]['id'] = body['id']
203
204
205class JavelinCheck(unittest.TestCase):
206 def __init__(self, users, resources):
207 super(JavelinCheck, self).__init__()
208 self.users = users
209 self.res = resources
210
211 def runTest(self, *args):
212 pass
213
214 def check(self):
215 self.check_users()
216 self.check_objects()
217 self.check_servers()
Emilien Macchid18fec12014-09-15 14:32:54 -0400218 self.check_volumes()
Chris Dent878f3782014-06-30 17:04:15 +0100219 self.check_telemetry()
Sean Dague655e0af2014-05-29 09:00:22 -0400220
221 def check_users(self):
222 """Check that the users we expect to exist, do.
223
224 We don't use the resource list for this because we need to validate
225 that things like tenantId didn't drift across versions.
226 """
Joe Gordon618c9fb2014-07-16 15:40:01 +0200227 LOG.info("checking users")
Sean Dague655e0af2014-05-29 09:00:22 -0400228 for name, user in self.users.iteritems():
229 client = keystone_admin()
230 _, found = client.identity.get_user(user['id'])
231 self.assertEqual(found['name'], user['name'])
232 self.assertEqual(found['tenantId'], user['tenant_id'])
233
234 # also ensure we can auth with that user, and do something
235 # on the cloud. We don't care about the results except that it
236 # remains authorized.
237 client = client_for_user(user['name'])
238 resp, body = client.servers.list_servers()
239 self.assertEqual(resp['status'], '200')
240
241 def check_objects(self):
242 """Check that the objects created are still there."""
Joe Gordon22cd6de2014-07-25 00:16:17 +0000243 if not self.res.get('objects'):
Joe Gordonb9bcdd82014-07-17 15:44:57 +0000244 return
Joe Gordon618c9fb2014-07-16 15:40:01 +0200245 LOG.info("checking objects")
Sean Dague655e0af2014-05-29 09:00:22 -0400246 for obj in self.res['objects']:
247 client = client_for_user(obj['owner'])
248 r, contents = client.objects.get_object(
249 obj['container'], obj['name'])
250 source = _file_contents(obj['file'])
251 self.assertEqual(contents, source)
252
253 def check_servers(self):
254 """Check that the servers are still up and running."""
Joe Gordon22cd6de2014-07-25 00:16:17 +0000255 if not self.res.get('servers'):
Joe Gordonb9bcdd82014-07-17 15:44:57 +0000256 return
Joe Gordon618c9fb2014-07-16 15:40:01 +0200257 LOG.info("checking servers")
Sean Dague655e0af2014-05-29 09:00:22 -0400258 for server in self.res['servers']:
259 client = client_for_user(server['owner'])
260 found = _get_server_by_name(client, server['name'])
261 self.assertIsNotNone(
262 found,
263 "Couldn't find expected server %s" % server['name'])
264
265 r, found = client.servers.get_server(found['id'])
266 # get the ipv4 address
267 addr = found['addresses']['private'][0]['addr']
Joe Gordonb6faa8b2014-07-24 23:42:35 +0000268 for count in range(60):
269 return_code = os.system("ping -c1 " + addr)
270 if return_code is 0:
271 break
272 self.assertNotEqual(count, 59,
Matthew Treinish1d14c542014-06-17 20:25:40 -0400273 "Server %s is not pingable at %s" % (
274 server['name'], addr))
Sean Dague655e0af2014-05-29 09:00:22 -0400275
Chris Dent878f3782014-06-30 17:04:15 +0100276 def check_telemetry(self):
277 """Check that ceilometer provides a sane sample.
278
279 Confirm that there are more than one sample and that they have the
280 expected metadata.
281
282 If in check mode confirm that the oldest sample available is from
283 before the upgrade.
284 """
285 LOG.info("checking telemetry")
286 for server in self.res['servers']:
287 client = client_for_user(server['owner'])
288 response, body = client.telemetry.list_samples(
289 'instance',
290 query=('metadata.display_name', 'eq', server['name'])
291 )
292 self.assertEqual(response.status, 200)
293 self.assertTrue(len(body) >= 1, 'expecting at least one sample')
294 self._confirm_telemetry_sample(server, body[-1])
295
Emilien Macchi626b4f82014-06-15 21:44:29 +0200296 def check_volumes(self):
297 """Check that the volumes are still there and attached."""
Joe Gordon22cd6de2014-07-25 00:16:17 +0000298 if not self.res.get('volumes'):
Joe Gordonb9bcdd82014-07-17 15:44:57 +0000299 return
Joe Gordon618c9fb2014-07-16 15:40:01 +0200300 LOG.info("checking volumes")
Emilien Macchi626b4f82014-06-15 21:44:29 +0200301 for volume in self.res['volumes']:
302 client = client_for_user(volume['owner'])
Emilien Macchid18fec12014-09-15 14:32:54 -0400303 vol_body = _get_volume_by_name(client, volume['name'])
Emilien Macchi626b4f82014-06-15 21:44:29 +0200304 self.assertIsNotNone(
Emilien Macchid18fec12014-09-15 14:32:54 -0400305 vol_body,
Emilien Macchi626b4f82014-06-15 21:44:29 +0200306 "Couldn't find expected volume %s" % volume['name'])
307
308 # Verify that a volume's attachment retrieved
309 server_id = _get_server_by_name(client, volume['server'])['id']
Emilien Macchid18fec12014-09-15 14:32:54 -0400310 attachment = client.volumes.get_attachment_from_volume(vol_body)
311 self.assertEqual(vol_body['id'], attachment['volume_id'])
Emilien Macchi626b4f82014-06-15 21:44:29 +0200312 self.assertEqual(server_id, attachment['server_id'])
313
Chris Dent878f3782014-06-30 17:04:15 +0100314 def _confirm_telemetry_sample(self, server, sample):
315 """Check this sample matches the expected resource metadata."""
316 # Confirm display_name
317 self.assertEqual(server['name'],
318 sample['resource_metadata']['display_name'])
319 # Confirm instance_type of flavor
320 flavor = sample['resource_metadata'].get(
321 'flavor.name',
322 sample['resource_metadata'].get('instance_type')
323 )
324 self.assertEqual(server['flavor'], flavor)
325 # Confirm the oldest sample was created before upgrade.
326 if OPTS.mode == 'check':
327 oldest_timestamp = timeutils.normalize_time(
328 timeutils.parse_isotime(sample['timestamp']))
329 self.assertTrue(
330 oldest_timestamp < JAVELIN_START,
331 'timestamp should come before start of second javelin run'
332 )
333
Sean Dague655e0af2014-05-29 09:00:22 -0400334
335#######################
336#
337# OBJECTS
338#
339#######################
340
341
342def _file_contents(fname):
343 with open(fname, 'r') as f:
344 return f.read()
345
346
347def create_objects(objects):
Joe Gordonb9bcdd82014-07-17 15:44:57 +0000348 if not objects:
349 return
Sean Dague655e0af2014-05-29 09:00:22 -0400350 LOG.info("Creating objects")
351 for obj in objects:
352 LOG.debug("Object %s" % obj)
353 _assign_swift_role(obj['owner'])
354 client = client_for_user(obj['owner'])
355 client.containers.create_container(obj['container'])
356 client.objects.create_object(
357 obj['container'], obj['name'],
358 _file_contents(obj['file']))
359
Emilien Macchibb71e072014-07-05 19:18:52 +0200360
361def destroy_objects(objects):
362 for obj in objects:
363 client = client_for_user(obj['owner'])
364 r, body = client.objects.delete_object(obj['container'], obj['name'])
Emilien Macchid70f5102014-09-10 09:54:49 -0400365 if not (200 <= int(r['status']) < 299):
Emilien Macchibb71e072014-07-05 19:18:52 +0200366 raise ValueError("unable to destroy object: [%s] %s" % (r, body))
367
368
Sean Dague655e0af2014-05-29 09:00:22 -0400369#######################
370#
371# IMAGES
372#
373#######################
374
375
Sean Dague319b37a2014-07-11 07:28:11 -0400376def _resolve_image(image, imgtype):
377 name = image[imgtype]
378 fname = os.path.join(OPTS.devstack_base, image['imgdir'], name)
379 return name, fname
380
381
Joe Gordon6f0426c2014-07-25 01:10:28 +0000382def _get_image_by_name(client, name):
383 r, body = client.images.image_list()
384 for image in body:
385 if name == image['name']:
386 return image
387 return None
388
389
Sean Dague655e0af2014-05-29 09:00:22 -0400390def create_images(images):
Joe Gordonb9bcdd82014-07-17 15:44:57 +0000391 if not images:
392 return
Joe Gordona18d6862014-07-24 22:55:46 +0000393 LOG.info("Creating images")
Sean Dague655e0af2014-05-29 09:00:22 -0400394 for image in images:
395 client = client_for_user(image['owner'])
396
397 # only upload a new image if the name isn't there
Joe Gordon6f0426c2014-07-25 01:10:28 +0000398 if _get_image_by_name(client, image['name']):
Joe Gordona18d6862014-07-24 22:55:46 +0000399 LOG.info("Image '%s' already exists" % image['name'])
Sean Dague655e0af2014-05-29 09:00:22 -0400400 continue
401
402 # special handling for 3 part image
403 extras = {}
404 if image['format'] == 'ami':
Sean Dague319b37a2014-07-11 07:28:11 -0400405 name, fname = _resolve_image(image, 'aki')
Sean Dague655e0af2014-05-29 09:00:22 -0400406 r, aki = client.images.create_image(
Sean Dague319b37a2014-07-11 07:28:11 -0400407 'javelin_' + name, 'aki', 'aki')
408 client.images.store_image(aki.get('id'), open(fname, 'r'))
Sean Dague655e0af2014-05-29 09:00:22 -0400409 extras['kernel_id'] = aki.get('id')
410
Sean Dague319b37a2014-07-11 07:28:11 -0400411 name, fname = _resolve_image(image, 'ari')
Sean Dague655e0af2014-05-29 09:00:22 -0400412 r, ari = client.images.create_image(
Sean Dague319b37a2014-07-11 07:28:11 -0400413 'javelin_' + name, 'ari', 'ari')
414 client.images.store_image(ari.get('id'), open(fname, 'r'))
Sean Dague655e0af2014-05-29 09:00:22 -0400415 extras['ramdisk_id'] = ari.get('id')
416
Sean Dague319b37a2014-07-11 07:28:11 -0400417 _, fname = _resolve_image(image, 'file')
Sean Dague655e0af2014-05-29 09:00:22 -0400418 r, body = client.images.create_image(
419 image['name'], image['format'], image['format'], **extras)
420 image_id = body.get('id')
Sean Dague319b37a2014-07-11 07:28:11 -0400421 client.images.store_image(image_id, open(fname, 'r'))
Sean Dague655e0af2014-05-29 09:00:22 -0400422
423
Joe Gordon6f0426c2014-07-25 01:10:28 +0000424def destroy_images(images):
425 if not images:
426 return
427 LOG.info("Destroying images")
428 for image in images:
429 client = client_for_user(image['owner'])
430
431 response = _get_image_by_name(client, image['name'])
432 if not response:
433 LOG.info("Image '%s' does not exists" % image['name'])
434 continue
435 client.images.delete_image(response['id'])
436
437
Sean Dague655e0af2014-05-29 09:00:22 -0400438#######################
439#
440# SERVERS
441#
442#######################
443
444def _get_server_by_name(client, name):
445 r, body = client.servers.list_servers()
446 for server in body['servers']:
447 if name == server['name']:
448 return server
449 return None
450
451
Sean Dague655e0af2014-05-29 09:00:22 -0400452def _get_flavor_by_name(client, name):
453 r, body = client.flavors.list_flavors()
454 for flavor in body:
455 if name == flavor['name']:
456 return flavor
457 return None
458
459
460def create_servers(servers):
Joe Gordonb9bcdd82014-07-17 15:44:57 +0000461 if not servers:
462 return
Joe Gordona18d6862014-07-24 22:55:46 +0000463 LOG.info("Creating servers")
Sean Dague655e0af2014-05-29 09:00:22 -0400464 for server in servers:
465 client = client_for_user(server['owner'])
466
467 if _get_server_by_name(client, server['name']):
Joe Gordona18d6862014-07-24 22:55:46 +0000468 LOG.info("Server '%s' already exists" % server['name'])
Sean Dague655e0af2014-05-29 09:00:22 -0400469 continue
470
471 image_id = _get_image_by_name(client, server['image'])['id']
472 flavor_id = _get_flavor_by_name(client, server['flavor'])['id']
Joe Gordon10f260b2014-07-24 23:27:19 +0000473 resp, body = client.servers.create_server(server['name'], image_id,
Matthew Treinish1d14c542014-06-17 20:25:40 -0400474 flavor_id)
Joe Gordon10f260b2014-07-24 23:27:19 +0000475 server_id = body['id']
476 client.servers.wait_for_server_status(server_id, 'ACTIVE')
Sean Dague655e0af2014-05-29 09:00:22 -0400477
478
Joe Gordondb63b1c2014-07-24 23:21:21 +0000479def destroy_servers(servers):
480 if not servers:
481 return
482 LOG.info("Destroying servers")
483 for server in servers:
484 client = client_for_user(server['owner'])
485
486 response = _get_server_by_name(client, server['name'])
487 if not response:
488 LOG.info("Server '%s' does not exist" % server['name'])
489 continue
490
491 client.servers.delete_server(response['id'])
492 client.servers.wait_for_server_termination(response['id'],
Matthew Treinish1d14c542014-06-17 20:25:40 -0400493 ignore_error=True)
Joe Gordondb63b1c2014-07-24 23:21:21 +0000494
495
Sean Dague655e0af2014-05-29 09:00:22 -0400496#######################
497#
Emilien Macchi626b4f82014-06-15 21:44:29 +0200498# VOLUMES
499#
500#######################
501
502def _get_volume_by_name(client, name):
503 r, body = client.volumes.list_volumes()
Emilien Macchid18fec12014-09-15 14:32:54 -0400504 for volume in body:
505 if name == volume['display_name']:
Emilien Macchi626b4f82014-06-15 21:44:29 +0200506 return volume
507 return None
508
509
510def create_volumes(volumes):
511 for volume in volumes:
512 client = client_for_user(volume['owner'])
513
514 # only create a volume if the name isn't here
Emilien Macchid18fec12014-09-15 14:32:54 -0400515 if _get_volume_by_name(client, volume['name']):
516 LOG.info("volume '%s' already exists" % volume['name'])
Emilien Macchi626b4f82014-06-15 21:44:29 +0200517 continue
518
Emilien Macchid18fec12014-09-15 14:32:54 -0400519 size = volume['gb']
520 v_name = volume['name']
521 resp, body = client.volumes.create_volume(size=size,
522 display_name=v_name)
523 client.volumes.wait_for_volume_status(body['id'], 'available')
Emilien Macchi626b4f82014-06-15 21:44:29 +0200524
525
Emilien Macchibb71e072014-07-05 19:18:52 +0200526def destroy_volumes(volumes):
527 for volume in volumes:
528 client = client_for_user(volume['owner'])
529 volume_id = _get_volume_by_name(client, volume['name'])['id']
Emilien Macchi5ebc27b2014-09-15 14:30:35 -0400530 client.volumes.detach_volume(volume_id)
531 client.volumes.delete_volume(volume_id)
Emilien Macchibb71e072014-07-05 19:18:52 +0200532
533
Emilien Macchi626b4f82014-06-15 21:44:29 +0200534def attach_volumes(volumes):
535 for volume in volumes:
536 client = client_for_user(volume['owner'])
Emilien Macchi626b4f82014-06-15 21:44:29 +0200537 server_id = _get_server_by_name(client, volume['server'])['id']
Emilien Macchid18fec12014-09-15 14:32:54 -0400538 volume_id = _get_volume_by_name(client, volume['name'])['id']
539 device = volume['device']
540 client.volumes.attach_volume(volume_id, server_id, device)
Emilien Macchi626b4f82014-06-15 21:44:29 +0200541
542
543#######################
544#
Sean Dague655e0af2014-05-29 09:00:22 -0400545# MAIN LOGIC
546#
547#######################
548
549def create_resources():
550 LOG.info("Creating Resources")
551 # first create keystone level resources, and we need to be admin
552 # for those.
553 create_tenants(RES['tenants'])
554 create_users(RES['users'])
555 collect_users(RES['users'])
556
557 # next create resources in a well known order
558 create_objects(RES['objects'])
559 create_images(RES['images'])
560 create_servers(RES['servers'])
Emilien Macchid18fec12014-09-15 14:32:54 -0400561 create_volumes(RES['volumes'])
562 attach_volumes(RES['volumes'])
Sean Dague655e0af2014-05-29 09:00:22 -0400563
564
Joe Gordondb63b1c2014-07-24 23:21:21 +0000565def destroy_resources():
566 LOG.info("Destroying Resources")
567 # Destroy in inverse order of create
Joe Gordondb63b1c2014-07-24 23:21:21 +0000568 destroy_servers(RES['servers'])
Joe Gordon6f0426c2014-07-25 01:10:28 +0000569 destroy_images(RES['images'])
Emilien Macchibb71e072014-07-05 19:18:52 +0200570 destroy_objects(RES['objects'])
Emilien Macchibb71e072014-07-05 19:18:52 +0200571 destroy_volumes(RES['volumes'])
572 destroy_users(RES['users'])
573 destroy_tenants(RES['tenants'])
Joe Gordon6f0426c2014-07-25 01:10:28 +0000574 LOG.warn("Destroy mode incomplete")
575
Joe Gordondb63b1c2014-07-24 23:21:21 +0000576
Sean Dague655e0af2014-05-29 09:00:22 -0400577def get_options():
578 global OPTS
579 parser = argparse.ArgumentParser(
580 description='Create and validate a fixed set of OpenStack resources')
581 parser.add_argument('-m', '--mode',
582 metavar='<create|check|destroy>',
583 required=True,
584 help=('One of (create, check, destroy)'))
585 parser.add_argument('-r', '--resources',
586 required=True,
587 metavar='resourcefile.yaml',
588 help='Resources definition yaml file')
Joe Gordon28a84ae2014-07-17 15:38:28 +0000589
Sean Dague319b37a2014-07-11 07:28:11 -0400590 parser.add_argument(
591 '-d', '--devstack-base',
592 required=True,
593 metavar='/opt/stack/old',
594 help='Devstack base directory for retrieving artifacts')
Joe Gordon28a84ae2014-07-17 15:38:28 +0000595 parser.add_argument(
596 '-c', '--config-file',
597 metavar='/etc/tempest.conf',
598 help='path to javelin2(tempest) config file')
599
Sean Dague655e0af2014-05-29 09:00:22 -0400600 # auth bits, letting us also just source the devstack openrc
601 parser.add_argument('--os-username',
602 metavar='<auth-user-name>',
603 default=os.environ.get('OS_USERNAME'),
604 help=('Defaults to env[OS_USERNAME].'))
605 parser.add_argument('--os-password',
606 metavar='<auth-password>',
607 default=os.environ.get('OS_PASSWORD'),
608 help=('Defaults to env[OS_PASSWORD].'))
609 parser.add_argument('--os-tenant-name',
610 metavar='<auth-tenant-name>',
611 default=os.environ.get('OS_TENANT_NAME'),
612 help=('Defaults to env[OS_TENANT_NAME].'))
613
614 OPTS = parser.parse_args()
615 if OPTS.mode not in ('create', 'check', 'destroy'):
616 print("ERROR: Unknown mode -m %s\n" % OPTS.mode)
617 parser.print_help()
618 sys.exit(1)
Joe Gordon28a84ae2014-07-17 15:38:28 +0000619 if OPTS.config_file:
620 config.CONF.set_config_path(OPTS.config_file)
Sean Dague655e0af2014-05-29 09:00:22 -0400621
622
Joe Gordon915eb8e2014-07-17 11:25:46 +0200623def setup_logging():
Sean Dague655e0af2014-05-29 09:00:22 -0400624 global LOG
Joe Gordon915eb8e2014-07-17 11:25:46 +0200625 logging.setup(__name__)
Sean Dague655e0af2014-05-29 09:00:22 -0400626 LOG = logging.getLogger(__name__)
Sean Dague655e0af2014-05-29 09:00:22 -0400627
628
629def main():
630 global RES
631 get_options()
632 setup_logging()
633 RES = load_resources(OPTS.resources)
634
635 if OPTS.mode == 'create':
636 create_resources()
Joe Gordon1a097002014-07-24 23:44:08 +0000637 # Make sure the resources we just created actually work
638 checker = JavelinCheck(USERS, RES)
639 checker.check()
Sean Dague655e0af2014-05-29 09:00:22 -0400640 elif OPTS.mode == 'check':
641 collect_users(RES['users'])
642 checker = JavelinCheck(USERS, RES)
643 checker.check()
644 elif OPTS.mode == 'destroy':
Joe Gordondb63b1c2014-07-24 23:21:21 +0000645 collect_users(RES['users'])
646 destroy_resources()
Sean Dague655e0af2014-05-29 09:00:22 -0400647 else:
648 LOG.error('Unknown mode %s' % OPTS.mode)
649 return 1
Joe Gordon246353a2014-07-18 00:10:28 +0200650 LOG.info('javelin2 successfully finished')
Sean Dague655e0af2014-05-29 09:00:22 -0400651 return 0
652
653if __name__ == "__main__":
654 sys.exit(main())