Refactor to /opt/planetstack, final tweaks to make sure planetstack can run in non-openstack mode, adjustments to GUI for model focus changes
diff --git a/planetstack/core/models/__init__.py b/planetstack/core/models/__init__.py
new file mode 100644
index 0000000..4d9387b
--- /dev/null
+++ b/planetstack/core/models/__init__.py
@@ -0,0 +1,14 @@
+from .plcorebase import PlCoreBase
+from .deploymentnetwork import DeploymentNetwork
+from .site import Site
+from .site import SitePrivilege
+from .image import Image
+from .key import Key
+from .user import User
+from .role import Role
+from .node import Node
+from .slice import Slice
+from .slice import SliceMembership
+from .sliver import Sliver
+from .subnet import Subnet
+
diff --git a/planetstack/core/models/deploymentnetwork.py b/planetstack/core/models/deploymentnetwork.py
new file mode 100644
index 0000000..4068ee9
--- /dev/null
+++ b/planetstack/core/models/deploymentnetwork.py
@@ -0,0 +1,11 @@
+import os
+from django.db import models
+from core.models import PlCoreBase
+
+# Create your models here.
+
+class DeploymentNetwork(PlCoreBase):
+    name = models.CharField(max_length=200, unique=True, help_text="Name of the Deployment Network")
+
+    def __unicode__(self):  return u'%s' % (self.name)
+
diff --git a/planetstack/core/models/image.py b/planetstack/core/models/image.py
new file mode 100644
index 0000000..b4803e2
--- /dev/null
+++ b/planetstack/core/models/image.py
@@ -0,0 +1,13 @@
+import os
+from django.db import models
+from core.models import PlCoreBase
+
+# Create your models here.
+
+class Image(PlCoreBase):
+    image_id = models.CharField(max_length=256, unique=True)
+    name = models.CharField(max_length=256, unique=True)
+    disk_format = models.CharField(max_length=256)
+    container_format = models.CharField(max_length=256)
+
+    def __unicode__(self):  return u'%s' % (self.name)
diff --git a/planetstack/core/models/key.py b/planetstack/core/models/key.py
new file mode 100644
index 0000000..98cfb9b
--- /dev/null
+++ b/planetstack/core/models/key.py
@@ -0,0 +1,23 @@
+import os
+from django.db import models
+from core.models import PlCoreBase
+
+# Create your models here.
+
+class Key(PlCoreBase):
+    name = models.CharField(max_length=256, unique=True)
+    nkey_id = models.CharField(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 save(self, *args, **kwds):
+        self.os_manager.save_key(self)
+        super(Key, self).save(*args, **kwds)
+
+    def delete(self, *args, **kwds):
+        self.os_manager.delete_key(self)
+        super(Key, self).delete(*args, **kwds) 
+    
diff --git a/planetstack/core/models/node.py b/planetstack/core/models/node.py
new file mode 100644
index 0000000..a249628
--- /dev/null
+++ b/planetstack/core/models/node.py
@@ -0,0 +1,14 @@
+import os
+from django.db import models
+from core.models import PlCoreBase
+from core.models import Site
+from core.models import DeploymentNetwork
+
+# Create your models here.
+
+class Node(PlCoreBase):
+    name = models.CharField(max_length=200, unique=True, help_text="Name of the Node")
+    site  = models.ForeignKey(Site, related_name='nodes')
+    deploymentNetwork  = models.ForeignKey(DeploymentNetwork, related_name='nodes')
+
+    def __unicode__(self):  return u'%s' % (self.name)
diff --git a/planetstack/core/models/plcorebase.py b/planetstack/core/models/plcorebase.py
new file mode 100644
index 0000000..52aa0f7
--- /dev/null
+++ b/planetstack/core/models/plcorebase.py
@@ -0,0 +1,14 @@
+import os
+from django.db import models
+
+class PlCoreBase(models.Model):
+
+    created = models.DateTimeField(auto_now_add=True)
+    updated = models.DateTimeField(auto_now=True)
+
+    class Meta:
+        abstract = True
+        app_label = "core"
+
+
+
diff --git a/planetstack/core/models/role.py b/planetstack/core/models/role.py
new file mode 100644
index 0000000..b3611c1
--- /dev/null
+++ b/planetstack/core/models/role.py
@@ -0,0 +1,22 @@
+import os
+import datetime
+from django.db import models
+from core.models import PlCoreBase
+
+class Role(PlCoreBase):
+
+    #ROLE_CHOICES = (('admin', 'Admin'), ('pi', 'Principle Investigator'), ('user','User'))
+    role_id = models.CharField(max_length=256, unique=True)
+    role_type = models.CharField(max_length=80, unique=True)
+
+    def __unicode__(self):  return u'%s' % (self.role_type)
+
+
+    def save(self, *args, **kwds):
+        self.os_manager.save_role(self)
+        super(Role, self).save(*args, **kwds)
+    
+    def delete(self, *args, **kwds):
+        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
new file mode 100644
index 0000000..ebf2ab9
--- /dev/null
+++ b/planetstack/core/models/site.py
@@ -0,0 +1,49 @@
+import os
+from django.db import models
+from core.models import PlCoreBase
+from core.models import DeploymentNetwork
+
+
+class Site(PlCoreBase):
+
+    tenant_id = models.CharField(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")
+    longitude = models.FloatField(null=True, blank=True)
+    latitude = models.FloatField(null=True, blank=True)
+    login_base = models.CharField(max_length=50, unique=True, help_text="Prefix for Slices associated with this Site")
+    is_public = models.BooleanField(default=True, help_text="Indicates the visibility of this site to other members")
+    abbreviated_name = models.CharField(max_length=80)
+
+    deployments = models.ManyToManyField(DeploymentNetwork, blank=True, related_name='sites')
+
+    def __unicode__(self):  return u'%s' % (self.name)
+
+    def save(self, *args, **kwds):
+        self.os_manager.save_site(self)
+        super(Site, self).save(*args, **kwds)               
+
+
+    def delete(self, *args, **kwds):
+        self.os_manager.delete_site(self)
+        super(Site, self).delete(*args, **kwds)         
+        
+
+class SitePrivilege(PlCoreBase):
+
+    user = models.ForeignKey('User', related_name='site_privileges')
+    site = models.ForeignKey('Site', related_name='site_privileges')
+    role = models.ForeignKey('Role')
+
+    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)
+        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)
+        super(SitePrivilege, self).delete(*args, **kwds)
+
+
diff --git a/planetstack/core/models/slice.py b/planetstack/core/models/slice.py
new file mode 100644
index 0000000..539be24
--- /dev/null
+++ b/planetstack/core/models/slice.py
@@ -0,0 +1,51 @@
+import os
+from django.db import models
+from core.models import PlCoreBase
+from core.models import Site
+from core.models import User
+from core.models import Role
+from core.models import DeploymentNetwork
+
+# Create your models here.
+
+class Slice(PlCoreBase):
+    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")
+
+    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)
+
+
+    def __unicode__(self):  return u'%s' % (self.name)
+
+    def save(self, *args, **kwds):
+        self.os_manager.save_slice(self)
+        super(Slice, self).save(*args, **kwds)
+
+    def delete(self, *args, **kwds):
+        self.os_manager.delete_slice(self)
+        super(Slice, self).delete(*args, **kwds)    
+
+class SliceMembership(PlCoreBase):
+    user = models.ForeignKey('User', related_name='slice_memberships')
+    slice = models.ForeignKey('Slice', related_name='slice_memberships')
+    role = models.ForeignKey('Role')
+
+    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)
+        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)
+        super(SliceMembership, self).delete(*args, **kwds)
diff --git a/planetstack/core/models/sliver.py b/planetstack/core/models/sliver.py
new file mode 100644
index 0000000..580c2af
--- /dev/null
+++ b/planetstack/core/models/sliver.py
@@ -0,0 +1,37 @@
+import os
+from django.db import models
+from django.core import exceptions
+from core.models import PlCoreBase
+from core.models import Image
+from core.models import Key
+from core.models import Slice
+from core.models import Node
+from core.models import Site
+from core.models import DeploymentNetwork
+
+# Create your models here.
+class Sliver(PlCoreBase):
+    instance_id = models.CharField(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)
+    image = models.ForeignKey(Image, related_name='slivers')
+    key = models.ForeignKey(Key, related_name='slivers')
+    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)
+
+
+    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)
+        super(Sliver, self).save(*args, **kwds)
+
+    def delete(self, *args, **kwds):
+        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
new file mode 100644
index 0000000..cad9fea
--- /dev/null
+++ b/planetstack/core/models/subnet.py
@@ -0,0 +1,25 @@
+import os
+import commands    
+from django.db import models
+from core.models import PlCoreBase
+from core.models import Slice
+
+# Create your models here.
+
+class Subnet(PlCoreBase):
+    subnet_id = models.CharField(max_length=256, unique=True)
+    cidr = models.CharField(max_length=20)
+    ip_version = models.IntegerField()
+    start = models.IPAddressField()
+    end = models.IPAddressField()
+    slice = models.ForeignKey(Slice, related_name='subnet')
+
+    def __unicode__(self):  return u'%s' % (self.slice.name)
+
+    def save(self, *args, **kwds):
+        self.os_manager.save_subnet(self)
+        super(Subnet, self).save(*args, **kwds)
+
+    def delete(self, *args, **kwds):
+        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
new file mode 100644
index 0000000..6c776b1
--- /dev/null
+++ b/planetstack/core/models/user.py
@@ -0,0 +1,122 @@
+import os
+import datetime
+from django.db import models
+from core.models import PlCoreBase
+from core.models import Site
+from core.models import Key
+from openstack.manager import OpenStackManager
+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):
+        """
+        Creates and saves a User with the given email, date of
+        birth and password.
+        """
+        if not email:
+            raise ValueError('Users must have an email address')
+
+        user = self.model(
+            email=UserManager.normalize_email(email),
+            firstname=firstname,
+            lastname=lastname,
+            password=password
+        )
+        #user.set_password(password)
+        user.is_admin = True
+        user.save(using=self._db)
+        return user
+
+    def create_superuser(self, email, firstname, lastname, password):
+        """
+        Creates and saves a superuser with the given email, date of
+        birth and password.
+        """
+        user = self.create_user(email,
+            password=password,
+            firstname=firstname,
+            lastname=lastname
+        )
+        user.is_admin = True
+        user.save(using=self._db)
+        return user
+
+
+class User(AbstractBaseUser):
+
+    class Meta:
+        app_label = "core"
+
+    email = models.EmailField(
+        verbose_name='email address',
+        max_length=255,
+        unique=True,
+        db_index=True,
+    )
+
+    kuser_id = models.CharField(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)
+
+    phone = models.CharField(null=True, blank=True, help_text="phone number contact", max_length=100)
+    user_url = models.URLField(null=True, blank=True)
+    site = models.ForeignKey(Site, related_name='users', verbose_name="Site this user will be homed too", null=True)
+    key = models.ForeignKey(Key, related_name='user', null=True, blank=True)
+
+    is_active = models.BooleanField(default=True)
+    is_admin = models.BooleanField(default=True)
+    is_staff = models.BooleanField(default=True)
+
+    objects = UserManager()
+
+    USERNAME_FIELD = 'email'
+    REQUIRED_FIELDS = ['firstname', 'lastname']
+
+    def get_full_name(self):
+        # The user is identified by their email address
+        return self.email
+
+    def get_short_name(self):
+        # The user is identified by their email address
+        return self.email
+
+    def __unicode__(self):
+        return self.email
+
+    def has_perm(self, perm, obj=None):
+        "Does the user have a specific permission?"
+        # Simplest possible answer: Yes, always
+        return True
+
+    def has_module_perms(self, app_label):
+        "Does the user have permissions to view the app `app_label`?"
+        # 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 save(self, *args, **kwds):
+        if has_openstack:
+            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())
+
+            self.os_manager.delete_user(self)
+        super(User, self).delete(*args, **kwds)