Parcourir la source

Implemented create volume method

vikramdoda il y a 9 ans
Parent
commit
7267420f82

+ 40 - 0
cloudbridge/cloud/providers/azure/azure_client.py

@@ -41,6 +41,10 @@ class AzureClient(object):
     def storage_account_name(self):
     def storage_account_name(self):
         return self._config.get('azure_storage_account_name')
         return self._config.get('azure_storage_account_name')
 
 
+    @property
+    def region_name(self):
+        return self._config.get('azure_region_name')
+
     @property
     @property
     def storage_client(self):
     def storage_client(self):
         return self._storage_client
         return self._storage_client
@@ -142,3 +146,39 @@ class AzureClient(object):
 
 
     def get_blob_content(self, container_name, blob_name):
     def get_blob_content(self, container_name, blob_name):
         return self.blob_service.get_blob_to_text(container_name, blob_name)
         return self.blob_service.get_blob_to_text(container_name, blob_name)
+
+    def create_empty_disk(self, disk_name, size, region=None, snapshot_id=None):
+        if snapshot_id:
+            return self.create_snapshot_disk(disk_name, snapshot_id, region)
+
+        async_creation = self.compute_client.disks.create_or_update(
+            self.resource_group_name,
+            disk_name,
+            {
+                'location': region or self.region_name,
+                'disk_size_gb': size,
+                'creation_data': {
+                    'create_option': 'empty'
+                }
+            }
+        )
+        disk_resource = async_creation.result()
+        return disk_resource
+
+    def create_snapshot_disk(self, disk_name, snapshot_id, region=None):
+        async_creation = self.compute_client.disks.create_or_update(
+            self.resource_group_name,
+            disk_name,
+            {
+                'location': region or self.region_name,
+                'creation_data': {
+                    'create_option': 'copy',
+                    'source_uri':snapshot_id
+                }
+            }
+        )
+        disk_resource = async_creation.result()
+        return disk_resource
+
+    def get_disk(self, disk_name):
+        return self.compute_client.disks.get(self.resource_group_name, disk_name)

+ 4 - 3
cloudbridge/cloud/providers/azure/provider.py

@@ -6,7 +6,8 @@ from cloudbridge.cloud.interfaces import TestMockHelperMixin
 
 
 from cloudbridge.cloud.providers.azure.azure_client import AzureClient
 from cloudbridge.cloud.providers.azure.azure_client import AzureClient
 from cloudbridge.cloud.providers.azure.mock_azure_client import MockAzureClient
 from cloudbridge.cloud.providers.azure.mock_azure_client import MockAzureClient
-from cloudbridge.cloud.providers.azure.services import AzureSecurityService, AzureObjectStoreService
+from cloudbridge.cloud.providers.azure.services import AzureSecurityService, AzureObjectStoreService, \
+    AzureBlockStoreService
 
 
 log = logging.getLogger(__name__)
 log = logging.getLogger(__name__)
 
 
@@ -58,6 +59,7 @@ class AzureCloudProvider(BaseCloudProvider):
 
 
         self._security = AzureSecurityService(self)
         self._security = AzureSecurityService(self)
         self._object_store = AzureObjectStoreService(self)
         self._object_store = AzureObjectStoreService(self)
+        self._block_store = AzureBlockStoreService(self)
 
 
     @property
     @property
     def compute(self):
     def compute(self):
@@ -75,8 +77,7 @@ class AzureCloudProvider(BaseCloudProvider):
 
 
     @property
     @property
     def block_store(self):
     def block_store(self):
-        raise NotImplementedError(
-            "AzureCloudProvider does not implement this service")
+        return self._block_store
 
 
     @property
     @property
     def object_store(self):
     def object_store(self):

+ 160 - 1
cloudbridge/cloud/providers/azure/resources.py

@@ -5,8 +5,39 @@ import inspect
 import json
 import json
 from datetime import datetime
 from datetime import datetime
 
 
+from msrestazure.azure_exceptions import CloudError
+
 from cloudbridge.cloud.base.resources import BaseBucket, BaseSecurityGroup, BaseSecurityGroupRule, BaseBucketObject, \
 from cloudbridge.cloud.base.resources import BaseBucket, BaseSecurityGroup, BaseSecurityGroupRule, BaseBucketObject, \
-    ClientPagedResultList
+    ClientPagedResultList, BaseVolume, BaseAttachmentInfo, BaseInstance, BaseSnapshot
+from cloudbridge.cloud.interfaces import VolumeState, SnapshotState, InstanceState
+
+NETWORK_RESOURCE_ID = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/virtualNetworks/{virtualNetworkName}'
+IMAGE_RESOURCE_ID =  '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/images/{imageName}'
+INSTANCE_RESOURCE_ID = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}'
+VOLUME_RESOURCE_ID = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/disks/{diskName}'
+SNAPSHOT_RESOURCE_ID = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/snapshots/{snapshotName}'
+NETWORK_SECURITY_GROUP_RESOURCE_ID = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/networkSecurityGroups/{networkSecurityGroupName}'
+NETWORK_SECURITY_RULE_RESOURCE_ID = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/networkSecurityGroups/{networkSecurityGroupName}/securityRules/{securityRuleName}'
+SUBNET_RESOURCE_ID = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/virtualNetworks/{virtualNetworkName}/subnets/{subnetName}'
+PUBLIC_IP_RESOURCE_ID = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/publicIPAddresses/{publicIpAddressName}'
+ROUTE_TABLE_RESOURCE_ID = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/routeTables/{routeTableName}'
+ROUTE_RESOURCE_ID = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/routeTables/{routeTableName}/routes/{routeName}'
+NETWORK_INTERFACE_RESOURCE_ID = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/networkInterfaces/{networkInterfaceName}'
+
+RESOURCE_GROUP_NAME='resourceGroupName'
+SUBSCRIPTION_ID='subscriptionId'
+NETWORK_NAME='virtualNetworkName'
+IMAGE_NAME='imageName'
+VM_NAME='vmName'
+VOLUME_NAME ='diskName'
+SNAPSHOT_NAME ='snapshotName'
+SECURITY_GROUP_NAME='networkSecurityGroupName'
+SECURITY_GROUP_RULE_NAME ='securityRuleName'
+SUBNET_NAME = 'subnetName'
+PUBLIC_IP_NAME = 'publicIpAddressName'
+ROUTE_TABLE_NAME = 'routeTableName'
+ROUTE_NAME = 'routeName'
+NETWORK_INTERFACE_NAME ='networkInterfaceName'
 
 
 
 
 class AzureSecurityGroup(BaseSecurityGroup):
 class AzureSecurityGroup(BaseSecurityGroup):
@@ -281,3 +312,131 @@ class AzureBucket(BaseBucket):
         Determine if an object with given name exists in this bucket.
         Determine if an object with given name exists in this bucket.
         """
         """
         return True if self.get(name) else False
         return True if self.get(name) else False
+
+
+class AzureVolume(BaseVolume):
+
+    VOLUME_STATE_MAP = {
+        'creating': VolumeState.CREATING,
+        'available': VolumeState.AVAILABLE,
+        'in-use': VolumeState.IN_USE,
+        'deleting': VolumeState.CONFIGURING,
+        'deleted': VolumeState.DELETED,
+        'error': VolumeState.ERROR
+    }
+
+    def __init__(self, provider, volume):
+        super(AzureVolume, self).__init__(provider)
+        self._volume = volume
+        self._url_params= TemplateUrlParser.parse(VOLUME_RESOURCE_ID,volume.id)
+
+    @property
+    def id(self):
+        return self._volume.id
+
+    @property
+    def name(self):
+        """
+        Get the volume name.
+
+        .. note:: an instance must have a (case sensitive) tag ``Name``
+        """
+        return self._volume.name
+
+    @name.setter
+    # pylint:disable=arguments-differ
+    def name(self, value):
+        """
+        Set the volume name.
+        """
+        self._volume.name = value
+
+    @property
+    def description(self):
+        return None
+
+    @description.setter
+    def description(self, value):
+        pass
+
+    @property
+    def size(self):
+        return self._volume.disk_size_gb
+
+    @property
+    def create_time(self):
+        return self._volume.time_created
+
+    @property
+    def zone_id(self):
+        return self._volume.location
+
+    @property
+    def source(self):
+        return None
+
+    @property
+    def attachments(self):
+        return None
+
+    def attach(self, instance, device=None):
+        pass
+
+    def detach(self, force=False):
+        pass
+
+    def create_snapshot(self, name, description=None):
+        pass
+
+    def delete(self):
+        pass
+
+    @property
+    def state(self):
+        return AzureVolume.VOLUME_STATE_MAP.get(
+            self._volume.provisioning_state, VolumeState.UNKNOWN)
+
+    def refresh(self):
+        pass
+
+
+class AzureInstance(BaseInstance):
+
+    def __init__(self, provider, vm_instace):
+        super(AzureInstance, self).__init__(provider)
+        self._vm = vm_instace
+        self._url_params = TemplateUrlParser.parse(INSTANCE_RESOURCE_ID,vm_instace.id)
+
+    @property
+    def id(self):
+        """
+        Get the instance identifier.
+        """
+        return self._vm.id
+
+
+class AzureSnapshot(BaseSnapshot):
+
+    def __init__(self, provider, snapshot):
+        super(AzureSnapshot, self).__init__(provider)
+        self._snapshot = snapshot
+        self._url_params = TemplateUrlParser.parse(SNAPSHOT_RESOURCE_ID,snapshot.id)
+
+    @property
+    def id(self):
+        return self._snapshot.id
+
+
+class TemplateUrlParser:
+    @staticmethod
+    def parse(template_url, original_url):
+        template_url_parts = template_url.split('/')
+        original_url_parts = original_url.split('/')
+        if len(template_url_parts) != len(original_url_parts):
+            raise Exception('Invalid url parameter passed')
+        d = {}
+        for k, v in zip(template_url_parts, original_url_parts):
+            if k.startswith('{') and k.endswith('}'):
+                d.update({k[1:-1]: v})
+
+        return d

+ 46 - 2
cloudbridge/cloud/providers/azure/services.py

@@ -1,7 +1,14 @@
 import logging
 import logging
 
 
+from cloudbridge.cloud.interfaces.resources import PlacementZone
+from .resources import SUBNET_RESOURCE_ID, NETWORK_NAME, SUBNET_NAME, NETWORK_RESOURCE_ID, \
+    INSTANCE_RESOURCE_ID, VM_NAME, IMAGE_RESOURCE_ID, RESOURCE_GROUP_NAME, IMAGE_NAME, SNAPSHOT_RESOURCE_ID, \
+    SNAPSHOT_NAME, VOLUME_RESOURCE_ID, VOLUME_NAME, NETWORK_SECURITY_GROUP_RESOURCE_ID, SECURITY_GROUP_NAME, \
+    TemplateUrlParser, AzureVolume, AzureSnapshot
+
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.resources import ClientPagedResultList
-from cloudbridge.cloud.base.services import BaseObjectStoreService, BaseSecurityGroupService, BaseSecurityService
+from cloudbridge.cloud.base.services import BaseObjectStoreService, BaseSecurityGroupService, BaseSecurityService, \
+    BaseVolumeService, BaseBlockStoreService
 
 
 from .resources import AzureBucket, AzureSecurityGroup
 from .resources import AzureBucket, AzureSecurityGroup
 
 
@@ -101,4 +108,41 @@ class AzureObjectStoreService(BaseObjectStoreService):
 
 
     def create(self, name, location=None):
     def create(self, name, location=None):
         object_store = self.provider.azure_client.create_container(name)
         object_store = self.provider.azure_client.create_container(name)
-        return AzureBucket(self.provider, object_store)
+        return AzureBucket(self.provider, object_store)
+
+
+class AzureBlockStoreService(BaseBlockStoreService):
+    def __init__(self, provider):
+        super(AzureBlockStoreService, self).__init__(provider)
+
+        # Initialize provider services
+        self._volume_svc = AzureVolumeService(self.provider)
+        #self._snapshot_svc = AzureSnapshotService(self.provider)
+
+    @property
+    def volumes(self):
+        return self._volume_svc
+
+    @property
+    def snapshots(self):
+        pass
+
+class AzureVolumeService(BaseVolumeService):
+
+    def __init__(self, provider):
+        super(AzureVolumeService, self).__init__(provider)
+
+    def get(self, volume_id):
+        raise NotImplementedError('AzureVolumeService not imeplemented this method')
+
+    def find(self, name, limit=None, marker=None):
+        raise NotImplementedError('AzureVolumeService not imeplemented this method')
+
+    def list(self, limit=None, marker=None):
+        raise NotImplementedError('AzureVolumeService not imeplemented this method')
+
+    def create(self, name, size, zone=None, snapshot=None, description=None):
+        region = zone.id if isinstance(zone, PlacementZone) else zone
+        snapshot_id = snapshot.id if isinstance(snapshot, AzureSnapshot) and snapshot else snapshot
+        volume =  self.provider.azure_client.create_empty_disk(name, size, region, snapshot_id)
+        return AzureVolume(self.provider, volume)