Remove v2 identity from tempest cleanup command
This patch remove the calls for v2 identity in the tempest cleanup command. Change-Id: I74d171b65d036ed3f665b1a8dec17dc5ed73eb07 Closes-Bug: 1659065 Closes-Bug: 1724599
This commit is contained in:
parent
10973fb725
commit
05fe4bcb35
tempest
@ -54,17 +54,17 @@ associated with the Tempest and alternate Tempest users and projects but will
|
||||
not delete the projects themselves.
|
||||
|
||||
**--dry-run**: Creates a report (``./dry_run.json``) of the projects that will
|
||||
be cleaned up (in the ``_tenants_to_clean`` dictionary [1]_) and the global
|
||||
be cleaned up (in the ``_projects_to_clean`` dictionary [1]_) and the global
|
||||
objects that will be removed (domains, flavors, images, roles, projects,
|
||||
and users). Once the cleanup command is executed (e.g. run without
|
||||
parameters), running it again with **--dry-run** should yield an empty report.
|
||||
|
||||
**--help**: Print the help text for the command and parameters.
|
||||
|
||||
.. [1] The ``_tenants_to_clean`` dictionary in ``dry_run.json`` lists the
|
||||
.. [1] The ``_projects_to_clean`` dictionary in ``dry_run.json`` lists the
|
||||
projects that ``tempest cleanup`` will loop through to delete child
|
||||
objects, but the command will, by default, not delete the projects
|
||||
themselves. This may differ from the ``tenants`` list as you can clean
|
||||
themselves. This may differ from the ``projects`` list as you can clean
|
||||
the Tempest and alternate Tempest users and projects but they will not be
|
||||
deleted unless the **--delete-tempest-conf-objects** flag is used to
|
||||
force their deletion.
|
||||
@ -111,13 +111,13 @@ class TempestCleanup(command.Command):
|
||||
|
||||
self.admin_id = ""
|
||||
self.admin_role_id = ""
|
||||
self.admin_tenant_id = ""
|
||||
self.admin_project_id = ""
|
||||
self._init_admin_ids()
|
||||
|
||||
self.admin_role_added = []
|
||||
|
||||
# available services
|
||||
self.tenant_services = cleanup_service.get_tenant_cleanup_services()
|
||||
self.project_services = cleanup_service.get_project_cleanup_services()
|
||||
self.global_services = cleanup_service.get_global_cleanup_services()
|
||||
|
||||
if parsed_args.init_saved_state:
|
||||
@ -133,24 +133,24 @@ class TempestCleanup(command.Command):
|
||||
is_save_state = False
|
||||
|
||||
if is_dry_run:
|
||||
self.dry_run_data["_tenants_to_clean"] = {}
|
||||
self.dry_run_data["_projects_to_clean"] = {}
|
||||
|
||||
admin_mgr = self.admin_mgr
|
||||
# Always cleanup tempest and alt tempest tenants unless
|
||||
# Always cleanup tempest and alt tempest projects unless
|
||||
# they are in saved state json. Therefore is_preserve is False
|
||||
kwargs = {'data': self.dry_run_data,
|
||||
'is_dry_run': is_dry_run,
|
||||
'saved_state_json': self.json_data,
|
||||
'is_preserve': False,
|
||||
'is_save_state': is_save_state}
|
||||
tenant_service = cleanup_service.TenantService(admin_mgr, **kwargs)
|
||||
tenants = tenant_service.list()
|
||||
print("Process %s tenants" % len(tenants))
|
||||
project_service = cleanup_service.ProjectService(admin_mgr, **kwargs)
|
||||
projects = project_service.list()
|
||||
print("Process %s projects" % len(projects))
|
||||
|
||||
# Loop through list of tenants and clean them up.
|
||||
for tenant in tenants:
|
||||
self._add_admin(tenant['id'])
|
||||
self._clean_tenant(tenant)
|
||||
# Loop through list of projects and clean them up.
|
||||
for project in projects:
|
||||
self._add_admin(project['id'])
|
||||
self._clean_project(project)
|
||||
|
||||
kwargs = {'data': self.dry_run_data,
|
||||
'is_dry_run': is_dry_run,
|
||||
@ -169,49 +169,51 @@ class TempestCleanup(command.Command):
|
||||
self._remove_admin_user_roles()
|
||||
|
||||
def _remove_admin_user_roles(self):
|
||||
tenant_ids = self.admin_role_added
|
||||
LOG.debug("Removing admin user roles where needed for tenants: %s",
|
||||
tenant_ids)
|
||||
for tenant_id in tenant_ids:
|
||||
self._remove_admin_role(tenant_id)
|
||||
project_ids = self.admin_role_added
|
||||
LOG.debug("Removing admin user roles where needed for projects: %s",
|
||||
project_ids)
|
||||
for project_id in project_ids:
|
||||
self._remove_admin_role(project_id)
|
||||
|
||||
def _clean_tenant(self, tenant):
|
||||
print("Cleaning tenant: %s " % tenant['name'])
|
||||
def _clean_project(self, project):
|
||||
print("Cleaning project: %s " % project['name'])
|
||||
is_dry_run = self.options.dry_run
|
||||
dry_run_data = self.dry_run_data
|
||||
is_preserve = not self.options.delete_tempest_conf_objects
|
||||
tenant_id = tenant['id']
|
||||
tenant_name = tenant['name']
|
||||
tenant_data = None
|
||||
project_id = project['id']
|
||||
project_name = project['name']
|
||||
project_data = None
|
||||
if is_dry_run:
|
||||
tenant_data = dry_run_data["_tenants_to_clean"][tenant_id] = {}
|
||||
tenant_data['name'] = tenant_name
|
||||
project_data = dry_run_data["_projects_to_clean"][project_id] = {}
|
||||
project_data['name'] = project_name
|
||||
|
||||
kwargs = {"username": CONF.auth.admin_username,
|
||||
"password": CONF.auth.admin_password,
|
||||
"tenant_name": tenant['name']}
|
||||
"project_name": project['name']}
|
||||
mgr = clients.Manager(credentials=credentials.get_credentials(
|
||||
**kwargs))
|
||||
kwargs = {'data': tenant_data,
|
||||
kwargs = {'data': project_data,
|
||||
'is_dry_run': is_dry_run,
|
||||
'saved_state_json': None,
|
||||
'is_preserve': is_preserve,
|
||||
'is_save_state': False,
|
||||
'tenant_id': tenant_id}
|
||||
for service in self.tenant_services:
|
||||
'project_id': project_id}
|
||||
for service in self.project_services:
|
||||
svc = service(mgr, **kwargs)
|
||||
svc.run()
|
||||
|
||||
def _init_admin_ids(self):
|
||||
tn_cl = self.admin_mgr.tenants_client
|
||||
rl_cl = self.admin_mgr.roles_client
|
||||
pr_cl = self.admin_mgr.projects_client
|
||||
rl_cl = self.admin_mgr.roles_v3_client
|
||||
rla_cl = self.admin_mgr.role_assignments_client
|
||||
us_cl = self.admin_mgr.users_v3_client
|
||||
|
||||
tenant = identity.get_tenant_by_name(tn_cl,
|
||||
CONF.auth.admin_project_name)
|
||||
self.admin_tenant_id = tenant['id']
|
||||
|
||||
user = identity.get_user_by_username(tn_cl, self.admin_tenant_id,
|
||||
CONF.auth.admin_username)
|
||||
project = identity.get_project_by_name(pr_cl,
|
||||
CONF.auth.admin_project_name)
|
||||
self.admin_project_id = project['id']
|
||||
user = identity.get_user_by_project(us_cl, rla_cl,
|
||||
self.admin_project_id,
|
||||
CONF.auth.admin_username)
|
||||
self.admin_id = user['id']
|
||||
|
||||
roles = rl_cl.list_roles()['roles']
|
||||
@ -236,7 +238,7 @@ class TempestCleanup(command.Command):
|
||||
dest='delete_tempest_conf_objects',
|
||||
default=False,
|
||||
help="Force deletion of the tempest and "
|
||||
"alternate tempest users and tenants.")
|
||||
"alternate tempest users and projects.")
|
||||
parser.add_argument('--dry-run', action="store_true",
|
||||
dest='dry_run', default=False,
|
||||
help="Generate JSON file:" + DRY_RUN_JSON +
|
||||
@ -247,44 +249,44 @@ class TempestCleanup(command.Command):
|
||||
def get_description(self):
|
||||
return 'Cleanup after tempest run'
|
||||
|
||||
def _add_admin(self, tenant_id):
|
||||
rl_cl = self.admin_mgr.roles_client
|
||||
def _add_admin(self, project_id):
|
||||
rl_cl = self.admin_mgr.roles_v3_client
|
||||
needs_role = True
|
||||
roles = rl_cl.list_user_roles_on_project(tenant_id,
|
||||
roles = rl_cl.list_user_roles_on_project(project_id,
|
||||
self.admin_id)['roles']
|
||||
for role in roles:
|
||||
if role['id'] == self.admin_role_id:
|
||||
needs_role = False
|
||||
LOG.debug("User already had admin privilege for this tenant")
|
||||
LOG.debug("User already had admin privilege for this project")
|
||||
if needs_role:
|
||||
LOG.debug("Adding admin privilege for : %s", tenant_id)
|
||||
rl_cl.create_user_role_on_project(tenant_id, self.admin_id,
|
||||
LOG.debug("Adding admin privilege for : %s", project_id)
|
||||
rl_cl.create_user_role_on_project(project_id, self.admin_id,
|
||||
self.admin_role_id)
|
||||
self.admin_role_added.append(tenant_id)
|
||||
self.admin_role_added.append(project_id)
|
||||
|
||||
def _remove_admin_role(self, tenant_id):
|
||||
LOG.debug("Remove admin user role for tenant: %s", tenant_id)
|
||||
def _remove_admin_role(self, project_id):
|
||||
LOG.debug("Remove admin user role for projectt: %s", project_id)
|
||||
# Must initialize Admin Manager for each user role
|
||||
# Otherwise authentication exception is thrown, weird
|
||||
id_cl = clients.Manager(
|
||||
credentials.get_configured_admin_credentials()).identity_client
|
||||
if (self._tenant_exists(tenant_id)):
|
||||
if (self._project_exists(project_id)):
|
||||
try:
|
||||
id_cl.delete_role_from_user_on_project(tenant_id,
|
||||
id_cl.delete_role_from_user_on_project(project_id,
|
||||
self.admin_id,
|
||||
self.admin_role_id)
|
||||
except Exception as ex:
|
||||
LOG.exception("Failed removing role from tenant which still"
|
||||
LOG.exception("Failed removing role from project which still"
|
||||
"exists, exception: %s", ex)
|
||||
|
||||
def _tenant_exists(self, tenant_id):
|
||||
tn_cl = self.admin_mgr.tenants_client
|
||||
def _project_exists(self, project_id):
|
||||
pr_cl = self.admin_mgr.projects_client
|
||||
try:
|
||||
t = tn_cl.show_tenant(tenant_id)
|
||||
LOG.debug("Tenant is: %s", str(t))
|
||||
p = pr_cl.show_project(project_id)
|
||||
LOG.debug("Project is: %s", str(p))
|
||||
return True
|
||||
except Exception as ex:
|
||||
LOG.debug("Tenant no longer exists? %s", ex)
|
||||
LOG.debug("Project no longer exists? %s", ex)
|
||||
return False
|
||||
|
||||
def _init_state(self):
|
||||
|
@ -32,7 +32,7 @@ CONF_NETWORKS = []
|
||||
CONF_PRIV_NETWORK_NAME = None
|
||||
CONF_PUB_NETWORK = None
|
||||
CONF_PUB_ROUTER = None
|
||||
CONF_TENANTS = None
|
||||
CONF_PROJECTS = None
|
||||
CONF_USERS = None
|
||||
|
||||
IS_CINDER = None
|
||||
@ -50,7 +50,7 @@ def init_conf():
|
||||
global CONF_PRIV_NETWORK_NAME
|
||||
global CONF_PUB_NETWORK
|
||||
global CONF_PUB_ROUTER
|
||||
global CONF_TENANTS
|
||||
global CONF_PROJECTS
|
||||
global CONF_USERS
|
||||
global IS_CINDER
|
||||
global IS_GLANCE
|
||||
@ -69,7 +69,7 @@ def init_conf():
|
||||
CONF_PRIV_NETWORK_NAME = CONF.compute.fixed_network_name
|
||||
CONF_PUB_NETWORK = CONF.network.public_network_id
|
||||
CONF_PUB_ROUTER = CONF.network.public_router_id
|
||||
CONF_TENANTS = [CONF.auth.admin_project_name]
|
||||
CONF_PROJECTS = [CONF.auth.admin_project_name]
|
||||
CONF_USERS = [CONF.auth.admin_username]
|
||||
|
||||
if IS_NEUTRON:
|
||||
@ -82,14 +82,14 @@ def _get_network_id(net_name, project_name):
|
||||
am = clients.Manager(
|
||||
credentials.get_configured_admin_credentials())
|
||||
net_cl = am.networks_client
|
||||
tn_cl = am.tenants_client
|
||||
pr_cl = am.projects_client
|
||||
|
||||
networks = net_cl.list_networks()
|
||||
tenant = identity.get_tenant_by_name(tn_cl, project_name)
|
||||
t_id = tenant['id']
|
||||
project = identity.get_project_by_name(pr_cl, project_name)
|
||||
p_id = project['id']
|
||||
n_id = None
|
||||
for net in networks['networks']:
|
||||
if (net['tenant_id'] == t_id and net['name'] == net_name):
|
||||
if (net['project_id'] == p_id and net['name'] == net_name):
|
||||
n_id = net['id']
|
||||
break
|
||||
return n_id
|
||||
@ -786,14 +786,14 @@ class ImageService(BaseService):
|
||||
class IdentityService(BaseService):
|
||||
def __init__(self, manager, **kwargs):
|
||||
super(IdentityService, self).__init__(kwargs)
|
||||
self.client = manager.identity_client
|
||||
self.client = manager.identity_v3_client
|
||||
|
||||
|
||||
class UserService(BaseService):
|
||||
|
||||
def __init__(self, manager, **kwargs):
|
||||
super(UserService, self).__init__(kwargs)
|
||||
self.client = manager.users_client
|
||||
self.client = manager.users_v3_client
|
||||
|
||||
def list(self):
|
||||
users = self.client.list_users()['users']
|
||||
@ -872,43 +872,43 @@ class RoleService(BaseService):
|
||||
self.data['roles'][role['id']] = role['name']
|
||||
|
||||
|
||||
class TenantService(BaseService):
|
||||
class ProjectService(BaseService):
|
||||
|
||||
def __init__(self, manager, **kwargs):
|
||||
super(TenantService, self).__init__(kwargs)
|
||||
self.client = manager.tenants_client
|
||||
super(ProjectService, self).__init__(kwargs)
|
||||
self.client = manager.projects_client
|
||||
|
||||
def list(self):
|
||||
tenants = self.client.list_tenants()['tenants']
|
||||
projects = self.client.list_projects()['projects']
|
||||
if not self.is_save_state:
|
||||
tenants = [tenant for tenant in tenants if (tenant['id']
|
||||
not in self.saved_state_json['tenants'].keys()
|
||||
and tenant['name'] != CONF.auth.admin_project_name)]
|
||||
projects = [project for project in projects if (project['id']
|
||||
not in self.saved_state_json['projects'].keys()
|
||||
and project['name'] != CONF.auth.admin_project_name)]
|
||||
|
||||
if self.is_preserve:
|
||||
tenants = [tenant for tenant in tenants if tenant['name']
|
||||
not in CONF_TENANTS]
|
||||
projects = [project for project in projects if project['name']
|
||||
not in CONF_PROJECTS]
|
||||
|
||||
LOG.debug("List count, %s Tenants after reconcile", len(tenants))
|
||||
return tenants
|
||||
LOG.debug("List count, %s Projects after reconcile", len(projects))
|
||||
return projects
|
||||
|
||||
def delete(self):
|
||||
tenants = self.list()
|
||||
for tenant in tenants:
|
||||
projects = self.list()
|
||||
for project in projects:
|
||||
try:
|
||||
self.client.delete_tenant(tenant['id'])
|
||||
self.client.delete_project(project['id'])
|
||||
except Exception:
|
||||
LOG.exception("Delete Tenant exception.")
|
||||
LOG.exception("Delete project exception.")
|
||||
|
||||
def dry_run(self):
|
||||
tenants = self.list()
|
||||
self.data['tenants'] = tenants
|
||||
projects = self.list()
|
||||
self.data['projects'] = projects
|
||||
|
||||
def save_state(self):
|
||||
tenants = self.list()
|
||||
self.data['tenants'] = {}
|
||||
for tenant in tenants:
|
||||
self.data['tenants'][tenant['id']] = tenant['name']
|
||||
projects = self.list()
|
||||
self.data['projects'] = {}
|
||||
for project in projects:
|
||||
self.data['projects'][project['id']] = project['name']
|
||||
|
||||
|
||||
class DomainService(BaseService):
|
||||
@ -948,35 +948,35 @@ class DomainService(BaseService):
|
||||
self.data['domains'][domain['id']] = domain['name']
|
||||
|
||||
|
||||
def get_tenant_cleanup_services():
|
||||
tenant_services = []
|
||||
def get_project_cleanup_services():
|
||||
project_services = []
|
||||
# TODO(gmann): Tempest should provide some plugin hook for cleanup
|
||||
# script extension to plugin tests also.
|
||||
if IS_NOVA:
|
||||
tenant_services.append(ServerService)
|
||||
tenant_services.append(KeyPairService)
|
||||
tenant_services.append(SecurityGroupService)
|
||||
tenant_services.append(ServerGroupService)
|
||||
project_services.append(ServerService)
|
||||
project_services.append(KeyPairService)
|
||||
project_services.append(SecurityGroupService)
|
||||
project_services.append(ServerGroupService)
|
||||
if not IS_NEUTRON:
|
||||
tenant_services.append(FloatingIpService)
|
||||
tenant_services.append(NovaQuotaService)
|
||||
project_services.append(FloatingIpService)
|
||||
project_services.append(NovaQuotaService)
|
||||
if IS_HEAT:
|
||||
tenant_services.append(StackService)
|
||||
project_services.append(StackService)
|
||||
if IS_NEUTRON:
|
||||
tenant_services.append(NetworkFloatingIpService)
|
||||
project_services.append(NetworkFloatingIpService)
|
||||
if utils.is_extension_enabled('metering', 'network'):
|
||||
tenant_services.append(NetworkMeteringLabelRuleService)
|
||||
tenant_services.append(NetworkMeteringLabelService)
|
||||
tenant_services.append(NetworkRouterService)
|
||||
tenant_services.append(NetworkPortService)
|
||||
tenant_services.append(NetworkSubnetService)
|
||||
tenant_services.append(NetworkService)
|
||||
tenant_services.append(NetworkSecGroupService)
|
||||
project_services.append(NetworkMeteringLabelRuleService)
|
||||
project_services.append(NetworkMeteringLabelService)
|
||||
project_services.append(NetworkRouterService)
|
||||
project_services.append(NetworkPortService)
|
||||
project_services.append(NetworkSubnetService)
|
||||
project_services.append(NetworkService)
|
||||
project_services.append(NetworkSecGroupService)
|
||||
if IS_CINDER:
|
||||
tenant_services.append(SnapshotService)
|
||||
tenant_services.append(VolumeService)
|
||||
tenant_services.append(VolumeQuotaService)
|
||||
return tenant_services
|
||||
project_services.append(SnapshotService)
|
||||
project_services.append(VolumeService)
|
||||
project_services.append(VolumeQuotaService)
|
||||
return project_services
|
||||
|
||||
|
||||
def get_global_cleanup_services():
|
||||
@ -986,7 +986,7 @@ def get_global_cleanup_services():
|
||||
if IS_GLANCE:
|
||||
global_services.append(ImageService)
|
||||
global_services.append(UserService)
|
||||
global_services.append(TenantService)
|
||||
global_services.append(ProjectService)
|
||||
global_services.append(DomainService)
|
||||
global_services.append(RoleService)
|
||||
return global_services
|
||||
|
@ -20,6 +20,15 @@ from tempest.lib import exceptions as lib_exc
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
def get_project_by_name(client, project_name):
|
||||
projects = client.list_projects({'name': project_name})['projects']
|
||||
for project in projects:
|
||||
if project['name'] == project_name:
|
||||
return project
|
||||
raise lib_exc.NotFound('No such project(%s) in %s' % (project_name,
|
||||
projects))
|
||||
|
||||
|
||||
def get_tenant_by_name(client, tenant_name):
|
||||
tenants = client.list_tenants()['tenants']
|
||||
for tenant in tenants:
|
||||
@ -36,6 +45,18 @@ def get_user_by_username(client, tenant_id, username):
|
||||
raise lib_exc.NotFound('No such user(%s) in %s' % (username, users))
|
||||
|
||||
|
||||
def get_user_by_project(users_client, roles_client, project_id, username):
|
||||
users = users_client.list_users(**{'name': username})['users']
|
||||
users_in_project = roles_client.list_role_assignments(
|
||||
**{'scope.project.id': project_id})['role_assignments']
|
||||
for user in users:
|
||||
if user['name'] == username:
|
||||
for u in users_in_project:
|
||||
if u['user']['id'] == user['id']:
|
||||
return user
|
||||
raise lib_exc.NotFound('No such user(%s) in %s' % (username, users))
|
||||
|
||||
|
||||
def identity_utils(clients):
|
||||
"""A client that abstracts v2 and v3 identity operations.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user