Merge ~smoser/cloud-init:fix/ds-identify-smartos-is-container into cloud-init:master

Proposed by Scott Moser
Status: Merged
Approved by: Chad Smith
Approved revision: bc9a7e1b8ba845b71a7c06067498a0ccd0302a09
Merge reported by: Scott Moser
Merged at revision: 0d7ee5592621d09699d079945ffd6febf16669b2
Proposed branch: ~smoser/cloud-init:fix/ds-identify-smartos-is-container
Merge into: cloud-init:master
Diff against target: 152 lines (+57/-10)
3 files modified
cloudinit/sources/DataSourceSmartOS.py (+2/-2)
tests/unittests/test_ds_identify.py (+48/-3)
tools/ds-identify (+7/-5)
Reviewer Review Type Date Requested Status
Chad Smith Approve
Server Team CI bot continuous-integration Approve
Mike Gerdts (community) Approve
Review via email: mp+343738@code.launchpad.net

Commit message

ds-identify: recognize container-other as a container, test SmartOS.

In playing with a SmartOS container I found that ds-identify did
not identify the container there as a container. Systemd-detect-virt
identifies it as 'container-other'.

Also here are tests for ds-identify for the SmartOS platform
identification, and some indentation fixes in ds-identify.

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 :

PASSED: Continuous integration, rev:0b32c3c25c632c7ea630ab93ac00b3ef3f722b3f
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1040/
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/1040/rebuild

review: Approve (continuous-integration)
Revision history for this message
Mike Gerdts (mgerdts) wrote :

Code seems fine, but this is the first time I've looked at this part of cloud-init. Would be best to have a second reviewer.

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

PASSED: Continuous integration, rev:2c99bef83c7631c3559255ba520154ce3e20f553
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1095/
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/1095/rebuild

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

Also shouldntx`

Revision history for this message
Scott Moser (smoser) wrote :

thanks for the thoughtful review.

i responded inline.

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

PASSED: Continuous integration, rev:bc9a7e1b8ba845b71a7c06067498a0ccd0302a09
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1112/
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/1112/rebuild

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

+1 here, thanks for this change I'll trust "${PATH_ROOT}/native/.zonecontrol/metadata.sock" exists on SmartOS for our use case here. I validated that we don't accidentally detect other datasources even if SmartOS is first in datasource_list. The only question I had (as I have no SmartOS account) is whether we still detect SmartOS on the desired non-container platform and it feels a bit strange that we aren't detecting/rejecting using the same type of logic in DataSourceSmartOS that ds-identify is using, but that may be minutia that doesn't really matter (as it'd be platform sub-type detection difference which would still be using the proper base datasource).

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

What did you think we were missing? Anything more than just checking for
the socket file in get_smartos_environ?
http://paste.ubuntu.com/p/3z7R6J8fV5/

I think if we do that , then get_data will get out quickly . As it is
right now, in a lxc container inside the smart-os-container get_data would
take the path:

if not self.smartos_type:
            LOG.debug("Not running on smartos")

We should do that.

On Thu, May 10, 2018 at 3:19 PM, Chad Smith <email address hidden>
wrote:

> Review: Approve
>
> +1 here, thanks for this change I'll trust "${PATH_ROOT}/native/.zonecontrol/metadata.sock"
> exists on SmartOS for our use case here. I validated that we don't
> accidentally detect other datasources even if SmartOS is first in
> datasource_list. The only question I had (as I have no SmartOS account) is
> whether we still detect SmartOS on the desired non-container platform and
> it feels a bit strange that we aren't detecting/rejecting using the same
> type of logic in DataSourceSmartOS that ds-identify is using, but that may
> be minutia that doesn't really matter (as it'd be platform sub-type
> detection difference which would still be using the proper base datasource).
> --
> https://code.launchpad.net/~smoser/cloud-init/+git/cloud-
> init/+merge/343738
> You are the owner of ~smoser/cloud-init:fix/ds-
> identify-smartos-is-container.
>

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

The difference between python's get_smartos_environ() and ds-identify:

1. Ordering of the checks (kernel version versus system-product-name) is reversed in python. As you mentioned, maybe it's faster in python to field the uname call than to parse and lower system-product-name sysfs.

2. Less strict matching of system-product-name in python than in ds-identify
 'smartdc' in system_type.lower() instead of system_type.startswith('SmartDC')

3. Missing the sockfile test when matching the kernel and we match either upper or lowercase 'BrandZ virtual linux' in python.

they are minor differences, but those differences could lead to mis-matches from ds-identify where python would pass. I just wanted to see those differences tidied up a bit where sensible. I'm ok if you believe that is overkill in this case.

Revision history for this message
Scott Moser (smoser) wrote :

1. Order doesn't really matter, the end result is the same. we can change them but I dont consider that a problem unless I'm misunderstanding.
2. shell case insenstive matching is costly, so I had just done case sensitive there and the case insensitive in python.
I've added a commit to put python in case-sensitive match.
3. I think we *are* correctly going to return None in get_data on SmartOS if there is no METADATA_SOCKFILE .

get_smartos_environ doesn't check for the file, but when the client is created, a 'exists' is immediately done, and *that* will check for the presene of that file.

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

+1 Scott thanks for the back and forth

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

An upstream commit landed for this bug.

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

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/DataSourceSmartOS.py b/cloudinit/sources/DataSourceSmartOS.py
2index 4ea00eb..fcb46b1 100644
3--- a/cloudinit/sources/DataSourceSmartOS.py
4+++ b/cloudinit/sources/DataSourceSmartOS.py
5@@ -745,7 +745,7 @@ def get_smartos_environ(uname_version=None, product_name=None):
6 # report 'BrandZ virtual linux' as the kernel version
7 if uname_version is None:
8 uname_version = uname[3]
9- if uname_version.lower() == 'brandz virtual linux':
10+ if uname_version == 'BrandZ virtual linux':
11 return SMARTOS_ENV_LX_BRAND
12
13 if product_name is None:
14@@ -753,7 +753,7 @@ def get_smartos_environ(uname_version=None, product_name=None):
15 else:
16 system_type = product_name
17
18- if system_type and 'smartdc' in system_type.lower():
19+ if system_type and system_type.startswith('SmartDC'):
20 return SMARTOS_ENV_KVM
21
22 return None
23diff --git a/tests/unittests/test_ds_identify.py b/tests/unittests/test_ds_identify.py
24index 4d8a436..7f12be5 100644
25--- a/tests/unittests/test_ds_identify.py
26+++ b/tests/unittests/test_ds_identify.py
27@@ -10,7 +10,8 @@ from cloudinit import util
28 from cloudinit.tests.helpers import (
29 CiTestCase, dir2dict, populate_dir, populate_dir_with_ts)
30
31-from cloudinit.sources import DataSourceIBMCloud as dsibm
32+from cloudinit.sources import DataSourceIBMCloud as ds_ibm
33+from cloudinit.sources import DataSourceSmartOS as ds_smartos
34
35 UNAME_MYSYS = ("Linux bart 4.4.0-62-generic #83-Ubuntu "
36 "SMP Wed Jan 18 14:10:15 UTC 2017 x86_64 GNU/Linux")
37@@ -69,8 +70,12 @@ P_DSID_CFG = "etc/cloud/ds-identify.cfg"
38
39 IBM_CONFIG_UUID = "9796-932E"
40
41+MOCK_VIRT_IS_CONTAINER_OTHER = {'name': 'detect_virt',
42+ 'RET': 'container-other', 'ret': 0}
43 MOCK_VIRT_IS_KVM = {'name': 'detect_virt', 'RET': 'kvm', 'ret': 0}
44 MOCK_VIRT_IS_VMWARE = {'name': 'detect_virt', 'RET': 'vmware', 'ret': 0}
45+# currenty' SmartOS hypervisor "bhyve" is unknown by systemd-detect-virt.
46+MOCK_VIRT_IS_VM_OTHER = {'name': 'detect_virt', 'RET': 'vm-other', 'ret': 0}
47 MOCK_VIRT_IS_XEN = {'name': 'detect_virt', 'RET': 'xen', 'ret': 0}
48 MOCK_UNAME_IS_PPC64 = {'name': 'uname', 'out': UNAME_PPC64EL, 'ret': 0}
49
50@@ -330,7 +335,7 @@ class TestDsIdentify(DsIdentifyBase):
51 break
52 if not offset:
53 raise ValueError("Expected to find 'blkid' mock, but did not.")
54- data['mocks'][offset]['out'] = d['out'].replace(dsibm.IBM_CONFIG_UUID,
55+ data['mocks'][offset]['out'] = d['out'].replace(ds_ibm.IBM_CONFIG_UUID,
56 "DEAD-BEEF")
57 self._check_via_dict(
58 data, rc=RC_FOUND, dslist=['ConfigDrive', DS_NONE])
59@@ -516,6 +521,20 @@ class TestDsIdentify(DsIdentifyBase):
60 """Hetzner cloud is identified in sys_vendor."""
61 self._test_ds_found('Hetzner')
62
63+ def test_smartos_bhyve(self):
64+ """SmartOS cloud identified by SmartDC in dmi."""
65+ self._test_ds_found('SmartOS-bhyve')
66+
67+ def test_smartos_lxbrand(self):
68+ """SmartOS cloud identified on lxbrand container."""
69+ self._test_ds_found('SmartOS-lxbrand')
70+
71+ def test_smartos_lxbrand_requires_socket(self):
72+ """SmartOS cloud should not be identified if no socket file."""
73+ mycfg = copy.deepcopy(VALID_CFG['SmartOS-lxbrand'])
74+ del mycfg['files'][ds_smartos.METADATA_SOCKFILE]
75+ self._check_via_dict(mycfg, rc=RC_NOT_FOUND, policy_dmi="disabled")
76+
77
78 class TestIsIBMProvisioning(DsIdentifyBase):
79 """Test the is_ibm_provisioning method in ds-identify."""
80@@ -777,7 +796,7 @@ VALID_CFG = {
81 [{'DEVNAME': 'xvda1', 'TYPE': 'ext3', 'PARTUUID': uuid4(),
82 'UUID': uuid4(), 'LABEL': 'cloudimg-bootfs'},
83 {'DEVNAME': 'xvdb', 'TYPE': 'vfat', 'LABEL': 'config-2',
84- 'UUID': dsibm.IBM_CONFIG_UUID},
85+ 'UUID': ds_ibm.IBM_CONFIG_UUID},
86 {'DEVNAME': 'xvda2', 'TYPE': 'ext4',
87 'LABEL': 'cloudimg-rootfs', 'PARTUUID': uuid4(),
88 'UUID': uuid4()},
89@@ -798,6 +817,32 @@ VALID_CFG = {
90 },
91 ],
92 },
93+ 'SmartOS-bhyve': {
94+ 'ds': 'SmartOS',
95+ 'mocks': [
96+ MOCK_VIRT_IS_VM_OTHER,
97+ {'name': 'blkid', 'ret': 0,
98+ 'out': blkid_out(
99+ [{'DEVNAME': 'vda1', 'TYPE': 'ext4',
100+ 'PARTUUID': '49ec635a-01'},
101+ {'DEVNAME': 'vda2', 'TYPE': 'swap',
102+ 'LABEL': 'cloudimg-swap', 'PARTUUID': '49ec635a-02'}]),
103+ },
104+ ],
105+ 'files': {P_PRODUCT_NAME: 'SmartDC HVM\n'},
106+ },
107+ 'SmartOS-lxbrand': {
108+ 'ds': 'SmartOS',
109+ 'mocks': [
110+ MOCK_VIRT_IS_CONTAINER_OTHER,
111+ {'name': 'uname', 'ret': 0,
112+ 'out': ("Linux d43da87a-daca-60e8-e6d4-d2ed372662a3 4.3.0 "
113+ "BrandZ virtual linux x86_64 GNU/Linux")},
114+ {'name': 'blkid', 'ret': 2, 'out': ''},
115+ ],
116+ 'files': {ds_smartos.METADATA_SOCKFILE: 'would be a socket\n'},
117+ }
118+
119 }
120
121 # vi: ts=4 expandtab
122diff --git a/tools/ds-identify b/tools/ds-identify
123index 435a5bc..dc7ac3a 100755
124--- a/tools/ds-identify
125+++ b/tools/ds-identify
126@@ -261,7 +261,7 @@ read_virt() {
127
128 is_container() {
129 case "${DI_VIRT}" in
130- lxc|lxc-libvirt|systemd-nspawn|docker|rkt) return 0;;
131+ container-other|lxc|lxc-libvirt|systemd-nspawn|docker|rkt) return 0;;
132 *) return 1;;
133 esac
134 }
135@@ -990,12 +990,14 @@ dscheck_SmartOS() {
136 # joyent cloud has two virt types: kvm and container
137 # on kvm, product name on joyent public cloud shows 'SmartDC HVM'
138 # on the container platform, uname's version has: BrandZ virtual linux
139+ # for container, we also verify that the socketfile exists to protect
140+ # against embedded containers (lxd running on brandz)
141 local smartdc_kver="BrandZ virtual linux"
142+ local metadata_sockfile="${PATH_ROOT}/native/.zonecontrol/metadata.sock"
143 dmi_product_name_matches "SmartDC*" && return $DS_FOUND
144- if [ "${DI_UNAME_KERNEL_VERSION}" = "${smartdc_kver}" ] &&
145- [ "${DI_VIRT}" = "container-other" ]; then
146- return ${DS_FOUND}
147- fi
148+ [ "${DI_UNAME_KERNEL_VERSION}" = "${smartdc_kver}" ] &&
149+ [ -e "${metadata_sockfile}" ] &&
150+ return ${DS_FOUND}
151 return ${DS_NOT_FOUND}
152 }
153

Subscribers

People subscribed via source and target branches