Ver código fonte

Added openstack object store implementation

nuwan_ag 10 anos atrás
pai
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.auth.identity import Password
 from novaclient import client as nova_client
+from swiftclient import client as swift_client
 
 from cloudbridge.providers.base import BaseCloudProvider
 
 from .services import OpenStackBlockStoreService
 from .services import OpenStackComputeService
 from .services import OpenStackImageService
+from .services import OpenStackObjectStoreService
 from .services import OpenStackSecurityService
 
 
@@ -24,8 +26,6 @@ class OpenStackCloudProviderV1(BaseCloudProvider):
     def __init__(self, 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(
             'username', os.environ.get('OS_USERNAME', None))
         self.password = self._get_config_value(
@@ -38,12 +38,13 @@ class OpenStackCloudProviderV1(BaseCloudProvider):
         self.nova = self._connect_nova()
         self.keystone = self._connect_keystone()
         self.cinder = self._connect_cinder()
+        self.swift = self._connect_swift()
 
         self._compute = OpenStackComputeService(self)
         self._images = OpenStackImageService(self)
         self._security = OpenStackSecurityService(self)
         self._block_store = OpenStackBlockStoreService(self)
-        self._object_store = None  # OpenStackObjectStore(self)
+        self._object_store = OpenStackObjectStoreService(self)
 
     @property
     def compute(self):
@@ -69,9 +70,13 @@ class OpenStackCloudProviderV1(BaseCloudProvider):
         """
         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(
-            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):
         """
@@ -96,6 +101,18 @@ class OpenStackCloudProviderV1(BaseCloudProvider):
         """
         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(
-            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
 """
+import shutil
+
+from swiftclient.exceptions import ClientException
+
 from cloudbridge.providers.base import BaseInstance
 from cloudbridge.providers.base import BaseKeyPair
 from cloudbridge.providers.base import BaseMachineImage
 from cloudbridge.providers.base import BaseSecurityGroup
 from cloudbridge.providers.base import BaseSnapshot
 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 InstanceType
 from cloudbridge.providers.interfaces import MachineImageState
@@ -483,3 +489,102 @@ class OpenStackSecurityGroup(BaseSecurityGroup):
 
     def __init__(self, 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 KeyPairService
 from cloudbridge.providers.interfaces import MachineImage
+from cloudbridge.providers.interfaces import ObjectStoreService
 from cloudbridge.providers.interfaces import PlacementZone
 from cloudbridge.providers.interfaces import SecurityGroup
 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 VolumeService
 
+from .resources import OpenStackContainer
 from .resources import OpenStackInstance
 from .resources import OpenStackInstanceType
 from .resources import OpenStackKeyPair
@@ -122,7 +124,8 @@ class OpenStackSecurityGroupService(SecurityGroupService):
         :return:  list of SecurityGroup objects
         """
         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):
         """
@@ -157,7 +160,8 @@ class OpenStackSecurityGroupService(SecurityGroupService):
                           returned.
 
         :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(
             'get not implemented by this provider')
@@ -312,6 +316,46 @@ class OpenStackSnapshotService(SnapshotService):
         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):
 
     def __init__(self, provider):

+ 3 - 3
setup.py

@@ -8,9 +8,9 @@ setup(name='cloudbridge',
       author='Galaxy and GVL Projects',
       author_email='support@genome.edu.au',
       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(),
       license='MIT',
       classifiers=[