#!/usr/bin/env 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 tempest.common import credentials_factory as credentials
from tempest.common import identity
from tempest.common.utils import net_info
from tempest import config
from tempest import test

LOG = logging.getLogger(__name__)
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_TENANTS = None
CONF_USERS = None

IS_CINDER = None
IS_GLANCE = None
IS_HEAT = 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_TENANTS
    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_HEAT = CONF.service_available.heat
    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_TENANTS = [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 = credentials.AdminManager()
    net_cl = am.networks_client
    tn_cl = am.tenants_client

    networks = net_cl.list_networks()
    tenant = identity.get_tenant_by_name(tn_cl, project_name)
    t_id = tenant['id']
    n_id = None
    for net in networks['networks']:
        if (net['tenant_id'] == t_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['tenant_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):
        if self.is_dry_run:
            self.dry_run()
        elif self.is_save_state:
            self.save_state()
        else:
            self.delete()


class SnapshotService(BaseService):

    def __init__(self, manager, **kwargs):
        super(SnapshotService, self).__init__(kwargs)
        self.client = manager.snapshots_client

    def list(self):
        client = self.client
        snaps = client.list_snapshots()['snapshots']
        LOG.debug("List count, %s Snapshots", len(snaps))
        return snaps

    def delete(self):
        snaps = self.list()
        client = self.client
        for snap in snaps:
            try:
                client.delete_snapshot(snap['id'])
            except Exception:
                LOG.exception("Delete Snapshot exception.")

    def dry_run(self):
        snaps = self.list()
        self.data['snapshots'] = snaps


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']
        LOG.debug("List count, %s Servers", len(servers))
        return servers

    def delete(self):
        client = self.client
        servers = self.list()
        for server in servers:
            try:
                client.delete_server(server['id'])
            except Exception:
                LOG.exception("Delete Server exception.")

    def dry_run(self):
        servers = self.list()
        self.data['servers'] = servers


class ServerGroupService(ServerService):

    def list(self):
        client = self.server_groups_client
        sgs = client.list_server_groups()['server_groups']
        LOG.debug("List count, %s Server Groups", len(sgs))
        return sgs

    def delete(self):
        client = self.client
        sgs = self.list()
        for sg in sgs:
            try:
                client.delete_server_group(sg['id'])
            except Exception:
                LOG.exception("Delete Server Group exception.")

    def dry_run(self):
        sgs = self.list()
        self.data['server_groups'] = sgs


class StackService(BaseService):
    def __init__(self, manager, **kwargs):
        super(StackService, self).__init__(kwargs)
        params = config.service_client_config('orchestration')
        self.client = manager.orchestration.OrchestrationClient(
            manager.auth_provider, **params)

    def list(self):
        client = self.client
        stacks = client.list_stacks()['stacks']
        LOG.debug("List count, %s Stacks", len(stacks))
        return stacks

    def delete(self):
        client = self.client
        stacks = self.list()
        for stack in stacks:
            try:
                client.delete_stack(stack['id'])
            except Exception:
                LOG.exception("Delete Stack exception.")

    def dry_run(self):
        stacks = self.list()
        self.data['stacks'] = stacks


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']
        LOG.debug("List count, %s Keypairs", len(keypairs))
        return keypairs

    def delete(self):
        client = self.client
        keypairs = self.list()
        for k in keypairs:
            try:
                name = k['keypair']['name']
                client.delete_keypair(name)
            except Exception:
                LOG.exception("Delete Keypairs exception.")

    def dry_run(self):
        keypairs = self.list()
        self.data['keypairs'] = keypairs


class SecurityGroupService(BaseService):
    def __init__(self, manager, **kwargs):
        super(SecurityGroupService, self).__init__(kwargs)
        self.client = manager.compute_security_groups_client

    def list(self):
        client = self.client
        secgrps = client.list_security_groups()['security_groups']
        secgrp_del = [grp for grp in secgrps if grp['name'] != 'default']
        LOG.debug("List count, %s Security Groups", len(secgrp_del))
        return secgrp_del

    def delete(self):
        client = self.client
        secgrp_del = self.list()
        for g in secgrp_del:
            try:
                client.delete_security_group(g['id'])
            except Exception:
                LOG.exception("Delete Security Groups exception.")

    def dry_run(self):
        secgrp_del = self.list()
        self.data['security_groups'] = secgrp_del


class FloatingIpService(BaseService):
    def __init__(self, manager, **kwargs):
        super(FloatingIpService, self).__init__(kwargs)
        self.client = manager.compute_floating_ips_client

    def list(self):
        client = self.client
        floating_ips = client.list_floating_ips()['floating_ips']
        LOG.debug("List count, %s Floating IPs", len(floating_ips))
        return floating_ips

    def delete(self):
        client = self.client
        floating_ips = self.list()
        for f in floating_ips:
            try:
                client.delete_floating_ip(f['id'])
            except Exception:
                LOG.exception("Delete Floating IPs exception.")

    def dry_run(self):
        floating_ips = self.list()
        self.data['floating_ips'] = floating_ips


class VolumeService(BaseService):
    def __init__(self, manager, **kwargs):
        super(VolumeService, self).__init__(kwargs)
        self.client = manager.volumes_client

    def list(self):
        client = self.client
        vols = client.list_volumes()['volumes']
        LOG.debug("List count, %s Volumes", len(vols))
        return vols

    def delete(self):
        client = self.client
        vols = self.list()
        for v in vols:
            try:
                client.delete_volume(v['id'])
            except Exception:
                LOG.exception("Delete Volume exception.")

    def dry_run(self):
        vols = self.list()
        self.data['volumes'] = vols


class VolumeQuotaService(BaseService):
    def __init__(self, manager, **kwargs):
        super(VolumeQuotaService, self).__init__(kwargs)
        self.client = manager.volume_quotas_client

    def delete(self):
        client = self.client
        try:
            client.delete_quota_set(self.tenant_id)
        except Exception:
            LOG.exception("Delete Volume Quotas exception.")

    def dry_run(self):
        quotas = self.client.show_quota_set(
            self.tenant_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:
            client.delete_quota_set(self.tenant_id)
        except Exception:
            LOG.exception("Delete Quotas exception.")

    def dry_run(self):
        client = self.limits_client
        quotas = client.show_limits()['limits']
        self.data['compute_quotas'] = quotas['absolute']


# Begin network service classes
class NetworkService(BaseService):
    def __init__(self, manager, **kwargs):
        super(NetworkService, 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

    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]

    def list(self):
        client = self.networks_client
        networks = client.list_networks(**self.tenant_filter)
        networks = networks['networks']
        # 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", networks)
        return networks

    def delete(self):
        client = self.networks_client
        networks = self.list()
        for n in networks:
            try:
                client.delete_network(n['id'])
            except Exception:
                LOG.exception("Delete Network exception.")

    def dry_run(self):
        networks = self.list()
        self.data['networks'] = networks


class NetworkFloatingIpService(NetworkService):

    def list(self):
        client = self.floating_ips_client
        flips = client.list_floatingips(**self.tenant_filter)
        flips = flips['floatingips']
        LOG.debug("List count, %s Network Floating IPs", len(flips))
        return flips

    def delete(self):
        client = self.client
        flips = self.list()
        for flip in flips:
            try:
                client.delete_floatingip(flip['id'])
            except Exception:
                LOG.exception("Delete Network Floating IP exception.")

    def dry_run(self):
        flips = self.list()
        self.data['floating_ips'] = flips


class NetworkRouterService(NetworkService):

    def list(self):
        client = self.routers_client
        routers = client.list_routers(**self.tenant_filter)
        routers = routers['routers']
        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:
            try:
                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:
                    client.remove_router_interface(rid, port_id=port['id'])
                client.delete_router(rid)
            except Exception:
                LOG.exception("Delete Router exception.")

    def dry_run(self):
        routers = self.list()
        self.data['routers'] = routers


class NetworkHealthMonitorService(NetworkService):

    def list(self):
        client = self.client
        hms = client.list_health_monitors()
        hms = hms['health_monitors']
        hms = self._filter_by_tenant_id(hms)
        LOG.debug("List count, %s Health Monitors", len(hms))
        return hms

    def delete(self):
        client = self.client
        hms = self.list()
        for hm in hms:
            try:
                client.delete_health_monitor(hm['id'])
            except Exception:
                LOG.exception("Delete Health Monitor exception.")

    def dry_run(self):
        hms = self.list()
        self.data['health_monitors'] = hms


class NetworkMemberService(NetworkService):

    def list(self):
        client = self.client
        members = client.list_members()
        members = members['members']
        members = self._filter_by_tenant_id(members)
        LOG.debug("List count, %s Members", len(members))
        return members

    def delete(self):
        client = self.client
        members = self.list()
        for member in members:
            try:
                client.delete_member(member['id'])
            except Exception:
                LOG.exception("Delete Member exception.")

    def dry_run(self):
        members = self.list()
        self.data['members'] = members


class NetworkVipService(NetworkService):

    def list(self):
        client = self.client
        vips = client.list_vips()
        vips = vips['vips']
        vips = self._filter_by_tenant_id(vips)
        LOG.debug("List count, %s VIPs", len(vips))
        return vips

    def delete(self):
        client = self.client
        vips = self.list()
        for vip in vips:
            try:
                client.delete_vip(vip['id'])
            except Exception:
                LOG.exception("Delete VIP exception.")

    def dry_run(self):
        vips = self.list()
        self.data['vips'] = vips


class NetworkPoolService(NetworkService):

    def list(self):
        client = self.client
        pools = client.list_pools()
        pools = pools['pools']
        pools = self._filter_by_tenant_id(pools)
        LOG.debug("List count, %s Pools", len(pools))
        return pools

    def delete(self):
        client = self.client
        pools = self.list()
        for pool in pools:
            try:
                client.delete_pool(pool['id'])
            except Exception:
                LOG.exception("Delete Pool exception.")

    def dry_run(self):
        pools = self.list()
        self.data['pools'] = pools


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)
        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:
                client.delete_metering_label_rule(rule['id'])
            except Exception:
                LOG.exception("Delete Metering Label Rule exception.")

    def dry_run(self):
        rules = self.list()
        self.data['rules'] = rules


class NetworkMeteringLabelService(NetworkService):

    def list(self):
        client = self.metering_labels_client
        labels = client.list_metering_labels()
        labels = labels['metering_labels']
        labels = self._filter_by_tenant_id(labels)
        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:
                client.delete_metering_label(label['id'])
            except Exception:
                LOG.exception("Delete Metering Label exception.")

    def dry_run(self):
        labels = self.list()
        self.data['labels'] = labels


class NetworkPortService(NetworkService):

    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 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:
                client.delete_port(port['id'])
            except Exception:
                LOG.exception("Delete Port exception.")

    def dry_run(self):
        ports = self.list()
        self.data['ports'] = ports


class NetworkSecGroupService(NetworkService):
    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 self.is_preserve:
            secgroups = self._filter_by_conf_networks(secgroups)
        LOG.debug("List count, %s security_groups", len(secgroups))
        return secgroups

    def delete(self):
        client = self.client
        secgroups = self.list()
        for secgroup in secgroups:
            try:
                client.delete_secgroup(secgroup['id'])
            except Exception:
                LOG.exception("Delete security_group exception.")

    def dry_run(self):
        secgroups = self.list()
        self.data['secgroups'] = secgroups


class NetworkSubnetService(NetworkService):

    def list(self):
        client = self.subnets_client
        subnets = client.list_subnets(**self.tenant_filter)
        subnets = subnets['subnets']
        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:
                client.delete_subnet(subnet['id'])
            except Exception:
                LOG.exception("Delete Subnet exception.")

    def dry_run(self):
        subnets = self.list()
        self.data['subnets'] = subnets


# begin global services
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:
                client.delete_flavor(flavor['id'])
            except Exception:
                LOG.exception("Delete Flavor exception.")

    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.compute_images_client

    def list(self):
        client = self.client
        images = client.list_images({"all_tenants": True})['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:
                client.delete_image(image['id'])
            except Exception:
                LOG.exception("Delete Image exception.")

    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 IdentityService(BaseService):
    def __init__(self, manager, **kwargs):
        super(IdentityService, self).__init__(kwargs)
        self.client = manager.identity_client


class UserService(BaseService):

    def __init__(self, manager, **kwargs):
        super(UserService, self).__init__(kwargs)
        self.client = manager.users_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:
                self.client.delete_user(user['id'])
            except Exception:
                LOG.exception("Delete User exception.")

    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_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:
                self.client.delete_role(role['id'])
            except Exception:
                LOG.exception("Delete Role exception.")

    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 TenantService(BaseService):

    def __init__(self, manager, **kwargs):
        super(TenantService, self).__init__(kwargs)
        self.client = manager.tenants_client

    def list(self):
        tenants = self.client.list_tenants()['tenants']
        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)]

        if self.is_preserve:
            tenants = [tenant for tenant in tenants if tenant['name']
                       not in CONF_TENANTS]

        LOG.debug("List count, %s Tenants after reconcile", len(tenants))
        return tenants

    def delete(self):
        tenants = self.list()
        for tenant in tenants:
            try:
                self.client.delete_tenant(tenant['id'])
            except Exception:
                LOG.exception("Delete Tenant exception.")

    def dry_run(self):
        tenants = self.list()
        self.data['tenants'] = tenants

    def save_state(self):
        tenants = self.list()
        self.data['tenants'] = {}
        for tenant in tenants:
            self.data['tenants'][tenant['id']] = tenant['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:
                client.update_domain(domain['id'], enabled=False)
                client.delete_domain(domain['id'])
            except Exception:
                LOG.exception("Delete Domain exception.")

    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_tenant_cleanup_services():
    tenant_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)
        if not IS_NEUTRON:
            tenant_services.append(FloatingIpService)
        tenant_services.append(NovaQuotaService)
    if IS_HEAT:
        tenant_services.append(StackService)
    if IS_NEUTRON:
        tenant_services.append(NetworkFloatingIpService)
        if test.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)
    if IS_CINDER:
        tenant_services.append(SnapshotService)
        tenant_services.append(VolumeService)
        tenant_services.append(VolumeQuotaService)
    return tenant_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(TenantService)
    global_services.append(DomainService)
    global_services.append(RoleService)
    return global_services
