from core.models.plcorebase import *
from models_decl import VSMService_decl
from models_decl import VSMVendor_decl
from models_decl import VSMTenant_decl

from django.db import models
from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, NetworkParameter, NetworkParameterType, Port, AddressPool
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 *
from operator import itemgetter, attrgetter, methodcaller
from core.models import Tag
from core.models.service import LeastLoadedNodeScheduler
import traceback
from xos.exceptions import *
from xos.config import Config

class VSMService(VSMService_decl):
   class Meta:
        proxy = True 

   def create_tenant(self, **kwargs):
       t = VSMTenant(kind="vEPC", provider_service=self, connect_method="na", **kwargs)
       t.save()
       return t

class VSMVendor(VSMVendor_decl):
   class Meta:
        proxy = True

class VSMTenant(VSMTenant_decl):
   class Meta:
        proxy = True 

   def __init__(self, *args, **kwargs):
       vsmservice = VSMService.get_service_objects().all()
       if vsmservice:
           self._meta.get_field(
                   "provider_service").default = vsmservice[0].id
       super(VSMTenant, self).__init__(*args, **kwargs)

   @property
   def image(self):
       if not self.vsm_vendor:
           return super(VSMTenant, self).image
       return self.vsm_vendor.image
   
   def save_instance(self, instance):
       if self.vsm_vendor:
           instance.flavor = self.vsm_vendor.flavor
       super(VSMTenant, self).save_instance(instance)

   def save(self, *args, **kwargs):
       if not self.creator:
           if not getattr(self, "caller", None):
               raise XOSProgrammingError("VSMTenant's self.caller was not set")
           self.creator = self.caller
           if not self.creator:
               raise XOSProgrammingError("VSMTenant's self.creator was not set")

       super(VSMTenant, self).save(*args, **kwargs)
       # This call needs to happen so that an instance is created for this
       # tenant is created in the slice. One instance is created per tenant.
       model_policy_vsmtenant(self.pk)

   def delete(self, *args, **kwargs):
       # Delete the instance that was created for this tenant
       self.cleanup_container()
       super(VSMTenant, self).delete(*args, **kwargs)

def model_policy_vsmtenant(pk):
    # This section of code is atomic to prevent race conditions
    with transaction.atomic():
        # We find all of the tenants that are waiting to update
        tenant = VSMTenant.objects.select_for_update().filter(pk=pk)
        if not tenant:
            return
        # Since this code is atomic it is safe to always use the first tenant
        tenant = tenant[0]
        tenant.manage_container()
