sailesh1993 / rpms / cloud-init

Forked from rpms/cloud-init a year ago
Clone
c36ff1
From 83f3d481c5f0d962bff5bacfd2c323529754869e Mon Sep 17 00:00:00 2001
c36ff1
From: Amy Chen <xiachen@redhat.com>
c36ff1
Date: Thu, 2 Dec 2021 18:11:08 +0800
c36ff1
Subject: [PATCH] fix error on upgrade caused by new vendordata2 attributes
c36ff1
c36ff1
RH-Author: xiachen <None>
c36ff1
RH-MergeRequest: 14: fix error on upgrade caused by new vendordata2 attributes
c36ff1
RH-Commit: [1/1] ef14db399cd1fe6e4ba847d98acee15fef8021de (xiachen/cloud-init-centos)
c36ff1
RH-Bugzilla: 2028381
c36ff1
RH-Acked-by: Eduardo Otubo <otubo@redhat.com>
c36ff1
RH-Acked-by: Mohamed Gamal Morsy <mmorsy@redhat.com>
c36ff1
RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
c36ff1
c36ff1
commit d132356cc361abef2d90d4073438f3ab759d5964
c36ff1
Author: James Falcon <TheRealFalcon@users.noreply.github.com>
c36ff1
Date:   Mon Apr 19 11:31:28 2021 -0500
c36ff1
c36ff1
    fix error on upgrade caused by new vendordata2 attributes (#869)
c36ff1
c36ff1
    In #777, we added 'vendordata2' and 'vendordata2_raw' attributes to
c36ff1
    the DataSource class, but didn't use the upgrade framework to deal
c36ff1
    with an unpickle after upgrade. This commit adds the necessary
c36ff1
    upgrade code.
c36ff1
c36ff1
    Additionally, added a smaller-scope upgrade test to our integration
c36ff1
    tests that will be run on every CI run so we catch these issues
c36ff1
    immediately in the future.
c36ff1
c36ff1
    LP: #1922739
c36ff1
c36ff1
Signed-off-by: Amy Chen <xiachen@redhat.com>
c36ff1
---
c36ff1
 cloudinit/sources/__init__.py           | 12 +++++++++++-
c36ff1
 cloudinit/tests/test_upgrade.py         |  4 ++++
c36ff1
 tests/integration_tests/clouds.py       |  4 ++--
c36ff1
 tests/integration_tests/test_upgrade.py | 25 ++++++++++++++++++++++++-
c36ff1
 4 files changed, 41 insertions(+), 4 deletions(-)
c36ff1
c36ff1
diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py
c36ff1
index 1ad1880d..7d74f8d9 100644
c36ff1
--- a/cloudinit/sources/__init__.py
c36ff1
+++ b/cloudinit/sources/__init__.py
c36ff1
@@ -24,6 +24,7 @@ from cloudinit import util
c36ff1
 from cloudinit.atomic_helper import write_json
c36ff1
 from cloudinit.event import EventType
c36ff1
 from cloudinit.filters import launch_index
c36ff1
+from cloudinit.persistence import CloudInitPickleMixin
c36ff1
 from cloudinit.reporting import events
c36ff1
 
c36ff1
 DSMODE_DISABLED = "disabled"
c36ff1
@@ -134,7 +135,7 @@ URLParams = namedtuple(
c36ff1
     'URLParms', ['max_wait_seconds', 'timeout_seconds', 'num_retries'])
c36ff1
 
c36ff1
 
c36ff1
-class DataSource(metaclass=abc.ABCMeta):
c36ff1
+class DataSource(CloudInitPickleMixin, metaclass=abc.ABCMeta):
c36ff1
 
c36ff1
     dsmode = DSMODE_NETWORK
c36ff1
     default_locale = 'en_US.UTF-8'
c36ff1
@@ -196,6 +197,8 @@ class DataSource(metaclass=abc.ABCMeta):
c36ff1
     # non-root users
c36ff1
     sensitive_metadata_keys = ('merged_cfg', 'security-credentials',)
c36ff1
 
c36ff1
+    _ci_pkl_version = 1
c36ff1
+
c36ff1
     def __init__(self, sys_cfg, distro, paths, ud_proc=None):
c36ff1
         self.sys_cfg = sys_cfg
c36ff1
         self.distro = distro
c36ff1
@@ -218,6 +221,13 @@ class DataSource(metaclass=abc.ABCMeta):
c36ff1
         else:
c36ff1
             self.ud_proc = ud_proc
c36ff1
 
c36ff1
+    def _unpickle(self, ci_pkl_version: int) -> None:
c36ff1
+        """Perform deserialization fixes for Paths."""
c36ff1
+        if not hasattr(self, 'vendordata2'):
c36ff1
+            self.vendordata2 = None
c36ff1
+        if not hasattr(self, 'vendordata2_raw'):
c36ff1
+            self.vendordata2_raw = None
c36ff1
+
c36ff1
     def __str__(self):
c36ff1
         return type_utils.obj_name(self)
c36ff1
 
c36ff1
diff --git a/cloudinit/tests/test_upgrade.py b/cloudinit/tests/test_upgrade.py
c36ff1
index f79a2536..71cea616 100644
c36ff1
--- a/cloudinit/tests/test_upgrade.py
c36ff1
+++ b/cloudinit/tests/test_upgrade.py
c36ff1
@@ -43,3 +43,7 @@ class TestUpgrade:
c36ff1
     def test_blacklist_drivers_set_on_networking(self, previous_obj_pkl):
c36ff1
         """We always expect Networking.blacklist_drivers to be initialised."""
c36ff1
         assert previous_obj_pkl.distro.networking.blacklist_drivers is None
c36ff1
+
c36ff1
+    def test_vendordata_exists(self, previous_obj_pkl):
c36ff1
+        assert previous_obj_pkl.vendordata2 is None
c36ff1
+        assert previous_obj_pkl.vendordata2_raw is None
c36ff1
\ No newline at end of file
c36ff1
diff --git a/tests/integration_tests/clouds.py b/tests/integration_tests/clouds.py
c36ff1
index 9527a413..1d0b9d83 100644
c36ff1
--- a/tests/integration_tests/clouds.py
c36ff1
+++ b/tests/integration_tests/clouds.py
c36ff1
@@ -100,14 +100,14 @@ class IntegrationCloud(ABC):
c36ff1
             # Even if we're using the default key, it may still have a
c36ff1
             # different name in the clouds, so we need to set it separately.
c36ff1
             self.cloud_instance.key_pair.name = settings.KEYPAIR_NAME
c36ff1
-        self._released_image_id = self._get_initial_image()
c36ff1
+        self.released_image_id = self._get_initial_image()
c36ff1
         self.snapshot_id = None
c36ff1
 
c36ff1
     @property
c36ff1
     def image_id(self):
c36ff1
         if self.snapshot_id:
c36ff1
             return self.snapshot_id
c36ff1
-        return self._released_image_id
c36ff1
+        return self.released_image_id
c36ff1
 
c36ff1
     def emit_settings_to_log(self) -> None:
c36ff1
         log.info(
c36ff1
diff --git a/tests/integration_tests/test_upgrade.py b/tests/integration_tests/test_upgrade.py
c36ff1
index c20cb3c1..48e0691b 100644
c36ff1
--- a/tests/integration_tests/test_upgrade.py
c36ff1
+++ b/tests/integration_tests/test_upgrade.py
c36ff1
@@ -1,4 +1,5 @@
c36ff1
 import logging
c36ff1
+import os
c36ff1
 import pytest
c36ff1
 import time
c36ff1
 from pathlib import Path
c36ff1
@@ -8,6 +9,8 @@ from tests.integration_tests.conftest import (
c36ff1
     get_validated_source,
c36ff1
     session_start_time,
c36ff1
 )
c36ff1
+from tests.integration_tests.instances import CloudInitSource
c36ff1
+
c36ff1
 
c36ff1
 log = logging.getLogger('integration_testing')
c36ff1
 
c36ff1
@@ -63,7 +66,7 @@ def test_upgrade(session_cloud: IntegrationCloud):
c36ff1
         return  # type checking doesn't understand that skip raises
c36ff1
 
c36ff1
     launch_kwargs = {
c36ff1
-        'image_id': session_cloud._get_initial_image(),
c36ff1
+        'image_id': session_cloud.released_image_id,
c36ff1
     }
c36ff1
 
c36ff1
     image = ImageSpecification.from_os_image()
c36ff1
@@ -93,6 +96,26 @@ def test_upgrade(session_cloud: IntegrationCloud):
c36ff1
         instance.install_new_cloud_init(source, take_snapshot=False)
c36ff1
         instance.execute('hostname something-else')
c36ff1
         _restart(instance)
c36ff1
+        assert instance.execute('cloud-init status --wait --long').ok
c36ff1
         _output_to_compare(instance, after_path, netcfg_path)
c36ff1
 
c36ff1
     log.info('Wrote upgrade test logs to %s and %s', before_path, after_path)
c36ff1
+
c36ff1
+
c36ff1
+@pytest.mark.ci
c36ff1
+@pytest.mark.ubuntu
c36ff1
+def test_upgrade_package(session_cloud: IntegrationCloud):
c36ff1
+    if get_validated_source(session_cloud) != CloudInitSource.DEB_PACKAGE:
c36ff1
+        not_run_message = 'Test only supports upgrading to build deb'
c36ff1
+        if os.environ.get('TRAVIS'):
c36ff1
+            # If this isn't running on CI, we should know
c36ff1
+            pytest.fail(not_run_message)
c36ff1
+        else:
c36ff1
+            pytest.skip(not_run_message)
c36ff1
+
c36ff1
+    launch_kwargs = {'image_id': session_cloud.released_image_id}
c36ff1
+
c36ff1
+    with session_cloud.launch(launch_kwargs=launch_kwargs) as instance:
c36ff1
+        instance.install_deb()
c36ff1
+        instance.restart()
c36ff1
+        assert instance.execute('cloud-init status --wait --long').ok
c36ff1
-- 
c36ff1
2.27.0
c36ff1