Просмотр исходного кода

Add OpenStack implementation for mandatory network parameter to Instance.create

Enis Afgan 9 лет назад
Родитель
Сommit
64e6d34f94

+ 1 - 1
cloudbridge/cloud/providers/aws/services.py

@@ -629,7 +629,7 @@ class AWSInstanceService(BaseInstanceService):
             sn_id, _ = _get_potential_subnets(flters, exc)
         elif vpc_id:
             flters = {'state': 'available', 'vpcId': vpc_id}
-            exc = "No subnets found for network {1}.".format(vpc_id)
+            exc = "No subnets found for network {0}.".format(vpc_id)
             sn_id, zone_id = _get_potential_subnets(flters, exc)
             sg_ids = None
         elif zone_id:

+ 42 - 10
cloudbridge/cloud/providers/openstack/services.py

@@ -2,6 +2,7 @@
 Services implemented by the OpenStack provider.
 """
 import fnmatch
+import logging
 import re
 
 from cinderclient.exceptions import NotFound as CinderNotFound
@@ -25,6 +26,7 @@ from cloudbridge.cloud.base.services import BaseVolumeService
 from cloudbridge.cloud.interfaces.resources import InstanceType
 from cloudbridge.cloud.interfaces.resources import KeyPair
 from cloudbridge.cloud.interfaces.resources import MachineImage
+from cloudbridge.cloud.interfaces.resources import Network
 from cloudbridge.cloud.interfaces.resources import PlacementZone
 from cloudbridge.cloud.interfaces.resources import SecurityGroup
 from cloudbridge.cloud.interfaces.resources import Snapshot
@@ -47,6 +49,8 @@ from .resources import OpenStackSnapshot
 from .resources import OpenStackSubnet
 from .resources import OpenStackVolume
 
+log = logging.getLogger(__name__)
+
 
 class OpenStackSecurityService(BaseSecurityService):
 
@@ -564,6 +568,7 @@ class OpenStackInstanceService(BaseInstanceService):
             isinstance(instance_type, InstanceType) else \
             self.provider.compute.instance_types.find(
                 name=instance_type)[0].id
+        network_id = network.id if isinstance(network, Network) else network
         zone_id = zone.id if isinstance(zone, PlacementZone) else zone
         key_pair_name = key_pair.name if \
             isinstance(key_pair, KeyPair) else key_pair
@@ -575,11 +580,10 @@ class OpenStackInstanceService(BaseInstanceService):
                 security_groups_list = security_groups
         else:
             security_groups_list = None
+        bdm = None
         if launch_config:
             bdm = self._to_block_device_mapping(launch_config)
-            nics = self._format_nics(launch_config)
-        else:
-            bdm = nics = None
+        net = self._get_network(network_id)
 
         os_instance = self.provider.nova.servers.create(
             name,
@@ -592,7 +596,7 @@ class OpenStackInstanceService(BaseInstanceService):
             security_groups=security_groups_list,
             userdata=user_data,
             block_device_mapping_v2=bdm,
-            nics=nics)
+            nics=net)
         return OpenStackInstance(self.provider, os_instance)
 
     def _to_block_device_mapping(self, launch_config):
@@ -645,14 +649,42 @@ class OpenStackInstanceService(BaseInstanceService):
                 return True
         return False
 
-    def _format_nics(self, launch_config):
+    def _get_network(self, network_id=None):
         """
-        Format network IDs for the API call.
+        Format the network ID for the API call, figuring out a default network.
+
+        If a network_id is not supplied, figure out which is the default
+        network and use it. A default network is either marked as such by the
+        provider or matches the default network name defined within this
+        library (by default CloudBridgeNet). If a default network cannot be
+        found, attempt to create a new one.
         """
-        nics = []
-        for net_id in launch_config.network_interfaces:
-            nics.append({'net-id': net_id})
-        return nics
+        if network_id:
+            return [{'net-id': network_id}]
+        for net in self.provider.network.list():
+            if net.name == OpenStackNetwork.CB_DEFAULT_NETWORK_NAME:
+                return [{'net-id': net.id}]
+        try:
+            # Try to create a complete, Internet-connected new network
+            net = self.provider.network.create(
+                name=OpenStackNetwork.CB_DEFAULT_NETWORK_NAME)
+            sn = net.create_subnet('10.0.0.0/16', '{0}Subnet'.format(
+                OpenStackNetwork.CB_DEFAULT_NETWORK_NAME))
+            router = self.provider.network.create_router('{0}Router'.format(
+                OpenStackNetwork.CB_DEFAULT_NETWORK_NAME))
+            for n in self.provider.network.list():
+                if n.external:
+                    external_net = n
+                    break
+            router.attach_network(external_net.id)
+            router.add_route(sn.id)
+            return [{'net-id': net.id}]
+        except Exception as exc:
+            # At this point we assume the provider does support user-defined
+            # networks so return None
+            log.warn("Exception occurred trying to create a default "
+                     "CloudBridge network: {0}".format(exc))
+            return None
 
     def create_launch_config(self):
         return BaseLaunchConfig(self.provider)