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

First pass at moving gateways under a network

Didn't update the tests yet.

xref https://github.com/gvlproject/cloudbridge/issues/104
Enis Afgan 8 лет назад
Родитель
Сommit
7f33eef3aa

+ 9 - 0
cloudbridge/cloud/base/resources.py

@@ -22,6 +22,7 @@ from cloudbridge.cloud.interfaces.resources import CloudResource
 from cloudbridge.cloud.interfaces.resources import FloatingIP
 from cloudbridge.cloud.interfaces.resources import FloatingIPContainer
 from cloudbridge.cloud.interfaces.resources import FloatingIpState
+from cloudbridge.cloud.interfaces.resources import GatewayContainer
 from cloudbridge.cloud.interfaces.resources import GatewayState
 from cloudbridge.cloud.interfaces.resources import Instance
 from cloudbridge.cloud.interfaces.resources import InstanceState
@@ -912,6 +913,13 @@ class BaseBucketContainer(BasePageableObjectMixin, BucketContainer):
         return self.__provider
 
 
+class BaseGatewayContainer(GatewayContainer, BasePageableObjectMixin):
+
+    def __init__(self, provider, network):
+        self._network = network
+        self._provider = provider
+
+
 class BaseNetwork(BaseCloudResource, BaseObjectLifeCycleMixin, Network):
 
     CB_DEFAULT_NETWORK_NAME = os.environ.get('CB_DEFAULT_NETWORK_NAME',
@@ -1050,6 +1058,7 @@ class BaseInternetGateway(BaseCloudResource, BaseObjectLifeCycleMixin,
 
     def __init__(self, provider):
         super(BaseInternetGateway, self).__init__(provider)
+        self.__provider = provider
 
     def __repr__(self):
         return "<CB-{0}: {1} ({2})>".format(self.__class__.__name__, self.id,

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

@@ -8,7 +8,6 @@ from cloudbridge.cloud.interfaces.resources import Router
 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
@@ -208,10 +207,3 @@ class BaseRouterService(
             if router:
                 log.info("Router %s successful deleted.", router)
                 router.delete()
-
-
-class BaseGatewayService(
-        GatewayService, BaseCloudService):
-
-    def __init__(self, provider):
-        super(BaseGatewayService, self).__init__(provider)

+ 54 - 0
cloudbridge/cloud/interfaces/resources.py

@@ -888,6 +888,16 @@ class Network(ObjectLifeCycleMixin, CloudResource):
         """
         pass
 
+    @abstractproperty
+    def gateways(self):
+        """
+        Provides access to the internet gateways attached to this network.
+
+        :rtype: :class:`.GatewayContainer`
+        :return: A GatewayContainer object
+        """
+        pass
+
 
 class SubnetState(object):
     """
@@ -1205,6 +1215,50 @@ class GatewayState(object):
     ERROR = "error"
 
 
+class GatewayContainer(PageableObjectMixin):
+    """
+    Manage internet gateway resources.
+    """
+    __metaclass__ = ABCMeta
+
+    @abstractmethod
+    def get_or_create_inet_gateway(self, name=None):
+        """
+        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  name: ``str``
+        :param name: The gateway name. This applies only if creating a gateway
+                     and if the provider supports it.
+
+        :rtype: ``object``  of :class:`.InternetGateway` or ``None``
+        :return: an InternetGateway object of ``None`` if not found.
+        """
+        pass
+
+    @abstractmethod
+    def delete(self, gateway):
+        """
+        Delete a gateway.
+
+        :type gateway: :class:`.Gateway` object
+        :param gateway: Gateway object to delete.
+        """
+        pass
+
+    @abstractmethod
+    def list(self, limit=None, marker=None):
+        """
+        List all available internet gateways.
+
+        :rtype: ``list`` of :class:`.InternetGateway` or ``None``
+        :return: Current list of internet gateways.
+        """
+        pass
+
+
 class Gateway(CloudResource):
     """
     Represents a gateway resource.

+ 22 - 58
cloudbridge/cloud/interfaces/services.py

@@ -580,17 +580,6 @@ class NetworkingService(CloudService):
         """
         pass
 
-    @abstractproperty
-    def gateways(self):
-        """
-        Provides access to all Gateway related services, such as
-        Internet Gateways.
-
-        :rtype: :class:`.GatewayService`
-        :return: a Router service object
-        """
-        pass
-
 
 class NetworkService(PageableObjectMixin, CloudService):
 
@@ -690,6 +679,28 @@ class NetworkService(PageableObjectMixin, CloudService):
         """
         pass
 
+    @abstractproperty
+    def gateways(self):
+        """
+        Provides access to internet gateways associated with this network.
+
+        Example:
+
+        .. code-block:: python
+
+            # Print all gateways
+            for g in provider.networking.gateways:
+                print(g.id, g.name)
+
+            # Get a default gateway
+            g = network.gateways.get_or_create_inet_gateway('name')
+            print(g.id, g.name)
+
+        :rtype: :class:`.GatewayService`
+        :return: a GatewayService object
+        """
+        pass
+
 
 class SubnetService(PageableObjectMixin, CloudService):
 
@@ -864,53 +875,6 @@ class RouterService(PageableObjectMixin, CloudService):
         pass
 
 
-class GatewayService(CloudService):
-    """
-    Manage internet gateway resources.
-    """
-    __metaclass__ = ABCMeta
-
-    @abstractmethod
-    def get_or_create_inet_gateway(self, network, name=None):
-        """
-        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: :class:`.Network` object or ``str``
-        :param network: Network object or ID to which the gateway is attached.
-
-        :type  name: ``str``
-        :param name: The gateway name. This applies only if creating a gateway
-                     and if the provider supports it.
-
-        :rtype: ``object``  of :class:`.InternetGateway` or ``None``
-        :return: an InternetGateway object of ``None`` if not found.
-        """
-        pass
-
-    @abstractmethod
-    def delete(self, gateway):
-        """
-        Delete a gateway.
-
-        :type gateway: :class:`.Gateway` object
-        :param gateway: Gateway object to delete.
-        """
-        pass
-
-    @abstractmethod
-    def list(self, limit=None, marker=None):
-        """
-        List all available internet gateways.
-
-        :rtype: ``list`` of :class:`.InternetGateway` or ``None``
-        :return: Current list of internet gateways.
-        """
-        pass
-
-
 class BucketService(PageableObjectMixin, CloudService):
 
     """

+ 50 - 0
cloudbridge/cloud/providers/aws/resources.py

@@ -14,6 +14,7 @@ from cloudbridge.cloud.base.resources import BaseBucketContainer
 from cloudbridge.cloud.base.resources import BaseBucketObject
 from cloudbridge.cloud.base.resources import BaseFloatingIP
 from cloudbridge.cloud.base.resources import BaseFloatingIPContainer
+from cloudbridge.cloud.base.resources import BaseGatewayContainer
 from cloudbridge.cloud.base.resources import BaseInstance
 from cloudbridge.cloud.base.resources import BaseInternetGateway
 from cloudbridge.cloud.base.resources import BaseKeyPair
@@ -879,6 +880,7 @@ class AWSNetwork(BaseNetwork):
     def __init__(self, provider, network):
         super(AWSNetwork, self).__init__(provider)
         self._vpc = network
+        self._gtw_container = AWSGatewayContainer(provider, self)
 
     @property
     def id(self):
@@ -935,6 +937,10 @@ class AWSNetwork(BaseNetwork):
             VpcIds=[self.id])
         self.refresh()
 
+    @property
+    def gateways(self):
+        return self._gtw_container
+
 
 class AWSSubnet(BaseSubnet):
 
@@ -1118,6 +1124,50 @@ class AWSRouter(BaseRouter):
             InternetGatewayId=gw_id, VpcId=self._route_table.vpc_id)
 
 
+class AWSGatewayContainer(BaseGatewayContainer):
+
+    def __init__(self, provider, network):
+        super(AWSGatewayContainer, self).__init__(provider, network)
+        self.svc = BotoEC2Service(provider=provider,
+                                  cb_resource=AWSInternetGateway,
+                                  boto_collection_name='internet_gateways')
+
+    def get_or_create_inet_gateway(self, name=None):
+        log.debug("Get or create inet gateway %s on net %s", name,
+                  self._network)
+        if name:
+            AWSInternetGateway.assert_valid_resource_name(name)
+
+        network_id = self._network.id if isinstance(
+            self._network, AWSNetwork) else self._network
+        # Don't filter by name 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')
+        if name:
+            cb_gateway.name = 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.")
+        return self.svc.list(limit=None, marker=None)
+
+
+
 class AWSInternetGateway(BaseInternetGateway):
 
     def __init__(self, provider, gateway):

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

@@ -8,7 +8,6 @@ import cloudbridge.cloud.base.helpers as cb_helpers
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 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
@@ -615,7 +614,6 @@ 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):
@@ -629,10 +627,6 @@ class AWSNetworkingService(BaseNetworkingService):
     def routers(self):
         return self._router_service
 
-    @property
-    def gateways(self):
-        return self._gateway_service
-
 
 class AWSNetworkService(BaseNetworkService):
 
@@ -806,44 +800,3 @@ class AWSRouterService(BaseRouterService):
         if name:
             cb_router.name = name
         return cb_router
-
-
-class AWSGatewayService(BaseGatewayService):
-
-    def __init__(self, provider):
-        super(AWSGatewayService, self).__init__(provider)
-        self.svc = BotoEC2Service(provider=self.provider,
-                                  cb_resource=AWSInternetGateway,
-                                  boto_collection_name='internet_gateways')
-
-    def get_or_create_inet_gateway(self, network, name=None):
-        log.debug("Get or create inet gateway %s on net %s", name, network)
-        if name:
-            AWSInternetGateway.assert_valid_resource_name(name)
-
-        network_id = network.id if isinstance(network, AWSNetwork) else network
-        # Don't filter by name 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')
-        if name:
-            cb_gateway.name = 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.")
-        return self.svc.list(limit=None, marker=None)

+ 33 - 3
cloudbridge/cloud/providers/azure/resources.py

@@ -12,8 +12,8 @@ from azure.mgmt.network.models import NetworkSecurityGroup
 import cloudbridge.cloud.base.helpers as cb_helpers
 from cloudbridge.cloud.base.resources import BaseAttachmentInfo, \
     BaseBucket, BaseBucketContainer, BaseBucketObject, BaseFloatingIP, \
-    BaseFloatingIPContainer, BaseInstance, BaseInternetGateway, BaseKeyPair, \
-    BaseLaunchConfig, \
+    BaseFloatingIPContainer, BaseGatewayContainer, BaseInstance, \
+    BaseInternetGateway, BaseKeyPair, BaseLaunchConfig, \
     BaseMachineImage, BaseNetwork, BasePlacementZone, BaseRegion, BaseRouter, \
     BaseSnapshot, BaseSubnet, BaseVMFirewall, BaseVMFirewallRule, \
     BaseVMFirewallRuleContainer, BaseVMType, BaseVolume, ClientPagedResultList
@@ -859,6 +859,32 @@ class AzureMachineImage(BaseMachineImage):
             self._state = "unknown"
 
 
+class AzureGatewayContainer(BaseGatewayContainer):
+    def __init__(self, provider, network):
+        super(AzureGatewayContainer, 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, name=None):
+        if name:
+            AzureInternetGateway.assert_valid_resource_name(name)
+        gateway = AzureInternetGateway(self._provider, None, self._network)
+        if name:
+            gateway.name = name
+        return gateway
+
+    def list(self, limit=None, marker=None):
+        return [self.gateway_singleton]
+
+    def delete(self, gateway):
+        pass
+
+
 class AzureNetwork(BaseNetwork):
     NETWORK_STATE_MAP = {
         'InProgress': NetworkState.PENDING,
@@ -871,6 +897,7 @@ class AzureNetwork(BaseNetwork):
         self._state = self._network.provisioning_state
         if not self._network.tags:
             self._network.tags = {}
+        self._gateway_service = AzureGatewayContainer(provider, self)
 
     @property
     def id(self):
@@ -967,6 +994,10 @@ class AzureNetwork(BaseNetwork):
         return self._provider.networking.subnets. \
             create(network=self.id, cidr_block=cidr_block, name=name)
 
+    @property
+    def gateways(self):
+        return self._gateway_service
+
 
 class AzureFloatingIPContainer(BaseFloatingIPContainer):
 
@@ -1732,7 +1763,6 @@ class AzureInternetGateway(BaseInternetGateway):
         super(AzureInternetGateway, self).__init__(provider)
         self._gateway = gateway
         self._name = None
-        self._network_id = None
         self._network_id = gateway_net.id if isinstance(
             gateway_net, AzureNetwork) else gateway_net
         self._state = ''

+ 1 - 32
cloudbridge/cloud/providers/azure/services.py

@@ -8,7 +8,7 @@ import cloudbridge.cloud.base.helpers as cb_helpers
 from cloudbridge.cloud.base.resources import ClientPagedResultList, \
     ServerPagedResultList
 from cloudbridge.cloud.base.services import BaseBucketService, \
-    BaseComputeService, BaseGatewayService, \
+    BaseComputeService, \
     BaseImageService, BaseInstanceService, BaseKeyPairService, \
     BaseNetworkService, BaseNetworkingService, BaseRegionService, \
     BaseRouterService, BaseSecurityService, BaseSnapshotService, \
@@ -790,7 +790,6 @@ class AzureNetworkingService(BaseNetworkingService):
         self._network_service = AzureNetworkService(self.provider)
         self._subnet_service = AzureSubnetService(self.provider)
         self._router_service = AzureRouterService(self.provider)
-        self._gateway_service = AzureGatewayService(self.provider)
 
     @property
     def networks(self):
@@ -804,10 +803,6 @@ class AzureNetworkingService(BaseNetworkingService):
     def routers(self):
         return self._router_service
 
-    @property
-    def gateways(self):
-        return self._gateway_service
-
 
 class AzureNetworkService(BaseNetworkService):
     def __init__(self, provider):
@@ -1079,29 +1074,3 @@ class AzureRouterService(BaseRouterService):
         route = self.provider.azure_client. \
             create_route_table(name, parameters)
         return AzureRouter(self.provider, route)
-
-
-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
-        self.inet_gateways = []
-
-    def get_or_create_inet_gateway(self, network, name=None):
-        if name:
-            AzureInternetGateway.assert_valid_resource_name(name)
-        gateway = AzureInternetGateway(self.provider, None, network)
-        if name:
-            gateway.name = name
-        if gateway not in self.inet_gateways:
-            self.inet_gateways.append(gateway)
-        return gateway
-
-    def list(self, limit=None, marker=None):
-        return self.inet_gateways
-
-    def delete(self, gateway):
-        pass

+ 34 - 0
cloudbridge/cloud/providers/openstack/resources.py

@@ -13,6 +13,7 @@ from cloudbridge.cloud.base.resources import BaseBucketContainer
 from cloudbridge.cloud.base.resources import BaseBucketObject
 from cloudbridge.cloud.base.resources import BaseFloatingIP
 from cloudbridge.cloud.base.resources import BaseFloatingIPContainer
+from cloudbridge.cloud.base.resources import BaseGatewayContainer
 from cloudbridge.cloud.base.resources import BaseInstance
 from cloudbridge.cloud.base.resources import BaseInternetGateway
 from cloudbridge.cloud.base.resources import BaseKeyPair
@@ -711,6 +712,34 @@ class OpenStackSnapshot(BaseSnapshot):
         return cb_vol
 
 
+class OpenStackGatewayContainer(BaseGatewayContainer):
+    """For OpenStack, an internet gateway is a just an 'external' network."""
+
+    def __init__(self, provider, network):
+        super(OpenStackGatewayContainer, self).__init__(provider, network)
+
+    def get_or_create_inet_gateway(self, name=None):
+        """For OS, inet gtw is any net that has `external` property set."""
+        if name:
+            OpenStackInternetGateway.assert_valid_resource_name(name)
+
+        for n in self._provider.networking.networks:
+            if n.external:
+                return OpenStackInternetGateway(self._provider, n)
+        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]
+        return ClientPagedResultList(self._provider, igl, limit=limit,
+                                     marker=marker)
+
+
 class OpenStackNetwork(BaseNetwork):
 
     # Ref: https://github.com/openstack/neutron/blob/master/neutron/plugins/
@@ -729,6 +758,7 @@ class OpenStackNetwork(BaseNetwork):
     def __init__(self, provider, network):
         super(OpenStackNetwork, self).__init__(provider)
         self._network = network
+        self._gateway_service = OpenStackGatewayContainer(provider, self)
 
     @property
     def id(self):
@@ -795,6 +825,10 @@ class OpenStackNetwork(BaseNetwork):
             # subnet no longer exists
             self._network.state = NetworkState.UNKNOWN
 
+    @property
+    def gateways(self):
+        return self._gateway_service
+
 
 class OpenStackSubnet(BaseSubnet):
 

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

@@ -12,7 +12,6 @@ from cloudbridge.cloud.base.resources import BaseLaunchConfig
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 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
@@ -782,7 +781,6 @@ class OpenStackNetworkingService(BaseNetworkingService):
         self._network_service = OpenStackNetworkService(self.provider)
         self._subnet_service = OpenStackSubnetService(self.provider)
         self._router_service = OpenStackRouterService(self.provider)
-        self._gateway_service = OpenStackGatewayService(self.provider)
 
     @property
     def networks(self):
@@ -796,10 +794,6 @@ class OpenStackNetworkingService(BaseNetworkingService):
     def routers(self):
         return self._router_service
 
-    @property
-    def gateways(self):
-        return self._gateway_service
-
 
 class OpenStackNetworkService(BaseNetworkService):
 
@@ -955,31 +949,3 @@ class OpenStackRouterService(BaseRouterService):
         body = {'router': {'name': name}} if name else None
         router = self.provider.neutron.create_router(body)
         return OpenStackRouter(self.provider, router.get('router'))
-
-
-class OpenStackGatewayService(BaseGatewayService):
-    """For OpenStack, an internet gateway is a just an 'external' network."""
-
-    def __init__(self, provider):
-        super(OpenStackGatewayService, self).__init__(provider)
-
-    def get_or_create_inet_gateway(self, network, name=None):
-        """For OS, inet gtw is any net that has `external` property set."""
-        if name:
-            OpenStackInternetGateway.assert_valid_resource_name(name)
-
-        for n in self.provider.networking.networks:
-            if n.external:
-                return OpenStackInternetGateway(self.provider, n)
-        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]
-        return ClientPagedResultList(self.provider, igl, limit=limit,
-                                     marker=marker)