
# Copyright 2017-present Open Networking Foundation
#
# 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 os
import sys
import time
from synchronizers.new_base.syncstep import SyncStep, DeferredException
from synchronizers.new_base.ansible_helper import run_template_ssh
from synchronizers.new_base.modelaccessor import ExampleServiceInstance
from xosconfig import Config
from multistructlog import create_logger

log = create_logger(Config().get('logging'))

# TODO(smbaker): Move this to the core
class SyncServiceInstanceWithComputeUsingAnsible(SyncStep):
    def __init__(self, *args, **kwargs):
        SyncStep.__init__(self, *args, **kwargs)

    def defer_sync(self, o, reason):
        log.info("defer object", object = str(o), reason = reason, **o.tologdict())
        raise DeferredException("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 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, object=o)
        log.info("playbook execution time", time=int(time.time() - tStart), **o.tologdict())

    def get_ssh_ip(self, instance):
        for port in instance.ports.all():
            if port.network.template and port.network.template.vtn_kind == "MANAGEMENT_LOCAL":
                return port.ip

        for port in instance.ports.all():
            if port.network.template and port.network.template.vtn_kind == "MANAGEMENT_HOST":
                return port.ip

        return None

    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.

        # Cast to the leaf_model. For OpenStackServiceInstance, this will allow us access to fields like "node"
        instance = instance.leaf_model

        node = getattr(instance, "node")
        if not node:
            raise Exception("Instance has no node for instance %s" % str(instance))

        if not instance.slice:
            raise Exception("Instance has no slice for instance %s" % str(instance))

        if not instance.slice.service:
            raise Exception("Instance's slice has no service for instance %s" % str(instance))

        if not instance.slice.service.private_key_fn:
            raise Exception("Instance's slice's service has no private_key_fn for instance %s" % str(instance))

        key_name = instance.slice.service.private_key_fn
        if not os.path.exists(key_name):
            raise Exception("Node key %s does not exist for instance %s" % (key_name, str(instance)))

        ssh_ip = self.get_ssh_ip(instance)
        if not ssh_ip:
            raise Exception("Unable to determine ssh ip for instance %s" % str(instance))

        key = file(key_name).read()

        fields = {"instance_name": instance.name,
                  "hostname": node.name,
                  "username": "ubuntu",
                  "ssh_ip": ssh_ip,
                  "private_key": key,
                  "instance_id": "none", # is not used for proxy-ssh ansible connections
                  }

        return fields

    def sync_record(self, o):
        log.info("sync'ing object", object=str(o), **o.tologdict())

        compute_service_instance = o.compute_instance
        if not compute_service_instance:
            self.defer_sync(o, "waiting on instance")
            return

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

        fields = self.get_ansible_fields(compute_service_instance)

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

        fields.update(self.get_extra_attributes(o))

        self.run_playbook(o, fields)

        o.save()

class SyncExampleServiceInstance(SyncServiceInstanceWithComputeUsingAnsible):

    provides = [ExampleServiceInstance]

    observes = ExampleServiceInstance

    requested_interval = 0

    template_name = "exampleserviceinstance_playbook.yaml"

    def __init__(self, *args, **kwargs):
        super(SyncExampleServiceInstance, self).__init__(*args, **kwargs)

    # Gets the attributes that are used by the Ansible template but are not
    # part of the set of default attributes.
    def get_extra_attributes(self, o):
        fields = {}
        fields['tenant_message'] = o.tenant_message
        exampleservice = o.owner.leaf_model
        fields['service_message'] = exampleservice.service_message

        if o.foreground_color:
            fields["foreground_color"] = o.foreground_color.html_code

        if o.background_color:
            fields["background_color"] = o.background_color.html_code

        images = []
        for image in o.embedded_images.all():
            images.append({"name": image.name,
                           "url": image.url})
        fields["images"] = images

        return fields

    def delete_record(self, port):
        # Nothing needs to be done to delete an exampleservice; it goes away
        # when the instance holding the exampleservice is deleted.
        pass

