refactor container stuff out of vCPE and into TenantWithContainer
diff --git a/xos/cord/models.py b/xos/cord/models.py
index 37b29a5..f115045 100644
--- a/xos/cord/models.py
+++ b/xos/cord/models.py
@@ -1,5 +1,5 @@
 from django.db import models
-from core.models import Service, PlCoreBase, Slice, Sliver, Tenant, Node, Image, User, Flavor, Subscriber
+from core.models import Service, PlCoreBase, Slice, Sliver, Tenant, TenantWithContainer, Node, Image, User, Flavor, Subscriber
 from core.models.plcorebase import StrippedCharField
 import os
 from django.db import models, transaction
@@ -457,7 +457,7 @@
 VCPEService.setup_simple_attributes()
 
 
-class VCPETenant(Tenant):
+class VCPETenant(TenantWithContainer):
     class Meta:
         proxy = True
 
@@ -477,66 +477,6 @@
     def __init__(self, *args, **kwargs):
         super(VCPETenant, self).__init__(*args, **kwargs)
         self.cached_vbng=None
-        self.cached_sliver=None
-        self.orig_sliver_id = self.get_initial_attribute("sliver_id")
-
-    @property
-    def image(self):
-        LOOK_FOR_IMAGES=["ubuntu-vcpe4",        # ONOS demo machine -- preferred vcpe image
-                         "Ubuntu 14.04 LTS",    # portal
-                         "Ubuntu-14.04-LTS",    # ONOS demo machine
-                        ]
-        for image_name in LOOK_FOR_IMAGES:
-            images = Image.objects.filter(name = image_name)
-            if images:
-                return images[0]
-
-        raise XOSProgrammingError("No VPCE image (looked for %s)" % str(LOOK_FOR_IMAGES))
-
-    @property
-    def sliver(self):
-        if getattr(self, "cached_sliver", None):
-            return self.cached_sliver
-        sliver_id=self.get_attribute("sliver_id")
-        if not sliver_id:
-            return None
-        slivers=Sliver.objects.filter(id=sliver_id)
-        if not slivers:
-            return None
-        sliver=slivers[0]
-        sliver.caller = self.creator
-        self.cached_sliver = sliver
-        return sliver
-
-    @sliver.setter
-    def sliver(self, value):
-        if value:
-            value = value.id
-        if (value != self.get_attribute("sliver_id", None)):
-            self.cached_sliver=None
-        self.set_attribute("sliver_id", value)
-
-    @property
-    def creator(self):
-        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 vbng(self):
@@ -659,53 +599,6 @@
     def is_synced(self, value):
         pass
 
-    def pick_node(self):
-        nodes = list(Node.objects.all())
-        # TODO: logic to filter nodes by which nodes are up, and which
-        #   nodes the slice can instantiate on.
-        nodes = sorted(nodes, key=lambda node: node.slivers.all().count())
-        return nodes[0]
-
-    def manage_sliver(self):
-        # Each VCPE object owns exactly one sliver.
-
-        if self.deleted:
-            return
-
-        if (self.sliver is not None) and (self.sliver.image != self.image):
-            self.sliver.delete()
-            self.sliver = None
-
-        if self.sliver is None:
-            if not self.provider_service.slices.count():
-                raise XOSConfigurationError("The VCPE service has no slices")
-
-            flavors = Flavor.objects.filter(name="m1.small")
-            if not flavors:
-                raise XOSConfigurationError("No m1.small flavor")
-
-            node =self.pick_node()
-            sliver = Sliver(slice = self.provider_service.slices.all()[0],
-                            node = node,
-                            image = self.image,
-                            creator = self.creator,
-                            deployment = node.site_deployment.deployment,
-                            flavor = flavors[0])
-            sliver.save()
-
-            try:
-                self.sliver = sliver
-                super(VCPETenant, self).save()
-            except:
-                sliver.delete()
-                raise
-
-    def cleanup_sliver(self):
-        if self.sliver:
-            # print "XXX cleanup sliver", self.sliver
-            self.sliver.delete()
-            self.sliver = None
-
     def manage_vbng(self):
         # Each vCPE object owns exactly one vBNG object
 
@@ -774,7 +667,7 @@
 
     def delete(self, *args, **kwargs):
         self.cleanup_vbng()
-        self.cleanup_sliver()
+        self.cleanup_container()
         super(VCPETenant, self).delete(*args, **kwargs)
 
 def model_policy_vcpe(pk):
@@ -784,7 +677,7 @@
         if not vcpe:
             return
         vcpe = vcpe[0]
-        vcpe.manage_sliver()
+        vcpe.manage_container()
         vcpe.manage_vbng()
         vcpe.manage_bbs_account()
         vcpe.cleanup_orphans()
diff --git a/xos/core/models/__init__.py b/xos/core/models/__init__.py
index d7bf036..d48dc46 100644
--- a/xos/core/models/__init__.py
+++ b/xos/core/models/__init__.py
@@ -1,7 +1,7 @@
 from .plcorebase import PlCoreBase,PlCoreBaseManager,PlCoreBaseDeletionManager,PlModelMixIn
 from .project import Project
 from .singletonmodel import SingletonModel
-from .service import Service, Tenant, CoarseTenant, ServicePrivilege, TenantRoot, TenantRootPrivilege, TenantRootRole, Subscriber, Provider
+from .service import Service, Tenant, TenantWithContainer, CoarseTenant, ServicePrivilege, TenantRoot, TenantRootPrivilege, TenantRootRole, Subscriber, Provider
 from .service import ServiceAttribute
 from .tag import Tag
 from .role import Role
diff --git a/xos/core/models/service.py b/xos/core/models/service.py
index 0940176..df2fa71 100644
--- a/xos/core/models/service.py
+++ b/xos/core/models/service.py
@@ -332,6 +332,130 @@
             return None
         return sorted(st, key=attrgetter('id'))[0]
 
+class TenantWithContainer(Tenant):
+    """ A tenant that manages a container """
+
+    # this is a hack and should be replaced by something smarter...
+    LOOK_FOR_IMAGES=["trusty-server-multi-nic",
+                     "ubuntu-vcpe4",        # ONOS demo machine -- preferred vcpe image
+                     "Ubuntu 14.04 LTS",    # portal
+                     "Ubuntu-14.04-LTS",    # ONOS demo machine
+                    ]
+
+    class Meta:
+        proxy = True
+
+    def __init__(self, *args, **kwargs):
+        super(TenantWithContainer, self).__init__(*args, **kwargs)
+        self.cached_sliver=None
+        self.orig_sliver_id = self.get_initial_attribute("sliver_id")
+
+    @property
+    def sliver(self):
+        from core.models import Sliver
+        if getattr(self, "cached_sliver", None):
+            return self.cached_sliver
+        sliver_id=self.get_attribute("sliver_id")
+        if not sliver_id:
+            return None
+        slivers=Sliver.objects.filter(id=sliver_id)
+        if not slivers:
+            return None
+        sliver=slivers[0]
+        sliver.caller = self.creator
+        self.cached_sliver = sliver
+        return sliver
+
+    @sliver.setter
+    def sliver(self, value):
+        if value:
+            value = value.id
+        if (value != self.get_attribute("sliver_id", None)):
+            self.cached_sliver=None
+        self.set_attribute("sliver_id", value)
+
+    @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 image(self):
+        from core.models import Image
+        # Implement the logic here to pick the image that should be used when
+        # instantiating the VM that will hold the container.
+        for image_name in self.LOOK_FOR_IMAGES:
+            images = Image.objects.filter(name = image_name)
+            if images:
+                return images[0]
+
+        raise XOSProgrammingError("No VPCE image (looked for %s)" % str(self.LOOK_FOR_IMAGES))
+
+    def pick_node(self):
+        from core.models import Node
+        nodes = list(Node.objects.all())
+        # TODO: logic to filter nodes by which nodes are up, and which
+        #   nodes the slice can instantiate on.
+        nodes = sorted(nodes, key=lambda node: node.slivers.all().count())
+        return nodes[0]
+
+    def manage_container(self):
+        from core.models import Sliver, Flavor
+
+        if self.deleted:
+            return
+
+        if (self.sliver is not None) and (self.sliver.image != self.image):
+            self.sliver.delete()
+            self.sliver = None
+
+        if self.sliver is None:
+            if not self.provider_service.slices.count():
+                raise XOSConfigurationError("The VCPE service has no slices")
+
+            flavors = Flavor.objects.filter(name="m1.small")
+            if not flavors:
+                raise XOSConfigurationError("No m1.small flavor")
+
+            node =self.pick_node()
+            sliver = Sliver(slice = self.provider_service.slices.all()[0],
+                            node = node,
+                            image = self.image,
+                            creator = self.creator,
+                            deployment = node.site_deployment.deployment,
+                            flavor = flavors[0])
+            sliver.save()
+
+            try:
+                self.sliver = sliver
+                super(TenantWithContainer, self).save()
+            except:
+                sliver.delete()
+                raise
+
+    def cleanup_container(self):
+        if self.sliver:
+            # print "XXX cleanup sliver", self.sliver
+            self.sliver.delete()
+            self.sliver = None
 
 class CoarseTenant(Tenant):
     """ TODO: rename "CoarseTenant" --> "StaticTenant" """