Enis Afgan 8 лет назад
Родитель
Сommit
4df449b92a

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

@@ -12,6 +12,7 @@ from cloudbridge.cloud.interfaces.services import NetworkService
 from cloudbridge.cloud.interfaces.services import NetworkingService
 from cloudbridge.cloud.interfaces.services import ObjectStoreService
 from cloudbridge.cloud.interfaces.services import RegionService
+from cloudbridge.cloud.interfaces.services import RouterService
 from cloudbridge.cloud.interfaces.services import SecurityGroupService
 from cloudbridge.cloud.interfaces.services import SecurityService
 from cloudbridge.cloud.interfaces.services import SnapshotService
@@ -176,3 +177,10 @@ class BaseSubnetService(
         else:
             raise TypeError(
                 "Invalid parameters for search. Supported attributes: {name}")
+
+
+class BaseRouterService(
+        BasePageableObjectMixin, RouterService, BaseCloudService):
+
+    def __init__(self, provider):
+        super(BaseRouterService, self).__init__(provider)

+ 74 - 2
cloudbridge/cloud/interfaces/services.py

@@ -530,6 +530,16 @@ class NetworkingService(CloudService):
         """
         pass
 
+    @abstractproperty
+    def routers(self):
+        """
+        Provides access to all Router related services.
+
+        :rtype: :class:`.RouterService`
+        :return: a Router service object
+        """
+        pass
+
 
 class NetworkService(PageableObjectMixin, CloudService):
 
@@ -686,8 +696,8 @@ class SubnetService(PageableObjectMixin, CloudService):
         """
         Returns a Subnet given its ID or ``None`` if not found.
 
-        :type network_id: :class:`.Network` object or ``str``
-        :param network_id: The ID of the subnet to retrieve.
+        :type subnet_id: :class:`.Network` object or ``str``
+        :param subnet_id: The ID of the subnet to retrieve.
 
         :rtype: ``object`` of :class:`.Subnet`
         return: a Subnet object
@@ -768,6 +778,68 @@ class SubnetService(PageableObjectMixin, CloudService):
         pass
 
 
+class RouterService(PageableObjectMixin, CloudService):
+
+    """
+    Manage networking router actions and resoruces.
+    """
+    __metaclass__ = ABCMeta
+
+    @abstractmethod
+    def get(self, router_id):
+        """
+        Returns a Router object given its ID.
+
+        :type router_id: ``str``
+        :param router_id: The ID of the router to retrieve.
+
+        :rtyoe: ``object``  of :class:`.Router` or ``None``
+        :return: a Router object ot ``None`` if not found.
+        """
+        pass
+
+    @abstractmethod
+    def list(self, limit=None, marker=None):
+        """
+        List all routers.
+
+        :rtype: ``list`` of :class:`.Router`
+        :return: list of Router objects
+        """
+        pass
+
+    @abstractmethod
+    def create(self, network, name=None):
+        """
+        Create a new router.
+
+        :type network: :class:`.Network` object or ``str``
+        :param network: Network object or ID under which to create the router.
+
+        :type name: ``str``
+        :param name: A router name. The name will be set if the provider supports it.
+
+        :rtype: ``object`` of :class:`.Router`
+        :return:  A Router object
+        """
+        pass
+
+    @abstractmethod
+    def delete(self, router):
+        """
+        Delete an existing Router.
+
+        :type router: :class:`.Router` object or ``str``
+        :param router: Router object or ID of the router to delete.
+
+        :rtype: ``bool``
+        :return:  ``True`` if the router does not exist, ``False`` otherwise.
+                  Note that this implies that the router may not have been
+                  deleted by this method but instead has not existed at all.
+        """
+        pass
+
+
 class ObjectStoreService(PageableObjectMixin, CloudService):
 
     """

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

@@ -18,6 +18,7 @@ from cloudbridge.cloud.base.services import BaseNetworkService
 from cloudbridge.cloud.base.services import BaseNetworkingService
 from cloudbridge.cloud.base.services import BaseObjectStoreService
 from cloudbridge.cloud.base.services import BaseRegionService
+from cloudbridge.cloud.base.services import BaseRouterService
 from cloudbridge.cloud.base.services import BaseSecurityGroupService
 from cloudbridge.cloud.base.services import BaseSecurityService
 from cloudbridge.cloud.base.services import BaseSnapshotService
@@ -741,6 +742,7 @@ class AWSNetworkingService(BaseNetworkingService):
         super(AWSNetworkingService, self).__init__(provider)
         self._network_service = AWSNetworkService(self.provider)
         self._subnet_service = AWSSubnetService(self.provider)
+        self._router_service = AWSRouterService(self.provider)
 
     @property
     def networks(self):
@@ -750,6 +752,10 @@ class AWSNetworkingService(BaseNetworkingService):
     def subnets(self):
         return self._subnet_service
 
+    @property
+    def routers(self):
+        return self._router_service
+
 
 class AWSNetworkService(BaseNetworkService):
 
@@ -894,3 +900,41 @@ class AWSSubnetService(BaseSubnetService):
     def delete(self, subnet):
         subnet_id = subnet.id if isinstance(subnet, AWSSubnet) else subnet
         return self.provider.vpc_conn.delete_subnet(subnet_id=subnet_id)
+
+
+class AWSRouterService(BaseRouterService):
+    """For AWS, a CloudBridge router corresponds to an AWS Route Table."""
+
+    def __init__(self, provider):
+        super(AWSRouterService, self).__init__(provider)
+
+    def get(self, router_id):
+        try:
+            routers = self.provider.vpc_conn.get_all_route_tables([router_id])
+            return AWSRouter(self.provider, routers[0]) if routers else None
+        except EC2ResponseError as ec2e:
+            if ec2e.code == 'InvalidRouteTableID.NotFound':
+                return None
+            elif ec2e.code == 'InvalidParameterValue':
+                # Occurs if id does not start with 'rtb-...'
+                return None
+            raise ec2e
+
+    def list(self, limit=None, marker=None):
+        routers = self.provider.vpc_conn.get_all_route_tables()
+        aws_routers = [AWSRouter(self.provider, r) for r in routers]
+        return ClientPagedResultList(self.provider, aws_routers, limit=limit,
+                                     marker=marker)
+
+    def create(self, network, name=None):
+        network_id = network.id if isinstance(network, AWSNetwork) else network
+        router = self.provider.vpc_conn.create_route_table(vpc_id=network_id)
+        cb_router = AWSRouter(self.provider, router)
+        if name:
+            time.sleep(2)  # Some time is required
+            cb_router.name = name
+        return cb_router
+
+    def delete(self, router):
+        router_id = router.id if isinstance(router, AWSRouter) else router
+        return self.provider.vpc_conn.delete_route_table(router_id)

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

@@ -19,6 +19,7 @@ from cloudbridge.cloud.base.services import BaseNetworkService
 from cloudbridge.cloud.base.services import BaseNetworkingService
 from cloudbridge.cloud.base.services import BaseObjectStoreService
 from cloudbridge.cloud.base.services import BaseRegionService
+from cloudbridge.cloud.base.services import BaseRouterService
 from cloudbridge.cloud.base.services import BaseSecurityGroupService
 from cloudbridge.cloud.base.services import BaseSecurityService
 from cloudbridge.cloud.base.services import BaseSnapshotService
@@ -717,6 +718,7 @@ class OpenStackNetworkingService(BaseNetworkingService):
         super(OpenStackNetworkingService, self).__init__(provider)
         self._network_service = OpenStackNetworkService(self.provider)
         self._subnet_service = OpenStackSubnetService(self.provider)
+        self._router_service = OpenStackRouterService(self.provider)
 
     @property
     def networks(self):
@@ -726,6 +728,10 @@ class OpenStackNetworkingService(BaseNetworkingService):
     def subnets(self):
         return self._subnet_service
 
+    @property
+    def routers(self):
+        return self._router_service
+
 
 class OpenStackNetworkService(BaseNetworkService):
 
@@ -852,3 +858,40 @@ class OpenStackSubnetService(BaseSubnetService):
         if subnet_id not in self.list():
             return True
         return False
+
+
+class OpenStackRouterService(BaseRouterService):
+
+    def __init__(self, provider):
+        super(OpenStackRouterService, self).__init__(provider)
+
+    def get(self, router_id):
+        router = (r for r in self if r.id == router_id)
+        return next(router, None)
+
+    def list(self, limit=None, marker=None):
+        routers = self.provider.neutron.list_routers().get('routers')
+        os_routers = [OpenStackRouter(self.provider, r) for r in routers]
+        return ClientPagedResultList(self.provider, os_routers, limit=limit,
+                                     marker=marker)
+
+    def create(self, network, name=None):
+        """
+        ``network`` is not used by OpenStack.
+
+        However, the API seems to indicate it is a (required) param?!
+        https://developer.openstack.org/api-ref/networking/v2/
+            ?expanded=delete-router-detail,create-router-detail#create-router
+        """
+        router = self.provider.neutron.create_router(
+            {'router': {'name': name}})
+        return OpenStackRouter(self.provider, router.get('router'))
+
+    def delete(self, router):
+        router_id = (router.id if isinstance(router, OpenStackRouter)
+                     else router)
+        self.provider.neutron.delete_router(router_id)
+        # Adhere to the interface docs
+        if router_id not in self.list():
+            return True
+        return False