import base64
import concurrent.futures as cex
import os
import random
import sys
from typing import Dict, Final, List

import connection as conn
from openstack.exceptions import ResourceFailure
from oslo_utils import encodeutils


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,
        user_data: str
) -> None:
    rand_name = str(random.randint(1, 0x7fffffff))
    vm_name = f"{CLIENT_NAME_MASK}-{rand_name}"

    kwargs = {}
    if user_data:
        kwargs['user_data'] = user_data
    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},
        **kwargs)
    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=vol)
    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 = compute.find_server_group(
        AA_SERVER_GROUP_NAME, all_projects=True)
    if not server_group:
        server_group = compute.create_server_group(
            name=AA_SERVER_GROUP_NAME, policies=['soft-anti-affinity'])

    # Prepare user data for fio client VMs
    udata = None
    with open('user_data.sh', 'r') as script:
        f = encodeutils.safe_encode(script.read().encode('utf-8'))
        udata = base64.b64encode(f).decode('utf-8')

    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,
        user_data=udata)

    # Create fio client VMs in parallel in batches of CONCURRENCY size
    with cex.ThreadPoolExecutor(max_workers=CONCURRENCY) as executor:
        futures = [executor.submit(create_fio_client, **vm_kwargs) for _ in range(CLIENTS_COUNT)]
        # Wait for batch of fio client VMs to be created
        _ = [future.result() for future in futures]
