checking in step
authorTony Mack <tmack@paris.CS.Princeton.EDU>
Tue, 8 Apr 2014 20:36:52 +0000 (16:36 -0400)
committerTony Mack <tmack@paris.CS.Princeton.EDU>
Tue, 8 Apr 2014 20:36:52 +0000 (16:36 -0400)
planetstack/observer/steps/sync_network_deployments.py [new file with mode: 0644]

diff --git a/planetstack/observer/steps/sync_network_deployments.py b/planetstack/observer/steps/sync_network_deployments.py
new file mode 100644 (file)
index 0000000..3bfa103
--- /dev/null
@@ -0,0 +1,113 @@
+import os
+import base64
+from collections import defaultdict
+from netaddr import IPAddress, IPNetwork
+from django.db.models import F, Q
+from planetstack.config import Config
+from observer.openstacksyncstep import OpenStackSyncStep
+from core.models.network import *
+from core.models.slice import *
+from util.logger import Logger, logging
+
+logger = Logger(level=logging.INFO)
+
+class SyncNetworkDeployments(OpenStackSyncStep):
+    provides=[NetworkDeployments]
+    request_interval = 0 
+    
+    def fetch_pending(self):
+        # network deployments are not visible to users. We must ensure
+        # networks are deployed at all deploymets available to their slices. 
+        slice_deployments = SliceDeployments.objects.all()
+        slice_deploy_lookup = defaultdict(list)
+        for slice_deployment in slice_deployments:
+            slice_deploy_lookup[slice_deployment.slice].append(slice_deployment.deployment)
+        
+        network_deployments = NetworkDeployments.objects.all()
+        network_deploy_lookup = defaultdict(list)
+        for network_deployment in network_deployments:
+            network_deploy_lookup[network_deployment.network].append(network_deployment.deployment)
+
+        for network in Network.objects.filter():
+            expected_deployments = slice_deploy_lookup[network.owner]
+            for expected_deployment in expected_deployments:
+                if network not in network_deploy_lookup or \
+                  expected_deployment not in network_deploy_lookup[network]:
+                    nd = NetworkDeployments(network=network, deployment=expected_deployment)
+                    nd.save()
+        return NetworkDeployments.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
+
+    def get_next_subnet(self, deployment=None):
+        # limit ourself to 10.0.x.x for now
+        valid_subnet = lambda net: net.startswith('10.0')
+        driver = self.driver.admin_driver(deployment=deployment)
+        subnets = driver.shell.quantum.list_subnets()['subnets']
+        ints = [int(IPNetwork(subnet['cidr']).ip) for subnet in subnets \
+                if valid_subnet(subnet['cidr'])]
+        ints.sort()
+        if ints:
+            last_ip = IPAddress(ints[-1])
+        else:
+            last_ip = IPAddress('10.0.0.1')
+        last_ip = IPAddress(ints[-1])
+        last_network = IPNetwork(str(last_ip) + "/24")
+        next_network = IPNetwork(str(IPAddress(last_network) + last_network.size) + "/24")
+        return next_network
+
+    def save_network_deployment(self, network_deployment):
+        if not network_deployment.network_id and network_deployment.network.template.sharedNetworkName:
+            network_deployment.network_id = network_deployment.network.template.sharedNetworkId
+
+        if not network_deployment.net_id:
+            network_name = network_deployment.network.name
+
+            # create network
+            os_network = self.driver.create_network(network_name, shared=True)
+            network_deployment.net_id = os_network['id']
+
+            # create router
+            router = self.driver.create_router(network_name)
+            network_deployment.router_id = router['id']
+
+            # create subnet
+            next_subnet = self.get_next_subnet(deployment=network_deployment.deployment.name)
+            cidr = str(next_subnet.cidr)
+            ip_version = next_subnet.version
+            start = str(next_subnet[2])
+            end = str(next_subnet[-2])
+            subnet = self.driver.create_subnet(name=network_name,
+                                               network_id = network_deployment.net_id,
+                                               cidr_ip = cidr,
+                                               ip_version = ip_version,
+                                               start = start,
+                                               end = end)
+            network_deployment.subnet = cidr
+            network_deployment.subnet_id = subnet['id']
+            # add subnet as interface to slice's router
+            self.driver.add_router_interface(router['id'], subnet['id'])
+            # add external route
+            self.driver.add_external_route(subnet)
+            logger.info("created private subnet (%s) for network: %s" % (cidr, network_deployment.network))
+        else:
+            (network_deployment.subnet_id, network_deployment.subnet) = self.driver.get_network_subnet(network_deployment.net_id)
+            logger.info("sync'ed subnet (%s) for network: %s" % (network_deployment.subnet, network_deployment.network))
+
+        network_deployment.save()
+
+    def sync_record(self, network_deployment):
+        if network_deployment.network.owner and network_deployment.network.owner.creator:
+            try:
+                # update manager context
+                real_driver = self.driver
+                self.driver = self.driver.client_driver(caller=network_deployment.network.owner.creator, 
+                                                        tenant=network_deployment.network.owner.name,
+                                                        deployment=network_deployment.deployment.name)
+                self.save_network_deployment(network_deployment)
+                self.driver = real_driver
+                logger.info("saved network deployment: %s" % (network_deployment))
+            except Exception,e:
+                logger.log_exc("save network deployment failed: %s" % network_deployment)
+                raise e            
+        
+          
+