libcloud-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From to...@apache.org
Subject [libcloud] 01/03: [LIBCLOUD-1017] Improvements to Azure ARM compute driver
Date Sun, 30 Jun 2019 19:41:02 GMT
This is an automated email from the ASF dual-hosted git repository.

tomaz pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/libcloud.git

commit db750900a9d104ae66edce980a0617466215ece8
Author: Palash Gandhi <palash.gandhi@delphix.com>
AuthorDate: Mon Apr 29 17:11:48 2019 -0700

    [LIBCLOUD-1017] Improvements to Azure ARM compute driver
---
 libcloud/compute/drivers/azure_arm.py              | 161 +++++++++++++++++++--
 ...viders_Microsoft_Network_networkInterfaces.json |  56 +++++++
 ...roviders_Microsoft_Network_virtualnetworks.json |  56 +++++++
 ...rosoft_Compute_virtualMachines_test_node_1.json |  53 +++----
 ...crosoft_Network_networkInterfaces_test_nic.json |  52 +++++++
 ...ks_test_network_CheckIPAddressAvailability.json |  10 ++
 libcloud/test/compute/test_azure_arm.py            |  50 +++++++
 7 files changed, 402 insertions(+), 36 deletions(-)

diff --git a/libcloud/compute/drivers/azure_arm.py b/libcloud/compute/drivers/azure_arm.py
index edac4bb..2ae0af5 100644
--- a/libcloud/compute/drivers/azure_arm.py
+++ b/libcloud/compute/drivers/azure_arm.py
@@ -366,19 +366,19 @@ class AzureNodeDriver(NodeDriver):
         """
         List all nodes.
 
-        :param ex_resource_group: List nodes in a specific resource group.
-        :type ex_urn: ``str``
+        :param ex_resource_group: The resource group to list all nodes from.
+        :type ex_resource_group: ``str``
 
         :param ex_fetch_nic: Fetch NIC resources in order to get
         IP address information for nodes.  If True, requires an extra API
         call for each NIC of each node.  If False, IP addresses will not
         be returned.
-        :type ex_urn: ``bool``
+        :type ex_fetch_nic: ``bool``
 
         :param ex_fetch_power_state: Fetch node power state.  If True, requires
         an extra API call for each node.  If False, node state
         will be returned based on provisioning state only.
-        :type ex_urn: ``bool``
+        :type ex_fetch_power_state: ``bool``
 
         :return:  list of node objects
         :rtype: ``list`` of :class:`.Node`
@@ -997,6 +997,53 @@ class AzureNodeDriver(NodeDriver):
             })
         return True
 
+    def ex_resize_volume(self, volume, new_size, ex_resource_group):
+        """
+        Resize a volume.
+
+        :param volume: A volume to resize.
+        :type volume: :class:`StorageVolume`
+
+        :param new_size: The new size to resize the volume to in Gib.
+        :type new_size: ``int``
+
+        :param ex_resource_group: The name of the resource group in which to
+            create the volume.
+        :type ex_resource_group: ``str``
+
+        """
+        action = (
+            u'/subscriptions/{subscription_id}/resourceGroups/{resource_group}'
+            u'/providers/Microsoft.Compute/disks/{volume_name}'
+        ).format(
+            subscription_id=self.subscription_id,
+            resource_group=ex_resource_group,
+            volume_name=volume.name,
+        )
+
+        data = {
+            'location': volume.extra['location'],
+            'properties': {
+                'diskSizeGB': new_size,
+                'creationData': volume.extra['properties']['creationData']
+            }
+        }
+
+        response = self.connection.request(
+            action,
+            method='PUT',
+            params={
+                'api-version': '2018-06-01',
+            },
+            data=data
+        )
+
+        return self._to_volume(
+            response.object,
+            name=volume.name,
+            ex_resource_group=ex_resource_group
+        )
+
     def detach_volume(self, volume, ex_node=None):
         """
         Detach a managed volume from a node.
@@ -1301,7 +1348,7 @@ class AzureNodeDriver(NodeDriver):
         :type locale: ``str``
 
         :param region: Region (two-letter code) (default: "US")
-        :type regions: ``str``
+        :type region: ``str``
 
         :return: A dictionary of rates whose ID's correspond to nothing at all
         :rtype: ``dict``
@@ -1368,14 +1415,14 @@ class AzureNodeDriver(NodeDriver):
 
         :param offer: The complete resource path to an offer (as returned by
         `ex_list_offers`)
-        :type publisher: ``str``
+        :type offer: ``str``
 
         :return: A list of tuples in the form
         ("sku id", "sku name")
         :rtype: ``list``
         """
 
-        action = "%s/skus" % (offer)
+        action = "%s/skus" % offer
         r = self.connection.request(action,
                                     params={"api-version": "2015-06-15"})
         return [(sku["id"], sku["name"]) for sku in r.object]
@@ -1575,12 +1622,77 @@ class AzureNodeDriver(NodeDriver):
         r = self.connection.request(id, params={"api-version": "2015-06-15"})
         return self._to_nic(r.object)
 
+    def ex_update_nic_properties(self, network_interface,
+                                 resource_group, properties):
+        """
+        Update the properties of an already existing virtual network
+        interface (NIC).
+
+        :param network_interface: The NIC to update.
+        :type network_interface: :class:`.AzureNic`
+
+        :param resource_group: The resource group to check the ip address in.
+        :type resource_group: ``str``
+
+        :param properties: The dictionary of the NIC's properties
+        :type properties: ``dict``
+
+        :return: The NIC object
+        :rtype: :class:`.AzureNic`
+        """
+
+        target = "/subscriptions/%s/resourceGroups/%s/providers" \
+                 "/Microsoft.Network/networkInterfaces/%s" \
+                 % (self.subscription_id, resource_group,
+                    network_interface.name)
+
+        data = {
+            "properties": properties,
+            "location": network_interface.location,
+        }
+
+        r = self.connection.request(target,
+                                    params={"api-version": '2018-06-01'},
+                                    data=data,
+                                    method='PUT')
+        return AzureNic(r.object["id"], r.object["name"], r.object["location"],
+                        r.object["properties"])
+
+    def ex_update_network_profile_of_node(self, node, network_profile):
+        """
+        Update the network profile of a node. This method can be used to
+        attach or detach a NIC to a node.
+
+        :param node: A node to attach the network interface to.
+        :type node: :class:`Node`
+
+        :param network_profile: The new network profile to update.
+        :type network_profile: ``dict``
+        """
+        action = node.extra['id']
+        location = node.extra['location']
+        self.connection.request(
+            action,
+            method='PUT',
+            params={
+                'api-version': '2018-06-01'
+            },
+            data={
+                "id": node.id,
+                "name": node.name,
+                "type": "Microsoft.Compute/virtualMachines",
+                "location": location,
+                'properties': {
+                    'networkProfile': network_profile
+                }
+            })
+
     def ex_destroy_nic(self, nic):
         """
         Destroy a NIC.
 
-        :param id: The NIC to destroy.
-        :type id: ``.AzureNic``
+        :param nic: The NIC to destroy.
+        :type nic: ``.AzureNic``
 
         :return: True on success
         :rtype: ``bool``
@@ -1600,6 +1712,33 @@ class AzureNodeDriver(NodeDriver):
             else:
                 raise
 
+    def ex_check_ip_address_availability(self, resource_group, network,
+                                         ip_address):
+        """
+        Checks whether a private IP address is available for use. Also
+        returns an object that contains the available IPs in the subnet.
+
+        :param resource_group: The resource group to check the ip address in.
+        :type resource_group: ``str``
+
+        :param network: The virtual network.
+        :type network: :class:`.AzureNetwork`
+
+        :param ip_address: The private IP address to be verified.
+        :type ip_address: ``str``
+        """
+        params = {"api-version": '2018-06-01'}
+        action = "/subscriptions/%s/resourceGroups/%s/providers" \
+                 "/Microsoft.Network/virtualNetworks/%s/" \
+                 "CheckIPAddressAvailability" % \
+                 (self.subscription_id, resource_group, network.name)
+        if ip_address is not None:
+            params["ipAddress"] = ip_address
+        r = self.connection.request(
+            action,
+            params=params)
+        return r.object
+
     def ex_get_node(self, id):
         """
         Fetch information about a node.
@@ -1811,7 +1950,7 @@ class AzureNodeDriver(NodeDriver):
             resource = resource.id
         r = self.connection.request(
             resource,
-            params={"api-version": RESOURCE_API_VERSION})
+            params={"api-version": '2018-06-01'})
         if replace:
             r.object["tags"] = tags
         else:
@@ -1819,7 +1958,7 @@ class AzureNodeDriver(NodeDriver):
         self.connection.request(
             resource,
             data={"tags": r.object["tags"]},
-            params={"api-version": RESOURCE_API_VERSION},
+            params={"api-version": '2018-06-01'},
             method="PATCH")
 
     def ex_start_node(self, node):
diff --git a/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Network_networkInterfaces.json
b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Network_networkInterfaces.json
new file mode 100644
index 0000000..308411c
--- /dev/null
+++ b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Network_networkInterfaces.json
@@ -0,0 +1,56 @@
+{
+  "value": [
+    {
+      "name": "test-nic",
+      "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/REVIZOR/providers/Microsoft.Network/networkInterfaces/test-nic",
+      "etag": "Z/\"99999999-9999-9999-9999-999999999999\"",
+      "location": "eastus",
+      "tags": {
+        "tag_key1": "tag_val1"
+      },
+      "properties": {
+        "provisioningState": "Succeeded",
+        "resourceGuid": "99999999-9999-9999-9999-999999999999",
+        "ipConfigurations": [
+          {
+            "name": "ipconfig1",
+            "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Network/networkInterfaces/test-nic/ipConfigurations/ipconfig1",
+            "etag": "Z/\"99999999-9999-9999-9999-999999999999\"",
+            "type": "Microsoft.Network/networkInterfaces/ipConfigurations",
+            "properties": {
+              "provisioningState": "Succeeded",
+              "privateIPAddress": "172.20.2.4",
+              "privateIPAllocationMethod": "Dynamic",
+              "publicIPAddress": {
+                "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Network/publicIPAddresses/test-ip"
+              },
+              "subnet": {
+                "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Network/virtualNetworks/rg1-vnet/subnets/default"
+              },
+              "primary": false,
+              "privateIPAddressVersion": "IPv4",
+              "isInUseWithService": false
+            }
+          }
+        ],
+        "dnsSettings": {
+          "dnsServers": [
+
+          ],
+          "appliedDnsServers": [
+
+          ],
+          "internalDomainNameSuffix": "test.bx.internal.cloudapp.net"
+        },
+        "macAddress": "00-0D-3A-1B-C7-21",
+        "enableAcceleratedNetworking": false,
+        "enableIPForwarding": false,
+        "primary": true,
+        "virtualMachine": {
+          "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Compute/virtualMachines/test-vm-1"
+        }
+      },
+      "type": "Microsoft.Network/networkInterfaces"
+    }
+  ]
+}
diff --git a/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Network_virtualnetworks.json
b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Network_virtualnetworks.json
new file mode 100644
index 0000000..e2296f0
--- /dev/null
+++ b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Network_virtualnetworks.json
@@ -0,0 +1,56 @@
+{
+  "value": [
+    {
+      "name": "test_network",
+      "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/REVIZOR/providers/Microsoft.Network/virtualNetworks/test_network",
+      "etag": "W/\"99999999-9999-9999-9999-999999999999\"",
+      "type": "Microsoft.Network/virtualNetworks",
+      "location": "westus2",
+      "tags": {
+        "tag_key1": "tag_val1"
+      },
+      "properties": {
+        "provisioningState": "Succeeded",
+        "resourceGuid": "99999999-9999-9999-9999-999999999999",
+        "addressSpace": {
+          "addressPrefixes": [
+            "10.39.0.0/16"
+          ]
+        },
+        "dhcpOptions": {
+          "dnsServers": [
+            "172.11.111.11",
+            "172.11.111.12",
+            "8.8.8.8",
+            "8.8.4.4"
+          ]
+        },
+        "subnets": [
+          {
+            "name": "Azure_VPC_Subnet",
+            "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/REVIZOR/providers/Microsoft.Network/virtualNetworks/test_network/subnets/Azure_VPC_Subnet",
+            "etag": "W/\"99999999-9999-9999-9999-999999999990\"",
+            "properties": {
+              "provisioningState": "Succeeded",
+              "addressPrefix": "10.17.26.0/19",
+              "ipConfigurations": [
+                {
+                  "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/REVIZOR/providers/Microsoft.Network/networkInterfaces/test-nic/ipConfigurations/ipconfig1"
+                }
+              ],
+              "delegations": [
+
+              ]
+            },
+            "type": "Microsoft.Network/virtualNetworks/subnets"
+          }
+        ],
+        "virtualNetworkPeerings": [
+
+        ],
+        "enableDdosProtection": false,
+        "enableVmProtection": false
+      }
+    }
+  ]
+}
diff --git a/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Compute_virtualMachines_test_node_1.json
b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Compute_virtualMachines_test_node_1.json
index c45d32f..9cbc7c1 100644
--- a/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Compute_virtualMachines_test_node_1.json
+++ b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Compute_virtualMachines_test_node_1.json
@@ -1,48 +1,51 @@
 {
   "properties": {
-    "vmId": "e717ae77-db36-4225-b12a-68506fe5fc8f",
+    "vmId": "99999999-9999-9999-9999-999999999999",
     "hardwareProfile": {
       "vmSize": "Standard_A1"
     },
     "storageProfile": {
-      "imageReference": {
-        "publisher": "OpenLogic",
-        "offer": "CentOS",
-        "sku": "7.3",
-        "version": "latest"
-      },
       "osDisk": {
         "osType": "Linux",
-        "name": "test-node-disk-1",
-        "createOption": "FromImage",
+        "name": "OSD-9999",
+        "createOption": "Attach",
         "caching": "ReadWrite",
         "managedDisk": {
           "storageAccountType": "Standard_LRS",
-          "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/disks/test-node-disk-1"
+          "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/disks/OSD-9999"
         }
       },
-      "dataDisks": []
-    },
-    "osProfile": {
-      "computerName": "test-node-1",
-      "adminUsername": "user",
-      "linuxConfiguration": {
-        "disablePasswordAuthentication": false
-      },
-      "secrets": []
+      "dataDisks": [
+        {
+          "lun": 0,
+          "name": "DD0-9999",
+          "createOption": "Attach",
+          "caching": "None",
+          "managedDisk": {
+            "storageAccountType": "Standard_LRS",
+            "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/disks/DD0-9999"
+          },
+          "diskSizeGB": 8
+        }
+      ]
     },
     "networkProfile": {
       "networkInterfaces": [
         {
-          "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Network/networkInterfaces/test-node-1-nic"
+          "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/0000/providers/Microsoft.Network/networkInterfaces/test-nic",
+          "properties": {
+            "primary": true
+          }
         }
       ]
     },
-    "provisioningState": "Running"
+    "provisioningState": "Succeeded"
   },
   "type": "Microsoft.Compute/virtualMachines",
   "location": "eastus",
-  "tags": {},
-  "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/virtualMachines/test-node-1",
-  "name": "test-node-1"
-}
\ No newline at end of file
+  "tags": {
+    "tag_key1": "tag_val1"
+  },
+  "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/0000/providers/Microsoft.Compute/virtualMachines/test_vm",
+  "name": "test_vm"
+}
diff --git a/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_REVIZOR_providers_Microsoft_Network_networkInterfaces_test_nic.json
b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_REVIZOR_providers_Microsoft_Network_networkInterfaces_test_nic.json
new file mode 100644
index 0000000..e4fbb9e
--- /dev/null
+++ b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_REVIZOR_providers_Microsoft_Network_networkInterfaces_test_nic.json
@@ -0,0 +1,52 @@
+{
+  "name": "test-nic",
+  "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/REVIZOR/providers/Microsoft.Network/networkInterfaces/test-nic",
+  "etag": "Z/\"99999999-9999-9999-9999-999999999999\"",
+  "location": "eastus",
+  "tags": {
+    "tag_key1": "tag_val1"
+  },
+  "properties": {
+    "provisioningState": "Succeeded",
+    "resourceGuid": "99999999-9999-9999-9999-999999999999",
+    "ipConfigurations": [
+      {
+        "name": "ipconfig1",
+        "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Network/networkInterfaces/test-nic/ipConfigurations/ipconfig1",
+        "etag": "Z/\"99999999-9999-9999-9999-999999999999\"",
+        "type": "Microsoft.Network/networkInterfaces/ipConfigurations",
+        "properties": {
+          "provisioningState": "Succeeded",
+          "privateIPAddress": "172.20.2.4",
+          "privateIPAllocationMethod": "Dynamic",
+          "publicIPAddress": {
+            "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Network/publicIPAddresses/test-ip"
+          },
+          "subnet": {
+            "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Network/virtualNetworks/rg1-vnet/subnets/default"
+          },
+          "primary": true,
+          "privateIPAddressVersion": "IPv4",
+          "isInUseWithService": false
+        }
+      }
+    ],
+    "dnsSettings": {
+      "dnsServers": [
+
+      ],
+      "appliedDnsServers": [
+
+      ],
+      "internalDomainNameSuffix": "test.bx.internal.cloudapp.net"
+    },
+    "macAddress": "00-0D-3A-1B-C7-21",
+    "enableAcceleratedNetworking": false,
+    "enableIPForwarding": false,
+    "primary": true,
+    "virtualMachine": {
+      "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Compute/virtualMachines/test-vm-1"
+    }
+  },
+  "type": "Microsoft.Network/networkInterfaces"
+}
diff --git a/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_REVIZOR_providers_Microsoft_Network_virtualNetworks_test_network_CheckIPAddressAvailability.json
b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_REVIZOR_providers_Microsoft_Network_virtualNetworks_test_network_CheckIPAddressAvailability.json
new file mode 100644
index 0000000..c13e093
--- /dev/null
+++ b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_REVIZOR_providers_Microsoft_Network_virtualNetworks_test_network_CheckIPAddressAvailability.json
@@ -0,0 +1,10 @@
+{
+  "available": false,
+  "availableIPAddresses": [
+    "10.32.36.102",
+    "10.32.36.103",
+    "10.32.36.104",
+    "10.32.36.105",
+    "10.32.36.106"
+  ]
+}
diff --git a/libcloud/test/compute/test_azure_arm.py b/libcloud/test/compute/test_azure_arm.py
index 68dd1ce..285d752 100644
--- a/libcloud/test/compute/test_azure_arm.py
+++ b/libcloud/test/compute/test_azure_arm.py
@@ -432,6 +432,17 @@ class AzureNodeDriverTests(LibcloudTestCase):
         self.assertTrue(len(data_disks), len(volumes))
         self.assertTrue(set(luns), {0, 1, 15})
 
+    def test_resize_volume(self):
+        volume = self.driver.list_volumes()[0]
+        original_size = volume.size
+
+        volume = self.driver.ex_resize_volume(
+            volume, volume.size + 8, '000000'
+        )
+        new_size = volume.size
+
+        self.assertEqual(new_size , original_size + 8)
+
     def test_detach_volume(self):
         volumes = self.driver.list_volumes()
         node = self.driver.list_nodes()[0]
@@ -554,6 +565,45 @@ class AzureNodeDriverTests(LibcloudTestCase):
         res_value = snapshot.destroy()
         self.assertTrue(res_value)
 
+    def test_update_network_profile(self):
+        nics = self.driver.ex_list_nics()
+        node = self.driver.list_nodes()[0]
+        network_profile = node.extra['properties']['networkProfile']
+        primary_nic_exists = False
+        num_nics_before = len(network_profile["networkInterfaces"])
+
+        for nic in network_profile["networkInterfaces"]:
+            if "properties" in nic and nic["properties"]["primary"]:
+                primary_nic_exists = True
+        if not primary_nic_exists:
+            network_profile["networkInterfaces"][0]["properties"] = {
+                "primary": True}
+        network_profile["networkInterfaces"].append({"id": nics[0].id})
+        self.driver.ex_update_network_profile_of_node(
+            node, network_profile)
+
+        network_profile = node.extra['properties']['networkProfile']
+        num_nics_after = len(network_profile["networkInterfaces"])
+
+        self.assertEqual(num_nics_after, num_nics_before + 1)
+
+    def test_update_nic_properties(self):
+        nics = self.driver.ex_list_nics()
+        nic_to_update = nics[0]
+        nic_properties = nic_to_update.extra
+        ip_configs = nic_properties['ipConfigurations']
+        ip_configs[0]['properties']['primary'] = True
+        updated_nic = self.driver.ex_update_nic_properties(
+            nic_to_update, resource_group='REVIZOR', properties=nic_properties)
+        self.assertTrue(
+            updated_nic.extra['ipConfigurations'][0]['properties']['primary'])
+
+    def test_check_ip_address_availability(self):
+        networks = self.driver.ex_list_networks()
+        result = self.driver.ex_check_ip_address_availability(
+            'REVIZOR', networks[0], '0.0.0.0')
+        self.assertFalse(result['available'])
+
     def test_get_instance_vhd(self):
         with mock.patch.object(self.driver, '_ex_delete_old_vhd'):
             # Default storage suffix


Mime
View raw message