Explorar el Código

Changed interface definitions to be more consistent. Updated example.py

nuwan_ag hace 10 años
padre
commit
e5ca43eb54

+ 2 - 2
README.md

@@ -10,6 +10,6 @@ from cloudbridge.util import Bunch
 config = Bunch(access_key='a_key',
 config = Bunch(access_key='a_key',
                secret_key='s_key')
                secret_key='s_key')
 
 
-ec2 = CloudProviderFactory().get_interface_V1("ec2", config)
-print ec2.Security.list_key_pairs()
+provider = CloudProviderFactory().create_provider(ProviderList.EC2, config)
+print provider.Security.list_key_pairs()
 ```
 ```

+ 0 - 12
cloudbridge/example.py

@@ -1,12 +0,0 @@
-from cloudbridge.providers.interfaces import CloudProviderFactory
-from cloudbridge.providers.interfaces import CloudProvider
-
-
-ec2driver = CloudProviderFactory().get_interface_V1("EC2")
-provider = ec2driver(access_key="", secret_key="", region="", port="", connection_path="")
-instances = provider.Compute.list_instances()
-regions = provider.Compute.list_regions()
-images = provider.Images.list_images()
-volumes = provider.Compute.list_volumes()
-
-provider.Compute.launch_instance("my_instance", regions[0], images[0])

+ 16 - 29
cloudbridge/providers/ec2/__init__.py

@@ -3,11 +3,11 @@ Provider implementation based on boto library for EC2-compatible clouds.
 """
 """
 
 
 import boto
 import boto
+import os
 from boto.ec2.regioninfo import RegionInfo
 from boto.ec2.regioninfo import RegionInfo
 
 
-from cloudbridge.util import Bunch
 from cloudbridge.providers.interfaces import CloudProvider
 from cloudbridge.providers.interfaces import CloudProvider
-from cloudbridge.providers.interfaces import SecurityManager
+from cloudbridge.providers.interfaces import SecurityService
 from cloudbridge.providers.interfaces import KeyPair
 from cloudbridge.providers.interfaces import KeyPair
 
 
 
 
@@ -15,44 +15,31 @@ class EC2CloudProviderV1(CloudProvider):
 
 
     def __init__(self, config):
     def __init__(self, config):
         self.config = config
         self.config = config
-        self.a_key = config.access_key
-        self.s_key = config.secret_key
         self.cloud_type = 'ec2'
         self.cloud_type = 'ec2'
 
 
         # Initialize optional fields
         # Initialize optional fields
-        if type(config) is Bunch:
+        if isinstance(config, dict):
+            self.a_key = config.get('access_key', os.environ.get('EC2_ACCESS_KEY', None))
+            self.s_key = config.get('secret_key', os.environ.get('EC2_SECRET_KEY', None))
             self.is_secure = config.get('is_secure', True)
             self.is_secure = config.get('is_secure', True)
             self.region_name = config.get('region_name', 'us-east-1')
             self.region_name = config.get('region_name', 'us-east-1')
             self.region_endpoint = config.get('region_endpoint', 'ec2.us-east-1.amazonaws.com')
             self.region_endpoint = config.get('region_endpoint', 'ec2.us-east-1.amazonaws.com')
             self.ec2_port = config.get('ec2_port', '')
             self.ec2_port = config.get('ec2_port', '')
             self.ec2_conn_path = config.get('ec2_conn_path', '/')
             self.ec2_conn_path = config.get('ec2_conn_path', '/')
         else:
         else:
-            if hasattr(config.is_secure):
-                self.is_secure = config.is_secure
-            else:
-                self.is_secure = True
-            if hasattr(config.region_name):
-                self.region_name = config.region_name
-            else:
-                self.region_name = 'us-east-1'
-            if hasattr(config.region_endpoint):
-                self.region_endpoint = config.region_endpoint
-            else:
-                self.region_endpoint = 'ec2.us-east-1.amazonaws.com'
-            if hasattr(config.ec2_port):
-                self.ec2_port = config.ec2_port
-            else:
-                self.ec2_port = ''
-            if hasattr(config.ec2_conn_path):
-                self.ec2_conn_path = config.ec2_conn_path
-            else:
-                self.ec2_conn_path = "/"
+            self.a_key = config.access_key if hasattr(config, 'access_key') and config.access_key else os.environ.get('EC2_ACCESS_KEY', None)
+            self.s_key = config.secret_key if hasattr(config, 'secret_key') and config.secret_key else os.environ.get('EC2_ACCESS_KEY', None)
+            self.is_secure = config.is_secure if hasattr(config, 'is_secure') else True
+            self.region_name = config.region_name if hasattr(config, 'region_name') else 'us-east-1'
+            self.region_endpoint = config.region_endpoint if hasattr(config, 'region_endpoint') else 'ec2.us-east-1.amazonaws.com'
+            self.ec2_port = config.ec2_port if hasattr(config, 'ec2_port') else ''
+            self.ec2_conn_path = config.ec2_conn_path if hasattr(config, 'ec2_conn_path') else "/"
 
 
         self.ec2_conn = self._connect_ec2()
         self.ec2_conn = self._connect_ec2()
 
 
-        # self.Compute = EC2ComputeManager(self)
-        # self.Images = EC2ImageManager(self)
-        self.Security = EC2SecurityManager(self)
+        # self.Compute = EC2ComputeService(self)
+        # self.Images = EC2ImageService(self)
+        self.Security = EC2SecurityService(self)
         # self.BlockStore = EC2BlockStore(self)
         # self.BlockStore = EC2BlockStore(self)
         # self.ObjectStore = EC2ObjectStore(self)
         # self.ObjectStore = EC2ObjectStore(self)
 
 
@@ -73,7 +60,7 @@ class EC2CloudProviderV1(CloudProvider):
         return ec2_conn
         return ec2_conn
 
 
 
 
-class EC2SecurityManager(SecurityManager):
+class EC2SecurityService(SecurityService):
     def __init__(self, provider):
     def __init__(self, provider):
         self.provider = provider
         self.provider = provider
 
 

+ 91 - 0
cloudbridge/providers/factory.py

@@ -0,0 +1,91 @@
+import importlib
+
+class ProviderList():
+    EC2 = 'ec2'
+    OPENSTACK = 'openstack'
+    AZURE = 'azure'
+
+class CloudProviderFactory():
+    """
+    Get info and handle on the available cloud provider implementations.
+    """
+
+    def list_providers(self):
+        """
+        Get a list of available providers.
+
+        (This function could eventually be implemented as a registry file
+        containing all available implementations, or alternatively, using
+        automatic discovery.)
+
+        :rtype: list
+        :return: A list of available providers and their interface versions.
+        """
+        return [{"name": "openstack",
+                 "implementation":
+                 [{"class": "cloudbridge.providers.openstack.OpenstackCloudProviderV1",
+                   "version": 1}]},
+                {"name": "ec2",
+                 "implementation":
+                 [{"class": "cloudbridge.providers.ec2.EC2CloudProviderV1",
+                   "version": 1}]}]
+
+    def find_provider_impl(self, name, version=None):
+        """
+        Finds a provider implementation class given its name.
+
+        :type name: str
+        :param name: A name of the provider whose implementation to look for.
+
+        :type version: inst
+        :param version: A specific version of the provider to look for. If the
+                        version is not specified, return the latest available
+                        version.
+
+        :rtype: ``None`` or str
+        :return: If found, return a module (including class name) of the
+                 provider or ``None`` if the provider was not found.
+        """
+        for provider in self.list_providers():
+            if provider['name'] == name:
+                if version:
+                    match = [item for item in provider["implementation"]
+                             if item["version"] == version]
+                    if match:
+                        return match[0]["class"]
+                    else:
+                        return None
+                else:
+                    # Return latest available version
+                    return sorted((item for item in provider["implementation"]),
+                                  key=lambda x: x["version"])[-1]["class"]
+        return None
+
+    def create_provider(self, name, config, version=None):
+        """
+        Searches all available providers for a CloudProvider interface with the
+        given name, and instantiates it based on the given config dictionary,
+        where the config dictionary is a dictionary understood by that
+        cloud provider.
+
+        :type name: str
+        :param name: Cloud provider name: one of ``ec2``, ``openstack``.
+
+        :type config: an object with required fields
+        :param config: This can be a Bunch or any other object whose fields can
+                       be accessed using dot notation. See specific provider
+                       implementation for the required fields.
+
+        :return:  a concrete provider instance
+        :rtype: ``object`` of :class:`.CloudProviderV1`
+        """
+        provider = self.find_provider_impl(name, version=version)
+        if provider is None:
+            raise NotImplementedError(
+                'A provider by name {0} implementing interface v1 could not be '
+                'found'.format(name))
+        else:
+            module_name, class_name = provider.rsplit(".", 1)
+            provider_class = getattr(importlib.import_module(module_name),
+                                     class_name)
+            return provider_class(config)

+ 108 - 111
cloudbridge/providers/interfaces.py

@@ -1,100 +1,42 @@
-import importlib
+class CloudProviderServiceType():
+    """
+    Defines possible service types that
+    are offered by providers. Providers can implement the
+    has_service method and clients can check for the availability
+    of a service with
+    if (provider.has_service(CloudProviderServiceTypes.OBJECTSTORE))
+        provider.ObjectStore.
+    """
+    COMPUTE = 'compute'
+    IMAGE = 'image'
+    SECURITY =  'security'
+    VOLUME =  'volume'
+    OBJECTSTORE =  'objectstore'
 
 
 
 
-class CloudProviderFactory():
+class CloudProvider():
     """
     """
-    Get info and handle on the available cloud provider implementations.
+    Base interface for a cloud provider
     """
     """
-
-    def get_providers(self):
+    def __init__(self, config):
         """
         """
-        Get a list of available providers.
-
-        (This function could eventually be implemented as a registry file
-        containing all available implementations, or alternatively, using
-        automatic discovery.)
-
-        :rtype: list
-        :return: A list of available providers and their interface versions.
-        """
-        return [{"name": "openstack",
-                 "implementation":
-                 [{"class": "cloudbridge.providers.openstack.OpenstackCloudProviderV1",
-                   "version": 1}]},
-                {"name": "ec2",
-                 "implementation":
-                 [{"class": "cloudbridge.providers.ec2.EC2CloudProviderV1",
-                   "version": 1}]}]
-
-    def find_provider_impl(self, name, version=None):
-        """
-        Finds a provider implementation class given its name.
-
-        :type name: str
-        :param name: A name of the provider whose implementation to look for.
-
-        :type version: inst
-        :param version: A specific version of the provider to look for. If the
-                        version is not specified, return the latest available
-                        version.
-
-        :rtype: ``None`` or str
-        :return: If found, return a module (including class name) of the
-                 provider or ``None`` if the provider was not found.
-        """
-        for provider in self.get_providers():
-            if provider["name"] == name:
-                if version:
-                    match = [item for item in provider["implementation"]
-                             if item["version"] == version]
-                    if match:
-                        return match[0]["class"]
-                    else:
-                        return None
-                else:
-                    # Return latest available version
-                    return sorted((item for item in provider["implementation"]),
-                                  key=lambda x: x["version"])[-1]
-        return None
-
-    def get_interface_V1(self, name, config):
-        """
-        Searches all available providers for a CloudProvider interface with the
-        given name, and instantiates it based on the given config dictionary,
-        where the config dictionary is a dictionary understood by that
-        cloud provider.
-
-        :type name: str
-        :param name: Cloud provider name: one of ``ec2``, ``openstack``.
+        Create a new provider implementation given a dictionary of configuration
+        attributes.
 
 
         :type config: an object with required fields
         :type config: an object with required fields
         :param config: This can be a Bunch or any other object whose fields can
         :param config: This can be a Bunch or any other object whose fields can
                        be accessed using dot notation. See specific provider
                        be accessed using dot notation. See specific provider
                        implementation for the required fields.
                        implementation for the required fields.
 
 
+        :rtype: ``object`` of :class:`.CloudProvider`
         :return:  a concrete provider instance
         :return:  a concrete provider instance
-        :rtype: ``object`` of :class:`.CloudProviderV1`
         """
         """
-        provider = self.find_provider_impl(name, version=1)
-        if provider is None:
-            raise NotImplementedError(
-                'A provider by name {0} implementing interface v1 could not be '
-                'found'.format(name))
-        else:
-            module_name, class_name = provider.rsplit(".", 1)
-            provider_class = getattr(importlib.import_module(module_name),
-                                     class_name)
-            return provider_class(config)
-
+        raise NotImplementedError(
+            '__init__ not implemented by this provider')
 
 
-class CloudProvider():
-    """
-    Base interface for a cloud provider
-    """
-    def __init__(self, config):
+    def has_service(self, service):
         """
         """
-        Create a new provider implementation given a dictionary of configuration
-        attributes.
+        Checks whether this provider supports a given service"
 
 
         :type config: an object with required fields
         :type config: an object with required fields
         :param config: This can be a Bunch or any other object whose fields can
         :param config: This can be a Bunch or any other object whose fields can
@@ -105,25 +47,26 @@ class CloudProvider():
         :return:  a concrete provider instance
         :return:  a concrete provider instance
         """
         """
         raise NotImplementedError(
         raise NotImplementedError(
-            '__init__ not implemented by this provider')
+            'has_service not implemented by this provider')
+
 
 
     def Compute(self):
     def Compute(self):
         """
         """
         Provides access to all compute related services in this provider.
         Provides access to all compute related services in this provider.
 
 
-        :rtype: ``object`` of :class:`.ComputeManager`
-        :return:  a ComputeManager object
+        :rtype: ``object`` of :class:`.ComputeService`
+        :return:  a ComputeService object
         """
         """
         raise NotImplementedError(
         raise NotImplementedError(
             'CloudProvider.Compute not implemented by this provider')
             'CloudProvider.Compute not implemented by this provider')
 
 
-    def Images(self):
+    def Image(self):
         """
         """
         Provides access to all Image related services in this provider.
         Provides access to all Image related services in this provider.
         (e.g. Glance in Openstack)
         (e.g. Glance in Openstack)
 
 
-        :rtype: ``object`` of :class:`.ImageManager`
-        :return: an ImageManager object
+        :rtype: ``object`` of :class:`.ImageService`
+        :return: an ImageService object
         """
         """
         raise NotImplementedError(
         raise NotImplementedError(
             'CloudProvider.Images not implemented by this provider')
             'CloudProvider.Images not implemented by this provider')
@@ -132,47 +75,47 @@ class CloudProvider():
         """
         """
         Provides access to keypair management and firewall control
         Provides access to keypair management and firewall control
 
 
-        :rtype: ``object`` of :class:`.SecurityManager`
-        :return: a SecurityManager object
+        :rtype: ``object`` of :class:`.SecurityService`
+        :return: a SecurityService object
         """
         """
         raise NotImplementedError(
         raise NotImplementedError(
             'CloudProvider.Security not implemented by this provider')
             'CloudProvider.Security not implemented by this provider')
 
 
-    def BlockStore(self):
+    def Volume(self):
         """
         """
         Provides access to the volume/elastic block store services in this
         Provides access to the volume/elastic block store services in this
         provider.
         provider.
 
 
-        :rtype: ``object`` of :class:`.BlockStoreManager`
-        :return: a BlockStoreManager object
+        :rtype: ``object`` of :class:`.VolumeService`
+        :return: a VolumeService object
         """
         """
         raise NotImplementedError(
         raise NotImplementedError(
-            'CloudProvider.BlockStore not implemented by this provider')
+            'CloudProvider.VolumeService not implemented by this provider')
 
 
     def ObjectStore(self):
     def ObjectStore(self):
         """
         """
         Provides access to object storage services in this provider.
         Provides access to object storage services in this provider.
 
 
-        :rtype: ``object`` of :class:`.ObjectStoreManager`
-        :return: an ObjectStoreManager object
+        :rtype: ``object`` of :class:`.ObjectStoreService`
+        :return: an ObjectStoreService object
         """
         """
         raise NotImplementedError(
         raise NotImplementedError(
             'CloudProvider.ObjectStore not implemented by this provider')
             'CloudProvider.ObjectStore not implemented by this provider')
 
 
 
 
-class ComputeManager():
+class ComputeService():
     """
     """
     Base interface for compute service supported by a provider
     Base interface for compute service supported by a provider
     """
     """
     def Provider(self):
     def Provider(self):
         """
         """
-        Returns the provider instance associated with this manager.
+        Returns the provider instance associated with this service.
 
 
         :rtype: ``object`` of :class:`.CloudProvider`
         :rtype: ``object`` of :class:`.CloudProvider`
         :return: a Provider object
         :return: a Provider object
         """
         """
         raise NotImplementedError(
         raise NotImplementedError(
-            'ComputeManager.Provider not implemented by this provider')
+            'ComputeService.Provider not implemented by this provider')
 
 
     def get_instance(self, id):
     def get_instance(self, id):
         """
         """
@@ -235,19 +178,19 @@ class ComputeManager():
             'create_instance not implemented by this provider')
             'create_instance not implemented by this provider')
 
 
 
 
-class VolumeManager():
+class VolumeService():
     """
     """
-    Base interface for a Volume Manager
+    Base interface for a Volume Service
     """
     """
     def Provider(self):
     def Provider(self):
         """
         """
-        Returns the provider instance associated with this manager
+        Returns the provider instance associated with this Service
 
 
         :rtype: ``object`` of :class:`.CloudProvider`
         :rtype: ``object`` of :class:`.CloudProvider`
         :return: a CloudProvider object
         :return: a CloudProvider object
         """
         """
         raise NotImplementedError(
         raise NotImplementedError(
-            'ComputeManager.Provider not implemented by this provider')
+            'VolumeService.Provider not implemented by this provider')
 
 
     def get_volume(self, id):
     def get_volume(self, id):
         """
         """
@@ -300,19 +243,19 @@ class VolumeManager():
             'create_volume not implemented by this provider')
             'create_volume not implemented by this provider')
 
 
 
 
-class ImageManager():
+class ImageService():
     """
     """
-    Base interface for an Image Manager
+    Base interface for an Image Service
     """
     """
     def Provider(self):
     def Provider(self):
         """
         """
-        Returns the provider instance associated with this manager
+        Returns the provider instance associated with this service
 
 
         :rtype: ``object`` of :class:`.CloudProvider`
         :rtype: ``object`` of :class:`.CloudProvider`
         :return:   a  provider instance
         :return:   a  provider instance
         """
         """
         raise NotImplementedError(
         raise NotImplementedError(
-            'ComputeManager.Provider not implemented by this provider')
+            'ImageService.Provider not implemented by this provider')
 
 
     def get_image(self, id):
     def get_image(self, id):
         """
         """
@@ -354,19 +297,73 @@ class ImageManager():
             'create_image not implemented by this provider')
             'create_image not implemented by this provider')
 
 
 
 
-class SecurityManager():
+class ObjectStoreService():
+    """
+    Base interface for an Object Storage Service
+    """
+    def Provider(self):
+        """
+        Returns the provider instance associated with this service
+
+        :rtype: ``object`` of :class:`.CloudProvider`
+        :return:   a  provider instance
+        """
+        raise NotImplementedError(
+            'ObjectStoreService.Provider not implemented by this provider')
+
+    def get_container(self, id):
+        """
+        Returns a container given its id
+
+        :rtype: ``object`` of :class:`.Container`
+        :return:  a Container instance
+        """
+        raise NotImplementedError(
+            'get_container implemented by this provider')
+
+    def find_container(self, name):
+        """
+        Searches for a container by a given list of attributes
+
+        :rtype: ``object`` of :class:`.Container`
+        :return:  a Container instance
+        """
+        raise NotImplementedError(
+            'find_container not implemented by this provider')
+
+    def list_containers(self):
+        """
+        List all containers.
+
+        :rtype: ``list`` of :class:`.Container`
+        :return:  list of container objects
+        """
+        raise NotImplementedError(
+            'list_containers not implemented by this provider')
+
+    def create_container(self):
+        """
+        Create a new container.
+        :return:  a Container object
+        :rtype: ``object`` of :class:`.Container`
+        """
+        raise NotImplementedError(
+            'create_container not implemented by this provider')
+
+
+class SecurityService():
     """
     """
-    Base interface for an Image Manager
+    Base interface for an Image Service
     """
     """
     def Provider(self):
     def Provider(self):
         """
         """
-        Returns the provider instance associated with this manager
+        Returns the provider instance associated with this service
 
 
         :rtype: ``object`` of :class:`.CloudProvider`
         :rtype: ``object`` of :class:`.CloudProvider`
         :return:   a  provider instance
         :return:   a  provider instance
         """
         """
         raise NotImplementedError(
         raise NotImplementedError(
-            'ComputeManager.Provider not implemented by this provider')
+            'ComputeService.Provider not implemented by this provider')
 
 
     def list_key_pairs(self):
     def list_key_pairs(self):
         """
         """

+ 0 - 26
cloudbridge/util/__init__.py

@@ -1,26 +0,0 @@
-"""
-A utility class with convenience classes.
-"""
-
-
-class Bunch(object):
-    """
-    A convenience class to allow dict keys to be represented as object fields.
-
-    The end result is that this allows a dict to be to be represented the same
-    as a database class, thus the two become interchangeable as a data source.
-    """
-    def __init__(self, **kwargs):
-        self.__dict__.update(kwargs)
-
-    def __repr__(self):
-        """
-        Return the contents of the dict in a printable representation
-        """
-        return str(self.__dict__)
-
-    def get(self, key, default=None):
-        """
-        Returns a value for the given key, if found or `'default` otherwise.
-        """
-        return self.__dict__.get(key, default)

+ 9 - 0
example.py

@@ -0,0 +1,9 @@
+from cloudbridge.providers.factory import CloudProviderFactory
+from cloudbridge.providers.factory import ProviderList
+from bunch import Bunch
+
+config = Bunch(access_key='AKIAJLFOW2JCQVPBVFAA',
+               secret_key='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')
+
+provider = CloudProviderFactory().create_provider(ProviderList.EC2, config)
+print provider.Security.list_key_pairs()

+ 2 - 0
requirements.txt

@@ -0,0 +1,2 @@
+bunch==1.01
+nose