organized
diff --git a/plstackapi/core/admin.py b/plstackapi/core/admin.py
new file mode 100644
index 0000000..c3b655f
--- /dev/null
+++ b/plstackapi/core/admin.py
@@ -0,0 +1,18 @@
+from plstackapi.core.models import *
+from django.contrib import admin
+
+from django.contrib.auth.admin import UserAdmin
+from django.contrib.auth.models import User
+
+admin.site.register(Role)
+admin.site.register(Site)
+#admin.site.register(User)
+admin.site.register(Key)
+admin.site.register(Slice)
+admin.site.register(Node)
+admin.site.register(DeploymentNetwork)
+admin.site.register(SiteDeploymentNetwork)
+admin.site.register(Sliver)
+admin.site.register(Image)
+admin.site.register(Flavor)
+
diff --git a/plstackapi/core/api/__init__.py b/plstackapi/core/api/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plstackapi/core/api/__init__.py
diff --git a/plstackapi/core/api/auth.py b/plstackapi/core/api/auth.py
new file mode 100644
index 0000000..4054da6
--- /dev/null
+++ b/plstackapi/core/api/auth.py
@@ -0,0 +1,8 @@
+from plstackapi.openstack.client import OpenStackClient
+
+def auth_check(auth):
+    client = OpenStackClient(username=auth['Username'],
+                             password=auth['AuthString'],
+                             tenant=auth['LoginBase'])
+    client.authenticate()
+    return client
diff --git a/plstackapi/core/api/deployment_networks.py b/plstackapi/core/api/deployment_networks.py
new file mode 100644
index 0000000..812ca15
--- /dev/null
+++ b/plstackapi/core/api/deployment_networks.py
@@ -0,0 +1,26 @@
+from plstackapi.openstack.client import OpenStackClient
+from plstackapi.openstack.driver import OpenStackDriver
+from plstackapi.core.api.auth import auth_check
+from plstackapi.core.models import DeploymentNetwork
+ 
+
+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 = DeploymentNetwork.objects.filter(**filter)
+    for deployment in deployments:
+        deployment.delete()
+    return 1
+
+def get_deployment_networks(auth, filter={}):
+    auth_check(auth)   
+    deployments = DeploymentNetwork.objects.filter(**filter)
+    return deployments             
+        
+
+    
diff --git a/plstackapi/core/api/flavors.py b/plstackapi/core/api/flavors.py
new file mode 100644
index 0000000..a2d0b23
--- /dev/null
+++ b/plstackapi/core/api/flavors.py
@@ -0,0 +1,21 @@
+from plstackapi.openstack.client import OpenStackClient
+from plstackapi.openstack.driver import OpenStackDriver
+from plstackapi.core.api.auth import auth_check
+from plstackapi.core.models import Flavor
+ 
+
+def add_flavor(auth, fields={}):
+    """not implemented"""
+    return 
+
+def delete_flavor(auth, filter={}):
+    """not implemented"""
+    return 1
+
+def get_flavors(auth, filter={}):
+    auth_check(auth)   
+    flavors = Flavor.objects.filter(**filter)
+    return flavors             
+        
+
+    
diff --git a/plstackapi/core/api/images.py b/plstackapi/core/api/images.py
new file mode 100644
index 0000000..b773b0b
--- /dev/null
+++ b/plstackapi/core/api/images.py
@@ -0,0 +1,21 @@
+from plstackapi.openstack.client import OpenStackClient
+from plstackapi.openstack.driver import OpenStackDriver
+from plstackapi.core.api.auth import auth_check
+from plstackapi.core.models import Image
+ 
+
+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 = Image.objects.filter(**filter)
+    return images             
+        
+
+    
diff --git a/plstackapi/core/api/keys.py b/plstackapi/core/api/keys.py
new file mode 100644
index 0000000..af21f41
--- /dev/null
+++ b/plstackapi/core/api/keys.py
@@ -0,0 +1,45 @@
+from plstackapi.openstack.client import OpenStackClient
+from plstackapi.openstack.driver import OpenStackDriver
+from plstackapi.core.api.auth import auth_check
+from plstackapi.core.models import Key, User
+ 
+def lookup_user(fields):
+    user = None
+    if 'user' in fields:
+        if isinstance(fields['user'], int):
+            users = User.objects.filter(id=fields['user'])
+        else:
+            users = User.objects.filter(email=fields['user'])
+        if users:
+            user = users[0]
+    return user 
+
+def add_key(auth, fields):
+    driver = OpenStackDriver(client = auth_check(auth))
+    user = lookup_user(fields) 
+    if user: fields['user'] = user     
+    key = Key(**fields)
+    nova_fields = {'name': key.name,
+                   'key': key.key} 
+    nova_key = driver.create_keypair(**nova_fields)
+    key.save()
+    return key
+
+def update_key(auth, id, **fields):
+    return  
+
+def delete_key(auth, filter={}):
+    driver = OpenStackDriver(client = auth_check(auth))   
+    keys = Key.objects.filter(**filter)
+    for key in keys:
+        driver.delete_keypair(name=key.name) 
+        key.delete()
+    return 1
+
+def get_keys(auth, filter={}):
+    client = auth_check(auth)
+    keys = Key.objects.filter(**filter)
+    return keys             
+        
+
+    
diff --git a/plstackapi/core/api/roles.py b/plstackapi/core/api/roles.py
new file mode 100644
index 0000000..844fb4f
--- /dev/null
+++ b/plstackapi/core/api/roles.py
@@ -0,0 +1,28 @@
+from plstackapi.openstack.client import OpenStackClient
+from plstackapi.openstack.driver import OpenStackDriver
+from plstackapi.core.api.auth import auth_check
+from plstackapi.core.models import Role
+ 
+
+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 = Role.objects.filter(**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)
+    roles = Role.objects.filter(**filter)
+    return roles             
+        
+
+    
diff --git a/plstackapi/core/api/sites.py b/plstackapi/core/api/sites.py
new file mode 100644
index 0000000..0d07605
--- /dev/null
+++ b/plstackapi/core/api/sites.py
@@ -0,0 +1,48 @@
+from plstackapi.openstack.client import OpenStackClient
+from plstackapi.openstack.driver import OpenStackDriver
+from plstackapi.core.api.auth import auth_check
+from plstackapi.core.models import Site
+ 
+
+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 = Site.objects.filter(id=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 = Site.objects.filter(**filter)
+    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 = Site.objects.filter(**filter)
+    return sites             
+        
+
+    
diff --git a/plstackapi/core/api/users.py b/plstackapi/core/api/users.py
new file mode 100644
index 0000000..6862e30
--- /dev/null
+++ b/plstackapi/core/api/users.py
@@ -0,0 +1,67 @@
+from plstackapi.openstack.client import OpenStackClient
+from plstackapi.openstack.driver import OpenStackDriver
+from plstackapi.core.api.auth import auth_check
+from plstackapi.core.models import User, Site
+ 
+def lookup_site(fields):
+    site = None
+    if 'site' in fields:
+        if isinstance(fields['site'], int):
+            sites = Site.objects.filter(id=fields['site'])
+        else:
+            sites = Site.objects.filter(login_base=fields['site'])
+        if sites:
+            site = sites[0]
+    return site 
+
+def add_user(auth, fields):
+    driver = OpenStackDriver(client = auth_check(auth))
+    site = lookup_site(fields) 
+    if site: fields['site'] = site     
+    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_role(user.id, user.site.tenant_id, 'user')
+    user.user_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.user_id, **nova_fields)
+    site = lookup_site(fields)
+    if site: fields['site'] = site
+    user.update(**fields)
+    return user 
+
+def delete_user(auth, filter={}):
+    driver = OpenStackDriver(client = auth_check(auth))   
+    users = User.objects.filter(**filter)
+    for user in users:
+        driver.delete_user(id=user.user_id) 
+        user.delete()
+    return 1
+
+def get_users(auth, filter={}):
+    client = auth_check(auth)
+    users = User.objects.filter(**filter)
+    return users             
+        
+
+    
diff --git a/plstackapi/core/fixtures/__init__.py b/plstackapi/core/fixtures/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plstackapi/core/fixtures/__init__.py
diff --git a/plstackapi/core/fixtures/initial_data.json b/plstackapi/core/fixtures/initial_data.json
new file mode 100644
index 0000000..62d943b
--- /dev/null
+++ b/plstackapi/core/fixtures/initial_data.json
@@ -0,0 +1 @@
+[{"pk": 1, "model": "plstackapi.planetstack.deploymentnetwork", "fields": {"updated": "2013-03-20T01:18:31.247Z", "name": "VICCI", "created": "2013-03-20T01:18:31.247Z"}}, {"pk": 2, "model": "plstackapi.planetstack.deploymentnetwork", "fields": {"updated": "2013-03-20T01:19:00.063Z", "name": "VINI", "created": "2013-03-20T01:19:00.063Z"}}, {"pk": 3, "model": "plstackapi.planetstack.deploymentnetwork", "fields": {"updated": "2013-03-20T01:19:15.143Z", "name": "GENI", "created": "2013-03-20T01:19:15.143Z"}}, {"pk": 4, "model": "plstackapi.planetstack.deploymentnetwork", "fields": {"updated": "2013-03-20T01:19:40.098Z", "name": "PlanetLab Classic", "created": "2013-03-20T01:19:25.672Z"}}]
diff --git a/plstackapi/core/models.py b/plstackapi/core/models.py
new file mode 100644
index 0000000..1ae0a44
--- /dev/null
+++ b/plstackapi/core/models.py
@@ -0,0 +1,261 @@
+import os
+import datetime
+from django.db import models
+from plstackapi.openstack.driver import OpenStackDriver
+
+# Create your models here.
+
+class PlCoreBase(models.Model):
+
+    created = models.DateTimeField(auto_now_add=True)
+    updated = models.DateTimeField(auto_now=True)
+
+    class Meta:
+        abstract = True
+
+    def save(self):
+        if not self.id:
+            self.created = datetime.date.today()
+        self.updated = datetime.datetime.today()
+        super(PlCoreBase, self).save()
+
+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, choices=ROLE_CHOICES)
+
+    def __unicode__(self):  return u'%s' % (self.role_type)
+
+    def save(self):
+        if not self.id:
+            self.created = datetime.date.today()
+        self.updated = datetime.datetime.today()
+        super(Role, self).save()
+
+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)
+
+    def __unicode__(self):  return u'%s' % (self.name)
+
+
+class User(PlCoreBase):
+    user_id = models.CharField(max_length=256, unique=True)
+    firstname = models.CharField(help_text="person's given name", max_length=200)
+    lastname = models.CharField(help_text="person's surname", max_length=200)
+    email = models.EmailField(help_text="e-mail address")
+    phone = models.CharField(null=True, blank=True, help_text="phone number contact", max_length=100)
+    user_url = models.URLField(null=True, blank=True)
+    is_admin = models.BooleanField(default=False)
+    enabled = models.BooleanField(default=True, help_text="Status for this User")
+    site = models.ForeignKey(Site, related_name='users', verbose_name="Site this user will be homed too")
+
+    def __unicode__(self):  return u'%s' % (self.email)
+
+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):
+        driver  = OpenStackDriver()
+        driver.add_user_role(user_id=user.user_id, 
+                             tenant_id=site.tenant_id, 
+                             role_name=role.name)
+        super(SitePrivilege, self).save(*args, **kwds)
+
+    def delete(self, *args, **kwds):
+        driver = OpenStackDriver()
+        driver.delete_user_role(user_id=user.user_id,
+                                tenant_id=site.tenant_id,
+                                role_name=role.name)
+        super(SitePrivilege, self).delete(*args, **kwds)
+         
+
+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)
+
+class SiteDeploymentNetwork(PlCoreBase):
+    class Meta:
+        unique_together = ['site', 'deploymentNetwork']
+
+    site = models.ForeignKey(Site, related_name='deployment_networks')
+    deploymentNetwork = models.ForeignKey(DeploymentNetwork, related_name='sites')
+    name = models.CharField(default="Blah", max_length=100)
+
+
+    def __unicode__(self):  return u'%s::%s' % (self.site, self.deploymentNetwork)
+
+
+class Slice(PlCoreBase):
+    tenant_id = models.CharField(max_length=200, help_text="Keystone tenant id")
+    name = models.CharField(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")
+
+    def __unicode__(self):  return u'%s' % (self.name)
+
+    def save(self, *args, **kwds):
+        # sync keystone tenant
+        driver  = OpenStackDriver()
+
+        if not self.id:
+            tenant = driver.create_tenant(tenant_name=self.name,
+                                          description=self.description,
+                                          enabled=self.enabled)
+            self.tenant_id = tenant.id
+            
+            # create a network  
+            network = driver.create_network(name=self.name)
+            self.network_id = network['id']        
+            # create router
+            router = driver.create_router(name=self.name)
+            self.router_id = router['id']     
+
+        else:
+            # update record
+            self.driver.update_tenant(self.tenant_id, name=self.name,
+                                      description=self.description, enabled=self.enabled)
+        super(Slice, self).save(*args, **kwds)
+
+    def delete(self, *args, **kwds):
+        # delete keystone tenant
+        driver  = OpenStackDriver()
+        driver.delete_tenant(self.tenant_id)
+        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):
+        driver  = OpenStackDriver()
+        driver.add_user_role(user_id=user.user_id,
+                             tenant_id=slice.tenant_id,
+                             role_name=role.name)
+        super(SliceMembership, self).save(*args, **kwds)
+
+    def delete(self, *args, **kwds):
+        driver = OpenStackDriver()
+        driver.delete_user_role(user_id=user.user_id,
+                                tenant_id=slice.tenant_id,
+                                role_name=role.name)
+        super(SliceMembership, self).delete(*args, **kwds)
+
+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='subnets')
+
+    def __unicode__(self):  return u'%s' % (self.name)
+
+    def save(self, *args, **kwargs):
+        driver  = OpenStackDriver()
+        if not self.id:
+            subnet = driver.create_subnet(network_name=self.slice.name,
+                                          cidr_ip = self.cidr,
+                                          ip_version=self.ip_version,
+                                          start = self.start,
+                                          end = self.end)
+
+            self.subnet_id = subnet.id
+
+        # add subnet as interface to slice router
+        driver.add_router_interface(self.slice.router_id, subnet.id)
+
+        super(SubNet, self).save(*args, **kwargs)
+
+
+    def delete(self, *args, **kwargs):
+        # delete quantum network
+        driver  = OpenStackDriver()
+        driver.delete_subnet(self.subnet_id)
+        driver.delete_router_interface(self.slice.router_id, self.subnet.id)
+        super(SubNet, self).delete(*args, **kwargs)
+
+class Node(PlCoreBase):
+    name = models.CharField(max_length=200, unique=True, help_text="Name of the Node")
+    siteDeploymentNetwork = models.ForeignKey(SiteDeploymentNetwork, help_text="The Site and Deployment Network this Node belongs too.")
+
+    def __unicode__(self):  return u'%s' % (self.name)
+
+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)
+
+
+class Flavor(PlCoreBase):
+    flavor_id = models.IntegerField(unique=True)
+    name = models.CharField(max_length=256, unique=True)
+    memory_mb = models.IntegerField()
+    disk_gb = models.IntegerField()
+    vcpus = models.IntegerField()
+
+    def __unicode__(self):  return u'%s' % (self.name)
+
+class Key(PlCoreBase):
+    name = models.CharField(max_length=256, unique=True)
+    key = models.CharField(max_length=512)
+    type = models.CharField(max_length=256)
+    blacklisted = models.BooleanField(default=False)
+    user = models.ForeignKey(User, related_name='keys')
+
+    def __unicode__(self):  return u'%s' % (self.name)
+
+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")
+    flavor = models.ForeignKey(Flavor)
+    image = models.ForeignKey(Image) 
+    key = models.ForeignKey(Key)        
+    slice = models.ForeignKey(Slice)
+    siteDeploymentNetwork = models.ForeignKey(SiteDeploymentNetwork)
+    node = models.ForeignKey(Node)
+
+    def __unicode__(self):  return u'%s::%s' % (self.slice, self.siteDeploymentNetwork)
+
+    def save(self, *args, **kwds):
+        driver  = OpenStackDriver()
+        instance = driver.spawn_instances(name=self.name,
+                                          keyname=self.name,
+                                          hostnames=self.node.name,
+                                          flavor=self.flavor.name,
+                                          image=self.image.name)
+        self.instance_id = instance.id
+        super(Sliver, self).save(*args, **kwds)
+
+    def delete(self, *args, **kwds):
+        driver  = OpenStackDriver()
+        driver.destroy_instance(name=self.name, id=self.instance_id)
+        super(Sliver, self).delete(*args, **kwds)
+
diff --git a/plstackapi/core/serializers.py b/plstackapi/core/serializers.py
new file mode 100644
index 0000000..0ffd86b
--- /dev/null
+++ b/plstackapi/core/serializers.py
@@ -0,0 +1,179 @@
+from django.forms import widgets
+from rest_framework import serializers
+from plstackapi.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', 
+                  'firstname', 
+                  'lastname',
+                  'email', 
+                  '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')
+
+    class Meta:
+        model = Slice
+        fields = ('id',
+                  'url',
+                  'name',
+                  'instantiation',
+                  'omf_friendly',
+                  'description',
+                  'slice_url',
+                  'site',
+                  'updated',
+                  'created')
+
+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')
+    deployment_networks = serializers.HyperlinkedRelatedField(many=True, read_only=True,view_name='sitedeploymentnetwork-detail')
+
+    class Meta:
+        model = Site
+        fields = ('id',
+                  'url',
+                  'name',
+                  'deployment_networks',
+                  'slices',
+                  'site_url',
+                  'enabled',
+                  'longitude',
+                  'latitude',
+                  'login_base',
+                  'tenant_id',
+                  'is_public',
+                  'abbreviated_name',
+                  'updated',
+                  'created')
+
+class DeploymentNetworkSerializer(serializers.HyperlinkedModelSerializer):
+
+    # HyperlinkedModelSerializer doesn't include the id by default
+    id = serializers.Field()
+    sites = serializers.HyperlinkedRelatedField(view_name='sitedeploymentnetwork-detail')
+    class Meta:
+        model = DeploymentNetwork
+        fields = ('id',
+                  'name',
+                  'sites'
+                 )
+
+class SiteDeploymentNetworkSerializer(serializers.HyperlinkedModelSerializer):
+    # HyperlinkedModelSerializer doesn't include the id by default
+    id = serializers.Field()
+    site = serializers.HyperlinkedRelatedField(view_name='site-detail')
+    deploymentNetwork = serializers.HyperlinkedRelatedField(view_name='deploymentnetwork-detail')
+
+    class Meta:
+        model = SiteDeploymentNetwork
+        fields = ('id',
+                 'url',
+                 'site',
+                 'deploymentNetwork')
+
+class SliverSerializer(serializers.HyperlinkedModelSerializer):
+    # HyperlinkedModelSerializer doesn't include the id by default
+    id = serializers.Field()
+    slice = serializers.RelatedField(read_only=True)
+    #slice = serializers.PrimaryKeyRelatedField(read_only=True)
+
+    class Meta:
+        model = Sliver
+        fields = ('id',
+                  'slice',
+                  'name')
+
+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')
+
+class FlavorSerializer(serializers.HyperlinkedModelSerializer):
+    # HyperlinkedModelSerializer doesn't include the id by default
+    id = serializers.Field()
+    class Meta:
+        model = Flavor
+        fields = ('id',
+                  'flavor_id',
+                  'name',
+                  'memory_mb',
+                  'disk_gb',
+                  'vcpus')
+
+serializerLookUp = { 
+                 Role: RoleSerializer,
+                 User: UserSerializer,
+                 Key: KeySerializer,
+                 Site: SiteSerializer,
+                 Slice: SliceSerializer,
+                 Node: NodeSerializer,
+                 Sliver: SliverSerializer,
+                 DeploymentNetwork: DeploymentNetworkSerializer,
+                 SiteDeploymentNetwork: SiteDeploymentNetworkSerializer,
+                 Image: ImageSerializer,
+                 Flavor: FlavorSerializer, 
+                 None: None,
+                }
+
diff --git a/plstackapi/core/urls.py b/plstackapi/core/urls.py
new file mode 100644
index 0000000..b34e89a
--- /dev/null
+++ b/plstackapi/core/urls.py
@@ -0,0 +1,68 @@
+from django.conf.urls import patterns, include, url
+
+# Uncomment the next two lines to enable the admin:
+from django.contrib import admin
+from plstackapi.core.views.roles import RoleListCreate, RoleRetrieveUpdateDestroy
+from plstackapi.core.views.sites import SiteListCreate, SiteRetrieveUpdateDestroy
+from plstackapi.core.views.users import UserListCreate, UserRetrieveUpdateDestroy
+from plstackapi.core.views.keys import KeyListCreate, KeyRetrieveUpdateDestroy
+from plstackapi.core.views.deployment_networks import DeploymentNetworkListCreate, DeploymentNetworkRetrieveUpdateDestroy
+from plstackapi.core.views.images import ImageListCreate, ImageRetrieveUpdateDestroy
+from plstackapi.core.views.flavors import FlavorListCreate, FlavorRetrieveUpdateDestroy
+from plstackapi.core.models import Site
+from plstackapi.planetstack.api_root import api_root
+from rest_framework import generics
+
+admin.autodiscover()
+
+urlpatterns = patterns('',
+    # Examples:
+    # url(r'^$', 'planetstack.views.home', name='home'),
+    # url(r'^planetstack/', include('planetstack.foo.urls')),
+
+    # Uncomment the admin/doc line below to enable admin documentation:
+    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
+
+    # Uncomment the next line to enable the admin:
+    url(r'^admin/', include(admin.site.urls)),
+
+    url(r'^plstackapi/$', api_root),
+    
+    url(r'^plstackapi/roles/$', RoleListCreate.as_view(), name='role-list'),
+    url(r'^plstackapi/roles/(?P<pk>[a-zA-Z0-9]+)/$', RoleRetrieveUpdateDestroy.as_view(), name='role-detail'),
+
+    url(r'^plstackapi/users/$', UserListCreate.as_view(), name='user-list'),
+    url(r'^plstackapi/users/(?P<pk>[a-zA-Z0-9]+)/$', UserRetrieveUpdateDestroy.as_view(), name='user-detail'),
+
+    url(r'^plstackapi/keys/$', KeyListCreate.as_view(), name='key-list'),
+    url(r'^plstackapi/keys/(?P<pk>[a-zA-Z0-9]+)/$', KeyRetrieveUpdateDestroy.as_view(), name='key-detail'),
+
+    url(r'^plstackapi/sites/$', SiteListCreate.as_view(), name='site-list'),
+    url(r'^plstackapi/sites/(?P<pk>[a-zA-Z0-9_]+)/$', SiteRetrieveUpdateDestroy.as_view(), name='site-detail'),
+
+
+    #url(r'^plstackapi/slices/$', views.SliceList.as_view(), name='slice-list'),
+    #url(r'^plstackapi/slices/(?P<pk>[0-9]+)/$', views.SliceDetail.as_view(), name='slice-detail'),
+
+    #url(r'^plstackapi/slivers/$', views.SliverList.as_view()),
+    #url(r'^plstackapi/slivers/(?P<pk>[0-9]+)/$', views.SliverDetail.as_view()),
+
+    #url(r'^plstackapi/nodes/$', views.NodeList.as_view(), name='node-list'),
+    #url(r'^plstackapi/nodes/(?P<pk>[0-9]+)/$', views.NodeDetail.as_view(), name='node-detail'),
+
+    
+    url(r'^plstackapi/deploymentnetworks/$', DeploymentNetworkListCreate.as_view(), name='deploymentnetwork-list'),
+    url(r'^plstackapi/deploymentnetworks/(?P<pk>[a-zA-Z0-9]+)/$', DeploymentNetworkRetrieveUpdateDestroy.as_view(), name='deploymentnetwork-detail'),
+
+    #url(r'^plstackapi/sitedeploymentnetworks/$', views.SiteDeploymentNetworkList.as_view(), name='sitedeploymentnetwork-list'),
+    #url(r'^plstackapi/sitedeploymentnetworks/(?P<pk>[0-9]+)/$', views.SiteDeploymentNetworkDetail.as_view(), name='sitedeploymentnetwork-detail'),
+
+    url(r'^plstackapi/images/$', ImageListCreate.as_view(), name='image-list'),
+    url(r'^plstackapi/images/(?P<pk>[a-zA-Z0-9_]+)/$', ImageRetrieveUpdateDestroy.as_view(), name='image-detail'),
+
+    url(r'^plstackapi/flavors/$', FlavorListCreate.as_view(), name='flavor-list'),
+    url(r'^plstackapi/flavors/(?P<pk>[a-zA-Z0-9_]+)/$', FlavorRetrieveUpdateDestroy.as_view(), name='flavor-detail'),
+    #Adding in rest_framework urls
+    url(r'^plstackapi/', include('rest_framework.urls', namespace='rest_framework')),
+    
+)
diff --git a/plstackapi/core/views/__init__.py b/plstackapi/core/views/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plstackapi/core/views/__init__.py
diff --git a/plstackapi/core/views/api_root.py b/plstackapi/core/views/api_root.py
new file mode 100644
index 0000000..10ceae1
--- /dev/null
+++ b/plstackapi/core/views/api_root.py
@@ -0,0 +1,17 @@
+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)
+        'images': reverse('image-list', request=request, format=format),
+        'flavors': reverse('flavor-list', request=request, format=format),
+    })
diff --git a/plstackapi/core/views/deployment_networks.py b/plstackapi/core/views/deployment_networks.py
new file mode 100644
index 0000000..60e8030
--- /dev/null
+++ b/plstackapi/core/views/deployment_networks.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 plstackapi.core.api.deployment_networks import add_deployment_network, delete_deployment_network, get_deployment_networks
+from plstackapi.core.serializers import DeploymentNetworkSerializer
+from plstackapi.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 'deployment_network' in data:
+            deployment = add_deployment_network(data['auth'], data['deployment_network'].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'], {'name': 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'], {'name': pk})
+        return Response(status=status.HTTP_204_NO_CONTENT) 
+            
+            
+        
diff --git a/plstackapi/core/views/flavors.py b/plstackapi/core/views/flavors.py
new file mode 100644
index 0000000..ef48499
--- /dev/null
+++ b/plstackapi/core/views/flavors.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 plstackapi.core.api.flavors import add_flavor, delete_flavor, get_flavors
+from plstackapi.core.serializers import FlavorSerializer
+from plstackapi.util.request import parse_request
+
+
+class FlavorListCreate(APIView):
+    """ 
+    List all flavors or create a new flavor.
+    """
+
+    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 'flavor' in data:
+            """Not Implemented"""
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        else:
+            flavors = get_flavors(data['auth'])
+            serializer = FlavorSerializer(flavors, many=True)
+            return Response(serializer.data)
+        
+            
+class FlavorRetrieveUpdateDestroy(APIView):
+    """
+    Retrieve, update or delete an flavor  
+    """
+
+    def post(self, request, pk, format=None):
+        """Retrieve an flavor """
+        data = parse_request(request.DATA)
+        if 'auth' not in data:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        flavors = get_flavors(data['auth'], {'id': pk})
+        if not flavors:
+            return Response(status=status.HTTP_404_NOT_FOUND)
+        serializer = FlavorSerializer(flavors[0])
+        return Response(serializer.data)                  
+
+    def put(self, request, pk, format=None):
+        """update flavor not implemnted""" 
+        return Response(status=status.HTTP_404_NOT_FOUND) 
+
+    def delete(self, request, pk, format=None):
+        """delete flavor not implemnted""" 
+        return Response(status=status.HTTP_404_NOT_FOUND) 
+
+            
+            
+        
diff --git a/plstackapi/core/views/images.py b/plstackapi/core/views/images.py
new file mode 100644
index 0000000..f48cb71
--- /dev/null
+++ b/plstackapi/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 plstackapi.core.api.images import add_image, delete_image, get_images
+from plstackapi.core.serializers import ImageSerializer
+from plstackapi.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'], {'id': 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/plstackapi/core/views/keys.py b/plstackapi/core/views/keys.py
new file mode 100644
index 0000000..6b52b8e
--- /dev/null
+++ b/plstackapi/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 plstackapi.core.api.keys import add_key, delete_key, get_keys, update_key
+from plstackapi.core.serializers import KeySerializer
+from plstackapi.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'], {'id': 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'], {'id': pk})
+        return Response(status=status.HTTP_204_NO_CONTENT) 
+            
+            
+        
diff --git a/plstackapi/core/views/roles.py b/plstackapi/core/views/roles.py
new file mode 100644
index 0000000..05eb77e
--- /dev/null
+++ b/plstackapi/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 plstackapi.core.api.roles import add_role, delete_role, get_roles
+from plstackapi.core.serializers import RoleSerializer
+from plstackapi.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']['name'])
+            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'], {'role_id': 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'], {'role_id': pk})
+        return Response(status=status.HTTP_204_NO_CONTENT) 
+            
+            
+        
diff --git a/plstackapi/core/views/sites.py b/plstackapi/core/views/sites.py
new file mode 100644
index 0000000..700547c
--- /dev/null
+++ b/plstackapi/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 plstackapi.core.api.sites import add_site, delete_site, get_sites
+from plstackapi.core.serializers import SiteSerializer
+from plstackapi.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/plstackapi/core/views/users.py b/plstackapi/core/views/users.py
new file mode 100644
index 0000000..0ec867f
--- /dev/null
+++ b/plstackapi/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 plstackapi.core.api.users import add_user, delete_user, get_users, update_user
+from plstackapi.core.serializers import UserSerializer
+from plstackapi.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) 
+            
+            
+