Explorar el Código

Added openstack object store implementation

nuwan_ag hace 10 años
padre
commit
6a602f4380

+ 24 - 7
cloudbridge/providers/openstack/impl.py

@@ -10,12 +10,14 @@ from keystoneclient import client as keystone_client
 from keystoneclient import session
 from keystoneclient import session
 from keystoneclient.auth.identity import Password
 from keystoneclient.auth.identity import Password
 from novaclient import client as nova_client
 from novaclient import client as nova_client
+from swiftclient import client as swift_client
 
 
 from cloudbridge.providers.base import BaseCloudProvider
 from cloudbridge.providers.base import BaseCloudProvider
 
 
 from .services import OpenStackBlockStoreService
 from .services import OpenStackBlockStoreService
 from .services import OpenStackComputeService
 from .services import OpenStackComputeService
 from .services import OpenStackImageService
 from .services import OpenStackImageService
+from .services import OpenStackObjectStoreService
 from .services import OpenStackSecurityService
 from .services import OpenStackSecurityService
 
 
 
 
@@ -24,8 +26,6 @@ class OpenStackCloudProviderV1(BaseCloudProvider):
     def __init__(self, config):
     def __init__(self, config):
         super(OpenStackCloudProviderV1, self).__init__(config)
         super(OpenStackCloudProviderV1, self).__init__(config)
 
 
-        self.api_version = self._get_config_value(
-            'api_version', os.environ.get('OS_COMPUTE_API_VERSION', 2))
         self.username = self._get_config_value(
         self.username = self._get_config_value(
             'username', os.environ.get('OS_USERNAME', None))
             'username', os.environ.get('OS_USERNAME', None))
         self.password = self._get_config_value(
         self.password = self._get_config_value(
@@ -38,12 +38,13 @@ class OpenStackCloudProviderV1(BaseCloudProvider):
         self.nova = self._connect_nova()
         self.nova = self._connect_nova()
         self.keystone = self._connect_keystone()
         self.keystone = self._connect_keystone()
         self.cinder = self._connect_cinder()
         self.cinder = self._connect_cinder()
+        self.swift = self._connect_swift()
 
 
         self._compute = OpenStackComputeService(self)
         self._compute = OpenStackComputeService(self)
         self._images = OpenStackImageService(self)
         self._images = OpenStackImageService(self)
         self._security = OpenStackSecurityService(self)
         self._security = OpenStackSecurityService(self)
         self._block_store = OpenStackBlockStoreService(self)
         self._block_store = OpenStackBlockStoreService(self)
-        self._object_store = None  # OpenStackObjectStore(self)
+        self._object_store = OpenStackObjectStoreService(self)
 
 
     @property
     @property
     def compute(self):
     def compute(self):
@@ -69,9 +70,13 @@ class OpenStackCloudProviderV1(BaseCloudProvider):
         """
         """
         Get an openstack nova client object for the given cloud.
         Get an openstack nova client object for the given cloud.
         """
         """
+        api_version = self._get_config_value(
+            'os_compute_api_version',
+            os.environ.get('OS_COMPUTE_API_VERSION', 2))
+
         return nova_client.Client(
         return nova_client.Client(
-            self.api_version, self.username, self.password, self.tenant_name,
-            self.auth_url)
+            api_version, username=self.username, api_key=self.password,
+            project_id=self.tenant_name, auth_url=self.auth_url)
 
 
     def _connect_keystone(self):
     def _connect_keystone(self):
         """
         """
@@ -96,6 +101,18 @@ class OpenStackCloudProviderV1(BaseCloudProvider):
         """
         """
         Get an openstack cinder client object for the given cloud.
         Get an openstack cinder client object for the given cloud.
         """
         """
+        api_version = self._get_config_value(
+            'os_volume_api_version',
+            os.environ.get('OS_VOLUME_API_VERSION', 2))
+
         return cinder_client.Client(
         return cinder_client.Client(
-            self.api_version, self.username, self.password, self.tenant_name,
-            self.auth_url)
+            api_version, username=self.username, api_key=self.password,
+            project_id=self.tenant_name, auth_url=self.auth_url)
+
+    def _connect_swift(self):
+        """
+        Get an openstack swift client object for the given cloud.
+        """
+        return swift_client.Connection(
+            authurl=self.auth_url, auth_version='2', user=self.username,
+            key=self.password, tenant_name=self.tenant_name)

+ 105 - 0
cloudbridge/providers/openstack/resources.py

@@ -1,12 +1,18 @@
 """
 """
 DataTypes used by this provider
 DataTypes used by this provider
 """
 """
+import shutil
+
+from swiftclient.exceptions import ClientException
+
 from cloudbridge.providers.base import BaseInstance
 from cloudbridge.providers.base import BaseInstance
 from cloudbridge.providers.base import BaseKeyPair
 from cloudbridge.providers.base import BaseKeyPair
 from cloudbridge.providers.base import BaseMachineImage
 from cloudbridge.providers.base import BaseMachineImage
 from cloudbridge.providers.base import BaseSecurityGroup
 from cloudbridge.providers.base import BaseSecurityGroup
 from cloudbridge.providers.base import BaseSnapshot
 from cloudbridge.providers.base import BaseSnapshot
 from cloudbridge.providers.base import BaseVolume
 from cloudbridge.providers.base import BaseVolume
+from cloudbridge.providers.interfaces import Container
+from cloudbridge.providers.interfaces import ContainerObject
 from cloudbridge.providers.interfaces import InstanceState
 from cloudbridge.providers.interfaces import InstanceState
 from cloudbridge.providers.interfaces import InstanceType
 from cloudbridge.providers.interfaces import InstanceType
 from cloudbridge.providers.interfaces import MachineImageState
 from cloudbridge.providers.interfaces import MachineImageState
@@ -483,3 +489,102 @@ class OpenStackSecurityGroup(BaseSecurityGroup):
 
 
     def __init__(self, provider, security_group):
     def __init__(self, provider, security_group):
         super(OpenStackSecurityGroup, self).__init__(provider, security_group)
         super(OpenStackSecurityGroup, self).__init__(provider, security_group)
+
+
+class OpenStackContainerObject(ContainerObject):
+
+    def __init__(self, provider, cbcontainer, obj):
+        self.provider = provider
+        self.cbcontainer = cbcontainer
+        self._obj = obj
+
+    @property
+    def name(self):
+        """
+        Get this object's name.
+        """
+        return self._obj.get("name")
+
+    def download(self, target_stream):
+        """
+        Download this object and write its
+        contents to the target_stream.
+        """
+        _, content = self.provider.swift.get_object(
+            self.cbcontainer.name, self.name, resp_chunk_size=65536)
+        shutil.copyfileobj(content, target_stream)
+
+    def upload(self, data):
+        """
+        Set the contents of this object to the data read from the source
+        string.
+        """
+        self.provider.swift.put_object(self.cbcontainer.name, self.name,
+                                       data)
+
+    def delete(self):
+        """
+        Delete this object.
+
+        :rtype: bool
+        :return: True if successful
+        """
+        try:
+            self.provider.swift.delete_object(self.cbcontainer.name, self.name)
+        except ClientException as err:
+            if err.http_status == 404:
+                return True
+        return False
+
+    def __repr__(self):
+        return "<CB-OpenStackContainerObject: {0}>".format(self.name)
+
+
+class OpenStackContainer(Container):
+
+    def __init__(self, provider, container):
+        self.provider = provider
+        self._container = container
+
+    @property
+    def name(self):
+        """
+        Get this container's name.
+        """
+        return self._container.get("name")
+
+    def get(self, key):
+        """
+        Retrieve a given object from this container.
+        """
+        _, object_list = self.provider.swift.get_container(
+            self.name, prefix=key)
+        if object_list:
+            return OpenStackContainerObject(self.provider, self,
+                                            object_list[0])
+        else:
+            return None
+
+    def list(self):
+        """
+        List all objects within this container.
+
+        :rtype: ContainerObject
+        :return: List of all available ContainerObjects within this container
+        """
+        _, object_list = self.provider.swift.get_container(self.name)
+        return [
+            OpenStackContainer(self.provider, o) for o in object_list]
+
+    def delete(self, delete_contents=False):
+        """
+        Delete this container.
+        """
+        self.provider.swift.delete_container(self.name)
+
+    def create_object(self, object_name):
+        self.provider.swift.put_object(self.name, object_name, None)
+        return self.get(object_name)
+
+    def __repr__(self):
+        return "<CB-OpenStackContainer: {0}>".format(self.name)

+ 46 - 2
cloudbridge/providers/openstack/services.py

@@ -12,6 +12,7 @@ from cloudbridge.providers.interfaces import InstanceTypesService
 from cloudbridge.providers.interfaces import KeyPair
 from cloudbridge.providers.interfaces import KeyPair
 from cloudbridge.providers.interfaces import KeyPairService
 from cloudbridge.providers.interfaces import KeyPairService
 from cloudbridge.providers.interfaces import MachineImage
 from cloudbridge.providers.interfaces import MachineImage
+from cloudbridge.providers.interfaces import ObjectStoreService
 from cloudbridge.providers.interfaces import PlacementZone
 from cloudbridge.providers.interfaces import PlacementZone
 from cloudbridge.providers.interfaces import SecurityGroup
 from cloudbridge.providers.interfaces import SecurityGroup
 from cloudbridge.providers.interfaces import SecurityGroupService
 from cloudbridge.providers.interfaces import SecurityGroupService
@@ -19,6 +20,7 @@ from cloudbridge.providers.interfaces import SecurityService
 from cloudbridge.providers.interfaces import SnapshotService
 from cloudbridge.providers.interfaces import SnapshotService
 from cloudbridge.providers.interfaces import VolumeService
 from cloudbridge.providers.interfaces import VolumeService
 
 
+from .resources import OpenStackContainer
 from .resources import OpenStackInstance
 from .resources import OpenStackInstance
 from .resources import OpenStackInstanceType
 from .resources import OpenStackInstanceType
 from .resources import OpenStackKeyPair
 from .resources import OpenStackKeyPair
@@ -122,7 +124,8 @@ class OpenStackSecurityGroupService(SecurityGroupService):
         :return:  list of SecurityGroup objects
         :return:  list of SecurityGroup objects
         """
         """
         groups = self.provider.nova.security_groups.list()
         groups = self.provider.nova.security_groups.list()
-        return [OpenStackSecurityGroup(self.provider, group) for group in groups]
+        return [OpenStackSecurityGroup(
+            self.provider, group) for group in groups]
 
 
     def create(self, name, description):
     def create(self, name, description):
         """
         """
@@ -157,7 +160,8 @@ class OpenStackSecurityGroupService(SecurityGroupService):
                           returned.
                           returned.
 
 
         :rtype: list of :class:`SecurityGroup`
         :rtype: list of :class:`SecurityGroup`
-        :return: A list of SecurityGroup objects or an empty list if none found.
+        :return: A list of SecurityGroup objects or an empty list if none
+        found.
         """
         """
         raise NotImplementedError(
         raise NotImplementedError(
             'get not implemented by this provider')
             'get not implemented by this provider')
@@ -312,6 +316,46 @@ class OpenStackSnapshotService(SnapshotService):
         return OpenStackSnapshot(self.provider, os_snap)
         return OpenStackSnapshot(self.provider, os_snap)
 
 
 
 
+class OpenStackObjectStoreService(ObjectStoreService):
+
+    def __init__(self, provider):
+        self.provider = provider
+
+    def get_container(self, container_id):
+        """
+        Returns a container given its id. Returns None if the container
+        does not exist.
+        """
+        _, container_list = self.provider.swift.get_account(
+            prefix=container_id)
+        if container_list:
+            return OpenStackContainer(self.provider, container_list[0])
+        else:
+            return None
+
+    def find_container(self, name):
+        """
+        Searches for a container by a given list of attributes
+        """
+        raise NotImplementedError(
+            'find_container not implemented by this provider')
+
+    def list_containers(self):
+        """
+        List all containers.
+        """
+        _, container_list = self.provider.swift.get_account()
+        return [
+            OpenStackContainer(self.provider, c) for c in container_list]
+
+    def create_container(self, name, location=None):
+        """
+        Create a new container.
+        """
+        self.provider.swift.put_container(name)
+        return self.get_container(name)
+
+
 class OpenStackComputeService(ComputeService):
 class OpenStackComputeService(ComputeService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):

+ 3 - 3
setup.py

@@ -8,9 +8,9 @@ setup(name='cloudbridge',
       author='Galaxy and GVL Projects',
       author='Galaxy and GVL Projects',
       author_email='support@genome.edu.au',
       author_email='support@genome.edu.au',
       url='http://cloudbridge.readthedocs.org/',
       url='http://cloudbridge.readthedocs.org/',
-      install_requires=['bunch>=1.00', 'six>=1.9.0',
-                        'python-keystoneclient', 'python-novaclient',
-                        'python-cinderclient', 'boto'],
+      install_requires=['bunch>=1.00', 'six>=1.9.0', 'python-keystoneclient',
+                        'python-novaclient', 'python-cinderclient',
+                        'python-swiftclient', 'boto'],
       packages=find_packages(),
       packages=find_packages(),
       license='MIT',
       license='MIT',
       classifiers=[
       classifiers=[