Przeglądaj źródła

Add implementation for interacting with security groups (AWS only)

Enis Afgan 10 lat temu
rodzic
commit
7b7ca226c3

+ 7 - 2
cloudbridge/providers/aws/resources.py

@@ -236,8 +236,7 @@ class AWSInstance(BaseInstance):
         """
         Get the security group IDs associated with this instance.
         """
-        return [BaseSecurityGroup(group.id, group.name, group.description)
-                for group in self._ec2_instance.groups]
+        return self._ec2_instance.groups
 
     @property
     def key_pair_name(self):
@@ -435,6 +434,12 @@ class AWSKeyPair(BaseKeyPair):
         return self._key_pair.material
 
 
+class AWSSecurityGroup(BaseSecurityGroup):
+
+    def __init__(self, provider, security_group):
+        super(AWSSecurityGroup, self).__init__(provider, security_group)
+
+
 class AWSContainerObject(ContainerObject):
 
     def __init__(self, provider, key):

+ 77 - 0
cloudbridge/providers/aws/services.py

@@ -1,6 +1,7 @@
 """
 Services implemented by the AWS provider.
 """
+from boto.exception import EC2ResponseError
 
 from cloudbridge.providers.interfaces import BlockStoreService
 from cloudbridge.providers.interfaces import ComputeService
@@ -21,6 +22,7 @@ from .resources import AWSContainer
 from .resources import AWSInstance
 from .resources import AWSKeyPair
 from .resources import AWSMachineImage
+from .resources import AWSSecurityGroup
 from .resources import AWSSnapshot
 from .resources import AWSVolume
 
@@ -109,6 +111,81 @@ class AWSSecurityGroupService(SecurityGroupService):
     def __init__(self, provider):
         self.provider = provider
 
+    def list(self):
+        """
+        List all security groups associated with this account.
+
+        :rtype: ``list`` of :class:`.SecurityGroup`
+        :return:  list of SecurityGroup objects
+        """
+        security_groups = self.provider.ec2_conn.get_all_security_groups()
+        return [AWSSecurityGroup(self.provider, sg) for sg in security_groups]
+
+    def create(self, name, description):
+        """
+        Create a new SecurityGroup.
+
+        :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 or ``None`` if one was not created.
+        """
+        sg = self.provider.ec2_conn.create_security_group(name, description)
+        if sg:
+            return AWSSecurityGroup(self.provider, sg)
+        return None
+
+    def get(self, groupnames=None, group_ids=None):
+        """
+        Get a security group.
+
+        :type groupnames: list
+        :param groupnames: A list of the names of security groups to retrieve.
+                           If not provided, all security groups will be
+                           returned.
+
+        :type group_ids: list
+        :param group_ids: A list of IDs of security groups to retrieve.
+                          If not provided, all security groups will be
+                          returned.
+
+        :rtype: list of :class:`SecurityGroup`
+        :return: A list of SecurityGroup objects or an empty list if none found.
+        """
+        try:
+            security_groups = self.provider.ec2_conn.get_all_security_groups(
+                groupnames=groupnames, group_ids=group_ids)
+        except EC2ResponseError:
+            security_groups = []
+        return [AWSSecurityGroup(self.provider, sg) for sg in security_groups]
+
+    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 the security group does not exist, ``False``
+                  otherwise. Note that this implies that the group may not have
+                  been deleted by this method but instead has not existed in
+                  the first place.
+        """
+        try:
+            for sg in self.provider.ec2_conn.get_all_security_groups(group_ids=[group_id]):
+                try:
+                    sg.delete()
+                except EC2ResponseError:
+                    return False
+        except EC2ResponseError:
+            pass
+        return True
+
 
 class AWSBlockStoreService(BlockStoreService):
 

+ 12 - 7
cloudbridge/providers/base.py

@@ -208,10 +208,9 @@ class BaseKeyPair(KeyPair):
 
 class BaseSecurityGroup(SecurityGroup):
 
-    def __init__(self, group_id, name, description):
-        self._id = group_id
-        self._name = name
-        self._description = description
+    def __init__(self, provider, security_group):
+        self.provider = provider
+        self._security_group = security_group
 
     @property
     def id(self):
@@ -221,21 +220,27 @@ class BaseSecurityGroup(SecurityGroup):
         :rtype: str
         :return: Security group ID
         """
-        return self._id
+        return self._security_group.id
 
     @property
     def name(self):
         """
         Return the name of this security group.
         """
-        return self._name
+        return self._security_group.name
 
     @property
     def description(self):
         """
         Return the description of this security group.
         """
-        return self._description
+        return self._security_group.description
+
+    def delete(self):
+        """
+        Delete this security group.
+        """
+        return self._security_group.delete()
 
     def __repr__(self):
         return "<CBSecurityGroup: {0}>".format(self.name)

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

@@ -470,20 +470,27 @@ class SecurityGroupService(ProviderService):
         :param description: The description of the new security group.
 
         :rtype: ``object`` of :class:`.SecurityGroup`
-        :return:  A SecurityGroup instance
+        :return:  A SecurityGroup instance or ``None`` if one was not created.
         """
         raise NotImplementedError(
             'create not implemented by this provider')
 
-    def get(self, group_id):
+    def get(self, groupnames=None, group_ids=None):
         """
         Get a security group.
 
-        :type group_id: str
-        :param group_id: The security group to get by ID
+        :type groupnames: list
+        :param groupnames: A list of the names of security groups to retrieve.
+                           If not provided, all security groups will be
+                           returned.
+
+        :type group_ids: list
+        :param group_ids: A list of IDs of security groups to retrieve.
+                          If not provided, all security groups will be
+                          returned.
 
-        :rtype: :class:`SecurityGroup`
-        :return: If found, return SecurityGroup object. Else, return ``None``.
+        :rtype: list of :class:`SecurityGroup`
+        :return: A list of SecurityGroup objects or an empty list if none found.
         """
         raise NotImplementedError(
             'get not implemented by this provider')
@@ -496,7 +503,10 @@ class SecurityGroupService(ProviderService):
         :param group_id: The security group ID to be deleted.
 
         :rtype: ``bool``
-        :return:  ``True`` if successful, ``False`` otherwise
+        :return:  ``True`` if the security group does not exist, ``False``
+                  otherwise. Note that this implies that the group may not have
+                  been deleted by this method but instead has not existed in
+                  the first place.
         """
         raise NotImplementedError(
             'delete not implemented by this provider')

+ 4 - 5
test/test_provider_security_service.py

@@ -14,9 +14,8 @@ class ProviderSecurityServiceTestCase(ProviderTestBase):
         self.assertIsInstance(key_pairs[0], interfaces.KeyPair)
         self.assertIsNotNone(key_pairs[0].name)
 
-    def test_crud_security_groups(self):
-        # groups = self.provider.security.create_security_group()
-        groups = self.provider.security.list_security_groups()
+    def test_list_security_groups(self):
+        groups = self.provider.security.security_groups.list()
         # Assume there's always one keypair at least
-#         self.assertIsInstance(groups[0], interfaces.KeyPair)
-#         self.assertIsNotNone(key_pairs[0].name)
+        self.assertIsInstance(groups[0], interfaces.SecurityGroup)
+        self.assertIsNotNone(groups[0].name)