← Back to team overview

cloud-init-dev team mailing list archive

[Merge] ~ahosmanmsft/cloud-init:idchange into cloud-init:master

 

Ahmed has proposed merging ~ahosmanmsft/cloud-init:idchange into cloud-init:master.

Commit message:
Fixed instance id endioness on Azure

Requested reviews:
  cloud-init Commiters (cloud-init-dev)

For more details, see:
https://code.launchpad.net/~ahosmanmsft/cloud-init/+git/cloud-init/+merge/376298

Corrected instance id comparison and implemented a change for id byte swap on gen2 VM's
-- 
Your team cloud-init Commiters is requested to review the proposed merge of ~ahosmanmsft/cloud-init:idchange into cloud-init:master.
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
index 87a848c..9afca1b 100755
--- a/cloudinit/sources/DataSourceAzure.py
+++ b/cloudinit/sources/DataSourceAzure.py
@@ -33,7 +33,8 @@ from cloudinit.sources.helpers.azure import (
     get_boot_telemetry,
     get_system_info,
     report_diagnostic_event,
-    EphemeralDHCPv4WithReporting)
+    EphemeralDHCPv4WithReporting,
+    byte_swapped)
 
 LOG = logging.getLogger(__name__)
 
@@ -471,8 +472,7 @@ class DataSourceAzure(sources.DataSource):
         seed = _get_random_seed()
         if seed:
             crawled_data['metadata']['random_seed'] = seed
-        crawled_data['metadata']['instance-id'] = util.read_dmi_data(
-            'system-uuid')
+        crawled_data['metadata']['instance-id'] = self._iid()
 
         if perform_reprovision:
             LOG.info("Reporting ready to Azure after getting ReprovisionData")
@@ -558,6 +558,15 @@ class DataSourceAzure(sources.DataSource):
         # quickly (local check only) if self.instance_id is still valid
         return sources.instance_id_matches_system_uuid(self.get_instance_id())
 
+    def _iid(self):
+        previous = util.load_file(os.path.join(
+            self.paths.get_cpath('data'),
+            'instance-id')).strip()
+        iid = util.read_dmi_data(
+            'system-uuid')
+        swap = byte_swapped(previous, iid)
+        return swap if swap else iid
+
     @azure_ds_telemetry_reporter
     def setup(self, is_new_instance):
         if self._negotiated is False:
diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py
index e6baf8f..ab268af 100644
--- a/cloudinit/sources/__init__.py
+++ b/cloudinit/sources/__init__.py
@@ -15,6 +15,7 @@ import json
 import os
 import six
 
+from cloudinit.sources.helpers.azure import byte_swapped
 from cloudinit.atomic_helper import write_json
 from cloudinit import importer
 from cloudinit import log as logging
@@ -800,9 +801,11 @@ def instance_id_matches_system_uuid(instance_id, field='system-uuid'):
         return False
 
     dmi_value = util.read_dmi_data(field)
+    previous = dmi_value.lower()
+    current = instance_id.lower()
     if not dmi_value:
         return False
-    return instance_id.lower() == dmi_value.lower()
+    return current == previous or current == byte_swapped(current, previous)
 
 
 def canonical_cloud_id(cloud_name, region, platform):
diff --git a/cloudinit/sources/helpers/azure.py b/cloudinit/sources/helpers/azure.py
index f5cdb3f..88f3498 100755
--- a/cloudinit/sources/helpers/azure.py
+++ b/cloudinit/sources/helpers/azure.py
@@ -48,6 +48,37 @@ def azure_ds_telemetry_reporter(func):
     return impl
 
 
+def byte_swapped(previous_id, current_id):
+    """
+    Azure stores the instance ID with an incorrect byte ordering for the
+    first parts. This corrects the byte order such that it is consistent with
+    that returned by the metadata service.
+    """
+    if previous_id == current_id:
+        return None
+
+    def swap_hexstring(s, width=2):
+        r = len(s) % width
+        if r != 0:
+            s = ('0' * (width - (len(s) % width))) + s
+
+        return ''.join(reversed(
+            re.findall(
+                r'[a-f0-9]{{{0}}}'.format(width),
+                s,
+                re.IGNORECASE)))
+
+    parts = current_id.split('-')
+    swapped_id = '-'.join([
+            swap_hexstring(parts[0], width=2),
+            swap_hexstring(parts[1], width=2),
+            swap_hexstring(parts[2], width=2),
+            parts[3],
+            parts[4]
+        ])
+
+    return swapped_id if previous_id == swapped_id else None
+
 @azure_ds_telemetry_reporter
 def get_boot_telemetry():
     """Report timestamps related to kernel initialization and systemd

Follow ups