Merge branch 'master' of github.com:open-cloud/xos
diff --git a/xos/core/admin.py b/xos/core/admin.py
index f0d402e..904d64e 100644
--- a/xos/core/admin.py
+++ b/xos/core/admin.py
@@ -1840,7 +1840,7 @@
     verbose_name_plural = "Controller Networks"
     verbose_name = "Controller Network"
     suit_classes = 'suit-tab suit-tab-admin-only'
-    fields = ['backend_status_icon', 'controller','net_id','subnet_id']
+    fields = ['backend_status_icon', 'controller','net_id','subnet_id','subnet']
     readonly_fields = ('backend_status_icon', )
 
 class NetworkForm(forms.ModelForm):
diff --git a/xos/synchronizers/openstack/model_policies/model_policy_Network.py b/xos/synchronizers/openstack/model_policies/model_policy_Network.py
index 38d0377..9f9e5fd 100644
--- a/xos/synchronizers/openstack/model_policies/model_policy_Network.py
+++ b/xos/synchronizers/openstack/model_policies/model_policy_Network.py
@@ -22,4 +22,9 @@
 		if network not in network_deploy_lookup or \
 		  expected_controller not in network_deploy_lookup[network]:
 			nd = ControllerNetwork(network=network, controller=expected_controller, lazy_blocked=True)
+                        if network.subnet:
+                            # XXX: Possibly unpredictable behavior if there is
+                            # more than one ControllerNetwork and the subnet
+                            # is specified.
+                            nd.subnet = network.subnet
 			nd.save()
diff --git a/xos/synchronizers/openstack/steps/sync_controller_networks.py b/xos/synchronizers/openstack/steps/sync_controller_networks.py
index 0b876fa..f8b2292 100644
--- a/xos/synchronizers/openstack/steps/sync_controller_networks.py
+++ b/xos/synchronizers/openstack/steps/sync_controller_networks.py
@@ -34,22 +34,21 @@
         cidr = '%d.%d.%d.%d/24'%(a,b,c,d)
         return cidr
 
-    def alloc_gateway(self, uuid):
-        # 16 bits only
-        uuid_masked = uuid & 0xffff
-        a = 10
-        b = uuid_masked >> 8
-        c = uuid_masked & 0xff
-        d = 1
-
-        gateway = '%d.%d.%d.%d'%(a,b,c,d)
-        return gateway
-
+    def alloc_gateway(self, subnet):
+        parts = subnet.split(".")
+        if len(parts)!=4:
+            raise Exception("Invalid subnet %s" % subnet)
+        return ".".join(parts[:3]) + ".1"
 
     def save_controller_network(self, controller_network):
         network_name = controller_network.network.name
         subnet_name = '%s-%d'%(network_name,controller_network.pk)
-        cidr = self.alloc_subnet(controller_network.pk)
+        if controller_network.subnet and controller_network.subnet.strip():
+            # If a subnet is already specified (pass in by the creator), then
+            # use that rather than auto-generating one.
+            cidr = controller_network.subnet.strip()
+        else:
+            cidr = self.alloc_subnet(controller_network.pk)
         self.cidr=cidr
         slice = controller_network.network.owner
 
@@ -63,9 +62,9 @@
                     'subnet_name':subnet_name,
                     'ansible_tag':'%s-%s@%s'%(network_name,slice.slicename,controller_network.controller.name),
                     'cidr':cidr,
-                    'gateway':self.alloc_gateway(controller_network.pk),
+                    'gateway':self.alloc_gateway(cidr),
                     'use_vtn':getattr(Config(), "networking_use_vtn", False),
-                    'delete':False	
+                    'delete':False
                     }
         return network_fields