blob: 0adc7e0eeb398b9b5baa973d1de089d420f4886a [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 Dent51e76de2014-10-01 12:07:14 +010023import collections
Chris Dent878f3782014-06-30 17:04:15 +010024import datetime
Sean Dague655e0af2014-05-29 09:00:22 -040025import os
26import sys
27import unittest
Sean Dague655e0af2014-05-29 09:00:22 -040028
Matthew Treinish96e9e882014-06-09 18:37:19 -040029import yaml
Sean Dague655e0af2014-05-29 09:00:22 -040030
31import tempest.auth
Joe Gordon28a84ae2014-07-17 15:38:28 +000032from tempest import config
Sean Dague655e0af2014-05-29 09:00:22 -040033from tempest import exceptions
Joe Gordon915eb8e2014-07-17 11:25:46 +020034from tempest.openstack.common import log as logging
Chris Dent878f3782014-06-30 17:04:15 +010035from tempest.openstack.common import timeutils
Sean Dague655e0af2014-05-29 09:00:22 -040036from tempest.services.compute.json import flavors_client
37from tempest.services.compute.json import servers_client
38from tempest.services.identity.json import identity_client
39from tempest.services.image.v2.json import image_client
40from tempest.services.object_storage import container_client
41from tempest.services.object_storage import object_client
Chris Dent878f3782014-06-30 17:04:15 +010042from tempest.services.telemetry.json import telemetry_client
Emilien Macchi626b4f82014-06-15 21:44:29 +020043from tempest.services.volume.json import volumes_client
Sean Dague655e0af2014-05-29 09:00:22 -040044
45OPTS = {}
46USERS = {}
Chris Dent51e76de2014-10-01 12:07:14 +010047RES = collections.defaultdict(list)
Sean Dague655e0af2014-05-29 09:00:22 -040048
49LOG = None
50
Chris Dent878f3782014-06-30 17:04:15 +010051JAVELIN_START = datetime.datetime.utcnow()
52
Sean Dague655e0af2014-05-29 09:00:22 -040053
54class OSClient(object):
55 _creds = None
56 identity = None
57 servers = None
58
59 def __init__(self, user, pw, tenant):
60 _creds = tempest.auth.KeystoneV2Credentials(
61 username=user,
62 password=pw,
63 tenant_name=tenant)
64 _auth = tempest.auth.KeystoneV2AuthProvider(_creds)
65 self.identity = identity_client.IdentityClientJSON(_auth)
66 self.servers = servers_client.ServersClientJSON(_auth)
67 self.objects = object_client.ObjectClient(_auth)
68 self.containers = container_client.ContainerClient(_auth)
69 self.images = image_client.ImageClientV2JSON(_auth)
70 self.flavors = flavors_client.FlavorsClientJSON(_auth)
Chris Dent878f3782014-06-30 17:04:15 +010071 self.telemetry = telemetry_client.TelemetryClientJSON(_auth)
Emilien Macchi626b4f82014-06-15 21:44:29 +020072 self.volumes = volumes_client.VolumesClientJSON(_auth)
Sean Dague655e0af2014-05-29 09:00:22 -040073
74
75def load_resources(fname):
76 """Load the expected resources from a yaml flie."""
77 return yaml.load(open(fname, 'r'))
78
79
80def keystone_admin():
81 return OSClient(OPTS.os_username, OPTS.os_password, OPTS.os_tenant_name)
82
83
84def client_for_user(name):
85 LOG.debug("Entering client_for_user")
86 if name in USERS:
87 user = USERS[name]
88 LOG.debug("Created client for user %s" % user)
89 return OSClient(user['name'], user['pass'], user['tenant'])
90 else:
91 LOG.error("%s not found in USERS: %s" % (name, USERS))
92
93###################
94#
95# TENANTS
96#
97###################
98
99
100def create_tenants(tenants):
101 """Create tenants from resource definition.
102
103 Don't create the tenants if they already exist.
104 """
105 admin = keystone_admin()
106 _, body = admin.identity.list_tenants()
107 existing = [x['name'] for x in body]
108 for tenant in tenants:
109 if tenant not in existing:
110 admin.identity.create_tenant(tenant)
111 else:
112 LOG.warn("Tenant '%s' already exists in this environment" % tenant)
113
Emilien Macchibb71e072014-07-05 19:18:52 +0200114
115def destroy_tenants(tenants):
116 admin = keystone_admin()
117 for tenant in tenants:
118 tenant_id = admin.identity.get_tenant_by_name(tenant)['id']
119 r, body = admin.identity.delete_tenant(tenant_id)
120
Sean Dague655e0af2014-05-29 09:00:22 -0400121##############
122#
123# USERS
124#
125##############
126
127
128def _users_for_tenant(users, tenant):
129 u_for_t = []
130 for user in users:
131 for n in user:
132 if user[n]['tenant'] == tenant:
133 u_for_t.append(user[n])
134 return u_for_t
135
136
137def _tenants_from_users(users):
138 tenants = set()
139 for user in users:
140 for n in user:
141 tenants.add(user[n]['tenant'])
142 return tenants
143
144
145def _assign_swift_role(user):
146 admin = keystone_admin()
147 resp, roles = admin.identity.list_roles()
148 role = next(r for r in roles if r['name'] == 'Member')
149 LOG.debug(USERS[user])
150 try:
151 admin.identity.assign_user_role(
152 USERS[user]['tenant_id'],
153 USERS[user]['id'],
154 role['id'])
155 except exceptions.Conflict:
156 # don't care if it's already assigned
157 pass
158
159
160def create_users(users):
161 """Create tenants from resource definition.
162
163 Don't create the tenants if they already exist.
164 """
165 global USERS
166 LOG.info("Creating users")
167 admin = keystone_admin()
168 for u in users:
169 try:
170 tenant = admin.identity.get_tenant_by_name(u['tenant'])
171 except exceptions.NotFound:
172 LOG.error("Tenant: %s - not found" % u['tenant'])
173 continue
174 try:
175 admin.identity.get_user_by_username(tenant['id'], u['name'])
176 LOG.warn("User '%s' already exists in this environment"
177 % u['name'])
178 except exceptions.NotFound:
179 admin.identity.create_user(
180 u['name'], u['pass'], tenant['id'],
181 "%s@%s" % (u['name'], tenant['id']),
182 enabled=True)
183
184
Emilien Macchibb71e072014-07-05 19:18:52 +0200185def destroy_users(users):
186 admin = keystone_admin()
187 for user in users:
Emilien Macchi436de862014-09-30 17:09:50 -0400188 tenant_id = admin.identity.get_tenant_by_name(user['tenant'])['id']
189 user_id = admin.identity.get_user_by_username(tenant_id,
190 user['name'])['id']
Emilien Macchibb71e072014-07-05 19:18:52 +0200191 r, body = admin.identity.delete_user(user_id)
192
193
Sean Dague655e0af2014-05-29 09:00:22 -0400194def collect_users(users):
195 global USERS
Joe Gordon618c9fb2014-07-16 15:40:01 +0200196 LOG.info("Collecting users")
Sean Dague655e0af2014-05-29 09:00:22 -0400197 admin = keystone_admin()
198 for u in users:
199 tenant = admin.identity.get_tenant_by_name(u['tenant'])
200 u['tenant_id'] = tenant['id']
201 USERS[u['name']] = u
202 body = admin.identity.get_user_by_username(tenant['id'], u['name'])
203 USERS[u['name']]['id'] = body['id']
204
205
206class JavelinCheck(unittest.TestCase):
207 def __init__(self, users, resources):
208 super(JavelinCheck, self).__init__()
209 self.users = users
210 self.res = resources
211
212 def runTest(self, *args):
213 pass
214
215 def check(self):
216 self.check_users()
217 self.check_objects()
218 self.check_servers()
Emilien Macchid18fec12014-09-15 14:32:54 -0400219 self.check_volumes()
Chris Dent878f3782014-06-30 17:04:15 +0100220 self.check_telemetry()
Sean Dague655e0af2014-05-29 09:00:22 -0400221
222 def check_users(self):
223 """Check that the users we expect to exist, do.
224
225 We don't use the resource list for this because we need to validate
226 that things like tenantId didn't drift across versions.
227 """
Joe Gordon618c9fb2014-07-16 15:40:01 +0200228 LOG.info("checking users")
Sean Dague655e0af2014-05-29 09:00:22 -0400229 for name, user in self.users.iteritems():
230 client = keystone_admin()
231 _, found = client.identity.get_user(user['id'])
232 self.assertEqual(found['name'], user['name'])
233 self.assertEqual(found['tenantId'], user['tenant_id'])
234
235 # also ensure we can auth with that user, and do something
236 # on the cloud. We don't care about the results except that it
237 # remains authorized.
238 client = client_for_user(user['name'])
239 resp, body = client.servers.list_servers()
240 self.assertEqual(resp['status'], '200')
241
242 def check_objects(self):
243 """Check that the objects created are still there."""
Joe Gordon22cd6de2014-07-25 00:16:17 +0000244 if not self.res.get('objects'):
Joe Gordonb9bcdd82014-07-17 15:44:57 +0000245 return
Joe Gordon618c9fb2014-07-16 15:40:01 +0200246 LOG.info("checking objects")
Sean Dague655e0af2014-05-29 09:00:22 -0400247 for obj in self.res['objects']:
248 client = client_for_user(obj['owner'])
249 r, contents = client.objects.get_object(
250 obj['container'], obj['name'])
251 source = _file_contents(obj['file'])
252 self.assertEqual(contents, source)
253
254 def check_servers(self):
255 """Check that the servers are still up and running."""
Joe Gordon22cd6de2014-07-25 00:16:17 +0000256 if not self.res.get('servers'):
Joe Gordonb9bcdd82014-07-17 15:44:57 +0000257 return
Joe Gordon618c9fb2014-07-16 15:40:01 +0200258 LOG.info("checking servers")
Sean Dague655e0af2014-05-29 09:00:22 -0400259 for server in self.res['servers']:
260 client = client_for_user(server['owner'])
261 found = _get_server_by_name(client, server['name'])
262 self.assertIsNotNone(
263 found,
264 "Couldn't find expected server %s" % server['name'])
265
266 r, found = client.servers.get_server(found['id'])
267 # get the ipv4 address
268 addr = found['addresses']['private'][0]['addr']
Joe Gordonb6faa8b2014-07-24 23:42:35 +0000269 for count in range(60):
270 return_code = os.system("ping -c1 " + addr)
271 if return_code is 0:
272 break
273 self.assertNotEqual(count, 59,
Matthew Treinish1d14c542014-06-17 20:25:40 -0400274 "Server %s is not pingable at %s" % (
275 server['name'], addr))
Sean Dague655e0af2014-05-29 09:00:22 -0400276
Chris Dent878f3782014-06-30 17:04:15 +0100277 def check_telemetry(self):
278 """Check that ceilometer provides a sane sample.
279
280 Confirm that there are more than one sample and that they have the
281 expected metadata.
282
283 If in check mode confirm that the oldest sample available is from
284 before the upgrade.
285 """
Chris Dent0b76f2f2014-10-10 14:24:28 +0100286 if not self.res.get('telemetry'):
287 return
Chris Dent878f3782014-06-30 17:04:15 +0100288 LOG.info("checking telemetry")
289 for server in self.res['servers']:
290 client = client_for_user(server['owner'])
291 response, body = client.telemetry.list_samples(
292 'instance',
293 query=('metadata.display_name', 'eq', server['name'])
294 )
295 self.assertEqual(response.status, 200)
296 self.assertTrue(len(body) >= 1, 'expecting at least one sample')
297 self._confirm_telemetry_sample(server, body[-1])
298
Emilien Macchi626b4f82014-06-15 21:44:29 +0200299 def check_volumes(self):
300 """Check that the volumes are still there and attached."""
Joe Gordon22cd6de2014-07-25 00:16:17 +0000301 if not self.res.get('volumes'):
Joe Gordonb9bcdd82014-07-17 15:44:57 +0000302 return
Joe Gordon618c9fb2014-07-16 15:40:01 +0200303 LOG.info("checking volumes")
Emilien Macchi626b4f82014-06-15 21:44:29 +0200304 for volume in self.res['volumes']:
305 client = client_for_user(volume['owner'])
Emilien Macchid18fec12014-09-15 14:32:54 -0400306 vol_body = _get_volume_by_name(client, volume['name'])
Emilien Macchi626b4f82014-06-15 21:44:29 +0200307 self.assertIsNotNone(
Emilien Macchid18fec12014-09-15 14:32:54 -0400308 vol_body,
Emilien Macchi626b4f82014-06-15 21:44:29 +0200309 "Couldn't find expected volume %s" % volume['name'])
310
311 # Verify that a volume's attachment retrieved
312 server_id = _get_server_by_name(client, volume['server'])['id']
Emilien Macchid18fec12014-09-15 14:32:54 -0400313 attachment = client.volumes.get_attachment_from_volume(vol_body)
314 self.assertEqual(vol_body['id'], attachment['volume_id'])
Emilien Macchi626b4f82014-06-15 21:44:29 +0200315 self.assertEqual(server_id, attachment['server_id'])
316
Chris Dent878f3782014-06-30 17:04:15 +0100317 def _confirm_telemetry_sample(self, server, sample):
318 """Check this sample matches the expected resource metadata."""
319 # Confirm display_name
320 self.assertEqual(server['name'],
321 sample['resource_metadata']['display_name'])
322 # Confirm instance_type of flavor
323 flavor = sample['resource_metadata'].get(
324 'flavor.name',
325 sample['resource_metadata'].get('instance_type')
326 )
327 self.assertEqual(server['flavor'], flavor)
328 # Confirm the oldest sample was created before upgrade.
329 if OPTS.mode == 'check':
330 oldest_timestamp = timeutils.normalize_time(
331 timeutils.parse_isotime(sample['timestamp']))
332 self.assertTrue(
333 oldest_timestamp < JAVELIN_START,
334 'timestamp should come before start of second javelin run'
335 )
336
Sean Dague655e0af2014-05-29 09:00:22 -0400337
338#######################
339#
340# OBJECTS
341#
342#######################
343
344
345def _file_contents(fname):
346 with open(fname, 'r') as f:
347 return f.read()
348
349
350def create_objects(objects):
Joe Gordonb9bcdd82014-07-17 15:44:57 +0000351 if not objects:
352 return
Sean Dague655e0af2014-05-29 09:00:22 -0400353 LOG.info("Creating objects")
354 for obj in objects:
355 LOG.debug("Object %s" % obj)
356 _assign_swift_role(obj['owner'])
357 client = client_for_user(obj['owner'])
358 client.containers.create_container(obj['container'])
359 client.objects.create_object(
360 obj['container'], obj['name'],
361 _file_contents(obj['file']))
362
Emilien Macchibb71e072014-07-05 19:18:52 +0200363
364def destroy_objects(objects):
365 for obj in objects:
366 client = client_for_user(obj['owner'])
367 r, body = client.objects.delete_object(obj['container'], obj['name'])
Emilien Macchid70f5102014-09-10 09:54:49 -0400368 if not (200 <= int(r['status']) < 299):
Emilien Macchibb71e072014-07-05 19:18:52 +0200369 raise ValueError("unable to destroy object: [%s] %s" % (r, body))
370
371
Sean Dague655e0af2014-05-29 09:00:22 -0400372#######################
373#
374# IMAGES
375#
376#######################
377
378
Sean Dague319b37a2014-07-11 07:28:11 -0400379def _resolve_image(image, imgtype):
380 name = image[imgtype]
381 fname = os.path.join(OPTS.devstack_base, image['imgdir'], name)
382 return name, fname
383
384
Joe Gordon6f0426c2014-07-25 01:10:28 +0000385def _get_image_by_name(client, name):
386 r, body = client.images.image_list()
387 for image in body:
388 if name == image['name']:
389 return image
390 return None
391
392
Sean Dague655e0af2014-05-29 09:00:22 -0400393def create_images(images):
Joe Gordonb9bcdd82014-07-17 15:44:57 +0000394 if not images:
395 return
Joe Gordona18d6862014-07-24 22:55:46 +0000396 LOG.info("Creating images")
Sean Dague655e0af2014-05-29 09:00:22 -0400397 for image in images:
398 client = client_for_user(image['owner'])
399
400 # only upload a new image if the name isn't there
Joe Gordon6f0426c2014-07-25 01:10:28 +0000401 if _get_image_by_name(client, image['name']):
Joe Gordona18d6862014-07-24 22:55:46 +0000402 LOG.info("Image '%s' already exists" % image['name'])
Sean Dague655e0af2014-05-29 09:00:22 -0400403 continue
404
405 # special handling for 3 part image
406 extras = {}
407 if image['format'] == 'ami':
Sean Dague319b37a2014-07-11 07:28:11 -0400408 name, fname = _resolve_image(image, 'aki')
Sean Dague655e0af2014-05-29 09:00:22 -0400409 r, aki = client.images.create_image(
Sean Dague319b37a2014-07-11 07:28:11 -0400410 'javelin_' + name, 'aki', 'aki')
411 client.images.store_image(aki.get('id'), open(fname, 'r'))
Sean Dague655e0af2014-05-29 09:00:22 -0400412 extras['kernel_id'] = aki.get('id')
413
Sean Dague319b37a2014-07-11 07:28:11 -0400414 name, fname = _resolve_image(image, 'ari')
Sean Dague655e0af2014-05-29 09:00:22 -0400415 r, ari = client.images.create_image(
Sean Dague319b37a2014-07-11 07:28:11 -0400416 'javelin_' + name, 'ari', 'ari')
417 client.images.store_image(ari.get('id'), open(fname, 'r'))
Sean Dague655e0af2014-05-29 09:00:22 -0400418 extras['ramdisk_id'] = ari.get('id')
419
Sean Dague319b37a2014-07-11 07:28:11 -0400420 _, fname = _resolve_image(image, 'file')
Sean Dague655e0af2014-05-29 09:00:22 -0400421 r, body = client.images.create_image(
422 image['name'], image['format'], image['format'], **extras)
423 image_id = body.get('id')
Sean Dague319b37a2014-07-11 07:28:11 -0400424 client.images.store_image(image_id, open(fname, 'r'))
Sean Dague655e0af2014-05-29 09:00:22 -0400425
426
Joe Gordon6f0426c2014-07-25 01:10:28 +0000427def destroy_images(images):
428 if not images:
429 return
430 LOG.info("Destroying images")
431 for image in images:
432 client = client_for_user(image['owner'])
433
434 response = _get_image_by_name(client, image['name'])
435 if not response:
436 LOG.info("Image '%s' does not exists" % image['name'])
437 continue
438 client.images.delete_image(response['id'])
439
440
Sean Dague655e0af2014-05-29 09:00:22 -0400441#######################
442#
443# SERVERS
444#
445#######################
446
447def _get_server_by_name(client, name):
448 r, body = client.servers.list_servers()
449 for server in body['servers']:
450 if name == server['name']:
451 return server
452 return None
453
454
Sean Dague655e0af2014-05-29 09:00:22 -0400455def _get_flavor_by_name(client, name):
456 r, body = client.flavors.list_flavors()
457 for flavor in body:
458 if name == flavor['name']:
459 return flavor
460 return None
461
462
463def create_servers(servers):
Joe Gordonb9bcdd82014-07-17 15:44:57 +0000464 if not servers:
465 return
Joe Gordona18d6862014-07-24 22:55:46 +0000466 LOG.info("Creating servers")
Sean Dague655e0af2014-05-29 09:00:22 -0400467 for server in servers:
468 client = client_for_user(server['owner'])
469
470 if _get_server_by_name(client, server['name']):
Joe Gordona18d6862014-07-24 22:55:46 +0000471 LOG.info("Server '%s' already exists" % server['name'])
Sean Dague655e0af2014-05-29 09:00:22 -0400472 continue
473
474 image_id = _get_image_by_name(client, server['image'])['id']
475 flavor_id = _get_flavor_by_name(client, server['flavor'])['id']
Joe Gordon10f260b2014-07-24 23:27:19 +0000476 resp, body = client.servers.create_server(server['name'], image_id,
Matthew Treinish1d14c542014-06-17 20:25:40 -0400477 flavor_id)
Joe Gordon10f260b2014-07-24 23:27:19 +0000478 server_id = body['id']
479 client.servers.wait_for_server_status(server_id, 'ACTIVE')
Sean Dague655e0af2014-05-29 09:00:22 -0400480
481
Joe Gordondb63b1c2014-07-24 23:21:21 +0000482def destroy_servers(servers):
483 if not servers:
484 return
485 LOG.info("Destroying servers")
486 for server in servers:
487 client = client_for_user(server['owner'])
488
489 response = _get_server_by_name(client, server['name'])
490 if not response:
491 LOG.info("Server '%s' does not exist" % server['name'])
492 continue
493
494 client.servers.delete_server(response['id'])
495 client.servers.wait_for_server_termination(response['id'],
Matthew Treinish1d14c542014-06-17 20:25:40 -0400496 ignore_error=True)
Joe Gordondb63b1c2014-07-24 23:21:21 +0000497
498
Sean Dague655e0af2014-05-29 09:00:22 -0400499#######################
500#
Emilien Macchi626b4f82014-06-15 21:44:29 +0200501# VOLUMES
502#
503#######################
504
505def _get_volume_by_name(client, name):
506 r, body = client.volumes.list_volumes()
Emilien Macchid18fec12014-09-15 14:32:54 -0400507 for volume in body:
508 if name == volume['display_name']:
Emilien Macchi626b4f82014-06-15 21:44:29 +0200509 return volume
510 return None
511
512
513def create_volumes(volumes):
Chris Dent51e76de2014-10-01 12:07:14 +0100514 if not volumes:
515 return
516 LOG.info("Creating volumes")
Emilien Macchi626b4f82014-06-15 21:44:29 +0200517 for volume in volumes:
518 client = client_for_user(volume['owner'])
519
520 # only create a volume if the name isn't here
Emilien Macchid18fec12014-09-15 14:32:54 -0400521 if _get_volume_by_name(client, volume['name']):
522 LOG.info("volume '%s' already exists" % volume['name'])
Emilien Macchi626b4f82014-06-15 21:44:29 +0200523 continue
524
Emilien Macchid18fec12014-09-15 14:32:54 -0400525 size = volume['gb']
526 v_name = volume['name']
527 resp, body = client.volumes.create_volume(size=size,
528 display_name=v_name)
529 client.volumes.wait_for_volume_status(body['id'], 'available')
Emilien Macchi626b4f82014-06-15 21:44:29 +0200530
531
Emilien Macchibb71e072014-07-05 19:18:52 +0200532def destroy_volumes(volumes):
533 for volume in volumes:
534 client = client_for_user(volume['owner'])
535 volume_id = _get_volume_by_name(client, volume['name'])['id']
Emilien Macchi5ebc27b2014-09-15 14:30:35 -0400536 client.volumes.detach_volume(volume_id)
537 client.volumes.delete_volume(volume_id)
Emilien Macchibb71e072014-07-05 19:18:52 +0200538
539
Emilien Macchi626b4f82014-06-15 21:44:29 +0200540def attach_volumes(volumes):
541 for volume in volumes:
542 client = client_for_user(volume['owner'])
Emilien Macchi626b4f82014-06-15 21:44:29 +0200543 server_id = _get_server_by_name(client, volume['server'])['id']
Emilien Macchid18fec12014-09-15 14:32:54 -0400544 volume_id = _get_volume_by_name(client, volume['name'])['id']
545 device = volume['device']
546 client.volumes.attach_volume(volume_id, server_id, device)
Emilien Macchi626b4f82014-06-15 21:44:29 +0200547
548
549#######################
550#
Sean Dague655e0af2014-05-29 09:00:22 -0400551# MAIN LOGIC
552#
553#######################
554
555def create_resources():
556 LOG.info("Creating Resources")
557 # first create keystone level resources, and we need to be admin
558 # for those.
559 create_tenants(RES['tenants'])
560 create_users(RES['users'])
561 collect_users(RES['users'])
562
563 # next create resources in a well known order
564 create_objects(RES['objects'])
565 create_images(RES['images'])
566 create_servers(RES['servers'])
Emilien Macchid18fec12014-09-15 14:32:54 -0400567 create_volumes(RES['volumes'])
568 attach_volumes(RES['volumes'])
Sean Dague655e0af2014-05-29 09:00:22 -0400569
570
Joe Gordondb63b1c2014-07-24 23:21:21 +0000571def destroy_resources():
572 LOG.info("Destroying Resources")
573 # Destroy in inverse order of create
Joe Gordondb63b1c2014-07-24 23:21:21 +0000574 destroy_servers(RES['servers'])
Joe Gordon6f0426c2014-07-25 01:10:28 +0000575 destroy_images(RES['images'])
Emilien Macchibb71e072014-07-05 19:18:52 +0200576 destroy_objects(RES['objects'])
Emilien Macchibb71e072014-07-05 19:18:52 +0200577 destroy_volumes(RES['volumes'])
578 destroy_users(RES['users'])
579 destroy_tenants(RES['tenants'])
Joe Gordon6f0426c2014-07-25 01:10:28 +0000580 LOG.warn("Destroy mode incomplete")
581
Joe Gordondb63b1c2014-07-24 23:21:21 +0000582
Sean Dague655e0af2014-05-29 09:00:22 -0400583def get_options():
584 global OPTS
585 parser = argparse.ArgumentParser(
586 description='Create and validate a fixed set of OpenStack resources')
587 parser.add_argument('-m', '--mode',
588 metavar='<create|check|destroy>',
589 required=True,
590 help=('One of (create, check, destroy)'))
591 parser.add_argument('-r', '--resources',
592 required=True,
593 metavar='resourcefile.yaml',
594 help='Resources definition yaml file')
Joe Gordon28a84ae2014-07-17 15:38:28 +0000595
Sean Dague319b37a2014-07-11 07:28:11 -0400596 parser.add_argument(
597 '-d', '--devstack-base',
598 required=True,
599 metavar='/opt/stack/old',
600 help='Devstack base directory for retrieving artifacts')
Joe Gordon28a84ae2014-07-17 15:38:28 +0000601 parser.add_argument(
602 '-c', '--config-file',
603 metavar='/etc/tempest.conf',
604 help='path to javelin2(tempest) config file')
605
Sean Dague655e0af2014-05-29 09:00:22 -0400606 # auth bits, letting us also just source the devstack openrc
607 parser.add_argument('--os-username',
608 metavar='<auth-user-name>',
609 default=os.environ.get('OS_USERNAME'),
610 help=('Defaults to env[OS_USERNAME].'))
611 parser.add_argument('--os-password',
612 metavar='<auth-password>',
613 default=os.environ.get('OS_PASSWORD'),
614 help=('Defaults to env[OS_PASSWORD].'))
615 parser.add_argument('--os-tenant-name',
616 metavar='<auth-tenant-name>',
617 default=os.environ.get('OS_TENANT_NAME'),
618 help=('Defaults to env[OS_TENANT_NAME].'))
619
620 OPTS = parser.parse_args()
621 if OPTS.mode not in ('create', 'check', 'destroy'):
622 print("ERROR: Unknown mode -m %s\n" % OPTS.mode)
623 parser.print_help()
624 sys.exit(1)
Joe Gordon28a84ae2014-07-17 15:38:28 +0000625 if OPTS.config_file:
626 config.CONF.set_config_path(OPTS.config_file)
Sean Dague655e0af2014-05-29 09:00:22 -0400627
628
Joe Gordon915eb8e2014-07-17 11:25:46 +0200629def setup_logging():
Sean Dague655e0af2014-05-29 09:00:22 -0400630 global LOG
Joe Gordon915eb8e2014-07-17 11:25:46 +0200631 logging.setup(__name__)
Sean Dague655e0af2014-05-29 09:00:22 -0400632 LOG = logging.getLogger(__name__)
Sean Dague655e0af2014-05-29 09:00:22 -0400633
634
635def main():
636 global RES
637 get_options()
638 setup_logging()
Chris Dent51e76de2014-10-01 12:07:14 +0100639 RES.update(load_resources(OPTS.resources))
Sean Dague655e0af2014-05-29 09:00:22 -0400640
641 if OPTS.mode == 'create':
642 create_resources()
Joe Gordon1a097002014-07-24 23:44:08 +0000643 # Make sure the resources we just created actually work
644 checker = JavelinCheck(USERS, RES)
645 checker.check()
Sean Dague655e0af2014-05-29 09:00:22 -0400646 elif OPTS.mode == 'check':
647 collect_users(RES['users'])
648 checker = JavelinCheck(USERS, RES)
649 checker.check()
650 elif OPTS.mode == 'destroy':
Joe Gordondb63b1c2014-07-24 23:21:21 +0000651 collect_users(RES['users'])
652 destroy_resources()
Sean Dague655e0af2014-05-29 09:00:22 -0400653 else:
654 LOG.error('Unknown mode %s' % OPTS.mode)
655 return 1
Joe Gordon246353a2014-07-18 00:10:28 +0200656 LOG.info('javelin2 successfully finished')
Sean Dague655e0af2014-05-29 09:00:22 -0400657 return 0
658
659if __name__ == "__main__":
660 sys.exit(main())