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 d9f6268a2ec0211219e21b1e4f56813d265e62f1
Author: Tomaz Muraus <to...@tomaz.me>
AuthorDate: Fri Aug 4 15:40:38 2023 +0200

    Implement timeout based guard for list_volumes(). This way we don't end
    up in an infinite loop due to the bug in the code, invalid server
    response or similar.
---
 libcloud/compute/drivers/azure_arm.py              | 10 +++++++-
 ...oft_Compute_disks_PAGINATION_INFINITE_LOOP.json | 30 ++++++++++++++++++++++
 libcloud/test/compute/test_azure_arm.py            |  8 ++++++
 3 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/libcloud/compute/drivers/azure_arm.py 
b/libcloud/compute/drivers/azure_arm.py
index b9a83c9a9..75e1b7020 100644
--- a/libcloud/compute/drivers/azure_arm.py
+++ b/libcloud/compute/drivers/azure_arm.py
@@ -71,6 +71,9 @@ VM_SIZE_API_VERSION = "2015-06-15"  # this API is deprecated
 # etc).
 LIST_NODES_PAGINATION_TIMEOUT = 300
 
+# Pagination timeout for list_volumes() method.
+LIST_VOLUMES_PAGINATION_TIMEOUT = 300
+
 
 class AzureImage(NodeImage):
     """Represents a Marketplace node image that an Azure VM can boot from."""
@@ -1032,11 +1035,16 @@ class AzureNodeDriver(NodeDriver):
             subscription_id=self.subscription_id, 
resource_group=ex_resource_group
         )
         params = {"api-version": DISK_API_VERSION}
+
+        now_ts = int(time.time())
+        deadline_ts = now_ts + LIST_VOLUMES_PAGINATION_TIMEOUT
+
         volumes = []
-        while True:
+        while time.time() < deadline_ts:
             response = self.connection.request(action, method="GET", 
params=params)
             volumes.extend(self._to_volume(volume) for volume in 
response.object["value"])
             if not response.object.get("nextLink"):
+                # No next page
                 break
             parsed_next_link = urlparse.urlparse(response.object["nextLink"])
             params.update({k: v[0] for k, v in 
parse_qs(parsed_next_link.query).items()})
diff --git 
a/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_disks_PAGINATION_INFINITE_LOOP.json
 
b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_disks_PAGINATION_INFINITE_LOOP.json
new file mode 100644
index 000000000..abe8380f8
--- /dev/null
+++ 
b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_disks_PAGINATION_INFINITE_LOOP.json
@@ -0,0 +1,30 @@
+{
+  "value": [
+    {
+      "properties": {
+        "osType": "Linux",
+        "creationData": {
+          "createOption": "FromImage",
+          "imageReference": {
+            "id": 
"/Subscriptions/99999999-9999-9999-9999-999999999999/Providers/Microsoft.Compute/Locations/eastus/Publishers/OpenLogic/ArtifactTypes/VMImage/Offers/CentOS/Skus/7.3/Versions/latest"
+          }
+        },
+        "diskSizeGB": 1500,
+        "timeCreated": "2017-03-09T10:12:37.0256203+00:00",
+        "ownerId": 
"/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/REVIZOR/providers/Microsoft.Compute/virtualMachines/test-vm-2",
+        "provisioningState": "Succeeded",
+        "diskState": "Attached"
+      },
+      "sku": {
+        "name": "Standard_LRS",
+        "tier": "Standard"
+      },
+      "type": "Microsoft.Compute/disks",
+      "location": "eastus",
+      "tags": {},
+      "id": 
"/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/disks/test-disk-4",
+      "name": "test-disk-4",
+      "zones": ["1", "2", "3"]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/libcloud/test/compute/test_azure_arm.py 
b/libcloud/test/compute/test_azure_arm.py
index 66992ff96..a8ec7539b 100644
--- a/libcloud/test/compute/test_azure_arm.py
+++ b/libcloud/test/compute/test_azure_arm.py
@@ -591,6 +591,14 @@ class AzureNodeDriverTests(LibcloudTestCase):
         self.assertEqual(volumes[0].extra["properties"]["diskState"], 
"Unattached")
         self.assertEqual(volumes[0].state, StorageVolumeState.AVAILABLE)
 
+    
@mock.patch("libcloud.compute.drivers.azure_arm.LIST_NODES_PAGINATION_TIMEOUT", 
1)
+    def test_list_volumes_pagination_timeout(self):
+        # Verify we don't end up in an infinite loop in case server returns a 
bad response or
+        # similar
+        AzureMockHttp.type = "PAGINATION_INFINITE_LOOP"
+        volumes = self.driver.list_volumes()
+        self.assertTrue(len(volumes) >= 1)
+
     def test_attach_volume(self):
         volumes = self.driver.list_volumes()
         node = self.driver.list_nodes()[0]

Reply via email to