Merge branch 'feature/subscriber-portal' of github.com:open-cloud/xos into feature/subscriber-portal
diff --git a/xos/configurations/cord/cord.yaml b/xos/configurations/cord/cord.yaml
index 89db720..565c419 100644
--- a/xos/configurations/cord/cord.yaml
+++ b/xos/configurations/cord/cord.yaml
@@ -118,7 +118,7 @@
                     "defaultVlan" : "1"
                   },
                   "basic" : {
-                    "driver" : "default"
+                    "driver" : "pmc-olt"
                   }
                 }
               }
@@ -453,6 +453,18 @@
         path: andybavier/docker-vcpe
         tag: develop
 
+    # Let's add a user who can be administrator of the household
+    johndoe@myhouse.com:
+      type: tosca.nodes.User
+      properties:
+          password: letmein
+          firstname: john
+          lastname: doe
+      requirements:
+          - site:
+              node: mysite
+              relationship: tosca.relationships.MemberOfSite
+
     # A subscriber
     My House:
        type: tosca.nodes.CORDSubscriber
@@ -462,6 +474,10 @@
            cdn_enable: false
            url_filter_enable: false
            url_filter_level: R
+       requirements:
+          - house_admin:
+              node: johndoe@myhouse.com
+              relationship: tosca.relationships.AdminPrivilege
 
     Mom's PC:
        type: tosca.nodes.CORDUser
diff --git a/xos/configurations/opencloud/opencloud.yaml b/xos/configurations/opencloud/opencloud.yaml
index 15142a6..0b4a3ed 100644
--- a/xos/configurations/opencloud/opencloud.yaml
+++ b/xos/configurations/opencloud/opencloud.yaml
@@ -329,6 +329,7 @@
       properties:
           display_name: I2-atl
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: backbone
@@ -343,6 +344,7 @@
       properties:
           display_name: I2-chi
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: backbone
@@ -357,6 +359,7 @@
       properties:
           display_name: I2-hou
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: backbone
@@ -371,6 +374,7 @@
       properties:
           display_name: I2-kas
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: backbone
@@ -385,6 +389,7 @@
       properties:
           display_name: I2-lax
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: backbone
@@ -399,6 +404,7 @@
       properties:
           display_name: I2-nyc
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: backbone
@@ -413,6 +419,7 @@
       properties:
           display_name: I2-slc
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: backbone
@@ -427,6 +434,7 @@
       properties:
           display_name: I2-seae
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: backbone
@@ -441,6 +449,7 @@
       properties:
           display_name: I2-sng
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: backbone
@@ -455,6 +464,7 @@
       properties:
           display_name: I2-wdc
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: backbone
@@ -469,6 +479,7 @@
       properties:
           display_name: Princeton
           site_url: http://opencloud.us/
+          hosts_nodes: true
       requirements:
           - deployment:
                node: campus
@@ -483,6 +494,7 @@
       properties:
           display_name: Stanford
           site_url: http://opencloud.us/
+          hosts_nodes: true 
       requirements:
           - deployment:
                node: campus
@@ -497,6 +509,7 @@
       properties:
           display_name: Washington
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: campus
@@ -511,6 +524,7 @@
       properties:
           display_name: GTech
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: campus
@@ -525,6 +539,7 @@
       properties:
           display_name: Arizona
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: campus
@@ -539,6 +554,7 @@
       properties:
           display_name: Internet2
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: campus
@@ -553,6 +569,7 @@
       properties:
           display_name: Singapore
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: campus
@@ -567,6 +584,7 @@
       properties:
           display_name: ON.Lab
           site_url: http://opencloud.us/
+          hosts_nodes: false 
       requirements:
           - deployment:
                node: campus
diff --git a/xos/core/xoslib/methods/cordsubscriber.py b/xos/core/xoslib/methods/cordsubscriber.py
index 49e32a5..0615024 100644
--- a/xos/core/xoslib/methods/cordsubscriber.py
+++ b/xos/core/xoslib/methods/cordsubscriber.py
@@ -228,7 +228,7 @@
 
     def get_users(self, request, pk=None):
         subscriber = self.get_object()
-        return Response({"users": subscriber.users})
+        return Response(subscriber.users)
 
     def get_user_level(self, request, pk=None, uid=None):
         subscriber = self.get_object()
diff --git a/xos/core/xoslib/methods/loginview.py b/xos/core/xoslib/methods/loginview.py
index 51e940d..975a65b 100755
--- a/xos/core/xoslib/methods/loginview.py
+++ b/xos/core/xoslib/methods/loginview.py
@@ -16,6 +16,8 @@
 import django.middleware.csrf
 from xos.exceptions import *
 from django.forms.models import model_to_dict
+from django.contrib.sessions.backends.db import SessionStore
+from django.contrib.sessions.models import Session
 
 def date_handler(obj):
     return obj.isoformat() if hasattr(obj, 'isoformat') else obj
@@ -68,4 +70,33 @@
 
         return self.do_login(request, username, password)
 
+class LogoutView(APIView):
+    method_kind = "list"
+    method_name = "logout"
+
+    def do_logout(self, request, sessionid):
+        if not sessionid:
+            raise XOSMissingField("No xossessionid specified")
+
+        # Make sure the session exists. This prevents us from accidentally
+        # creating empty sessions with SessionStore()
+        session = Session.objects.filter(session_key=sessionid)
+        if not session:
+            # session doesn't exist
+            raise PermissionDenied("Session does not exist")
+
+        session = SessionStore(session_key=sessionid)
+        if "auth" in session:
+            del session["auth"]
+            session.save()
+
+        return Response("Logged Out")
+
+    def get(self, request, format=None):
+        sessionid = request.GET.get("xossessionid", None)
+        return self.do_logout(request, sessionid)
+
+    def post(self, request, format=None):
+        sessionid = request.DATA.get("xossessionid", None)
+        return self.do_logout(request, sessionid)
 
diff --git a/xos/synchronizers/base/xos-synchronizer.py b/xos/synchronizers/base/xos-synchronizer.py
index 3fffd33..493b94a 100644
--- a/xos/synchronizers/base/xos-synchronizer.py
+++ b/xos/synchronizers/base/xos-synchronizer.py
@@ -8,7 +8,7 @@
 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
 from synchronizers.base.backend import Backend
 from xos.config import Config, DEFAULT_CONFIG_FN
-from core.models import Instance
+from core.models import Instance,NetworkTemplate
 from xos.logger import Logger, logging, logger
 from django.db import ProgrammingError
 import time
@@ -67,9 +67,12 @@
     while not models_active:
         try:
             _ = Instance.objects.first()
+            _ = NetworkTemplate.objects.first()
             models_active = True
-        except ProgrammingError:
+        except Exception,e:
+            logger.info(str(e))
             logger.info('Waiting for data model to come up before starting...')
+            time.sleep(10)
             wait = True
 
     if (wait):
diff --git a/xos/synchronizers/openstack/xos-synchronizer.py b/xos/synchronizers/openstack/xos-synchronizer.py
index 3fffd33..493b94a 100644
--- a/xos/synchronizers/openstack/xos-synchronizer.py
+++ b/xos/synchronizers/openstack/xos-synchronizer.py
@@ -8,7 +8,7 @@
 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
 from synchronizers.base.backend import Backend
 from xos.config import Config, DEFAULT_CONFIG_FN
-from core.models import Instance
+from core.models import Instance,NetworkTemplate
 from xos.logger import Logger, logging, logger
 from django.db import ProgrammingError
 import time
@@ -67,9 +67,12 @@
     while not models_active:
         try:
             _ = Instance.objects.first()
+            _ = NetworkTemplate.objects.first()
             models_active = True
-        except ProgrammingError:
+        except Exception,e:
+            logger.info(str(e))
             logger.info('Waiting for data model to come up before starting...')
+            time.sleep(10)
             wait = True
 
     if (wait):
diff --git a/xos/tosca/resources/CORDSubscriber.py b/xos/tosca/resources/CORDSubscriber.py
index 4097ca9..f013032 100644
--- a/xos/tosca/resources/CORDSubscriber.py
+++ b/xos/tosca/resources/CORDSubscriber.py
@@ -6,7 +6,7 @@
 from translator.toscalib.tosca_template import ToscaTemplate
 import pdb
 
-from core.models import User
+from core.models import User, TenantRootPrivilege, TenantRootRole
 from services.cord.models import CordSubscriberRoot
 
 from xosresource import XOSResource
@@ -17,7 +17,8 @@
     copyin_props = ["service_specific_id", "firewall_enable", "url_filter_enable", "cdn_enable", "url_filter_level"]
 
     def postprocess(self, obj):
-        pass
+        rolemap = ( ("tosca.relationships.AdminPrivilege", "admin"), ("tosca.relationships.AccessPrivilege", "access"), )
+        self.postprocess_privileges(TenantRootRole, TenantRootPrivilege, rolemap, obj, "tenant_root")
 
     def can_delete(self, obj):
         return super(XOSCORDSubscriber, self).can_delete(obj)
diff --git a/xos/tosca/resources/xosresource.py b/xos/tosca/resources/xosresource.py
index fa14380..cc4672b 100644
--- a/xos/tosca/resources/xosresource.py
+++ b/xos/tosca/resources/xosresource.py
@@ -103,10 +103,16 @@
     def postprocess_privileges(self, roleclass, privclass, rolemap, obj, toFieldName):
         for (rel, role) in rolemap:
             for email in self.get_requirements(rel):
-                role = self.get_xos_object(roleclass, role=role)
+                role_obj = self.get_xos_object(roleclass, throw_exception=False, role=role)
+                if not role_obj:
+                    # if the role doesn't exist, make it
+                    self.info("Creating %s %s" % (roleclass.__name__, role))
+                    role_obj = roleclass(role=role)
+                    role_obj.save()
+
                 user = self.get_xos_object(User, email=email)
-                if not privclass.objects.filter(user=user, role=role, **{toFieldName: obj}):
-                    sp = privclass(user=user, role=role, **{toFieldName: obj})
+                if not privclass.objects.filter(user=user, role=role_obj, **{toFieldName: obj}):
+                    sp = privclass(user=user, role=role_obj, **{toFieldName: obj})
                     sp.save()
                     self.info("Added privilege on %s role %s for %s" % (str(obj), str(role), str(user)))
 
diff --git a/xos/tosca/samples/cord.yaml b/xos/tosca/samples/cord.yaml
index 567ced0..a9baf25 100644
--- a/xos/tosca/samples/cord.yaml
+++ b/xos/tosca/samples/cord.yaml
@@ -70,8 +70,19 @@
               node: mysite
               relationship: tosca.relationships.MemberOfSite
 
-    # Now let's add a subscriber
+    # Let's add a user who can be administrator of the household
+    johndoe@myhouse.com:
+      type: tosca.nodes.User
+      properties:
+          password: letmein
+          firstname: john
+          lastname: doe
+      requirements:
+          - site:
+              node: mysite
+              relationship: tosca.relationships.MemberOfSite
 
+    # Now let's add a subscriber
     My House:
        type: tosca.nodes.CORDSubscriber
        properties:
@@ -80,6 +91,10 @@
            cdn_enable: true
            url_filter_enable: true
            url_filter_level: R
+       requirements:
+          - house_admin:
+              node: johndoe@myhouse.com
+              relationship: tosca.relationships.AdminPrivilege
 
     Mom's PC:
        type: tosca.nodes.CORDUser
@@ -137,3 +152,5 @@
 
 
 
+
+