from django.db import models
from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, Subscriber
from core.models.plcorebase import StrippedCharField
import os
from django.db import models, transaction
from django.forms.models import model_to_dict
from django.db.models import Q
from operator import itemgetter, attrgetter, methodcaller
import traceback
from xos.exceptions import *
from core.models import SlicePrivilege, SitePrivilege
from sets import Set
from urlparse import urlparse

CEILOMETER_KIND = "ceilometer"

class CeilometerService(Service):
    KIND = CEILOMETER_KIND
    LOOK_FOR_IMAGES=[ "ceilometer-service-trusty-server-multi-nic",
                    ]

    class Meta:
        app_label = "monitoring"
        verbose_name = "Ceilometer Service"
        proxy = True

    def get_instance(self):
        for slice in self.slices.all():
             for instance in slice.instances.all():
                 if instance.image.name in self.LOOK_FOR_IMAGES:
                     return instance
        return None

    @property
    def addresses(self):
        if (not self.id) or (not self.get_instance()):
            return {}

        addresses = {}
        for ns in self.get_instance().ports.all():
            if "private" in ns.network.name.lower():
                addresses["private"] = (ns.ip, ns.mac)
            elif ("nat" in ns.network.name.lower()) or ("management" in ns.network.name.lower()):
                addresses["nat"] = (ns.ip, ns.mac)
            #TODO: Do we need this client_access_network. Revisit in VTN context
            #elif "ceilometer_client_access" in ns.network.labels.lower():
            #    addresses["ceilometer"] = (ns.ip, ns.mac)
        return addresses

    @property
    def nat_ip(self):
        return self.addresses.get("nat", (None, None))[0]

    @property
    def nat_mac(self):
        return self.addresses.get("nat", (None, None))[1]

    @property
    def private_ip(self):
        return self.addresses.get("private", (None, None))[0]

    @property
    def private_mac(self):
        return self.addresses.get("private", (None, None))[1]

    def get_controller(self):
        if not self.slices.count:
            raise XOSConfigurationError("The service has no slices")
        cslice = self.slices.all()[0].controllerslices.all()[0]
        controller = cslice.controller
        if not controller:
            raise XOSConfigurationError("The service slice has no controller")
        return controller

    @property
    def ceilometer_pub_sub_url(self):
        if not self.get_instance():
            return self.get_attribute("ceilometer_pub_sub_url", None)
        if not self.private_ip:
            return None
        return "http://" + self.private_ip + ":4455/"

    @ceilometer_pub_sub_url.setter
    def ceilometer_pub_sub_url(self, value):
        self.set_attribute("ceilometer_pub_sub_url", value)

    @property
    def ceilometer_auth_url(self):
        #FIXME: Crude way to determine if monitoring service is getting deployed with its own ceilometer+keystone 
        if not self.get_instance():
            return self.get_controller().auth_url
        if not self.private_ip:
            return None
        return "http://" + self.private_ip + ":5000/v2.0"

    @property
    def ceilometer_admin_user(self):
        if not self.get_instance():
            return self.get_controller().admin_user
        return 'admin'

    @property
    def ceilometer_admin_password(self):
        if not self.get_instance():
            return self.get_controller().admin_password
        return 'password'

    @property
    def ceilometer_admin_tenant(self):
        if not self.get_instance():
            return self.get_controller().admin_tenant
        return 'admin'

class MonitoringChannel(TenantWithContainer):   # aka 'CeilometerTenant'
    class Meta:
        proxy = True

    KIND = CEILOMETER_KIND
    LOOK_FOR_IMAGES=[ #"trusty-server-multi-nic-docker", # CloudLab
                      "ceilometer-trusty-server-multi-nic",
                      #"trusty-server-multi-nic",
                    ]


    sync_attributes = ("private_ip", "private_mac",
                       "ceilometer_ip", "ceilometer_mac",
                       "nat_ip", "nat_mac", "ceilometer_port",)

    default_attributes = {}
    def __init__(self, *args, **kwargs):
        ceilometer_services = CeilometerService.get_service_objects().all()
        if ceilometer_services:
            self._meta.get_field("provider_service").default = ceilometer_services[0].id
        super(MonitoringChannel, self).__init__(*args, **kwargs)
        self.set_attribute("use_same_instance_for_multiple_tenants", True)

    def can_update(self, user):
        #Allow creation of this model instances for non-admin users also
        return True

    def save(self, *args, **kwargs):
        if not self.creator:
            if not getattr(self, "caller", None):
                # caller must be set when creating a monitoring channel since it creates a slice
                raise XOSProgrammingError("MonitoringChannel's self.caller was not set")
            self.creator = self.caller
            if not self.creator:
                raise XOSProgrammingError("MonitoringChannel's self.creator was not set")

        if self.pk is None:
            #Allow only one monitoring channel per user
            channel_count = sum ( [1 for channel in MonitoringChannel.objects.filter(kind=CEILOMETER_KIND) if (channel.creator == self.creator)] )
            if channel_count > 0:
                raise XOSValidationError("Already %s channels exist for user Can only create max 1 MonitoringChannel instance per user" % str(channel_count))

        super(MonitoringChannel, self).save(*args, **kwargs)
        model_policy_monitoring_channel(self.pk)

    def delete(self, *args, **kwargs):
        self.cleanup_container()
        super(MonitoringChannel, self).delete(*args, **kwargs)

    @property
    def addresses(self):
        if (not self.id) or (not self.instance):
            return {}

        addresses = {}
        for ns in self.instance.ports.all():
            if "private" in ns.network.name.lower():
                addresses["private"] = (ns.ip, ns.mac)
            elif ("nat" in ns.network.name.lower()) or ("management" in ns.network.name.lower()):
                addresses["nat"] = (ns.ip, ns.mac)
            #TODO: Do we need this client_access_network. Revisit in VTN context
            #elif "ceilometer_client_access" in ns.network.labels.lower():
            #    addresses["ceilometer"] = (ns.ip, ns.mac)
        return addresses

    @property
    def nat_ip(self):
        return self.addresses.get("nat", (None, None))[0]

    @property
    def nat_mac(self):
        return self.addresses.get("nat", (None, None))[1]

    @property
    def private_ip(self):
        return self.addresses.get("nat", (None, None))[0]

    @property
    def private_mac(self):
        return self.addresses.get("nat", (None, None))[1]

    @property
    def ceilometer_ip(self):
        return self.addresses.get("ceilometer", (None, None))[0]

    @property
    def ceilometer_mac(self):
        return self.addresses.get("ceilometer", (None, None))[1]

    @property
    def site_tenant_list(self):
        tenant_ids = Set()
        for sp in SitePrivilege.objects.filter(user=self.creator):
            site = sp.site
            for cs in site.controllersite.all():
               if cs.tenant_id:
                   tenant_ids.add(cs.tenant_id)
        return tenant_ids

    @property
    def slice_tenant_list(self):
        tenant_ids = Set()
        for sp in SlicePrivilege.objects.filter(user=self.creator):
            slice = sp.slice
            for cs in slice.controllerslices.all():
               if cs.tenant_id:
                   tenant_ids.add(cs.tenant_id)
        for slice in Slice.objects.filter(creator=self.creator):
            for cs in slice.controllerslices.all():
                if cs.tenant_id:
                    tenant_ids.add(cs.tenant_id)
        if self.creator.is_admin:
            #TODO: Ceilometer publishes the SDN meters without associating to any tenant IDs.
            #For now, ceilometer code is changed to pusblish all such meters with tenant
            #id as "default_admin_tenant". Here add that default tenant as authroized tenant_id
            #for all admin users. 
            tenant_ids.add("default_admin_tenant")
        return tenant_ids

    @property
    def tenant_list(self):
        return self.slice_tenant_list | self.site_tenant_list

    @property
    def tenant_list_str(self):
        return ", ".join(self.tenant_list)

    @property
    def ceilometer_port(self):
        # TODO: Find a better logic to choose unique ceilometer port number for each instance 
        if not self.id:
            return None
        return 8888+self.id

    @property
    def ssh_proxy_tunnel(self):
        return self.get_attribute("ssh_proxy_tunnel", False)

    @ssh_proxy_tunnel.setter
    def ssh_proxy_tunnel(self, value):
        self.set_attribute("ssh_proxy_tunnel", value)

    @property
    def ssh_tunnel_port(self):
        return self.get_attribute("ssh_tunnel_port")

    @ssh_tunnel_port.setter
    def ssh_tunnel_port(self, value):
        self.set_attribute("ssh_tunnel_port", value)

    @property
    def ssh_tunnel_ip(self):
        return self.get_attribute("ssh_tunnel_ip")

    @ssh_tunnel_ip.setter
    def ssh_tunnel_ip(self, value):
        self.set_attribute("ssh_tunnel_ip", value)

    @property
    def ceilometer_url(self):
        if self.ssh_proxy_tunnel:
            if self.ssh_tunnel_ip and self.ssh_tunnel_port:
                return "http://" + self.ssh_tunnel_ip + ":" + str(self.ssh_tunnel_port) + "/"
            else:
                return None
        else:
            if self.private_ip and self.ceilometer_port:
                return "http://" + self.private_ip + ":" + str(self.ceilometer_port) + "/"
            else:
                return None

def model_policy_monitoring_channel(pk):
    # TODO: this should be made in to a real model_policy
    with transaction.atomic():
        mc = MonitoringChannel.objects.select_for_update().filter(pk=pk)
        if not mc:
            return
        mc = mc[0]
        mc.manage_container()


SFLOW_KIND = "sflow"
SFLOW_PORT = 6343
SFLOW_API_PORT = 33333

class SFlowService(Service):
    KIND = SFLOW_KIND

    class Meta:
        app_label = "monitoring"
        verbose_name = "sFlow Collection Service"
        proxy = True

    default_attributes = {"sflow_port": SFLOW_PORT, "sflow_api_port": SFLOW_API_PORT}

    sync_attributes = ("sflow_port", "sflow_api_port",)

    @property
    def sflow_port(self):
        return self.get_attribute("sflow_port", self.default_attributes["sflow_port"])

    @sflow_port.setter
    def sflow_port(self, value):
        self.set_attribute("sflow_port", value)

    @property
    def sflow_api_port(self):
        return self.get_attribute("sflow_api_port", self.default_attributes["sflow_api_port"])

    @sflow_api_port.setter
    def sflow_api_port(self, value):
        self.set_attribute("sflow_api_port", value)

    def get_instance(self):
        if self.slices.exists():
            slice = self.slices.all()[0]
            if slice.instances.exists():
                return slice.instances.all()[0]

        return None

    @property
    def sflow_api_url(self):
        if not self.get_instance():
            return None
        return "http://" + self.get_instance().get_ssh_ip() + ":" + str(self.sflow_api_port) + "/"

class SFlowTenant(Tenant): 
    class Meta:
        proxy = True

    KIND = SFLOW_KIND

    sync_attributes = ("listening_endpoint", )

    default_attributes = {}
    def __init__(self, *args, **kwargs):
        sflow_services = SFlowService.get_service_objects().all()
        if sflow_services:
            self._meta.get_field("provider_service").default = sflow_services[0].id
        super(SFlowTenant, self).__init__(*args, **kwargs)

    @property
    def creator(self):
        from core.models import User
        if getattr(self, "cached_creator", None):
            return self.cached_creator
        creator_id=self.get_attribute("creator_id")
        if not creator_id:
            return None
        users=User.objects.filter(id=creator_id)
        if not users:
            return None
        user=users[0]
        self.cached_creator = users[0]
        return user

    @creator.setter
    def creator(self, value):
        if value:
            value = value.id
        if (value != self.get_attribute("creator_id", None)):
            self.cached_creator=None
        self.set_attribute("creator_id", value)

    @property
    def listening_endpoint(self):
        return self.get_attribute("listening_endpoint", None)

    @listening_endpoint.setter
    def listening_endpoint(self, value):
        if urlparse(value).scheme != 'udp':
            raise XOSProgrammingError("SFlowTenant: Only UDP listening endpoint URLs are accepted...valid syntax is: udp://ip:port")
        self.set_attribute("listening_endpoint", value)

    def save(self, *args, **kwargs):
        if not self.creator:
            if not getattr(self, "caller", None):
                # caller must be set when creating a SFlow tenant since it creates a slice
                raise XOSProgrammingError("SFlowTenant's self.caller was not set")
            self.creator = self.caller
            if not self.creator:
                raise XOSProgrammingError("SFlowTenant's self.creator was not set")

        if not self.listening_endpoint:
            raise XOSProgrammingError("SFlowTenant's self.listening_endpoint was not set")

        if self.pk is None:
            #Allow only one sflow channel per user and listening_endpoint
            channel_count = sum ( [1 for channel in SFlowTenant.objects.filter(kind=SFLOW_KIND) if ((channel.creator == self.creator) and (channel.listening_endpoint == self.listening_endpoint))] )
            if channel_count > 0:
                raise XOSValidationError("Already %s sflow channels exist for user Can only create max 1 tenant per user and listening endpoint" % str(channel_count))

        super(SFlowTenant, self).save(*args, **kwargs)

    def delete(self, *args, **kwargs):
        super(MonitoringChannel, self).delete(*args, **kwargs)

    @property
    def authorized_resource_list(self):
        return ['all']

    @property
    def authorized_resource_list_str(self):
        return ", ".join(self.authorized_resource_list)

