import multiprocessing as mp
import os
import random
import sys
from typing import Dict, Final, List

import connection as conn
from openstack.exceptions import ResourceFailure


compute = conn.cloud.compute
network = conn.cloud.network
volume = conn.cloud.volume

CLIENTS_COUNT: Final[int] = conn.FIO_CLIENTS_COUNT
CLIENT_NAME_MASK: Final[str] = conn.FIO_CLIENT_NAME_MASK
AA_SERVER_GROUP_NAME: Final[str] = conn.FIO_AA_SERVER_GROUP_NAME
UBUNTU_IMAGE_NAME: Final[str] = conn.UBUNTU_IMAGE_NAME

VOL_NAME_MASK: Final[str] = conn.FIO_VOL_NAME_MASK
VOL_SIZE: Final[int] = conn.FIO_VOL_SIZE
VOL_TYPE: Final[str] = conn.FIO_VOL_TYPE
VOL_MOUNTPOINT: Final[str] = conn.FIO_VOL_MOUNTPOINT

FLAVOR_NAME: Final[str] = conn.FIO_FLAVOR_NAME
FLAVOR_RAM: Final[int] = conn.FIO_FLAVOR_RAM
FLAVOR_CPUS: Final[int] = conn.FIO_FLAVOR_CPUS
FLAVOR_DISK: Final[int] = conn.FIO_FLAVOR_DISK

NET_NAME: Final[str] = conn.FIO_NET_NAME
ROUTER_NAME: Final[str] = conn.FIO_ROUTER_NAME
FLOATING_NET_NAME = conn.FLOATING_NET_NAME
SUBNET_NAME = conn.FIO_SUBNET_NAME
SUBNET_RANGE = conn.FIO_SUBNET_RANGE
MTU_SIZE = conn.MTU_SIZE
NET_IPV4 = conn.NET_IPV4

KEYPAIR_NAME: Final[str] = conn.FIO_KEYPAIR_NAME
PRIVATE_KEYPAIR_FILE: Final[str] = conn.PRIVATE_KEYPAIR_FILE

SG_NAME: Final[str] = conn.FIO_SG_NAME
HV_SUFFIX: Final[str] = conn.HV_SUFFIX
CLOUD_NAME: Final[str] = conn.CLOUD_NAME
CONCURRENCY: Final[int] = conn.CONCURRENCY

NODES: Final[List[str]] = []
SKIP_NODES: Final[List[str]] = []


SG_ALLOW_ALL_RULES: Final[List[Dict]] = [
    {
        'remote_ip_prefix': '0.0.0.0/0',
        'protocol': 'icmp',
        'port_range_max': None,
        'port_range_min': None,
        'ethertype': 'IPv4'
    },
    {
        'remote_ip_prefix': '0.0.0.0/0',
        'protocol': 'tcp',
        'port_range_max': 65535,
        'port_range_min': 1,
        'ethertype': 'IPv4'
    },
    {
        'remote_ip_prefix': '0.0.0.0/0',
        'protocol': 'udp',
        'port_range_max': 65535,
        'port_range_min': 1,
        'ethertype': 'IPv4'
    }
]


def create_fio_client(
        image_id: str, flavor_id: str, networks: List,
        key_name: str, security_groups: List, server_group_id: str
) -> None:
    rand_name = str(random.randint(1, 0x7fffffff))
    vm_name = f"{CLIENT_NAME_MASK}-{rand_name}"

    vm = compute.create_server(
        name=vm_name,
        image_id=image_id,
        flavor_id=flavor_id,
        networks=networks,
        key_name=key_name,
        security_groups=security_groups,
        scheduler_hints={'group': server_group_id})
    try:
        vm = compute.wait_for_server(vm, wait=180)
        print(f"Fio client '{vm.name}' is created on '{vm.compute_host}' node")
    # Stop and exit if any of the servers creation failed (for any reason)
    except ResourceFailure as e:
        print(
            f"Fio client '{vm.name}' creation failed with '{e.message}'"
            " error.")
        conn.delete_server(vm)
        sys.exit(0)

    # Create a volume of the given type
    vol_name = f"{VOL_NAME_MASK}-{rand_name}"
    vol = volume.create_volume(
        name=vol_name, size=VOL_SIZE, volume_type=VOL_TYPE)
    try:
        vol = volume.wait_for_status(vol, status='available')
        print(f"Volume '{vol.name}' is created")
    # Delete a volume if its creation failed and switch to next
    # fio client VM
    except ResourceFailure as e:
        print(
            f"Volume '{vol.name}' creation failed with '{e.message}' "
            "error.")
        conn.delete_volume(vol)

    # Attach the volume to the fio client
    compute.create_volume_attachment(vm,  volume_id=vol.id)
    try:
        vol = volume.wait_for_status(vol, status='in-use')
        print(f"Volume '{vol.name}' is attached to '{vm.name}' fio client")
    # Delete a volume if attachment failed and switch to next
    # fio client VM
    except ResourceFailure as e:
        print(
            f"Volume '{vol.name}' attachment failed with '{e.message}' "
            "error.")
        conn.delete_volume(vol)


if __name__ == "__main__":
    # Check if any fio servers already exist on the cloud
    servers = compute.servers(details=False, name=CLIENT_NAME_MASK)
    srvrs = list(servers)
    if srvrs:
        names = [s.name for s in srvrs]
        print("The following servers already exist in the cloud:")
        print(*names, sep='\n')
        sys.exit(0)

    # Create fio sg if needed
    project_id = conn.cloud.current_project_id
    sg = network.find_security_group(SG_NAME, project_id=project_id)
    if not sg:
        sg = network.create_security_group(name=SG_NAME)
        # Add 'allow-all' kind of rules to the security group
        pairs = [
            (r, d) for r in SG_ALLOW_ALL_RULES for d in ('ingress', 'egress')]
        for (rule, direction) in pairs:
            network.create_security_group_rule(
                security_group_id=sg.id, direction=direction, **rule)

    # Create fio keypair if needed
    kp = compute.find_keypair(KEYPAIR_NAME)
    if not kp:
        kp = compute.create_keypair(name=KEYPAIR_NAME)
        with open(PRIVATE_KEYPAIR_FILE, 'w') as f:
            f.write("{}".format(kp.private_key))

        os.chmod(PRIVATE_KEYPAIR_FILE, 0o400)

    # Create fio flavor if needed
    flavor = compute.find_flavor(FLAVOR_NAME)
    if not flavor:
        flavor = compute.create_flavor(
            name=FLAVOR_NAME, ram=FLAVOR_RAM,
            vcpus=FLAVOR_CPUS, disk=FLAVOR_DISK)

    # Set image property to enable virtio-net multique in created servers
    img = compute.find_image(UBUNTU_IMAGE_NAME)
    compute.set_image_metadata(img.id, hw_vif_multiqueue_enabled='true')

    # Create fio router if needed
    fip_net = network.find_network(FLOATING_NET_NAME)
    router = network.find_router(ROUTER_NAME)
    if not router:
        router = network.create_router(
            name=ROUTER_NAME, external_gateway_info={'network_id': fip_net.id})

    # Create fio net/subnet if needed
    fio_net = network.find_network(NET_NAME)
    if not fio_net:
        fio_net = network.create_network(
            name=NET_NAME,
            availability_zone_hints=['nova'],
            # mtu=MTU_SIZE,
            shared=False,
            port_security_enabled=True)
        fio_subnet = network.create_subnet(
            name=SUBNET_NAME,
            network_id=fio_net.id,
            cidr=SUBNET_RANGE,
            ip_version=NET_IPV4)
        # Add fio net to fio router
        fio_net_port = network.add_interface_to_router(
            router.id, subnet_id=fio_subnet.id)

    # Create fio server group with anti-affinity scheduling policy
    server_group = conn.find_server_group(AA_SERVER_GROUP_NAME)
    if not server_group:
        server_group = compute.create_server_group(
            name=AA_SERVER_GROUP_NAME, policies=['soft-anti-affinity'])

    vm_kwargs = dict(
        image_id=img.id,
        flavor_id=flavor.id,
        networks=[{'uuid': fio_net.id}],
        key_name=KEYPAIR_NAME,
        security_groups=[{'name': SG_NAME}],
        server_group_id=server_group.id)

    # Create fio client VMs in parallel in batches of CONCURRENCY size
    with mp.Pool(processes=CONCURRENCY) as pool:
        results = [
            pool.apply_async(create_fio_client, kwds=vm_kwargs)
            for _ in range(CLIENTS_COUNT)]
        # Wait for batch of fio client VMs to be created
        _ = [r.get() for r in results]
