File azure_pagination.patch of Package python-apache-libcloud
Index: apache-libcloud-3.3.1/libcloud/compute/drivers/azure_arm.py
===================================================================
--- apache-libcloud-3.3.1.orig/libcloud/compute/drivers/azure_arm.py
+++ apache-libcloud-3.3.1/libcloud/compute/drivers/azure_arm.py
@@ -35,7 +35,7 @@ from libcloud.common.types import Libclo
from libcloud.storage.types import ObjectDoesNotExistError
from libcloud.common.exceptions import BaseHTTPError
from libcloud.storage.drivers.azure_blobs import AzureBlobsStorageDriver
-from libcloud.utils.py3 import basestring
+from libcloud.utils.py3 import parse_qs, urlparse, basestring
from libcloud.utils import iso8601
@@ -61,6 +61,13 @@ class AzureImage(NodeImage):
return (('<AzureImage: id=%s, name=%s, location=%s>')
% (self.id, self.name, self.location))
+# If pagination code in the list_nodes() method has still not completed after this mount of
+# seconds, we will break early from while True loop to avoid infinite loop under edge conditions.
+# Keep in mind that we want this timeout relatively high since each `_to_node()` method call which
+# is called for each node can result in additional HTTP requests (to retrieve power state, nics,
+# etc).
+LIST_NODES_PAGINATION_TIMEOUT = 300
+
class AzureVhdImage(NodeImage):
"""Represents a VHD node image that an Azure VM can boot from."""
@@ -392,12 +399,26 @@ class AzureNodeDriver(NodeDriver):
action = "/subscriptions/%s/providers/Microsoft.Compute/" \
"virtualMachines" \
% (self.subscription_id)
- r = self.connection.request(action,
- params={"api-version": "2015-06-15"})
- return [self._to_node(n,
- fetch_nic=ex_fetch_nic,
- fetch_power_state=ex_fetch_power_state)
- for n in r.object["value"]]
+ params = {"api-version": "2021-11-01"}
+
+ now_ts = int(time.time())
+ deadline_ts = now_ts + LIST_NODES_PAGINATION_TIMEOUT
+
+ nodes = []
+ while time.time() < deadline_ts:
+ r = self.connection.request(action, params=params)
+ nodes.extend(
+ self._to_node(n, fetch_nic=ex_fetch_nic, fetch_power_state=ex_fetch_power_state)
+ for n in r.object["value"]
+ )
+ if not r.object.get("nextLink"):
+ # No next page
+ break
+ parsed_next_link = urlparse.urlparse(r.object["nextLink"])
+ params.update({k: v[0] for k, v in parse_qs(parsed_next_link.query).items()})
+ action = parsed_next_link.path
+ return nodes
+
def create_node(self,
name,