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

GatewayService and GatewaySubService refactored

almahmoud 7 лет назад
Родитель
Сommit
10c618db17

+ 7 - 0
cloudbridge/cloud/base/services.py

@@ -9,6 +9,7 @@ from cloudbridge.cloud.interfaces.services import BucketObjectService
 from cloudbridge.cloud.interfaces.services import BucketService
 from cloudbridge.cloud.interfaces.services import CloudService
 from cloudbridge.cloud.interfaces.services import ComputeService
+from cloudbridge.cloud.interfaces.services import GatewayService
 from cloudbridge.cloud.interfaces.services import ImageService
 from cloudbridge.cloud.interfaces.services import InstanceService
 from cloudbridge.cloud.interfaces.services import KeyPairService
@@ -303,3 +304,9 @@ class BaseRouterService(
         else:
             return self.provider.networking.routers.create(
                 network=net_id, label=BaseRouter.CB_DEFAULT_ROUTER_LABEL)
+
+
+class BaseGatewayService(GatewayService, BaseCloudService):
+
+    def __init__(self, provider):
+        self._provider = provider

+ 20 - 1
cloudbridge/cloud/base/subservices.py

@@ -42,7 +42,26 @@ class BaseGatewaySubService(GatewaySubService, BasePageableObjectMixin):
 
     def __init__(self, provider, network):
         self._network = network
-        self._provider = provider
+        self.__provider = provider
+
+    @property
+    def _provider(self):
+        return self.__provider
+
+    def get_or_create_inet_gateway(self):
+        return (self._provider.networking
+                              ._gateways
+                              .get_or_create_inet_gateway(self._network))
+
+    def delete(self, gateway):
+        return (self._provider.networking
+                              ._gateways
+                              .delete(self._network, gateway))
+
+    def list(self, limit=None, marker=None):
+        return (self._provider.networking
+                              ._gateways
+                              .list(self._network, limit, marker))
 
 
 class BaseVMFirewallRuleSubService(BasePageableObjectMixin,

+ 49 - 0
cloudbridge/cloud/interfaces/services.py

@@ -1379,3 +1379,52 @@ class RegionService(PageableObjectMixin, CloudService):
         :return: a Region object
         """
         pass
+
+
+class GatewayService(CloudService):
+    """
+    Manage internet gateway resources.
+    """
+    __metaclass__ = ABCMeta
+
+    @abstractmethod
+    def get_or_create_inet_gateway(self, network):
+        """
+        Creates new or returns an existing internet gateway for a network.
+
+        The returned gateway object can subsequently be attached to a router to
+        provide internet routing to a network.
+
+        :type  network: ``Network``
+        :param network: The network to which the gateway should be attached.
+
+        :rtype: ``object``  of :class:`.InternetGateway` or ``None``
+        :return: an InternetGateway object of ``None`` if not found.
+        """
+        pass
+
+    @abstractmethod
+    def delete(self, network, gateway):
+        """
+        Delete a gateway.
+
+        :type  network: ``Network``
+        :param network: The network to which the gateway is attached.
+
+        :type gateway: :class:`.Gateway` object
+        :param gateway: Gateway object to delete.
+        """
+        pass
+
+    @abstractmethod
+    def list(self, network, limit=None, marker=None):
+        """
+        List all available internet gateways.
+
+        :type  network: ``Network``
+        :param network: The network to which the gateway is attached.
+
+        :rtype: ``list`` of :class:`.InternetGateway` or ``None``
+        :return: Current list of internet gateways.
+        """
+        pass

+ 0 - 3
cloudbridge/cloud/interfaces/subservices.py

@@ -86,9 +86,6 @@ class GatewaySubService(PageableObjectMixin):
         The returned gateway object can subsequently be attached to a router to
         provide internet routing to a network.
 
-        :type  name: ``str``
-        :param name: The gateway label.
-
         :rtype: ``object``  of :class:`.InternetGateway` or ``None``
         :return: an InternetGateway object of ``None`` if not found.
         """

+ 51 - 0
cloudbridge/cloud/providers/aws/services.py

@@ -15,6 +15,7 @@ from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.services import BaseBucketObjectService
 from cloudbridge.cloud.base.services import BaseBucketService
 from cloudbridge.cloud.base.services import BaseComputeService
+from cloudbridge.cloud.base.services import BaseGatewayService
 from cloudbridge.cloud.base.services import BaseImageService
 from cloudbridge.cloud.base.services import BaseInstanceService
 from cloudbridge.cloud.base.services import BaseKeyPairService
@@ -47,6 +48,7 @@ from .helpers import BotoS3Service
 from .resources import AWSBucket
 from .resources import AWSBucketObject
 from .resources import AWSInstance
+from .resources import AWSInternetGateway
 from .resources import AWSKeyPair
 from .resources import AWSLaunchConfig
 from .resources import AWSMachineImage
@@ -786,6 +788,7 @@ class AWSNetworkingService(BaseNetworkingService):
         self._network_service = AWSNetworkService(self.provider)
         self._subnet_service = AWSSubnetService(self.provider)
         self._router_service = AWSRouterService(self.provider)
+        self._gateway_service = AWSGatewayService(self.provider)
 
     @property
     def networks(self):
@@ -799,6 +802,10 @@ class AWSNetworkingService(BaseNetworkingService):
     def routers(self):
         return self._router_service
 
+    @property
+    def _gateways(self):
+        return self._gateway_service
+
 
 class AWSNetworkService(BaseNetworkService):
 
@@ -1088,3 +1095,47 @@ class AWSRouterService(BaseRouterService):
         if r:
             # pylint:disable=protected-access
             r._route_table.delete()
+
+
+class AWSGatewayService(BaseGatewayService):
+
+    def __init__(self, provider):
+        super(AWSGatewayService, self).__init__(provider)
+        self.svc = BotoEC2Service(provider=provider,
+                                  cb_resource=AWSInternetGateway,
+                                  boto_collection_name='internet_gateways')
+
+    def get_or_create_inet_gateway(self, network):
+        log.debug("Get or create inet gateway on net %s",
+                  network)
+        network_id = network.id if isinstance(
+            network, AWSNetwork) else network
+        # Don't filter by label because it may conflict with at least the
+        # default VPC that most accounts have but that network is typically
+        # without a name.
+        gtw = self.svc.find(filter_name='attachment.vpc-id',
+                            filter_value=network_id)
+        if gtw:
+            return gtw[0]  # There can be only one gtw attached to a VPC
+        # Gateway does not exist so create one and attach to the supplied net
+        cb_gateway = self.svc.create('create_internet_gateway')
+        cb_gateway._gateway.create_tags(
+            Tags=[{'Key': 'Name',
+                   'Value': AWSInternetGateway.CB_DEFAULT_INET_GATEWAY_NAME
+                   }])
+        cb_gateway._gateway.attach_to_vpc(VpcId=network_id)
+        return cb_gateway
+
+    def delete(self, network, gateway):
+        log.debug("Service deleting AWS Gateway %s", gateway)
+        gateway_id = gateway.id if isinstance(
+            gateway, AWSInternetGateway) else gateway
+        gateway = self.svc.get(gateway_id)
+        if gateway:
+            gateway.delete()
+
+    def list(self, network, limit=None, marker=None):
+        log.debug("Listing current AWS internet gateways for net %s.",
+                  network.id)
+        fltr = [{'Name': 'attachment.vpc-id', 'Values': [network.id]}]
+        return self.svc.list(limit=None, marker=None, Filters=fltr)

+ 6 - 46
cloudbridge/cloud/providers/aws/subservices.py

@@ -14,8 +14,6 @@ from cloudbridge.cloud.interfaces.resources import TrafficDirection
 from .helpers import BotoEC2Service
 from .helpers import trim_empty_params
 from .resources import AWSFloatingIP
-from .resources import AWSInternetGateway
-from .resources import AWSNetwork
 from .resources import AWSVMFirewall
 from .resources import AWSVMFirewallRule
 
@@ -28,6 +26,12 @@ class AWSBucketObjectSubService(BaseBucketObjectSubService):
         super(AWSBucketObjectSubService, self).__init__(provider, bucket)
 
 
+class AWSGatewaySubService(BaseGatewaySubService):
+
+    def __init__(self, provider, network):
+        super(AWSGatewaySubService, self).__init__(provider, network)
+
+
 class AWSVMFirewallRuleSubService(BaseVMFirewallRuleSubService):
 
     def __init__(self, provider, firewall):
@@ -101,47 +105,3 @@ class AWSFloatingIPSubService(BaseFloatingIPSubService):
         return AWSFloatingIP(
             self._provider,
             self._provider.ec2_conn.VpcAddress(ip.get('AllocationId')))
-
-
-class AWSGatewaySubService(BaseGatewaySubService):
-
-    def __init__(self, provider, network):
-        super(AWSGatewaySubService, self).__init__(provider, network)
-        self.svc = BotoEC2Service(provider=provider,
-                                  cb_resource=AWSInternetGateway,
-                                  boto_collection_name='internet_gateways')
-
-    def get_or_create_inet_gateway(self):
-        log.debug("Get or create inet gateway on net %s",
-                  self._network)
-        network_id = self._network.id if isinstance(
-            self._network, AWSNetwork) else self._network
-        # Don't filter by label because it may conflict with at least the
-        # default VPC that most accounts have but that network is typically
-        # without a name.
-        gtw = self.svc.find(filter_name='attachment.vpc-id',
-                            filter_value=network_id)
-        if gtw:
-            return gtw[0]  # There can be only one gtw attached to a VPC
-        # Gateway does not exist so create one and attach to the supplied net
-        cb_gateway = self.svc.create('create_internet_gateway')
-        cb_gateway._gateway.create_tags(
-            Tags=[{'Key': 'Name',
-                   'Value': AWSInternetGateway.CB_DEFAULT_INET_GATEWAY_NAME
-                   }])
-        cb_gateway._gateway.attach_to_vpc(VpcId=network_id)
-        return cb_gateway
-
-    def delete(self, gateway):
-        log.debug("Service deleting AWS Gateway %s", gateway)
-        gateway_id = gateway.id if isinstance(
-            gateway, AWSInternetGateway) else gateway
-        gateway = self.svc.get(gateway_id)
-        if gateway:
-            gateway.delete()
-
-    def list(self, limit=None, marker=None):
-        log.debug("Listing current AWS internet gateways for net %s.",
-                  self._network.id)
-        fltr = [{'Name': 'attachment.vpc-id', 'Values': [self._network.id]}]
-        return self.svc.list(limit=None, marker=None, Filters=fltr)

+ 27 - 0
cloudbridge/cloud/providers/azure/services.py

@@ -14,6 +14,7 @@ from cloudbridge.cloud.base.resources import ServerPagedResultList
 from cloudbridge.cloud.base.services import BaseBucketObjectService
 from cloudbridge.cloud.base.services import BaseBucketService
 from cloudbridge.cloud.base.services import BaseComputeService
+from cloudbridge.cloud.base.services import BaseGatewayService
 from cloudbridge.cloud.base.services import BaseImageService
 from cloudbridge.cloud.base.services import BaseInstanceService
 from cloudbridge.cloud.base.services import BaseKeyPairService
@@ -42,6 +43,7 @@ from cloudbridge.cloud.interfaces.resources import Volume
 from .resources import AzureBucket
 from .resources import AzureBucketObject
 from .resources import AzureInstance
+from .resources import AzureInternetGateway
 from .resources import AzureKeyPair
 from .resources import AzureLaunchConfig
 from .resources import AzureMachineImage
@@ -1217,3 +1219,28 @@ class AzureRouterService(BaseRouterService):
         r = router if isinstance(router, AzureRouter) else self.get(router)
         if r:
             self.provider.azure_client.delete_route_table(r.name)
+
+
+class AzureGatewayService(BaseGatewayService):
+    def __init__(self, provider):
+        super(AzureGatewayService, self).__init__(provider)
+
+    # Azure doesn't have a notion of a route table or an internet
+    # gateway as OS and AWS so create placeholder objects of the
+    # AzureInternetGateway here.
+    # http://bit.ly/2BqGdVh
+    # Singleton returned by the list and get methods
+    def _gateway_singleton(self, network):
+        return AzureInternetGateway(self._provider, None, network)
+
+    def get_or_create_inet_gateway(self, network):
+        return self._gateway_singleton(network)
+
+    def list(self, network, limit=None, marker=None):
+        gws = [self._gateway_singleton(network)]
+        return ClientPagedResultList(self._provider,
+                                     gws,
+                                     limit=limit, marker=marker)
+
+    def delete(self, network, gateway):
+        pass

+ 5 - 23
cloudbridge/cloud/providers/azure/subservices.py

@@ -10,7 +10,6 @@ from cloudbridge.cloud.base.subservices import BaseVMFirewallRuleSubService
 from cloudbridge.cloud.interfaces.resources import TrafficDirection
 
 from .resources import AzureFloatingIP
-from .resources import AzureInternetGateway
 from .resources import AzureVMFirewallRule
 
 log = logging.getLogger(__name__)
@@ -22,6 +21,11 @@ class AzureBucketObjectSubService(BaseBucketObjectSubService):
         super(AzureBucketObjectSubService, self).__init__(provider, bucket)
 
 
+class AzureGatewaySubService(BaseGatewaySubService):
+    def __init__(self, provider, network):
+        super(AzureGatewaySubService, self).__init__(provider, network)
+
+
 class AzureVMFirewallRuleSubService(BaseVMFirewallRuleSubService):
 
     def __init__(self, provider, firewall):
@@ -86,28 +90,6 @@ class AzureVMFirewallRuleSubService(BaseVMFirewallRuleSubService):
         return AzureVMFirewallRule(self.firewall, result)
 
 
-class AzureGatewaySubService(BaseGatewaySubService):
-    def __init__(self, provider, network):
-        super(AzureGatewaySubService, self).__init__(provider, network)
-        # Azure doesn't have a notion of a route table or an internet
-        # gateway as OS and AWS so create placeholder objects of the
-        # AzureInternetGateway here.
-        # http://bit.ly/2BqGdVh
-        # Singleton returned by the list method
-        self.gateway_singleton = AzureInternetGateway(self._provider, None,
-                                                      network)
-
-    def get_or_create_inet_gateway(self):
-        gateway = AzureInternetGateway(self._provider, None, self._network)
-        return gateway
-
-    def list(self, limit=None, marker=None):
-        return [self.gateway_singleton]
-
-    def delete(self, gateway):
-        pass
-
-
 class AzureFloatingIPSubService(BaseFloatingIPSubService):
 
     def __init__(self, provider, gateway, network_id):

+ 27 - 0
cloudbridge/cloud/providers/gce/services.py

@@ -14,6 +14,7 @@ from cloudbridge.cloud.base.resources import ServerPagedResultList
 from cloudbridge.cloud.base.services import BaseBucketObjectService
 from cloudbridge.cloud.base.services import BaseBucketService
 from cloudbridge.cloud.base.services import BaseComputeService
+from cloudbridge.cloud.base.services import BaseGatewayService
 from cloudbridge.cloud.base.services import BaseImageService
 from cloudbridge.cloud.base.services import BaseInstanceService
 from cloudbridge.cloud.base.services import BaseKeyPairService
@@ -36,6 +37,7 @@ from cloudbridge.cloud.providers.gce import helpers
 
 from .resources import GCEFirewallsDelegate
 from .resources import GCEInstance
+from .resources import GCEInternetGateway
 from .resources import GCEKeyPair
 from .resources import GCELaunchConfig
 from .resources import GCEMachineImage
@@ -1426,3 +1428,28 @@ class GCSBucketObjectService(BaseBucketObjectService):
         return GCSObject(self._provider,
                          bucket,
                          response) if response else None
+
+
+class GCEGatewayService(BaseGatewayService):
+    _DEFAULT_GATEWAY_NAME = 'default-internet-gateway'
+    _GATEWAY_URL_PREFIX = 'global/gateways/'
+
+    def __init__(self, provider):
+        super(GCEGatewayService, self).__init__(provider)
+        self._default_internet_gateway = GCEInternetGateway(
+            provider,
+            {'id': (GCEGatewayService._GATEWAY_URL_PREFIX +
+                    GCEGatewayService._DEFAULT_GATEWAY_NAME),
+             'name': GCEGatewayService._DEFAULT_GATEWAY_NAME})
+
+    def get_or_create_inet_gateway(self, network):
+        return self._default_internet_gateway
+
+    def delete(self, network, gateway):
+        pass
+
+    def list(self, network, limit=None, marker=None):
+        gws = [self._default_internet_gateway]
+        return ClientPagedResultList(self._provider,
+                                     gws,
+                                     limit=limit, marker=marker)

+ 5 - 25
cloudbridge/cloud/providers/gce/subservices.py

@@ -10,7 +10,6 @@ from cloudbridge.cloud.base.subservices import \
 from cloudbridge.cloud.base.subservices import BaseVMFirewallRuleSubService
 
 from .resources import GCEFloatingIP
-from .resources import GCEInternetGateway
 from .resources import GCEVMFirewallRule
 
 log = logging.getLogger(__name__)
@@ -22,6 +21,11 @@ class GCSBucketObjectSubService(BaseBucketObjectSubService):
         super(GCSBucketObjectSubService, self).__init__(provider, bucket)
 
 
+class GCEGatewaySubService(BaseGatewaySubService):
+    def __init__(self, provider, network):
+        super(GCEGatewaySubService, self).__init__(provider, network)
+
+
 class GCEVMFirewallRuleSubService(BaseVMFirewallRuleSubService):
 
     def __init__(self, firewall):
@@ -124,27 +128,3 @@ class GCEFloatingIPSubService(BaseFloatingIPSubService):
                     .execute())
         self._provider.wait_for_operation(response, region=region_name)
         return self.get(ip_name)
-
-
-class GCEGatewaySubService(BaseGatewaySubService):
-    _DEFAULT_GATEWAY_NAME = 'default-internet-gateway'
-    _GATEWAY_URL_PREFIX = 'global/gateways/'
-
-    def __init__(self, provider, network):
-        super(GCEGatewaySubService, self).__init__(provider, network)
-        self._default_internet_gateway = GCEInternetGateway(
-            provider,
-            {'id': (GCEGatewaySubService._GATEWAY_URL_PREFIX +
-                    GCEGatewaySubService._DEFAULT_GATEWAY_NAME),
-             'name': GCEGatewaySubService._DEFAULT_GATEWAY_NAME})
-
-    def get_or_create_inet_gateway(self, name=None):
-        return self._default_internet_gateway
-
-    def delete(self, gateway):
-        pass
-
-    def list(self, limit=None, marker=None):
-        return ClientPagedResultList(self._provider,
-                                     [self._default_internet_gateway],
-                                     limit=limit, marker=marker)

+ 46 - 0
cloudbridge/cloud/providers/openstack/services.py

@@ -22,6 +22,7 @@ from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.services import BaseBucketObjectService
 from cloudbridge.cloud.base.services import BaseBucketService
 from cloudbridge.cloud.base.services import BaseComputeService
+from cloudbridge.cloud.base.services import BaseGatewayService
 from cloudbridge.cloud.base.services import BaseImageService
 from cloudbridge.cloud.base.services import BaseInstanceService
 from cloudbridge.cloud.base.services import BaseKeyPairService
@@ -53,6 +54,7 @@ from cloudbridge.cloud.providers.openstack import helpers as oshelpers
 from .resources import OpenStackBucket
 from .resources import OpenStackBucketObject
 from .resources import OpenStackInstance
+from .resources import OpenStackInternetGateway
 from .resources import OpenStackKeyPair
 from .resources import OpenStackMachineImage
 from .resources import OpenStackNetwork
@@ -1083,3 +1085,47 @@ class OpenStackRouterService(BaseRouterService):
     def delete(self, router):
         r_id = router.id if isinstance(router, OpenStackRouter) else router
         self.provider.os_conn.delete_router(r_id)
+
+
+class OpenStackGatewayService(BaseGatewayService):
+    """For OpenStack, an internet gateway is a just an 'external' network."""
+
+    def __init__(self, provider):
+        super(OpenStackGatewayService, self).__init__(provider)
+
+    def _check_fip_connectivity(self, network, external_net):
+        # Due to current limitations in OpenStack:
+        # https://bugs.launchpad.net/neutron/+bug/1743480, it's not
+        # possible to differentiate between floating ip networks and provider
+        # external networks. Therefore, we systematically step through
+        # all available networks and perform an assignment test to infer valid
+        # floating ip nets.
+        dummy_router = self._provider.networking.routers.create(
+            label='cb-conn-test-router', network=network)
+        with cb_helpers.cleanup_action(lambda: dummy_router.delete()):
+            try:
+                dummy_router.attach_gateway(external_net)
+                return True
+            except Exception:
+                return False
+
+    def get_or_create_inet_gateway(self, network):
+        """For OS, inet gtw is any net that has `external` property set."""
+        external_nets = (n for n in self._provider.networking.networks
+                         if n.external)
+        for net in external_nets:
+            if self._check_fip_connectivity(net):
+                return OpenStackInternetGateway(self._provider, net)
+        return None
+
+    def delete(self, network, gateway):
+        log.debug("Deleting OpenStack Gateway: %s", gateway)
+        gateway.delete()
+
+    def list(self, network, limit=None, marker=None):
+        log.debug("OpenStack listing of all current internet gateways")
+        igl = [OpenStackInternetGateway(self._provider, n)
+               for n in self._provider.networking.networks
+               if n.external and self._check_fip_connectivity(n)]
+        return ClientPagedResultList(self._provider, igl, limit=limit,
+                                     marker=marker)

+ 0 - 40
cloudbridge/cloud/providers/openstack/subservices.py

@@ -4,7 +4,6 @@ from openstack.exceptions import HttpException
 from openstack.exceptions import NotFoundException
 from openstack.exceptions import ResourceNotFound
 
-from cloudbridge.cloud.base import helpers as cb_helpers
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.subservices import BaseBucketObjectSubService
 from cloudbridge.cloud.base.subservices import BaseFloatingIPSubService
@@ -15,7 +14,6 @@ from cloudbridge.cloud.interfaces.exceptions import InvalidValueException
 from cloudbridge.cloud.interfaces.resources import TrafficDirection
 
 from .resources import OpenStackFloatingIP
-from .resources import OpenStackInternetGateway
 from .resources import OpenStackVMFirewall
 from .resources import OpenStackVMFirewallRule
 
@@ -29,48 +27,10 @@ class OpenStackBucketObjectSubService(BaseBucketObjectSubService):
 
 
 class OpenStackGatewaySubService(BaseGatewaySubService):
-    """For OpenStack, an internet gateway is a just an 'external' network."""
 
     def __init__(self, provider, network):
         super(OpenStackGatewaySubService, self).__init__(provider, network)
 
-    def _check_fip_connectivity(self, external_net):
-        # Due to current limitations in OpenStack:
-        # https://bugs.launchpad.net/neutron/+bug/1743480, it's not
-        # possible to differentiate between floating ip networks and provider
-        # external networks. Therefore, we systematically step through
-        # all available networks and perform an assignment test to infer valid
-        # floating ip nets.
-        dummy_router = self._provider.networking.routers.create(
-            label='cb-conn-test-router', network=self._network)
-        with cb_helpers.cleanup_action(lambda: dummy_router.delete()):
-            try:
-                dummy_router.attach_gateway(external_net)
-                return True
-            except Exception:
-                return False
-
-    def get_or_create_inet_gateway(self):
-        """For OS, inet gtw is any net that has `external` property set."""
-        external_nets = (n for n in self._provider.networking.networks
-                         if n.external)
-        for net in external_nets:
-            if self._check_fip_connectivity(net):
-                return OpenStackInternetGateway(self._provider, net)
-        return None
-
-    def delete(self, gateway):
-        log.debug("Deleting OpenStack Gateway: %s", gateway)
-        gateway.delete()
-
-    def list(self, limit=None, marker=None):
-        log.debug("OpenStack listing of all current internet gateways")
-        igl = [OpenStackInternetGateway(self._provider, n)
-               for n in self._provider.networking.networks
-               if n.external and self._check_fip_connectivity(n)]
-        return ClientPagedResultList(self._provider, igl, limit=limit,
-                                     marker=marker)
-
 
 class OpenStackFloatingIPSubService(BaseFloatingIPSubService):