Merge pick up, tweaked role/site/plcore_base or os_manager path when OpenStack not present
diff --git a/planetstack/core/models/key.py b/planetstack/core/models/key.py
index 98cfb9b..7a8b322 100644
--- a/planetstack/core/models/key.py
+++ b/planetstack/core/models/key.py
@@ -1,23 +1,29 @@
 import os
 from django.db import models
 from core.models import PlCoreBase
+from openstack.manager import OpenStackManager
+
 
 # Create your models here.
 
 class Key(PlCoreBase):
-    name = models.CharField(max_length=256, unique=True)
-    nkey_id = models.CharField(max_length=256, unique=True)
+    name = models.CharField(max_length=256)
+    nkey_id = models.CharField(null=True, blank=True, max_length=256, unique=True)
     key = models.CharField(max_length=512)
     type = models.CharField(max_length=256)
     blacklisted = models.BooleanField(default=False)
 
-    def __unicode__(self):  return u'%s' % (self.name)
+    def __unicode__(self):  return u'%s' % (self.key)
 
     def save(self, *args, **kwds):
-        self.os_manager.save_key(self)
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.save_key(self)
         super(Key, self).save(*args, **kwds)
 
     def delete(self, *args, **kwds):
-        self.os_manager.delete_key(self)
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.delete_key(self)
         super(Key, self).delete(*args, **kwds) 
     
diff --git a/planetstack/core/models/plcorebase.py b/planetstack/core/models/plcorebase.py
index 52aa0f7..ed7c3ff 100644
--- a/planetstack/core/models/plcorebase.py
+++ b/planetstack/core/models/plcorebase.py
@@ -1,5 +1,6 @@
 import os
 from django.db import models
+from django.forms.models import model_to_dict
 
 class PlCoreBase(models.Model):
 
@@ -10,5 +11,36 @@
         abstract = True
         app_label = "core"
 
+    def __init__(self, *args, **kwargs):
+        super(PlCoreBase, self).__init__(*args, **kwargs)
+        self.__initial = self._dict
+
+    @property
+    def diff(self):
+        d1 = self.__initial
+        d2 = self._dict
+        diffs = [(k, (v, d2[k])) for k, v in d1.items() if v != d2[k]]
+        return dict(diffs)
+
+    @property
+    def has_changed(self):
+        return bool(self.diff)
+
+    @property
+    def changed_fields(self):
+        return self.diff.keys()
+
+    def get_field_diff(self, field_name):
+        return self.diff.get(field_name, None)
+
+    def save(self, *args, **kwargs):
+        super(PlCoreBase, self).save(*args, **kwargs)
+        self.__initial = self._dict
+
+    @property
+    def _dict(self):
+        return model_to_dict(self, fields=[field.name for field in
+                             self._meta.fields])
+
 
 
diff --git a/planetstack/core/models/role.py b/planetstack/core/models/role.py
index b3611c1..e7d31b9 100644
--- a/planetstack/core/models/role.py
+++ b/planetstack/core/models/role.py
@@ -2,6 +2,7 @@
 import datetime
 from django.db import models
 from core.models import PlCoreBase
+from openstack.manager import OpenStackManager
 
 class Role(PlCoreBase):
 
@@ -13,10 +14,14 @@
 
 
     def save(self, *args, **kwds):
-        self.os_manager.save_role(self)
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.save_role(self)
         super(Role, self).save(*args, **kwds)
     
     def delete(self, *args, **kwds):
-        self.os_manager.delete_role(self)   
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.delete_role(self)   
         super(Role, self).delete(*args, **kwds)
             
diff --git a/planetstack/core/models/site.py b/planetstack/core/models/site.py
index ebf2ab9..11e6a28 100644
--- a/planetstack/core/models/site.py
+++ b/planetstack/core/models/site.py
@@ -2,11 +2,11 @@
 from django.db import models
 from core.models import PlCoreBase
 from core.models import DeploymentNetwork
-
+from openstack.manager import OpenStackManager
 
 class Site(PlCoreBase):
 
-    tenant_id = models.CharField(max_length=200, help_text="Keystone tenant id")
+    tenant_id = models.CharField(null=True, blank=True, max_length=200, help_text="Keystone tenant id")
     name = models.CharField(max_length=200, help_text="Name for this Site")
     site_url = models.URLField(null=True, blank=True, max_length=512, help_text="Site's Home URL Page")
     enabled = models.BooleanField(default=True, help_text="Status for this Site")
@@ -21,12 +21,16 @@
     def __unicode__(self):  return u'%s' % (self.name)
 
     def save(self, *args, **kwds):
-        self.os_manager.save_site(self)
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.save_site(self)
         super(Site, self).save(*args, **kwds)               
 
 
     def delete(self, *args, **kwds):
-        self.os_manager.delete_site(self)
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.delete_site(self)
         super(Site, self).delete(*args, **kwds)         
         
 
@@ -39,11 +43,15 @@
     def __unicode__(self):  return u'%s %s %s' % (self.site, self.user, self.role)
 
     def save(self, *args, **kwds):
-        self.os_manager.driver.add_user_role(self.user.kuser_id, self.site.tenant_id, self.role.role_type)
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.driver.add_user_role(self.user.kuser_id, self.site.tenant_id, self.role.role_type)
         super(SitePrivilege, self).save(*args, **kwds)
 
     def delete(self, *args, **kwds):
-        self.os_manager.driver.delete_user_role(self.user.kuser_id, self.site.tenant_id, self.role.role_type)
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.driver.delete_user_role(self.user.kuser_id, self.site.tenant_id, self.role.role_type)
         super(SitePrivilege, self).delete(*args, **kwds)
 
 
diff --git a/planetstack/core/models/slice.py b/planetstack/core/models/slice.py
index 539be24..a4eb3a4 100644
--- a/planetstack/core/models/slice.py
+++ b/planetstack/core/models/slice.py
@@ -5,6 +5,7 @@
 from core.models import User
 from core.models import Role
 from core.models import DeploymentNetwork
+from openstack.manager import OpenStackManager
 
 # Create your models here.
 
@@ -12,14 +13,13 @@
     tenant_id = models.CharField(max_length=200, help_text="Keystone tenant id")
     name = models.CharField(unique=True, help_text="The Name of the Slice", max_length=80)
     enabled = models.BooleanField(default=True, help_text="Status for this Slice")
-    SLICE_CHOICES = (('plc', 'PLC'), ('delegated', 'Delegated'), ('controller','Controller'), ('none','None'))
-    instantiation = models.CharField(help_text="The instantiation type of the slice", max_length=80, choices=SLICE_CHOICES)
     omf_friendly = models.BooleanField()
     description=models.TextField(blank=True,help_text="High level description of the slice and expected activities", max_length=1024)
     slice_url = models.URLField(blank=True, max_length=512)
     site = models.ForeignKey(Site, related_name='slices', help_text="The Site this Node belongs too")
-    network_id = models.CharField(max_length=256, help_text="Quantum network")
-    router_id = models.CharField(max_length=256, help_text="Quantum router id")
+    network_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum network")
+    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")
 
     SVC_CLASS_CHOICES = (('besteffort', 'Best Effort'), ('silver', 'Silver'), ('gold','Gold'))
     serviceClass = models.CharField(verbose_name="Service Class",default="besteffort",help_text="The Service Class of this slice", max_length=30, choices=SVC_CLASS_CHOICES)
@@ -28,11 +28,15 @@
     def __unicode__(self):  return u'%s' % (self.name)
 
     def save(self, *args, **kwds):
-        self.os_manager.save_slice(self)
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.save_slice(self)
         super(Slice, self).save(*args, **kwds)
 
     def delete(self, *args, **kwds):
-        self.os_manager.delete_slice(self)
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.delete_slice(self)
         super(Slice, self).delete(*args, **kwds)    
 
 class SliceMembership(PlCoreBase):
@@ -43,9 +47,13 @@
     def __unicode__(self):  return u'%s %s %s' % (self.slice, self.user, self.role)
 
     def save(self, *args, **kwds):
-        self.os_manager.driver.add_user_role(self.user.kuser_id, self.slice.tenant_id, self.role.role_type)
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.driver.add_user_role(self.user.kuser_id, self.slice.tenant_id, self.role.role_type)
         super(SliceMembership, self).save(*args, **kwds)
 
     def delete(self, *args, **kwds):
-        self.os_manager.driver.delete_user_role(self.user.kuser_id, self.slice.tenant_id, self.role.role_type)
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.driver.delete_user_role(self.user.kuser_id, self.slice.tenant_id, self.role.role_type)
         super(SliceMembership, self).delete(*args, **kwds)
diff --git a/planetstack/core/models/sliver.py b/planetstack/core/models/sliver.py
index 580c2af..8ebcbd4 100644
--- a/planetstack/core/models/sliver.py
+++ b/planetstack/core/models/sliver.py
@@ -8,10 +8,11 @@
 from core.models import Node
 from core.models import Site
 from core.models import DeploymentNetwork
+from openstack.manager import OpenStackManager
 
 # Create your models here.
 class Sliver(PlCoreBase):
-    instance_id = models.CharField(max_length=200, help_text="Nova instance id")    
+    instance_id = models.CharField(null=True, blank=True, max_length=200, help_text="Nova instance id")    
     name = models.CharField(max_length=200, help_text="Sliver name")
     instance_name = models.CharField(blank=True, null=True, max_length=200, help_text="OpenStack generated name")
     ip = models.GenericIPAddressField(help_text="Sliver ip address", blank=True, null=True)
@@ -20,18 +21,21 @@
     slice = models.ForeignKey(Slice, related_name='slivers')
     node = models.ForeignKey(Node, related_name='slivers')
     deploymentNetwork = models.ForeignKey(DeploymentNetwork, verbose_name='deployment', related_name='sliver_deploymentNetwork')
-    numberCores = models.IntegerField(verbose_name="Number of Cores", help_text="Number of cores for sliver", default=2)
+    numberCores = models.IntegerField(verbose_name="Number of Cores", help_text="Number of cores for sliver", default=0)
 
 
     def __unicode__(self):  return u'%s' % (self.instance_name)
 
     def save(self, *args, **kwds):
-        if not self.slice.subnet.exists():
-            raise exceptions.ValidationError, "Slice %s has no subnet" % self.slice.name
-
-        self.os_manager.save_sliver(self)
+        if not self.name:
+            self.name = self.slice.name
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.save_sliver(self)
         super(Sliver, self).save(*args, **kwds)
 
     def delete(self, *args, **kwds):
-        self.os_manager.delete_sliver(self)
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.delete_sliver(self)
         super(Sliver, self).delete(*args, **kwds)
diff --git a/planetstack/core/models/subnet.py b/planetstack/core/models/subnet.py
index cad9fea..37175ec 100644
--- a/planetstack/core/models/subnet.py
+++ b/planetstack/core/models/subnet.py
@@ -3,6 +3,7 @@
 from django.db import models
 from core.models import PlCoreBase
 from core.models import Slice
+from openstack.manager import OpenStackManager
 
 # Create your models here.
 
@@ -17,9 +18,13 @@
     def __unicode__(self):  return u'%s' % (self.slice.name)
 
     def save(self, *args, **kwds):
-        self.os_manager.save_subnet(self)
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.save_subnet(self)
         super(Subnet, self).save(*args, **kwds)
 
     def delete(self, *args, **kwds):
-        self.os_manager.delete_subnet(self)
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
+            self.os_manager.delete_subnet(self)
         super(Subnet, self).delete(*args, **kwds)
diff --git a/planetstack/core/models/user.py b/planetstack/core/models/user.py
index 6c776b1..38c0d89 100644
--- a/planetstack/core/models/user.py
+++ b/planetstack/core/models/user.py
@@ -1,5 +1,6 @@
 import os
 import datetime
+from collections import defaultdict
 from django.db import models
 from core.models import PlCoreBase
 from core.models import Site
@@ -8,8 +9,6 @@
 from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
 
 # Create your models here.
-has_openstack = False
-
 class UserManager(BaseUserManager):
     def create_user(self, email, firstname, lastname, password=None):
         """
@@ -57,7 +56,7 @@
         db_index=True,
     )
 
-    kuser_id = models.CharField(help_text="keystone user id", max_length=200) 
+    kuser_id = models.CharField(null=True, blank=True, help_text="keystone user id", max_length=200) 
     firstname = models.CharField(help_text="person's given name", max_length=200)
     lastname = models.CharField(help_text="person's surname", max_length=200)
 
@@ -96,27 +95,31 @@
         # Simplest possible answer: Yes, always
         return True
 
-    @property
-    def is_staff(self):
-        "Is the user a member of staff?"
-        # Simplest possible answer: All admins are staff
-        return self.is_admin
+    def get_roles(self):
+        from plstackapi.core.models.site import SitePrivilege
+        from plstackapi.core.models.slice import SliceMembership
 
+        site_privileges = SitePrivilege.objects.filter(user=self)
+        slice_memberships = SliceMembership.objects.filter(user=self)
+        roles = defaultdict(list)
+        for site_privilege in site_privileges:
+            roles[site_privilege.role.role_type].append(site_privilege.site.login_base)
+        for slice_membership in slice_memberships:
+            roles[slice_membership.role.role_type].append(slice_membership.slice.name)
+        return roles   
 
     def save(self, *args, **kwds):
-        if has_openstack:
-            if not hasattr(self, 'os_manager'):
-                setattr(self, 'os_manager', OpenStackManager())
-
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
             self.os_manager.save_user(self)
+
         if not self.id:
             self.set_password(self.password)    
         super(User, self).save(*args, **kwds)   
 
     def delete(self, *args, **kwds):
-        if has_openstack:
-            if not hasattr(self, 'os_manager'):
-                setattr(self, 'os_manager', OpenStackManager())
-
+        if not hasattr(self, 'os_manager'):
+            setattr(self, 'os_manager', OpenStackManager())
             self.os_manager.delete_user(self)
+
         super(User, self).delete(*args, **kwds)