replace composite_primary_key hack with django's unique together
diff --git a/xos/core/models/controlleruser.py b/xos/core/models/controlleruser.py
index 0900df7..6b11b24 100644
--- a/xos/core/models/controlleruser.py
+++ b/xos/core/models/controlleruser.py
@@ -15,7 +15,9 @@
     controller = models.ForeignKey(Controller,related_name='controllersusers')
     kuser_id = StrippedCharField(null=True, blank=True, max_length=200, help_text="Keystone user id")
 
-    composite_primary_key = ('user', 'controller', 'kuser_id')
+
+    class Meta:
+        unique_together = ('user', 'controller')
 
     def __unicode__(self):  return u'%s %s' % (self.controller, self.user)
 
@@ -40,7 +42,8 @@
     site_privilege = models.ForeignKey('SitePrivilege', related_name='controllersiteprivileges')
     role_id = StrippedCharField(null=True, blank=True, max_length=200, db_index=True, help_text="Keystone id")
 
-    composite_primary_key = ('controller', 'site_privilege', 'role_id')
+    class Meta:
+        unique_together = ('controller', 'site_privilege', 'role_id')
 
     def __unicode__(self):  return u'%s %s' % (self.controller, self.site_privilege)
 
@@ -73,7 +76,9 @@
     slice_privilege = models.ForeignKey('SlicePrivilege', related_name='controllersliceprivileges')
     role_id = StrippedCharField(null=True, blank=True, max_length=200, db_index=True, help_text="Keystone id")
 
-    composite_primary_key = ('controller', 'slice_privilege')
+
+    class Meta:
+        unique_together = ('controller', 'slice_privilege')
 
     def __unicode__(self):  return u'%s %s' % (self.controller, self.slice_privilege)
 
diff --git a/xos/core/models/image.py b/xos/core/models/image.py
index 0e12473..21d4f23 100644
--- a/xos/core/models/image.py
+++ b/xos/core/models/image.py
@@ -19,7 +19,8 @@
     image = models.ForeignKey(Image,related_name='imagedeployments')
     deployment = models.ForeignKey(Deployment,related_name='imagedeployments')
 
-    composite_primary_key = ('image', 'deployment')
+    class Meta:
+        unique_together = ('image', 'deployment')
 
     def __unicode__(self):  return u'%s %s' % (self.image, self.deployment)
 
@@ -32,7 +33,8 @@
     image = models.ForeignKey(Image,related_name='controllerimages')
     controller = models.ForeignKey(Controller,related_name='controllerimages')
     glance_image_id = StrippedCharField(null=True, blank=True, max_length=200, help_text="Glance image id") 
-    
-    composite_primary_key = ('image', 'controller')
+   
+    class Meta:
+        unique_together = ('image', 'controller')
          
     def __unicode__(self):  return u'%s %s' % (self.image, self.controller)
diff --git a/xos/core/models/network.py b/xos/core/models/network.py
index 5346785..3a1c1a7 100644
--- a/xos/core/models/network.py
+++ b/xos/core/models/network.py
@@ -155,9 +155,9 @@
     router_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum router id")
     subnet_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum subnet id")
     subnet = models.CharField(max_length=32, blank=True)
-      
-      
-    composite_primary_key = ('network', 'controller')
+     
+    class Meta:
+        unique_together = ('network', 'controller')
         
     @staticmethod
     def select_by_user(user):
@@ -176,7 +176,8 @@
     network = models.ForeignKey(Network,related_name='networkslices')
     slice = models.ForeignKey(Slice,related_name='networkslices')
 
-    composite_primary_key = ('network', 'slice')
+    class Meta:
+        unique_together = ('network', 'slice')
 
     def save(self, *args, **kwds):
         slice = self.slice
@@ -209,7 +210,8 @@
     ip = models.GenericIPAddressField(help_text="Sliver ip address", blank=True, null=True)
     port_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum port id")
 
-    composite_primary_key = ('network', 'sliver')
+    class Meta:
+        unique_together = ('network', 'sliver')
 
     def save(self, *args, **kwds):
         slice = self.sliver.slice
diff --git a/xos/core/models/plcorebase.py b/xos/core/models/plcorebase.py
index a5f73e5..3760fde 100644
--- a/xos/core/models/plcorebase.py
+++ b/xos/core/models/plcorebase.py
@@ -151,10 +151,6 @@
     deleted = models.BooleanField(default=False)
     write_protect = models.BooleanField(default=False)
 
-    # XXX Django has no official support for composite primray keys yet
-    # so we will hack in an inefficient solution here.
-    composite_primary_key = []
-
     class Meta:
         # Changing abstract to False would require the managers of subclasses of
         # PlCoreBase to be customized individually.
@@ -190,28 +186,6 @@
                 self.enacted=None
                 self.save(update_fields=['enacted','deleted'], silent=silent)
 
-    def check_composite_primary_key(self):
-        try:
-            composite_key_exists = (self.composite_primary_key!=None) and (self.composite_primary_key!=[])
-        except AttributeError:
-            composite_key_exists = False
-
-        if (not composite_key_exists):
-            return
-
-        # dictionary containing cpk field name and value
-        cpk_fields = dict([(name, getattr(self, name)) for name in self.composite_primary_key])
-        objs = self.__class__.objects.filter(**cpk_fields)
-        # we can only continue if there are no matches or
-        # if this record is updating itself
-        if (len(objs) == 0 or
-            (len(objs) == 1 and self.id and objs[0].id == self.id)):
-            return
-        # if we reach this point then we've matched more than 1
-        # existing record or we are trying to
-        msg = "%s violates composite primray key constraint on fields: %s " % (self, self.composite_primary_key)
-        raise db.Error, msg
-
 
     def save(self, *args, **kwargs):
         # let the user specify silence as either a kwarg or an instance varible
@@ -229,9 +203,6 @@
                 if not (field in ["backend_register", "backend_status", "deleted", "enacted", "updated"]):
                     ignore_composite_key_check=False
 
-        if not ignore_composite_key_check:
-            self.check_composite_primary_key()
-
         super(PlCoreBase, self).save(*args, **kwargs)
 
         # This is a no-op if observer_disabled is set
diff --git a/xos/core/models/site.py b/xos/core/models/site.py
index 689dea0..1e8c7ca 100644
--- a/xos/core/models/site.py
+++ b/xos/core/models/site.py
@@ -219,7 +219,8 @@
     user = models.ForeignKey('User', related_name='deploymentprivileges')
     deployment = models.ForeignKey('Deployment', related_name='deploymentprivileges')
     role = models.ForeignKey('DeploymentRole',related_name='deploymentprivileges')
-    composite_primary_key = ('user', 'deployment', 'role')
+    class Meta:
+        unique_together = ('user', 'deployment', 'role')
 
     def __unicode__(self):  return u'%s %s %s' % (self.deployment, self.user, self.role)
 
@@ -281,7 +282,8 @@
     controller = models.ForeignKey(Controller, null=True, blank=True, related_name='sitedeployments')
     availability_zone = StrippedCharField(max_length=200, null=True, blank=True, help_text="OpenStack availability zone")
 
-    composite_primary_key = ('site', 'deployment', 'controller')
+    class Meta:
+        unique_together = ('site', 'deployment', 'controller')
 
     def __unicode__(self):  return u'%s %s' % (self.deployment, self.site)
     
@@ -291,4 +293,5 @@
     controller = models.ForeignKey(Controller, null=True, blank=True, related_name='controllersite')
     tenant_id = StrippedCharField(null=True, blank=True, max_length=200, db_index=True, help_text="Keystone tenant id")
     
-    composite_primary_key = ('site', 'controller') 
+    class Meta:
+        unique_together = ('site', 'controller') 
diff --git a/xos/core/models/slice.py b/xos/core/models/slice.py
index 44a918b..0c55791 100644
--- a/xos/core/models/slice.py
+++ b/xos/core/models/slice.py
@@ -126,7 +126,8 @@
     slice = models.ForeignKey('Slice', related_name='sliceprivileges')
     role = models.ForeignKey('SliceRole',related_name='sliceprivileges')
 
-    composite_primary_key = ('user', 'slice', 'role')
+    class Meta:
+        unique_together = ('user', 'slice', 'role')
 
     def __unicode__(self):  return u'%s %s %s' % (self.slice, self.user, self.role)
 
@@ -155,7 +156,8 @@
     slice = models.ForeignKey(Slice, related_name='controllerslices')
     tenant_id = StrippedCharField(null=True, blank=True, max_length=200, help_text="Keystone tenant id")
 
-    composite_primary_key = ('controller', 'slice')
+    class Meta:
+        unique_together = ('controller', 'slice')
      
     def __unicode__(self):  return u'%s %s'  % (self.slice, self.controller)