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

Implemented create and delete subnet methods

vikramdoda 9 лет назад
Родитель
Сommit
7ad4c52d5a

+ 4 - 0
azure_test/test_azure_image_service.py

@@ -19,6 +19,10 @@ class AzureImageServiceTestCase(ProviderTestBase):
         print(str(image_get.min_disk))
         print(str(image_get.state))
         self.assertIsNone(image_get.description)
+        image_get.name = 'newname'
+        self.assertEqual(image_get.name, 'newname')
+        image_get.description = 'newdesc'
+        self.assertEqual(image_get.description, 'newdesc')
         image_get.refresh()
         image_get.delete()
         image_get.refresh()

+ 5 - 0
azure_test/test_azure_instance_type_service.py

@@ -24,3 +24,8 @@ class AzureInstanceTypeServiceTestCase(ProviderTestBase):
         print("Extra data - " +
               str(instance_type_list[0].extra_data))
         self.assertTrue(instance_type_list.total_results > 0)
+
+        # Test find
+        inst_type = self.provider.compute. \
+            instance_types.find(name="Standard_DS1_v2")[0]
+        print(str(inst_type))

+ 47 - 12
azure_test/test_azure_network_service.py

@@ -1,5 +1,5 @@
-import test.helpers as helpers
-from test.helpers import ProviderTestBase
+import azure_test.helpers as helpers
+from azure_test.helpers import ProviderTestBase
 
 
 class AzureNetworkServiceTestCase(ProviderTestBase):
@@ -27,7 +27,7 @@ class AzureNetworkServiceTestCase(ProviderTestBase):
                          '/Microsoft.Network/virtualNetworks/CloudBridgeNet1')
         self.assertEqual(networks[0].name, "CloudBridgeNet1")
         self.assertEqual(networks[0].cidr_block,
-                         "{'address_prefixes': ['10.0.0.0/16']}")
+                         '10.0.0.0/16')
         self.assertEqual(networks[0].state, "available")
         self.assertEqual(networks[1].id,
                          '/subscriptions'
@@ -36,7 +36,7 @@ class AzureNetworkServiceTestCase(ProviderTestBase):
                          '/Microsoft.Network/virtualNetworks/CloudBridgeNet2')
         self.assertEqual(networks[1].name, "CloudBridgeNet2")
         self.assertEqual(networks[1].cidr_block,
-                         "{'address_prefixes': ['10.0.0.0/16']}")
+                         '10.0.0.0/16')
         self.assertEqual(networks[1].state, "unknown")
 
     @helpers.skipIfNoService(['network'])
@@ -53,7 +53,7 @@ class AzureNetworkServiceTestCase(ProviderTestBase):
                          '/Microsoft.Network/virtualNetworks/CloudBridgeNet1')
         self.assertEqual(network.name, "CloudBridgeNet1")
         self.assertEqual(network.cidr_block,
-                         "{'address_prefixes': ['10.0.0.0/16']}")
+                         '10.0.0.0/16')
         self.assertEqual(network.state, "available")
 
     @helpers.skipIfNoService(['network'])
@@ -78,16 +78,21 @@ class AzureNetworkServiceTestCase(ProviderTestBase):
     @helpers.skipIfNoService(['network'])
     def test_azure_network_service_create(self):
         network = self.provider.network.create("CloudBridgeNet1")
+        network.refresh()
         print("create: " + str(network))
-        self.assertEqual(network.id,
-                         '/subscriptions'
-                         '/7904d702-e01c-4826-8519-f5a25c866a96'
-                         '/resourceGroups/CLOUDBRIDGE-AZURE/providers'
-                         '/Microsoft.Network/virtualNetworks/CloudBridgeNet1')
+        self.assertIsNotNone(network.id)
         self.assertEqual(network.name, "CloudBridgeNet1")
         self.assertEqual(network.cidr_block,
-                         "{'address_prefixes': ['10.0.0.0/16']}")
+                         '10.0.0.0/16')
         self.assertEqual(network.state, "available")
+        self.assertTrue(network.external)
+        network.name = 'newname'
+        self.assertEqual(network.name, 'newname')
+        deleted = network.delete()
+        self.assertTrue(deleted)
+        deleted = network.delete()
+        self.assertFalse(deleted)
+        network.refresh()
 
     @helpers.skipIfNoService(['network'])
     def test_azure_network_service_delete_networkid_exists(self):
@@ -117,7 +122,7 @@ class AzureNetworkServiceTestCase(ProviderTestBase):
             '/Microsoft.Network/virtualNetworks/CloudBridgeNet10')
 
         print("Delete Network Id does not exist: " + str(isdeleted))
-        self.assertEqual(isdeleted, True)
+        self.assertEqual(isdeleted, False)
 
     @helpers.skipIfNoService(['network'])
     def test_azure_network_service_delete_with_invaid_networkid_throws(self):
@@ -127,3 +132,33 @@ class AzureNetworkServiceTestCase(ProviderTestBase):
             print("Delete with invalid network id: " + str(isdeleted))
             self.assertTrue(
                 'Invalid url parameter passed' in context.exception)
+
+    @helpers.skipIfNoService(['network'])
+    def test_network_methods(self):
+        with self.assertRaises(NotImplementedError):
+            floating_ips = self.provider.network.floating_ips()
+            self.assertIsNotNone(floating_ips)
+
+        with self.assertRaises(NotImplementedError):
+            floating_ip = self.provider.network.create_floating_ip()
+            self.assertIsNotNone(floating_ip)
+
+        with self.assertRaises(NotImplementedError):
+            routers = self.provider.network.routers()
+            self.assertIsNotNone(routers)
+
+        with self.assertRaises(NotImplementedError):
+            router = self.provider.network.create_router()
+            self.assertIsNotNone(router)
+
+    def test_network_create_and_list_subnet(self):
+        network = self.provider.network \
+            .get('/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96'
+                 '/resourceGroups/CLOUDBRIDGE-AZURE/providers'
+                 '/Microsoft.Network/virtualNetworks/CloudBridgeNet1')
+
+        subnet = network.create_subnet('10.0.0.0/24')
+        self.assertIsNotNone(subnet)
+        subnets = network.subnets()
+        self.assertTrue(len(subnets) > 0)
+        subnet.delete()

+ 3 - 3
azure_test/test_azure_snapshots_service.py

@@ -9,7 +9,7 @@ class AzureSnapshotsServiceTestCase(ProviderTestBase):
     def test_azure_snapshot_create_and_get(self):
         volume_id = "/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96'\
             '/resourceGroups/cloudbridge-azure'\
-            '/providers/Microsoft.Compute/disks/MySnapshotDisk123"
+            '/providers/Microsoft.Compute/disks/Volume1"
         snapshot = self.provider.block_store. \
             snapshots.create("MySnapshot",
                              volume_id)
@@ -36,7 +36,7 @@ class AzureSnapshotsServiceTestCase(ProviderTestBase):
     def test_azure_snapshot_delete(self):
         volume_id = "/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96'\
             '/resourceGroups/cloudbridge-azure'\
-            '/providers/Microsoft.Compute/disks/MyDisk"
+            '/providers/Microsoft.Compute/disks/Volume1"
         snapshot = self.provider.block_store. \
             snapshots.create("MySnapshot",
                              volume_id, description='My snapshot')
@@ -64,7 +64,7 @@ class AzureSnapshotsServiceTestCase(ProviderTestBase):
     def test_azure_snapshot_create_volume(self):
         volume_id = "/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96'\
             '/resourceGroups/cloudbridge-azure'\
-            '/providers/Microsoft.Compute/disks/MyDisk"
+            '/providers/Microsoft.Compute/disks/Volume1"
         snapshot = self.provider.block_store. \
             snapshots.create("MySnapshot",
                              volume_id,

+ 42 - 3
azure_test/test_azure_subnet_service.py

@@ -14,7 +14,7 @@ class AzureSubnetServiceTestCase(ProviderTestBase):
     def test_azure_subnet_service_list_filter_network_id(self):
         network_id = '/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/' \
                      'resourceGroups/CloudBridge-Azure/providers/' \
-                     'Microsoft.Network/virtualNetworks/CloudBridgeNet'
+                     'Microsoft.Network/virtualNetworks/CloudBridgeNet2'
         subnets = self.provider.network.subnets.list(network_id)
         self.assertIsNotNone(subnets)
         for subnet in subnets:
@@ -26,7 +26,7 @@ class AzureSubnetServiceTestCase(ProviderTestBase):
     def test_azure_subnet_service_list_filter_network_object(self):
         network_id = '/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/' \
                      'resourceGroups/CloudBridge-Azure/providers/' \
-                     'Microsoft.Network/virtualNetworks/CloudBridgeNet'
+                     'Microsoft.Network/virtualNetworks/CloudBridgeNet2'
         network = self.provider.network.get(network_id)
         subnets = self.provider.network.subnets.list(network)
         self.assertIsNotNone(subnets)
@@ -40,7 +40,7 @@ class AzureSubnetServiceTestCase(ProviderTestBase):
         subnet_id = '/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/' \
                     'resourceGroups/CloudBridge-Azure/providers/' \
                     'Microsoft.Network/virtualNetworks/' \
-                    'CloudBridgeNet/subnets/MySN1'
+                    'CloudBridgeNet2/subnets/MySN1'
         subnet = self.provider.network.subnets.get(subnet_id)
         self.assertIsNotNone(subnet)
         if subnet:
@@ -57,3 +57,42 @@ class AzureSubnetServiceTestCase(ProviderTestBase):
                     'CloudBridgeNet/subnets/MySN'
         subnet = self.provider.network.subnets.get(subnet_id)
         self.assertIsNone(subnet)
+
+    def test_azure_create_and_delete_from_resource_subnet(self):
+        network_id = '/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/' \
+                    'resourceGroups/CloudBridge-Azure/providers/' \
+                    'Microsoft.Network/virtualNetworks/' \
+                    'CloudBridgeNet2'
+        subnet = self.provider.network.\
+            subnets.create(network=network_id,
+                           cidr_block='10.0.0.0/24')
+        self.assertIsNotNone(subnet.zone)
+        self.assertIsNotNone(subnet)
+        deleted = subnet.delete()
+        self.assertTrue(deleted)
+        deleted = subnet.delete()
+        self.assertFalse(deleted)
+
+    def test_azure_create_and_delete_from_service_subnet(self):
+        network_id = '/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/' \
+                    'resourceGroups/CloudBridge-Azure/providers/' \
+                    'Microsoft.Network/virtualNetworks/' \
+                    'CloudBridgeNet2'
+        subnet = self.provider.network.\
+            subnets.create(network=network_id,
+                           name='test', cidr_block='10.0.0.0/24')
+        self.assertIsNotNone(subnet)
+        deleted = self.provider.network.subnets.delete(subnet)
+        self.assertTrue(deleted)
+        deleted = self.provider.network.subnets.delete(subnet)
+        self.assertFalse(deleted)
+
+    def test_azure_create_or_get_default_subnet(self):
+        subnet = self.provider.network.\
+            subnets.get_or_create_default()
+        self.assertIsNotNone(subnet)
+        subnet = self.provider.network. \
+            subnets.get_or_create_default()
+        self.assertIsNotNone(subnet)
+        subnet.delete()
+        self.provider.network.delete(subnet.network_id)

+ 39 - 4
cloudbridge/cloud/providers/azure/azure_client.py

@@ -228,6 +228,14 @@ class AzureClient(object):
         return self.network_management_client.virtual_networks. \
             delete(self.resource_group_name, network_name).wait()
 
+    def update_network_tags(self, network_name, tags):
+        return self.network_management_client.virtual_networks. \
+            create_or_update(self.resource_group_name,
+                             network_name,
+                             {
+                                 'tags': tags
+                             })
+
     def list_disks(self):
         return self.compute_client.disks. \
             list_by_resource_group(self.resource_group_name)
@@ -265,11 +273,12 @@ class AzureClient(object):
     def get_vm(self, vm_name):
         return self.compute_client.virtual_machines.get(
             self.resource_group_name,
-            vm_name
+            vm_name,
+            expand='instanceView'
         )
 
     def create_or_update_vm(self, vm_name, params):
-        return self.compute_client\
+        return self.compute_client \
             .virtual_machines.create_or_update(
                 self.resource_group_name,
                 vm_name,
@@ -278,11 +287,11 @@ class AzureClient(object):
             )
 
     def list_vm(self):
-        return self.compute_client.\
+        return self.compute_client. \
             virtual_machines.list(self.resource_group_name)
 
     def delete_image(self, name):
-        self.compute_client.images.\
+        self.compute_client.images. \
             delete(self.resource_group_name, name).wait()
 
     def list_images(self):
@@ -300,6 +309,10 @@ class AzureClient(object):
                                  'tags': tags
                              }).result()
 
+    def list_instance_types(self):
+        return self.compute_client.virtual_machine_sizes. \
+            list(self.region_name)
+
     def list_subnets(self, network_name):
         return self.network_management_client.subnets.\
             list(self.resource_group_name, network_name)
@@ -307,3 +320,25 @@ class AzureClient(object):
     def get_subnet(self, network_name, subnet_name):
         return self.network_management_client.subnets.\
             get(self.resource_group_name, network_name, subnet_name)
+
+    def create_subnet(self, network_name,
+                      subnet_name, params):
+        result_create = self.network_management_client \
+            .subnets.create_or_update(
+                self.resource_group_name,
+                network_name,
+                subnet_name,
+                params
+            )
+        subnet_info = result_create.result()
+
+        return subnet_info
+
+    def delete_subnet(self, network_name, subnet_name):
+        result_delete = self.network_management_client \
+            .subnets.delete(
+                self.resource_group_name,
+                network_name,
+                subnet_name
+            )
+        result_delete.wait()

+ 50 - 23
cloudbridge/cloud/providers/azure/mock_azure_client.py

@@ -9,7 +9,7 @@ from azure.mgmt.compute.models import CreationData, DataDisk, \
     Snapshot, StorageProfile, VirtualMachine, \
     VirtualMachineSize
 
-from azure.mgmt.network.models import NetworkSecurityGroup
+from azure.mgmt.network.models import AddressSpace, NetworkSecurityGroup
 from azure.mgmt.network.models import SecurityRule
 from azure.mgmt.network.models import Subnet, VirtualNetwork
 from azure.mgmt.resource.resources.models import ResourceGroup
@@ -99,7 +99,9 @@ class MockAzureClient:
                   '/resourceGroups/CLOUDBRIDGE-AZURE/providers' \
                   '/Microsoft.Network/virtualNetworks/CloudBridgeNet1'
     network1.name = "CloudBridgeNet1"
-    network1.address_space = "{'address_prefixes': ['10.0.0.0/16']}"
+    network1.location = 'eastus'
+    network1.address_space = AddressSpace()
+    network1.address_space.address_prefixes = ['10.0.0.0/16']
     network1.provisioning_state = "Succeeded"
 
     network2 = VirtualNetwork()
@@ -107,7 +109,9 @@ class MockAzureClient:
                   '/resourceGroups/CLOUDBRIDGE-AZURE/providers' \
                   '/Microsoft.Network/virtualNetworks/CloudBridgeNet2'
     network2.name = "CloudBridgeNet2"
-    network2.address_space = "{'address_prefixes': ['10.0.0.0/16']}"
+    network2.location = 'eastus'
+    network2.address_space = AddressSpace()
+    network2.address_space.address_prefixes = ['10.0.0.0/16']
     network2.provisioning_state = "Failed"
 
     network3 = VirtualNetwork()
@@ -115,7 +119,9 @@ class MockAzureClient:
                   '/resourceGroups/CLOUDBRIDGE-AZURE/providers' \
                   '/Microsoft.Network/virtualNetworks/CloudBridgeNet3'
     network3.name = "CloudBridgeNet3"
-    network3.address_space = "{'address_prefixes': ['10.0.0.0/16']}"
+    network3.location = 'eastus'
+    network3.address_space = AddressSpace()
+    network3.address_space.address_prefixes = ['10.0.0.0/16']
     network3.provisioning_state = "Succeeded"
 
     networks = [network1, network2, network3]
@@ -246,7 +252,7 @@ class MockAzureClient:
     subnets = [subnet1, subnet2]
 
     instance_type1 = VirtualMachineSize()
-    instance_type1.name = "instance_type1"
+    instance_type1.name = "Standard_DS1_v1"
     instance_type1.number_of_cores = 1
     instance_type1.os_disk_size_in_mb = 100
     instance_type1.resource_disk_size_in_mb = 100
@@ -254,7 +260,7 @@ class MockAzureClient:
     instance_type1.max_data_disk_count = 1
 
     instance_type2 = VirtualMachineSize()
-    instance_type2.name = "instance_type2"
+    instance_type2.name = "Standard_DS1_v2"
     instance_type2.number_of_cores = 2
     instance_type2.os_disk_size_in_mb = 200
     instance_type2.resource_disk_size_in_mb = 200
@@ -289,11 +295,8 @@ class MockAzureClient:
         return self.security_groups
 
     def delete_security_group(self, name):
-        for item in self.security_groups:
-            if item.name == name:
-                self.security_groups.remove(item)
-                return True
-        return False
+        sg = self.get_security_group(name)
+        self.security_groups.remove(sg)
 
     def get_security_group(self, name):
         for item in self.security_groups:
@@ -334,21 +337,30 @@ class MockAzureClient:
         for network in self.networks:
             if network.name == network_name:
                 return network
-        return None
 
-    def create_network(self, name, region=None):
-        for network in self.networks:
-            if network.name == name:
-                return network
+        response = Response()
+        response.status_code = 404
+        raise CloudError(response=response, error='Resource not found')
+
+    def create_network(self, name, params):
+        network = VirtualNetwork()
+        network.id = '/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96' \
+                     '/resourceGroups/CLOUDBRIDGE-AZURE/providers' \
+                     '/Microsoft.Network/virtualNetworks/{0}'.\
+            format(name)
+        network.name = name
+        network.address_space = AddressSpace()
+        network.address_space.address_prefixes = ['10.0.0.0/16']
+        network.provisioning_state = "Succeeded"
+        network.tags = params['tags']
+        self.networks.append(network)
+
+    def update_network_tags(self, name, tags):
+        pass
 
     def delete_network(self, network_name):
-        # Delete network method always returns True
-        # for both the scenarios if network exist or not
-        for network in self.networks:
-            if network.name == network_name:
-                self.networks.remove(network)
-
-        return True
+        network = self.get_network(network_name)
+        self.networks.remove(network)
 
     def create_resource_group(self, resource_group_name, params):
         rg = ResourceGroup(location='westus')
@@ -601,3 +613,18 @@ class MockAzureClient:
         response = Response()
         response.status_code = 404
         raise CloudError(response=response, error='Resource Not found')
+
+    def create_subnet(self, network_name, subnet_name, params):
+        subnet = Subnet()
+        subnet.id = '/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/' \
+                    'resourceGroups/CloudBridge-Azure/providers/' \
+                    'Microsoft.Network/virtualNetworks/{0}/' \
+                    'subnets/{1}'.format(network_name, subnet_name)
+        subnet.name = subnet_name
+        subnet.address_prefix = '10.0.0.0/25'
+        self.subnets.append(subnet)
+        return subnet
+
+    def delete_subnet(self, network_name, subnet_name):
+        subnet = self.get_subnet(network_name, subnet_name)
+        self.subnets.remove(subnet)

+ 57 - 33
cloudbridge/cloud/providers/azure/resources.py

@@ -7,10 +7,11 @@ import json
 from azure.common import AzureException
 
 from cloudbridge.cloud.base.resources import BaseAttachmentInfo, \
-    BaseBucket, BaseBucketObject, BaseInstanceType,\
+    BaseBucket, BaseBucketObject, BaseInstanceType, \
     BaseMachineImage, BaseNetwork, \
-    BasePlacementZone, BaseRegion, BaseSecurityGroup, BaseSecurityGroupRule, \
-    BaseSnapshot, BaseSubnet, BaseVolume, ClientPagedResultList
+    BasePlacementZone, BaseRegion, \
+    BaseSecurityGroup, BaseSecurityGroupRule, BaseSnapshot, BaseSubnet, \
+    BaseVolume, ClientPagedResultList
 from cloudbridge.cloud.interfaces import VolumeState
 from cloudbridge.cloud.interfaces.resources import Instance, \
     MachineImageState, NetworkState, SnapshotState
@@ -111,7 +112,7 @@ class AzureSecurityGroup(BaseSecurityGroup):
     @description.setter
     def description(self, value):
         self._security_group.tags.update(Description=value)
-        self._provider.azure_client. \
+        self._provider.azure_client.\
             update_security_group_tags(self.resource_name,
                                        self._security_group.tags)
 
@@ -124,6 +125,14 @@ class AzureSecurityGroup(BaseSecurityGroup):
             security_group_rules.append(sg_custom_rule)
         return security_group_rules
 
+    def delete(self):
+        try:
+            self._provider.azure_client.\
+                delete_security_group(self.resource_name)
+            return True
+        except CloudError:
+            return False
+
     def add_rule(self, ip_protocol=None, from_port=None, to_port=None,
                  cidr_ip=None, src_group=None):
         """
@@ -421,7 +430,8 @@ class AzureVolume(BaseVolume):
         'Deleting': VolumeState.CONFIGURING,
         'Updating': VolumeState.CONFIGURING,
         'Deleted': VolumeState.DELETED,
-        'Failed': VolumeState.ERROR
+        'Failed': VolumeState.ERROR,
+        'Canceled': VolumeState.ERROR
     }
 
     def __init__(self, provider, volume):
@@ -591,6 +601,8 @@ class AzureVolume(BaseVolume):
         try:
             self._volume = self._provider.azure_client. \
                 get_disk(self.resource_name)
+            if not self._volume.tags:
+                self._volume.tags = {}
             self.update_status()
         except (CloudError, ValueError):
             # The volume no longer exists and cannot be refreshed.
@@ -603,6 +615,7 @@ class AzureSnapshot(BaseSnapshot):
         'InProgress': SnapshotState.PENDING,
         'Succeeded': SnapshotState.AVAILABLE,
         'Failed': SnapshotState.ERROR,
+        'Canceled': SnapshotState.ERROR,
         'Updating': SnapshotState.CONFIGURING,
         'Deleting': SnapshotState.CONFIGURING,
         'Deleted': SnapshotState.UNKNOWN
@@ -683,6 +696,8 @@ class AzureSnapshot(BaseSnapshot):
         try:
             self._snapshot = self._provider.azure_client. \
                 get_snapshot(self.resource_name)
+            if not self._snapshot.tags:
+                self._snapshot.tags = {}
             self._status = self._snapshot.provisioning_state
         except (CloudError, ValueError):
             # The snapshot no longer exists and cannot be refreshed.
@@ -808,6 +823,8 @@ class AzureMachineImage(BaseMachineImage):
         try:
             self._image = self._provider.azure_client\
                 .get_image(self.resource_name)
+            if not self._image.tags:
+                self._image.tags = {}
             self._state = self._image.provisioning_state
         except CloudError:
             # image no longer exists
@@ -824,6 +841,8 @@ class AzureNetwork(BaseNetwork):
         super(AzureNetwork, self).__init__(provider)
         self._network = network
         self._state = self._network.provisioning_state
+        if not self._network.tags:
+            self._network.tags = {}
 
     @property
     def id(self):
@@ -836,6 +855,10 @@ class AzureNetwork(BaseNetwork):
 
         .. note:: the network must have a (case sensitive) tag ``Name``
         """
+        return self._network.tags.get('Name', self._network.name)
+
+    @property
+    def resource_name(self):
         return self._network.name
 
     @name.setter
@@ -844,7 +867,9 @@ class AzureNetwork(BaseNetwork):
         """
         Set the network name.
         """
-        self._network.name = value
+        self._network.tags.update(Name=value)
+        self._provider.azure_client.\
+            update_network_tags(self.resource_name, self._network.tags)
 
     @property
     def external(self):
@@ -865,7 +890,10 @@ class AzureNetwork(BaseNetwork):
         for its latest state.
         """
         try:
-            self._network = self._provider.azure_client.get_network(self.name)
+            self._network = self._provider.azure_client.\
+                get_network(self.resource_name)
+            if not self._network.tags:
+                self._network.tags = {}
             self._state = self._network.provisioning_state
         except (CloudError, ValueError):
             # The network no longer exists and cannot be refreshed.
@@ -874,25 +902,25 @@ class AzureNetwork(BaseNetwork):
 
     @property
     def cidr_block(self):
-        return self._network.address_space
+        return self._network.address_space.address_prefixes[0]
 
     def delete(self):
         """
         Delete an existing network.
         """
         try:
-            network = self._provider.azure_client.delete_network(self.name)
-            return True if network else False
+            self._provider.azure_client.\
+                delete_network(self.resource_name)
+            return True
         except CloudError:
             return False
 
     def subnets(self):
-        raise NotImplementedError('AzureNetworkService '
-                                  'not implemented this property')
+        return self._provider.network.subnets.list(network=self.id)
 
     def create_subnet(self, cidr_block, name=None, zone=None):
-        raise NotImplementedError('AzureNetworkService '
-                                  'not implemented this property')
+        return self._provider.network.subnets.\
+            create(network=self.id, cidr_block=cidr_block, name=name)
 
 
 class AzureRegion(BaseRegion):
@@ -964,6 +992,10 @@ class AzureSubnet(BaseSubnet):
     def __init__(self, provider, subnet):
         super(AzureSubnet, self).__init__(provider)
         self._subnet = subnet
+        self._url_params = azure_helpers\
+            .parse_url(SUBNET_RESOURCE_ID, subnet.id)
+        self._network = self._provider.azure_client.\
+            get_network(self._url_params.get(NETWORK_NAME))
 
     @property
     def id(self):
@@ -978,13 +1010,9 @@ class AzureSubnet(BaseSubnet):
         """
         return self._subnet.name
 
-    @name.setter
-    # pylint:disable=arguments-differ
-    def name(self, value):
-        """
-        Set the network name.
-        """
-        self._subnet.name = value
+    @property
+    def zone(self):
+        return self._network.location
 
     @property
     def cidr_block(self):
@@ -992,20 +1020,16 @@ class AzureSubnet(BaseSubnet):
 
     @property
     def network_id(self):
-        params = azure_helpers.parse_url(SUBNET_RESOURCE_ID, self._subnet.id)
-        networkname = params.get(NETWORK_NAME)
-        network = self._provider.azure_client.get_network(networkname)
-        if network:
-            return network.id
-        else:
-            return None
-
-    @property
-    def zone(self):
-        return self._provider.compute.regions.current.zones[0]
+        return self._network.id
 
     def delete(self):
-        return None
+        try:
+            self._provider.azure_client.\
+                delete_subnet(self._url_params.get(NETWORK_NAME),
+                              self._url_params.get(SUBNET_NAME))
+            return True
+        except CloudError as cloudError:
+            return False
 
 
 class AzureInstanceType(BaseInstanceType):

+ 118 - 59
cloudbridge/cloud/providers/azure/services.py

@@ -6,22 +6,23 @@ from azure.common import AzureException
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.services import BaseBlockStoreService, \
     BaseComputeService, BaseImageService, BaseInstanceTypesService, \
-    BaseNetworkService, BaseObjectStoreService, BaseRegionService, \
-    BaseSecurityGroupService, BaseSecurityService, \
-    BaseSnapshotService, BaseSubnetService, BaseVolumeService
-from cloudbridge.cloud.interfaces.resources import PlacementZone, \
-    Snapshot, Volume
+    BaseNetworkService, \
+    BaseObjectStoreService, BaseRegionService, \
+    BaseSecurityGroupService, \
+    BaseSecurityService, BaseSnapshotService, \
+    BaseSubnetService, BaseVolumeService
+from cloudbridge.cloud.interfaces.resources import Network,\
+    PlacementZone, Snapshot, Subnet, Volume
 from cloudbridge.cloud.providers.azure import helpers as azure_helpers
 
 from msrestazure.azure_exceptions import CloudError
-from .resources import AzureBucket, \
-    AzureInstanceType, AzureMachineImage, \
-    AzureNetwork, AzureRegion, \
-    AzureSecurityGroup, \
+
+from .resources import AzureBucket, AzureInstanceType, \
+    AzureMachineImage, \
+    AzureNetwork, AzureRegion, AzureSecurityGroup, \
     AzureSnapshot, AzureSubnet, AzureVolume, \
-    IMAGE_NAME, IMAGE_RESOURCE_ID, \
-    NETWORK_NAME, NETWORK_RESOURCE_ID, \
-    NETWORK_SECURITY_GROUP_RESOURCE_ID, \
+    IMAGE_NAME, IMAGE_RESOURCE_ID, NETWORK_NAME, \
+    NETWORK_RESOURCE_ID, NETWORK_SECURITY_GROUP_RESOURCE_ID, \
     SECURITY_GROUP_NAME, SNAPSHOT_NAME, \
     SNAPSHOT_RESOURCE_ID, SUBNET_NAME, SUBNET_RESOURCE_ID, \
     VOLUME_NAME, VOLUME_RESOURCE_ID
@@ -105,10 +106,16 @@ class AzureSecurityGroupService(BaseSecurityGroupService):
                                      limit=limit, marker=marker)
 
     def delete(self, group_id):
-        params = azure_helpers.parse_url(NETWORK_SECURITY_GROUP_RESOURCE_ID,
-                                         group_id)
-        return self.provider.azure_client.delete_security_group(
-            params.get(SECURITY_GROUP_NAME))
+        try:
+            params = azure_helpers.\
+                parse_url(NETWORK_SECURITY_GROUP_RESOURCE_ID,
+                          group_id)
+            self.provider.azure_client.delete_security_group(
+                params.get(SECURITY_GROUP_NAME))
+            return True
+        except CloudError as cloudError:
+            log.exception(cloudError.message)
+            return False
 
 
 class AzureObjectStoreService(BaseObjectStoreService):
@@ -271,12 +278,13 @@ class AzureSnapshotService(BaseSnapshotService):
         """
         snaps = [AzureSnapshot(self.provider, obj)
                  for obj in
-                 self.provider.
-                 azure_client.list_snapshots()]
+                 self.provider.azure_client.list_snapshots()]
         return ClientPagedResultList(self.provider, snaps, limit, marker)
 
     def create(self, name, volume, description=None):
         volume_id = volume.id if isinstance(volume, Volume) else volume
+        disk_size = volume.size if isinstance(volume, Volume) else \
+            self.provider.block_store.volumes.get(volume_id).size
 
         tags = {'Name': name}
         snapshot_name = "{0}-{1}".format(name, uuid.uuid4().hex[:6])
@@ -290,6 +298,7 @@ class AzureSnapshotService(BaseSnapshotService):
                 'create_option': 'Copy',
                 'source_uri': volume_id
             },
+            'disk_size_gb': disk_size,
             'tags': tags
         }
 
@@ -391,7 +400,7 @@ class AzureNetworkService(BaseNetworkService):
             params = azure_helpers.parse_url(NETWORK_RESOURCE_ID, network_id)
             network = self.provider.azure_client. \
                 get_network(params.get(NETWORK_NAME))
-            return AzureNetwork(self.provider, network) if network else None
+            return AzureNetwork(self.provider, network)
 
         except CloudError as cloudError:
             log.exception(cloudError.message)
@@ -407,19 +416,20 @@ class AzureNetworkService(BaseNetworkService):
                                      limit=limit, marker=marker)
 
     def create(self, name=None):
-        if name is None:
-            name = "{0}-{1}".format(AzureNetwork.CB_DEFAULT_NETWORK_NAME,
-                                    uuid.uuid4().hex[:6])
+        network_name = AzureNetwork.CB_DEFAULT_NETWORK_NAME
+        if name:
+            network_name = "{0}-{1}".format(name, uuid.uuid4().hex[:6])
 
         params = {
             'location': self.provider.azure_client.region_name,
             'address_space': {
                 'address_prefixes': ['10.0.0.0/16']
-            }
+            },
+            'tags': {'Name': name or AzureNetwork.CB_DEFAULT_NETWORK_NAME}
         }
 
-        self.provider.azure_client.create_network(name, params)
-        network = self.provider.azure_client.get_network(name)
+        self.provider.azure_client.create_network(network_name, params)
+        network = self.provider.azure_client.get_network(network_name)
         cb_network = AzureNetwork(self.provider, network)
 
         return cb_network
@@ -450,9 +460,9 @@ class AzureNetworkService(BaseNetworkService):
                 """
         try:
             params = azure_helpers.parse_url(NETWORK_RESOURCE_ID, network_id)
-            network = self.provider.azure_client. \
+            self.provider.azure_client. \
                 delete_network(params.get(NETWORK_NAME))
-            return True if network else False
+            return True
         except CloudError as cloudError:
             log.exception(cloudError.message)
             return False
@@ -478,16 +488,17 @@ class AzureRegionService(BaseRegionService):
 
     @property
     def current(self):
-        region = None
         # aws sets the name returned from the aws sdk to both the id & name
         # of BaseRegion and as such calling get() with the id works
         # but Azure sdk returns both id & name and are set to
         # the BaseRegion properties
-        for azureRegion in self.provider.azure_client.list_locations():
-            if azureRegion.name == self.provider.region_name:
-                region = AzureRegion(self.provider, azureRegion)
-                break
-        return region
+        regions = [region
+                   for region in self.provider.
+                   azure_client.list_locations()
+                   if region.name == self.provider.
+                   azure_client.region_name]
+
+        return AzureRegion(self.provider, regions[0])
 
 
 class AzureSubnetService(BaseSubnetService):
@@ -506,39 +517,87 @@ class AzureSubnetService(BaseSubnetService):
             log.exception(cloudError.message)
             return None
 
-    def list(self, network=None):
-        subnets = []
+    def list(self, network=None, limit=None, marker=None):
+        result_list = []
         if network:
-            network_id = (network.id if isinstance(network, AzureNetwork) else
-                          network)
+            network_id = network.id \
+                if isinstance(network, Network) else network
             params = azure_helpers.parse_url(NETWORK_RESOURCE_ID, network_id)
-            network_name = params.get(NETWORK_NAME)
-            subnets = [AzureSubnet(self.provider, subnet)
-                       for subnet in
-                       self.provider.azure_client.list_subnets(network_name)]
+            result_list = self.provider.azure_client.list_subnets(
+                params.get(NETWORK_NAME)
+            )
         else:
-            networks = [AzureNetwork(self.provider, network)
-                        for network in
-                        self.provider.azure_client.list_networks()]
+            for net in self.provider.azure_client.list_networks():
+                result_list.extend(self.provider.azure_client.list_subnets(
+                 net.name
+                ))
+        subnets = [AzureSubnet(self.provider, subnet)
+                   for subnet in result_list]
+        return ClientPagedResultList(self.provider, subnets,
+                                     limit=limit, marker=marker)
 
-            for network in networks:
+    def create(self, network, cidr_block, name=None, **kwargs):
+        network_id = network.id \
+            if isinstance(network, Network) else network
+        params = azure_helpers.parse_url(NETWORK_RESOURCE_ID, network_id)
+        network_name = params.get(NETWORK_NAME)
 
-                networksubnets = [AzureSubnet(self.provider, subnet)
-                                  for subnet in
-                                  self.provider.
-                                  azure_client.list_subnets(network.name)]
-                subnets.extend(networksubnets)
-        return ClientPagedResultList(self.provider, subnets,
-                                     limit=None, marker=None)
+        if not name:
+            subnet_name = AzureSubnet.CB_DEFAULT_SUBNET_NAME
+        else:
+            subnet_name = name
 
-    def create(self, network, cidr_block, name=None, zone=None):
-        raise NotImplementedError('AzureSubnetService '
-                                  'not implemented this method')
+        subnet_info = self.provider.azure_client\
+            .create_subnet(
+                            network_name,
+                            subnet_name,
+                            {
+                                'address_prefix': cidr_block
+                            }
+                          )
+
+        return AzureSubnet(self.provider, subnet_info)
 
     def get_or_create_default(self, zone=None):
-        raise NotImplementedError('AzureSubnetService '
-                                  'not implemented this method')
+        default_cdir = '10.0.1.0/24'
+        network = None
+        subnet = None
+        try:
+            network = self.provider.azure_client\
+                .get_network(AzureNetwork.CB_DEFAULT_NETWORK_NAME)
+        except CloudError:
+            pass
+
+        if not network:
+            self.provider.network.create()
+        try:
+            subnet = self.provider.azure_client.get_subnet(
+                AzureNetwork.CB_DEFAULT_NETWORK_NAME,
+                AzureSubnet.CB_DEFAULT_SUBNET_NAME
+            )
+        except CloudError:
+            pass
+
+        if not subnet:
+            subnet = self.provider.azure_client.create_subnet(
+                AzureNetwork.CB_DEFAULT_NETWORK_NAME,
+                AzureSubnet.CB_DEFAULT_SUBNET_NAME,
+                {'address_prefix': default_cdir}
+            )
+
+        return AzureSubnet(self.provider, subnet)
 
     def delete(self, subnet):
-        raise NotImplementedError('AzureSubnetService '
-                                  'not implemented this method')
+        try:
+            subnet_id = subnet.id if \
+                isinstance(subnet, Subnet) else subnet
+            params = azure_helpers.\
+                parse_url(SUBNET_RESOURCE_ID, subnet_id)
+            self.provider.azure_client.delete_subnet(
+                params.get(NETWORK_NAME),
+                params.get(SUBNET_NAME)
+            )
+            return True
+        except CloudError as cloudError:
+            log.exception(cloudError.message)
+            return False

+ 16 - 4
test/test_azure_security_service.py

@@ -16,6 +16,18 @@ class AzureSecurityServiceTestCase(ProviderTestBase):
         print("Create - " + str(sg))
         self.assertEqual(name, sg.name)
 
+    @helpers.skipIfNoService(['security.security_groups'])
+    def test_azure_security_group_create_and_delete(self):
+        name = "testCreateSecGroup10"
+        sg = self.provider.security.security_groups.create(
+            name=name, description=name, network_id="")
+        print("Create - " + str(sg))
+        self.assertEqual(name, sg.name)
+        deleted = sg.delete()
+        self.assertTrue(deleted)
+        deleted = sg.delete()
+        self.assertFalse(deleted)
+
     @helpers.skipIfNoService(['security.security_groups'])
     def test_azure_security_group_create_no_description(self):
         name = "testCreateSecGroup13"
@@ -75,18 +87,18 @@ class AzureSecurityServiceTestCase(ProviderTestBase):
 
     @helpers.skipIfNoService(['security.security_groups'])
     def test_azure_security_group_delete_IdExists(self):
-        sg = self.provider.security.security_groups.delete(
+        deleted = self.provider.security.security_groups.delete(
             "/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/resourceGroups/CloudBridge-Azure'\
             '/providers/Microsoft.Network/networkSecurityGroups/sg2")
         print("Delete - ")
-        self.assertEqual(sg, True)
+        self.assertEqual(deleted, True)
 
     @helpers.skipIfNoService(['security.security_groups'])
     def test_azure_security_group_delete_IdNotExist(self):
-        sg = self.provider.security.security_groups.delete(
+        deleted = self.provider.security.security_groups.delete(
             "/subscriptions/7904d702-e01c-4826-8519-f5a25c866a96/resourceGroups/CloudBridge-Azure'\
             '/providers/Microsoft.Network/networkSecurityGroups/sg5")
-        self.assertEqual(sg, False)
+        self.assertEqual(deleted, False)
 
     @helpers.skipIfNoService(['security.security_groups'])
     def test_azure_security_group_rule_create(self):