# vi: ts=4 expandtab
#
# Copyright (C) 2017 VMware Inc.
#
# Author: Anish Swaminathan <anishs@vmware.com>
#
import os
import base64

from cloudinit import log as logging
from cloudinit import sources
from cloudinit import util

from distutils.spawn import find_executable

LOG = logging.getLogger(__name__)

class DataSourceVmxGuestinfo(sources.DataSource):
    def __init__(self, sys_cfg, distro, paths, ud_proc=None):
        sources.DataSource.__init__(self, sys_cfg, distro, paths, ud_proc)
        self.metadata = {}
        self.userdata_raw = ''
        self.vmtoolsd = find_executable("vmtoolsd")
        if not self.vmtoolsd:
            LOG.error("Failed to find vmtoolsd")

    def get_data(self):
        if not self.vmtoolsd:
            LOG.error("vmtoolsd is required to fetch guestinfo value")
            return False
        hostname = self._get_guestinfo_value('hostname')
        if hostname:
            self.distro.set_hostname(hostname)
        ud = self._get_guestinfo_value('userdata')
        if ud:
            LOG.debug("Decoding base64 format guestinfo.userdata")
            self.userdata_raw = base64.b64decode(ud)
        found = True
        dev_index = 0
        network_settings = ''
        while found:
            key_begin = 'interface.' + str(dev_index)
            key_iname = key_begin + '.name'
            interface_name = self._get_guestinfo_value(key_iname)
            if interface_name:
                network_settings += 'auto ' + interface_name + '\n'
                network_settings += 'iface ' + interface_name
                key_proto = key_begin + '.dhcp'
                dhcp_enabled = self._get_guestinfo_value(key_proto)
                key_address = key_begin + '.address'
                address = self._get_guestinfo_value(key_address)
                bootproto = 'dhcp'
                if dhcp_enabled:
                    if dhcp_enabled == 'yes':
                        network_settings += ' dhcp\n'
                    elif dhcp_enabled == 'no':
                        network_settings += ' static\n'
                        bootproto = 'static'
                    else:
                        LOG.warning("Invalid value for yes/no parameter for %s, setting to dhcp", key_proto)
                elif address:
                    bootproto = 'static'
                    dhcp_enabled == 'no'
                    network_settings += ' static\n'
                else:
                    dhcp_enabled == 'yes'
                    network_settings += ' dhcp\n'
                    LOG.debug("Setting network bootproto to dhcp by default")
                key_mac = key_begin + '.mac'
                mac = self._get_guestinfo_value(key_mac)
                if address:
                    network_settings += 'address ' + address + '\n'
                if mac:
                    network_settings += 'hwaddress ' + mac + '\n'
                key_netmask = key_begin + '.netmask'
                netmask = self._get_guestinfo_value(key_netmask)
                if netmask:
                    network_settings += 'netmask ' + netmask + '\n'
                key_dnsserver = 'dns.servers'
                dnsserver = self._get_guestinfo_value(key_dnsserver)
                if dnsserver:
                    network_settings += 'dns-nameservers '
                    dnsserver = dnsserver.split(',')
                    for d in dnsserver:
                        network_settings += d + ' '
                    network_settings += '\n'
                key_dnsdomain = 'dns.domains'
                dnsdomain = self._get_guestinfo_value(key_dnsdomain)
                if dnsdomain:
                    network_settings += 'dns-search '
                    dnsdomain = dnsdomain.split(',')
                    for d in dnsdomain:
                        network_settings += d + ' '
                    network_settings += '\n'
                route_index = 0
                default_destination_set = False
                while True:
                    key_route = key_begin + '.route.' + str(route_index)
                    route = self._get_guestinfo_value(key_route)
                    if route:
                        network_settings += "routes.%s " % (route_index)
                        route = route.split(',')
                        if len(route) > 2:
                            LOG.debug("Route information for %s route in %s device incorrect - ", 
                                                "expected 2 values", route_index, dev_index)
                            continue
                        elif len(route) == 2:
                            network_settings += route[0] + ' ' + route[1] + '\n'# Gateway Destination
                        else: #length = 1
                            if not default_destination_set:
                                network_settings += route[0] + ' 0.0.0.0/0' + '\n'
                                default_destination_set = True
                            else:
                                LOG.debug("Default destination set previously, not setting route %s", route_index) 
                    else:
                        break
                    route_index += 1
            else:
                found = False
            dev_index += 1
        self.distro.apply_network(network_settings, False)
        return True

    def _get_guestinfo_value(self, key):
        LOG.debug("Getting guestinfo value for key %s", key)
        value = ''
        try:
            (value, _err) = util.subp([self.vmtoolsd, "--cmd", "info-get guestinfo." + key])
            if _err:
                LOG.error("Failed to get guestinfo value for key %s", key)
        except util.ProcessExecutionError as error:
            util.logexc(LOG,"Failed to get guestinfo value for key %s: %s", key, error)
        except Exception:
            util.logexc(LOG,"Unexpected error while trying to get guestinfo value for key %s", key)
        return value.rstrip()

    def get_instance_id(self):
        with open('/sys/class/dmi/id/product_uuid', 'r') as id_file:
            return str(id_file.read()).rstrip()

def get_datasource_list(depends):
    """
    Return a list of data sources that match this set of dependencies
    """
    return [DataSourceVmxGuestinfo]