blob: 77991831d282f4fecd6312c95e22e892fd61e858 [file] [log] [blame]
from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, NetworkParameter, NetworkParameterType, AddressPool, Port
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
from core.models import Tag
from core.models.service import LeastLoadedNodeScheduler
import traceback
from xos.exceptions import *
from core.models import SlicePrivilege, SitePrivilege
from sets import Set
from xos.config import Config
from models_decl import *
class VPGWCService (VPGWCService_decl):
class Meta:
proxy = True
class VPGWCTenant (VPGWCTenant_decl):
class Meta:
proxy = True
def __init__(self, *args, **kwargs):
pgwc_services = VPGWCService.get_service_objects().all()
# When the tenant is created the default service in the form is set
# to be the first created HelloWorldServiceComplete
if pgwc_services:
self._meta.get_field(
"provider_service").default = pgwc_services[0].id
super(VPGWCTenant, self).__init__(*args, **kwargs)
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("ServiceComponents's self.caller was not set")
self.creator = self.caller
if not self.creator:
raise XOSProgrammingError("ServiceComponents's self.creator was not set")
'''
super(VPGWCTenant, 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_mcord_servicecomponent(self.pk)
# def save_instance(self, instance):
# with transaction.atomic():
# super(VPGWCTenant, self).save_instance(instance)
# if instance.isolation in ["vm"]:
# for ntype in vpgwc_net_types:
# lan_network = self.get_lan_network(instance, ntype)
# port = self.find_or_make_port(instance,lan_network)
# if (ntype == "s5s8"):
# port.set_parameter("s_tag", self.s5s8_pgw_tag)
# port.set_parameter("neutron_port_name", "stag-%s" % self.s5s8_pgw_tag)
# port.save()
# else:
# return True
def save_instance(self, instance):
with transaction.atomic():
super(VPGWCTenant, self).save_instance(instance)
#if instance.isolation in ["vm"]:
# if self.image_name == 'pgwu':
# lan_network = self.get_lan_network(instance, "wan_network")
# port = self.find_or_make_port(instance,lan_network)
# port.set_parameter("neutron_port_ip", "102.0.0.8")
# port.save()
def delete(self, *args, **kwargs):
# Delete the instance that was created for this tenant
self.cleanup_container()
super(VPGWCTenant, self).delete(*args, **kwargs)
def find_or_make_port(self, instance, network, **kwargs):
port = Port.objects.filter(instance=instance, network=network)
if port:
port = port[0]
print "port already exist", port[0]
else:
port = Port(instance=instance, network=network, **kwargs)
print "NETWORK", network, "MAKE_PORT", port
port.save()
return port
def get_lan_network(self, instance, ntype):
slice = self.provider_service.slices.all()[0]
lan_networks = [x for x in slice.networks.all() if ntype in x.name]
if not lan_networks:
raise XOSProgrammingError("No lan_network")
return lan_networks[0]
def manage_container(self):
from core.models import Instance, Flavor
if self.deleted:
return
# For container or container_vm isolation, use what TenantWithCotnainer
# provides us
slice = self.get_slice()
if slice.default_isolation in ["container_vm", "container"]:
super(VPGWCTenant,self).manage_container()
return
if not self.s5s8_pgw_tag:
raise XOSConfigurationError("S5S8_PGW_TAG is missed")
if self.instance:
# We're good.
return
instance = self.make_instance()
self.instance = instance
super(TenantWithContainer, self).save()
def get_slice(self):
if not self.provider_service.slices.count():
raise XOSConfigurationError("The service has no slices")
slice = self.provider_service.slices.all()[0]
return slice
def make_instance(self):
slice = self.provider_service.slices.all()[0]
flavors = Flavor.objects.filter(name=slice.default_flavor)
# flavors = Flavor.objects.filter(name="m1.xlarge")
if not flavors:
raise XOSConfigurationError("No default flavor")
default_flavor = slice.default_flavor
slice = self.provider_service.slices.all()[0]
if slice.default_isolation == "container_vm":
(node, parent) = ContainerVmScheduler(slice).pick()
else:
(node, parent) = LeastLoadedNodeScheduler(slice).pick()
instance = Instance(slice = slice,
node = node,
image = self.image,
creator = self.creator,
deployment = node.site_deployment.deployment,
flavor = flavors[0],
isolation = slice.default_isolation,
parent = parent)
self.save_instance(instance)
return instance
def ip_to_mac(self, ip):
(a, b, c, d) = ip.split('.')
return "02:42:%02x:%02x:%02x:%02x" % (int(a), int(b), int(c), int(d))
@property
def image(self):
img = self.image_name.strip()
if img.lower() != "default":
return Image.objects.get(name=img)
else:
return super(VPGWCTenant, self).image
@property
def addresses(self):
if (not self.id) or (not self.instance):
return {}
addresses = {}
for ns in self.instance.ports.all():
if "s5s8_pgw" in ns.network.name.lower():
addresses["s5s8_pgw"] = (ns.ip, ns.mac)
return addresses
@property
def s5s8_pgw_ip(self):
return self.addresses.get("s5s8_pgw", (None, None))[0]
@property
def s5s8_pgw_mac(self):
return self.addresses.get("s5s8_pgw", (None, None))[1]
def model_policy_mcord_servicecomponent(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 = VPGWCTenant.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()