Merge branch 'master' of ssh://git.planet-lab.org/git/plstackapi
diff --git a/planetstack/core/tests.py b/planetstack/core/tests.py
new file mode 100644
index 0000000..1c490c8
--- /dev/null
+++ b/planetstack/core/tests.py
@@ -0,0 +1,128 @@
+#!/usr/bin/python
+from django.test import TestCase
+from core.models import *
+from rest_framework.test import *
+from genapi import *
+import json
+from datetime import datetime
+
+FIXTURES_FILE = 'core/fixtures/initial_data.json'
+MODELS = ['Deployment','Image','Node','Reservation','Slice','Sliver','User']
+
+def is_dynamic_type(x):
+	t = type(x)
+	return t in [datetime]
+
+class APITestCase(TestCase):
+	def setUp(self):
+		self.init_data=json.loads(open(FIXTURES_FILE).read())
+		self.data_dict={}
+		self.hidden_keys={}
+
+		for d in self.init_data:
+			model_tag = d['model']
+			model_name = model_tag.split('.')[1]
+
+			try:
+				self.data_dict[model_name].append(d)
+			except:
+				self.data_dict[model_name]=[d]
+
+		# Any admin user would do
+		self.calling_user = User('sapan@onlab.us')
+		self.client = APIClient()
+		self.client.force_authenticate(user=self.calling_user)
+
+
+	def check_items(self, response, data_list):
+		rdict = {}
+		for r in response:
+			rdict['%d'%r['id']]=r
+
+		for d in data_list:
+			match = True
+			try:
+				item = rdict['%d'%d['pk']]
+			except Exception,e:
+				print 'API missing item %d / %r'%(d['pk'],rdict.keys())
+				raise e
+
+			fields=d['fields']
+			fields['id']=d['pk']
+
+			for k in item.keys():
+				try:
+					resp_val = fields[k]
+				except KeyError:
+					if (not self.hidden_keys.has_key(k)):
+						print 'Hidden key %s'%k
+						self.hidden_keys[k]=True
+
+					continue
+
+				if (item[k]!=resp_val and not is_dynamic_type(item[k])):
+					if (type(resp_val)==type(item[k])):
+						print 'Key %s did not match: 1. %r 2. %r'%(k,item[k],resp_val)
+						print fields
+						match = False
+
+
+
+	def create(self, model, mplural, record):
+		request = self.client.put('/plstackapi/%s/'%mplural,record['fields'])
+
+		#if (len2==len1):
+		#	raise Exception('Could not delete %s/%d'%(model,pk))
+
+		return
+
+	def update(self, model, mplural, pk):
+		src_record = self.data_dict[model.lower()][0]
+		record_to_update = src_record['fields']
+		now = datetime.now()
+		record_to_update['enacted']=now
+		response = self.client.put('/plstackapi/%s/%d/'%(mplural,pk),record_to_update)
+		self.assertEqual(response.data['enacted'],now)
+
+		return
+
+	def delete(self, model, mplural, pk):
+		mclass = globals()[model]
+		len1 = len(mclass.objects.all())
+		response = self.client.delete('/plstackapi/%s/%d/'%(mplural,pk))
+		len2 = len(mclass.objects.all())
+		self.assertNotEqual(len1,len2)
+
+		return
+
+	def retrieve(self, m, mplural, mlower):
+		response = self.client.get('/plstackapi/%s/'%mplural)
+		#force_authenticate(request,user=self.calling_user)
+		self.check_items(response.data,self.data_dict[mlower])
+
+		return
+
+	def test_initial_retrieve(self):
+		for m in MODELS:
+			print 'Checking retrieve on %s...'%m
+			self.retrieve(m, m.lower()+'s',m.lower())
+
+	
+	def test_update(self):
+		for m in MODELS:
+			print 'Checking update on %s...'%m
+			first = self.data_dict[m.lower()][0]['pk']
+			self.update(m, m.lower()+'s',int(first))
+	
+	def test_delete(self):
+		for m in MODELS:
+			print 'Checking delete on %s...'%m
+			first = self.data_dict[m.lower()][0]['pk']
+			self.delete(m, m.lower()+'s',int(first))
+
+	def test_create(self):
+		for m in MODELS:
+			print 'Checking create on %s...'%m
+			first = self.data_dict[m.lower()][0]
+			self.create(m, m.lower()+'s',first)
+
diff --git a/planetstack/observer/steps/garbage_collector.py b/planetstack/observer/steps/garbage_collector.py
index 6feff14..7c42922 100644
--- a/planetstack/observer/steps/garbage_collector.py
+++ b/planetstack/observer/steps/garbage_collector.py
@@ -6,7 +6,6 @@
 from planetstack.config import Config
 from util.logger import Logger, logging
 from observer.openstacksyncstep import OpenStackSyncStep
-from core.models.deployment import Deployment
 from core.models import *
 
 logger = Logger(logfile='/var/log/observer.log', level=logging.INFO)
diff --git a/planetstack/observer/steps/sync_image_deployments.py b/planetstack/observer/steps/sync_image_deployments.py
index 3957e74..4a69b1c 100644
--- a/planetstack/observer/steps/sync_image_deployments.py
+++ b/planetstack/observer/steps/sync_image_deployments.py
@@ -4,8 +4,8 @@
 from django.db.models import F, Q
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
-from core.models.deployment import Deployment
-from core.models.image import Image, ImageDeployments
+from core.models import Deployment
+from core.models import Image, ImageDeployments
 from util.logger import Logger, logging
 

 logger = Logger(level=logging.INFO)
diff --git a/planetstack/observer/steps/sync_nodes.py b/planetstack/observer/steps/sync_nodes.py
index ecd32b4..030d57c 100644
--- a/planetstack/observer/steps/sync_nodes.py
+++ b/planetstack/observer/steps/sync_nodes.py
@@ -6,8 +6,7 @@
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
 from core.models.node import Node
-from core.models.deployment import Deployment
-from core.models.site import Site
+from core.models.site import Site, Deployment
 
 class SyncNodes(OpenStackSyncStep):
     provides=[Node]
diff --git a/planetstack/observer/steps/sync_roles.py b/planetstack/observer/steps/sync_roles.py
index ca85d57..e3a20e9 100644
--- a/planetstack/observer/steps/sync_roles.py
+++ b/planetstack/observer/steps/sync_roles.py
@@ -4,9 +4,8 @@
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
 from core.models.role import Role
-from core.models.site import SiteRole
+from core.models.site import SiteRole, Deployment, DeploymentRole
 from core.models.slice import SliceRole
-from core.models.deployment import Deployment, DeploymentRole
 
 class SyncRoles(OpenStackSyncStep):
     provides=[Role]
diff --git a/planetstack/observer/steps/sync_site_deployments.py b/planetstack/observer/steps/sync_site_deployments.py
index a996c85..fa89d2c 100644
--- a/planetstack/observer/steps/sync_site_deployments.py
+++ b/planetstack/observer/steps/sync_site_deployments.py
@@ -21,7 +21,7 @@
             site_deployment.tenant_id = tenant.id
             site_deployment.save()
         elif site_deployment.site.id and site_deployment.tenant_id:
-            driver = self.driver.admin_driver(deployment=site_deployment.name)
+            driver = self.driver.admin_driver(deployment=site_deployment.deployment.name)
             driver.update_tenant(site_deployment.tenant_id,
                                  description=site_deployment.site.name,
                                  enabled=site_deployment.site.enabled)
diff --git a/planetstack/observer/steps/sync_site_privileges.py b/planetstack/observer/steps/sync_site_privileges.py
index b57ae43..c229257 100644
--- a/planetstack/observer/steps/sync_site_privileges.py
+++ b/planetstack/observer/steps/sync_site_privileges.py
@@ -3,8 +3,7 @@
 from django.db.models import F, Q
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
-from core.models.site import *
-from core.models.user import User, UserDeployments    
+from core.models import User, UserDeployments, SitePrivilege, SiteDeployments   
 
 class SyncSitePrivileges(OpenStackSyncStep):
     requested_interval=0
diff --git a/planetstack/observer/steps/sync_slice_deployments.py b/planetstack/observer/steps/sync_slice_deployments.py
index b40eb6b..7cce152 100644
--- a/planetstack/observer/steps/sync_slice_deployments.py
+++ b/planetstack/observer/steps/sync_slice_deployments.py
@@ -5,10 +5,9 @@
 from django.db.models import F, Q
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
-from core.models.deployment import Deployment
-from core.models.site import SiteDeployments
+from core.models.site import Deployment, SiteDeployments
 from core.models.slice import Slice, SliceDeployments
-from core.models.user import UserDeployments
+from core.models.userdeployments import UserDeployments
 from util.logger import Logger, logging
 
 logger = Logger(level=logging.INFO)
diff --git a/planetstack/observer/steps/sync_slice_memberships.py b/planetstack/observer/steps/sync_slice_memberships.py
index 38bd26c..d2ec03e 100644
--- a/planetstack/observer/steps/sync_slice_memberships.py
+++ b/planetstack/observer/steps/sync_slice_memberships.py
@@ -4,7 +4,7 @@
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
 from core.models.slice import *
-from core.models.user import UserDeployments
+from core.models.userdeployments import UserDeployments
 from util.logger import Logger, logging
 
 logger = Logger(level=logging.INFO)
diff --git a/planetstack/observer/steps/sync_user_deployments.py b/planetstack/observer/steps/sync_user_deployments.py
index 39943f7..a6995ab 100644
--- a/planetstack/observer/steps/sync_user_deployments.py
+++ b/planetstack/observer/steps/sync_user_deployments.py
@@ -6,7 +6,8 @@
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
 from core.models.site import SiteDeployments, Deployment
-from core.models.user import User, UserDeployments
+from core.models.user import User
+from core.models.userdeployments import UserDeployments
 from util.logger import Logger, logging
 
 logger = Logger(level=logging.INFO)
diff --git a/planetstack/observer/steps/sync_users.py b/planetstack/observer/steps/sync_users.py
index 71f9c0f..9d88918 100644
--- a/planetstack/observer/steps/sync_users.py
+++ b/planetstack/observer/steps/sync_users.py
@@ -4,7 +4,8 @@
 from django.db.models import F, Q
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
-from core.models.user import User, UserDeployments
+from core.models.user import User
+from core.models.userdeployments import  UserDeployments
 
 class SyncUsers(OpenStackSyncStep):
     provides=[User]
diff --git a/planetstack/openstack/client.py b/planetstack/openstack/client.py
index 162e506..af91387 100644
--- a/planetstack/openstack/client.py
+++ b/planetstack/openstack/client.py
@@ -42,7 +42,7 @@
 
 class Client:
     def __init__(self, username=None, password=None, tenant=None, url=None, token=None, endpoint=None, deployment=None, admin=True, *args, **kwds):
-        
+       
         self.has_openstack = has_openstack
         self.url = deployment.auth_url
         if admin:
@@ -193,7 +193,7 @@
         self.keystone_db = KeystoneDB()
         self.glance = GlanceClient(*args, **kwds)
         
-        self.glanceclient = GlanceClientNew('1', endpoint='http://%s:9292' % hostname, token=token.id)
+        self.glanceclient = GlanceClientNew('1', endpoint='http://%s:9292' % hostname, token=token.id, **kwds)
         self.nova = NovaClient(*args, **kwds)
         self.nova_db = NovaDB(*args, **kwds)
         self.quantum = QuantumClient(*args, **kwds)
diff --git a/planetstack/openstack/driver.py b/planetstack/openstack/driver.py
index 8ebea68..c3e1f35 100644
--- a/planetstack/openstack/driver.py
+++ b/planetstack/openstack/driver.py
@@ -1,6 +1,7 @@
 import commands
 import hashlib
 from planetstack.config import Config
+from core.models import Deployment
 
 try:
     from openstack.client import OpenStackClient
@@ -12,38 +13,41 @@
 
 class OpenStackDriver:
 
-    def __init__(self, config = None, client=None, deployment=None):
+    def __init__(self, config = None, client=None):
         if config:
             self.config = Config(config)
         else:
             self.config = Config()
 
-        self.admin_client = OpenStackClient(deployment=deployment)
-        self.admin_user = self.admin_client.keystone.users.find(name=self.admin_client.keystone.username)
-
         if client:
             self.shell = client
-        else:
-            self.shell = OpenStackClient(deployment=deployment)
 
         self.enabled = manager_enabled
         self.has_openstack = has_openstack
+        self.deployment = None
+        self.admin_user = None
 
     def client_driver(self, caller=None, tenant=None, deployment=None):
+        admin_driver = self.admin_driver(tenant=tenant, deployment=deployment)
         if caller:
             auth = {'username': caller.email,
                     'password': hashlib.md5(caller.password).hexdigest()[:6],
                     'tenant': tenant}
-            client = OpenStackClient(deployment=deployment, **auth)
+            client = OpenStackClient(deployment=admin_driver.deployment, **auth)
         else:
-            client = OpenStackClient(tenant=tenant, deployment=deployment)
+            client = OpenStackClient(tenant=tenant, deployment=admin_driver.deployment)
 
-        driver = OpenStackDriver(client=client, deployment=deployment)
+        driver = OpenStackDriver(client=client)
+        driver.admin_user = admin_driver.admin_user
+        driver.deployment = admin_driver.deployment
         return driver
 
     def admin_driver(self, tenant=None, deployment=None):
+        deployment = Deployment.objects.get(name=deployment)
         client = OpenStackClient(tenant=tenant, deployment=deployment)
-        driver = OpenStackDriver(client=client, deployment=deployment)
+        driver = OpenStackDriver(client=client)
+        driver.admin_user = client.keystone.users.find(name=deployment.admin_user)
+        driver.deployment = deployment
         return driver    
 
     def create_role(self, name):
diff --git a/planetstack/planetstack/urls.py b/planetstack/planetstack/urls.py
index ca997d9..eb7f40c 100644
--- a/planetstack/planetstack/urls.py
+++ b/planetstack/planetstack/urls.py
@@ -36,12 +36,27 @@
 
     url(r'^plstackapi/$', api_root),
 
+    url(r'^plstackapi/dashboardviews/$', DashboardViewList.as_view(), name='dashboardview-list'),
+    url(r'^plstackapi/dashboardview/(?P<pk>[a-zA-Z0-9\-]+)/$', DashboardViewDetail.as_view(), name='dashboardview-detail'),
+
+    url(r'^plstackapi/payments/$', PaymentList.as_view(), name='payment-list'),
+    url(r'^plstackapi/payments/(?P<pk>[a-zA-Z0-9\-]+)/$', PaymentDetail.as_view(), name='payment-detail'),
+
+    url(r'^plstackapi/charges/$', ChargeList.as_view(), name='charge-list'),
+    url(r'^plstackapi/charges/(?P<pk>[a-zA-Z0-9\-]+)/$', ChargeDetail.as_view(), name='charge-detail'),
+
+    url(r'^plstackapi/accounts/$', AccountList.as_view(), name='account-list'),
+    url(r'^plstackapi/accounts/(?P<pk>[a-zA-Z0-9\-]+)/$', AccountDetail.as_view(), name='account-detail'),
+
     url(r'^plstackapi/deployments/$', DeploymentList.as_view(), name='deployment-list'),
     url(r'^plstackapi/deployments/(?P<pk>[a-zA-Z0-9\-]+)/$', DeploymentDetail.as_view(), name='deployment-detail'),
 
     url(r'^plstackapi/images/$', ImageList.as_view(), name='image-list'),
     url(r'^plstackapi/images/(?P<pk>[a-zA-Z0-9_\-]+)/$', ImageDetail.as_view(), name='image-detail'),
 
+    url(r'^plstackapi/networkparametertypes/$', NodeList.as_view(), name='node-list'),
+    url(r'^plstackapi/networkparametertypes/(?P<pk>[a-zA-Z0-9_\-]+)/$', NodeDetail.as_view(), name='node-detail'),
+
     url(r'^plstackapi/nodes/$', NodeList.as_view(), name='node-list'),
     url(r'^plstackapi/nodes/(?P<pk>[a-zA-Z0-9_\-]+)/$', NodeDetail.as_view(), name='node-detail'),
     
@@ -66,10 +81,19 @@
     url(r'^plstackapi/sites/$', SiteList.as_view(), name='site-list'),
     url(r'^plstackapi/sites/(?P<pk>[a-zA-Z0-9_\-]+)/$', SiteDetail.as_view(), name='site-detail'),
 
-	url(r'^plstackapi/networks/$', NetworkList.as_view(), name='network-list'),
-	url(r'^plstackapi/networks/(?P<pk>[a-zA-Z0-9_\-]+)/$', NetworkDetail.as_view(), name='network-detail'),
-	
-	url(r'^plstackapi/services/$', SliceList.as_view(), name='service-list'),
+    url(r'^plstackapi/accounts/$', AccountList.as_view(), name='account-list'),
+    url(r'^plstackapi/accounts/(?P<pk>[a-zA-Z0-9_\-]+)/$', AccountDetail.as_view(), name='account-detail'),
+
+    url(r'^plstackapi/networktemplates/$', NetworkSliceList.as_view(), name='networkslice-list'),
+    url(r'^plstackapi/networktemplates/(?P<pk>[a-zA-Z0-9_\-]+)/$', NetworkSliceDetail.as_view(), name='networkslice-detail'),
+
+    url(r'^plstackapi/networkslices/$', NetworkSliceList.as_view(), name='networkslice-list'),
+    url(r'^plstackapi/networkslices/(?P<pk>[a-zA-Z0-9_\-]+)/$', NetworkSliceDetail.as_view(), name='networkslice-detail'),
+
+    url(r'^plstackapi/networks/$', NetworkList.as_view(), name='network-list'),
+    url(r'^plstackapi/networks/(?P<pk>[a-zA-Z0-9_\-]+)/$', NetworkDetail.as_view(), name='network-detail'),
+    
+    url(r'^plstackapi/services/$', SliceList.as_view(), name='service-list'),
     url(r'^plstackapi/services/(?P<pk>[a-zA-Z0-9_\-]+)/$', SliceDetail.as_view(), name='service-detail'),
 
     url(r'^plstackapi/slices/$', SliceList.as_view(), name='slice-list'),