Bläddra i källkod

Continuation of network simplification

Nuwan Goonasekera 9 år sedan
förälder
incheckning
55cd08b3ca

+ 27 - 155
cloudbridge/cloud/providers/aws/services.py

@@ -484,7 +484,7 @@ class AWSInstanceService(BaseInstanceService):
             bdm = None
 
         subnet_id, zone_id, security_group_ids = \
-            self._resolve_launch_options(zone_id, subnet, security_groups)
+            self._resolve_launch_options(subnet, zone_id, security_groups)
 
         reservation = self.provider.ec2_conn.run_instances(
             image_id=image_id, instance_type=instance_size,
@@ -498,99 +498,29 @@ class AWSInstanceService(BaseInstanceService):
             instance.name = name
         return instance
 
-    def _resolve_launch_options(self, zone_id=None, subnet=None,
+    def _resolve_launch_options(self, subnet=None, zone_id=None,
                                 security_groups=None):
         """
         Work out interdependent launch options.
 
-        Some launch options are required and interdependent so work through
-        those constraints. There are 8 subsets of options so the logic works
-        through each of those combinations to figure out the proper launch
-        options.
-
-        :type zone_id: ``str``
-        :param zone_id: ID of the zone where the launch should happen.
+        Some launch options are required and interdependent so make sure
+        they conform to the interface contract.
 
         :type subnet: ``Subnet``
         :param subnet: Subnet object within which to launch.
 
-        :type security_groups: ``list`` of ``str``
-        :param zone_id: List of security group names.
+        :type zone_id: ``str``
+        :param zone_id: ID of the zone where the launch should happen.
+
+        :type security_groups: ``list`` of ``id``
+        :param zone_id: List of security group IDs.
 
         :rtype: triplet of ``str``
         :return: Subnet ID, zone ID and security group IDs for launch.
 
-        :raise ValueError: In case a conflicting combination is found or the
-                           method cannot infer the defaults, raise.
+        :raise ValueError: In case a conflicting combination is found.
         """
-        def _get_default_vpc(vpcs):
-            """
-            Inspect supplied VPCs to figure out a default one or create one.
-
-            Default VPC either has ``is_default`` property set or matches the
-            default network name used by this library. If a default network
-            is not found, an attempt to create one is made.
-
-            :type vpcs: ``list``
-            :param vpcs: A list of boto VPC objects.
-
-            :rtype: ``str``
-            :return: Default VPC ID.
-            """
-            for vpc in vpcs:
-                if vpc.is_default:
-                    return vpc.id
-            return self.provider.network.get_or_create_default().id
-
-        def _get_a_subnet(filters, exc):
-            """
-            Query existing subnets through supplied filters.
-
-            :type filters: ``dict``
-            :param filters: A dictionary supplying desired filters.
-
-            :type exc: ``str``
-            :type exc: A string value to use if/when raising ValueError.
-
-            :rtype: tuple of ``str``
-            :return: A tuple with a subnet that matches supplied
-                     filters and an availability zone where the given subnet
-                     is defined. First choice of a subnet is one marked as the
-                     `default`, then one contained within a default network
-                     for the library and lastly a random subnet.
-
-            :raise ValueError: If no subnet can be found, raise a ValueError.
-            """
-            potential_subnets = self.provider.vpc_conn.get_all_subnets(
-                filters=filters)
-            sn_id = zone_id = None
-            # Look for the official default subnet
-            for sn in potential_subnets:
-                if sn.defaultForAz:
-                    sn_id = sn.id
-                    zone_id = sn.availability_zone
-                    break
-            # Look for a library-defined default subnet
-            if not sn_id:
-                default_vpc = _get_default_vpc(
-                    self.provider.vpc_conn.get_all_vpcs())
-                filters['vpcId'] = default_vpc
-                default_subnets = self.provider.vpc_conn.get_all_subnets(
-                    filters=filters)
-                print("default subnets: %s" % default_subnets)
-                if default_subnets and len(default_subnets) > 0:
-                    sn_id = default_subnets[0].id
-                    zone_id = default_subnets[0].availability_zone
-            # Try a random subnet
-            if not sn_id:
-                if len(potential_subnets) > 0:
-                    sn_id = potential_subnets[0].id
-                    zone_id = potential_subnets[0].availability_zone
-            if not sn_id:
-                raise ValueError(exc)
-            return sn_id, zone_id
-
-        def _get_security_groups(security_groups, vpc_id=None, obj=False):
+        def _get_security_groups(security_groups, vpc_id, obj=False):
             """
             Resolve exact security groups to use.
 
@@ -611,80 +541,22 @@ class AWSInstanceService(BaseInstanceService):
             :return: provider-native security group objects or the IDs (see
                     ``obj`` param).
             """
-            if isinstance(security_groups, list) and \
-               isinstance(security_groups[0], SecurityGroup):
-                # Update the ref to the objects not to get stale info
-                sg_ids = [sg.id for sg in security_groups]
-                sgs = self.provider.ec2_conn.get_all_security_groups(
-                    group_ids=sg_ids)
-                return list(set([sg if obj else sg.id for sg in sgs]))
-            else:
-                flters = {'group_name': security_groups}
-                if vpc_id:
-                    flters['vpc_id'] = vpc_id
-                sgs = self.provider.ec2_conn.get_all_security_groups(
-                    filters=flters)
-                return list(set([sg if obj else sg.id for sg in sgs]))
-
-        if zone_id and subnet and security_groups:
-            sg_ids = _get_security_groups(security_groups, subnet.network_id)
-            sn_id = subnet.id
-        elif subnet and security_groups:
-            sg_ids = _get_security_groups(security_groups, subnet.network_id)
-            sn_id = subnet.id
-            zone_id = subnet._subnet.availability_zone
-        elif subnet and zone_id:
-            sg_ids = None
-            sn_id = subnet.id
-        elif zone_id and security_groups:
-            sgs = _get_security_groups(security_groups, obj=True)
-            # Get VPCs the supplied SGs belong to
-            vpc_ids = list(set([sg.vpc_id for sg in sgs if sg.vpc_id]))
-            vpcs = []
-            if vpc_ids:
-                vpcs = self.provider.vpc_conn.get_all_vpcs(vpc_ids=vpc_ids)
-            exc = ("No default network found for zone {0} and security groups "
-                   "{1}".format(zone_id, security_groups))
-            default_vpc = _get_default_vpc(vpcs)
-            # Filter only the SGs within the default VPC
-            sg_ids = _get_security_groups(security_groups, default_vpc)
-            flters = {'availabilityZone': zone_id, 'state': 'available',
-                      'vpc_id': default_vpc}
-            exc = "No subnets found in zone {0} for default network {1}." \
-                .format(zone_id, default_vpc)
-            sn_id, _ = _get_a_subnet(flters, exc)
-        elif subnet:
-            sn_id = subnet.id
-            zone_id = subnet._subnet.availability_zone
-            sg_ids = None
-        elif zone_id:
-            flters = {'availabilityZone': zone_id, 'state': 'available'}
-            exc = "No subnets found in zone {0}.".format(zone_id)
-            sn_id, _ = self.provider.get_a_subnet(flters, exc)
-            sg_ids = None
-        elif security_groups:
-            sgs = _get_security_groups(security_groups, obj=True)
-            # Get VPCs the supplied SGs belong to
-            vpc_ids = list(set([sg.vpc_id for sg in sgs if sg.vpc_id]))
-            vpcs = []
-            if vpc_ids:
-                vpcs = self.provider.vpc_conn.get_all_vpcs(vpc_ids=vpc_ids)
-            exc = "No default network exists for security groups {0}.".format(
-                security_groups)
-            default_vpc = _get_default_vpc(vpcs)
-            # Filter only the SGs within the default VPC
-            sg_ids = _get_security_groups(security_groups, default_vpc)
-            flters = {'state': 'available', 'vpcId': default_vpc}
-            exc = "No subnets found in network {0}.".format(default_vpc)
-            sn_id, zone_id = _get_a_subnet(flters, exc)
-        else:
-            # Nothing was defined, use all defaults
-            flters = {'state': 'available'}
-            exc = "No default subnets found."
-            sn_id, zone_id = _get_a_subnet(flters, exc)
-            sg_ids = None
-
-        return sn_id, zone_id, sg_ids
+            flters = {'group_name': security_groups}
+            if vpc_id:
+                flters['vpc_id'] = vpc_id
+            sgs = self.provider.ec2_conn.get_all_security_groups(
+                filters=flters)
+            return list(set([sg if obj else sg.id for sg in sgs]))
+
+        if subnet:
+            zone_id = subnet.zone.id
+            if security_groups:
+                sg_ids = _get_security_groups(security_groups, subnet.network_id)
+                if set(security_groups) != set(sg_ids):
+                    raise ValueError(
+                        "Provided security groups must be associated"
+                        " with the same network as the provided subnet.")
+        return subnet, zone_id, security_groups
 
     def _process_block_device_mappings(self, launch_config, zone=None):
         """

+ 1 - 40
cloudbridge/cloud/providers/openstack/services.py

@@ -590,7 +590,6 @@ class OpenStackInstanceService(BaseInstanceService):
         bdm = None
         if launch_config:
             bdm = self._to_block_device_mapping(launch_config)
-        net = self._get_network(network_id)
 
         log.debug("Launching with net %s" % net)
         os_instance = self.provider.nova.servers.create(
@@ -604,7 +603,7 @@ class OpenStackInstanceService(BaseInstanceService):
             security_groups=security_groups_list,
             userdata=user_data,
             block_device_mapping_v2=bdm,
-            nics=net)
+            nics=[{'net-id': network_id}])
         return OpenStackInstance(self.provider, os_instance)
 
     def _to_block_device_mapping(self, launch_config):
@@ -657,44 +656,6 @@ class OpenStackInstanceService(BaseInstanceService):
                 return True
         return False
 
-    def _get_network(self, network_id=None):
-        """
-        Format the network ID for the API call, figuring out a default network.
-
-        The returned network will be the parent network for the supplied
-        subnet. If a subnet_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 is made.
-        """
-        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)