You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1132 lines
38 KiB
Python
1132 lines
38 KiB
Python
# Copyright 2015 Dell Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
from oslo_log import log as logging
|
|
from six.moves.urllib import parse as urllib
|
|
|
|
from tempest import clients
|
|
from tempest.common import credentials_factory as credentials
|
|
from tempest.common import identity
|
|
from tempest.common import utils
|
|
from tempest.common.utils import net_info
|
|
from tempest import config
|
|
from tempest.lib import exceptions
|
|
|
|
LOG = logging.getLogger('tempest.cmd.cleanup')
|
|
CONF = config.CONF
|
|
|
|
CONF_FLAVORS = None
|
|
CONF_IMAGES = None
|
|
CONF_NETWORKS = []
|
|
CONF_PRIV_NETWORK_NAME = None
|
|
CONF_PUB_NETWORK = None
|
|
CONF_PUB_ROUTER = None
|
|
CONF_PROJECTS = None
|
|
CONF_USERS = None
|
|
|
|
IS_CINDER = None
|
|
IS_GLANCE = None
|
|
IS_NEUTRON = None
|
|
IS_NOVA = None
|
|
|
|
|
|
def init_conf():
|
|
global CONF_FLAVORS
|
|
global CONF_IMAGES
|
|
global CONF_NETWORKS
|
|
global CONF_PRIV_NETWORK
|
|
global CONF_PRIV_NETWORK_NAME
|
|
global CONF_PUB_NETWORK
|
|
global CONF_PUB_ROUTER
|
|
global CONF_PROJECTS
|
|
global CONF_USERS
|
|
global IS_CINDER
|
|
global IS_GLANCE
|
|
global IS_HEAT
|
|
global IS_NEUTRON
|
|
global IS_NOVA
|
|
|
|
IS_CINDER = CONF.service_available.cinder
|
|
IS_GLANCE = CONF.service_available.glance
|
|
IS_NEUTRON = CONF.service_available.neutron
|
|
IS_NOVA = CONF.service_available.nova
|
|
|
|
CONF_FLAVORS = [CONF.compute.flavor_ref, CONF.compute.flavor_ref_alt]
|
|
CONF_IMAGES = [CONF.compute.image_ref, CONF.compute.image_ref_alt]
|
|
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_PROJECTS = [CONF.auth.admin_project_name]
|
|
CONF_USERS = [CONF.auth.admin_username]
|
|
|
|
if IS_NEUTRON:
|
|
CONF_PRIV_NETWORK = _get_network_id(CONF.compute.fixed_network_name,
|
|
CONF.auth.admin_project_name)
|
|
CONF_NETWORKS = [CONF_PUB_NETWORK, CONF_PRIV_NETWORK]
|
|
|
|
|
|
def _get_network_id(net_name, project_name):
|
|
am = clients.Manager(
|
|
credentials.get_configured_admin_credentials())
|
|
net_cl = am.networks_client
|
|
pr_cl = am.projects_client
|
|
|
|
networks = net_cl.list_networks()
|
|
project = identity.get_project_by_name(pr_cl, project_name)
|
|
p_id = project['id']
|
|
n_id = None
|
|
for net in networks['networks']:
|
|
if (net['project_id'] == p_id and net['name'] == net_name):
|
|
n_id = net['id']
|
|
break
|
|
return n_id
|
|
|
|
|
|
class BaseService(object):
|
|
def __init__(self, kwargs):
|
|
self.client = None
|
|
for key, value in kwargs.items():
|
|
setattr(self, key, value)
|
|
|
|
self.tenant_filter = {}
|
|
if hasattr(self, 'tenant_id'):
|
|
self.tenant_filter['project_id'] = self.tenant_id
|
|
|
|
def _filter_by_tenant_id(self, item_list):
|
|
if (item_list is None or
|
|
not item_list or
|
|
not hasattr(self, 'tenant_id') or
|
|
self.tenant_id is None or
|
|
'tenant_id' not in item_list[0]):
|
|
return item_list
|
|
|
|
return [item for item in item_list
|
|
if item['tenant_id'] == self.tenant_id]
|
|
|
|
def list(self):
|
|
pass
|
|
|
|
def delete(self):
|
|
pass
|
|
|
|
def dry_run(self):
|
|
pass
|
|
|
|
def save_state(self):
|
|
pass
|
|
|
|
def run(self):
|
|
try:
|
|
if self.is_dry_run:
|
|
self.dry_run()
|
|
elif self.is_save_state:
|
|
self.save_state()
|
|
else:
|
|
self.delete()
|
|
except exceptions.NotImplemented as exc:
|
|
# Many OpenStack services use extensions logic to implement the
|
|
# features or resources. Tempest cleanup tries to clean up the test
|
|
# resources without having much logic of extensions checks etc.
|
|
# If any of the extension is missing then, service will return
|
|
# NotImplemented error.
|
|
msg = ("Got NotImplemented error in %s, full exception: %s" %
|
|
(str(self.__class__), str(exc)))
|
|
LOG.exception(msg)
|
|
self.got_exceptions.append(exc)
|
|
|
|
|
|
class SnapshotService(BaseService):
|
|
|
|
def __init__(self, manager, **kwargs):
|
|
super(SnapshotService, self).__init__(kwargs)
|
|
self.client = manager.snapshots_client_latest
|
|
|
|
def list(self):
|
|
client = self.client
|
|
snaps = client.list_snapshots()['snapshots']
|
|
if not self.is_save_state:
|
|
# recreate list removing saved snapshots
|
|
snaps = [snap for snap in snaps if snap['id']
|
|
not in self.saved_state_json['snapshots'].keys()]
|
|
LOG.debug("List count, %s Snapshots", len(snaps))
|
|
return snaps
|
|
|
|
def delete(self):
|
|
snaps = self.list()
|
|
client = self.client
|
|
for snap in snaps:
|
|
try:
|
|
LOG.debug("Deleting Snapshot with id %s", snap['id'])
|
|
client.delete_snapshot(snap['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Snapshot %s exception.", snap['id'])
|
|
|
|
def dry_run(self):
|
|
snaps = self.list()
|
|
self.data['snapshots'] = snaps
|
|
|
|
def save_state(self):
|
|
snaps = self.list()
|
|
self.data['snapshots'] = {}
|
|
for snap in snaps:
|
|
self.data['snapshots'][snap['id']] = snap['name']
|
|
|
|
|
|
class ServerService(BaseService):
|
|
def __init__(self, manager, **kwargs):
|
|
super(ServerService, self).__init__(kwargs)
|
|
self.client = manager.servers_client
|
|
self.server_groups_client = manager.server_groups_client
|
|
|
|
def list(self):
|
|
client = self.client
|
|
servers_body = client.list_servers()
|
|
servers = servers_body['servers']
|
|
if not self.is_save_state:
|
|
# recreate list removing saved servers
|
|
servers = [server for server in servers if server['id']
|
|
not in self.saved_state_json['servers'].keys()]
|
|
LOG.debug("List count, %s Servers", len(servers))
|
|
return servers
|
|
|
|
def delete(self):
|
|
client = self.client
|
|
servers = self.list()
|
|
for server in servers:
|
|
try:
|
|
LOG.debug("Deleting Server with id %s", server['id'])
|
|
client.delete_server(server['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Server %s exception.", server['id'])
|
|
|
|
def dry_run(self):
|
|
servers = self.list()
|
|
self.data['servers'] = servers
|
|
|
|
def save_state(self):
|
|
servers = self.list()
|
|
self.data['servers'] = {}
|
|
for server in servers:
|
|
self.data['servers'][server['id']] = server['name']
|
|
|
|
|
|
class ServerGroupService(ServerService):
|
|
|
|
def list(self):
|
|
client = self.server_groups_client
|
|
sgs = client.list_server_groups()['server_groups']
|
|
if not self.is_save_state:
|
|
# recreate list removing saved server_groups
|
|
sgs = [sg for sg in sgs if sg['id']
|
|
not in self.saved_state_json['server_groups'].keys()]
|
|
LOG.debug("List count, %s Server Groups", len(sgs))
|
|
return sgs
|
|
|
|
def delete(self):
|
|
client = self.server_groups_client
|
|
sgs = self.list()
|
|
for sg in sgs:
|
|
try:
|
|
LOG.debug("Deleting Server Group with id %s", sg['id'])
|
|
client.delete_server_group(sg['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Server Group %s exception.", sg['id'])
|
|
|
|
def dry_run(self):
|
|
sgs = self.list()
|
|
self.data['server_groups'] = sgs
|
|
|
|
def save_state(self):
|
|
sgs = self.list()
|
|
self.data['server_groups'] = {}
|
|
for sg in sgs:
|
|
self.data['server_groups'][sg['id']] = sg['name']
|
|
|
|
|
|
class KeyPairService(BaseService):
|
|
def __init__(self, manager, **kwargs):
|
|
super(KeyPairService, self).__init__(kwargs)
|
|
self.client = manager.keypairs_client
|
|
|
|
def list(self):
|
|
client = self.client
|
|
keypairs = client.list_keypairs()['keypairs']
|
|
if not self.is_save_state:
|
|
# recreate list removing saved keypairs
|
|
keypairs = [keypair for keypair in keypairs
|
|
if keypair['keypair']['name']
|
|
not in self.saved_state_json['keypairs'].keys()]
|
|
LOG.debug("List count, %s Keypairs", len(keypairs))
|
|
return keypairs
|
|
|
|
def delete(self):
|
|
client = self.client
|
|
keypairs = self.list()
|
|
for k in keypairs:
|
|
name = k['keypair']['name']
|
|
try:
|
|
LOG.debug("Deleting keypair %s", name)
|
|
client.delete_keypair(name)
|
|
except Exception:
|
|
LOG.exception("Delete Keypair %s exception.", name)
|
|
|
|
def dry_run(self):
|
|
keypairs = self.list()
|
|
self.data['keypairs'] = keypairs
|
|
|
|
def save_state(self):
|
|
keypairs = self.list()
|
|
self.data['keypairs'] = {}
|
|
for keypair in keypairs:
|
|
keypair = keypair['keypair']
|
|
self.data['keypairs'][keypair['name']] = keypair
|
|
|
|
|
|
class VolumeService(BaseService):
|
|
def __init__(self, manager, **kwargs):
|
|
super(VolumeService, self).__init__(kwargs)
|
|
self.client = manager.volumes_client_latest
|
|
|
|
def list(self):
|
|
client = self.client
|
|
vols = client.list_volumes()['volumes']
|
|
if not self.is_save_state:
|
|
# recreate list removing saved volumes
|
|
vols = [vol for vol in vols if vol['id']
|
|
not in self.saved_state_json['volumes'].keys()]
|
|
LOG.debug("List count, %s Volumes", len(vols))
|
|
return vols
|
|
|
|
def delete(self):
|
|
client = self.client
|
|
vols = self.list()
|
|
for v in vols:
|
|
try:
|
|
LOG.debug("Deleting volume with id %s", v['id'])
|
|
client.delete_volume(v['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Volume %s exception.", v['id'])
|
|
|
|
def dry_run(self):
|
|
vols = self.list()
|
|
self.data['volumes'] = vols
|
|
|
|
def save_state(self):
|
|
vols = self.list()
|
|
self.data['volumes'] = {}
|
|
for vol in vols:
|
|
self.data['volumes'][vol['id']] = vol['name']
|
|
|
|
|
|
class VolumeQuotaService(BaseService):
|
|
def __init__(self, manager, **kwargs):
|
|
super(VolumeQuotaService, self).__init__(kwargs)
|
|
self.client = manager.volume_quotas_client_latest
|
|
|
|
def delete(self):
|
|
client = self.client
|
|
try:
|
|
LOG.debug("Deleting Volume Quotas for project with id %s",
|
|
self.project_id)
|
|
client.delete_quota_set(self.project_id)
|
|
except Exception:
|
|
LOG.exception("Delete Volume Quotas exception for 'project %s'.",
|
|
self.project_id)
|
|
|
|
def dry_run(self):
|
|
quotas = self.client.show_quota_set(
|
|
self.project_id, params={'usage': True})['quota_set']
|
|
self.data['volume_quotas'] = quotas
|
|
|
|
|
|
class NovaQuotaService(BaseService):
|
|
def __init__(self, manager, **kwargs):
|
|
super(NovaQuotaService, self).__init__(kwargs)
|
|
self.client = manager.quotas_client
|
|
self.limits_client = manager.limits_client
|
|
|
|
def delete(self):
|
|
client = self.client
|
|
try:
|
|
LOG.debug("Deleting Nova Quotas for project with id %s",
|
|
self.project_id)
|
|
client.delete_quota_set(self.project_id)
|
|
except Exception:
|
|
LOG.exception("Delete Nova Quotas exception for 'project %s'.",
|
|
self.project_id)
|
|
|
|
def dry_run(self):
|
|
client = self.limits_client
|
|
quotas = client.show_limits()['limits']
|
|
self.data['compute_quotas'] = quotas['absolute']
|
|
|
|
|
|
class NetworkQuotaService(BaseService):
|
|
def __init__(self, manager, **kwargs):
|
|
super(NetworkQuotaService, self).__init__(kwargs)
|
|
self.client = manager.network_quotas_client
|
|
|
|
def delete(self):
|
|
client = self.client
|
|
try:
|
|
LOG.debug("Deleting Network Quotas for project with id %s",
|
|
self.project_id)
|
|
client.reset_quotas(self.project_id)
|
|
except Exception:
|
|
LOG.exception("Delete Network Quotas exception for 'project %s'.",
|
|
self.project_id)
|
|
|
|
def dry_run(self):
|
|
resp = [quota for quota in self.client.list_quotas()['quotas']
|
|
if quota['project_id'] == self.project_id]
|
|
self.data['network_quotas'] = resp
|
|
|
|
|
|
# Begin network service classes
|
|
class BaseNetworkService(BaseService):
|
|
def __init__(self, manager, **kwargs):
|
|
super(BaseNetworkService, self).__init__(kwargs)
|
|
self.networks_client = manager.networks_client
|
|
self.subnets_client = manager.subnets_client
|
|
self.ports_client = manager.ports_client
|
|
self.floating_ips_client = manager.floating_ips_client
|
|
self.metering_labels_client = manager.metering_labels_client
|
|
self.metering_label_rules_client = manager.metering_label_rules_client
|
|
self.security_groups_client = manager.security_groups_client
|
|
self.routers_client = manager.routers_client
|
|
self.subnetpools_client = manager.subnetpools_client
|
|
|
|
def _filter_by_conf_networks(self, item_list):
|
|
if not item_list or not all(('network_id' in i for i in item_list)):
|
|
return item_list
|
|
|
|
return [item for item in item_list if item['network_id']
|
|
not in CONF_NETWORKS]
|
|
|
|
|
|
class NetworkService(BaseNetworkService):
|
|
|
|
def list(self):
|
|
client = self.networks_client
|
|
networks = client.list_networks(**self.tenant_filter)
|
|
networks = networks['networks']
|
|
|
|
if not self.is_save_state:
|
|
# recreate list removing saved networks
|
|
networks = [network for network in networks if network['id']
|
|
not in self.saved_state_json['networks'].keys()]
|
|
# filter out networks declared in tempest.conf
|
|
if self.is_preserve:
|
|
networks = [network for network in networks
|
|
if network['id'] not in CONF_NETWORKS]
|
|
LOG.debug("List count, %s Networks", len(networks))
|
|
return networks
|
|
|
|
def delete(self):
|
|
client = self.networks_client
|
|
networks = self.list()
|
|
for n in networks:
|
|
try:
|
|
LOG.debug("Deleting Network with id %s", n['id'])
|
|
client.delete_network(n['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Network %s exception.", n['id'])
|
|
|
|
def dry_run(self):
|
|
networks = self.list()
|
|
self.data['networks'] = networks
|
|
|
|
def save_state(self):
|
|
networks = self.list()
|
|
self.data['networks'] = {}
|
|
for network in networks:
|
|
self.data['networks'][network['id']] = network
|
|
|
|
|
|
class NetworkFloatingIpService(BaseNetworkService):
|
|
|
|
def list(self):
|
|
client = self.floating_ips_client
|
|
flips = client.list_floatingips(**self.tenant_filter)
|
|
flips = flips['floatingips']
|
|
|
|
if not self.is_save_state:
|
|
# recreate list removing saved flips
|
|
flips = [flip for flip in flips if flip['id']
|
|
not in self.saved_state_json['floatingips'].keys()]
|
|
LOG.debug("List count, %s Network Floating IPs", len(flips))
|
|
return flips
|
|
|
|
def delete(self):
|
|
client = self.floating_ips_client
|
|
flips = self.list()
|
|
for flip in flips:
|
|
try:
|
|
LOG.debug("Deleting Network Floating IP with id %s",
|
|
flip['id'])
|
|
client.delete_floatingip(flip['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Network Floating IP %s exception.",
|
|
flip['id'])
|
|
|
|
def dry_run(self):
|
|
flips = self.list()
|
|
self.data['floatingips'] = flips
|
|
|
|
def save_state(self):
|
|
flips = self.list()
|
|
self.data['floatingips'] = {}
|
|
for flip in flips:
|
|
self.data['floatingips'][flip['id']] = flip
|
|
|
|
|
|
class NetworkRouterService(BaseNetworkService):
|
|
|
|
def list(self):
|
|
client = self.routers_client
|
|
routers = client.list_routers(**self.tenant_filter)
|
|
routers = routers['routers']
|
|
|
|
if not self.is_save_state:
|
|
# recreate list removing saved routers
|
|
routers = [router for router in routers if router['id']
|
|
not in self.saved_state_json['routers'].keys()]
|
|
if self.is_preserve:
|
|
routers = [router for router in routers
|
|
if router['id'] != CONF_PUB_ROUTER]
|
|
|
|
LOG.debug("List count, %s Routers", len(routers))
|
|
return routers
|
|
|
|
def delete(self):
|
|
client = self.routers_client
|
|
ports_client = self.ports_client
|
|
routers = self.list()
|
|
for router in routers:
|
|
rid = router['id']
|
|
ports = [port for port
|
|
in ports_client.list_ports(device_id=rid)['ports']
|
|
if net_info.is_router_interface_port(port)]
|
|
for port in ports:
|
|
try:
|
|
LOG.debug("Deleting port with id %s of router with id %s",
|
|
port['id'], rid)
|
|
client.remove_router_interface(rid, port_id=port['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Router Interface exception for "
|
|
"'port %s' of 'router %s'.", port['id'], rid)
|
|
try:
|
|
LOG.debug("Deleting Router with id %s", rid)
|
|
client.delete_router(rid)
|
|
except Exception:
|
|
LOG.exception("Delete Router %s exception.", rid)
|
|
|
|
def dry_run(self):
|
|
routers = self.list()
|
|
self.data['routers'] = routers
|
|
|
|
def save_state(self):
|
|
routers = self.list()
|
|
self.data['routers'] = {}
|
|
for router in routers:
|
|
self.data['routers'][router['id']] = router['name']
|
|
|
|
|
|
class NetworkMeteringLabelRuleService(NetworkService):
|
|
|
|
def list(self):
|
|
client = self.metering_label_rules_client
|
|
rules = client.list_metering_label_rules()
|
|
rules = rules['metering_label_rules']
|
|
rules = self._filter_by_tenant_id(rules)
|
|
|
|
if not self.is_save_state:
|
|
saved_rules = self.saved_state_json['metering_label_rules'].keys()
|
|
# recreate list removing saved rules
|
|
rules = [rule for rule in rules if rule['id'] not in saved_rules]
|
|
LOG.debug("List count, %s Metering Label Rules", len(rules))
|
|
return rules
|
|
|
|
def delete(self):
|
|
client = self.metering_label_rules_client
|
|
rules = self.list()
|
|
for rule in rules:
|
|
try:
|
|
LOG.debug("Deleting Metering Label Rule with id %s",
|
|
rule['id'])
|
|
client.delete_metering_label_rule(rule['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Metering Label Rule %s exception.",
|
|
rule['id'])
|
|
|
|
def dry_run(self):
|
|
rules = self.list()
|
|
self.data['metering_label_rules'] = rules
|
|
|
|
def save_state(self):
|
|
rules = self.list()
|
|
self.data['metering_label_rules'] = {}
|
|
for rule in rules:
|
|
self.data['metering_label_rules'][rule['id']] = rule
|
|
|
|
|
|
class NetworkMeteringLabelService(BaseNetworkService):
|
|
|
|
def list(self):
|
|
client = self.metering_labels_client
|
|
labels = client.list_metering_labels()
|
|
labels = labels['metering_labels']
|
|
labels = self._filter_by_tenant_id(labels)
|
|
|
|
if not self.is_save_state:
|
|
# recreate list removing saved labels
|
|
labels = [label for label in labels if label['id']
|
|
not in self.saved_state_json['metering_labels'].keys()]
|
|
LOG.debug("List count, %s Metering Labels", len(labels))
|
|
return labels
|
|
|
|
def delete(self):
|
|
client = self.metering_labels_client
|
|
labels = self.list()
|
|
for label in labels:
|
|
try:
|
|
LOG.debug("Deleting Metering Label with id %s", label['id'])
|
|
client.delete_metering_label(label['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Metering Label %s exception.",
|
|
label['id'])
|
|
|
|
def dry_run(self):
|
|
labels = self.list()
|
|
self.data['metering_labels'] = labels
|
|
|
|
def save_state(self):
|
|
labels = self.list()
|
|
self.data['metering_labels'] = {}
|
|
for label in labels:
|
|
self.data['metering_labels'][label['id']] = label['name']
|
|
|
|
|
|
class NetworkPortService(BaseNetworkService):
|
|
|
|
def list(self):
|
|
client = self.ports_client
|
|
ports = [port for port in
|
|
client.list_ports(**self.tenant_filter)['ports']
|
|
if port["device_owner"] == "" or
|
|
port["device_owner"].startswith("compute:")]
|
|
|
|
if not self.is_save_state:
|
|
# recreate list removing saved ports
|
|
ports = [port for port in ports if port['id']
|
|
not in self.saved_state_json['ports'].keys()]
|
|
if self.is_preserve:
|
|
ports = self._filter_by_conf_networks(ports)
|
|
|
|
LOG.debug("List count, %s Ports", len(ports))
|
|
return ports
|
|
|
|
def delete(self):
|
|
client = self.ports_client
|
|
ports = self.list()
|
|
for port in ports:
|
|
try:
|
|
LOG.debug("Deleting port with id %s", port['id'])
|
|
client.delete_port(port['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Port %s exception.", port['id'])
|
|
|
|
def dry_run(self):
|
|
ports = self.list()
|
|
self.data['ports'] = ports
|
|
|
|
def save_state(self):
|
|
ports = self.list()
|
|
self.data['ports'] = {}
|
|
for port in ports:
|
|
self.data['ports'][port['id']] = port['name']
|
|
|
|
|
|
class NetworkSecGroupService(BaseNetworkService):
|
|
def list(self):
|
|
client = self.security_groups_client
|
|
filter = self.tenant_filter
|
|
# cannot delete default sec group so never show it.
|
|
secgroups = [secgroup for secgroup in
|
|
client.list_security_groups(**filter)['security_groups']
|
|
if secgroup['name'] != 'default']
|
|
|
|
if not self.is_save_state:
|
|
# recreate list removing saved security_groups
|
|
secgroups = [secgroup for secgroup in secgroups if secgroup['id']
|
|
not in self.saved_state_json['security_groups'].keys()
|
|
]
|
|
if self.is_preserve:
|
|
secgroups = [secgroup for secgroup in secgroups
|
|
if secgroup['security_group_rules'][0]['project_id']
|
|
not in CONF_PROJECTS]
|
|
LOG.debug("List count, %s security_groups", len(secgroups))
|
|
return secgroups
|
|
|
|
def delete(self):
|
|
client = self.security_groups_client
|
|
secgroups = self.list()
|
|
for secgroup in secgroups:
|
|
try:
|
|
LOG.debug("Deleting security_group with id %s", secgroup['id'])
|
|
client.delete_security_group(secgroup['id'])
|
|
except Exception:
|
|
LOG.exception("Delete security_group %s exception.",
|
|
secgroup['id'])
|
|
|
|
def dry_run(self):
|
|
secgroups = self.list()
|
|
self.data['security_groups'] = secgroups
|
|
|
|
def save_state(self):
|
|
secgroups = self.list()
|
|
self.data['security_groups'] = {}
|
|
for secgroup in secgroups:
|
|
self.data['security_groups'][secgroup['id']] = secgroup['name']
|
|
|
|
|
|
class NetworkSubnetService(BaseNetworkService):
|
|
|
|
def list(self):
|
|
client = self.subnets_client
|
|
subnets = client.list_subnets(**self.tenant_filter)
|
|
subnets = subnets['subnets']
|
|
if not self.is_save_state:
|
|
# recreate list removing saved subnets
|
|
subnets = [subnet for subnet in subnets if subnet['id']
|
|
not in self.saved_state_json['subnets'].keys()]
|
|
if self.is_preserve:
|
|
subnets = self._filter_by_conf_networks(subnets)
|
|
LOG.debug("List count, %s Subnets", len(subnets))
|
|
return subnets
|
|
|
|
def delete(self):
|
|
client = self.subnets_client
|
|
subnets = self.list()
|
|
for subnet in subnets:
|
|
try:
|
|
LOG.debug("Deleting subnet with id %s", subnet['id'])
|
|
client.delete_subnet(subnet['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Subnet %s exception.", subnet['id'])
|
|
|
|
def dry_run(self):
|
|
subnets = self.list()
|
|
self.data['subnets'] = subnets
|
|
|
|
def save_state(self):
|
|
subnets = self.list()
|
|
self.data['subnets'] = {}
|
|
for subnet in subnets:
|
|
self.data['subnets'][subnet['id']] = subnet['name']
|
|
|
|
|
|
class NetworkSubnetPoolsService(BaseNetworkService):
|
|
|
|
def list(self):
|
|
client = self.subnetpools_client
|
|
pools = client.list_subnetpools(**self.tenant_filter)['subnetpools']
|
|
if not self.is_save_state:
|
|
# recreate list removing saved subnet pools
|
|
pools = [pool for pool in pools if pool['id']
|
|
not in self.saved_state_json['subnetpools'].keys()]
|
|
if self.is_preserve:
|
|
pools = [pool for pool in pools if pool['project_id']
|
|
not in CONF_PROJECTS]
|
|
LOG.debug("List count, %s Subnet Pools", len(pools))
|
|
return pools
|
|
|
|
def delete(self):
|
|
client = self.subnetpools_client
|
|
pools = self.list()
|
|
for pool in pools:
|
|
try:
|
|
LOG.debug("Deleting Subnet Pool with id %s", pool['id'])
|
|
client.delete_subnetpool(pool['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Subnet Pool %s exception.", pool['id'])
|
|
|
|
def dry_run(self):
|
|
pools = self.list()
|
|
self.data['subnetpools'] = pools
|
|
|
|
def save_state(self):
|
|
pools = self.list()
|
|
self.data['subnetpools'] = {}
|
|
for pool in pools:
|
|
self.data['subnetpools'][pool['id']] = pool['name']
|
|
|
|
|
|
# begin global services
|
|
class RegionService(BaseService):
|
|
|
|
def __init__(self, manager, **kwargs):
|
|
super(RegionService, self).__init__(kwargs)
|
|
self.client = manager.regions_client
|
|
|
|
def list(self):
|
|
client = self.client
|
|
regions = client.list_regions()
|
|
if not self.is_save_state:
|
|
regions = [region for region in regions['regions'] if region['id']
|
|
not in self.saved_state_json['regions'].keys()]
|
|
LOG.debug("List count, %s Regions", len(regions))
|
|
return regions
|
|
else:
|
|
LOG.debug("List count, %s Regions", len(regions['regions']))
|
|
return regions['regions']
|
|
|
|
def delete(self):
|
|
client = self.client
|
|
regions = self.list()
|
|
for region in regions:
|
|
try:
|
|
LOG.debug("Deleting region with id %s", region['id'])
|
|
client.delete_region(region['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Region %s exception.", region['id'])
|
|
|
|
def dry_run(self):
|
|
regions = self.list()
|
|
self.data['regions'] = {}
|
|
for region in regions:
|
|
self.data['regions'][region['id']] = region
|
|
|
|
def save_state(self):
|
|
regions = self.list()
|
|
self.data['regions'] = {}
|
|
for region in regions:
|
|
self.data['regions'][region['id']] = region
|
|
|
|
|
|
class FlavorService(BaseService):
|
|
def __init__(self, manager, **kwargs):
|
|
super(FlavorService, self).__init__(kwargs)
|
|
self.client = manager.flavors_client
|
|
|
|
def list(self):
|
|
client = self.client
|
|
flavors = client.list_flavors({"is_public": None})['flavors']
|
|
if not self.is_save_state:
|
|
# recreate list removing saved flavors
|
|
flavors = [flavor for flavor in flavors if flavor['id']
|
|
not in self.saved_state_json['flavors'].keys()]
|
|
|
|
if self.is_preserve:
|
|
flavors = [flavor for flavor in flavors
|
|
if flavor['id'] not in CONF_FLAVORS]
|
|
LOG.debug("List count, %s Flavors after reconcile", len(flavors))
|
|
return flavors
|
|
|
|
def delete(self):
|
|
client = self.client
|
|
flavors = self.list()
|
|
for flavor in flavors:
|
|
try:
|
|
LOG.debug("Deleting flavor with id %s", flavor['id'])
|
|
client.delete_flavor(flavor['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Flavor %s exception.", flavor['id'])
|
|
|
|
def dry_run(self):
|
|
flavors = self.list()
|
|
self.data['flavors'] = flavors
|
|
|
|
def save_state(self):
|
|
flavors = self.list()
|
|
self.data['flavors'] = {}
|
|
for flavor in flavors:
|
|
self.data['flavors'][flavor['id']] = flavor['name']
|
|
|
|
|
|
class ImageService(BaseService):
|
|
def __init__(self, manager, **kwargs):
|
|
super(ImageService, self).__init__(kwargs)
|
|
self.client = manager.image_client_v2
|
|
|
|
def list(self):
|
|
client = self.client
|
|
response = client.list_images()
|
|
images = []
|
|
images.extend(response['images'])
|
|
while 'next' in response:
|
|
parsed = urllib.urlparse(response['next'])
|
|
marker = urllib.parse_qs(parsed.query)['marker'][0]
|
|
response = client.list_images(params={"marker": marker})
|
|
images.extend(response['images'])
|
|
|
|
if not self.is_save_state:
|
|
images = [image for image in images if image['id']
|
|
not in self.saved_state_json['images'].keys()]
|
|
if self.is_preserve:
|
|
images = [image for image in images
|
|
if image['id'] not in CONF_IMAGES]
|
|
LOG.debug("List count, %s Images after reconcile", len(images))
|
|
return images
|
|
|
|
def delete(self):
|
|
client = self.client
|
|
images = self.list()
|
|
for image in images:
|
|
try:
|
|
LOG.debug("Deleting image with id %s", image['id'])
|
|
client.delete_image(image['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Image %s exception.", image['id'])
|
|
|
|
def dry_run(self):
|
|
images = self.list()
|
|
self.data['images'] = images
|
|
|
|
def save_state(self):
|
|
self.data['images'] = {}
|
|
images = self.list()
|
|
for image in images:
|
|
self.data['images'][image['id']] = image['name']
|
|
|
|
|
|
class UserService(BaseService):
|
|
|
|
def __init__(self, manager, **kwargs):
|
|
super(UserService, self).__init__(kwargs)
|
|
self.client = manager.users_v3_client
|
|
|
|
def list(self):
|
|
users = self.client.list_users()['users']
|
|
|
|
if not self.is_save_state:
|
|
users = [user for user in users if user['id']
|
|
not in self.saved_state_json['users'].keys()]
|
|
|
|
if self.is_preserve:
|
|
users = [user for user in users if user['name']
|
|
not in CONF_USERS]
|
|
|
|
elif not self.is_save_state: # Never delete admin user
|
|
users = [user for user in users if user['name'] !=
|
|
CONF.auth.admin_username]
|
|
|
|
LOG.debug("List count, %s Users after reconcile", len(users))
|
|
return users
|
|
|
|
def delete(self):
|
|
users = self.list()
|
|
for user in users:
|
|
try:
|
|
LOG.debug("Deleting user with id %s", user['id'])
|
|
self.client.delete_user(user['id'])
|
|
except Exception:
|
|
LOG.exception("Delete User %s exception.", user['id'])
|
|
|
|
def dry_run(self):
|
|
users = self.list()
|
|
self.data['users'] = users
|
|
|
|
def save_state(self):
|
|
users = self.list()
|
|
self.data['users'] = {}
|
|
for user in users:
|
|
self.data['users'][user['id']] = user['name']
|
|
|
|
|
|
class RoleService(BaseService):
|
|
|
|
def __init__(self, manager, **kwargs):
|
|
super(RoleService, self).__init__(kwargs)
|
|
self.client = manager.roles_v3_client
|
|
|
|
def list(self):
|
|
try:
|
|
roles = self.client.list_roles()['roles']
|
|
# reconcile roles with saved state and never list admin role
|
|
if not self.is_save_state:
|
|
roles = [role for role in roles if
|
|
(role['id'] not in
|
|
self.saved_state_json['roles'].keys() and
|
|
role['name'] != CONF.identity.admin_role)]
|
|
LOG.debug("List count, %s Roles after reconcile", len(roles))
|
|
return roles
|
|
except Exception:
|
|
LOG.exception("Cannot retrieve Roles.")
|
|
return []
|
|
|
|
def delete(self):
|
|
roles = self.list()
|
|
for role in roles:
|
|
try:
|
|
LOG.debug("Deleting role with id %s", role['id'])
|
|
self.client.delete_role(role['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Role %s exception.", role['id'])
|
|
|
|
def dry_run(self):
|
|
roles = self.list()
|
|
self.data['roles'] = roles
|
|
|
|
def save_state(self):
|
|
roles = self.list()
|
|
self.data['roles'] = {}
|
|
for role in roles:
|
|
self.data['roles'][role['id']] = role['name']
|
|
|
|
|
|
class ProjectService(BaseService):
|
|
|
|
def __init__(self, manager, **kwargs):
|
|
super(ProjectService, self).__init__(kwargs)
|
|
self.client = manager.projects_client
|
|
|
|
def list(self):
|
|
projects = self.client.list_projects()['projects']
|
|
if not self.is_save_state:
|
|
project_ids = self.saved_state_json['projects']
|
|
projects = [project
|
|
for project in projects
|
|
if (project['id'] not in project_ids and
|
|
project['name'] != CONF.auth.admin_project_name)]
|
|
|
|
if self.is_preserve:
|
|
projects = [project
|
|
for project in projects
|
|
if project['name'] not in CONF_PROJECTS]
|
|
|
|
LOG.debug("List count, %s Projects after reconcile", len(projects))
|
|
return projects
|
|
|
|
def delete(self):
|
|
projects = self.list()
|
|
for project in projects:
|
|
try:
|
|
LOG.debug("Deleting project with id %s", project['id'])
|
|
self.client.delete_project(project['id'])
|
|
except Exception:
|
|
LOG.exception("Delete project %s exception.", project['id'])
|
|
|
|
def dry_run(self):
|
|
projects = self.list()
|
|
self.data['projects'] = projects
|
|
|
|
def save_state(self):
|
|
projects = self.list()
|
|
self.data['projects'] = {}
|
|
for project in projects:
|
|
self.data['projects'][project['id']] = project['name']
|
|
|
|
|
|
class DomainService(BaseService):
|
|
|
|
def __init__(self, manager, **kwargs):
|
|
super(DomainService, self).__init__(kwargs)
|
|
self.client = manager.domains_client
|
|
|
|
def list(self):
|
|
client = self.client
|
|
domains = client.list_domains()['domains']
|
|
if not self.is_save_state:
|
|
domains = [domain for domain in domains if domain['id']
|
|
not in self.saved_state_json['domains'].keys()]
|
|
|
|
LOG.debug("List count, %s Domains after reconcile", len(domains))
|
|
return domains
|
|
|
|
def delete(self):
|
|
client = self.client
|
|
domains = self.list()
|
|
for domain in domains:
|
|
try:
|
|
LOG.debug("Deleting domain with id %s", domain['id'])
|
|
client.update_domain(domain['id'], enabled=False)
|
|
client.delete_domain(domain['id'])
|
|
except Exception:
|
|
LOG.exception("Delete Domain %s exception.", domain['id'])
|
|
|
|
def dry_run(self):
|
|
domains = self.list()
|
|
self.data['domains'] = domains
|
|
|
|
def save_state(self):
|
|
domains = self.list()
|
|
self.data['domains'] = {}
|
|
for domain in domains:
|
|
self.data['domains'][domain['id']] = domain['name']
|
|
|
|
|
|
def get_project_associated_cleanup_services():
|
|
"""Returns list of project service classes.
|
|
|
|
The list contains services whose resources need to be deleted prior,
|
|
the project they are associated with, deletion. The resources cannot be
|
|
most likely deleted after the project is deleted first.
|
|
"""
|
|
project_associated_services = []
|
|
# TODO(gmann): Tempest should provide some plugin hook for cleanup
|
|
# script extension to plugin tests also.
|
|
if IS_NOVA:
|
|
project_associated_services.append(NovaQuotaService)
|
|
if IS_CINDER:
|
|
project_associated_services.append(VolumeQuotaService)
|
|
if IS_NEUTRON:
|
|
project_associated_services.append(NetworkQuotaService)
|
|
return project_associated_services
|
|
|
|
|
|
def get_resource_cleanup_services():
|
|
"""Returns list of project related classes.
|
|
|
|
The list contains services whose resources are associated with a project,
|
|
however, their deletion is possible also after the project is deleted
|
|
first.
|
|
"""
|
|
resource_cleanup_services = []
|
|
# TODO(gmann): Tempest should provide some plugin hook for cleanup
|
|
# script extension to plugin tests also.
|
|
if IS_NOVA:
|
|
resource_cleanup_services.append(ServerService)
|
|
resource_cleanup_services.append(KeyPairService)
|
|
resource_cleanup_services.append(ServerGroupService)
|
|
if IS_NEUTRON:
|
|
resource_cleanup_services.append(NetworkFloatingIpService)
|
|
if utils.is_extension_enabled('metering', 'network'):
|
|
resource_cleanup_services.append(NetworkMeteringLabelRuleService)
|
|
resource_cleanup_services.append(NetworkMeteringLabelService)
|
|
resource_cleanup_services.append(NetworkRouterService)
|
|
resource_cleanup_services.append(NetworkPortService)
|
|
resource_cleanup_services.append(NetworkSubnetService)
|
|
resource_cleanup_services.append(NetworkService)
|
|
resource_cleanup_services.append(NetworkSecGroupService)
|
|
resource_cleanup_services.append(NetworkSubnetPoolsService)
|
|
if IS_CINDER:
|
|
resource_cleanup_services.append(SnapshotService)
|
|
resource_cleanup_services.append(VolumeService)
|
|
return resource_cleanup_services
|
|
|
|
|
|
def get_global_cleanup_services():
|
|
global_services = []
|
|
if IS_NOVA:
|
|
global_services.append(FlavorService)
|
|
if IS_GLANCE:
|
|
global_services.append(ImageService)
|
|
global_services.append(UserService)
|
|
global_services.append(ProjectService)
|
|
global_services.append(DomainService)
|
|
global_services.append(RoleService)
|
|
global_services.append(RegionService)
|
|
return global_services
|