Merge ~smoser/cloud-init:fix/1766401-ibmcloud-upgrade-xenial into cloud-init:master

Proposed by Scott Moser
Status: Merged
Approved by: Chad Smith
Approved revision: 73864f648ea0de48eca36cfe3e214726d3891586
Merge reported by: Chad Smith
Merged at revision: 11172924a48a47a7231d19d9cefe628dfddda8bf
Proposed branch: ~smoser/cloud-init:fix/1766401-ibmcloud-upgrade-xenial
Merge into: cloud-init:master
Diff against target: 206 lines (+91/-14)
3 files modified
cloudinit/sources/DataSourceConfigDrive.py (+8/-3)
tests/unittests/test_ds_identify.py (+71/-6)
tools/ds-identify (+12/-5)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
Chad Smith Approve
Review via email: mp+344784@code.launchpad.net

Commit message

IBMCloud: Disable config-drive and nocloud only if IBMCloud is enabled.

Ubuntu images on IBMCloud for 16.04 have some seed data in
/var/lib/cloud/data/seed/nocloud-net. In order to have systems with
IBMCloud enabled, we modified ds-identify detection to skip that seed
if the system was on IBMCloud. That change did not consider the
fact that IBMCloud might not be in the datasource list.

There was similar logic in the ConfigDrive datasource in ds-identify
and the datasource itself.

Config drive is now updated to only check and avoid IBMCloud if IBMCloud
is enabled. The check in ds-identify for nocloud was dropped. If a
user provides a nocloud seed on IBMCloud, then that can be used.

This means that systems running Xenial will continue to get their
old datasources.

LP: #1766401

Description of the change

see commit message

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

FAILED: Continuous integration, rev:0b32d7c319523978e9bd568651d5b68dfe663313
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1073/
Executed test runs:
    SUCCESS: Checkout
    FAILED: Unit & Style Tests

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1073/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Scott Moser (smoser) wrote :

PPA at https://launchpad.net/~smoser/+archive/ubuntu/lp1766401 has a build with a proposed fix.

Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:01045b5d5f2706911688c6deca86d02f9da4facc
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1074/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    SUCCESS: MAAS Compatability Testing
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1074/rebuild

review: Approve (continuous-integration)
Revision history for this message
Scott Moser (smoser) wrote :

I've tested upgrading the from xenial image to the build in the ppa.
It seems to have gone correctly for each of the instances I launched.
Here are the results:
The paste is a result of running 'collect-info' from
  https://gist.github.com/smoser/94195d335b5af32efe1be056e413e130/

Basically I used our 'launch-softlayer' script to launch
via 'template' and 'oscode' and with and without user-data for each.
So 4 total instances.

Then collect info from each, upgrade, reboot, collect-info:

 $ wget https://gist.githubusercontent.com/smoser/94195d335b5af32efe1be056e413e130/raw/collect-info -O collect-info
 $ chmod 755 collect-info
 $ echo $(hostname) before $(./collect-info before $(hostname) | pastebinit)
 $ mv /var/log/cloud-init* .
 $ apt-add-repository -y ppa:smoser/lp1766401 && apt-get update -q
 $ apt-get install cloud-init
 $ reboot
 $ echo $(hostname) after $(./collect-info after $(hostname) | pastebinit)

xt-oscode-with before http://paste.ubuntu.com/p/gW9gR5WQnR/
xt-oscode-with after http://paste.ubuntu.com/p/Z7pM4bGjPy/
xt-oscode-without before http://paste.ubuntu.com/p/JJK3mm6gZ2/
xt-oscode-without after http://paste.ubuntu.com/p/RrSNSJnNbg/
xt-template-with before http://paste.ubuntu.com/p/2kFZ9wb768/
xt-template-with after http://paste.ubuntu.com/p/QtyYy3MBKm/
xt-template-without before http://paste.ubuntu.com/p/ZJZS8CkTYm/
xt-template-without after http://paste.ubuntu.com/p/GdPr4YT7jV/

Revision history for this message
Chad Smith (chad.smith) wrote :

Tested as well on systems broken by the previous SRU'd cloud-init. A 'cloud-init clean --reboot' properly detects the ConfigDrive datasource which presents the proper network configuration.
+1

Validated both clean and dirty reboot scenarios with user-data to confirm proper behavior.

review: Approve
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

FAILED: Continuous integration, rev:295aefac72a64ad08a5af09e28b0baa179e1ec47
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1077/
Executed test runs:
    SUCCESS: Checkout
    FAILED: Unit & Style Tests

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1077/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:d1342ce1567596f71141d9643fb1a7c1d0937bc1
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1078/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    SUCCESS: MAAS Compatability Testing
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1078/rebuild

review: Approve (continuous-integration)
Revision history for this message
Chad Smith (chad.smith) :
review: Approve
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:73864f648ea0de48eca36cfe3e214726d3891586
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1079/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    SUCCESS: MAAS Compatability Testing
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1079/rebuild

review: Approve (continuous-integration)
Revision history for this message
Chad Smith (chad.smith) wrote :

An upstream commit landed for this bug.

To view that commit see the following URL:
https://git.launchpad.net/cloud-init/commit/?id=11172924

There was an error fetching revisions from git servers. Please try again in a few minutes. If the problem persists, contact Launchpad support.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/cloudinit/sources/DataSourceConfigDrive.py b/cloudinit/sources/DataSourceConfigDrive.py
2index c7b5fe5..121cf21 100644
3--- a/cloudinit/sources/DataSourceConfigDrive.py
4+++ b/cloudinit/sources/DataSourceConfigDrive.py
5@@ -69,7 +69,8 @@ class DataSourceConfigDrive(openstack.SourceMixin, sources.DataSource):
6 util.logexc(LOG, "Failed reading config drive from %s", sdir)
7
8 if not found:
9- for dev in find_candidate_devs():
10+ dslist = self.sys_cfg.get('datasource_list')
11+ for dev in find_candidate_devs(dslist=dslist):
12 try:
13 # Set mtype if freebsd and turn off sync
14 if dev.startswith("/dev/cd"):
15@@ -211,7 +212,7 @@ def write_injected_files(files):
16 util.logexc(LOG, "Failed writing file: %s", filename)
17
18
19-def find_candidate_devs(probe_optical=True):
20+def find_candidate_devs(probe_optical=True, dslist=None):
21 """Return a list of devices that may contain the config drive.
22
23 The returned list is sorted by search order where the first item has
24@@ -227,6 +228,9 @@ def find_candidate_devs(probe_optical=True):
25 * either vfat or iso9660 formated
26 * labeled with 'config-2' or 'CONFIG-2'
27 """
28+ if dslist is None:
29+ dslist = []
30+
31 # query optical drive to get it in blkid cache for 2.6 kernels
32 if probe_optical:
33 for device in OPTICAL_DEVICES:
34@@ -257,7 +261,8 @@ def find_candidate_devs(probe_optical=True):
35 devices = [d for d in candidates
36 if d in by_label or not util.is_partition(d)]
37
38- if devices:
39+ LOG.debug("devices=%s dslist=%s", devices, dslist)
40+ if devices and "IBMCloud" in dslist:
41 # IBMCloud uses config-2 label, but limited to a single UUID.
42 ibm_platform, ibm_path = get_ibm_platform()
43 if ibm_path in devices:
44diff --git a/tests/unittests/test_ds_identify.py b/tests/unittests/test_ds_identify.py
45index ad7fe41..4d8a436 100644
46--- a/tests/unittests/test_ds_identify.py
47+++ b/tests/unittests/test_ds_identify.py
48@@ -184,17 +184,18 @@ class DsIdentifyBase(CiTestCase):
49 data, RC_FOUND, dslist=[data.get('ds'), DS_NONE])
50
51 def _check_via_dict(self, data, rc, dslist=None, **kwargs):
52- found_rc, out, err, cfg, files = self._call_via_dict(data, **kwargs)
53+ ret = self._call_via_dict(data, **kwargs)
54 good = False
55 try:
56- self.assertEqual(rc, found_rc)
57+ self.assertEqual(rc, ret.rc)
58 if dslist is not None:
59- self.assertEqual(dslist, cfg['datasource_list'])
60+ self.assertEqual(dslist, ret.cfg['datasource_list'])
61 good = True
62 finally:
63 if not good:
64- _print_run_output(rc, out, err, cfg, files)
65- return rc, out, err, cfg, files
66+ _print_run_output(ret.rc, ret.stdout, ret.stderr, ret.cfg,
67+ ret.files)
68+ return ret
69
70
71 class TestDsIdentify(DsIdentifyBase):
72@@ -245,13 +246,40 @@ class TestDsIdentify(DsIdentifyBase):
73 def test_config_drive(self):
74 """ConfigDrive datasource has a disk with LABEL=config-2."""
75 self._test_ds_found('ConfigDrive')
76- return
77
78 def test_config_drive_upper(self):
79 """ConfigDrive datasource has a disk with LABEL=CONFIG-2."""
80 self._test_ds_found('ConfigDriveUpper')
81 return
82
83+ def test_config_drive_seed(self):
84+ """Config Drive seed directory."""
85+ self._test_ds_found('ConfigDrive-seed')
86+
87+ def test_config_drive_interacts_with_ibmcloud_config_disk(self):
88+ """Verify ConfigDrive interaction with IBMCloud.
89+
90+ If ConfigDrive is enabled and not IBMCloud, then ConfigDrive
91+ should claim the ibmcloud 'config-2' disk.
92+ If IBMCloud is enabled, then ConfigDrive should skip."""
93+ data = copy.deepcopy(VALID_CFG['IBMCloud-config-2'])
94+ files = data.get('files', {})
95+ if not files:
96+ data['files'] = files
97+ cfgpath = 'etc/cloud/cloud.cfg.d/99_networklayer_common.cfg'
98+
99+ # with list including IBMCloud, config drive should be not found.
100+ files[cfgpath] = 'datasource_list: [ ConfigDrive, IBMCloud ]\n'
101+ ret = self._check_via_dict(data, shell_true)
102+ self.assertEqual(
103+ ret.cfg.get('datasource_list'), ['IBMCloud', 'None'])
104+
105+ # But if IBMCloud is not enabled, config drive should claim this.
106+ files[cfgpath] = 'datasource_list: [ ConfigDrive, NoCloud ]\n'
107+ ret = self._check_via_dict(data, shell_true)
108+ self.assertEqual(
109+ ret.cfg.get('datasource_list'), ['ConfigDrive', 'None'])
110+
111 def test_ibmcloud_template_userdata_in_provisioning(self):
112 """Template provisioned with user-data during provisioning stage.
113
114@@ -307,6 +335,37 @@ class TestDsIdentify(DsIdentifyBase):
115 self._check_via_dict(
116 data, rc=RC_FOUND, dslist=['ConfigDrive', DS_NONE])
117
118+ def test_ibmcloud_with_nocloud_seed(self):
119+ """NoCloud seed should be preferred over IBMCloud.
120+
121+ A nocloud seed should be preferred over IBMCloud even if enabled.
122+ Ubuntu 16.04 images have <vlc>/seed/nocloud-net. LP: #1766401."""
123+ data = copy.deepcopy(VALID_CFG['IBMCloud-config-2'])
124+ files = data.get('files', {})
125+ if not files:
126+ data['files'] = files
127+ files.update(VALID_CFG['NoCloud-seed']['files'])
128+ ret = self._check_via_dict(data, shell_true)
129+ self.assertEqual(
130+ ['NoCloud', 'IBMCloud', 'None'],
131+ ret.cfg.get('datasource_list'))
132+
133+ def test_ibmcloud_with_configdrive_seed(self):
134+ """ConfigDrive seed should be preferred over IBMCloud.
135+
136+ A ConfigDrive seed should be preferred over IBMCloud even if enabled.
137+ Ubuntu 16.04 images have a fstab entry that mounts the
138+ METADATA disk into <vlc>/seed/config_drive. LP: ##1766401."""
139+ data = copy.deepcopy(VALID_CFG['IBMCloud-config-2'])
140+ files = data.get('files', {})
141+ if not files:
142+ data['files'] = files
143+ files.update(VALID_CFG['ConfigDrive-seed']['files'])
144+ ret = self._check_via_dict(data, shell_true)
145+ self.assertEqual(
146+ ['ConfigDrive', 'IBMCloud', 'None'],
147+ ret.cfg.get('datasource_list'))
148+
149 def test_policy_disabled(self):
150 """A Builtin policy of 'disabled' should return not found.
151
152@@ -684,6 +743,12 @@ VALID_CFG = {
153 },
154 ],
155 },
156+ 'ConfigDrive-seed': {
157+ 'ds': 'ConfigDrive',
158+ 'files': {
159+ os.path.join(P_SEED_DIR, 'config_drive', 'openstack',
160+ 'latest', 'meta_data.json'): 'md\n'},
161+ },
162 'Hetzner': {
163 'ds': 'Hetzner',
164 'files': {P_SYS_VENDOR: 'Hetzner\n'},
165diff --git a/tools/ds-identify b/tools/ds-identify
166index 7fff5d1..9f0d96f 100755
167--- a/tools/ds-identify
168+++ b/tools/ds-identify
169@@ -601,7 +601,6 @@ dscheck_NoCloud() {
170 *\ ds=nocloud*) return ${DS_FOUND};;
171 esac
172
173- is_ibm_cloud && return ${DS_NOT_FOUND}
174 for d in nocloud nocloud-net; do
175 check_seed_dir "$d" meta-data user-data && return ${DS_FOUND}
176 check_writable_seed_dir "$d" meta-data user-data && return ${DS_FOUND}
177@@ -612,11 +611,12 @@ dscheck_NoCloud() {
178 return ${DS_NOT_FOUND}
179 }
180
181+is_ds_enabled() {
182+ local name="$1" pad=" ${DI_DSLIST} "
183+ [ "${pad#* $name }" != "${pad}" ]
184+}
185+
186 check_configdrive_v2() {
187- is_ibm_cloud && return ${DS_NOT_FOUND}
188- if has_fs_with_label CONFIG-2 config-2; then
189- return ${DS_FOUND}
190- fi
191 # look in /config-drive <vlc>/seed/config_drive for a directory
192 # openstack/YYYY-MM-DD format with a file meta_data.json
193 local d=""
194@@ -631,6 +631,13 @@ check_configdrive_v2() {
195 debug 1 "config drive seeded directory had only 'latest'"
196 return ${DS_FOUND}
197 fi
198+
199+ is_ds_enabled "IBMCloud"
200+ debug 1 "is_ds_enabled returned $?: $DI_DSLIST"
201+ is_ds_enabled "IBMCloud" && is_ibm_cloud && return ${DS_NOT_FOUND}
202+ if has_fs_with_label CONFIG-2 config-2; then
203+ return ${DS_FOUND}
204+ fi
205 return ${DS_NOT_FOUND}
206 }
207

Subscribers

People subscribed via source and target branches