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/__init__.py b/planetstack/core/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/planetstack/core/__init__.py
diff --git a/planetstack/core/admin.py b/planetstack/core/admin.py
new file mode 100644
index 0000000..6a8b71e
--- /dev/null
+++ b/planetstack/core/admin.py
@@ -0,0 +1,387 @@
+from core.models import Site
+from core.models import *
+from openstack.manager import OpenStackManager
+
+from django.contrib import admin
+from django.contrib.auth.models import Group
+from django import forms
+from django.utils.safestring import mark_safe
+from django.contrib.auth.admin import UserAdmin
+from django.contrib.admin.widgets import FilteredSelectMultiple
+from django.contrib.auth.forms import ReadOnlyPasswordHashField
+from django.contrib.auth.signals import user_logged_in 
+
+
+class ReadonlyTabularInline(admin.TabularInline):
+    can_delete = False
+    extra = 0
+    editable_fields = []
+
+    def get_readonly_fields(self, request, obj=None):
+        fields = []
+        for field in self.model._meta.get_all_field_names():
+            if (not field == 'id'):
+                if (field not in self.editable_fields):
+                    fields.append(field)
+        return fields
+
+    def has_add_permission(self, request):
+        return False
+
+class SliverInline(admin.TabularInline):
+    model = Sliver
+    fields = ['ip', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
+    extra = 0
+
+class SiteInline(admin.TabularInline):
+    model = Site
+    extra = 0
+
+class UserInline(admin.TabularInline):
+    model = User
+    extra = 0
+
+class SliceInline(admin.TabularInline):
+    model = Slice
+    extra = 0
+
+class UserInline(admin.TabularInline):
+    model = User
+    extra = 0
+
+class RoleInline(admin.TabularInline):
+    model = Role
+    extra = 0 
+
+class NodeInline(admin.TabularInline):
+    model = Node
+    extra = 0
+
+class PlainTextWidget(forms.Widget):
+    def render(self, _name, value, attrs):
+        return mark_safe(value) if value is not None else ''
+
+class PlanetStackBaseAdmin(admin.ModelAdmin):
+    save_on_top = False
+
+class OSModelAdmin(PlanetStackBaseAdmin):
+    """Attach client connection to openstack on delete() and save()"""
+
+    def save_model(self, request, obj, form, change):
+        auth = request.session.get('auth', {})
+        #auth['tenant'] = request.user.site.login_base
+        obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
+        obj.save()
+
+    def delete_model(self, request, obj):
+        auth = request.session.get('auth', {})
+        #auth['tenant'] = request.user.site.login_base
+        obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
+        obj.delete() 
+
+class RoleAdmin(OSModelAdmin):
+    fieldsets = [
+        ('Role', {'fields': ['role_type']})
+    ]
+    list_display = ('role_type',)
+
+
+class DeploymentNetworkAdminForm(forms.ModelForm):
+    sites = forms.ModelMultipleChoiceField(
+        queryset=Site.objects.all(),
+        required=False,
+        widget=FilteredSelectMultiple(
+            verbose_name=('Sites'), is_stacked=False
+        )
+    )
+    class Meta:
+        model = DeploymentNetwork
+
+    def __init__(self, *args, **kwargs):
+        super(DeploymentNetworkAdminForm, self).__init__(*args, **kwargs)
+
+        if self.instance and self.instance.pk:
+            self.fields['sites'].initial = self.instance.sites.all()
+
+    def save(self, commit=True):
+        deploymentNetwork = super(DeploymentNetworkAdminForm, self).save(commit=False)
+        if commit:
+            deploymentNetwork.save()
+
+        if deploymentNetwork.pk:
+            deploymentNetwork.sites = self.cleaned_data['sites']
+            self.save_m2m()
+
+        return deploymentNetwork
+
+class DeploymentNetworkAdmin(PlanetStackBaseAdmin):
+    form = DeploymentNetworkAdminForm
+    inlines = [NodeInline,]
+
+    def get_formsets(self, request, obj=None):
+        for inline in self.get_inline_instances(request, obj):
+            # hide MyInline in the add view
+            if obj is None:
+                continue
+            # give inline object access to driver and caller
+            auth = request.session.get('auth', {})
+            auth['tenant'] = request.user.site.login_base
+            inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
+            yield inline.get_formset(request, obj)
+
+class SiteAdmin(OSModelAdmin):
+    fieldsets = [
+        (None, {'fields': ['name', 'site_url', 'enabled', 'is_public', 'login_base']}),
+        ('Location', {'fields': ['latitude', 'longitude']}),
+        ('Deployment Networks', {'fields': ['deployments']})
+    ]
+    list_display = ('name', 'login_base','site_url', 'enabled')
+    filter_horizontal = ('deployments',)
+    inlines = [NodeInline, UserInline]
+    search_fields = ['name']
+
+    def get_formsets(self, request, obj=None):
+        for inline in self.get_inline_instances(request, obj):
+            # hide MyInline in the add view
+            if obj is None:
+                continue
+            # give inline object access to driver and caller
+            auth = request.session.get('auth', {})
+            #auth['tenant'] = request.user.site.login_base
+            inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
+            yield inline.get_formset(request, obj)
+
+class SitePrivilegeAdmin(PlanetStackBaseAdmin):
+    fieldsets = [
+        (None, {'fields': ['user', 'site', 'role']})
+    ]
+    list_display = ('user', 'site', 'role')
+
+    def save_model(self, request, obj, form, change):
+        # update openstack connection to use this site/tenant   
+        auth = request.session.get('auth', {})
+        #auth['tenant'] = obj.site.login_base
+        obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
+        obj.save()
+
+    def delete_model(self, request, obj):
+        # update openstack connection to use this site/tenant   
+        auth = request.session.get('auth', {})
+        #auth['tenant'] = obj.site.login_base
+        obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
+        obj.delete()
+
+class KeyAdmin(OSModelAdmin):
+    fieldsets = [
+        ('Key', {'fields': ['name', 'key', 'type', 'blacklisted']})
+    ]
+    list_display = ['name', 'key', 'type', 'blacklisted']
+
+    def get_queryset(self, request):
+        # get keys user is allowed to see
+        qs = super(KeyAdmin, self).get_queryset(request)
+        if request.user.is_superuser:
+            return qs
+        # users can only see their own keys
+        return qs.filter(user=request.user)  
+        
+
+class SliceAdmin(OSModelAdmin):
+    fields = ['name', 'site', 'serviceClass', 'description', 'slice_url']
+    list_display = ('name', 'site','serviceClass', 'slice_url')
+    inlines = [SliverInline]
+
+    def get_formsets(self, request, obj=None):
+        for inline in self.get_inline_instances(request, obj):
+            # hide MyInline in the add view
+            if obj is None:
+                continue
+            # give inline object access to driver and caller
+            auth = request.session.get('auth', {})
+            auth['tenant'] = obj.name       # meed to connect using slice's tenant
+            inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
+            yield inline.get_formset(request, obj)
+
+    def get_queryset(self, request):
+        qs = super(SliceAdmin, self).get_queryset(request)
+        if request.user.is_superuser:
+            return qs
+        # users can only see slices at their site
+        return qs.filter(site=request.user.site) 
+
+class SliceMembershipAdmin(PlanetStackBaseAdmin):
+    fieldsets = [
+        (None, {'fields': ['user', 'slice', 'role']})
+    ]
+    list_display = ('user', 'slice', 'role')
+
+    def save_model(self, request, obj, form, change):
+        # update openstack connection to use this site/tenant
+        auth = request.session.get('auth', {})
+        auth['tenant'] = obj.slice.name
+        obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
+        obj.save()
+
+    def delete_model(self, request, obj):
+        # update openstack connection to use this site/tenant
+        auth = request.session.get('auth', {})
+        auth['tenant'] = obj.slice.name
+        obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
+        obj.delete()
+
+
+class SubnetAdmin(PlanetStackBaseAdmin):
+    fields = ['cidr', 'ip_version', 'start', 'end', 'slice']
+    list_display = ('slice','cidr', 'start', 'end', 'ip_version')
+
+    def save_model(self, request, obj, form, change):
+        # update openstack connection to use this site/tenant
+        auth = request.session.get('auth', {})
+        auth['tenant'] = obj.slice.name
+        obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
+        obj.save()
+
+    def delete_model(self, request, obj):
+        # update openstack connection to use this site/tenant
+        auth = request.session.get('auth', {})
+        auth['tenant'] = obj.slice.name
+        obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
+        obj.delete()
+
+class ImageAdmin(admin.ModelAdmin):
+    fields = ['image_id', 'name', 'disk_format', 'container_format']
+
+class NodeAdmin(admin.ModelAdmin):
+    list_display = ('name', 'site', 'deploymentNetwork')
+    list_filter = ('deploymentNetwork',)
+
+
+class SliverForm(forms.ModelForm):
+    class Meta:
+        ip = forms.CharField(widget=PlainTextWidget)
+        instance_name = forms.CharField(widget=PlainTextWidget)
+        model = Sliver
+        widgets = {
+            'ip': PlainTextWidget(),
+            'instance_name': PlainTextWidget(),
+        }
+
+class SliverAdmin(PlanetStackBaseAdmin):
+    form = SliverForm
+    fieldsets = [
+        ('Sliver', {'fields': ['ip', 'instance_name', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']})
+    ]
+    list_display = ['ip', 'instance_name', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
+
+    def save_model(self, request, obj, form, change):
+        # update openstack connection to use this site/tenant
+        auth = request.session.get('auth', {})
+        auth['tenant'] = obj.slice.name
+        obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
+        obj.save()
+
+    def delete_model(self, request, obj):
+        # update openstack connection to use this site/tenant
+        auth = request.session.get('auth', {})
+        auth['tenant'] = obj.slice.name
+        obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
+        obj.delete()
+
+class UserCreationForm(forms.ModelForm):
+    """A form for creating new users. Includes all the required
+    fields, plus a repeated password."""
+    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
+    password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
+
+    class Meta:
+        model = User
+        fields = ('email', 'firstname', 'lastname', 'phone', 'key', 'site')
+
+    def clean_password2(self):
+        # Check that the two password entries match
+        password1 = self.cleaned_data.get("password1")
+        password2 = self.cleaned_data.get("password2")
+        if password1 and password2 and password1 != password2:
+            raise forms.ValidationError("Passwords don't match")
+        return password2
+
+    def save(self, commit=True):
+        # Save the provided password in hashed format
+        user = super(UserCreationForm, self).save(commit=False)
+        user.password = self.cleaned_data["password1"]
+        #user.set_password(self.cleaned_data["password1"])
+        if commit:
+            user.save()
+        return user
+
+
+class UserChangeForm(forms.ModelForm):
+    """A form for updating users. Includes all the fields on
+    the user, but replaces the password field with admin's
+    password hash display field.
+    """
+    password = ReadOnlyPasswordHashField()
+
+    class Meta:
+        model = User
+
+    def clean_password(self):
+        # Regardless of what the user provides, return the initial value.
+        # This is done here, rather than on the field, because the
+        # field does not have access to the initial value
+        return self.initial["password"]
+
+
+class UserAdmin(UserAdmin, OSModelAdmin):
+    class Meta:
+        app_label = "core"
+
+    # The forms to add and change user instances
+    form = UserChangeForm
+    add_form = UserCreationForm
+
+    # The fields to be used in displaying the User model.
+    # These override the definitions on the base UserAdmin
+    # that reference specific fields on auth.User.
+    list_display = ('email', 'site', 'firstname', 'lastname', 'last_login')
+    list_filter = ('site',)
+    fieldsets = (
+        (None, {'fields': ('email', 'password')}),
+        ('Personal info', {'fields': ('firstname','lastname','phone','site', 'key')}),
+        #('Important dates', {'fields': ('last_login',)}),
+    )
+    add_fieldsets = (
+        (None, {
+            'classes': ('wide',),
+            'fields': ('email', 'firstname', 'lastname', 'phone', 'site', 'password1', 'password2', 'key')}
+        ),
+    )
+    search_fields = ('email',)
+    ordering = ('email',)
+    filter_horizontal = ()
+
+# register a signal that caches the user's credentials when they log in
+def cache_credentials(sender, user, request, **kwds):
+    auth = {'username': request.POST['username'],
+            'password': request.POST['password']}
+    request.session['auth'] = auth
+user_logged_in.connect(cache_credentials)
+
+# Now register the new UserAdmin...
+admin.site.register(User, UserAdmin)
+# ... and, since we're not using Django's builtin permissions,
+# unregister the Group model from admin.
+admin.site.unregister(Group)
+
+admin.site.register(Site, SiteAdmin)
+#admin.site.register(SitePrivilege, SitePrivilegeAdmin)
+admin.site.register(Slice, SliceAdmin)
+#admin.site.register(SliceMembership, SliceMembershipAdmin)
+admin.site.register(Subnet, SubnetAdmin)
+#admin.site.register(Image, ImageAdmin)
+#admin.site.register(Node, NodeAdmin)
+admin.site.register(Sliver, SliverAdmin)
+admin.site.register(Key, KeyAdmin)
+#admin.site.register(Role, RoleAdmin)
+admin.site.register(DeploymentNetwork, DeploymentNetworkAdmin)
+
diff --git a/planetstack/core/api/__init__.py b/planetstack/core/api/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/planetstack/core/api/__init__.py
diff --git a/planetstack/core/api/auth.py b/planetstack/core/api/auth.py
new file mode 100644
index 0000000..8796f14
--- /dev/null
+++ b/planetstack/core/api/auth.py
@@ -0,0 +1,8 @@
+from openstack.client import OpenStackClient
+
+def auth_check(username, password, tenant):
+    client = OpenStackClient(username=username,
+                             password=password,
+                             tenant=tenant)
+    client.authenticate()
+    return client
diff --git a/planetstack/core/api/deployment_networks.py b/planetstack/core/api/deployment_networks.py
new file mode 100644
index 0000000..51fa03e
--- /dev/null
+++ b/planetstack/core/api/deployment_networks.py
@@ -0,0 +1,39 @@
+from types import StringTypes
+from openstack.client import OpenStackClient
+from openstack.driver import OpenStackDriver
+from core.api.auth import auth_check
+from core.models import DeploymentNetwork
+
+def _get_deployment_networks(filter):
+    if isinstance(filter, StringTypes) and filter.isdigit():
+        filter = int(filter)
+    if isinstance(filter, int):
+        deployment_networks = DeploymentNetwork.objects.filter(id=filter)
+    elif isinstance(filter, StringTypes):
+        deployment_networks = DeploymentNetwork.objects.filter(name=filter)
+    elif isinstance(filter, dict):
+        deployment_networks = DeploymentNetwork.objects.filter(**filter)
+    else:
+        deployment_networks = []
+    return deployment_networks 
+
+def add_deployment_network(auth, name):
+    auth_check(auth)    
+    deployment = DeploymentNetwork(name=name)
+    deployment.save()
+    return deployment
+
+def delete_deployment_network(auth, filter={}):
+    auth_check(auth)   
+    deployments = _get_deployment_networks(filter)
+    for deployment in deployments:
+        deployment.delete()
+    return 1
+
+def get_deployment_networks(auth, filter={}):
+    auth_check(auth)   
+    deployments = _get_deployment_networks(filter)
+    return deployments             
+        
+
+    
diff --git a/planetstack/core/api/images.py b/planetstack/core/api/images.py
new file mode 100644
index 0000000..c080a55
--- /dev/null
+++ b/planetstack/core/api/images.py
@@ -0,0 +1,34 @@
+from types import StringTypes
+from openstack.client import OpenStackClient
+from openstack.driver import OpenStackDriver
+from core.api.auth import auth_check
+from core.models import Image
+ 
+def _get_images(filter):
+    if isinstance(filter, StringTypes) and filter.isdigit():
+        filter = int(filter)
+    if isinstance(filter, int):
+        images = Image.objects.filter(id=filter)
+    elif isinstance(filter, StringTypes):
+        images = Image.objects.filter(name=filter)
+    elif isinstance(filter, dict):
+        images = Image.objects.filter(**filter)
+    else:
+        images = []
+    return images
+
+def add_image(auth, fields={}):
+    """not implemented"""
+    return 
+
+def delete_image(auth, filter={}):
+    """not implemented"""
+    return 1
+
+def get_images(auth, filter={}):
+    auth_check(auth)   
+    images = _get_images(filter)
+    return images             
+        
+
+    
diff --git a/planetstack/core/api/keys.py b/planetstack/core/api/keys.py
new file mode 100644
index 0000000..e653690
--- /dev/null
+++ b/planetstack/core/api/keys.py
@@ -0,0 +1,51 @@
+from types import StringTypes
+from openstack.client import OpenStackClient
+from openstack.driver import OpenStackDriver
+from core.models import Key
+from core.api.auth import auth_check
+from core.api.users import _get_users
+
+
+def _get_keys(filter):
+    if isinstance(filter, StringTypes) and filter.isdigit():
+        filter = int(filter)
+    if isinstance(filter, int):
+        keys = Key.objects.filter(id=filter)
+    elif isinstance(filter, StringTypes):
+        keys = Key.objects.filter(name=filter)
+    elif isinstance(filter, dict):
+        keys = Key.objects.filter(**filter)
+    else:
+        keys = []
+    return keys 
+
+def add_key(auth, fields):
+    driver = OpenStackDriver(client = auth_check(auth))
+    users = _get_users(fields.get('user')) 
+    if users: fields['user'] = users[0]    
+    key = Key(**fields)
+    nova_fields = {'name': key.name,
+                   'key': key.key} 
+    nova_key = driver.create_keypair(**nova_fields)
+    key.nkey_id = nova_key.id
+    key.save()
+    return key
+
+def update_key(auth, id, **fields):
+    return  
+
+def delete_key(auth, filter={}):
+    driver = OpenStackDriver(client = auth_check(auth))   
+    keys = _get_keys(filter)
+    for key in keys:
+        driver.delete_keypair(id=key.nkey_id) 
+        key.delete()
+    return 1
+
+def get_keys(auth, filter={}):
+    client = auth_check(auth)
+    keys = _get_keys(filter)
+    return keys             
+        
+
+    
diff --git a/planetstack/core/api/nodes.py b/planetstack/core/api/nodes.py
new file mode 100644
index 0000000..6514e54
--- /dev/null
+++ b/planetstack/core/api/nodes.py
@@ -0,0 +1,37 @@
+from types import StringTypes
+from openstack.client import OpenStackClient
+from openstack.driver import OpenStackDriver
+from core.api.auth import auth_check
+from core.models import Node
+ 
+def _get_nodes(filter):
+    if isinstance(filter, StringTypes) and filter.isdigit():
+        filter = int(filter)
+    if isinstance(filter, int):
+        nodes = Node.objects.filter(id=filter)
+    elif isinstance(filter, StringTypes):
+        nodes = Node.objects.filter(name=filter)
+    elif isinstance(filter, dict):
+        nodes = Node.objects.filter(**filter)
+    else:
+        nodes = []
+    return nodes
+
+def add_node(auth, fields={}):
+    """not implemented"""
+    return 
+
+def delete_node(auth, filter={}):
+    """not implemented"""
+    return 1
+
+def update_node(auth, id, fields={}):
+    return 
+
+def get_nodes(auth, filter={}):
+    auth_check(auth)   
+    nodes = _get_nodes(filter)
+    return nodes             
+        
+
+    
diff --git a/planetstack/core/api/roles.py b/planetstack/core/api/roles.py
new file mode 100644
index 0000000..a799c01
--- /dev/null
+++ b/planetstack/core/api/roles.py
@@ -0,0 +1,39 @@
+from types import StringTypes
+from openstack.client import OpenStackClient
+from openstack.driver import OpenStackDriver
+from core.api.auth import auth_check
+from core.models import Role
+ 
+
+def _get_roles(filter):
+    if isinstance(filter, StringTypes) and filter.isdigit():
+        filter = int(filter)
+    if isinstance(filter, int):
+        roles = Role.objects.filter(id=filter)
+    elif isinstance(filter, StringTypes):
+        roles = Role.objects.filter(role_type=filter)
+    elif isinstance(filter, dict):
+        roles = Role.objects.filter(**filter)
+    else:
+        roles = []
+    return roles
+
+def add_role(auth, name):
+    driver = OpenStackDriver(client = auth_check(auth))    
+    keystone_role = driver.create_role(name=name)
+    role = Role(role_type=name, role_id=keystone_role.id)
+    role.save()
+    return role
+
+def delete_role(auth, filter={}):
+    driver = OpenStackDriver(client = auth_check(auth))   
+    roles = _get_roles(filter) 
+    for role in roles:
+        driver.delete_role({'id': role.role_id}) 
+        role.delete()
+    return 1
+
+def get_roles(auth, filter={}):
+    client = auth_check(auth)
+    return _get_roles(filter)             
+        
diff --git a/planetstack/core/api/site_privileges.py b/planetstack/core/api/site_privileges.py
new file mode 100644
index 0000000..85a8a83
--- /dev/null
+++ b/planetstack/core/api/site_privileges.py
@@ -0,0 +1,72 @@
+from types import StringTypes
+import re
+from openstack.client import OpenStackClient
+from openstack.driver import OpenStackDriver
+from core.api.auth import auth_check
+from core.models import SitePrivilege
+from core.api.users import _get_users
+from core.api.sites import _get_sites
+from core.api.roles import _get_roles
+
+
+def _get_site_privileges(filter):
+    if isinstance(filter, StringTypes) and filter.isdigit():
+        filter = int(filter)
+    if isinstance(filter, int):
+        site_privileges = SitePrivilege.objects.filter(id=filter)
+    elif isinstance(filter, StringTypes):
+        site_privileges = SitePrivilege.objects.filter(name=filter)
+    elif isinstance(filter, dict):
+        site_privileges = SitePrivilege.objects.filter(**filter)
+    else:
+        site_privileges = []
+    return site_privileges
+ 
+def add_site_privilege(auth, fields):
+    driver = OpenStackDriver(client = auth_check(auth))
+    users = _get_user(fields.get('user')) 
+    sites = _get_slice(fields.get('site')) 
+    roles = _get_role(fields.get('role'))
+    
+    if users: fields['user'] = users[0]     
+    if slices: fields['site'] = sites[0] 
+    if roles: fields['role'] = roles[0]
+ 
+    site_privilege = SitePrivilege(**fields)
+
+    # update nova role
+    driver.add_user_role(site_privilege.user.kuser_id, 
+                         site_privilege.site.tenant_id, 
+                         site_privilege.role.name)
+    
+    site_privilege.save()
+    return site_privilege
+
+def update_site_privilege(auth, id, **fields):
+    return  
+
+def delete_site_privilege(auth, filter={}):
+    driver = OpenStackDriver(client = auth_check(auth))   
+    site_privileges = _get_site_privileges(filter)
+    for site_privilege in site_privileges:
+        driver.delete_user_role(kuser_id=site_privilege.user.id,
+                                tenant_id = site_privilege.site.tenant_id,
+                                role_name = site_privilege.role.name) 
+        site_privilege.delete()
+    return 1
+
+def get_site_privileges(auth, filter={}):
+    client = auth_check(auth)
+    users = _get_users(filter.get('user'))
+    sites = _get_slices(filter.get('site'))
+    roles = _get_roles(filter.get('role'))
+
+    if users: filter['user'] = users[0]
+    if sites: filter['site'] = sites[0]
+    if roles: filter['role'] = roles[0]
+    
+    site_privileges = _get_site_privileges(filter)
+    return site_privileges             
+        
+
+    
diff --git a/planetstack/core/api/sites.py b/planetstack/core/api/sites.py
new file mode 100644
index 0000000..cfca6cf
--- /dev/null
+++ b/planetstack/core/api/sites.py
@@ -0,0 +1,62 @@
+from types import StringTypes
+from openstack.client import OpenStackClient
+from openstack.driver import OpenStackDriver
+from core.api.auth import auth_check
+from core.models import Site
+
+
+def _get_sites(filter):
+    if isinstance(filter, StringTypes) and filter.isdigit():
+        filter = int(filter)
+    if isinstance(filter, int):
+        sites = Site.objects.filter(id=filter)
+    elif isinstance(filter, StringTypes):
+        sites = Site.objects.filter(login_base=filter)
+    elif isinstance(filter, dict):
+        sites = Site.objects.filter(**filter)
+    else:
+        sites = []
+    return sites 
+
+def add_site(auth, fields):
+    driver = OpenStackDriver(client = auth_check(auth))
+    site = Site(**fields)
+    nova_fields = {'tenant_name': site.login_base,
+                   'description': site.name,
+                   'enabled': site.enabled}    
+    tenant = driver.create_tenant(**nova_fields)
+    site.tenant_id=tenant.id
+    site.save()
+    return site
+
+def update_site(auth, id, **fields):
+    driver = OpenStackDriver(client = auth_check(auth))
+    sites = _get_sites(id)
+    if not sites:
+        return
+
+    site = Site[0]
+    nova_fields = {}
+    if 'description' in fields:
+        nova_fields['description'] = fields['name']
+    if 'enabled' in fields:
+        nova_fields['enabled'] = fields['enabled']
+    driver.update_tenant(site.tenant_id, **nova_fields)
+    site.update(**fields)
+    return site 
+
+def delete_site(auth, filter={}):
+    driver = OpenStackDriver(client = auth_check(auth))   
+    sites = _get_sites(id)
+    for site in sites:
+        driver.delete_tenant(id=site.tenant_id) 
+        site.delete()
+    return 1
+
+def get_sites(auth, filter={}):
+    client = auth_check(auth)
+    sites = _get_sites(filter)
+    return sites             
+        
+
+    
diff --git a/planetstack/core/api/slice_memberships.py b/planetstack/core/api/slice_memberships.py
new file mode 100644
index 0000000..77d79bf
--- /dev/null
+++ b/planetstack/core/api/slice_memberships.py
@@ -0,0 +1,71 @@
+from types import StringTypes
+from openstack.client import OpenStackClient
+from openstack.driver import OpenStackDriver
+from core.api.auth import auth_check
+from core.models import SliceMembership
+from core.api.users import _get_users
+from core.api.slices import _get_slices
+from core.api.roles import _get_roles
+
+def _get_slice_memberships(filter):
+    if isinstance(filter, StringTypes) and filter.isdigit():
+        filter = int(filter)
+    if isinstance(filter, int):
+        slice_memberships = SitePrivilege.objects.filter(id=filter)
+    elif isinstance(filter, StringTypes):
+        slice_memberships = SitePrivilege.objects.filter(name=filter)
+    elif isinstance(filter, dict):
+        slice_memberships = SitePrivilege.objects.filter(**filter)
+    else:
+        slice_memberships = []
+    return slice_memberships
+
+ 
+def add_slice_membership(auth, fields):
+    driver = OpenStackDriver(client = auth_check(auth))
+    users = _get_users(fields.get('user')) 
+    slices = _get_slices(fields.get('slice')) 
+    roles = _get_roles(fields.get('role'))
+    
+    if users: fields['user'] = users[0]     
+    if slices: fields['slice'] = slices[0] 
+    if roles: fields['role'] = roles[0]
+ 
+    slice_membership = SliceMembership(**fields)
+
+    # update nova role
+    driver.add_user_role(slice_membership.user.user_id, 
+                         slice_membership.slice.tenant_id, 
+                         slice_membership.role.name)
+    
+    slice_membership.save()
+    return slice_membership
+
+def update_slice_membership(auth, id, **fields):
+    return  
+
+def delete_slice_membership(auth, filter={}):
+    driver = OpenStackDriver(client = auth_check(auth))   
+    slice_memberships = _get_slice_memberships(filter)
+    for slice_membership in slice_memberships:
+        driver.delete_user_role(kuser_id=slice_membership.user.id,
+                                tenant_id = slice_membership.slice.tenant_id,
+                                role_name = slice_membership.role.name) 
+        slice_membership.delete()
+    return 1
+
+def get_slice_memberships(auth, filter={}):
+    client = auth_check(auth)
+    users = _get_users(fields.get('user'))
+    slices = _get_slices(fields.get('slice'))
+    roles = _get_roles(fields.get('role'))
+
+    if users: fields['user'] = users[0]
+    if slices: fields['slice'] = slices[0]
+    if roles: fields['role'] = roles[0]
+
+    slice_memberships = _get_slice_memberships(filter)
+    return slice_memberships             
+        
+
+    
diff --git a/planetstack/core/api/slices.py b/planetstack/core/api/slices.py
new file mode 100644
index 0000000..f03dd6f
--- /dev/null
+++ b/planetstack/core/api/slices.py
@@ -0,0 +1,93 @@
+import re
+from types import StringTypes
+from django.contrib.auth import authenticate
+from openstack.client import OpenStackClient
+from openstack.driver import OpenStackDriver
+from core.api.auth import auth_check
+from core.models import Slice
+from core.api.sites import _get_sites
+
+def _get_slices(filter):
+    if isinstance(filter, StringTypes) and filter.isdigit():
+        filter = int(filter)
+    if isinstance(filter, int):
+        slices = Slice.objects.filter(id=filter)
+    elif isinstance(filter, StringTypes):
+        slices = Slice.objects.filter(name=filter)
+    elif isinstance(filter, dict):
+        slices = Slice.objects.filter(**filter)
+    else:
+        slices = []
+    return slices
+    
+ 
+def add_slice(auth, fields):
+    driver = OpenStackDriver(client = auth_check(auth))
+    login_base = fields['name'][:fields['name'].find('_')]
+    sites = _get_sites(login_base) 
+    if sites: fields['site'] = sites[0]     
+    slice = Slice(**fields)
+   
+    # create tenant
+    nova_fields = {'tenant_name': slice.name,
+                   'description': slice.description,
+                   'enabled': slice.enabled}
+    tenant = driver.create_tenant(**nova_fields)
+    slice.tenant_id=tenant.id
+    
+    # create network
+    network = driver.create_network(slice.name)
+    slice.network_id = network['id']
+
+    # create router
+    router = driver.create_router(slice.name)
+    slice.router_id = router['id']    
+
+    slice.save()
+    return slice
+
+def update_slice(auth, id, **fields):
+    driver = OpenStackDriver(client = auth_check(auth))
+    slices = _get_slices(id)
+    if not slices:
+        return
+
+    # update tenant
+    slice = slices[0]
+    nova_fields = {}
+    if 'name' in fields:
+        nova_fields['tenant_name'] = fields['name']
+    if 'description' in fields:
+        nova_fields['description'] = fields['description']
+    if 'enabled' in fields:
+        nova_fields['enabled'] = fields['enabled']
+    driver.update_tenant(slice.tenant_id, **nova_fields)
+
+    # update db record 
+    sites = _get_sites(fields.get('site'))
+    if sites: fields['site'] = sites[0]
+    slice.update(**fields)
+
+    return slice 
+
+def delete_slice(auth, filter={}):
+    driver = OpenStackDriver(client = auth_check(auth))   
+    slices = _get_slices(id)
+    for slice in slices:
+        driver.delete_network(slice.network_id)
+        driver.delete_router(slice.router_id)
+        driver.delete_slice(id=slice.tenant_id) 
+        slice.delete()
+    return 1
+
+def get_slices(auth, filter={}):
+    user = authenticate(username=auth.get('username'),
+                        password=auth.get('password'))
+    if 'site' in filter:
+        sites = _get_sites(filter.get('site'))
+        if sites: filter['site'] = sites[0]
+    slices = _get_slices(filter)
+    return slices             
+        
+
+    
diff --git a/planetstack/core/api/slivers.py b/planetstack/core/api/slivers.py
new file mode 100644
index 0000000..e3244a4
--- /dev/null
+++ b/planetstack/core/api/slivers.py
@@ -0,0 +1,67 @@
+from types import StringTypes
+from django.contrib.auth import authenticate
+from openstack.client import OpenStackClient
+from openstack.driver import OpenStackDriver
+from core.api.auth import auth_check
+from core.models import Sliver, Slice
+from core.api.images import _get_images
+from core.api.keys import _get_keys
+from core.api.slices import _get_slices
+from core.api.deployment_networks import _get_deployment_networks
+from core.api.nodes import _get_nodes
+ 
+
+def _get_slivers(filter):
+    if isinstance(filter, StringTypes) and filter.isdigit():
+        filter = int(filter)
+    if isinstance(filter, int):
+        slivers = Sliver.objects.filter(id=filter)
+    elif isinstance(filter, StringTypes):
+        slivers = Sliver.objects.filter(name=filter)
+    elif isinstance(filter, dict):
+        slivers = Sliver.objects.filter(**filter)
+    else:
+        slivers = []
+    return slivers
+ 
+def add_sliver(auth, fields):
+    driver = OpenStackDriver(client = auth_check(auth))
+        
+    images = _get_images(fields.get('image'))
+    if images: fields['image'] = images[0]     
+    keys = _get_keys(fields.get('key'))
+    if keys: fields['key'] = keys[0]     
+    slices = _get_slices(fields.get('slice'))
+    if slices: 
+        fields['slice'] = slices[0]     
+    deployment_networks = _get_deployment_networks(fields.get('deploymentNetwork'))
+    if deployment_networks: fields['deploymentNetwork'] = deployment_networks[0]     
+    nodes = _get_nodes(fields.get('node'))
+    if nodes: fields['node'] = nodes[0]     
+    sliver = Sliver(**fields)
+    sliver.driver = driver    
+    sliver.save()
+    return sliver
+
+def update_sliver(auth, sliver, **fields):
+    return  
+
+def delete_sliver(auth, filter={}):
+    driver = OpenStackDriver(client = auth_check(auth))   
+    slivers = _get_slivers(filter)
+    for sliver in slivers:
+        sliver.driver = driver
+        sliver.delete()
+    return 1
+
+def get_slivers(auth, filter={}):
+    user = authenticate(username=auth.get('username'),
+                        password=auth.get('password'))
+    if 'slice' in filter:
+        slices = _get_slices(filter.get('slice'))
+        if slices: filter['slice'] = slices[0]
+    slivers = _get_slivers(filter)
+    return slivers             
+        
+
+    
diff --git a/planetstack/core/api/subnets.py b/planetstack/core/api/subnets.py
new file mode 100644
index 0000000..d618eda
--- /dev/null
+++ b/planetstack/core/api/subnets.py
@@ -0,0 +1,74 @@
+import commands
+from types import StringTypes
+from openstack.client import OpenStackClient
+from openstack.driver import OpenStackDriver
+from core.api.auth import auth_check
+from core.models import Subnet
+from core.api.slices import _get_slices
+
+
+def _get_subnets(filter):
+    if isinstance(filter, StringTypes) and filter.isdigit():
+        filter = int(filter)
+    if isinstance(filter, int):
+        subnets = Subnet.objects.filter(id=filter)
+    elif isinstance(filter, StringTypes):
+        # the name is the subnet's slice's name
+        slices = _get_slices(filter)
+        slice = None
+        if slices: slice=slices[0]
+        subnets = Subnet.objects.filter(slice=slice)
+    elif isinstance(filter, dict):
+        subnets = Subnet.objects.filter(**filter)
+    else:
+        subnets = []
+    return subnets
+
+def add_subnet(auth, fields):
+    driver = OpenStackDriver(client = auth_check(auth))
+    slices = _get_slices(fields.get('slice')) 
+    if slices: fields['slice'] = slices[0]     
+    subnet = Subnet(**fields)
+    # create quantum subnet
+    quantum_subnet = driver.create_subnet(name= subnet.slice.name,
+                                          network_id=subnet.slice.network_id,
+                                          cidr_ip = subnet.cidr,
+                                          ip_version=subnet.ip_version,
+                                          start = subnet.start,
+                                          end = subnet.end)
+    subnet.subnet_id=quantum_subnet['id']
+    ## set dns servers
+    #driver.update_subnet(subnet.id, {'dns_nameservers': ['8.8.8.8', '8.8.4.4']})
+
+    # add subnet as interface to slice's router
+    try: driver.add_router_interface(subnet.slice.router_id, subnet.subnet_id)
+    except: pass         
+    #add_route = 'route add -net %s dev br-ex gw 10.100.0.5' % self.cidr
+    commands.getstatusoutput(add_route)    
+    subnet.save()
+    return subnet
+
+def update_subnet(auth, subnet, **fields):
+    return  
+
+def delete_subnet(auth, filter={}):
+    driver = OpenStackDriver(client = auth_check(auth))   
+    subnets = Subnet.objects.filter(**filter)
+    for subnet in subnets:
+        driver.delete_router_interface(subnet.slice.router_id, subnet.subnet_id)
+        driver.delete_subnet(subnet.subnet_id) 
+        subnet.delete()
+        #del_route = 'route del -net %s' % subnet.cidr
+    commands.getstatusoutput(del_route)
+    return 1
+
+def get_subnets(auth, filter={}):
+    client = auth_check(auth)
+    if 'slice' in filter:
+        slice = _get_slice(filter.get('slice'))
+        if slice: filter['slice'] = slice
+    subnets = Subnet.objects.filter(**filter)
+    return subnets             
+        
+
+    
diff --git a/planetstack/core/api/users.py b/planetstack/core/api/users.py
new file mode 100644
index 0000000..3b157ac
--- /dev/null
+++ b/planetstack/core/api/users.py
@@ -0,0 +1,71 @@
+from types import StringTypes
+from openstack.client import OpenStackClient
+from openstack.driver import OpenStackDriver
+from core.api.auth import auth_check
+from core.models import User, Site
+from core.api.sites import _get_sites
+
+def _get_users(filter):
+    if isinstance(filter, StringTypes) and filter.isdigit():
+        filter = int(filter)
+    if isinstance(filter, int):
+        users = User.objects.filter(id=filter)
+    elif isinstance(filter, StringTypes):
+        users = User.objects.filter(email=filter)
+    elif isinstance(filter, dict):
+        users = User.objects.filter(**filter)
+    else:
+        users = []
+    return users 
+
+def add_user(auth, fields):
+    driver = OpenStackDriver(client = auth_check(auth))
+    sites = _get_sites(fields.get('site')) 
+    if sites: fields['site'] = sites[0]     
+    user = User(**fields)
+    nova_fields = {'name': user.email[:user.email.find('@')],
+                   'email': user.email, 
+                   'password': fields.get('password'),
+                   'enabled': user.enabled}    
+    nova_user = driver.create_user(**nova_fields)
+    #driver.add_user_user(user.id, user.site.tenant_id, 'user')
+    user.kuser_id=nova_user.id
+    user.save()
+    return user
+
+def update_user(auth, id, **fields):
+    driver = OpenStackDriver(client = auth_check(auth))
+    users = User.objects.filter(id=id)
+    if not users:
+        return
+
+    user = users[0]
+    nova_fields = {}
+    if 'email' in fields:
+        nova_fields['name'] = fields['email'][:self.email.find('@')]
+        nova_fields['email'] = fields['email']
+    if 'password' in fields:
+        nova_fields['password'] = fields['password']
+    if 'enabled' in fields:
+        nova_fields['enabled'] = fields['enabled']
+    driver.update_user(user.kuser_id, **nova_fields)
+    sites = _get_sites(fields.get('site'))
+    if sites: fields['site'] = sites[0]
+    user.update(**fields)
+    return user 
+
+def delete_user(auth, filter={}):
+    driver = OpenStackDriver(client = auth_check(auth))   
+    users = _get_users(filter)
+    for user in users:
+        driver.delete_user(id=user.kuser_id) 
+        user.delete()
+    return 1
+
+def get_users(auth, filter={}):
+    client = auth_check(auth)
+    users = _get_users(filter)
+    return users             
+        
+
+    
diff --git a/planetstack/core/api_root.py b/planetstack/core/api_root.py
new file mode 100644
index 0000000..61e76da
--- /dev/null
+++ b/planetstack/core/api_root.py
@@ -0,0 +1,18 @@
+from rest_framework.decorators import api_view
+from rest_framework.response import Response
+from rest_framework.reverse import reverse
+
+@api_view(['GET'])
+def api_root(request, format=None):
+    return Response({
+        'roles': reverse('role-list', request=request, format=format),
+        'users': reverse('user-list', request=request, format=format),
+        'keys': reverse('key-list', request=request, format=format),
+        #'nodes': reverse('node-list', request=request, format=format),
+        'sites': reverse('site-list', request=request, format=format),
+        'deploymentNetworks': reverse('deploymentnetwork-list', request=request, format=format),
+        'slices': reverse('slice-list', request=request, format=format),
+        'subnets': reverse('subnet-list', request=request, format=format),
+        'slivers': reverse('sliver-list', request=request, format=format),
+        'images': reverse('image-list', request=request, format=format),
+    })
diff --git a/planetstack/core/fixtures/__init__.py b/planetstack/core/fixtures/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/planetstack/core/fixtures/__init__.py
diff --git a/planetstack/core/fixtures/initial_data.json b/planetstack/core/fixtures/initial_data.json
new file mode 100644
index 0000000..638b00d
--- /dev/null
+++ b/planetstack/core/fixtures/initial_data.json
@@ -0,0 +1,167 @@
+[
+{
+    "pk": 1, 
+    "model": "core.deploymentnetwork", 
+    "fields": {
+        "updated": "2013-04-03T22:57:09.331Z", 
+        "name": "VICCI", 
+        "created": "2013-04-03T22:57:09.331Z"
+    }
+},
+{
+    "pk": 2, 
+    "model": "core.deploymentnetwork", 
+    "fields": {
+        "updated": "2013-04-03T22:57:15.013Z", 
+        "name": "VINI", 
+        "created": "2013-04-03T22:57:15.013Z"
+    }
+},
+{
+    "pk": 3, 
+    "model": "core.deploymentnetwork", 
+    "fields": {
+        "updated": "2013-04-03T22:57:23.015Z", 
+        "name": "PlanetLab Classic", 
+        "created": "2013-04-03T22:57:23.015Z"
+    }
+},
+{
+    "pk": 4, 
+    "model": "core.deploymentnetwork", 
+    "fields": {
+        "updated": "2013-04-03T22:57:29.569Z", 
+        "name": "GENI", 
+        "created": "2013-04-03T22:57:29.569Z"
+    }
+},
+{
+    "pk": 1, 
+    "model": "core.site", 
+    "fields": {
+        "updated": "2013-04-05T15:21:04.135Z", 
+        "name": "Princeton University", 
+        "created": "2013-04-03T23:00:10.085Z", 
+        "tenant_id": "", 
+        "enabled": true, 
+        "longitude": -74.6524, 
+        "site_url": "http://princeton.edu/", 
+        "login_base": "princeton", 
+        "latitude": 40.3502, 
+        "is_public": true, 
+        "deployments": [
+            3, 
+            4
+        ], 
+        "abbreviated_name": ""
+    }
+},
+{
+    "pk": 2, 
+    "model": "core.site", 
+    "fields": {
+        "updated": "2013-04-05T15:42:36.517Z", 
+        "name": "Stanford University", 
+        "created": "2013-04-03T23:03:51.742Z", 
+        "tenant_id": "", 
+        "enabled": true, 
+        "longitude": -122.172, 
+        "site_url": "http://www.stanford.edu/", 
+        "login_base": "stanford", 
+        "latitude": 37.4294, 
+        "is_public": true, 
+        "deployments": [], 
+        "abbreviated_name": ""
+    }
+},
+{
+    "pk": 3, 
+    "model": "core.site", 
+    "fields": {
+        "updated": "2013-04-05T15:42:17.263Z", 
+        "name": "Georgia Institute of Technology", 
+        "created": "2013-04-03T23:05:51.984Z", 
+        "tenant_id": "", 
+        "enabled": true, 
+        "longitude": -84.3976, 
+        "site_url": "http://www.gatech.edu/", 
+        "login_base": "gt", 
+        "latitude": 33.7772, 
+        "is_public": true, 
+        "deployments": [], 
+        "abbreviated_name": ""
+    }
+},
+{
+    "pk": 4, 
+    "model": "core.site", 
+    "fields": {
+        "updated": "2013-04-05T15:39:27.501Z", 
+        "name": "University of Washington", 
+        "created": "2013-04-03T23:09:52.337Z", 
+        "tenant_id": "", 
+        "enabled": true, 
+        "longitude": -122.313, 
+        "site_url": "https://www.washington.edu/", 
+        "login_base": "uw", 
+        "latitude": 47.6531, 
+        "is_public": true, 
+        "deployments": [], 
+        "abbreviated_name": ""
+    }
+},
+{
+    "pk": 5, 
+    "model": "core.site", 
+    "fields": {
+        "updated": "2013-04-05T15:38:56.889Z", 
+        "name": "ETH Zuerich - Computer Science", 
+        "created": "2013-04-03T23:14:11.072Z", 
+        "tenant_id": "", 
+        "enabled": true, 
+        "longitude": 8.54513, 
+        "site_url": "http://www.inf.ethz.ch/", 
+        "login_base": "ethzcs", 
+        "latitude": 47.3794, 
+        "is_public": true, 
+        "deployments": [], 
+        "abbreviated_name": ""
+    }
+},
+{
+    "pk": 6, 
+    "model": "core.site", 
+    "fields": {
+        "updated": "2013-04-05T15:38:15.960Z", 
+        "name": "Max Planck Institute for Software Systems", 
+        "created": "2013-04-03T23:19:38.789Z", 
+        "tenant_id": "", 
+        "enabled": true, 
+        "longitude": 6.589, 
+        "site_url": "http://www.mpi-sws.mpg.de/", 
+        "login_base": "mpisws", 
+        "latitude": 49.14, 
+        "is_public": true, 
+        "deployments": [], 
+        "abbreviated_name": ""
+    }
+},
+{
+    "pk": 7, 
+    "model": "core.site", 
+    "fields": {
+        "updated": "2013-04-05T15:37:32.185Z", 
+        "name": "University of Tokyo", 
+        "created": "2013-04-03T23:20:49.815Z", 
+        "tenant_id": "", 
+        "enabled": true, 
+        "longitude": 139.5, 
+        "site_url": "http://www.planet-lab-jp.org/", 
+        "login_base": "utokyo", 
+        "latitude": 35.75, 
+        "is_public": true, 
+        "deployments": [], 
+        "abbreviated_name": ""
+    }
+}
+]
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)    
diff --git a/planetstack/core/serializers.py b/planetstack/core/serializers.py
new file mode 100644
index 0000000..55cf7c8
--- /dev/null
+++ b/planetstack/core/serializers.py
@@ -0,0 +1,210 @@
+from django.forms import widgets
+from rest_framework import serializers
+from core.models import *
+
+
+class RoleSerializer(serializers.HyperlinkedModelSerializer):
+    # HyperlinkedModelSerializer doesn't include the id by default
+    id = serializers.Field()
+    class Meta:
+        model = Role
+        fields = ('id', 
+                  'role_id',
+                  'role_type')
+
+
+class UserSerializer(serializers.HyperlinkedModelSerializer):
+    # HyperlinkedModelSerializer doesn't include the id by default
+    id = serializers.Field()
+    site = serializers.HyperlinkedRelatedField(view_name='site-detail')
+    slice_memberships = serializers.HyperlinkedRelatedField(view_name='slice-membership-detail')
+    site_privileges = serializers.HyperlinkedRelatedField(view_name='site-privilege-detail')
+    class Meta:
+        model = User
+        fields = ('id',
+                  'user_id', 
+                  'kuser_id', 
+                  'firstname', 
+                  'lastname',
+                  'email', 
+                  'password', 
+                  'phone', 
+                  'user_url',
+                  'is_admin',
+                  'site',
+                  'slice_memberships',
+                  'site_privileges')
+                    
+class KeySerializer(serializers.HyperlinkedModelSerializer):
+    id = serializers.Field()
+    user = serializers.HyperlinkedRelatedField(view_name='user-detail') 
+    class Meta:
+        model = Key
+        fields = ('id',
+                  'name',
+                  'key',
+                  'type',
+                  'blacklisted', 
+                  'user')
+
+
+class SliceSerializer(serializers.HyperlinkedModelSerializer):
+    # HyperlinkedModelSerializer doesn't include the id by default
+    id = serializers.Field()
+    site = serializers.HyperlinkedRelatedField(view_name='site-detail')
+    slivers = serializers.HyperlinkedRelatedField(view_name='sliver-detail')
+    subnet= serializers.HyperlinkedRelatedField(view_name='subnet-detail')
+    class Meta:
+        model = Slice
+        fields = ('id',
+                  'tenant_id',
+                  'enabled',
+                  'name',
+                  'url',
+                  'instantiation',
+                  'omf_friendly',
+                  'description',
+                  'slice_url',
+                  'network_id',
+                  'router_id',
+                  'site',
+                  'slivers',
+                  'updated',
+                  'created')
+
+class SliceMembershipSerializer(serializers.HyperlinkedModelSerializer):
+    id = serializers.Field()
+    slice = serializers.HyperlinkedRelatedField(view_name='slice-detail')
+    user = serializers.HyperlinkedRelatedField(view_name='user-detail')
+    role = serializers.HyperlinkedRelatedField(view_name='role-detail')
+    class Meta:
+        model = SitePrivilege
+        fields = ('id',
+                  'user',
+                  'slice',
+                  'role')
+
+class SubnetSerializer(serializers.HyperlinkedModelSerializer):
+    id = serializers.Field()
+    slice = serializers.HyperlinkedRelatedField(view_name='slice-detail')
+    class Meta:
+        model = Subnet
+        fields = ('id',
+                  'subnet_id',
+                  'cidr',
+                  'ip_version',
+                  'start',
+                  'end',
+                  'slice')  
+
+class SiteSerializer(serializers.HyperlinkedModelSerializer):
+
+    #Experimenting with whether to use ids, hyperlinks, or nested includes
+    #slices = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
+    #slices = serializers.RelatedField(many=True, read_only=True)
+    #slices = SliceSerializer(many=True)
+    # HyperlinkedModelSerializer doesn't include the id by default
+    id = serializers.Field()
+    slices = serializers.HyperlinkedRelatedField(many=True, read_only=True,view_name='slice-detail')
+
+    class Meta:
+        model = Site
+        fields = ('id',
+                  'url',
+                  'name',
+                  'slices',
+                  'site_url',
+                  'enabled',
+                  'longitude',
+                  'latitude',
+                  'login_base',
+                  'tenant_id',
+                  'is_public',
+                  'abbreviated_name',
+                  'updated',
+                  'created')
+
+class SitePrivilegeSerializer(serializers.HyperlinkedModelSerializer):
+    id = serializers.Field()
+    site = serializers.HyperlinkedRelatedField(view_name='site-detail')
+    user = serializers.HyperlinkedRelatedField(view_name='user-detail')
+    role = serializers.HyperlinkedRelatedField(view_name='role-detail')
+    class Meta:
+        model = SitePrivilege
+        fields = ('id',
+                  'user',
+                  'site',
+                  'role')
+
+class DeploymentNetworkSerializer(serializers.HyperlinkedModelSerializer):
+
+    # HyperlinkedModelSerializer doesn't include the id by default
+    id = serializers.Field()
+    sites = serializers.HyperlinkedRelatedField(view_name='deploymentnetwork-detail')
+    class Meta:
+        model = DeploymentNetwork
+        fields = ('id',
+                  'name',
+                  'sites'
+                 )
+
+class SliverSerializer(serializers.HyperlinkedModelSerializer):
+    # HyperlinkedModelSerializer doesn't include the id by default
+    id = serializers.Field()
+    image = serializers.HyperlinkedRelatedField(view_name='image-detail')
+    key = serializers.HyperlinkedRelatedField(view_name='key-detail')
+    slice = serializers.HyperlinkedRelatedField(view_name='slice-detail')
+    deployment_network = serializers.HyperlinkedRelatedField(view_name='deployment_network-detail')
+    node = serializers.HyperlinkedRelatedField(view_name='node-detail')
+    
+    
+    #slice = serializers.PrimaryKeyRelatedField(read_only=True)
+
+    class Meta:
+        model = Sliver
+        fields = ('id',
+                  'instance_id',
+                  'name',
+                  'instance_name',
+                  'ip',
+                  'image',
+                  'key',
+                  'slice',
+                  'deploymentNetwork',
+                  'node')
+
+class NodeSerializer(serializers.HyperlinkedModelSerializer):
+    # HyperlinkedModelSerializer doesn't include the id by default
+    id = serializers.Field()
+    class Meta:
+        model = Node
+        fields = ('id',
+                 'name')
+
+class ImageSerializer(serializers.HyperlinkedModelSerializer):
+    # HyperlinkedModelSerializer doesn't include the id by default
+    id = serializers.Field()
+    class Meta:
+        model = Image
+        fields = ('id',
+                  'image_id',
+                  'name',
+                  'disk_format',
+                  'container_format')
+
+serializerLookUp = { 
+                 Role: RoleSerializer,
+                 User: UserSerializer,
+                 Key: KeySerializer,
+                 Site: SiteSerializer,
+                 SitePrivilege: SitePrivilegeSerializer,
+                 Slice: SliceSerializer,
+                 SliceMembership: SliceMembershipSerializer,
+                 Subnet: SubnetSerializer,
+                 Node: NodeSerializer,
+                 Sliver: SliverSerializer,
+                 DeploymentNetwork: DeploymentNetworkSerializer,
+                 Image: ImageSerializer,
+                 None: None,
+                }
+
diff --git a/planetstack/core/views/__init__.py b/planetstack/core/views/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/planetstack/core/views/__init__.py
diff --git a/planetstack/core/views/deployment_networks.py b/planetstack/core/views/deployment_networks.py
new file mode 100644
index 0000000..63220a4
--- /dev/null
+++ b/planetstack/core/views/deployment_networks.py
@@ -0,0 +1,59 @@
+from django.http import Http404
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework import status
+
+from core.api.deployment_networks import add_deployment_network, delete_deployment_network, get_deployment_networks
+from core.serializers import DeploymentNetworkSerializer
+from util.request import parse_request
+
+
+class DeploymentNetworkListCreate(APIView):
+    """ 
+    List all deployment networks or create a new role.
+    """
+
+    def post(self, request, format = None):
+        data = parse_request(request.DATA)  
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)        
+        elif 'deploymentNetwork' in data:
+        
+            deployment = add_deployment_network(data['auth'], data['deploymentNetwork'].get('name'))
+            serializer = DeploymentNetworkSerializer(deployment)
+            return Response(serializer.data, status=status.HTTP_201_CREATED)
+        else:
+            deployment_networks = get_deployment_networks(data['auth'])
+            serializer = DeploymentNetworkSerializer(deployment_networks, many=True)
+            return Response(serializer.data)
+        
+            
+class DeploymentNetworkRetrieveUpdateDestroy(APIView):
+    """
+    Retrieve, update or delete a deployment network 
+    """
+
+    def post(self, request, pk, format=None):
+        """Retrieve a deployment network"""
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        deployment_networks = get_deployment_networks(data['auth'], pk)
+        if not deployment_networks:
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        serializer = DeploymentNetworkSerializer(deployment_networks[0])
+        return Response(serializer.data)                  
+
+    def put(self, request, pk, format=None):
+        """deployment network update not implemnted""" 
+        return Response(status=status.HTTP_404_NOT_FOUND) 
+
+    def delete(self, request, pk, format=None):
+        data = parse_request(request.DATA) 
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        delete_deployment_network(data['auth'], pk)
+        return Response(status=status.HTTP_204_NO_CONTENT) 
+            
+            
+        
diff --git a/planetstack/core/views/images.py b/planetstack/core/views/images.py
new file mode 100644
index 0000000..7e0ab59
--- /dev/null
+++ b/planetstack/core/views/images.py
@@ -0,0 +1,55 @@
+from django.http import Http404
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework import status
+
+from core.api.images import add_image, delete_image, get_images
+from core.serializers import ImageSerializer
+from util.request import parse_request
+
+
+class ImageListCreate(APIView):
+    """ 
+    List all images or create a new image.
+    """
+
+    def post(self, request, format = None):
+        data = parse_request(request.DATA)  
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)        
+        elif 'image' in data:
+            """Not Implemented"""
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        else:
+            images = get_images(data['auth'])
+            serializer = ImageSerializer(images, many=True)
+            return Response(serializer.data)
+        
+            
+class ImageRetrieveUpdateDestroy(APIView):
+    """
+    Retrieve, update or delete an image  
+    """
+
+    def post(self, request, pk, format=None):
+        """Retrieve an image """
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        images = get_images(data['auth'], pk)
+        if not images:
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        serializer = ImageSerializer(images[0])
+        return Response(serializer.data)                  
+
+    def put(self, request, pk, format=None):
+        """update image not implemnted""" 
+        return Response(status=status.HTTP_404_NOT_FOUND) 
+
+    def delete(self, request, pk, format=None):
+        """delete image not implemnted""" 
+        return Response(status=status.HTTP_404_NOT_FOUND) 
+
+            
+            
+        
diff --git a/planetstack/core/views/keys.py b/planetstack/core/views/keys.py
new file mode 100644
index 0000000..a5d0995
--- /dev/null
+++ b/planetstack/core/views/keys.py
@@ -0,0 +1,66 @@
+from django.http import Http404
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework import status
+
+from core.api.keys import add_key, delete_key, get_keys, update_key
+from core.serializers import KeySerializer
+from util.request import parse_request
+
+
+class KeyListCreate(APIView):
+    """ 
+    List all users or create a new key.
+    """
+
+    def post(self, request, format = None):
+        data = parse_request(request.DATA)  
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)        
+        elif 'key' in data:
+            key = add_key(data['auth'], data['key'])
+            serializer = KeySerializer(key)
+            return Response(serializer.data, status=status.HTTP_201_CREATED)
+        else:
+            keys = get_keys(data['auth'])
+            serializer = KeySerializer(keys, many=True)
+            return Response(serializer.data)
+        
+            
+class KeyRetrieveUpdateDestroy(APIView):
+    """
+    Retrieve, update or delete a key 
+    """
+
+    def post(self, request, pk, format=None):
+        """Retrieve a key"""
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        keys = get_keys(data['auth'], pk)
+        if not keys:
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        serializer = KeySerializer(keys[0])
+        return Response(serializer.data)                  
+
+    def put(self, request, pk, format=None):
+        """update a key""" 
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        elif 'key' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+
+        key = update_key(pk, data['key'])
+        serializer = KeySerializer(key)
+        return Response(serializer.data) 
+
+    def delete(self, request, pk, format=None):
+        data = parse_request(request.DATA) 
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        delete_key(data['auth'], pk)
+        return Response(status=status.HTTP_204_NO_CONTENT) 
+            
+            
+        
diff --git a/planetstack/core/views/nodes.py b/planetstack/core/views/nodes.py
new file mode 100644
index 0000000..0f1977e
--- /dev/null
+++ b/planetstack/core/views/nodes.py
@@ -0,0 +1,55 @@
+from django.http import Http404
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework import status
+
+from core.api.nodes import add_node, delete_node, get_nodes, update_node
+from core.serializers import NodeSerializer
+from util.request import parse_request
+
+
+class NodeListCreate(APIView):
+    """ 
+    List all nodes or create a new node.
+    """
+
+    def post(self, request, format = None):
+        data = parse_request(request.DATA)  
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)        
+        elif 'node' in data:
+            """Not Implemented"""
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        else:
+            nodes = get_nodes(data['auth'])
+            serializer = NodeSerializer(nodes, many=True)
+            return Response(serializer.data)
+        
+            
+class NodeRetrieveUpdateDestroy(APIView):
+    """
+    Retrieve, update or delete an node  
+    """
+
+    def post(self, request, pk, format=None):
+        """Retrieve an node """
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        nodes = get_nodes(data['auth'], pk)
+        if not nodes:
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        serializer = NodeSerializer(nodes[0])
+        return Response(serializer.data)                  
+
+    def put(self, request, pk, format=None):
+        """update node not implemnted""" 
+        return Response(status=status.HTTP_404_NOT_FOUND) 
+
+    def delete(self, request, pk, format=None):
+        """delete node not implemnted""" 
+        return Response(status=status.HTTP_404_NOT_FOUND) 
+
+            
+            
+        
diff --git a/planetstack/core/views/roles.py b/planetstack/core/views/roles.py
new file mode 100644
index 0000000..37bb149
--- /dev/null
+++ b/planetstack/core/views/roles.py
@@ -0,0 +1,58 @@
+from django.http import Http404
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework import status
+
+from core.api.roles import add_role, delete_role, get_roles
+from core.serializers import RoleSerializer
+from util.request import parse_request
+
+
+class RoleListCreate(APIView):
+    """ 
+    List all roles or create a new role.
+    """
+
+    def post(self, request, format = None):
+        data = parse_request(request.DATA)  
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)        
+        elif 'role' in data:
+            role = add_role(data['auth'], data['role']['role_type'])
+            serializer = RoleSerializer(data=role)
+            return Response(serializer.data, status=status.HTTP_201_CREATED)
+        else:
+            roles = get_roles(data['auth'])
+            serializer = RoleSerializer(roles, many=True)
+            return Response(serializer.data)
+        
+            
+class RoleRetrieveUpdateDestroy(APIView):
+    """
+    Retrieve, update or delete a role 
+    """
+
+    def post(self, request, pk, format=None):
+        """Retrieve a role"""
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        roles = get_roles(data['auth'], pk)
+        if not roles:
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        serializer = RoleSerializer(roles[0])
+        return Response(serializer.data)                  
+
+    def put(self, request, pk, format=None):
+        """role update not implemnted""" 
+        return Response(status=status.HTTP_404_NOT_FOUND) 
+
+    def delete(self, request, pk, format=None):
+        data = parse_request(request.DATA) 
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        delete_role(data['auth'], pk)
+        return Response(status=status.HTTP_204_NO_CONTENT) 
+            
+            
+        
diff --git a/planetstack/core/views/site_privileges.py b/planetstack/core/views/site_privileges.py
new file mode 100644
index 0000000..37fc371
--- /dev/null
+++ b/planetstack/core/views/site_privileges.py
@@ -0,0 +1,66 @@
+from django.http import Http404
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework import status
+
+from core.api.site_privileges import add_site_privilege, delete_site_privilege, get_site_privileges, update_site_privilege
+from core.serializers import SitePrivilegeSerializer
+from util.request import parse_request
+
+
+class SitePrivilegeListCreate(APIView):
+    """ 
+    List all site_privileges or create a new site_privilege.
+    """
+
+    def post(self, request, format = None):
+        data = parse_request(request.DATA)  
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)        
+        elif 'site_privilege' in data:
+            site_privilege = add_site_privilege(data['auth'], data['site_privilege'])
+            serializer = SitePrivilegeSerializer(site_privilege)
+            return Response(serializer.data, status=status.HTTP_201_CREATED)
+        else:
+            site_privileges = get_site_privileges(data['auth'])
+            serializer = SitePrivilegeSerializer(site_privileges, many=True)
+            return Response(serializer.data)
+        
+            
+class SitePrivilegeRetrieveUpdateDestroy(APIView):
+    """
+    Retrieve, update or delete a site_privilege 
+    """
+
+    def post(self, request, pk, format=None):
+        """Retrieve a site_privilege"""
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        site_privileges = get_site_privileges(data['auth'], pk)
+        if not site_privileges:
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        serializer = SitePrivilegeSerializer(site_privileges[0])
+        return Response(serializer.data)                  
+
+    def put(self, request, pk, format=None):
+        """update a site_privilege""" 
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        elif 'site_privilege' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+
+        site_privilege = update_site_privilege(pk, data['site_privilege'])
+        serializer = SitePrivilegeSerializer(site_privilege)
+        return Response(serializer.data) 
+
+    def delete(self, request, pk, format=None):
+        data = parse_request(request.DATA) 
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        delete_site_privilege(data['auth'], pk)
+        return Response(status=status.HTTP_204_NO_CONTENT) 
+            
+            
+        
diff --git a/planetstack/core/views/sites.py b/planetstack/core/views/sites.py
new file mode 100644
index 0000000..6449b67
--- /dev/null
+++ b/planetstack/core/views/sites.py
@@ -0,0 +1,66 @@
+from django.http import Http404
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework import status
+
+from core.api.sites import add_site, delete_site, get_sites
+from core.serializers import SiteSerializer
+from util.request import parse_request
+
+
+class SiteListCreate(APIView):
+    """ 
+    List all sites or create a new site.
+    """
+
+    def post(self, request, format = None):
+        data = parse_request(request.DATA)  
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)        
+        elif 'site' in data:
+            site = add_site(data['auth'], data['site'])
+            serializer = SiteSerializer(site)
+            return Response(serializer.data, status=status.HTTP_201_CREATED)
+        else:
+            sites = get_sites(data['auth'])
+            serializer = SiteSerializer(sites, many=True)
+            return Response(serializer.data)
+        
+            
+class SiteRetrieveUpdateDestroy(APIView):
+    """
+    Retrieve, update or delete a site 
+    """
+
+    def post(self, request, pk, format=None):
+        """Retrieve a site"""
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        sites = get_sites(data['auth'], {'id': pk})
+        if not sites:
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        serializer = SiteSerializer(sites[0])
+        return Response(serializer.data)                  
+
+    def put(self, request, pk, format=None):
+        """update a site""" 
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        elif 'site' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+
+        site = update_site(pk, data['site'])
+        serializer = SiteSerializer(site)
+        return Response(serializer.data) 
+
+    def delete(self, request, pk, format=None):
+        data = parse_request(request.DATA) 
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        delete_site(data['auth'], {'id': pk})
+        return Response(status=status.HTTP_204_NO_CONTENT) 
+            
+            
+        
diff --git a/planetstack/core/views/slice_memberships.py b/planetstack/core/views/slice_memberships.py
new file mode 100644
index 0000000..4bb581c
--- /dev/null
+++ b/planetstack/core/views/slice_memberships.py
@@ -0,0 +1,66 @@
+from django.http import Http404
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework import status
+
+from core.api.slice_memberships import add_slice_membership, delete_slice_membership, get_slice_memberships, update_slice_membership
+from core.serializers import SliceMembershipSerializer
+from util.request import parse_request
+
+
+class SliceMembershipListCreate(APIView):
+    """ 
+    List all slice_memberships or create a new slice_membership.
+    """
+
+    def post(self, request, format = None):
+        data = parse_request(request.DATA)  
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)        
+        elif 'slice_membership' in data:
+            slice_membership = add_slice_membership(data['auth'], data['slice_membership'])
+            serializer = SliceMembershipSerializer(slice_membership)
+            return Response(serializer.data, status=status.HTTP_201_CREATED)
+        else:
+            slice_memberships = get_slice_memberships(data['auth'])
+            serializer = SliceMembershipSerializer(slice_memberships, many=True)
+            return Response(serializer.data)
+        
+            
+class SliceMembershipRetrieveUpdateDestroy(APIView):
+    """
+    Retrieve, update or delete a slice_membership 
+    """
+
+    def post(self, request, pk, format=None):
+        """Retrieve a slice_membership"""
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        slice_memberships = get_slice_memberships(data['auth'], pk)
+        if not slice_memberships:
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        serializer = SliceMembershipSerializer(slice_memberships[0])
+        return Response(serializer.data)                  
+
+    def put(self, request, pk, format=None):
+        """update a slice_membership""" 
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        elif 'slice_membership' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+
+        slice_membership = update_slice_membership(pk, data['slice_membership'])
+        serializer = SliceMembershipSerializer(slice_membership)
+        return Response(serializer.data) 
+
+    def delete(self, request, pk, format=None):
+        data = parse_request(request.DATA) 
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        delete_slice_membership(data['auth'], pk)
+        return Response(status=status.HTTP_204_NO_CONTENT) 
+            
+            
+        
diff --git a/planetstack/core/views/slices.py b/planetstack/core/views/slices.py
new file mode 100644
index 0000000..5954d0c
--- /dev/null
+++ b/planetstack/core/views/slices.py
@@ -0,0 +1,66 @@
+from django.http import Http404
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework import status
+
+from core.api.slices import add_slice, delete_slice, get_slices, update_slice
+from core.serializers import SliceSerializer
+from util.request import parse_request
+
+
+class SliceListCreate(APIView):
+    """ 
+    List all slices or create a new slice.
+    """
+
+    def post(self, request, format = None):
+        data = parse_request(request.DATA)  
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)        
+        elif 'slice' in data:
+            slice = add_slice(data['auth'], data['slice'])
+            serializer = SliceSerializer(slice)
+            return Response(serializer.data, status=status.HTTP_201_CREATED)
+        else:
+            slices = get_slices(data['auth'])
+            serializer = SliceSerializer(slices, many=True)
+            return Response(serializer.data)
+        
+            
+class SliceRetrieveUpdateDestroy(APIView):
+    """
+    Retrieve, update or delete a slice 
+    """
+
+    def post(self, request, pk, format=None):
+        """Retrieve a slice"""
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        slices = get_slices(data['auth'],  pk)
+        if not slices:
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        serializer = SliceSerializer(slices[0])
+        return Response(serializer.data)                  
+
+    def put(self, request, pk, format=None):
+        """update a slice""" 
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        elif 'slice' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+
+        slice = update_slice(pk, data['slice'])
+        serializer = SliceSerializer(slice)
+        return Response(serializer.data) 
+
+    def delete(self, request, pk, format=None):
+        data = parse_request(request.DATA) 
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        delete_slice(data['auth'],  pk)
+        return Response(status=status.HTTP_204_NO_CONTENT) 
+            
+            
+        
diff --git a/planetstack/core/views/slivers.py b/planetstack/core/views/slivers.py
new file mode 100644
index 0000000..3741cce
--- /dev/null
+++ b/planetstack/core/views/slivers.py
@@ -0,0 +1,66 @@
+from django.http import Http404
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework import status
+
+from core.api.slivers import add_sliver, delete_sliver, get_slivers, update_sliver
+from core.serializers import SliverSerializer
+from util.request import parse_request
+
+
+class SliverListCreate(APIView):
+    """ 
+    List all slivers or create a new sliver.
+    """
+
+    def post(self, request, format = None):
+        data = parse_request(request.DATA)  
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)        
+        elif 'sliver' in data:
+            sliver = add_sliver(data['auth'], data['sliver'])
+            serializer = SliverSerializer(sliver)
+            return Response(serializer.data, status=status.HTTP_201_CREATED)
+        else:
+            slivers = get_slivers(data['auth'])
+            serializer = SliverSerializer(slivers, many=True)
+            return Response(serializer.data)
+        
+            
+class SliverRetrieveUpdateDestroy(APIView):
+    """
+    Retrieve, update or delete a sliver 
+    """
+
+    def post(self, request, pk, format=None):
+        """Retrieve a sliver"""
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        slivers = get_slivers(data['auth'], pk)
+        if not slivers:
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        serializer = SliverSerializer(slivers[0])
+        return Response(serializer.data)                  
+
+    def put(self, request, pk, format=None):
+        """update a sliver""" 
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        elif 'sliver' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+
+        sliver = update_sliver(pk, data['sliver'])
+        serializer = SliverSerializer(sliver)
+        return Response(serializer.data) 
+
+    def delete(self, request, pk, format=None):
+        data = parse_request(request.DATA) 
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        delete_sliver(data['auth'], pk)
+        return Response(status=status.HTTP_204_NO_CONTENT) 
+            
+            
+        
diff --git a/planetstack/core/views/subnets.py b/planetstack/core/views/subnets.py
new file mode 100644
index 0000000..881f615
--- /dev/null
+++ b/planetstack/core/views/subnets.py
@@ -0,0 +1,66 @@
+from django.http import Http404
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework import status
+
+from core.api.subnets import add_subnet, delete_subnet, get_subnets, update_subnet
+from core.serializers import SubnetSerializer
+from util.request import parse_request
+
+
+class SubnetListCreate(APIView):
+    """ 
+    List all subnets or create a new subnet.
+    """
+
+    def post(self, request, format = None):
+        data = parse_request(request.DATA)  
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)        
+        elif 'subnet' in data:
+            subnet = add_subnet(data['auth'], data['subnet'])
+            serializer = SubnetSerializer(subnet)
+            return Response(serializer.data, status=status.HTTP_201_CREATED)
+        else:
+            subnets = get_subnets(data['auth'])
+            serializer = SubnetSerializer(subnets, many=True)
+            return Response(serializer.data)
+        
+            
+class SubnetRetrieveUpdateDestroy(APIView):
+    """
+    Retrieve, update or delete a subnet 
+    """
+
+    def post(self, request, pk, format=None):
+        """Retrieve a subnet"""
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        subnets = get_subnets(data['auth'], {'id': pk})
+        if not subnets:
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        serializer = SubnetSerializer(subnets[0])
+        return Response(serializer.data)                  
+
+    def put(self, request, pk, format=None):
+        """update a subnet""" 
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        elif 'subnet' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+
+        subnet = update_subnet(pk, data['subnet'])
+        serializer = SubnetSerializer(subnet)
+        return Response(serializer.data) 
+
+    def delete(self, request, pk, format=None):
+        data = parse_request(request.DATA) 
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        delete_subnet(data['auth'], {'id': pk})
+        return Response(status=status.HTTP_204_NO_CONTENT) 
+            
+            
+        
diff --git a/planetstack/core/views/users.py b/planetstack/core/views/users.py
new file mode 100644
index 0000000..8b27928
--- /dev/null
+++ b/planetstack/core/views/users.py
@@ -0,0 +1,66 @@
+from django.http import Http404
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework import status
+
+from core.api.users import add_user, delete_user, get_users, update_user
+from core.serializers import UserSerializer
+from util.request import parse_request
+
+
+class UserListCreate(APIView):
+    """ 
+    List all users or create a new user.
+    """
+
+    def post(self, request, format = None):
+        data = parse_request(request.DATA)  
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)        
+        elif 'user' in data:
+            user = add_user(data['auth'], data['user'])
+            serializer = UserSerializer(user)
+            return Response(serializer.data, status=status.HTTP_201_CREATED)
+        else:
+            users = get_users(data['auth'])
+            serializer = UserSerializer(users, many=True)
+            return Response(serializer.data)
+        
+            
+class UserRetrieveUpdateDestroy(APIView):
+    """
+    Retrieve, update or delete a user 
+    """
+
+    def post(self, request, pk, format=None):
+        """Retrieve a user"""
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        users = get_users(data['auth'], {'id': pk})
+        if not users:
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        serializer = UserSerializer(users[0])
+        return Response(serializer.data)                  
+
+    def put(self, request, pk, format=None):
+        """update a user""" 
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        elif 'user' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+
+        user = update_user(pk, data['user'])
+        serializer = UserSerializer(user)
+        return Response(serializer.data) 
+
+    def delete(self, request, pk, format=None):
+        data = parse_request(request.DATA) 
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        delete_user(data['auth'], {'id': pk})
+        return Response(status=status.HTTP_204_NO_CONTENT) 
+            
+            
+