import argparse
import json
import os
import re
import sys
import time

from types import SimpleNamespace

import openstack


# Send logs to both, a log file and stdout
openstack.enable_logging(debug=False, path='openstack.log', stream=sys.stdout)

volume_api_version = "3.43"
manila_api_version = "2.75"

# Connect to cloud
TEST_CLOUD = os.getenv('OS_TEST_CLOUD', 'os-cloud')
cloud = openstack.connect(cloud=TEST_CLOUD)
log = cloud.log

# Get cloud config (clouds.yaml vars)
config_obj = openstack.config.loader.OpenStackConfig()
cloud_config = config_obj.get_one(cloud=TEST_CLOUD)

compute = cloud.compute
identity = cloud.identity
image = cloud.image
network = cloud.network
orchestration = cloud.orchestration
volume = cloud.volume
load_balancer = cloud.load_balancer

# Check if Object Storage is present on the cloud, else skip
object_store_present = any(service.type == 'object-store' for service
                           in list(identity.services()))
if object_store_present:
    object_store = cloud.object_store

# Check if Manila Shared File System is present on the cloud, else skip
manila_present = any(service.type == 'sharev2' for service
                           in list(identity.services()))
if manila_present:
    shared_file_system = cloud.shared_file_system

mask = "cvp|s_rally|rally_|tempest-|tempest_|spt|fio"
full_mask = f"^(?!.*(manual|-static-)).*({mask}).*$"
mask_pattern = re.compile(full_mask, re.IGNORECASE)
stack_mask = "api-[0-9]+-[a-z]+"
stack_pattern = re.compile(stack_mask, re.IGNORECASE)


def get_resource_value(resource_key, default):
    try:
        return cloud_config.config['custom_vars'][resource_key]
    except KeyError:
        return default


def items_to_object(items):
    data = json.dumps(items)
    return json.loads(data, object_hook=lambda d: SimpleNamespace(**d))


def _filter_test_resources(resources, attribute, pattern=mask_pattern):
    filtered_resources = {}
    for item in resources:
        # If there is no attribute in object, use just empty string as value
        value = getattr(item, attribute, '')
        # If the attribute value is None, use empty string instead, to be
        # able to run regex search
        if value is None:
            value = ''
        found = pattern.match(value)
        if found:
            filtered_resources[item.id] = getattr(item, attribute)
    return filtered_resources


def _log_resources_count(count, resource, pattern=mask):
    log.info(f"{count} {resource} containing '{pattern}' are found.")


def _log_resource_delete(id_, name, type_):
    log.info(f"... deleting {name} (id={id_}) {type_}")


def _get_volume_groups(all_tenants='true'):
    ep = volume.get_endpoint()
    uri = f"{ep}/groups/detail"
    headers = {'X-Auth-Token': cloud.session.get_token(),
               'Accept': 'application/json',
               'OpenStack-API-Version': f'volume {volume_api_version}'}
    params = {'all_tenants': all_tenants}
    response = cloud.session.request(url=uri, method='GET',
                                     headers=headers, params=params).json()
    for group in response['groups']:
        yield group


def _get_shares(all_tenants='true'):
    ep = shared_file_system.get_endpoint()
    uri = f"{ep}/shares/detail"
    headers = {'X-Auth-Token': cloud.session.get_token(),
               'Accept': 'application/json',
               'X-Openstack-Manila-Api-Version': f'{manila_api_version}'}
    params = {'all_tenants': all_tenants}
    response = cloud.session.request(url=uri, method='GET',
                                     headers=headers, params=params).json()
    for share in response['shares']:
        yield share


def _get_share_types(all_tenants='true'):
    ep = shared_file_system.get_endpoint()
    uri = f"{ep}/types"
    headers = {'X-Auth-Token': cloud.session.get_token(),
               'Accept': 'application/json',
               'X-Openstack-Manila-Api-Version': f'{manila_api_version}'}
    params = {'all_tenants': all_tenants}
    response = cloud.session.request(url=uri, method='GET',
                                     headers=headers, params=params).json()
    for share_type in response['volume_types']:
        yield share_type


def _get_share_networks(all_tenants='true'):
    ep = shared_file_system.get_endpoint()
    uri = f"{ep}/share-networks/detail"
    headers = {'X-Auth-Token': cloud.session.get_token(),
               'Accept': 'application/json',
               'X-Openstack-Manila-Api-Version': f'{manila_api_version}'}
    params = {'all_tenants': all_tenants}
    response = cloud.session.request(url=uri, method='GET',
                                     headers=headers, params=params).json()
    for share_network in response['share_networks']:
        yield share_network


def _delete_volume_group(uuid, delete_volumes='false'):
    ep = volume.get_endpoint()
    uri = f"{ep}/groups/{uuid}/action"
    headers = {'X-Auth-Token': cloud.session.get_token(),
               'OpenStack-API-Version': f'volume {volume_api_version}',
               'Content-Type': 'application/json',
               'Accept': 'application/json'}
    body = {"delete": {"delete-volumes": delete_volumes}}
    cloud.session.request(
        url=uri, method='POST', headers=headers, json=body)


def _delete_share_type(uuid):
    ep = shared_file_system.get_endpoint()
    uri = f"{ep}/types/{uuid}"
    headers = {'X-Auth-Token': cloud.session.get_token(),
               'X-Openstack-Manila-Api-Version': f'{manila_api_version}',
               'Content-Type': 'application/json',
               'Accept': 'application/json'}
    cloud.session.request(
        url=uri, method='DELETE', headers=headers)


def _delete_share(uuid, force_delete=True):
    ep = shared_file_system.get_endpoint()
    uri = f"{ep}/shares/{uuid}/action"
    headers = {'X-Auth-Token': cloud.session.get_token(),
               'X-Openstack-Manila-Api-Version': f'{manila_api_version}',
               'Content-Type': 'application/json',
               'Accept': 'application/json'}
    body = {"force_delete": force_delete}
    cloud.session.request(
        url=uri, method='POST', headers=headers, json=body)


def _delete_share_network(uuid):
    ep = shared_file_system.get_endpoint()
    uri = f"{ep}/share-networks/{uuid}"
    headers = {'X-Auth-Token': cloud.session.get_token(),
               'X-Openstack-Manila-Api-Version': f'{manila_api_version}',
               'Content-Type': 'application/json',
               'Accept': 'application/json'}
    cloud.session.request(
        url=uri, method='DELETE', headers=headers)


def _reset_volume_status(uuid, status='available', attach_status='detached',
                         migration_status='None'):
    ep = volume.get_endpoint()
    uri = f"{ep}/volumes/{uuid}/action"
    headers = {'X-Auth-Token': cloud.session.get_token(),
               'Content-Type': 'application/json',
               'Accept': 'application/json'}
    body = {"os-reset_status": {
        "status": status, "attach_status": attach_status,
        "migration_status": migration_status}}
    cloud.session.request(
        url=uri, method='POST', headers=headers, json=body)


def cleanup_users():
    users = identity.users()
    users_to_delete = _filter_test_resources(users, 'name')
    _log_resources_count(len(users_to_delete), 'user(s)')
    if args.dry_run:
        return
    for id_ in users_to_delete:
        _log_resource_delete(id_, users_to_delete[id_], 'user')
        identity.delete_user(id_)


def cleanup_roles():
    roles = identity.roles()
    roles_to_delete = _filter_test_resources(roles, 'name')
    _log_resources_count(len(roles_to_delete), 'role(s)')
    if args.dry_run:
        return
    for id_ in roles_to_delete:
        _log_resource_delete(id_, roles_to_delete[id_], 'role')
        identity.delete_role(id_)


def cleanup_projects():
    projects = identity.projects()
    projects_to_delete = _filter_test_resources(projects, 'name')
    _log_resources_count(len(projects_to_delete), 'project(s)')
    if args.dry_run:
        return
    for id_ in projects_to_delete:
        _log_resource_delete(id_, projects_to_delete[id_], 'project')
        identity.delete_project(id_)


def cleanup_regions():
    regions = identity.regions()
    regions_to_delete = _filter_test_resources(regions, 'id')
    _log_resources_count(len(regions_to_delete), 'region(s)')
    if args.dry_run:
        return
    for id_ in regions_to_delete:
        _log_resource_delete(id_, id_, 'region')
        identity.delete_region(id_)


def cleanup_services():
    services = identity.services()
    services_to_delete = _filter_test_resources(services, 'name')
    _log_resources_count(len(services_to_delete), 'service(s)')
    if args.dry_run:
        return
    for id_ in services_to_delete:
        _log_resource_delete(id_, services_to_delete[id_], 'service')
        identity.delete_service(id_)


def cleanup_stacks(stacks_alt=False):
    stacks = orchestration.stacks()
    stacks_to_delete = _filter_test_resources(stacks, 'name')
    _log_resources_count(len(stacks_to_delete), 'stack(s)')

    # Use additional pattern for searching/deleting test Heat resources,
    # if enabled
    if stacks_alt:
        stacks_alt_to_delete = _filter_test_resources(
            stacks, 'name', stack_pattern)
        _log_resources_count(len(stacks_alt_to_delete), 'stack(s)', stack_mask)
        stacks_to_delete.update(stacks_alt_to_delete)

    if args.dry_run:
        return

    for id_ in stacks_to_delete:
        _log_resource_delete(id_, stacks_to_delete[id_], 'stack')
        stack_obj = orchestration.get_stack(id_)
        orchestration.delete_stack(id_)
        orchestration.wait_for_delete(stack_obj)


def cleanup_flavors():
    flavors = compute.flavors()
    flavors_to_delete = _filter_test_resources(flavors, 'name')
    _log_resources_count(len(flavors_to_delete), 'flavor(s)')
    if args.dry_run:
        return
    for id_ in flavors_to_delete:
        _log_resource_delete(id_, flavors_to_delete[id_], 'flavor')
        compute.delete_flavor(id_)


def cleanup_images():
    images = image.images()
    images_to_delete = _filter_test_resources(images, 'name')
    _log_resources_count(len(images_to_delete), 'image(s)')
    if args.dry_run:
        return
    for id_ in images_to_delete:
        _log_resource_delete(id_, images_to_delete[id_], 'image')
        image.delete_image(id_)


def cleanup_keypairs():
    keypairs = compute.keypairs()
    keypairs_to_delete = _filter_test_resources(keypairs, 'name')
    _log_resources_count(len(keypairs_to_delete), 'keypair(s)')
    if args.dry_run:
        return
    for id_ in keypairs_to_delete:
        _log_resource_delete(id_, keypairs_to_delete[id_], 'keypair')
        compute.delete_keypair(id_)


def cleanup_servers():
    servers = compute.servers(all_projects=True)
    servers_to_delete = _filter_test_resources(servers, 'name')
    _log_resources_count(len(servers_to_delete), 'server(s)')
    if args.dry_run:
        return
    for id_ in servers_to_delete:
        if args.servers_active:
            log.info(
                f"... resetting {servers_to_delete[id_]} (id={id_}) server "
                "state to 'active'")
            compute.reset_server_state(id_, 'active')
        _log_resource_delete(id_, servers_to_delete[id_], 'server')
        compute.delete_server(id_)
        srv_obj = compute.get_server(id_)
        compute.wait_for_delete(srv_obj)


def cleanup_shares():
    shares_in_response = _get_shares()
    shares = items_to_object([g for g in shares_in_response])
    shares_to_delete = _filter_test_resources(shares, 'name')
    _log_resources_count(len(shares_to_delete), 'share(s)')
    if args.dry_run:
        return
    for id_ in shares_to_delete:
        _log_resource_delete(id_, shares_to_delete[id_], 'share')
        # TODO: uncomment
        _delete_share(id_)
        shr_obj = shared_file_system.get_share(id_)
        shared_file_system.wait_for_delete(shr_obj)


def cleanup_share_types():
    share_types_in_response = _get_share_types()
    share_types = items_to_object([g for g in share_types_in_response])
    share_types_to_delete = _filter_test_resources(share_types, 'name')
    _log_resources_count(len(share_types_to_delete), 'share type(s)')
    if args.dry_run:
        return
    for id_ in share_types_to_delete:
        _log_resource_delete(id_, share_types_to_delete[id_], 'type')
        _delete_share_type(id_)


def cleanup_share_networks():
    share_networks_in_response = _get_share_networks()
    share_networks = items_to_object([g for g in share_networks_in_response])
    share_networks_to_delete = _filter_test_resources(share_networks, 'name')
    _log_resources_count(len(share_networks_to_delete), 'share network(s)')
    if args.dry_run:
        return
    for id_ in share_networks_to_delete:
        _log_resource_delete(id_, share_networks_to_delete[id_], 'type')
        _delete_share_network(id_)


def cleanup_snapshots():
    snapshots = volume.snapshots(all_projects=True)
    snapshots_to_delete = _filter_test_resources(snapshots, 'name')
    _log_resources_count(len(snapshots_to_delete), 'snapshot(s)')
    if args.dry_run:
        return
    for id_ in snapshots_to_delete:
        snapshot_obj = volume.get_snapshot(id_)
        volume.reset_snapshot(id_, 'available')
        _log_resource_delete(id_, snapshots_to_delete[id_], 'snapshot')
        volume.delete_snapshot(id_, force=True)
        volume.wait_for_delete(snapshot_obj)


def cleanup_volumes():
    volumes = volume.volumes(all_projects=True)
    volumes_to_delete = _filter_test_resources(volumes, 'name')
    _log_resources_count(len(volumes_to_delete), 'volume(s)')
    if args.dry_run:
        return
    for id_ in volumes_to_delete:
        _reset_volume_status(id_, 'available', 'detached', 'None')
        _log_resource_delete(id_, volumes_to_delete[id_], 'volume')
        volume.delete_volume(id_)
        vol_obj = volume.get_volume(id_)
        volume.wait_for_delete(vol_obj)


def cleanup_volume_groups():
    groups_in_response = _get_volume_groups()
    groups = items_to_object([g for g in groups_in_response])
    groups_to_delete = _filter_test_resources(groups, 'name')
    _log_resources_count(len(groups_to_delete), 'volume group(s)')
    if args.dry_run:
        return
    for id_ in groups_to_delete:
        _log_resource_delete(id_, groups_to_delete[id_], 'volume group')
        _delete_volume_group(id_)
        time.sleep(10)      # TODO(izadorozhna): need to add a proper waiter


def cleanup_volume_backups():
    backups = volume.backups(all_tenants=True)
    backups_to_delete = _filter_test_resources(backups, 'name')
    _log_resources_count(len(backups_to_delete), 'volume backup(s)')
    if args.dry_run:
        return
    for id_ in backups_to_delete:
        backup_obj = volume.get_backup(id_)
        _log_resource_delete(id_, backups_to_delete[id_], 'volume backup')
        volume.delete_backup(id_)
        volume.wait_for_delete(backup_obj)


def cleanup_volume_group_types():
    group_types = volume.group_types()
    group_types_to_delete = _filter_test_resources(group_types, 'name')
    _log_resources_count(len(group_types_to_delete), 'volume group type(s)')
    if args.dry_run:
        return
    for id_ in group_types_to_delete:
        _log_resource_delete(
            id_, group_types_to_delete[id_], 'volume group type')
        volume.delete_group_type(id_)


def cleanup_volume_types():
    volume_types = volume.types()
    volume_types_to_delete = _filter_test_resources(volume_types, 'name')
    _log_resources_count(len(volume_types_to_delete), 'volume type(s)')
    if args.dry_run:
        return
    for id_ in volume_types_to_delete:
        _log_resource_delete(id_, volume_types_to_delete[id_], 'volume type')
        volume.delete_type(id_)


def cleanup_sec_groups():
    sec_groups = network.security_groups()
    sec_groups_to_delete = _filter_test_resources(sec_groups, 'name')
    _log_resources_count(len(sec_groups_to_delete), 'security group(s)')
    if args.dry_run:
        return
    for id_ in sec_groups_to_delete:
        _log_resource_delete(id_, sec_groups_to_delete[id_], 'security group')
        network.delete_security_group(id_)


def cleanup_containers():
    containers = object_store.containers()
    containers_to_delete = _filter_test_resources(containers, 'name')
    _log_resources_count(len(containers_to_delete), 'container(s)')
    if args.dry_run:
        return
    for id_ in containers_to_delete:
        _log_resource_delete(id_, containers_to_delete[id_], 'container')
        object_store.delete_container(id_)


def cleanup_routers():
    routers = network.routers()
    routers_to_delete = _filter_test_resources(routers, 'name')
    _log_resources_count(len(routers_to_delete), 'router(s)')
    if args.dry_run:
        return
    for id_ in routers_to_delete:
        _log_resource_delete(id_, routers_to_delete[id_], 'router')

        # Unset external gateway and remove ports from router
        log.info("... ... removing external gateway from the router")
        network.update_router(id_, external_gateway_info={})
        ports = network.ports(device_id=id_)
        for p in ports:
            if p.device_owner != 'network:router_ha_interface':
                log.info(f"... ... removing port {p.id} from the router")
                network.remove_interface_from_router(id_, port_id=p.id)

        network.delete_router(id_)


def cleanup_networks():
    nets = network.networks()
    nets_to_delete = _filter_test_resources(nets, 'name')
    _log_resources_count(len(nets_to_delete), 'network(s)')
    if args.dry_run:
        return
    for id_ in nets_to_delete:
        _log_resource_delete(id_, nets_to_delete[id_], 'network')

        ports = network.ports(network_id=id_)
        for p in ports:
            log.info(
                f"... ... removing port {p.id} from the network")
            network.delete_port(p.id)
        subnets = network.subnets(network_id=id_)
        for s in subnets:
            log.info(
                f"... ... removing subnet {s.id} from the network")
            network.delete_subnet(s.id)

        network.delete_network(id_)


def cleanup_load_balancers():
    lbs = load_balancer.load_balancers()
    lbs_to_delete = _filter_test_resources(lbs, 'name')
    _log_resources_count(len(lbs_to_delete), 'load_balancer(s)')
    if args.dry_run:
        return
    for id_ in lbs_to_delete:
        _log_resource_delete(id_, lbs_to_delete[id_], 'load_balancer')
        try:
            load_balancer.delete_load_balancer(id_, cascade=True)
        except openstack.exceptions.ConflictException:
            # force delete the LB in case it is in some PENDING_* state
            log.info(f"... ... force deleting {id_} load balancer")
            load_balancer.delete_load_balancer(id_, cascade=True, force=True)
        except Exception as e:
            log.info(f"... ... could not delete {id_} load balancer: {e}")


def cleanup_floating_ips():
    projects = identity.projects()
    list_projects_to_delete = list(_filter_test_resources(projects, 'name'))
    floating_ips = network.ips()
    fips_to_delete = {}
    for ip in floating_ips:
        # filter only non-associated IPs, only inside target projects
        if (ip.status == 'DOWN') and (ip.fixed_ip_address is None):
            if ip.project_id in list_projects_to_delete:
                fips_to_delete[ip.id] = ip.floating_ip_address
    _log_resources_count(len(fips_to_delete), 'floating ip(s)')
    if args.dry_run:
        return
    for id_ in fips_to_delete:
        _log_resource_delete(id_, fips_to_delete[id_], 'floating ip')
        network.delete_ip(id_)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description='OpenStack test resources cleanup script')
    parser.add_argument(
        '-t', dest='dry_run', action='store_true',
        help='Dry run mode, no cleanup is done')
    parser.add_argument(
        '-P', dest='projects', action='store_true',
        help='Force cleanup of projects')
    parser.add_argument(
        '-S', dest='servers_active', action='store_true',
        help='Set servers to ACTIVE before deletion (reqiured by bare metal)')
    parser.add_argument(
        '-f', dest='stacks_alt', action='store_true',
        help='Use additional mask for stack cleanup')

    args = parser.parse_args()

    if args.dry_run:
        log.info("Running in dry-run mode")
    if args.servers_active:
        log.info("Servers will be set to ACTIVE before cleanup")
    if args.projects:
        log.info("Project cleanup is enabled")
    if args.stacks_alt:
        log.info(
            f"Stacks will be cleaned up using additional '{stack_mask}' mask")

    cleanup_stacks(stacks_alt=args.stacks_alt)
    cleanup_load_balancers()

    if manila_present:
        cleanup_shares()
        cleanup_share_types()
        cleanup_share_networks()

    cleanup_servers()
    cleanup_flavors()
    try:  # Skip if cinder-backup service is not enabled
        cleanup_volume_backups()
    except openstack.exceptions.ResourceNotFound:
        pass
    cleanup_snapshots()
    cleanup_volumes()
    cleanup_volume_groups()
    cleanup_volume_group_types()
    cleanup_volume_types()
    cleanup_images()
    cleanup_keypairs()
    cleanup_users()
    cleanup_roles()
    cleanup_services()
    cleanup_regions()
    cleanup_routers()
    cleanup_networks()
    cleanup_sec_groups()
    if object_store_present:
        cleanup_containers()
    cleanup_floating_ips()

    if args.projects:
        cleanup_projects()

    msg = "Cleanup is FINISHED"
    log.info(f"\n{'=' * len(msg)}\n{msg}")
