Merge branch 'master' of https://github.com/open-cloud/xos
diff --git a/xos/ceilometer/admin.py b/xos/ceilometer/admin.py
index 987877c..3ed70b2 100644
--- a/xos/ceilometer/admin.py
+++ b/xos/ceilometer/admin.py
@@ -81,6 +81,18 @@
form = MonitoringChannelForm
suit_form_tabs = (('general','Details'),)
+ actions=['delete_selected_objects']
+
+ def get_actions(self, request):
+ actions = super(MonitoringChannelAdmin, self).get_actions(request)
+ if 'delete_selected' in actions:
+ del actions['delete_selected']
+ return actions
+
+ def delete_selected_objects(self, request, queryset):
+ for obj in queryset:
+ obj.delete()
+ delete_selected_objects.short_description = "Delete Selected MonitoringChannel Objects"
def queryset(self, request):
return MonitoringChannel.get_tenant_objects_by_user(request.user)
diff --git a/xos/core/models/service.py b/xos/core/models/service.py
index c203b70..662a054 100644
--- a/xos/core/models/service.py
+++ b/xos/core/models/service.py
@@ -366,31 +366,16 @@
if getattr(self, "cached_instance", None):
return self.cached_instance
instance_id=self.get_attribute("instance_id")
- instance = None
- if instance_id:
- instances=Instance.objects.filter(id=instance_id)
- instance=instances[0]
- if not instance:
- if not self.get_attribute("use_same_instance_for_multiple_tenants", default=False):
- return None
- if not self.provider_service.slices.count():
- raise XOSConfigurationError("The service has no associated slices")
- slices = self.provider_service.slices.all()
- instance = self.pick_least_loaded_instance_in_slice(slices)
- if not instance:
- return None
+ if not instance_id:
+ return None
+ instances=Instance.objects.filter(id=instance_id)
+ if not instances:
+ return None
+ instance=instances[0]
instance.caller = self.creator
self.cached_instance = instance
return instance
- def pick_least_loaded_instance_in_slice(self, slices):
- for slice in slices:
- if slice.instances.all().count() > 0:
- #TODO: Temporarily returning the first instance in the slice
- #TODO: Change logic to pick instance based on number of monitoring channels ruuning in each instance
- return slice.instances.all()[0]
- return None
-
@instance.setter
def instance(self, value):
if value:
@@ -494,6 +479,25 @@
# for container-in-VM, pick a VM
raise "Not Implemented"
+ def pick_least_loaded_instance_in_slice(self, slices):
+ for slice in slices:
+ if slice.instances.all().count() > 0:
+ for instance in slice.instances.all():
+ #Pick the first instance that has lesser than 5 tenants
+ if self.count_of_tenants_of_an_instance(instance) < 5:
+ return instance
+ return None
+
+ #TODO: Ideally the tenant count for an instance should be maintained using a
+ #many-to-one relationship attribute, however this model being proxy, it does
+ #not permit any new attributes to be defined. Find if any better solutions
+ def count_of_tenants_of_an_instance(self, instance):
+ tenant_count = 0
+ for tenant in self.get_tenant_objects().all():
+ if tenant.get_attribute("instance_id", None) == instance.id:
+ tenant_count += 1
+ return tenant_count
+
def manage_container(self):
from core.models import Instance, Flavor
@@ -506,42 +510,56 @@
if self.instance is None:
if not self.provider_service.slices.count():
- raise XOSConfigurationError("The VCPE service has no slices")
+ raise XOSConfigurationError("The service has no slices")
- flavors = Flavor.objects.filter(name="m1.small")
- if not flavors:
- raise XOSConfigurationError("No m1.small flavor")
+ new_instance_created = False
+ instance = None
+ if self.get_attribute("use_same_instance_for_multiple_tenants", default=False):
+ #Find if any existing instances can be used for this tenant
+ slices = self.provider_service.slices.all()
+ instance = self.pick_least_loaded_instance_in_slice(slices)
- node = self.pick_node_for_instance()
- slice = self.provider_service.slices.all()[0]
+ if not instance:
+ flavors = Flavor.objects.filter(name="m1.small")
+ if not flavors:
+ raise XOSConfigurationError("No m1.small flavor")
- if slice.default_isolation == "container_vm":
- parent = self.pick_vm()
- else:
- parent = None
+ node =self.pick_node_for_instance()
+ slice = self.provider_service.slices.all()[0]
- 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)
+ if slice.default_isolation == "container_vm":
+ parent = self.pick_vm()
+ else:
+ parent = None
- self.save_instance(instance)
+ 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)
+ new_instance_created = True
try:
self.instance = instance
super(TenantWithContainer, self).save()
except:
- instance.delete()
+ if new_instance_created:
+ instance.delete()
raise
def cleanup_container(self):
if self.instance:
- # print "XXX cleanup instance", self.instance
- self.instance.delete()
+ if self.get_attribute("use_same_instance_for_multiple_tenants", default=False):
+ #Delete the instance only if this is last tenant in that instance
+ tenant_count = self.count_of_tenants_of_an_instance(self.instance)
+ if tenant_count == 0:
+ self.instance.delete()
+ else:
+ self.instance.delete()
self.instance = None
class CoarseTenant(Tenant):