blob: 436162edb5ad12adedd411280b307417987476a3 [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 logging
25import 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
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:
187 user_id = admin.identity.get_user_by_name(user['name'])['id']
188 r, body = admin.identity.delete_user(user_id)
189
190
Sean Dague655e0af2014-05-29 09:00:22 -0400191def collect_users(users):
192 global USERS
Joe Gordon618c9fb2014-07-16 15:40:01 +0200193 LOG.info("Collecting users")
Sean Dague655e0af2014-05-29 09:00:22 -0400194 admin = keystone_admin()
195 for u in users:
196 tenant = admin.identity.get_tenant_by_name(u['tenant'])
197 u['tenant_id'] = tenant['id']
198 USERS[u['name']] = u
199 body = admin.identity.get_user_by_username(tenant['id'], u['name'])
200 USERS[u['name']]['id'] = body['id']
201
202
203class JavelinCheck(unittest.TestCase):
204 def __init__(self, users, resources):
205 super(JavelinCheck, self).__init__()
206 self.users = users
207 self.res = resources
208
209 def runTest(self, *args):
210 pass
211
212 def check(self):
213 self.check_users()
214 self.check_objects()
215 self.check_servers()
Sean Dague319b37a2014-07-11 07:28:11 -0400216 # TODO(sdague): Volumes not yet working, bring it back once the
217 # code is self testing.
218 # 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'])
303 found = _get_volume_by_name(client, volume['name'])
304 self.assertIsNotNone(
305 found,
306 "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']
310 attachment = self.client.get_attachment_from_volume(volume)
311 self.assertEqual(volume['id'], attachment['volume_id'])
312 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'])
365 if not (200 >= int(r['status']) < 299):
366 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()
504 for volume in body['volumes']:
505 if name == volume['name']:
506 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
515 r, body = client.volumes.list_volumes()
516 if any(item['name'] == volume['name'] for item in body):
517 continue
518
519 client.volumes.create_volume(volume['name'], volume['size'])
520
521
Emilien Macchibb71e072014-07-05 19:18:52 +0200522def destroy_volumes(volumes):
523 for volume in volumes:
524 client = client_for_user(volume['owner'])
525 volume_id = _get_volume_by_name(client, volume['name'])['id']
526 r, body = client.volumes.delete_volume(volume_id)
527
528
Emilien Macchi626b4f82014-06-15 21:44:29 +0200529def attach_volumes(volumes):
530 for volume in volumes:
531 client = client_for_user(volume['owner'])
532
533 server_id = _get_server_by_name(client, volume['server'])['id']
534 client.volumes.attach_volume(volume['name'], server_id)
535
536
537#######################
538#
Sean Dague655e0af2014-05-29 09:00:22 -0400539# MAIN LOGIC
540#
541#######################
542
543def create_resources():
544 LOG.info("Creating Resources")
545 # first create keystone level resources, and we need to be admin
546 # for those.
547 create_tenants(RES['tenants'])
548 create_users(RES['users'])
549 collect_users(RES['users'])
550
551 # next create resources in a well known order
552 create_objects(RES['objects'])
553 create_images(RES['images'])
554 create_servers(RES['servers'])
Sean Dague319b37a2014-07-11 07:28:11 -0400555 # TODO(sdague): volumes definition doesn't work yet, bring it
556 # back once we're actually executing the code
557 # create_volumes(RES['volumes'])
558 # attach_volumes(RES['volumes'])
Sean Dague655e0af2014-05-29 09:00:22 -0400559
560
Joe Gordondb63b1c2014-07-24 23:21:21 +0000561def destroy_resources():
562 LOG.info("Destroying Resources")
563 # Destroy in inverse order of create
Joe Gordondb63b1c2014-07-24 23:21:21 +0000564 destroy_servers(RES['servers'])
Joe Gordon6f0426c2014-07-25 01:10:28 +0000565 destroy_images(RES['images'])
Emilien Macchibb71e072014-07-05 19:18:52 +0200566 destroy_objects(RES['objects'])
567 destroy_servers(RES['servers'])
568 destroy_volumes(RES['volumes'])
569 destroy_users(RES['users'])
570 destroy_tenants(RES['tenants'])
Joe Gordon6f0426c2014-07-25 01:10:28 +0000571 LOG.warn("Destroy mode incomplete")
572
Joe Gordondb63b1c2014-07-24 23:21:21 +0000573
Sean Dague655e0af2014-05-29 09:00:22 -0400574def get_options():
575 global OPTS
576 parser = argparse.ArgumentParser(
577 description='Create and validate a fixed set of OpenStack resources')
578 parser.add_argument('-m', '--mode',
579 metavar='<create|check|destroy>',
580 required=True,
581 help=('One of (create, check, destroy)'))
582 parser.add_argument('-r', '--resources',
583 required=True,
584 metavar='resourcefile.yaml',
585 help='Resources definition yaml file')
Joe Gordon28a84ae2014-07-17 15:38:28 +0000586
Sean Dague319b37a2014-07-11 07:28:11 -0400587 parser.add_argument(
588 '-d', '--devstack-base',
589 required=True,
590 metavar='/opt/stack/old',
591 help='Devstack base directory for retrieving artifacts')
Joe Gordon28a84ae2014-07-17 15:38:28 +0000592 parser.add_argument(
593 '-c', '--config-file',
594 metavar='/etc/tempest.conf',
595 help='path to javelin2(tempest) config file')
596
Sean Dague655e0af2014-05-29 09:00:22 -0400597 # auth bits, letting us also just source the devstack openrc
598 parser.add_argument('--os-username',
599 metavar='<auth-user-name>',
600 default=os.environ.get('OS_USERNAME'),
601 help=('Defaults to env[OS_USERNAME].'))
602 parser.add_argument('--os-password',
603 metavar='<auth-password>',
604 default=os.environ.get('OS_PASSWORD'),
605 help=('Defaults to env[OS_PASSWORD].'))
606 parser.add_argument('--os-tenant-name',
607 metavar='<auth-tenant-name>',
608 default=os.environ.get('OS_TENANT_NAME'),
609 help=('Defaults to env[OS_TENANT_NAME].'))
610
611 OPTS = parser.parse_args()
612 if OPTS.mode not in ('create', 'check', 'destroy'):
613 print("ERROR: Unknown mode -m %s\n" % OPTS.mode)
614 parser.print_help()
615 sys.exit(1)
Joe Gordon28a84ae2014-07-17 15:38:28 +0000616 if OPTS.config_file:
617 config.CONF.set_config_path(OPTS.config_file)
Sean Dague655e0af2014-05-29 09:00:22 -0400618
619
620def setup_logging(debug=True):
621 global LOG
622 LOG = logging.getLogger(__name__)
623 if debug:
624 LOG.setLevel(logging.DEBUG)
625 else:
626 LOG.setLevel(logging.INFO)
627
628 ch = logging.StreamHandler(sys.stdout)
629 ch.setLevel(logging.DEBUG)
630 formatter = logging.Formatter(
631 datefmt='%Y-%m-%d %H:%M:%S',
632 fmt='%(asctime)s.%(msecs).03d - %(levelname)s - %(message)s')
633 ch.setFormatter(formatter)
634 LOG.addHandler(ch)
635
636
637def main():
638 global RES
639 get_options()
640 setup_logging()
641 RES = load_resources(OPTS.resources)
642
643 if OPTS.mode == 'create':
644 create_resources()
Joe Gordon1a097002014-07-24 23:44:08 +0000645 # Make sure the resources we just created actually work
646 checker = JavelinCheck(USERS, RES)
647 checker.check()
Sean Dague655e0af2014-05-29 09:00:22 -0400648 elif OPTS.mode == 'check':
649 collect_users(RES['users'])
650 checker = JavelinCheck(USERS, RES)
651 checker.check()
652 elif OPTS.mode == 'destroy':
Joe Gordondb63b1c2014-07-24 23:21:21 +0000653 collect_users(RES['users'])
654 destroy_resources()
Sean Dague655e0af2014-05-29 09:00:22 -0400655 else:
656 LOG.error('Unknown mode %s' % OPTS.mode)
657 return 1
Joe Gordon246353a2014-07-18 00:10:28 +0200658 LOG.info('javelin2 successfully finished')
Sean Dague655e0af2014-05-29 09:00:22 -0400659 return 0
660
661if __name__ == "__main__":
662 sys.exit(main())