Merge branch 'master' of github.com:open-cloud/xos
diff --git a/xos/cord/models.py b/xos/cord/models.py
index 926a42d..594eb31 100644
--- a/xos/cord/models.py
+++ b/xos/cord/models.py
@@ -127,6 +127,10 @@
     KIND = "vCPE"
 
     default_attributes = {"firewall_enable": False,
+                          "firewall_rules": "accept all anywhere anywhere",
+                          "url_filter_enable": False,
+                          "url_filter_rules": "allow all",
+                          "cdn_enable": False,
                           "sliver_id": None}
 
     @property
@@ -160,6 +164,38 @@
     def firewall_enable(self, value):
         self.set_attribute("firewall_enable", value)
 
+    @property
+    def firewall_rules(self):
+        return self.get_attribute("firewall_rules", self.default_attributes["firewall_rules"])
+
+    @firewall_rules.setter
+    def firewall_rules(self, value):
+        self.set_attribute("firewall_rules", value)
+
+    @property
+    def url_filter_enable(self):
+        return self.get_attribute("url_filter_enable", self.default_attributes["url_filter_enable"])
+
+    @url_filter_enable.setter
+    def url_filter_enable(self, value):
+        self.set_attribute("url_filter_enable", value)
+
+    @property
+    def url_filter_rules(self):
+        return self.get_attribute("url_filter_rules", self.default_attributes["url_filter_rules"])
+
+    @url_filter_rules.setter
+    def url_filter_rules(self, value):
+        self.set_attribute("url_filter_rules", value)
+
+    @property
+    def cdn_enable(self):
+        return self.get_attribute("cdn_enable", self.default_attributes["cdn_enable"])
+
+    @cdn_enable.setter
+    def cdn_enable(self, value):
+        self.set_attribute("cdn_enable", value)
+
     def pick_node(self):
         nodes = list(Node.objects.all())
         # TODO: logic to filter nodes by which nodes are up, and which
diff --git a/xos/core/models/service.py b/xos/core/models/service.py
index c6e0061..48d1677 100644
--- a/xos/core/models/service.py
+++ b/xos/core/models/service.py
@@ -58,6 +58,13 @@
         super(Tenant, self).__init__(*args, **kwargs)
 
     def __unicode__(self):
+        if not hasattr(self, "provider_service"):
+           # When the REST API does a POST on a CordSubscriber object, for
+           # some reason there is no provider_service field. All of the other
+           # fields are there. Provider_service is even in the dir(). However,
+           # trying to getattr() on it will fail.
+           return "confused-tenant-object"
+
         if self.subscriber_service:
             return u'%s service %s on service %s' % (str(self.kind), str(self.subscriber_service.id), str(self.provider_service.id))
         elif self.subscriber_tenant:
diff --git a/xos/core/xoslib/methods/cordsubscriber.py b/xos/core/xoslib/methods/cordsubscriber.py
index f724c1e..1470323 100644
--- a/xos/core/xoslib/methods/cordsubscriber.py
+++ b/xos/core/xoslib/methods/cordsubscriber.py
@@ -12,16 +12,23 @@
 
 if hasattr(serializers, "ReadOnlyField"):
     # rest_framework 3.x
-    IdField = serializers.ReadOnlyField
+    ReadOnlyField = serializers.ReadOnlyField
 else:
     # rest_framework 2.x
-    IdField = serializers.Field
+    ReadOnlyField = serializers.Field
 
 class CordSubscriberIdSerializer(serializers.ModelSerializer, PlusSerializerMixin):
-        id = IdField()
-        vcpe_id = IdField()
-        sliver_id = IdField()
+        id = ReadOnlyField()
+        vcpe_id = ReadOnlyField()
+        sliver = ReadOnlyField()
+        image = ReadOnlyField()
         firewall_enable = serializers.BooleanField()
+        firewall_rules = serializers.CharField()
+        url_filter_enable = serializers.BooleanField()
+        url_filter_rules = serializers.CharField()
+        cdn_enable = serializers.BooleanField()
+        sliver_name = ReadOnlyField()
+        image_name = ReadOnlyField()
 
         humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
 
@@ -29,11 +36,11 @@
             model = CordSubscriber
             fields = ('humanReadableName', 'id',
                       'service_specific_id',
-                      'vcpe_id', 'sliver_id', 'firewall_enable')
+                      'vcpe_id', 'sliver', 'sliver_name', 'image', 'image_name', 'firewall_enable', 'firewall_rules', 'url_filter_enable', 'url_filter_rules', 'cdn_enable')
 
 
         def getHumanReadableName(self, obj):
-            return str(obj)
+            return obj.__unicode__()
 
 class CordSubscriberList(XOSListCreateAPIView):
     queryset = CordSubscriber.get_tenant_objects().select_related().all()
diff --git a/xos/core/xoslib/objects/cordsubscriber.py b/xos/core/xoslib/objects/cordsubscriber.py
index d483cac..654d8a3 100644
--- a/xos/core/xoslib/objects/cordsubscriber.py
+++ b/xos/core/xoslib/objects/cordsubscriber.py
@@ -4,6 +4,20 @@
 from operator import itemgetter, attrgetter
 from rest_framework.exceptions import APIException
 
+"""
+import os
+import sys
+sys.path.append("/opt/xos")
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
+import django
+from core.models import *

+from hpc.models import *

+from cord.models import *

+django.setup()
+from core.xoslib.objects.cordsubscriber import CordSubscriber
+c=CordSubscriber.get_tenant_objects().select_related().all()[0]
+"""
+
 class CordSubscriber(VOLTTenant, PlusObjectMixin):
     class Meta:
         proxy = True
@@ -22,29 +36,45 @@
     def vcpe_id(self, value):
         pass
 
-    @property
-    def sliver_id(self):
-        if self.vcpe and self.vcpe.sliver:
-            return self.vcpe.sliver.id
-        else:
-            return None
+    passthroughs = ( ("firewall_enable", "vcpe.firewall_enable"),
+                     ("firewall_rules", "vcpe.firewall_rules"),
+                     ("url_filter_enable", "vcpe.url_filter_enable"),
+                     ("url_filter_rules", "vcpe.url_filter_rules"),
+                     ("cdn_enable", "vcpe.cdn_enable"),
+                     ("image", "vcpe.image.id"),
+                     ("image_name", "vcpe.image.name"),
+                     ("sliver", "vcpe.sliver.id"),
+                     ("sliver_name", "vcpe.sliver.name") )
 
-    @sliver_id.setter
-    def sliver_id(self, value):
-        pass
+    def __getattr__(self, key):
+        for (member_name, passthrough_name) in self.passthroughs:
+            if key==member_name:
+                parts = passthrough_name.split(".")
+                obj = self
+                for part in parts[:-1]:
+                    obj = getattr(obj, part)
+                    if not obj:
+                        return None
+                return getattr(obj, parts[-1])
 
-    @property
-    def firewall_enable(self):
-        if self.vcpe:
-            return self.vcpe.firewall_enable
-        else:
-            return None
+        raise AttributeError("getattr: %r object has no attribute %r" %
+                         (self.__class__, key))
 
-    @firewall_enable.setter
-    def firewall_enable(self, value):
-        if self.vcpe:
-            self.vcpe.firewall_enable = value
-            # TODO: save it
+    def __setattr__(self, key, value):
+        for (member_name, passthrough_name) in self.passthroughs:
+            if key==member_name:
+                parts = passthrough_name.split(".")
+                obj = self
+                for part in parts[:-1]:
+                     obj = getattr(obj, part)
+                     if not obj:
+                         return
+                setattr(obj, parts[-1], value)
+
+        super(CordSubscriber, self).__setattr__(key, value)
+
+
+
 
 
 
diff --git a/xos/core/xoslib/static/js/xoslib/xos-backbone.js b/xos/core/xoslib/static/js/xoslib/xos-backbone.js
index 2e9daf1..f22a2e2 100644
--- a/xos/core/xoslib/static/js/xoslib/xos-backbone.js
+++ b/xos/core/xoslib/static/js/xoslib/xos-backbone.js
@@ -730,8 +730,10 @@
         define_model(this, {urlRoot: CORDSUBSCRIBER_API,
                             modelName: "cordSubscriber",
                             listFields: ["id"],
-                            detailFields: ["id", "service_specific_id", "vcpe_id", "firewall_enable"],
-                            inputType: {"firewall_enable": "checkbox"},
+                            detailFields: ["id", "service_specific_id", "vcpe_id", "image_name", "sliver_name", "firewall_enable", "firewall_rules", "url_filter_enable", "url_filter_rules", "cdn_enable"],
+                            inputType: {"firewall_enable": "checkbox",
+                                        "url_filter_enable": "checkbox",
+                                        "cdn_enable": "checkbox"},
                             });
 
         /* by default, have slicePlus only fetch the slices the user can see */