#!/usr/bin/env python3

# 
#   Copyright 2016-2017 RIFT.IO 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.
#


import argparse
import itertools
import logging
import os
import sys
import tempfile
import uuid
import yaml

import gi
gi.require_version('RwYang', '1.0')
gi.require_version('RwProjectVnfdYang', '1.0')
gi.require_version('RwProjectNsdYang', '1.0')
gi.require_version('RwProjectYang', '1.0')
from gi.repository import (
    RwYang,
    RwProjectVnfdYang as RwVnfdYang,
    RwProjectNsdYang as RwNsdYang,
    RwProjectYang,
    )

logging.basicConfig(level=logging.WARNING)
logger = logging.getLogger("openmano2rift.py")


class UnknownVNFError(Exception):
    pass


class DescriptorFileWriter(object):
    def __init__(self, module_list, output_dir, output_format):
        self._model = RwYang.Model.create_libncx()
        for module in module_list:
            self._model.load_module(module)

        self._output_dir = output_dir
        self._output_format = output_format

    def _write_file(self, file_name, output):
        file_path = os.path.join(self._output_dir, file_name)
        dir_path = os.path.dirname(file_path)
        if not os.path.exists(dir_path):
            os.makedirs(dir_path)

        with open(file_path, "w") as hdl:
            hdl.write(output)

        logger.info("Wrote descriptor to %s", file_path)

    def _write_json(self, descriptor, subdir):
        self._write_file(
            '%s.json' % os.path.join(descriptor.name, subdir, descriptor.name),
            descriptor.descriptor.to_json(self._model)
            )

    def _write_xml(self, descriptor, subdir):
        self._write_file(
            '%s.xml' % os.path.join(descriptor.name, subdir, descriptor.name),
            descriptor.descriptor.to_xml_v2(self._model, pretty_print=True)
            )

    def _write_yaml(self, descriptor, subdir):
        self._write_file(
            '%s.yaml' % os.path.join(descriptor.name, subdir, descriptor.name),
            yaml.dump(descriptor.descriptor.as_dict()),
            )

    def write_descriptor(self, descriptor, subdir=""):
        if self._output_format == 'json':
            self._write_json(descriptor, subdir=subdir)

        elif self._output_format == 'xml':
            self._write_xml(descriptor, subdir=subdir)

        elif self._output_format == 'yaml':
            self._write_yaml(descriptor, subdir=subdir)


class RiftManoDescriptor(object):
    def __init__(self, openmano=None):
        self.openmano = openmano
        self.descriptor = None


class RiftNS(RiftManoDescriptor):
    def __init__(self, openmano=None):
        super().__init__(openmano)
        self.nsd_catalog = None
        self.nsd = None
        self.name = None

    def get_vnfd_id(self, vnf_list, vnf_name):
        for vnf in vnf_list:
            if vnf.name == vnf_name:
                return vnf.vnfd.id

        # Didn't find the vnf just return the vnf_name
        return vnf_name

    def openmano2rift(self, vnf_list):
        self.descriptor = RwNsdYang.YangData_RwProject_Project_NsdCatalog()
        openmano_nsd = self.openmano.dictionary
        self.name = openmano_nsd['name']
        nsd = self.descriptor.nsd.add()
        nsd.id = str(uuid.uuid1())
        nsd.name = self.name
        nsd.short_name = self.name
        nsd.description = openmano_nsd['description']

        nodes = openmano_nsd['topology']['nodes']
        connections = openmano_nsd['topology']['connections']

        def create_consituent_vnfds():
            vnf_member_index_dict = {}

            vnfd_idx_gen = itertools.count(1)
            for key in nodes:
                node = nodes[key]
                if node['type'] != 'VNF':
                    continue

                vnfd_idx = next(vnfd_idx_gen)
                constituent_vnfd = nsd.constituent_vnfd.add()
                constituent_vnfd.member_vnf_index = vnfd_idx
                constituent_vnfd.vnfd_id_ref = self.get_vnfd_id(vnf_list, node['VNF model'])
                vnf_member_index_dict[key] = vnfd_idx

            return vnf_member_index_dict

        def create_connections(vnf_member_index_dict):
            keys = connections.keys()
            for key in keys:
                # TODO: Need clarification from TEF
                # skip the mgmtnet in OpenMANO descriptor
                if key == 'mgmtnet':
                    continue
                conn = connections[key]
                vld = nsd.vld.add()
                vld.from_dict(dict(
                    id=str(uuid.uuid1()),
                    name=key,
                    short_name=key,
                    type_yang='ELAN',
                    ))

                nodes = conn['nodes']
                for node, node_keys in [(node, node.keys()) for node in nodes]:
                    for node_key in node_keys:
                        topo_node = openmano_nsd['topology']['nodes'][node_key]
                        if topo_node['type'] == 'VNF':
                            cpref = vld.vnfd_connection_point_ref.add()
                            cpref.from_dict(dict(
                                member_vnf_index_ref=vnf_member_index_dict[node_key],
                                vnfd_id_ref=self.get_vnfd_id(vnf_list, topo_node['VNF model']),
                                #vnfd_id_ref=topo_node['VNF model'],
                                vnfd_connection_point_ref=node[node_key],
                                ))
                            if key != 'control-net':
                                vld.provider_network.physical_network = 'physnet_sriov'
                                vld.provider_network.overlay_type = 'VLAN'

        vnf_member_index_dict = create_consituent_vnfds()
        create_connections(vnf_member_index_dict)


class RiftVnfd(RiftManoDescriptor):
    def __init__(self, openmano=None):
        super().__init__(openmano)
        self.vnfd_catalog = None
        self.vnfd = None

    def find_external_connection(self, vdu_name, if_name):
        """
        Find if the vdu interface has an external connection.
        """
        openmano_vnfd = self.openmano.dictionary['vnf']
        if 'external-connections' not in openmano_vnfd:
            return None

        ext_conn_list = openmano_vnfd['external-connections']
        for ext_conn in ext_conn_list:
            if ((ext_conn['VNFC'] == vdu_name) and
                    (ext_conn['local_iface_name'] == if_name)):
                return ext_conn

        return None

    def openmano2rift(self):
        self.descriptor = RwVnfdYang.YangData_RwProject_Project_VnfdCatalog()
        vnfd = self.descriptor.vnfd.add()
        self.vnfd = vnfd
        vnfd.id = str(uuid.uuid1())

        openmano_vnfd = self.openmano.dictionary['vnf']
        self.name = openmano_vnfd['name']
        vnfd.name = self.name
        if "description" in openmano_vnfd:
            vnfd.description = openmano_vnfd['description']

        # Parse and add all the external connection points
        if 'external-connections' in openmano_vnfd:
            ext_conn_list = openmano_vnfd['external-connections']

            for ext_conn in ext_conn_list:
                # TODO: Fix this
                if ext_conn['name'] == 'eth0':
                    continue
                conn_point = vnfd.connection_point.add()
                conn_point.name = ext_conn['name']
                conn_point.type_yang = 'VPORT'

        # TODO: Need a concrete example of how openmano descriptor
        # uses internal connections.
        if 'internal-connections' in openmano_vnfd:
            int_conn_list = openmano_vnfd['internal-connections']

        def add_external_interfaces(vdu, numa):
            if 'interfaces' not in numa:
                return

            numa_if_list = numa['interfaces']
            for numa_if in numa_if_list:
                ext_conn = self.find_external_connection(vdu.name, numa_if['name'])
                if not ext_conn:
                    continue

                ext_iface = vdu.external_interface.add()
                ext_iface.name = numa_if['name']
                ext_iface.vnfd_connection_point_ref = ext_conn['name']
                ext_iface.virtual_interface.vpci = numa_if['vpci']
                if numa_if['dedicated'] == 'no':
                    ext_iface.virtual_interface.type_yang = 'SR_IOV'
                else:
                    ext_iface.virtual_interface.type_yang = 'PCI_PASSTHROUGH'

        vnfc_list = openmano_vnfd['VNFC']
        for vnfc in vnfc_list:
            vdu = vnfd.vdu.add()
            vdu_dict = dict(
                id=str(uuid.uuid1()),
                name=vnfc['name'],
                image=vnfc['VNFC image'],
                vm_flavor={"storage_gb": vnfc["disk"] if "disk" in vnfc else 20},
                )
            if "description" in vnfc:
                vdu_dict["description"] = vnfc['description']

            vdu.from_dict(vdu_dict)

            vnfd.mgmt_interface.vdu_id = vdu.id

            numa_list = vnfc['numas']
            memory = 0
            vcpu_count = 0
            numa_node_cnt = 0

            for numa in numa_list:
                node = vdu.guest_epa.numa_node_policy.node.add()
                node.id = numa_node_cnt
                # node.memory_mb = int(numa['memory']) * 1024
                numa_node_cnt += 1

                memory = memory + node.memory_mb
                # Need a better explanation of "cores", "paired-threads", "threads"
                # in openmano descriptor. Particularly how they map to cpu and
                # thread pinning policies
                if 'paired-threads' in numa:
                    vcpu_count = vcpu_count + int(numa['paired-threads']) * 2

                if 'cores' in numa:
                    vcpu_count = vcpu_count + int(numa['cores'])

                add_external_interfaces(vdu, numa)


            # vdu.vm_flavor.memory_mb = memory
            vdu.vm_flavor.memory_mb = 12 * 1024
            vdu.vm_flavor.vcpu_count = vcpu_count
            vdu.guest_epa.numa_node_policy.node_cnt = numa_node_cnt
            vdu.guest_epa.numa_node_policy.mem_policy = 'STRICT'
            vdu.guest_epa.mempage_size = 'LARGE'
            vdu.guest_epa.cpu_pinning_policy = 'DEDICATED'
            vdu.guest_epa.cpu_thread_pinning_policy = 'PREFER'

            # TODO: Enable hypervisor epa
            # vdu.hypervisor_epa.version = vnfc['hypervisor']['version']
            # if vnfc['hypervisor']['type'] == 'QEMU-kvm':
            #     vdu.hypervisor_epa.type_yang = 'REQUIRE_KVM'
            # else:
            #     vdu.hypervisor_epa.type_yang = 'PREFER_KVM'

            # TODO: Enable host epa
            # vdu.host_epa.cpu_feature = vnfc['processor']['features']

            # Parse the bridge interfaces
            if 'bridge-ifaces' in vnfc:
                bridge_ifaces = vnfc['bridge-ifaces']


                for bridge_iface in bridge_ifaces:
                    # TODO: Fix this
                    if bridge_iface['name'] == 'eth0':
                        continue

                    ext_conn = self.find_external_connection(vdu.name,
                                                             bridge_iface['name'])
                    if ext_conn:
                        ext_iface = vdu.external_interface.add()
                        ext_iface.name = bridge_iface['name']
                        ext_iface.vnfd_connection_point_ref = ext_conn['name']
                        if 'vpci' in bridge_iface:
                            ext_iface.virtual_interface.vpci = bridge_iface['vpci']
                        ext_iface.virtual_interface.type_yang = 'VIRTIO'

            # set vpci information for the 'default' network
            # TODO: This needs to be inferred gtom bridge ifaces, 
            # need input from TEF
            vdu.mgmt_vpci = "0000:00:0a.0"


class OpenManoDescriptor(object):
    def __init__(self, yaml_file_hdl):
        self.dictionary = yaml.load(yaml_file_hdl)

    @property
    def type(self):
        """ The descriptor type (ns or vnf)"""
        if 'vnf' in self.dictionary:
            return "vnf"
        else:
            return "ns"

    def dump(self):
        """ Dump the Descriptor out to stdout """
        print(yaml.dump(self.dictionary))


def is_writable_directory(dir_path):
    """ Returns True if dir_path is writable, False otherwise

    Arguments:
        dir_path - A directory path
    """
    if not os.path.exists(dir_path):
        raise ValueError("Directory does not exist: %s", dir_path)

    try:
        testfile = tempfile.TemporaryFile(dir=dir_path)
        testfile.close()
    except OSError:
        return False

    return True


def create_vnfs_from_yaml_files(yaml_file_hdls):
    """ Create a list of RiftVnfd instances from yaml file handles

    Arguments:
        yaml_file_hdls - OpenMano Yaml file handles

    Returns:
        A list of RiftVnfd instances
    """
    vnf_list = []
    for yaml_file_hdl in yaml_file_hdls:
        openmano = OpenManoDescriptor(yaml_file_hdl)
        yaml_file_hdl.seek(0)

        if openmano.type != "vnf":
            continue

        vnf = RiftVnfd(openmano)
        vnf.openmano2rift()
        vnf_list.append(vnf)

    return vnf_list


def create_ns_from_yaml_files(yaml_file_hdls, vnf_list):
    """ Create a list of RiftNS instances from yaml file handles

    Arguments:
        yaml_file_hdls - OpenMano Yaml file handles
        vnf_list - list of RiftVnfd

    Returns:
        A list of RiftNS instances
    """
    ns_list = []
    for yaml_file_hdl in yaml_file_hdls:
        openmano = OpenManoDescriptor(yaml_file_hdl)
        if openmano.type != "ns":
            continue

        net_svc = RiftNS(openmano)
        net_svc.openmano2rift(vnf_list)
        ns_list.append(net_svc)

    return ns_list


def parse_args(argv=sys.argv[1:]):
    """ Parse the command line arguments

    Arguments:
        arv - The list of arguments to parse

    Returns:
        Argparse Namespace instance

    """
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '-o', '--outdir',
        default='.',
        help="Directory to output converted descriptors",
        )

    parser.add_argument(
        '-f', '--format',
        choices=['yaml', 'xml', 'json'],
        default='xml',
        help="Descriptor output format",
        )

    parser.add_argument(
        'yaml_file_hdls',
        metavar="yaml_file",
        nargs="+",
        type=argparse.FileType('r'),
        help="OpenMano YAML Descriptor File",
        )

    args = parser.parse_args(argv)

    if not os.path.exists(args.outdir):
        os.makedirs(args.outdir)

    if not is_writable_directory(args.outdir):
        logging.error("Directory %s is not writable", args.outdir)
        sys.exit(1)

    return args


def main(argv=sys.argv[1:]):
    args = parse_args(argv)

    vnf_list = create_vnfs_from_yaml_files(args.yaml_file_hdls)
    ns_list = create_ns_from_yaml_files(args.yaml_file_hdls, vnf_list)

    # TODO (Philip): Relook at the model generation
    writer = DescriptorFileWriter(
        module_list=['rw-project', 'project-nsd', 'rw-project-nsd', 'project-vnfd', 'rw-project-vnfd'],
        output_dir=args.outdir,
        output_format=args.format,
        )

    for nw_svc in ns_list:
        writer.write_descriptor(nw_svc, subdir="nsd")

    for vnf in vnf_list:
        writer.write_descriptor(vnf, subdir="vnfd")


if __name__ == "__main__":
    main()

