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"

# 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
object_store = cloud.object_store
volume = cloud.volume
load_balancer = cloud.load_balancer

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 _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 _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_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()
    cleanup_servers()
    cleanup_flavors()
    cleanup_volume_backups()
    cleanup_snapshots()
    cleanup_volumes()
    cleanup_volume_groups()
    cleanup_volume_group_types()
    cleanup_volume_types()
    cleanup_images()
    cleanup_sec_groups()
    cleanup_keypairs()
    cleanup_users()
    cleanup_roles()
    cleanup_services()
    cleanup_regions()
    cleanup_routers()
    cleanup_networks()
    cleanup_containers()
    cleanup_floating_ips()

    if args.projects:
        cleanup_projects()

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