import hashlib
import os
import socket
import sys
import base64
import time
from django.db.models import F, Q
from xos.config import Config
from synchronizers.base.syncstep import SyncStep
from synchronizers.base.ansible import run_template_ssh
from core.models import Service, Slice, ControllerSlice, ControllerUser, ModelLink, CoarseTenant, Tenant, ServiceMonitoringAgentInfo
from xos.logger import Logger, logging

logger = Logger(level=logging.INFO)

class SyncInstanceUsingAnsible(SyncStep):
    # All of the following should be defined for classes derived from this
    # base class. Examples below use VSGTenant.

    # provides=[VSGTenant]
    # observes=VSGTenant
    # requested_interval=0
    # template_name = "sync_vcpetenant.yaml"

    def __init__(self, **args):
        SyncStep.__init__(self, **args)

    def skip_ansible_fields(self, o):
        # Return True if the instance processing and get_ansible_fields stuff
        # should be skipped. This hook is primarily for the OnosApp
        # sync step, so it can do its external REST API sync thing.
        return False

    def defer_sync(self, o, reason):
        logger.info("defer object %s due to %s" % (str(o), reason),extra=o.tologdict())
        raise Exception("defer object %s due to %s" % (str(o), reason))

    def get_extra_attributes(self, o):
        # This is a place to include extra attributes that aren't part of the
        # object itself.

        return {}

    def get_instance(self, o):
        # We need to know what instance is associated with the object. Let's
        # assume 'o' has a field called 'instance'. If the field is called
        # something else, or if custom logic is needed, then override this
        # method.

        return o.instance

    def get_external_sync(self, o):
        hostname = getattr(o, "external_hostname", None)
        container = getattr(o, "external_container", None)
        if hostname and container:
            return (hostname, container)
        else:
            return None

    def run_playbook(self, o, fields, template_name=None):
        if not template_name:
            template_name = self.template_name
        tStart = time.time()
        run_template_ssh(template_name, fields)
        logger.info("playbook execution time %d" % int(time.time()-tStart),extra=o.tologdict())

    def pre_sync_hook(self, o, fields):
        pass

    def post_sync_hook(self, o, fields):
        pass

    def sync_fields(self, o, fields):
        self.run_playbook(o, fields)

    def prepare_record(self, o):
        pass

    def get_node(self,o):
        return o.node

    def get_node_key(self, node):
        return "/root/setup/node_key"

    def get_key_name(self, instance):
        if instance.isolation=="vm":
            if (instance.slice) and (instance.slice.service) and (instance.slice.service.private_key_fn):
                key_name = instance.slice.service.private_key_fn
            else:
                raise Exception("Make sure to set private_key_fn in the service")
        elif instance.isolation=="container":
            node = self.get_node(instance)
            key_name = self.get_node_key(node)
        else:
            # container in VM
            key_name = instance.parent.slice.service.private_key_fn

        return key_name

    def get_ansible_fields(self, instance):
        # return all of the fields that tell Ansible how to talk to the context
        # that's setting up the container.

        if (instance.isolation == "vm"):
            # legacy where container was configured by sync_vcpetenant.py

            fields = { "instance_name": instance.name,
                       "hostname": instance.node.name,
                       "instance_id": instance.instance_id,
                       "username": "ubuntu",
                       "ssh_ip": instance.get_ssh_ip(),
                     }

        elif (instance.isolation == "container"):
            # container on bare metal
            node = self.get_node(instance)
            hostname = node.name
            fields = { "hostname": hostname,
                       "baremetal_ssh": True,
                       "instance_name": "rootcontext",
                       "username": "root",
                       "container_name": "%s-%s" % (instance.slice.name, str(instance.id))
                       # ssh_ip is not used for container-on-metal
                     }
        else:
            # container in a VM
            if not instance.parent:
                raise Exception("Container-in-VM has no parent")
            if not instance.parent.instance_id:
                raise Exception("Container-in-VM parent is not yet instantiated")
            if not instance.parent.slice.service:
                raise Exception("Container-in-VM parent has no service")
            if not instance.parent.slice.service.private_key_fn:
                raise Exception("Container-in-VM parent service has no private_key_fn")
            fields = { "hostname": instance.parent.node.name,
                       "instance_name": instance.parent.name,
                       "instance_id": instance.parent.instance_id,
                       "username": "ubuntu",
                       "ssh_ip": instance.parent.get_ssh_ip(),
                       "container_name": "%s-%s" % (instance.slice.name, str(instance.id))
                         }

        key_name = self.get_key_name(instance)
        if not os.path.exists(key_name):
            raise Exception("Node key %s does not exist" % key_name)

        key = file(key_name).read()

        fields["private_key"] = key

        # now the ceilometer stuff

        cslice = ControllerSlice.objects.get(slice=instance.slice)
        if not cslice:
            raise Exception("Controller slice object for %s does not exist" % instance.slice.name)

        cuser = ControllerUser.objects.get(user=instance.creator)
        if not cuser:
            raise Exception("Controller user object for %s does not exist" % instance.creator)

        fields.update({"keystone_tenant_id": cslice.tenant_id,
                       "keystone_user_id": cuser.kuser_id,
                       "rabbit_user": getattr(instance.controller,"rabbit_user", None),
                       "rabbit_password": getattr(instance.controller, "rabbit_password", None),
                       "rabbit_host": getattr(instance.controller, "rabbit_host", None)})

        return fields

    def sync_record(self, o):
        logger.info("sync'ing object %s" % str(o),extra=o.tologdict())

        self.prepare_record(o)

        if self.skip_ansible_fields(o):
            fields = {}
        else:
            if self.get_external_sync(o):
                # sync to some external host

                # UNTESTED

                (hostname, container_name) = self.get_external_sync(o)
                fields = { "hostname": hostname,
                           "baremetal_ssh": True,
                           "instance_name": "rootcontext",
                           "username": "root",
                           "container_name": container_name
                         }
                key_name = self.get_node_key(node)
                if not os.path.exists(key_name):
                    raise Exception("Node key %s does not exist" % key_name)

                key = file(key_name).read()

                fields["private_key"] = key
                # TO DO: Ceilometer stuff
            else:
                instance = self.get_instance(o)
                # sync to an XOS instance
                if not instance:
                    self.defer_sync(o, "waiting on instance")
                    return

                if not instance.instance_name:
                    self.defer_sync(o, "waiting on instance.instance_name")
                    return

                fields = self.get_ansible_fields(instance)

        fields["ansible_tag"] =  o.__class__.__name__ + "_" + str(o.id)

        # If 'o' defines a 'sync_attributes' list, then we'll copy those
        # attributes into the Ansible recipe's field list automatically.
        if hasattr(o, "sync_attributes"):
            for attribute_name in o.sync_attributes:
                fields[attribute_name] = getattr(o, attribute_name)

        fields.update(self.get_extra_attributes(o))

        self.sync_fields(o, fields)

        o.save()

    def delete_record(self, o):
        try:
            controller = o.get_controller()
            controller_register = json.loads(o.node.site_deployment.controller.backend_register)

            if (controller_register.get('disabled',False)):
                raise InnocuousException('Controller %s is disabled'%o.node.site_deployment.controller.name)
        except AttributeError:
            pass

        instance = self.get_instance(o)

        if not instance:
            # the instance is gone. There's nothing left for us to do.
            return

        if isinstance(instance, basestring):
            # sync to some external host

            # XXX - this probably needs more work...

            fields = { "hostname": instance,
                       "instance_id": "ubuntu",     # this is the username to log into
                       "private_key": service.key,
                     }
        else:
            # sync to an XOS instance
            fields = self.get_ansible_fields(instance)

            fields["ansible_tag"] =  o.__class__.__name__ + "_" + str(o.id)

        # If 'o' defines a 'sync_attributes' list, then we'll copy those
        # attributes into the Ansible recipe's field list automatically.
        if hasattr(o, "sync_attributes"):
            for attribute_name in o.sync_attributes:
                fields[attribute_name] = getattr(o, attribute_name)

        fields.update(self.map_delete_inputs(o))

        fields['delete']=True
        res = self.run_playbook(o,fields)
        try:
                self.map_delete_outputs(o,res)
        except AttributeError:
                pass

    #In order to enable the XOS watcher functionality for a synchronizer, define the 'watches' attribute 
    #in the derived class: eg. watches = [ModelLink(CoarseTenant,via='coarsetenant')]
    #This base class implements the notification handler for handling CoarseTenant model notifications
    #If a synchronizer need to watch on multiple objects, the additional handlers need to be implemented
    #in the derived class and override the below handle_watched_object() method to route the notifications
    #accordingly
    def handle_watched_object(self, o):
        logger.info("handle_watched_object is invoked for object %s" % (str(o)),extra=o.tologdict())
        if (type(o) is CoarseTenant):
           self.handle_service_composition_watch_notification(o)
        elif (type(o) is ServiceMonitoringAgentInfo):
           self.handle_service_monitoringagentinfo_watch_notification(o)
        pass

    def handle_service_composition_watch_notification(self, coarse_tenant):
        cls_obj = self.observes
        if (type(cls_obj) is list):
            cls_obj = cls_obj[0]
        logger.info("handle_watched_object observed model %s" % (cls_obj))

        objs = cls_obj.objects.filter(kind=cls_obj.KIND).all()

        for obj in objs:
            self.handle_service_composition_for_object(obj, coarse_tenant)
        pass

    def handle_service_monitoringagentinfo_watch_notification(self, monitoring_agent_info):
        pass

    def handle_service_composition_for_object(self, obj, coarse_tenant):
        try:
           instance = self.get_instance(obj)
           valid_instance = True
        except:
           valid_instance = False

        if not valid_instance:
           logger.warn("handle_watched_object: No valid instance found for object %s" % (str(obj)))
           return

        provider_service = coarse_tenant.provider_service
        subscriber_service = coarse_tenant.subscriber_service

        if isinstance(obj,Service):
            if obj.id == provider_service.id:
                matched_service = provider_service
                other_service = subscriber_service
            elif obj.id == subscriber_service.id:
                matched_service = subscriber_service
                other_service = provider_service
            else:
                logger.info("handle_watched_object: Service object %s does not match with any of composed services" % (str(obj)))
                return
        elif isinstance(obj,Tenant):
            if obj.provider_service.id == provider_service.id:
                matched_service = provider_service
                other_service = subscriber_service
            elif obj.provider_service.id == subscriber_service.id:
                matched_service = subscriber_service
                other_service = provider_service
            else:
                logger.info("handle_watched_object: Tenant object %s does not match with any of composed services" % (str(obj)))
                return
        else:
           logger.warn("handle_watched_object: Model object %s is of neither Service nor Tenant type" % (str(obj)))

        src_networks = matched_service.get_composable_networks()
        target_networks = other_service.get_composable_networks()
        if src_networks and target_networks:
            src_network = src_networks[0] #Only one composable network should present per service
            target_network = target_networks[0]
            src_ip = instance.get_network_ip(src_network.name)
            target_subnet = target_network.controllernetworks.all()[0].subnet
  
            #Run ansible playbook to update the routing table entries in the instance
            fields = self.get_ansible_fields(instance)
            fields["ansible_tag"] =  obj.__class__.__name__ + "_" + str(obj.id) + "_service_composition"
            fields["src_intf_ip"] = src_ip
            fields["target_subnet"] = target_subnet
            #Template file is available under .../synchronizers/shared_templates
            service_composition_template_name = "sync_service_composition.yaml"
            logger.info("handle_watched_object: Updating routing tables in the instance associated with object %s: target_subnet:%s src_ip:%s" % (str(obj), target_subnet, src_ip))
            SyncInstanceUsingAnsible.run_playbook(self, obj, fields, service_composition_template_name)
        else:
           logger.info("handle_watched_object: No intersection of composable networks between composed services %s" % (str(coarse_tenant)))
