WIP, make sync_vcpetenant pay attention to settings in VCPEService object
diff --git a/xos/observers/vcpe/steps/sync_vcpetenant.py b/xos/observers/vcpe/steps/sync_vcpetenant.py
index ccab3d6..6db4a1f 100644
--- a/xos/observers/vcpe/steps/sync_vcpetenant.py
+++ b/xos/observers/vcpe/steps/sync_vcpetenant.py
@@ -43,49 +43,76 @@
 
         return objs
 
+    def get_vcpe_service(self, o):
+        if not o.provider_service:
+            return None
+
+        vcpes = VCPEService.get_service_objects().filter(id=o.provider_service.id)
+        if not vcpes:
+            return None
+
+        return vcpes[0]
+
     def get_extra_attributes(self, o):
         # This is a place to include extra attributes that aren't part of the
-        # object itself. In our case, it's handy to know the VLAN IDs when
-        # configuring the VCPE.
+        # object itself. In the case of vCPE, we need to know:
+        #   1) the addresses of dnsdemux, to setup dnsmasq in the vCPE
+        #   2) CDN prefixes, so we know what URLs to send to dnsdemux
+        #   3) BroadBandShield server addresses, for parental filtering
+        #   4) vlan_ids, for setting up networking in the vCPE VM
 
-        dnsdemux_ip = "none"
-        for service in HpcService.objects.all():
-            for slice in service.slices.all():
-                if "dnsdemux" in slice.name:
-                    for sliver in slice.slivers.all():
-                        # Connect to a dnsdemux that's on the hpc_client network
-                        # if one is available.
-                        for ns in sliver.networkslivers.all():
-                            if ns.ip and ns.network.labels and ("hpc_client" in ns.network.labels):
-                                dnsdemux_ip = ns.ip
-                        if dnsdemux_ip=="none":
-                            try:
-                                dnsdemux_ip = socket.gethostbyname(sliver.node.name)
-                            except:
-                                pass
+        vcpe_service = self.get_vcpe_service(o)
+
+        dnsdemux_ip = None
+        if vcpe_service.backend_network_label:
+            # Connect to dnsdemux using the network specified by
+            #     vcpe_service.backend_network_label
+            for service in HpcService.objects.all():
+                for slice in service.slices.all():
+                    if "dnsdemux" in slice.name:
+                        for sliver in slice.slivers.all():
+                            for ns in sliver.networkslivers.all():
+                                if ns.ip and
+                                   ns.network.labels and
+                                   (vcpe_service.backend_network_label in ns.network.labels):
+                                    dnsdemux_ip = ns.ip
+            if not dnsdemux_ip:
+                logger.info("failed to find a dnsdemux on network %s" % vcpe_service.backend_network_label)
+        else:
+            # Connect to dnsdemux using the sliver's public address
+            for service in HpcService.objects.all():
+                for slice in service.slices.all():
+                    if "dnsdemux" in slice.name:
+                        for sliver in slice.slivers.all():
+                            if dnsdemux_ip=="none":
+                                try:
+                                    dnsdemux_ip = socket.gethostbyname(sliver.node.name)
+                                except:
+                                    pass
+            if not dnsdemux_ip:
+                logger.info("failed to find a dnsdemux with a public address")
+
+        dnsdemux_ip = dnsdemux_ip or "none"
 
         cdn_prefixes = []
         for prefix in CDNPrefix.objects.all():
             cdn_prefixes.append(prefix.prefix)
 
-        vlan_ids = []
-        if o.volt:
-            vlan_ids.append(o.volt.vlan_id)
-
         bbs_addrs = []
-        bbs_slices = Slice.objects.filter(name="mysite_bbs")
-        if bbs_slices:
+        if vcpe.bbs_slice:
             bbs_slice = bbs_slices[0]
             for bbs_sliver in bbs_slice.slivers.all():
                 for ns in bbs_sliver.networkslivers.all():
                     if ns.ip and ns.network.labels and ("hpc_client" in ns.network.labels):
                         bbs_addrs.append(ns.ip)
+        elif vcpe.bbs_server:
+            bbs_addrs.append(vcpe.bbs_server)
+        else:
+            logger.info("neither bbs_slice nor bbs_server is configured in the vCPE")
 
-        if not bbs_addrs:
-            bbs_addrs = ["198.105.255.10",
-                         "198.105.255.11",
-                         "198.105.255.12",
-                         "198.105.255.13"]
+        vlan_ids = []
+        if o.volt:
+            vlan_ids.append(o.volt.vlan_id)
 
         return {"vlan_ids": vlan_ids,
                 "dnsdemux_ip": dnsdemux_ip,
@@ -106,13 +133,17 @@
             self.defer_sync(o, "waiting on sliver")
             return
 
-        service = o.sliver.slice.service
+        service = self.get_vcpe_service(o)
         if not service:
             # Ansible uses the service's keypair in order to SSH into the
             # instance. It would be bad if the slice had no service.
 
             raise Exception("Slice %s is not associated with a service" % sliver.slice.name)
 
+        # Make sure the slice is configured properly
+        if (service != o.sliver.slice.service):
+            raise Exception("Slice %s is associated with some service that is not %s % (str(sliver.slice), str(service)))
+
         if not os.path.exists(self.service_key_name):
             raise Exception("Service key %s does not exist" % self.service_key_name)
 
@@ -154,17 +185,32 @@
             logger.info("playbook execution time %d" % int(time.time()-tStart))
 
         if url_filter_enable:
-            tStart = time.time()
-            bbs = BBS(o.bbs_account, "123")
-            bbs.sync(url_filter_level, url_filter_users)
-
-            if o.hpc_client_ip:
-                logger.info("associate account %s with ip %s" % (o.bbs_account, o.hpc_client_ip))
-                bbs.associate(o.hpc_client_ip)
+            bbs_hostname = None
+            if service.bbs_api_hostname and service.bbs_api_port:
+                bbs_hostname = service.bbs_api_hostname
             else:
-                logger.info("no hpc_client_ip to associate")
+                # TODO: extract from slice
+                bbs_hostname = "cordcompute01.onlab.us"
 
-            logger.info("bbs update tiem %d" % int(time.time()-tStart))
+            if service.bbs_api_port:
+                bbs_port = service.bbs_api_port
+            else:
+                bbs_port = 8018
+
+            if not bbs_hostname:
+                logger.info("broadbandshield is not configured")
+            else:
+                tStart = time.time()
+                bbs = BBS(o.bbs_account, "123", bbs_hostname, bbs_port)
+                bbs.sync(url_filter_level, url_filter_users)
+
+                if o.hpc_client_ip:
+                    logger.info("associate account %s with ip %s" % (o.bbs_account, o.hpc_client_ip))
+                    bbs.associate(o.hpc_client_ip)
+                else:
+                    logger.info("no hpc_client_ip to associate")
+
+                logger.info("bbs update time %d" % int(time.time()-tStart))
 
         o.last_ansible_hash = ansible_hash
         o.save()