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

Fixed issues found while running cloudbridge tests
Updated the network security service and fixed unit tests

vikramdoda 9 лет назад
Родитель
Сommit
75f5d48b5b

+ 36 - 30
cloudbridge/cloud/providers/azure/azure_client.py

@@ -27,12 +27,19 @@ class AzureClient(object):
         self._network_management_client = NetworkManagementClient(credentials, self.subscription_id)
         self._network_management_client = NetworkManagementClient(credentials, self.subscription_id)
         self._subscription_client = SubscriptionClient(credentials)
         self._subscription_client = SubscriptionClient(credentials)
         self._compute_client = ComputeManagementClient(credentials, self.subscription_id)
         self._compute_client = ComputeManagementClient(credentials, self.subscription_id)
-        access_key_result = self.storage_client.storage_accounts.list_keys(self.resource_group_name,
-                                                                           self.storage_account_name)
-        self._block_blob_service = BlockBlobService(self.storage_account_name, access_key_result.keys[0].value)
+
+        self._access_key_result = None
+        self._block_blob_service = None
 
 
         log.debug("azure subscription : %s", self.subscription_id)
         log.debug("azure subscription : %s", self.subscription_id)
 
 
+    @property
+    def access_key_result(self):
+        if not self._access_key_result:
+            self._access_key_result = self.storage_client.storage_accounts.list_keys(self.resource_group_name,
+                                                                                     self.storage_account_name)
+        return self._access_key_result
+
     @property
     @property
     def resource_group_name(self):
     def resource_group_name(self):
         return self._config.get('azure_resource_group')
         return self._config.get('azure_resource_group')
@@ -67,6 +74,8 @@ class AzureClient(object):
 
 
     @property
     @property
     def blob_service(self):
     def blob_service(self):
+        if not self._block_blob_service:
+            self._block_blob_service = BlockBlobService(self.storage_account_name, self.access_key_result.keys[0].value)
         return self._block_blob_service
         return self._block_blob_service
 
 
     def get_resource_group(self, name):
     def get_resource_group(self, name):
@@ -75,6 +84,12 @@ class AzureClient(object):
     def create_resource_group(self, name, parameters):
     def create_resource_group(self, name, parameters):
         return self.resource_client.resource_groups.create_or_update(name, parameters)
         return self.resource_client.resource_groups.create_or_update(name, parameters)
 
 
+    def get_storage_account(self, storage_account_name):
+        return self.storage_client.storage_accounts.get_properties(self.resource_group_name, storage_account_name)
+
+    def create_storage_account(self, name, params):
+        return self.storage_client.storage_accounts.create(self.resource_group_name, name, params).result()
+
     def list_locations(self):
     def list_locations(self):
         return self.subscription_client.subscriptions.list_locations(self.subscription_id)
         return self.subscription_client.subscriptions.list_locations(self.subscription_id)
 
 
@@ -82,21 +97,16 @@ class AzureClient(object):
         return self.network_management_client.network_security_groups.list(self.resource_group_name)
         return self.network_management_client.network_security_groups.list(self.resource_group_name)
 
 
     def create_security_group(self, name, parameters):
     def create_security_group(self, name, parameters):
-        sg_create = self.network_management_client.network_security_groups.create_or_update(self.resource_group_name,
-                                                                                            name, parameters)
-        return sg_create.result()
+        return self.network_management_client.network_security_groups.create_or_update(self.resource_group_name,
+                                                                                       name, parameters).result()
 
 
     def create_security_group_rule(self, security_group, rule_name, parameters):
     def create_security_group_rule(self, security_group, rule_name, parameters):
-        security_rules_operations = self.network_management_client.security_rules
-        sro = security_rules_operations.create_or_update(self.resource_group_name, security_group, rule_name,
-                                                         parameters)
-        result = sro.result()
-        return result
+        return self.network_management_client.security_rules.create_or_update(self.resource_group_name, security_group,
+                                                                              rule_name, parameters).result()
 
 
     def delete_security_group_rule(self, name, security_group):
     def delete_security_group_rule(self, name, security_group):
-        security_rules_operations = self.network_management_client.security_rules
-        sro = security_rules_operations.delete(self.resource_group_name, security_group, name)
-        return sro.result()
+        return self.network_management_client.security_rules.delete(self.resource_group_name, security_group,
+                                                                    name).result()
 
 
     def get_security_group(self, name):
     def get_security_group(self, name):
         return self.network_management_client.network_security_groups.get(self.resource_group_name, name)
         return self.network_management_client.network_security_groups.get(self.resource_group_name, name)
@@ -109,7 +119,7 @@ class AzureClient(object):
         return self.blob_service.list_containers()
         return self.blob_service.list_containers()
 
 
     def create_container(self, container_name):
     def create_container(self, container_name):
-        self.blob_service.create_container(container_name, public_access=PublicAccess.Container)
+        self.blob_service.create_container(container_name)
         return self.blob_service.get_container_properties(container_name)
         return self.blob_service.get_container_properties(container_name)
 
 
     def get_container(self, container_name):
     def get_container(self, container_name):
@@ -117,7 +127,6 @@ class AzureClient(object):
 
 
     def delete_container(self, container_name):
     def delete_container(self, container_name):
         self.blob_service.delete_container(container_name)
         self.blob_service.delete_container(container_name)
-        return None
 
 
     def list_blobs(self, container_name):
     def list_blobs(self, container_name):
         return self.blob_service.list_blobs(container_name)
         return self.blob_service.list_blobs(container_name)
@@ -127,11 +136,9 @@ class AzureClient(object):
 
 
     def create_blob_from_text(self, container_name, blob_name, text):
     def create_blob_from_text(self, container_name, blob_name, text):
         self.blob_service.create_blob_from_text(container_name, blob_name, text)
         self.blob_service.create_blob_from_text(container_name, blob_name, text)
-        return None
 
 
     def create_blob_from_file(self, container_name, blob_name, file_path):
     def create_blob_from_file(self, container_name, blob_name, file_path):
         self.blob_service.create_blob_from_path(container_name, blob_name, file_path)
         self.blob_service.create_blob_from_path(container_name, blob_name, file_path)
-        return None
 
 
     def delete_blob(self, container_name, blob_name):
     def delete_blob(self, container_name, blob_name):
         self.blob_service.delete_blob(container_name, blob_name)
         self.blob_service.delete_blob(container_name, blob_name)
@@ -146,7 +153,7 @@ class AzureClient(object):
 
 
     def create_empty_disk(self, disk_name, size, region=None, snapshot_id=None):
     def create_empty_disk(self, disk_name, size, region=None, snapshot_id=None):
         if snapshot_id:
         if snapshot_id:
-            return self.create_snapshot_disk(disk_name, snapshot_id, region)
+            return self.create_snapshot_disk(disk_name, snapshot_id, region=region)
 
 
         async_creation = self.compute_client.disks.create_or_update(
         async_creation = self.compute_client.disks.create_or_update(
             self.resource_group_name,
             self.resource_group_name,
@@ -163,7 +170,7 @@ class AzureClient(object):
         return async_creation
         return async_creation
 
 
     def create_snapshot_disk(self, disk_name, snapshot_id, region=None):
     def create_snapshot_disk(self, disk_name, snapshot_id, region=None):
-        async_creation = self.compute_client.disks.create_or_update(
+        disk_response = self.compute_client.disks.create_or_update(
             self.resource_group_name,
             self.resource_group_name,
             disk_name,
             disk_name,
             {
             {
@@ -172,10 +179,11 @@ class AzureClient(object):
                     'create_option': 'copy',
                     'create_option': 'copy',
                     'source_uri': snapshot_id
                     'source_uri': snapshot_id
                 }
                 }
-            }
+            },
+            raw=True
         )
         )
-        disk_resource = async_creation.result()
-        return disk_resource
+
+        return disk_response
 
 
     def get_disk(self, disk_name):
     def get_disk(self, disk_name):
         return self.compute_client.disks.get(self.resource_group_name, disk_name)
         return self.compute_client.disks.get(self.resource_group_name, disk_name)
@@ -195,20 +203,19 @@ class AzureClient(object):
 
 
         if vm:
         if vm:
             vm.storage_profile.data_disks.append({
             vm.storage_profile.data_disks.append({
-                'lun': len(vm.storage_profile.data_disks),  # You choose the value, depending of what is available for you
+                'lun': len(vm.storage_profile.data_disks),
                 'name': disk_name,
                 'name': disk_name,
                 'create_option': 'attach',
                 'create_option': 'attach',
                 'managed_disk': {
                 'managed_disk': {
                     'id': disk_id
                     'id': disk_id
                 }
                 }
             })
             })
-            async_update = self.compute_client.virtual_machines.create_or_update(
+            self.compute_client.virtual_machines.create_or_update(
                 self.resource_group_name,
                 self.resource_group_name,
                 vm.name,
                 vm.name,
                 vm,
                 vm,
+                raw=True
             )
             )
-            async_update.wait()
-        return None
 
 
     def detach_disk(self, disk_id):
     def detach_disk(self, disk_id):
         virtual_machine = None
         virtual_machine = None
@@ -223,7 +230,6 @@ class AzureClient(object):
             async_update = self.compute_client.virtual_machines.create_or_update(
             async_update = self.compute_client.virtual_machines.create_or_update(
                 self.resource_group_name,
                 self.resource_group_name,
                 virtual_machine.name,
                 virtual_machine.name,
-                virtual_machine
+                virtual_machine,
+                raw=True
             )
             )
-            async_update.wait()
-        return None

+ 4 - 1
cloudbridge/cloud/providers/azure/helpers.py

@@ -5,7 +5,10 @@ def filter(list_items, filters):
             for key in filters:
             for key in filters:
                 if filters[key] in str(getattr(obj, key)):
                 if filters[key] in str(getattr(obj, key)):
                     filtered_list.append(obj)
                     filtered_list.append(obj)
-    return filtered_list
+
+        return filtered_list
+    else:
+        return list_items
 
 
 
 
 def parse_url(template_url, original_url):
 def parse_url(template_url, original_url):

+ 30 - 15
cloudbridge/cloud/providers/azure/mock_azure_client.py

@@ -1,10 +1,14 @@
 from io import BytesIO
 from io import BytesIO
 
 
-from azure.mgmt.compute.models import Disk, CreationData, DiskCreateOption
+from azure.common import AzureMissingResourceHttpError, AzureException
+from azure.mgmt.compute.models import Disk, CreationData, DiskCreateOption, Snapshot
 from azure.mgmt.network.models import NetworkSecurityGroup
 from azure.mgmt.network.models import NetworkSecurityGroup
 from azure.mgmt.network.models import SecurityRule
 from azure.mgmt.network.models import SecurityRule
 from azure.mgmt.resource.resources.models import ResourceGroup
 from azure.mgmt.resource.resources.models import ResourceGroup
+from azure.mgmt.storage.models import StorageAccount
 from azure.storage.blob.models import Container, Blob
 from azure.storage.blob.models import Container, Blob
+from msrestazure.azure_exceptions import CloudError
+from requests import Response
 
 
 from cloudbridge.cloud.providers.azure import helpers as azure_helpers
 from cloudbridge.cloud.providers.azure import helpers as azure_helpers
 
 
@@ -21,27 +25,23 @@ class MockAzureClient:
                             direction="Inbound")
                             direction="Inbound")
     sg_rule2.name = "rule2"
     sg_rule2.name = "rule2"
     sg_rule2.id = "r2"
     sg_rule2.id = "r2"
-    sg_rule2.is_default = True
     sg_rule2.destination_port_range = "*"
     sg_rule2.destination_port_range = "*"
     sg_rule2.source_port_range = "*"
     sg_rule2.source_port_range = "*"
 
 
     sec_gr1 = NetworkSecurityGroup()
     sec_gr1 = NetworkSecurityGroup()
     sec_gr1.name = "sg1"
     sec_gr1.name = "sg1"
     sec_gr1.id = "/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/resourceGroups/CloudBridge-Azure/providers/Microsoft.Network/networkSecurityGroups/sg1"
     sec_gr1.id = "/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/resourceGroups/CloudBridge-Azure/providers/Microsoft.Network/networkSecurityGroups/sg1"
-    sec_gr1.default_security_rules = [sg_rule1]
-    sec_gr1.security_rules = [sg_rule2]
+    sec_gr1.security_rules = [sg_rule1, sg_rule2]
 
 
     sec_gr2 = NetworkSecurityGroup()
     sec_gr2 = NetworkSecurityGroup()
     sec_gr2.name = "sg2"
     sec_gr2.name = "sg2"
     sec_gr2.id = "/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/resourceGroups/CloudBridge-Azure/providers/Microsoft.Network/networkSecurityGroups/sg2"
     sec_gr2.id = "/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/resourceGroups/CloudBridge-Azure/providers/Microsoft.Network/networkSecurityGroups/sg2"
-    sec_gr2.default_security_rules = [sg_rule1]
-    sec_gr2.security_rules = [sg_rule2]
+    sec_gr2.security_rules = [sg_rule1, sg_rule2]
 
 
     sec_gr3 = NetworkSecurityGroup()
     sec_gr3 = NetworkSecurityGroup()
     sec_gr3.name = "sg3"
     sec_gr3.name = "sg3"
     sec_gr3.id = "/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/resourceGroups/CloudBridge-Azure/providers/Microsoft.Network/networkSecurityGroups/sg3"
     sec_gr3.id = "/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/resourceGroups/CloudBridge-Azure/providers/Microsoft.Network/networkSecurityGroups/sg3"
-    sec_gr3.default_security_rules = [sg_rule1]
-    sec_gr3.security_rules = [sg_rule2]
+    sec_gr3.security_rules = [sg_rule1, sg_rule2]
 
 
     security_groups = [sec_gr1, sec_gr2, sec_gr3]
     security_groups = [sec_gr1, sec_gr2, sec_gr3]
 
 
@@ -78,6 +78,7 @@ class MockAzureClient:
     volume1.creation_data = CreationData(create_option=DiskCreateOption.empty)
     volume1.creation_data = CreationData(create_option=DiskCreateOption.empty)
     volume1.time_created = '20-04-2017'
     volume1.time_created = '20-04-2017'
     volume1.owner_id = 'ubuntu-intro1'
     volume1.owner_id = 'ubuntu-intro1'
+    volume1.provisioning_state = 'InProgress'
 
 
     volume2 = Disk(location='eastus', creation_data=None)
     volume2 = Disk(location='eastus', creation_data=None)
     volume2.id = '/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/resourceGroups/CLOUDBRIDGE-AZURE/providers/Microsoft.Compute/disks/Volume2'
     volume2.id = '/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/resourceGroups/CLOUDBRIDGE-AZURE/providers/Microsoft.Compute/disks/Volume2'
@@ -85,10 +86,13 @@ class MockAzureClient:
     volume2.disk_size_gb = 1
     volume2.disk_size_gb = 1
     volume2.creation_data = CreationData(create_option=DiskCreateOption.empty)
     volume2.creation_data = CreationData(create_option=DiskCreateOption.empty)
     volume2.time_created = '20-04-2017'
     volume2.time_created = '20-04-2017'
-    volume2.owner_id = 'ubuntu-intro2'
+    volume2.owner_id = None
+    volume2.provisioning_state = 'Succeeded'
 
 
     volumes = [volume1, volume2]
     volumes = [volume1, volume2]
 
 
+    snapshots = []
+
     def __init__(self, provider):
     def __init__(self, provider):
         self._provider = provider
         self._provider = provider
 
 
@@ -115,7 +119,9 @@ class MockAzureClient:
         for item in self.security_groups:
         for item in self.security_groups:
             if item.name == name:
             if item.name == name:
                 return item
                 return item
-        return None
+        response = Response()
+        response.status_code = 404
+        raise CloudError(response=response, error='Resource Not found')
 
 
     def create_security_group_rule(self, security_group, rule_name, parameters):
     def create_security_group_rule(self, security_group, rule_name, parameters):
         new_sg_rule = SecurityRule(protocol='*', source_address_prefix='100', destination_address_prefix="*",
         new_sg_rule = SecurityRule(protocol='*', source_address_prefix='100', destination_address_prefix="*",
@@ -143,7 +149,7 @@ class MockAzureClient:
         for container in self.containers:
         for container in self.containers:
             if container.name == container_name:
             if container.name == container_name:
                 return container
                 return container
-        return None
+        raise AzureException()
 
 
     def list_containers(self):
     def list_containers(self):
         return self.containers
         return self.containers
@@ -167,7 +173,7 @@ class MockAzureClient:
         for blob in self.blocks.get(container_name):
         for blob in self.blocks.get(container_name):
             if blob.name == blob_name:
             if blob.name == blob_name:
                 return blob
                 return blob
-        return None
+        raise AzureException()
 
 
     def list_blobs(self, container_name):
     def list_blobs(self, container_name):
         return self.blocks.get(container_name)
         return self.blocks.get(container_name)
@@ -200,6 +206,7 @@ class MockAzureClient:
         volume.disk_size_gb = size
         volume.disk_size_gb = size
         volume.creation_data = CreationData(create_option=DiskCreateOption.empty)
         volume.creation_data = CreationData(create_option=DiskCreateOption.empty)
         volume.time_created = '01-01-2017'
         volume.time_created = '01-01-2017'
+        volume.provisioning_state = 'Succeeded'
         volume.owner_id = '/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/resourceGroups/CloudBridge-Azure/providers/Microsoft.Compute/virtualMachines/ubuntu-intro1'
         volume.owner_id = '/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/resourceGroups/CloudBridge-Azure/providers/Microsoft.Compute/virtualMachines/ubuntu-intro1'
         self.volumes.append(volume)
         self.volumes.append(volume)
         return volume
         return volume
@@ -208,14 +215,17 @@ class MockAzureClient:
         for volume in self.volumes:
         for volume in self.volumes:
             if volume.name == disk_name:
             if volume.name == disk_name:
                 return volume
                 return volume
-        return None
+        response = Response()
+        response.status_code = 404
+        raise CloudError(response=response, error='Resource Not found')
 
 
     def list_disks(self):
     def list_disks(self):
         return self.volumes
         return self.volumes
 
 
     def delete_disk(self, disk_name):
     def delete_disk(self, disk_name):
-        disk = self.get_disk(disk_name)
-        self.volumes.remove(disk)
+        for disk in self.volumes:
+            if disk.name == disk_name:
+                self.volumes.remove(disk)
 
 
         return True
         return True
 
 
@@ -224,3 +234,8 @@ class MockAzureClient:
 
 
     def detach_disk(self, disk_id):
     def detach_disk(self, disk_id):
         return None
         return None
+
+    def get_storage_account(self, storage_account_name):
+        storage_account = StorageAccount()
+        storage_account.name = storage_account_name
+        return storage_account

+ 15 - 1
cloudbridge/cloud/providers/azure/provider.py

@@ -1,6 +1,8 @@
 import logging
 import logging
 import os
 import os
 
 
+from msrestazure.azure_exceptions import CloudError
+
 from cloudbridge.cloud.base import BaseCloudProvider
 from cloudbridge.cloud.base import BaseCloudProvider
 from cloudbridge.cloud.interfaces import TestMockHelperMixin
 from cloudbridge.cloud.interfaces import TestMockHelperMixin
 
 
@@ -53,10 +55,22 @@ class AzureCloudProvider(BaseCloudProvider):
         self._azure_client = azureclient or AzureClient(self.allconfig)
         self._azure_client = azureclient or AzureClient(self.allconfig)
         try:
         try:
             rg = self._azure_client.get_resource_group(self.resource_group)
             rg = self._azure_client.get_resource_group(self.resource_group)
-        except:
+        except CloudError:
             resource_group_params = {'location': self.region_name}
             resource_group_params = {'location': self.region_name}
             self._azure_client.create_resource_group(self.resource_group, resource_group_params)
             self._azure_client.create_resource_group(self.resource_group, resource_group_params)
 
 
+        try:
+            storage_account = self._azure_client.get_storage_account(self.storage_account_name)
+        except CloudError:
+            storage_account_params = {
+                'sku': {
+                    'name': 'Standard_LRS'
+                },
+                'kind': 'storage',
+                'location': self.region_name,
+            }
+            self._azure_client.create_storage_account(self.storage_account_name, storage_account_params)
+
         self._security = AzureSecurityService(self)
         self._security = AzureSecurityService(self)
         self._object_store = AzureObjectStoreService(self)
         self._object_store = AzureObjectStoreService(self)
         self._block_store = AzureBlockStoreService(self)
         self._block_store = AzureBlockStoreService(self)

+ 86 - 49
cloudbridge/cloud/providers/azure/resources.py

@@ -7,7 +7,7 @@ from datetime import datetime
 
 
 from cloudbridge.cloud.providers.azure import helpers as azure_helpers
 from cloudbridge.cloud.providers.azure import helpers as azure_helpers
 
 
-from azure.common import AzureMissingResourceHttpError
+from azure.common import AzureMissingResourceHttpError, AzureException
 from msrestazure.azure_exceptions import CloudError
 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, \
@@ -47,22 +47,25 @@ NETWORK_INTERFACE_NAME ='networkInterfaceName'
 class AzureSecurityGroup(BaseSecurityGroup):
 class AzureSecurityGroup(BaseSecurityGroup):
     def __init__(self, provider, security_group):
     def __init__(self, provider, security_group):
         super(AzureSecurityGroup, self).__init__(provider, security_group)
         super(AzureSecurityGroup, self).__init__(provider, security_group)
+        self._description = None
 
 
     @property
     @property
     def network_id(self):
     def network_id(self):
         return self._security_group.resource_guid
         return self._security_group.resource_guid
 
 
+    @property
+    def description(self):
+        return self._description
+
+    @description.setter
+    def description(self, value):
+        self._description = value
+
     @property
     @property
     def rules(self):
     def rules(self):
         security_group_rules = []
         security_group_rules = []
-        for rule in self._security_group.default_security_rules:
-            if rule.direction == "Inbound":
-                sg_rule = AzureSecurityGroupRule(self._provider, rule, self)
-                sg_rule.is_default = True
-                security_group_rules.append(sg_rule)
         for custom_rule in self._security_group.security_rules:
         for custom_rule in self._security_group.security_rules:
             sg_custom_rule = AzureSecurityGroupRule(self._provider, custom_rule, self)
             sg_custom_rule = AzureSecurityGroupRule(self._provider, custom_rule, self)
-            sg_custom_rule.is_default = False
             security_group_rules.append(sg_custom_rule)
             security_group_rules.append(sg_custom_rule)
         return security_group_rules
         return security_group_rules
 
 
@@ -94,29 +97,37 @@ class AzureSecurityGroup(BaseSecurityGroup):
         :rtype: :class:``.SecurityGroupRule``
         :rtype: :class:``.SecurityGroupRule``
         :return: Rule object if successful or ``None``.
         :return: Rule object if successful or ``None``.
         """
         """
-        security_group = self._security_group.name
-        resource_group = self._provider.resource_group
-        count = len(self.rules) + 1
-        rule_name = "Rule - " + str(count)
-        priority = count * 100
-        destination_port_range = "*"
-        destination_address_prefix = "*"
-        access = "Allow"
-        direction = "Inbound"
-        parameters = {"protocol": ip_protocol, "source_port_range": str(from_port) + "-" + str(to_port),
-                      "destination_port_range": destination_port_range,"priority": priority,
-                      "source_address_prefix": cidr_ip, "destination_address_prefix": destination_address_prefix,
-                      "access": access, "direction": direction}
-        result = self._provider.azure_client.create_security_group_rule(security_group, rule_name, parameters)
-        self._security_group.security_rules.append(result)
-        return result
+
+        if not cidr_ip:
+            cidr_ip = '0.0.0.0/0'
+
+        rule = self.get_rule(ip_protocol, from_port, to_port, cidr_ip, src_group)
+        if not rule:
+            security_group = self._security_group.name
+            resource_group = self._provider.resource_group
+            count = len(self.rules) + 1
+            rule_name = "Rule - " + str(count)
+            priority = count * 100
+            destination_port_range = "*"
+            destination_address_prefix = "*"
+            access = "Allow"
+            direction = "Inbound"
+            parameters = {"protocol": ip_protocol, "source_port_range": str(from_port) + "-" + str(to_port),
+                          "destination_port_range": destination_port_range, "priority": priority,
+                          "source_address_prefix": cidr_ip, "destination_address_prefix": destination_address_prefix,
+                          "access": access, "direction": direction}
+            result = self._provider.azure_client.create_security_group_rule(security_group, rule_name, parameters)
+            self._security_group.security_rules.append(result)
+            return AzureSecurityGroupRule(self._provider, result, self)
+
+        return rule
 
 
     def get_rule(self, ip_protocol=None, from_port=None, to_port=None,
     def get_rule(self, ip_protocol=None, from_port=None, to_port=None,
                  cidr_ip=None, src_group=None):
                  cidr_ip=None, src_group=None):
         for rule in self.rules:
         for rule in self.rules:
             if (rule.ip_protocol == ip_protocol and
             if (rule.ip_protocol == ip_protocol and
-               rule.from_port == from_port and
-               rule.to_port == to_port and
+                        rule.from_port == str(from_port) and
+                        rule.to_port == str(to_port) and
                rule.cidr_ip == cidr_ip):
                rule.cidr_ip == cidr_ip):
                 return rule
                 return rule
         return None
         return None
@@ -170,7 +181,7 @@ class AzureSecurityGroupRule(BaseSecurityGroupRule):
 
 
     @property
     @property
     def group(self):
     def group(self):
-        return None
+        return self.parent
 
 
     def to_json(self):
     def to_json(self):
         attr = inspect.getmembers(self, lambda a: not(inspect.isroutine(a)))
         attr = inspect.getmembers(self, lambda a: not(inspect.isroutine(a)))
@@ -180,10 +191,7 @@ class AzureSecurityGroupRule(BaseSecurityGroupRule):
         return json.dumps(js, sort_keys=True)
         return json.dumps(js, sort_keys=True)
 
 
     def delete(self):
     def delete(self):
-        if self.is_default:
-            raise Exception('Default Security Rules cannot be deleted!')
         security_group = self.parent.name
         security_group = self.parent.name
-        resource_group = self._provider.resource_group
         sro = self._provider.azure_client.delete_security_group_rule(self.name, security_group)
         sro = self._provider.azure_client.delete_security_group_rule(self.name, security_group)
         for i, o in enumerate(self.parent._security_group.security_rules):
         for i, o in enumerate(self.parent._security_group.security_rules):
             if o.name == self.name:
             if o.name == self.name:
@@ -239,13 +247,21 @@ class AzureBucketObject(BaseBucketObject):
         Set the contents of this object to the data read from the source
         Set the contents of this object to the data read from the source
         string.
         string.
         """
         """
-        self._provider.azure_client.create_blob_from_text(self._container.name, self.name, data)
+        try:
+            self._provider.azure_client.create_blob_from_text(self._container.name, self.name, data)
+            return True
+        except AzureException:
+            return False
 
 
     def upload_from_file(self, path):
     def upload_from_file(self, path):
         """
         """
         Store the contents of the file pointed by the "path" variable.
         Store the contents of the file pointed by the "path" variable.
         """
         """
-        self._provider.azure_client.create_blob_from_file(self._container.name, self.name, path)
+        try:
+            self._provider.azure_client.create_blob_from_file(self._container.name, self.name, path)
+            return True
+        except AzureException:
+            return False
 
 
     def delete(self):
     def delete(self):
         """
         """
@@ -254,7 +270,11 @@ class AzureBucketObject(BaseBucketObject):
         :rtype: bool
         :rtype: bool
         :return: True if successful
         :return: True if successful
         """
         """
-        self._provider.azure_client.delete_blob(self._container.name, self.name)
+        try:
+            self._provider.azure_client.delete_blob(self._container.name, self.name)
+            return True
+        except AzureException:
+            return False
 
 
     def generate_url(self, expires_in=0):
     def generate_url(self, expires_in=0):
         """
         """
@@ -285,12 +305,9 @@ class AzureBucket(BaseBucket):
         Retrieve a given object from this bucket.
         Retrieve a given object from this bucket.
         """
         """
         try:
         try:
-            obj =self._provider.azure_client.get_blob(self.name, key)
-            if obj:
-                return AzureBucketObject(self._provider, self, obj)
-
-            return None
-        except AzureMissingResourceHttpError:
+            obj = self._provider.azure_client.get_blob(self.name, key)
+            return AzureBucketObject(self._provider, self, obj)
+        except AzureException:
             return None
             return None
 
 
     def list(self, limit=None, marker=None, prefix=None):
     def list(self, limit=None, marker=None, prefix=None):
@@ -309,7 +326,11 @@ class AzureBucket(BaseBucket):
         """
         """
         Delete this bucket.
         Delete this bucket.
         """
         """
-        self._provider.azure_client.delete_container(self.name)
+        try:
+            self._provider.azure_client.delete_container(self.name)
+            return True
+        except AzureException:
+            return False
 
 
     def create_object(self, name):
     def create_object(self, name):
         obj = self._provider.azure_client.create_blob_from_text(self.name, name,'')
         obj = self._provider.azure_client.create_blob_from_text(self.name, name,'')
@@ -329,6 +350,7 @@ class AzureVolume(BaseVolume):
         'Unattached': VolumeState.AVAILABLE,
         'Unattached': VolumeState.AVAILABLE,
         'Attached': VolumeState.IN_USE,
         'Attached': VolumeState.IN_USE,
         'Deleting': VolumeState.CONFIGURING,
         'Deleting': VolumeState.CONFIGURING,
+        'Updating': VolumeState.CONFIGURING,
         'Deleted': VolumeState.DELETED,
         'Deleted': VolumeState.DELETED,
         'Failed': VolumeState.ERROR
         'Failed': VolumeState.ERROR
     }
     }
@@ -338,6 +360,9 @@ class AzureVolume(BaseVolume):
         self._volume = volume
         self._volume = volume
         self._description = None
         self._description = None
         self._status = 'unknown'
         self._status = 'unknown'
+        self.update_status()
+
+    def update_status(self):
         if not self._volume.provisioning_state == 'Succeeded':
         if not self._volume.provisioning_state == 'Succeeded':
             self._status = self._volume.provisioning_state
             self._status = self._volume.provisioning_state
         elif self._volume.owner_id:
         elif self._volume.owner_id:
@@ -347,7 +372,7 @@ class AzureVolume(BaseVolume):
 
 
     @property
     @property
     def id(self):
     def id(self):
-        return self._volume.id
+        return self._volume.id.lower()
 
 
     @property
     @property
     def name(self):
     def name(self):
@@ -405,30 +430,41 @@ class AzureVolume(BaseVolume):
         """
         """
         Attach this volume to an instance.
         Attach this volume to an instance.
         """
         """
-        instance_id = instance.id if isinstance(
-            instance,
-            Instance) else instance
-        params = azure_helpers.parse_url(INSTANCE_RESOURCE_ID, instance_id)
-        self._provider.azure_client.attach_disk( params.get(VM_NAME),
-                                                self.id, self.name)
+        try:
+            instance_id = instance.id if isinstance(
+                instance,
+                Instance) else instance
+            params = azure_helpers.parse_url(INSTANCE_RESOURCE_ID, instance_id)
+            self._provider.azure_client.attach_disk(params.get(VM_NAME), self.name, self.id)
+            return True
+        except CloudError:
+            return False
 
 
     def detach(self, force=False):
     def detach(self, force=False):
         """
         """
         Detach this volume from an instance.
         Detach this volume from an instance.
         """
         """
-        self._provider.azure_client.detach_disk(self.id)
+        try:
+            self._provider.azure_client.detach_disk(self.id)
+            return True
+        except CloudError:
+            return False
 
 
     def create_snapshot(self, name, description=None):
     def create_snapshot(self, name, description=None):
         """
         """
         Create a snapshot of this Volume.
         Create a snapshot of this Volume.
         """
         """
-        return self._provider.block_store.snapshots.create(name, self.name)
+        return self._provider.block_store.snapshots.create(name, self.id)
 
 
     def delete(self):
     def delete(self):
         """
         """
         Delete this volume.
         Delete this volume.
         """
         """
-        self._provider.azure_client.delete_disk(self.name)
+        try:
+            self._provider.azure_client.delete_disk(self.name)
+            return True
+        except CloudError:
+            return False
 
 
     @property
     @property
     def state(self):
     def state(self):
@@ -442,6 +478,7 @@ class AzureVolume(BaseVolume):
         """
         """
         try:
         try:
             self._volume = self._provider.azure_client.get_disk(self.name)
             self._volume = self._provider.azure_client.get_disk(self.name)
+            self.update_status()
         except (CloudError, ValueError):
         except (CloudError, ValueError):
             # The volume no longer exists and cannot be refreshed.
             # The volume no longer exists and cannot be refreshed.
             # set the status to unknown
             # set the status to unknown

+ 33 - 16
cloudbridge/cloud/providers/azure/services.py

@@ -1,9 +1,9 @@
 import logging
 import logging
 
 
-from azure.common import AzureMissingResourceHttpError
+from azure.common import AzureMissingResourceHttpError, AzureException
 from msrestazure.azure_exceptions import CloudError
 from msrestazure.azure_exceptions import CloudError
 
 
-from cloudbridge.cloud.interfaces.resources import PlacementZone, Snapshot
+from cloudbridge.cloud.interfaces.resources import PlacementZone, Snapshot, Volume
 
 
 from .resources import SUBNET_RESOURCE_ID, NETWORK_NAME, SUBNET_NAME, NETWORK_RESOURCE_ID, \
 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, \
     INSTANCE_RESOURCE_ID, VM_NAME, IMAGE_RESOURCE_ID, RESOURCE_GROUP_NAME, IMAGE_NAME, SNAPSHOT_RESOURCE_ID, \
@@ -12,7 +12,7 @@ from .resources import SUBNET_RESOURCE_ID, NETWORK_NAME, SUBNET_NAME, NETWORK_RE
 
 
 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
+    BaseVolumeService, BaseBlockStoreService, BaseSnapshotService
 
 
 from cloudbridge.cloud.providers.azure import helpers as azure_helpers
 from cloudbridge.cloud.providers.azure import helpers as azure_helpers
 
 
@@ -58,13 +58,12 @@ class AzureSecurityGroupService(BaseSecurityGroupService):
         try:
         try:
             params = azure_helpers.parse_url(NETWORK_SECURITY_GROUP_RESOURCE_ID, sg_id)
             params = azure_helpers.parse_url(NETWORK_SECURITY_GROUP_RESOURCE_ID, sg_id)
             sgs = self.provider.azure_client.get_security_group(params.get(SECURITY_GROUP_NAME))
             sgs = self.provider.azure_client.get_security_group(params.get(SECURITY_GROUP_NAME))
-            return AzureSecurityGroup(self.provider, sgs) if sgs else None
+            return AzureSecurityGroup(self.provider, sgs)
 
 
         except CloudError as cloudError:
         except CloudError as cloudError:
             log.exception(cloudError.message)
             log.exception(cloudError.message)
             return None
             return None
 
 
-
     def list(self, limit=None, marker=None):
     def list(self, limit=None, marker=None):
         sgs = [AzureSecurityGroup(self.provider, sg)
         sgs = [AzureSecurityGroup(self.provider, sg)
                for sg in self.provider.azure_client.list_security_group()]
                for sg in self.provider.azure_client.list_security_group()]
@@ -73,7 +72,12 @@ class AzureSecurityGroupService(BaseSecurityGroupService):
     def create(self, name, description, network_id):
     def create(self, name, description, network_id):
         parameters = {"location": self.provider.region_name}
         parameters = {"location": self.provider.region_name}
         sg = self.provider.azure_client.create_security_group(name, parameters)
         sg = self.provider.azure_client.create_security_group(name, parameters)
-        return AzureSecurityGroup(self.provider, sg)
+        cb_sg = AzureSecurityGroup(self.provider, sg)
+
+        if description:
+            cb_sg.description = description
+
+        return cb_sg
 
 
     def find(self, name, limit=None, marker=None):
     def find(self, name, limit=None, marker=None):
         """
         """
@@ -102,11 +106,9 @@ class AzureObjectStoreService(BaseObjectStoreService):
         """
         """
         try:
         try:
             bucket = self.provider.azure_client.get_container(bucket_id)
             bucket = self.provider.azure_client.get_container(bucket_id)
-            if bucket:
-                return AzureBucket(self.provider, bucket)
-            else:
-                return None
-        except AzureMissingResourceHttpError as error:
+            return AzureBucket(self.provider, bucket)
+
+        except AzureException as error:
             log.exception(error)
             log.exception(error)
             return None
             return None
 
 
@@ -143,6 +145,7 @@ class AzureBlockStoreService(BaseBlockStoreService):
 
 
         # Initialize provider services
         # Initialize provider services
         self._volume_svc = AzureVolumeService(self.provider)
         self._volume_svc = AzureVolumeService(self.provider)
+        self._snapshot_svc = AzureSnapshotService(self.provider)
 
 
     @property
     @property
     def volumes(self):
     def volumes(self):
@@ -150,7 +153,7 @@ class AzureBlockStoreService(BaseBlockStoreService):
 
 
     @property
     @property
     def snapshots(self):
     def snapshots(self):
-        raise NotImplementedError('AzureBlockStoreService not implemented.')
+        return self._snapshot_svc
 
 
 
 
 class AzureVolumeService(BaseVolumeService):
 class AzureVolumeService(BaseVolumeService):
@@ -161,10 +164,7 @@ class AzureVolumeService(BaseVolumeService):
         try:
         try:
             params = azure_helpers.parse_url(VOLUME_RESOURCE_ID, volume_id)
             params = azure_helpers.parse_url(VOLUME_RESOURCE_ID, volume_id)
             volume = self.provider.azure_client.get_disk(params.get(VOLUME_NAME))
             volume = self.provider.azure_client.get_disk(params.get(VOLUME_NAME))
-            if volume:
-                return AzureVolume(self.provider, volume)
-
-            return None
+            return AzureVolume(self.provider, volume)
         except CloudError as cloudError:
         except CloudError as cloudError:
             log.exception(cloudError.message)
             log.exception(cloudError.message)
             return None
             return None
@@ -195,3 +195,20 @@ class AzureVolumeService(BaseVolumeService):
             cb_vol.description = description
             cb_vol.description = description
 
 
         return cb_vol
         return cb_vol
+
+
+class AzureSnapshotService(BaseSnapshotService):
+    def __init__(self, provider):
+        super(AzureSnapshotService, self).__init__(provider)
+
+    def get(self, ss_id):
+        raise NotImplementedError('AzureSnapShotService not implemented this method')
+
+    def find(self, name, limit=None, marker=None):
+        raise NotImplementedError('AzureSnapShotService not implemented this method')
+
+    def list(self, limit=None, marker=None):
+        raise NotImplementedError('AzureSnapShotService not implemented this method')
+
+    def create(self, name, volume, description=None):
+        raise NotImplementedError('AzureSnapShotService not implemented this method')

+ 2 - 0
integration_test/test_integration_azure_volume_service.py

@@ -20,6 +20,8 @@ class AzureIntegrationVolumeServiceTestCase(helpers.ProviderTestBase):
         print(str(len(volume_list_before_create)))
         print(str(len(volume_list_before_create)))
 
 
         volume = self.provider.block_store.volumes.create(volume_name, 1)
         volume = self.provider.block_store.volumes.create(volume_name, 1)
+        volume.wait_till_ready()
+        self.assertTrue(volume is not None, 'Volume not created')
         volume_id= volume.id
         volume_id= volume.id
 
 
         volume_list_after_create = self.provider.block_store.volumes.list()
         volume_list_after_create = self.provider.block_store.volumes.list()

+ 48 - 0
test/test_azure_helpers.py

@@ -0,0 +1,48 @@
+from test.helpers import ProviderTestBase
+from cloudbridge.cloud.providers.azure import helpers as azure_helpers
+
+
+class AzureHelpersTestCase(ProviderTestBase):
+    def __init__(self, methodName, provider):
+        super(AzureHelpersTestCase, self).__init__(
+            methodName=methodName, provider=provider)
+
+    def test_parse_url_valid(self):
+        params = azure_helpers.parse_url('/subscriptionId/{subscriptionId}', '/subscriptionId/123-1345')
+        self.assertTrue(len(params) == 1, 'Parameter count should be 1')
+
+    def test_parse_url_invalid(self):
+        with self.assertRaises(Exception):
+            params = azure_helpers.parse_url('/subscriptionId/{subscriptionId}', '/123-1345')
+
+    def test_filter_matched(self):
+        ex1 = Expando()
+        ex1.name = 'test'
+
+        ex2 = Expando()
+        ex2.name = 'abc'
+
+        result = azure_helpers.filter([ex1, ex2], {'name': 'test'})
+        self.assertTrue(len(result) == 1, 'Result count should be one')
+
+    def test_filter_not_matched(self):
+        ex1 = Expando()
+        ex1.name = 'pqr'
+
+        ex2 = Expando()
+        ex2.name = 'abc'
+        result = azure_helpers.filter([ex1, ex2], {'name': 'test123'})
+        self.assertTrue(len(result) == 0, 'Result count should be zero')
+
+    def test_filter_None(self):
+        ex1 = Expando()
+        ex1.name = 'pqr'
+
+        ex2 = Expando()
+        ex2.name = 'abc'
+        result = azure_helpers.filter([ex1, ex2], None)
+        self.assertTrue(len(result) == 2, 'Result count should be two')
+
+
+class Expando(object):
+    pass

+ 1 - 1
test/test_azure_object_store_service.py

@@ -58,7 +58,7 @@ class AzureObjectStoreServiceTestCase(ProviderTestBase):
         contDel = cont.delete()
         contDel = cont.delete()
         print("Bucket delete - " + str(contDel))
         print("Bucket delete - " + str(contDel))
         self.assertEqual(
         self.assertEqual(
-            contDel, None)
+            contDel, True)
 
 
     @helpers.skipIfNoService(['object_store'])
     @helpers.skipIfNoService(['object_store'])
     def test_azure_bucket_create_object(self):
     def test_azure_bucket_create_object(self):

+ 2 - 12
test/test_azure_security_service.py

@@ -96,23 +96,13 @@ class AzureSecurityServiceTestCase(ProviderTestBase):
         print("After deleting Rule -  " + str(rules[0]) + " length - " + str(len(rules)))
         print("After deleting Rule -  " + str(rules[0]) + " length - " + str(len(rules)))
         self.assertEqual(len(rules), 2)
         self.assertEqual(len(rules), 2)
 
 
-    @helpers.skipIfNoService(['security.security_groups'])
-    def test_azure_security_group_rule_delete_Default(self):
-        list = self.security_groups.list()
-        cb = list.data[0]
-        rules = cb.rules
-        print("Before deleting Rule -  " + str(rules[0]) + " length - " + str(len(rules)))
-
-        with self.assertRaises(Exception):
-            rules[0].delete()
-
     @helpers.skipIfNoService(['security.security_groups'])
     @helpers.skipIfNoService(['security.security_groups'])
     def test_azure_security_group_rule_get_exist(self):
     def test_azure_security_group_rule_get_exist(self):
         list = self.security_groups.list()
         list = self.security_groups.list()
         cb = list.data[0]
         cb = list.data[0]
         rule = cb.get_rule('*', '25', '1', '100')
         rule = cb.get_rule('*', '25', '1', '100')
         print("Get Rule -  " + str(rule))
         print("Get Rule -  " + str(rule))
-        self.assertEqual(str(rule), "<CBSecurityGroupRule: IP: *; from: 25; to: 1; grp: None>")
+        self.assertIsNotNone(rule)
 
 
     @helpers.skipIfNoService(['security.security_groups'])
     @helpers.skipIfNoService(['security.security_groups'])
     def test_azure_security_group_rule_get_notExist(self):
     def test_azure_security_group_rule_get_notExist(self):
@@ -128,7 +118,7 @@ class AzureSecurityServiceTestCase(ProviderTestBase):
         cb = list.data[0]
         cb = list.data[0]
         rule = cb.to_json()
         rule = cb.to_json()
         print("Get Rule -  " + str(rule))
         print("Get Rule -  " + str(rule))
-        self.assertEqual(rule[2:4], "id")
+        self.assertIsNotNone(rule)
 
 
     @helpers.skipIfNoService(['security.security_groups'])
     @helpers.skipIfNoService(['security.security_groups'])
     def test_azure_security_group_rule_to_json(self):
     def test_azure_security_group_rule_to_json(self):

+ 4 - 2
test/test_azure_volume_service.py

@@ -24,7 +24,7 @@ class AzureVolumeServiceTestCase(ProviderTestBase):
 
 
     @helpers.skipIfNoService(['block_store.volumes'])
     @helpers.skipIfNoService(['block_store.volumes'])
     def test_azure_volume_delete(self):
     def test_azure_volume_delete(self):
-        volume = self.provider.block_store.volumes.create("MyVolume", 1, description='My volume')
+        volume = self.provider.block_store.volumes.create("MyVolume", 1)
         volume.refresh()
         volume.refresh()
         print("Create Volume - " + str(volume))
         print("Create Volume - " + str(volume))
         self.assertTrue(
         self.assertTrue(
@@ -56,7 +56,9 @@ class AzureVolumeServiceTestCase(ProviderTestBase):
         self.assertTrue(
         self.assertTrue(
             volume.name == "MyVolume", "Volume name should be MyVolume")
             volume.name == "MyVolume", "Volume name should be MyVolume")
         with self.assertRaises(NotImplementedError):
         with self.assertRaises(NotImplementedError):
-            volume.create_snapshot('MySnap')
+            snapshot = volume.create_snapshot("MySnap")
+            self.assertTrue(
+                snapshot is not None, "Snapshot not created")
 
 
         volume.delete()
         volume.delete()