summaryrefslogtreecommitdiff
path: root/cloudinit/sources
diff options
context:
space:
mode:
authorAOhassan <37305877+AOhassan@users.noreply.github.com>2019-12-12 13:51:42 -0800
committerChad Smith <chad.smith@canonical.com>2019-12-12 14:51:42 -0700
commit129b1c4ea250619bd7caed7aaffacc796b0139f2 (patch)
tree96970dbb7ef64d5f1399659dbf4a5f46519f81ef /cloudinit/sources
parente2840f1771158748780a768f6bfbb117cd7610c6 (diff)
downloadvyos-cloud-init-129b1c4ea250619bd7caed7aaffacc796b0139f2.tar.gz
vyos-cloud-init-129b1c4ea250619bd7caed7aaffacc796b0139f2.zip
azure: avoid re-running cloud-init when instance-id is byte-swapped (#84)
Azure stores the instance ID with an incorrect byte ordering for the first three hyphen delimited parts. This results in invalid is_new_instance checks forcing Azure datasource to recrawl the metadata service. When persisting instance-id from the metadata service, swap the instance-id string byte order such that it is consistent with that returned by dmi information. Check whether the instance-id string is a byte-swapped match when determining correctly whether the Azure platform instance-id has actually changed.
Diffstat (limited to 'cloudinit/sources')
-rwxr-xr-xcloudinit/sources/DataSourceAzure.py16
-rwxr-xr-xcloudinit/sources/helpers/azure.py27
2 files changed, 40 insertions, 3 deletions
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
index 87a848ce..24f448c5 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,
+ is_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,16 @@ 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=None):
+ prev_iid_path = os.path.join(
+ self.paths.get_cpath('data'), 'instance-id')
+ iid = util.read_dmi_data('system-uuid')
+ if os.path.exists(prev_iid_path):
+ previous = util.load_file(prev_iid_path).strip()
+ if is_byte_swapped(previous, iid):
+ return previous
+ return iid
+
@azure_ds_telemetry_reporter
def setup(self, is_new_instance):
if self._negotiated is False:
diff --git a/cloudinit/sources/helpers/azure.py b/cloudinit/sources/helpers/azure.py
index f5cdb3fd..fc760581 100755
--- a/cloudinit/sources/helpers/azure.py
+++ b/cloudinit/sources/helpers/azure.py
@@ -7,6 +7,7 @@ import re
import socket
import struct
import time
+import textwrap
from cloudinit.net import dhcp
from cloudinit import stages
@@ -48,6 +49,32 @@ def azure_ds_telemetry_reporter(func):
return impl
+def is_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 False
+
+ def swap_bytestring(s, width=2):
+ dd = [byte for byte in textwrap.wrap(s, 2)]
+ dd.reverse()
+ return ''.join(dd)
+
+ parts = current_id.split('-')
+ swapped_id = '-'.join([
+ swap_bytestring(parts[0]),
+ swap_bytestring(parts[1]),
+ swap_bytestring(parts[2]),
+ parts[3],
+ parts[4]
+ ])
+
+ return previous_id == swapped_id
+
+
@azure_ds_telemetry_reporter
def get_boot_telemetry():
"""Report timestamps related to kernel initialization and systemd