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

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

nuwan_ag 10 лет назад
Родитель
Сommit
e5ca43eb54

+ 2 - 2
README.md

@@ -10,6 +10,6 @@ from cloudbridge.util import Bunch
 config = Bunch(access_key='a_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 os
 from boto.ec2.regioninfo import RegionInfo
 
-from cloudbridge.util import Bunch
 from cloudbridge.providers.interfaces import CloudProvider
-from cloudbridge.providers.interfaces import SecurityManager
+from cloudbridge.providers.interfaces import SecurityService
 from cloudbridge.providers.interfaces import KeyPair
 
 
@@ -15,44 +15,31 @@ class EC2CloudProviderV1(CloudProvider):
 
     def __init__(self, config):
         self.config = config
-        self.a_key = config.access_key
-        self.s_key = config.secret_key
         self.cloud_type = 'ec2'
 
         # 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.region_name = config.get('region_name', 'us-east-1')
             self.region_endpoint = config.get('region_endpoint', 'ec2.us-east-1.amazonaws.com')
             self.ec2_port = config.get('ec2_port', '')
             self.ec2_conn_path = config.get('ec2_conn_path', '/')
         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.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.ObjectStore = EC2ObjectStore(self)
 
@@ -73,7 +60,7 @@ class EC2CloudProviderV1(CloudProvider):
         return ec2_conn
 
 
-class EC2SecurityManager(SecurityManager):
+class EC2SecurityService(SecurityService):
     def __init__(self, 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
         :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.
 
+        :rtype: ``object`` of :class:`.CloudProvider`
         :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
         :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
         """
         raise NotImplementedError(
-            '__init__ not implemented by this provider')
+            'has_service not implemented by this provider')
+
 
     def Compute(self):
         """
         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(
             'CloudProvider.Compute not implemented by this provider')
 
-    def Images(self):
+    def Image(self):
         """
         Provides access to all Image related services in this provider.
         (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(
             'CloudProvider.Images not implemented by this provider')
@@ -132,47 +75,47 @@ class CloudProvider():
         """
         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(
             'CloudProvider.Security not implemented by this provider')
 
-    def BlockStore(self):
+    def Volume(self):
         """
         Provides access to the volume/elastic block store services in this
         provider.
 
-        :rtype: ``object`` of :class:`.BlockStoreManager`
-        :return: a BlockStoreManager object
+        :rtype: ``object`` of :class:`.VolumeService`
+        :return: a VolumeService object
         """
         raise NotImplementedError(
-            'CloudProvider.BlockStore not implemented by this provider')
+            'CloudProvider.VolumeService not implemented by this provider')
 
     def ObjectStore(self):
         """
         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(
             'CloudProvider.ObjectStore not implemented by this provider')
 
 
-class ComputeManager():
+class ComputeService():
     """
     Base interface for compute service supported by a provider
     """
     def Provider(self):
         """
-        Returns the provider instance associated with this manager.
+        Returns the provider instance associated with this service.
 
         :rtype: ``object`` of :class:`.CloudProvider`
         :return: a Provider object
         """
         raise NotImplementedError(
-            'ComputeManager.Provider not implemented by this provider')
+            'ComputeService.Provider not implemented by this provider')
 
     def get_instance(self, id):
         """
@@ -235,19 +178,19 @@ class ComputeManager():
             '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):
         """
-        Returns the provider instance associated with this manager
+        Returns the provider instance associated with this Service
 
         :rtype: ``object`` of :class:`.CloudProvider`
         :return: a CloudProvider object
         """
         raise NotImplementedError(
-            'ComputeManager.Provider not implemented by this provider')
+            'VolumeService.Provider not implemented by this provider')
 
     def get_volume(self, id):
         """
@@ -300,19 +243,19 @@ class VolumeManager():
             '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):
         """
-        Returns the provider instance associated with this manager
+        Returns the provider instance associated with this service
 
         :rtype: ``object`` of :class:`.CloudProvider`
         :return:   a  provider instance
         """
         raise NotImplementedError(
-            'ComputeManager.Provider not implemented by this provider')
+            'ImageService.Provider not implemented by this provider')
 
     def get_image(self, id):
         """
@@ -354,19 +297,73 @@ class ImageManager():
             '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):
         """
-        Returns the provider instance associated with this manager
+        Returns the provider instance associated with this service
 
         :rtype: ``object`` of :class:`.CloudProvider`
         :return:   a  provider instance
         """
         raise NotImplementedError(
-            'ComputeManager.Provider not implemented by this provider')
+            'ComputeService.Provider not implemented by this provider')
 
     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