from django.db import models
from django.core.validators import URLValidator
from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, Subscriber, CoarseTenant, ServiceMonitoringAgentInfo
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"
#Ensure the length of name for 'kind' attribute is below 30
CEILOMETER_PUBLISH_TENANT_KIND = "ceilo-publish-tenant"
CEILOMETER_PUBLISH_TENANT_OS_KIND = "ceilo-os-publish-tenant"
CEILOMETER_PUBLISH_TENANT_ONOS_KIND = "ceilo-onos-publish-tenant"
CEILOMETER_PUBLISH_TENANT_USER_KIND = "ceilo-user-publish-tenant"

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

    sync_attributes = ("private_ip", "private_mac",
                       "nat_ip", "nat_mac", "ceilometer_enable_pub_sub")
    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_enable_pub_sub(self):
        return self.get_attribute("ceilometer_enable_pub_sub", False)

    @ceilometer_enable_pub_sub.setter
    def ceilometer_enable_pub_sub(self, value):
        self.set_attribute("ceilometer_enable_pub_sub", 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'

    @property
    def ceilometer_rabbit_compute_node(self):
        if not self.get_instance():
            return None
        return self.get_instance().node.name

    @property
    def ceilometer_rabbit_host(self):
        if not self.get_instance():
            return None
        return self.nat_ip

    @property
    def ceilometer_rabbit_user(self):
        if not self.get_instance():
            return None
        return 'openstack'

    @property
    def ceilometer_rabbit_password(self):
        if not self.get_instance():
            return None
        return 'password'

    @property
    def ceilometer_rabbit_uri(self):
        if not self.get_instance():
            return None
        if not self.private_ip:
            return None
        return 'rabbit://openstack:password@' + self.private_ip + ':5672'

    @property
    def kafka_url(self):
        if not self.get_instance():
            return None
        if not self.private_ip:
            return None
        return 'kafka://' + self.private_ip + ':9092'

    def delete(self, *args, **kwargs):
        instance = self.get_instance()
        if instance:
            instance.delete()
        super(CeilometerService, self).delete(*args, **kwargs)


class MonitoringChannel(TenantWithContainer):   # aka 'CeilometerTenant'
    class Meta:
        app_label = "monitoring"
        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.get_tenant_objects().all() 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("private", (None, None))[0]

    @property
    def private_mac(self):
        return self.addresses.get("private", (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.private_ip and self.ceilometer_port:
            return "http://" + self.private_ip + ":" + str(self.ceilometer_port) + "/"
        else:
            return None

    @property
    def ceilometer_ssh_proxy_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:
            return None

    @property
    def kafka_url(self):
        ceilometer_services = CeilometerService.get_service_objects().all()
        if not ceilometer_services:
            return None
        return ceilometer_services[0].kafka_url


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()

#@receiver(models.signals.post_delete, sender=MonitoringChannel)
#def cleanup_monitoring_channel(sender, o, *args, **kwargs):
#     #o.cleanup_container()
#     #Temporary change only, remove the below code after testing
#     if o.instance:
#         o.instance.delete()
#         o.instance = None

class MonitoringPublisher(Tenant):
    class Meta:
        app_label = "monitoring"
        proxy = True

    KIND = CEILOMETER_PUBLISH_TENANT_KIND

    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(MonitoringPublisher, self).__init__(*args, **kwargs)

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

    @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)

class OpenStackServiceMonitoringPublisher(MonitoringPublisher):
    class Meta:
        app_label = "monitoring"
        proxy = True

    KIND = CEILOMETER_PUBLISH_TENANT_OS_KIND

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

    def can_update(self, user):
        #Don't allow creation of this model instances for non-admin users also
        return False

    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("OpenStackServiceMonitoringPublisher's self.caller was not set")
            self.creator = self.caller
            if not self.creator:
                raise XOSProgrammingError("OpenStackServiceMonitoringPublisher's self.creator was not set")

        if self.pk is None:
            #Allow only one openstack monitoring publisher per admin user
            publisher_count = sum ( [1 for ospublisher in OpenStackServiceMonitoringPublisher.get_tenant_objects().all() if (ospublisher.creator == self.creator)] )
            if publisher_count > 0:
                raise XOSValidationError("Already %s openstack publishers exist for user Can only create max 1 OpenStackServiceMonitoringPublisher instance per user" % str(publisher_count))

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

class ONOSServiceMonitoringPublisher(MonitoringPublisher):
    class Meta:
        app_label = "monitoring"
        proxy = True

    KIND = CEILOMETER_PUBLISH_TENANT_ONOS_KIND

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

    def can_update(self, user):
        #Don't allow creation of this model instances for non-admin users also
        return False

    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("ONOSServiceMonitoringPublisher's self.caller was not set")
            self.creator = self.caller
            if not self.creator:
                raise XOSProgrammingError("ONOSServiceMonitoringPublisher's self.creator was not set")

        if self.pk is None:
            #Allow only one openstack monitoring publisher per admin user
            publisher_count = sum ( [1 for onospublisher in ONOSServiceMonitoringPublisher.get_tenant_objects().all() if (onospublisher.creator == self.creator)] )
            if publisher_count > 0:
                raise XOSValidationError("Already %s openstack publishers exist for user Can only create max 1 ONOSServiceMonitoringPublisher instance per user" % str(publisher_count))

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

class UserServiceMonitoringPublisher(MonitoringPublisher):
    class Meta:
        app_label = "monitoring"
        proxy = True

    KIND = CEILOMETER_PUBLISH_TENANT_USER_KIND

    def __init__(self, *args, **kwargs):
        self.cached_target_service = None
        self.cached_tenancy_from_target_service = None
        self.cached_service_monitoring_agent = None
        super(UserServiceMonitoringPublisher, self).__init__(*args, **kwargs)

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

    @property
    def target_service(self):
        if getattr(self, "cached_target_service", None):
            return self.cached_target_service
        target_service_id = self.get_attribute("target_service_id")
        if not target_service_id:
            return None
        services = Service.objects.filter(id=target_service_id)
        if not services:
            return None
        target_service = services[0]
        self.cached_target_service = target_service
        return target_service

    @target_service.setter
    def target_service(self, value):
        if value:
            value = value.id
        if (value != self.get_attribute("target_service_id", None)):
            self.cached_target_service = None
        self.set_attribute("target_service_id", value)

    @property
    def tenancy_from_target_service(self):
        if getattr(self, "cached_tenancy_from_target_service", None):
            return self.cached_tenancy_from_target_service
        tenancy_from_target_service_id = self.get_attribute("tenancy_from_target_service_id")
        if not tenancy_from_target_service_id:
            return None
        tenancy_from_target_services = CoarseTenant.objects.filter(id=tenancy_from_target_service_id)
        if not tenancy_from_target_services:
            return None
        tenancy_from_target_service = tenancy_from_target_services[0]
        self.cached_tenancy_from_target_service = tenancy_from_target_service
        return tenancy_from_target_service

    @tenancy_from_target_service.setter
    def tenancy_from_target_service(self, value):
        if value:
            value = value.id
        if (value != self.get_attribute("tenancy_from_target_service_id", None)):
            self.cached_tenancy_from_target_service = None
        self.set_attribute("tenancy_from_target_service_id", value)

    @property
    def service_monitoring_agent(self):
        if getattr(self, "cached_service_monitoring_agent", None):
            return self.cached_service_monitoring_agent
        service_monitoring_agent_id = self.get_attribute("service_monitoring_agent")
        if not service_monitoring_agent_id:
            return None
        service_monitoring_agents = CoarseTenant.objects.filter(id=service_monitoring_agent_id)
        if not service_monitoring_agents:
            return None
        service_monitoring_agent = service_monitoring_agents[0]
        self.cached_service_monitoring_agent = service_monitoring_agent
        return service_monitoring_agent

    @service_monitoring_agent.setter
    def service_monitoring_agent(self, value):
        if value:
            value = value.id
        if (value != self.get_attribute("service_monitoring_agent", None)):
            self.cached_service_monitoring_agent = None
        self.set_attribute("service_monitoring_agent", value)

    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("UserServiceMonitoringPublisher's self.caller was not set")
            self.creator = self.caller
            if not self.creator:
                raise XOSProgrammingError("UserServiceMonitoringPublisher's self.creator was not set")

        tenancy_from_target_service = None
        if self.pk is None:
            if self.target_service is None:
                raise XOSValidationError("Target service is not specified in UserServiceMonitoringPublisher")
            #Allow only one monitoring publisher for a given service 
            publisher_count = sum ( [1 for publisher in UserServiceMonitoringPublisher.get_tenant_objects().all() if (publisher.target_service.id == self.target_service.id)] )
            if publisher_count > 0:
                raise XOSValidationError("Already %s publishers exist for service. Can only create max 1 UserServiceMonitoringPublisher instances" % str(publisher_count))
            #Create Service composition object here
            tenancy_from_target_service = CoarseTenant(provider_service = self.provider_service,
                                                   subscriber_service = self.target_service)
            tenancy_from_target_service.save()
            self.tenancy_from_target_service = tenancy_from_target_service

            target_uri = CeilometerService.objects.get(id=self.provider_service.id).ceilometer_rabbit_uri
            if target_uri is None:
                raise XOSProgrammingError("Unable to get the Target_URI for Monitoring Agent")
            service_monitoring_agent = ServiceMonitoringAgentInfo(service = self.target_service,
                                                               target_uri = target_uri)
            service_monitoring_agent.save()
            self.service_monitoring_agent = service_monitoring_agent
        
        try:
            super(UserServiceMonitoringPublisher, self).save(*args, **kwargs)
        except:
            if tenancy_from_target_service:
                tenancy_from_target_service.delete()
            if service_monitoring_agent:
                service_monitoring_agent.delete()
            raise

class InfraMonitoringAgentInfo(ServiceMonitoringAgentInfo):
    class Meta:
        app_label = "monitoring"
    start_url = models.TextField(validators=[URLValidator()], help_text="URL/API to be used to start monitoring agent")
    start_url_json_data = models.TextField(help_text="Metadata to be passed along with start API")
    stop_url = models.TextField(validators=[URLValidator()], help_text="URL/API to be used to stop monitoring agent")
    monitoring_publisher = models.ForeignKey(MonitoringPublisher, related_name="monitoring_agents", null=True, blank=True)

class MonitoringCollectorPluginInfo(PlCoreBase):
    class Meta:
        app_label = "monitoring"
    name = models.CharField(max_length=32)
    plugin_folder_path = StrippedCharField(blank=True, null=True, max_length=1024, help_text="Path pointing to plugin files. e.g. /opt/xos/synchronizers/monitoring/ceilometer/ceilometer-plugins/network/ext_services/vsg/")
    plugin_rabbit_exchange = StrippedCharField(blank=True, null=True, max_length=100) 
    #plugin_notification_handlers_json = models.TextField(blank=True, null=True, help_text="Dictionary of notification handler classes. e.g {\"name\":\"plugin handler main class\"}")
    monitoring_publisher = models.OneToOneField(MonitoringPublisher, related_name="monitoring_collector_plugin", null=True, blank=True)

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.get_tenant_objects().all() 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)

