Преглед изворни кода

Merge pull request #282 from FabioRosado/fr/azure

Fix issues with upload blob, blob url and snapshots
Nuwan Goonasekera пре 4 година
родитељ
комит
fd12674f41

+ 22 - 8
cloudbridge/providers/azure/azure_client.py

@@ -436,30 +436,41 @@ class AzureClient(object):
 
 
     def upload_blob(self, container_name, blob_name, data, length=None):
     def upload_blob(self, container_name, blob_name, data, length=None):
         blob_client = self.blob_client(container_name, blob_name)
         blob_client = self.blob_client(container_name, blob_name)
-        blob_client.upload_blob(data=data, length=length)
+        blob_client.upload_blob(data=data, length=length, overwrite=True)
 
 
     def get_blob(self, container_name, blob_name):
     def get_blob(self, container_name, blob_name):
         blob_client = self.blob_client(container_name, blob_name)
         blob_client = self.blob_client(container_name, blob_name)
         return blob_client.get_blob_properties(container_name, blob_name)
         return blob_client.get_blob_properties(container_name, blob_name)
 
 
     def create_blob_from_text(self, container_name, blob_name, text):
     def create_blob_from_text(self, container_name, blob_name, text):
-        length = len(text.encode())
+        if isinstance(text, bytes):
+            length = len(text)
+        else:
+            length = len(text.encode())
         self.upload_blob(container_name, blob_name, text, length)
         self.upload_blob(container_name, blob_name, text, length)
 
 
     def create_blob_from_file(self, container_name, blob_name, file_path, length=None):
     def create_blob_from_file(self, container_name, blob_name, file_path, length=None):
         with open(file_path, 'rb') as data:
         with open(file_path, 'rb') as data:
-            self.upload_blob(container_name, blob_name, data, length)
+            data = data.read()
+            self.upload_blob(container_name, blob_name, data, len(data))
 
 
     def delete_blob(self, container_name, blob_name, delete_snapshots="include"):
     def delete_blob(self, container_name, blob_name, delete_snapshots="include"):
         blob_client = self.blob_client(container_name, blob_name)
         blob_client = self.blob_client(container_name, blob_name)
         blob_client.delete_blob(delete_snapshots)
         blob_client.delete_blob(delete_snapshots)
 
 
     def get_blob_url(self, container_name, blob_name, expiry_time):
     def get_blob_url(self, container_name, blob_name, expiry_time):
-        expiry_date = datetime.datetime.utcnow() + datetime.timedelta(
+        now = datetime.datetime.utcnow()
+        expiry = now + datetime.timedelta(
             seconds=expiry_time)
             seconds=expiry_time)
+        blob_name = blob_name.name
+        container_name = container_name.name
+        delegation_key = self.blob_service.get_user_delegation_key(
+            key_start_time=now, key_expiry_time=expiry
+        )
         sas = generate_blob_sas(
         sas = generate_blob_sas(
             self.storage_account, container_name, blob_name,
             self.storage_account, container_name, blob_name,
-            permission=BlobSasPermissions(read=True), expiry=expiry_date
+            permission=BlobSasPermissions(read=True), expiry=expiry,
+            user_delegation_key=delegation_key
         )
         )
         url = (
         url = (
             f"https://{self.storage_account}.blob.core.windows.net/"
             f"https://{self.storage_account}.blob.core.windows.net/"
@@ -519,13 +530,16 @@ class AzureClient(object):
         return self.compute_client.snapshots.get(self.resource_group,
         return self.compute_client.snapshots.get(self.resource_group,
                                                  snapshot_name)
                                                  snapshot_name)
 
 
-    def create_snapshot(self, snapshot_name, params):
-        return self.compute_client.snapshots.begin_create_or_update(
+    def create_snapshot(self, snapshot_name, volume, tags):
+        snapshot = self.compute_client.snapshots.begin_create_or_update(
             self.resource_group,
             self.resource_group,
             snapshot_name,
             snapshot_name,
-            params
+            volume,
         ).result()
         ).result()
 
 
+        self.update_snapshot_tags(snapshot.id, tags)
+        return snapshot
+
     def delete_snapshot(self, snapshot_id):
     def delete_snapshot(self, snapshot_id):
         url_params = azure_helpers.parse_url(SNAPSHOT_RESOURCE_ID,
         url_params = azure_helpers.parse_url(SNAPSHOT_RESOURCE_ID,
                                              snapshot_id)
                                              snapshot_id)

+ 15 - 10
cloudbridge/providers/azure/resources.py

@@ -24,6 +24,7 @@ from azure.common import AzureException
 from azure.core.exceptions import HttpResponseError
 from azure.core.exceptions import HttpResponseError
 from azure.mgmt.devtestlabs.models import GalleryImageReference
 from azure.mgmt.devtestlabs.models import GalleryImageReference
 from azure.mgmt.network.models import NetworkSecurityGroup
 from azure.mgmt.network.models import NetworkSecurityGroup
+from azure.storage.blob._models import BlobProperties
 
 
 from . import helpers as azure_helpers
 from . import helpers as azure_helpers
 from .subservices import (AzureBucketObjectSubService,
 from .subservices import (AzureBucketObjectSubService,
@@ -163,21 +164,25 @@ class AzureBucketObject(BaseBucketObject):
         super(AzureBucketObject, self).__init__(provider)
         super(AzureBucketObject, self).__init__(provider)
         self._container = container
         self._container = container
         self._blob_client = blob_client
         self._blob_client = blob_client
+        if isinstance(self._blob_client, BlobProperties):
+            self._blob_properties = blob_client
+        else:
+            self._blob_properties = self._blob_client.get_blob_properties()
 
 
     @property
     @property
     def id(self):
     def id(self):
-        return self._blob_client.blob_name
+        return self._blob_properties.name
 
 
     @property
     @property
     def name(self):
     def name(self):
-        return self._blob_client.blob_name
+        return self._blob_properties.name
 
 
     @property
     @property
     def size(self):
     def size(self):
         """
         """
         Get this object's size.
         Get this object's size.
         """
         """
-        return self._blob_client.get_blob_properties().content_length
+        return self._blob_properties.size
 
 
     @property
     @property
     def last_modified(self):
     def last_modified(self):
@@ -185,15 +190,14 @@ class AzureBucketObject(BaseBucketObject):
         """
         """
         Get the date and time this object was last modified.
         Get the date and time this object was last modified.
         """
         """
-        return self._blob_client.get_blob_properties().last_modified. \
-            strftime("%Y-%m-%dT%H:%M:%S.%f")
+        return self._blob_properties.last_modified.strftime("%Y-%m-%dT%H:%M:%S.%f")
 
 
     def iter_content(self):
     def iter_content(self):
         """
         """
         Returns this object's content as an
         Returns this object's content as an
         iterable.
         iterable.
         """
         """
-        return self._blob_client.download_blob.chunks()
+        return self._container._bucket.download_blob(self._blob_client).chunks()
 
 
     def upload(self, data):
     def upload(self, data):
         """
         """
@@ -213,8 +217,10 @@ class AzureBucketObject(BaseBucketObject):
         Store the contents of the file pointed by the "path" variable.
         Store the contents of the file pointed by the "path" variable.
         """
         """
         try:
         try:
-            with open(path, "rb") as stream:
-                self._blob_client.upload_blob(stream, overwrite=True)
+            self._provider.azure_client.create_blob_from_file(
+                self._container.name, self._blob_client,
+                path
+            )
             return True
             return True
         except AzureException as azureEx:
         except AzureException as azureEx:
             log.exception(azureEx)
             log.exception(azureEx)
@@ -227,7 +233,7 @@ class AzureBucketObject(BaseBucketObject):
         :rtype: bool
         :rtype: bool
         :return: True if successful
         :return: True if successful
         """
         """
-        self._blob_client.delete_blob()
+        self._provider.azure_client.delete_blob(self._container.name, self.name)
 
 
     def generate_url(self, expires_in):
     def generate_url(self, expires_in):
         """
         """
@@ -280,7 +286,6 @@ class AzureBucket(BaseBucket):
         return self._object_container
         return self._object_container
 
 
 
 
-
 class AzureVolume(BaseVolume):
 class AzureVolume(BaseVolume):
     VOLUME_STATE_MAP = {
     VOLUME_STATE_MAP = {
         'InProgress': VolumeState.CREATING,
         'InProgress': VolumeState.CREATING,

+ 6 - 11
cloudbridge/providers/azure/services.py

@@ -476,18 +476,13 @@ class AzureSnapshotService(BaseSnapshotService):
         volume = (self.provider.storage.volumes.get(volume)
         volume = (self.provider.storage.volumes.get(volume)
                   if isinstance(volume, str) else volume)
                   if isinstance(volume, str) else volume)
 
 
-        params = {
-            'location': self.provider.azure_client.region_name,
-            'creation_data': {
-                'create_option': DiskCreateOption.copy,
-                'source_uri': volume.resource_id
-            },
-            'disk_size_gb': volume.size,
-            'tags': tags
-        }
+        # We need to pass the Disk Object to create the snapshot
+        volume = volume._volume
+
+        azure_snap = self.provider.azure_client.create_snapshot(
+            snapshot_name, volume, tags
+        )
 
 
-        azure_snap = self.provider.azure_client.create_snapshot(snapshot_name,
-                                                                params)
         return AzureSnapshot(self.provider, azure_snap)
         return AzureSnapshot(self.provider, azure_snap)
 
 
     @dispatch(event="provider.storage.snapshots.delete",
     @dispatch(event="provider.storage.snapshots.delete",

+ 3 - 6
tests/test_network_service.py

@@ -1,11 +1,8 @@
 from cloudbridge.base import helpers as cb_helpers
 from cloudbridge.base import helpers as cb_helpers
 from cloudbridge.base.resources import BaseNetwork
 from cloudbridge.base.resources import BaseNetwork
-from cloudbridge.interfaces.resources import FloatingIP
-from cloudbridge.interfaces.resources import Network
-from cloudbridge.interfaces.resources import NetworkState
-from cloudbridge.interfaces.resources import RouterState
-from cloudbridge.interfaces.resources import Subnet
-from cloudbridge.interfaces.resources import SubnetState
+from cloudbridge.interfaces.resources import (FloatingIP, Network,
+                                              NetworkState, RouterState,
+                                              Subnet, SubnetState)
 
 
 import tests.helpers as helpers
 import tests.helpers as helpers
 from tests.helpers import ProviderTestBase
 from tests.helpers import ProviderTestBase