| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 1 | #!/usr/bin/env python | 
|  | 2 | # | 
|  | 3 | # Copyright 2014 Dell Inc. | 
|  | 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may | 
|  | 5 | # not use this file except in compliance with the License. You may obtain | 
|  | 6 | # a copy of the License at | 
|  | 7 | # | 
|  | 8 | #      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | # | 
|  | 10 | # Unless required by applicable law or agreed to in writing, software | 
|  | 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | 
| David Paterson | d6babc5 | 2014-10-14 00:11:56 -0400 | [diff] [blame] | 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 13 | # License for the specific language governing permissions and limitations | 
|  | 14 | # under the License. | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 15 |  | 
|  | 16 | """ | 
|  | 17 | Utility for cleaning up environment after Tempest run | 
|  | 18 |  | 
|  | 19 | Runtime Arguments | 
|  | 20 | ----------------- | 
|  | 21 |  | 
| Joe H. Rahme | 8bd59e0 | 2014-12-19 13:53:50 +0200 | [diff] [blame] | 22 | **--init-saved-state**: Before you can execute cleanup you must initialize | 
|  | 23 | the saved state by running it with the **--init-saved-state** flag | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 24 | (creating ./saved_state.json), which protects your deployment from | 
|  | 25 | cleanup deleting objects you want to keep.  Typically you would run | 
| Joe H. Rahme | 8bd59e0 | 2014-12-19 13:53:50 +0200 | [diff] [blame] | 26 | cleanup with **--init-saved-state** prior to a tempest run. If this is not | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 27 | the case saved_state.json must be edited, removing objects you want | 
|  | 28 | cleanup to delete. | 
|  | 29 |  | 
| Joe H. Rahme | 8bd59e0 | 2014-12-19 13:53:50 +0200 | [diff] [blame] | 30 | **--dry-run**: Creates a report (dry_run.json) of the tenants that will be | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 31 | cleaned up (in the "_tenants_to_clean" array), and the global objects | 
|  | 32 | that will be removed (tenants, users, flavors and images).  Once | 
| Joe H. Rahme | 8bd59e0 | 2014-12-19 13:53:50 +0200 | [diff] [blame] | 33 | cleanup is executed in normal mode, running it again with **--dry-run** | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 34 | should yield an empty report. | 
|  | 35 |  | 
|  | 36 | **NOTE**: The _tenants_to_clean array in dry-run.json lists the | 
|  | 37 | tenants that cleanup will loop through and delete child objects, not | 
|  | 38 | delete the tenant itself. This may differ from the tenants array as you | 
| David Paterson | d6babc5 | 2014-10-14 00:11:56 -0400 | [diff] [blame] | 39 | can clean the tempest and alternate tempest tenants but by default, | 
|  | 40 | cleanup deletes the objects in the tempest and alternate tempest tenants | 
| Joe H. Rahme | 8bd59e0 | 2014-12-19 13:53:50 +0200 | [diff] [blame] | 41 | but does not delete those tenants unless the **--delete-tempest-conf-objects** | 
| David Paterson | d6babc5 | 2014-10-14 00:11:56 -0400 | [diff] [blame] | 42 | flag is used to force their deletion. | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 43 |  | 
|  | 44 | **Normal mode**: running with no arguments, will query your deployment and | 
| David Paterson | d6babc5 | 2014-10-14 00:11:56 -0400 | [diff] [blame] | 45 | build a list of objects to delete after filtering out the objects found in | 
| Joe H. Rahme | 8bd59e0 | 2014-12-19 13:53:50 +0200 | [diff] [blame] | 46 | saved_state.json and based on the **--delete-tempest-conf-objects** flag. | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 47 |  | 
|  | 48 | By default the tempest and alternate tempest users and tenants are not | 
|  | 49 | deleted and the admin user specified in tempest.conf is never deleted. | 
|  | 50 |  | 
| Joe H. Rahme | 8bd59e0 | 2014-12-19 13:53:50 +0200 | [diff] [blame] | 51 | Please run with **--help** to see full list of options. | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 52 | """ | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 53 | import sys | 
| Marc Koderer | f339794 | 2015-12-21 11:17:09 +0100 | [diff] [blame] | 54 | import traceback | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 55 |  | 
| David Paterson | 07661de | 2015-10-29 20:15:04 -0700 | [diff] [blame] | 56 | from cliff import command | 
| Doug Hellmann | 583ce2c | 2015-03-11 14:55:46 +0000 | [diff] [blame] | 57 | from oslo_log import log as logging | 
| Matthew Treinish | 2190551 | 2015-07-13 10:33:35 -0400 | [diff] [blame] | 58 | from oslo_serialization import jsonutils as json | 
| Doug Hellmann | 583ce2c | 2015-03-11 14:55:46 +0000 | [diff] [blame] | 59 |  | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 60 | from tempest import clients | 
|  | 61 | from tempest.cmd import cleanup_service | 
| Andrea Frittoli (andreaf) | 290b3e1 | 2015-10-08 10:25:02 +0100 | [diff] [blame] | 62 | from tempest.common import credentials_factory as credentials | 
| Ken'ichi Ohmichi | 6ea3f98 | 2015-11-09 12:41:13 +0000 | [diff] [blame] | 63 | from tempest.common import identity | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 64 | from tempest import config | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 65 |  | 
|  | 66 | SAVED_STATE_JSON = "saved_state.json" | 
|  | 67 | DRY_RUN_JSON = "dry_run.json" | 
|  | 68 | LOG = logging.getLogger(__name__) | 
|  | 69 | CONF = config.CONF | 
|  | 70 |  | 
|  | 71 |  | 
| David Paterson | 07661de | 2015-10-29 20:15:04 -0700 | [diff] [blame] | 72 | class TempestCleanup(command.Command): | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 73 |  | 
| David Paterson | 07661de | 2015-10-29 20:15:04 -0700 | [diff] [blame] | 74 | def __init__(self, app, cmd): | 
|  | 75 | super(TempestCleanup, self).__init__(app, cmd) | 
|  | 76 |  | 
|  | 77 | def take_action(self, parsed_args): | 
| Marc Koderer | f339794 | 2015-12-21 11:17:09 +0100 | [diff] [blame] | 78 | try: | 
|  | 79 | self.init(parsed_args) | 
| Ghanshyam | 41711d3 | 2016-02-17 17:11:22 +0900 | [diff] [blame] | 80 | if not parsed_args.init_saved_state: | 
|  | 81 | self._cleanup() | 
| Marc Koderer | f339794 | 2015-12-21 11:17:09 +0100 | [diff] [blame] | 82 | except Exception: | 
|  | 83 | LOG.exception("Failure during cleanup") | 
|  | 84 | traceback.print_exc() | 
|  | 85 | raise | 
| Marc Koderer | f339794 | 2015-12-21 11:17:09 +0100 | [diff] [blame] | 86 |  | 
|  | 87 | def init(self, parsed_args): | 
| David Paterson | 07661de | 2015-10-29 20:15:04 -0700 | [diff] [blame] | 88 | cleanup_service.init_conf() | 
|  | 89 | self.options = parsed_args | 
| Andrea Frittoli (andreaf) | 290b3e1 | 2015-10-08 10:25:02 +0100 | [diff] [blame] | 90 | self.admin_mgr = credentials.AdminManager() | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 91 | self.dry_run_data = {} | 
|  | 92 | self.json_data = {} | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 93 |  | 
|  | 94 | self.admin_id = "" | 
|  | 95 | self.admin_role_id = "" | 
|  | 96 | self.admin_tenant_id = "" | 
|  | 97 | self._init_admin_ids() | 
|  | 98 |  | 
|  | 99 | self.admin_role_added = [] | 
|  | 100 |  | 
|  | 101 | # available services | 
|  | 102 | self.tenant_services = cleanup_service.get_tenant_cleanup_services() | 
|  | 103 | self.global_services = cleanup_service.get_global_cleanup_services() | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 104 |  | 
| David Paterson | 07661de | 2015-10-29 20:15:04 -0700 | [diff] [blame] | 105 | if parsed_args.init_saved_state: | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 106 | self._init_state() | 
|  | 107 | return | 
|  | 108 |  | 
|  | 109 | self._load_json() | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 110 |  | 
|  | 111 | def _cleanup(self): | 
| Marc Koderer | f339794 | 2015-12-21 11:17:09 +0100 | [diff] [blame] | 112 | print ("Begin cleanup") | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 113 | is_dry_run = self.options.dry_run | 
| David Paterson | d6babc5 | 2014-10-14 00:11:56 -0400 | [diff] [blame] | 114 | is_preserve = not self.options.delete_tempest_conf_objects | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 115 | is_save_state = False | 
|  | 116 |  | 
|  | 117 | if is_dry_run: | 
|  | 118 | self.dry_run_data["_tenants_to_clean"] = {} | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 119 |  | 
|  | 120 | admin_mgr = self.admin_mgr | 
|  | 121 | # Always cleanup tempest and alt tempest tenants unless | 
|  | 122 | # they are in saved state json. Therefore is_preserve is False | 
|  | 123 | kwargs = {'data': self.dry_run_data, | 
|  | 124 | 'is_dry_run': is_dry_run, | 
|  | 125 | 'saved_state_json': self.json_data, | 
|  | 126 | 'is_preserve': False, | 
|  | 127 | 'is_save_state': is_save_state} | 
|  | 128 | tenant_service = cleanup_service.TenantService(admin_mgr, **kwargs) | 
|  | 129 | tenants = tenant_service.list() | 
| Marc Koderer | f339794 | 2015-12-21 11:17:09 +0100 | [diff] [blame] | 130 | print ("Process %s tenants" % len(tenants)) | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 131 |  | 
|  | 132 | # Loop through list of tenants and clean them up. | 
|  | 133 | for tenant in tenants: | 
|  | 134 | self._add_admin(tenant['id']) | 
|  | 135 | self._clean_tenant(tenant) | 
|  | 136 |  | 
|  | 137 | kwargs = {'data': self.dry_run_data, | 
|  | 138 | 'is_dry_run': is_dry_run, | 
|  | 139 | 'saved_state_json': self.json_data, | 
|  | 140 | 'is_preserve': is_preserve, | 
|  | 141 | 'is_save_state': is_save_state} | 
|  | 142 | for service in self.global_services: | 
|  | 143 | svc = service(admin_mgr, **kwargs) | 
|  | 144 | svc.run() | 
|  | 145 |  | 
|  | 146 | if is_dry_run: | 
| zhang.lei | a4b1cef | 2016-03-01 10:50:01 +0800 | [diff] [blame] | 147 | with open(DRY_RUN_JSON, 'w+') as f: | 
|  | 148 | f.write(json.dumps(self.dry_run_data, sort_keys=True, | 
|  | 149 | indent=2, separators=(',', ': '))) | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 150 |  | 
|  | 151 | self._remove_admin_user_roles() | 
|  | 152 |  | 
|  | 153 | def _remove_admin_user_roles(self): | 
|  | 154 | tenant_ids = self.admin_role_added | 
|  | 155 | LOG.debug("Removing admin user roles where needed for tenants: %s" | 
|  | 156 | % tenant_ids) | 
|  | 157 | for tenant_id in tenant_ids: | 
|  | 158 | self._remove_admin_role(tenant_id) | 
|  | 159 |  | 
|  | 160 | def _clean_tenant(self, tenant): | 
| Marc Koderer | f339794 | 2015-12-21 11:17:09 +0100 | [diff] [blame] | 161 | print ("Cleaning tenant:  %s " % tenant['name']) | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 162 | is_dry_run = self.options.dry_run | 
|  | 163 | dry_run_data = self.dry_run_data | 
| David Paterson | d6babc5 | 2014-10-14 00:11:56 -0400 | [diff] [blame] | 164 | is_preserve = not self.options.delete_tempest_conf_objects | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 165 | tenant_id = tenant['id'] | 
|  | 166 | tenant_name = tenant['name'] | 
|  | 167 | tenant_data = None | 
|  | 168 | if is_dry_run: | 
|  | 169 | tenant_data = dry_run_data["_tenants_to_clean"][tenant_id] = {} | 
|  | 170 | tenant_data['name'] = tenant_name | 
|  | 171 |  | 
| David Paterson | 07661de | 2015-10-29 20:15:04 -0700 | [diff] [blame] | 172 | kwargs = {"username": CONF.auth.admin_username, | 
|  | 173 | "password": CONF.auth.admin_password, | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 174 | "tenant_name": tenant['name']} | 
| Andrea Frittoli (andreaf) | 290b3e1 | 2015-10-08 10:25:02 +0100 | [diff] [blame] | 175 | mgr = clients.Manager(credentials=credentials.get_credentials( | 
| Andrea Frittoli | 878d5ab | 2015-01-30 13:22:50 +0000 | [diff] [blame] | 176 | **kwargs)) | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 177 | kwargs = {'data': tenant_data, | 
|  | 178 | 'is_dry_run': is_dry_run, | 
|  | 179 | 'saved_state_json': None, | 
|  | 180 | 'is_preserve': is_preserve, | 
|  | 181 | 'is_save_state': False, | 
|  | 182 | 'tenant_id': tenant_id} | 
|  | 183 | for service in self.tenant_services: | 
|  | 184 | svc = service(mgr, **kwargs) | 
|  | 185 | svc.run() | 
|  | 186 |  | 
|  | 187 | def _init_admin_ids(self): | 
| Daniel Mellado | b83ea56 | 2015-12-18 09:12:49 +0000 | [diff] [blame] | 188 | tn_cl = self.admin_mgr.tenants_client | 
| Daniel Mellado | 6b16b92 | 2015-12-07 12:43:08 +0000 | [diff] [blame] | 189 | rl_cl = self.admin_mgr.roles_client | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 190 |  | 
| Daniel Mellado | b83ea56 | 2015-12-18 09:12:49 +0000 | [diff] [blame] | 191 | tenant = identity.get_tenant_by_name(tn_cl, | 
| Daniel Mellado | d4d0b93 | 2016-04-08 08:57:29 +0000 | [diff] [blame] | 192 | CONF.auth.admin_project_name) | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 193 | self.admin_tenant_id = tenant['id'] | 
|  | 194 |  | 
| Daniel Mellado | b83ea56 | 2015-12-18 09:12:49 +0000 | [diff] [blame] | 195 | user = identity.get_user_by_username(tn_cl, self.admin_tenant_id, | 
| Ken'ichi Ohmichi | d9fed31 | 2015-11-09 13:05:32 +0000 | [diff] [blame] | 196 | CONF.auth.admin_username) | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 197 | self.admin_id = user['id'] | 
|  | 198 |  | 
| Daniel Mellado | 6b16b92 | 2015-12-07 12:43:08 +0000 | [diff] [blame] | 199 | roles = rl_cl.list_roles()['roles'] | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 200 | for role in roles: | 
|  | 201 | if role['name'] == CONF.identity.admin_role: | 
|  | 202 | self.admin_role_id = role['id'] | 
|  | 203 | break | 
|  | 204 |  | 
| David Paterson | 07661de | 2015-10-29 20:15:04 -0700 | [diff] [blame] | 205 | def get_parser(self, prog_name): | 
|  | 206 | parser = super(TempestCleanup, self).get_parser(prog_name) | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 207 | parser.add_argument('--init-saved-state', action="store_true", | 
|  | 208 | dest='init_saved_state', default=False, | 
|  | 209 | help="Creates JSON file: " + SAVED_STATE_JSON + | 
|  | 210 | ", representing the current state of your " | 
| David Paterson | d6babc5 | 2014-10-14 00:11:56 -0400 | [diff] [blame] | 211 | "deployment,  specifically object types " | 
|  | 212 | "tempest creates and destroys during a run. " | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 213 | "You must run with this flag prior to " | 
| David Paterson | d6babc5 | 2014-10-14 00:11:56 -0400 | [diff] [blame] | 214 | "executing cleanup in normal mode, which is with " | 
|  | 215 | "no arguments.") | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 216 | parser.add_argument('--delete-tempest-conf-objects', | 
| David Paterson | d6babc5 | 2014-10-14 00:11:56 -0400 | [diff] [blame] | 217 | action="store_true", | 
|  | 218 | dest='delete_tempest_conf_objects', | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 219 | default=False, | 
| David Paterson | d6babc5 | 2014-10-14 00:11:56 -0400 | [diff] [blame] | 220 | help="Force deletion of the tempest and " | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 221 | "alternate tempest users and tenants.") | 
|  | 222 | parser.add_argument('--dry-run', action="store_true", | 
|  | 223 | dest='dry_run', default=False, | 
|  | 224 | help="Generate JSON file:" + DRY_RUN_JSON + | 
|  | 225 | ", that reports the objects that would have " | 
|  | 226 | "been deleted had a full cleanup been run.") | 
| David Paterson | 07661de | 2015-10-29 20:15:04 -0700 | [diff] [blame] | 227 | return parser | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 228 |  | 
| David Paterson | 07661de | 2015-10-29 20:15:04 -0700 | [diff] [blame] | 229 | def get_description(self): | 
|  | 230 | return 'Cleanup after tempest run' | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 231 |  | 
|  | 232 | def _add_admin(self, tenant_id): | 
| Daniel Mellado | 6b16b92 | 2015-12-07 12:43:08 +0000 | [diff] [blame] | 233 | rl_cl = self.admin_mgr.roles_client | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 234 | needs_role = True | 
| ghanshyam | 50894fc | 2016-06-17 13:20:25 +0900 | [diff] [blame] | 235 | roles = rl_cl.list_user_roles_on_project(tenant_id, | 
|  | 236 | self.admin_id)['roles'] | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 237 | for role in roles: | 
|  | 238 | if role['id'] == self.admin_role_id: | 
|  | 239 | needs_role = False | 
|  | 240 | LOG.debug("User already had admin privilege for this tenant") | 
|  | 241 | if needs_role: | 
| Tingting Bao | 2b51334 | 2015-02-15 22:54:55 -0800 | [diff] [blame] | 242 | LOG.debug("Adding admin privilege for : %s" % tenant_id) | 
| ghanshyam | 50894fc | 2016-06-17 13:20:25 +0900 | [diff] [blame] | 243 | rl_cl.create_user_role_on_project(tenant_id, self.admin_id, | 
|  | 244 | self.admin_role_id) | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 245 | self.admin_role_added.append(tenant_id) | 
|  | 246 |  | 
|  | 247 | def _remove_admin_role(self, tenant_id): | 
|  | 248 | LOG.debug("Remove admin user role for tenant: %s" % tenant_id) | 
|  | 249 | # Must initialize AdminManager for each user role | 
|  | 250 | # Otherwise authentication exception is thrown, weird | 
| Andrea Frittoli (andreaf) | 290b3e1 | 2015-10-08 10:25:02 +0100 | [diff] [blame] | 251 | id_cl = credentials.AdminManager().identity_client | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 252 | if (self._tenant_exists(tenant_id)): | 
|  | 253 | try: | 
| ghanshyam | 50894fc | 2016-06-17 13:20:25 +0900 | [diff] [blame] | 254 | id_cl.delete_role_from_user_on_project(tenant_id, | 
|  | 255 | self.admin_id, | 
|  | 256 | self.admin_role_id) | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 257 | except Exception as ex: | 
|  | 258 | LOG.exception("Failed removing role from tenant which still" | 
|  | 259 | "exists, exception: %s" % ex) | 
|  | 260 |  | 
|  | 261 | def _tenant_exists(self, tenant_id): | 
| Daniel Mellado | b83ea56 | 2015-12-18 09:12:49 +0000 | [diff] [blame] | 262 | tn_cl = self.admin_mgr.tenants_client | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 263 | try: | 
| Daniel Mellado | b83ea56 | 2015-12-18 09:12:49 +0000 | [diff] [blame] | 264 | t = tn_cl.show_tenant(tenant_id) | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 265 | LOG.debug("Tenant is: %s" % str(t)) | 
|  | 266 | return True | 
|  | 267 | except Exception as ex: | 
|  | 268 | LOG.debug("Tenant no longer exists? %s" % ex) | 
|  | 269 | return False | 
|  | 270 |  | 
|  | 271 | def _init_state(self): | 
| Marc Koderer | f339794 | 2015-12-21 11:17:09 +0100 | [diff] [blame] | 272 | print ("Initializing saved state.") | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 273 | data = {} | 
|  | 274 | admin_mgr = self.admin_mgr | 
|  | 275 | kwargs = {'data': data, | 
|  | 276 | 'is_dry_run': False, | 
|  | 277 | 'saved_state_json': data, | 
|  | 278 | 'is_preserve': False, | 
|  | 279 | 'is_save_state': True} | 
|  | 280 | for service in self.global_services: | 
|  | 281 | svc = service(admin_mgr, **kwargs) | 
|  | 282 | svc.run() | 
|  | 283 |  | 
| zhang.lei | a4b1cef | 2016-03-01 10:50:01 +0800 | [diff] [blame] | 284 | with open(SAVED_STATE_JSON, 'w+') as f: | 
|  | 285 | f.write(json.dumps(data, | 
|  | 286 | sort_keys=True, indent=2, separators=(',', ': '))) | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 287 |  | 
|  | 288 | def _load_json(self): | 
|  | 289 | try: | 
| zhang.lei | a4b1cef | 2016-03-01 10:50:01 +0800 | [diff] [blame] | 290 | with open(SAVED_STATE_JSON) as json_file: | 
|  | 291 | self.json_data = json.load(json_file) | 
|  | 292 |  | 
| David Paterson | ce78149 | 2014-09-18 01:07:01 -0400 | [diff] [blame] | 293 | except IOError as ex: | 
|  | 294 | LOG.exception("Failed loading saved state, please be sure you" | 
|  | 295 | " have first run cleanup with --init-saved-state " | 
|  | 296 | "flag prior to running tempest. Exception: %s" % ex) | 
|  | 297 | sys.exit(ex) | 
|  | 298 | except Exception as ex: | 
|  | 299 | LOG.exception("Exception parsing saved state json : %s" % ex) | 
|  | 300 | sys.exit(ex) |