Przeglądaj źródła

(WIP) Adding security-based resources. In the process, added SecurityGroupService and KeyPairService. ATM, OpenStack implementation is still incomplete and the AWS implementation is out of sync with the new interface. Missing tests

Enis Afgan 10 lat temu
rodzic
commit
a976bbd179

+ 1 - 1
cloudbridge/providers/aws/resources.py

@@ -233,7 +233,7 @@ class AWSInstance(BaseInstance):
         """
         Get the security group IDs associated with this instance.
         """
-        return [BaseSecurityGroup(group.name)
+        return [BaseSecurityGroup(group.id, group.name, group.description)
                 for group in self._ec2_instance.groups]
 
     @property

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

@@ -45,7 +45,8 @@ class AWSSecurityService(SecurityService):
         :return:  list of SecurityGroup objects
         """
         groups = self.provider.ec2_conn.get_all_security_groups()
-        return [BaseSecurityGroup(group.name) for group in groups]
+        return [BaseSecurityGroup(group.id, group.name, group.description)
+                for group in groups]
 
 
 class AWSBlockStoreService(BlockStoreService):

+ 21 - 2
cloudbridge/providers/base.py

@@ -204,15 +204,34 @@ class BaseKeyPair(KeyPair):
 
 class BaseSecurityGroup(SecurityGroup):
 
-    def __init__(self, name):
+    def __init__(self, group_id, name, description):
+        self._id = group_id
         self._name = name
+        self._description = description
+
+    @property
+    def id(self):
+        """
+        Get the ID of this security group.
+
+        :rtype: str
+        :return: Security group ID
+        """
+        return self._id
 
     @property
     def name(self):
         """
-        Return the name of this key pair.
+        Return the name of this security group.
         """
         return self._name
 
+    @property
+    def description(self):
+        """
+        Return the description of this security group.
+        """
+        return self._description
+
     def __repr__(self):
         return "<CBSecurityGroup: {0}>".format(self.name)

+ 2 - 0
cloudbridge/providers/interfaces/__init__.py

@@ -22,8 +22,10 @@ from .services import BlockStoreService
 from .services import ComputeService
 from .services import ImageService
 from .services import InstanceTypesService
+from .services import KeyPairService
 from .services import ObjectStoreService
 from .services import ProviderService
+from .services import SecurityGroupService
 from .services import SecurityService
 from .services import SnapshotService
 from .services import VolumeService

+ 28 - 9
cloudbridge/providers/interfaces/resources.py

@@ -539,6 +539,16 @@ class KeyPair(object):
         raise NotImplementedError(
             'material not implemented by this provider')
 
+    def delete(self):
+        """
+        Delete this key pair.
+
+        :rtype: bool
+        :return: ``True`` is successful.
+        """
+        raise NotImplementedError(
+            'delete not implemented by this provider')
+
 
 class Region(object):
 
@@ -628,25 +638,34 @@ class SecurityGroup(object):
         raise NotImplementedError(
             'name not implemented by this provider')
 
-    def create(self, name, description):
+    @property
+    def description(self):
         """
-        Create a new security group under the current account.
+        Return the description of this security group.
 
-        :type name: str
-        :param name: The name of the new security group.
+        :rtype: str
+        :return: A description of this security group.
+        """
+        raise NotImplementedError(
+            'description not implemented by this provider')
 
-        :type description: str
-        :param description: The description of the new security group.
+    @property
+    def id(self):
+        """
+        Get the ID of this security group.
 
-        :rtype: ``object`` of :class:`.SecurityGroup`
-        :return: a SecurityGroup object
+        :rtype: str
+        :return: Security group ID
         """
         raise NotImplementedError(
-            'create not implemented by this provider')
+            'id not implemented by this provider')
 
     def delete(self):
         """
         Delete this security group.
+
+        :rtype: bool
+        :return: ``True`` is successful.
         """
         raise NotImplementedError(
             'delete not implemented by this provider')

+ 85 - 17
cloudbridge/providers/interfaces/services.py

@@ -259,11 +259,10 @@ class BlockStoreService(ProviderService):
     @property
     def volumes(self):
         """
-        Provides access to the volume and snapshot services in this
-        provider.
+        Provides access to the volumes (i.e., block storage) for this provider.
 
-        :rtype: ``object`` of :class:`.BlockStoreService`
-        :return: a BlockStoreService object
+        :rtype: ``object`` of :class:`.VolumeService`
+        :return: a VolumeService object
         """
         raise NotImplementedError(
             'CloudProvider.block_store not implemented by this provider')
@@ -271,10 +270,10 @@ class BlockStoreService(ProviderService):
     @property
     def snapshots(self):
         """
-        Provides access to object storage services in this provider.
+        Provides access to volume snapshots for this provider.
 
-        :rtype: ``object`` of :class:`.ObjectStoreService`
-        :return: an ObjectStoreService object
+        :rtype: ``object`` of :class:`.SnapshotService`
+        :return: an SnapshotService object
         """
         raise NotImplementedError(
             'CloudProvider.object_store not implemented by this provider')
@@ -368,10 +367,37 @@ class ObjectStoreService(ProviderService):
 class SecurityService(ProviderService):
 
     """
-    Base interface for an Image Service
+    Base interface for a Security Service.
     """
 
-    def list_key_pairs(self):
+    @property
+    def key_pairs(self):
+        """
+        Provides access to key pairs for this provider.
+
+        :rtype: ``object`` of :class:`.KeyPairService`
+        :return: a KeyPairService object
+        """
+        return self._key_pairs
+
+    @property
+    def security_groups(self):
+        """
+        Provides access to security groups for this provider.
+
+        :rtype: ``object`` of :class:`.SecurityGroupService`
+        :return: a SecurityGroupService object
+        """
+        return self._security_groups
+
+
+class KeyPairService(ProviderService):
+
+    """
+    Base interface for key pairs.
+    """
+
+    def list(self):
         """
         List all key pairs associated with this account.
 
@@ -381,7 +407,7 @@ class SecurityService(ProviderService):
         raise NotImplementedError(
             'list_key_pairs not implemented by this provider')
 
-    def create_key_pair(self):
+    def create(self):
         """
         Create a new keypair.
 
@@ -391,7 +417,27 @@ class SecurityService(ProviderService):
         raise NotImplementedError(
             'create_key_pair not implemented by this provider')
 
-    def list_security_groups(self):
+    def delete(self, key_name):
+        """
+        Delete an existing SecurityGroup.
+
+        :type key_name: str
+        :param key_name: The name of the key pair to be deleted.
+
+        :rtype: ``bool``
+        :return:  ``True`` if successful, ``False`` otherwise
+        """
+        raise NotImplementedError(
+            'delete not implemented by this provider')
+
+
+class SecurityGroupService(ProviderService):
+
+    """
+    Base interface for security groups.
+    """
+
+    def list(self):
         """
         List all security groups associated with this account.
 
@@ -399,27 +445,49 @@ class SecurityService(ProviderService):
         :return:  list of SecurityGroup objects
         """
         raise NotImplementedError(
-            'list_security_groups not implemented by this provider')
+            'list not implemented by this provider')
 
-    def create_security_group(self):
+    def create(self, name, description):
         """
         Create a new SecurityGroup.
 
-        :rtype: ``object`` of :class:`.KeyPair`
+        :type name: str
+        :param name: The name of the new security group.
+
+        :type description: str
+        :param description: The description of the new security group.
+
+        :rtype: ``object`` of :class:`.SecurityGroup`
         :return:  A SecurityGroup instance
         """
         raise NotImplementedError(
-            'create_security_group not implemented by this provider')
+            'create not implemented by this provider')
+
+    def get(self, group_id):
+        """
+        Get a security group.
+
+        :type group_id: str
+        :param group_id: The security group to get by ID
+
+        :rtype: :class:`SecurityGroup`
+        :return: If found, return SecurityGroup object. Else, return ``None``.
+        """
+        raise NotImplementedError(
+            'get not implemented by this provider')
 
-    def delete_security_group(self):
+    def delete(self, group_id):
         """
         Delete an existing SecurityGroup.
 
+        :type group_id: str
+        :param group_id: The security group ID to be deleted.
+
         :rtype: ``bool``
         :return:  ``True`` if successful, ``False`` otherwise
         """
         raise NotImplementedError(
-            'delete_security_group not implemented by this provider')
+            'delete not implemented by this provider')
 
 
 class InstanceTypesService(object):

+ 1 - 1
cloudbridge/providers/openstack/resources.py

@@ -251,7 +251,7 @@ class OpenStackInstance(BaseInstance):
         """
         Get the security group IDs associated with this instance.
         """
-        return [BaseSecurityGroup(group.name)
+        return [BaseSecurityGroup(group.id, group.name, group.description)
                 for group in self._os_instance.security_groups]
 
     @property

+ 76 - 3
cloudbridge/providers/openstack/services.py

@@ -12,9 +12,11 @@ from cloudbridge.providers.interfaces import ImageService
 from cloudbridge.providers.interfaces import InstanceType
 from cloudbridge.providers.interfaces import InstanceTypesService
 from cloudbridge.providers.interfaces import KeyPair
+from cloudbridge.providers.interfaces import KeyPairService
 from cloudbridge.providers.interfaces import MachineImage
 from cloudbridge.providers.interfaces import PlacementZone
 from cloudbridge.providers.interfaces import SecurityGroup
+from cloudbridge.providers.interfaces import SecurityGroupService
 from cloudbridge.providers.interfaces import SecurityService
 from cloudbridge.providers.interfaces import SnapshotService
 from cloudbridge.providers.interfaces import VolumeService
@@ -23,6 +25,7 @@ from .resources import OpenStackInstance
 from .resources import OpenStackInstanceType
 from .resources import OpenStackMachineImage
 from .resources import OpenStackRegion
+# from .resources import OpenStackSecurityGroup
 from .resources import OpenStackSnapshot
 from .resources import OpenStackVolume
 
@@ -32,7 +35,37 @@ class OpenStackSecurityService(SecurityService):
     def __init__(self, provider):
         self.provider = provider
 
-    def list_key_pairs(self):
+        # Initialize provider services
+        self._key_pairs = OpenStackKeyPairService(provider)
+        self._security_groups = OpenStackSecurityGroupService(provider)
+
+    @property
+    def key_pairs(self):
+        """
+        Provides access to key pairs for this provider.
+
+        :rtype: ``object`` of :class:`.KeyPairService`
+        :return: a KeyPairService object
+        """
+        return self._key_pairs
+
+    @property
+    def security_groups(self):
+        """
+        Provides access to security groups for this provider.
+
+        :rtype: ``object`` of :class:`.SecurityGroupService`
+        :return: a SecurityGroupService object
+        """
+        return self._security_groups
+
+
+class OpenStackKeyPairService(KeyPairService):
+
+    def __init__(self, provider):
+        self.provider = provider
+
+    def list(self):
         """
         List all key pairs associated with this account.
 
@@ -42,7 +75,13 @@ class OpenStackSecurityService(SecurityService):
         key_pairs = self.provider.nova.keypairs.list()
         return [BaseKeyPair(kp.id) for kp in key_pairs]
 
-    def list_security_groups(self):
+
+class OpenStackSecurityGroupService(SecurityGroupService):
+
+    def __init__(self, provider):
+        self.provider = provider
+
+    def list(self):
         """
         List all security groups associated with this account.
 
@@ -50,7 +89,41 @@ class OpenStackSecurityService(SecurityService):
         :return:  list of SecurityGroup objects
         """
         groups = self.provider.nova.security_groups.list()
-        return [BaseSecurityGroup(group.name) for group in groups]
+        return [BaseSecurityGroup(group.id, group.name, group.description)
+                for group in groups]
+
+    def create(self, name, description):
+        """
+        Create a new security group under the current account.
+
+        :type name: str
+        :param name: The name of the new security group.
+
+        :type description: str
+        :param description: The description of the new security group.
+
+        :rtype: ``object`` of :class:`.SecurityGroup`
+        :return: a SecurityGroup object
+        """
+        sg = self.provider.nova.security_groups.create(name, description)
+        if sg:
+            return BaseSecurityGroup(sg.id, name, description)
+        return None
+
+    def get(self, group_id):
+        """
+        Get a security group.
+
+        :type group_id: str
+        :param group_id: The security group to get by ID
+
+        :rtype: :class:`SecurityGroup`
+        :return: If found, return SecurityGroup object. Else, return ``None``.
+        """
+        sg = self.provider.nova.security_groups.get(group_id)
+        if sg:
+            return BaseSecurityGroup(sg.id, sg.name, sg.description)
+        return None
 
 
 class OpenStackImageService(ImageService):