Merge branch 'master' of git://git.planet-lab.org/plstackapi
diff --git a/planetstack/core/admin.py b/planetstack/core/admin.py
index c9d3172..f4a78a3 100644
--- a/planetstack/core/admin.py
+++ b/planetstack/core/admin.py
@@ -542,7 +542,7 @@
       self.fields['accessControl'].initial = "allow site " + request.user.site.name
 
       if self.instance and self.instance.pk:
-        self.fields['sites'].initial = [x.site for x in self.instance.sitedeployments.all()]
+        self.fields['sites'].initial = [x for x in self.instance.sites.all()]
         self.fields['images'].initial = [x.image for x in self.instance.imagedeployments.all()]
         self.fields['flavors'].initial = self.instance.flavors.all()
 
@@ -594,7 +594,7 @@
         #    create/destroy the through models ourselves. There has to be
         #    a better way...
 
-        self.manipulate_m2m_objs(deployment, self.cleaned_data['sites'], deployment.sitedeployments.all(), SiteDeployment, "deployment", "site")
+        self.manipulate_m2m_objs(deployment, self.cleaned_data['sites'], deployment.sitedeployment.all(), SiteDeployment, "deployment", "site")
         self.manipulate_m2m_objs(deployment, self.cleaned_data['images'], deployment.imagedeployments.all(), ImageDeployments, "deployment", "image")
         # manipulate_m2m_objs doesn't work for Flavor/Deployment relationship
         # so well handle that manually here
diff --git a/planetstack/core/dashboard/views/view_common.py b/planetstack/core/dashboard/views/view_common.py
index f05d40a..bccd7d2 100644
--- a/planetstack/core/dashboard/views/view_common.py
+++ b/planetstack/core/dashboard/views/view_common.py
@@ -73,14 +73,14 @@
         for sliver in slice.slivers.all():
              #sites_used['deploymentSites'] = sliver.node.deployment.name
              # sites_used[sliver.image.name] = sliver.image.name
-             sites_used[sliver.node.site.name] = 1 #sliver.numberCores
+             sites_used[sliver.node.site_deployment.site.name] = 1 #sliver.numberCores
         sliceid = Slice.objects.get(id=entry.slice.id).id
         try:
             sliverList = Sliver.objects.filter(slice=entry.slice.id)
             siteList = {}
             for x in sliverList:
-               if x.node.site not in siteList:
-                  siteList[x.node.site] = 1
+               if x.node.site_deployment.site not in siteList:
+                  siteList[x.node.site_deployment.site] = 1
             slivercount = len(sliverList)
             sitecount = len(siteList)
         except:
diff --git a/planetstack/core/xoslib/methods/sliceplus.py b/planetstack/core/xoslib/methods/sliceplus.py
index 48102df..25e4d1e 100644
--- a/planetstack/core/xoslib/methods/sliceplus.py
+++ b/planetstack/core/xoslib/methods/sliceplus.py
@@ -15,11 +15,19 @@
     # rest_framework 2.x
     IdField = serializers.Field
 
+class NetworkPortsField(serializers.WritableField):   # note: maybe just Field in rest_framework 3.x instead of WritableField
+    def to_representation(self, obj):
+        return obj
+
+    def to_internal_value(self, data):
+        return data
+
 class SlicePlusIdSerializer(serializers.ModelSerializer, PlusSerializerMixin):
         id = IdField()
 

         sliceInfo = serializers.SerializerMethodField("getSliceInfo")

         humanReadableName = serializers.SerializerMethodField("getHumanReadableName")

+        network_ports = NetworkPortsField()

 

         def getSliceInfo(self, slice):

             return slice.getSliceInfo(user=self.context['request'].user)

@@ -27,12 +35,12 @@
         def getHumanReadableName(self, obj):

             return str(obj)

 

-        networks = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='network-detail')

-        availableNetworks = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='network-detail')

+        networks = serializers.PrimaryKeyRelatedField(many=True, read_only=True)

+#        availableNetworks = serializers.PrimaryKeyRelatedField(many=True, read_only=True, view_name='network-detail')

 

         class Meta:

             model = SlicePlus

-            fields = ('humanReadableName', 'id','created','updated','enacted','name','enabled','omf_friendly','description','slice_url','site','max_slivers','image_preference','service','network','mount_data_sets','serviceClass','creator','networks','availableNetworks','sliceInfo','backendIcon','backendHtml')
+            fields = ('humanReadableName', 'id','created','updated','enacted','name','enabled','omf_friendly','description','slice_url','site','max_slivers','image_preference','service','network','mount_data_sets','serviceClass','creator','networks','sliceInfo','network_ports','backendIcon','backendHtml')
 
 class SlicePlusList(generics.ListCreateAPIView):
     queryset = SlicePlus.objects.select_related().all()
diff --git a/planetstack/core/xoslib/methods/tenantview.py b/planetstack/core/xoslib/methods/tenantview.py
new file mode 100644
index 0000000..c7ce500
--- /dev/null
+++ b/planetstack/core/xoslib/methods/tenantview.py
@@ -0,0 +1,64 @@
+from rest_framework.decorators import api_view
+from rest_framework.response import Response

+from rest_framework.reverse import reverse

+from rest_framework import serializers

+from rest_framework import generics

+from rest_framework.views import APIView

+from core.models import *

+from django.forms import widgets
+from syndicate_storage.models import Volume
+
+# This REST API endpoint contains a bunch of misc information that the
+# tenant view needs to display
+
+BLESSED_DEPLOYMENTS = ["ViCCI"] # ["US-MaxPlanck", "US-GeorgiaTech", "US-Princeton", "US-Washington", "US-Stanford"]
+
+
+def getTenantViewDict():
+    blessed_sites = []
+    for site in Site.objects.all():
+        good=False
+        for deployment in site.deployments.all():
+            if deployment.name in BLESSED_DEPLOYMENTS:
+                good=True
+        if good:
+            blessed_sites.append(site)
+
+    blessed_images=[]
+    for image in Image.objects.all():
+        good = False
+        for deployment in image.deployments.all():
+            if deployment.name in BLESSED_DEPLOYMENTS:
+                 good=True
+        if good:
+            blessed_images.append(image)
+
+    volumes=[]
+    for volume in Volume.objects.all():
+        if not volume.private:

+            volumes.append(volume)
+
+    return {"id": 0,
+            "blessed_deployment_names": BLESSED_DEPLOYMENTS,
+            "blessed_site_names": [site.name for site in blessed_sites],
+            "blessed_sites": [site.id for site in blessed_sites],
+            "blessed_image_names": [image.name for image in blessed_images],
+            "blessed_images": [image.id for image in blessed_images],
+            "public_volume_names": [volume.name for volume in volumes],
+            "public_volumes": [volume.id for volume in volumes],
+            }
+
+class TenantList(APIView):
+    method_kind = "list"
+    method_name = "tenantview"
+
+    def get(self, request, format=None):
+        return Response( getTenantViewDict() )
+
+class TenantDetail(APIView):
+    method_kind = "detail"
+    method_name = "tenantview"
+
+    def get(self, request, format=None, pk=0):
+        return Response( [getTenantViewDict()] )
+
diff --git a/planetstack/core/xoslib/objects/sliceplus.py b/planetstack/core/xoslib/objects/sliceplus.py
index ddec295..efb6b2a 100644
--- a/planetstack/core/xoslib/objects/sliceplus.py
+++ b/planetstack/core/xoslib/objects/sliceplus.py
@@ -26,6 +26,23 @@
                 "siteCount": len(used_sites.keys()),
                 "roles": roles}
 
+    @property
+    def network_ports(self):
+        # XXX this assumes there is only one network that can have ports bound
+        # to it for a given slice. This is intended for the tenant view, which
+        # will obey this field.
+        networkPorts = ""
+        for networkSlice in self.networkslices.all():
+            network = networkSlice.network
+            if network.ports:
+                networkPorts = network.ports
+
+        return networkPorts
+
+    @network_ports.setter
+    def network_ports(self, value):
+        print "XXX set networkPorts to", value
+
     @staticmethod
     def select_by_user(user):
         if user.is_admin:
diff --git a/planetstack/openstack/client.py b/planetstack/openstack/client.py
index 72c5cb4..0aa6c7d 100644
--- a/planetstack/openstack/client.py
+++ b/planetstack/openstack/client.py
@@ -84,7 +84,7 @@
         return getattr(self.client, name)
 
 
-class GlanceClient(Client):
+class Glance(Client):
     def __init__(self, *args, **kwds):
         Client.__init__(self, *args, **kwds)
         if has_openstack:
@@ -97,11 +97,15 @@
     def __getattr__(self, name):
         return getattr(self.client, name)
 
-class GlanceClientNew(Client):
-    def __init__(self, version, endpoint, token, *args, **kwds):
+class GlanceClient(Client):
+    def __init__(self, version, endpoint, token, cacert=None, *args, **kwds):
         Client.__init__(self, *args, **kwds)
         if has_openstack:
-            self.client = glanceclient.Client(version, endpoint=endpoint, token=token)
+            self.client = glanceclient.Client(version, 
+                endpoint=endpoint, 
+                token=token,
+                cacert=cacert
+            )
 
     @require_enabled
     def __getattr__(self, name):
@@ -174,9 +178,9 @@
         url_parsed = urlparse.urlparse(self.keystone.url)
         hostname = url_parsed.netloc.split(':')[0]
         token = self.keystone.client.tokens.authenticate(username=self.keystone.username, password=self.keystone.password, tenant_name=self.keystone.tenant)
-        #self.glance = GlanceClient(*args, **kwds)
+        glance_endpoint = self.keystone.service_catalog.url_for(service_type='image', endpoint_type='publicURL')
         
-        self.glanceclient = GlanceClientNew('1', endpoint='https://%s:9292' % hostname, token=token.id, **kwds)
+        self.glanceclient = GlanceClient('1', endpoint=glance_endpoint, 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 53b8e3f..2edf10e 100644
--- a/planetstack/openstack/driver.py
+++ b/planetstack/openstack/driver.py
@@ -32,7 +32,7 @@
             auth = {'username': caller.email,
                     'password': hashlib.md5(caller.password).hexdigest()[:6],
                     'tenant': tenant}
-            client = OpenStackClient(controller=controller, **auth)
+            client = OpenStackClient(controller=controller, cacert=self.config.nova_ca_ssl_cert, **auth)
         else:
             admin_driver = self.admin_driver(tenant=tenant, controller=controller)
             client = OpenStackClient(tenant=tenant, controller=admin_driver.controller)
@@ -45,7 +45,7 @@
     def admin_driver(self, tenant=None, controller=None):
         if isinstance(controller, int):
             controller = Controller.objects.get(id=controller.id)
-        client = OpenStackClient(tenant=tenant, controller=controller)
+        client = OpenStackClient(tenant=tenant, controller=controller, cacert=self.config.nova_ca_ssl_cert)
         driver = OpenStackDriver(client=client)
         driver.admin_user = client.keystone.users.find(name=controller.admin_user)
         driver.controller = controller
diff --git a/planetstack/plstackapi_config b/planetstack/plstackapi_config
index a61e7ed..fb846b3 100644
--- a/planetstack/plstackapi_config
+++ b/planetstack/plstackapi_config
@@ -29,6 +29,7 @@
 default_image=None
 default_flavor=m1.small
 default_security_group=default
+ca_ssl_cert=/etc/ssl/certs/ca-certificates.crt
 
 [observer]
 images_directory=/opt/planetstack/images