← Back to team overview

cloud-init-dev team mailing list archive

[Merge] ~smoser/cloud-init:feature/1807466-ovf-guestinfo-transport into cloud-init:master

 

Scott Moser has proposed merging ~smoser/cloud-init:feature/1807466-ovf-guestinfo-transport into cloud-init:master.

Commit message:
Vmware: Add support for the com.vmware.guestInfo OVF transport.

This adds support for reading OVF information over the
'com.vmware.guestInfo' tranport.  The current implementation requires
vmware-rpctool be installed in the system.

LP: #1807466

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

For more details, see:
https://code.launchpad.net/~smoser/cloud-init/+git/cloud-init/+merge/361140
-- 
Your team cloud-init commiters is requested to review the proposed merge of ~smoser/cloud-init:feature/1807466-ovf-guestinfo-transport into cloud-init:master.
diff --git a/cloudinit/sources/DataSourceOVF.py b/cloudinit/sources/DataSourceOVF.py
index 045291e..ca57469 100644
--- a/cloudinit/sources/DataSourceOVF.py
+++ b/cloudinit/sources/DataSourceOVF.py
@@ -233,7 +233,7 @@ class DataSourceOVF(sources.DataSource):
 
         else:
             np = {'iso': transport_iso9660,
-                  'vmware-guestd': transport_vmware_guestd, }
+                  'com.vmware.guestInfo': transport_vmware_guestinfo}
             name = None
             for (name, transfunc) in np.items():
                 (contents, _dev, _fname) = transfunc()
@@ -503,17 +503,20 @@ def transport_iso9660(require_iso=True):
     return (False, None, None)
 
 
-def transport_vmware_guestd():
-    # http://blogs.vmware.com/vapp/2009/07/ \
-    #    selfconfiguration-and-the-ovf-environment.html
-    # try:
-    #     cmd = ['vmware-guestd', '--cmd', 'info-get guestinfo.ovfEnv']
-    #     (out, err) = subp(cmd)
-    #     return(out, 'guestinfo.ovfEnv', 'vmware-guestd')
-    # except:
-    #     # would need to error check here and see why this failed
-    #     # to know if log/error should be raised
-    #     return(False, None, None)
+def transport_vmware_guestinfo():
+    rpctool = "vmware-rpctool"
+    if not util.which(rpctool):
+        return None
+    cmd = [rpctool, "info-get guestinfo.ovfEnv"]
+    try:
+        out, _err = util.subp(cmd)
+        if out:
+            return (out, rpctool, "guestinfo.ovfEnv")
+        LOG.debug("cmd %s exited 0 with empty stdout: %s", cmd, out)
+    except util.ProcessExecutionError as e:
+        if e.exit_code != 1:
+            LOG.warn("%s exited with code %d", rpctool, e.exit_code)
+            LOG.debug(e)
     return (False, None, None)
 
 
diff --git a/tests/unittests/test_datasource/test_ovf.py b/tests/unittests/test_datasource/test_ovf.py
index a226c03..d1e6640 100644
--- a/tests/unittests/test_datasource/test_ovf.py
+++ b/tests/unittests/test_datasource/test_ovf.py
@@ -126,7 +126,7 @@ class TestDatasourceOVF(CiTestCase):
             'cloudinit.sources.DataSourceOVF',
             {'util.read_dmi_data': None,
              'transport_iso9660': (False, None, None),
-             'transport_vmware_guestd': (False, None, None)},
+             'transport_vmware_guestinfo': (False, None, None)},
             ds.get_data)
         self.assertFalse(retcode, 'Expected False return from ds.get_data')
         self.assertIn(
@@ -142,7 +142,7 @@ class TestDatasourceOVF(CiTestCase):
             'cloudinit.sources.DataSourceOVF',
             {'util.read_dmi_data': 'vmware',
              'transport_iso9660': (False, None, None),
-             'transport_vmware_guestd': (False, None, None)},
+             'transport_vmware_guestinfo': (False, None, None)},
             ds.get_data)
         self.assertFalse(retcode, 'Expected False return from ds.get_data')
         self.assertIn(
@@ -191,7 +191,7 @@ class TestDatasourceOVF(CiTestCase):
         self.assertEqual('ovf', ds.platform_type)
         MPATH = 'cloudinit.sources.DataSourceOVF.'
         with mock.patch(MPATH + 'util.read_dmi_data', return_value='!VMware'):
-            with mock.patch(MPATH + 'transport_vmware_guestd') as m_guestd:
+            with mock.patch(MPATH + 'transport_vmware_guestinfo') as m_guestd:
                 with mock.patch(MPATH + 'transport_iso9660') as m_iso9660:
                     m_iso9660.return_value = (None, 'ignored', 'ignored')
                     m_guestd.return_value = (None, 'ignored', 'ignored')
@@ -213,7 +213,7 @@ class TestDatasourceOVF(CiTestCase):
         self.assertEqual('ovf', ds.platform_type)
         MPATH = 'cloudinit.sources.DataSourceOVF.'
         with mock.patch(MPATH + 'util.read_dmi_data', return_value='VMWare'):
-            with mock.patch(MPATH + 'transport_vmware_guestd') as m_guestd:
+            with mock.patch(MPATH + 'transport_vmware_guestinfo') as m_guestd:
                 with mock.patch(MPATH + 'transport_iso9660') as m_iso9660:
                     m_iso9660.return_value = (None, 'ignored', 'ignored')
                     m_guestd.return_value = (None, 'ignored', 'ignored')
diff --git a/tests/unittests/test_ds_identify.py b/tests/unittests/test_ds_identify.py
index 80640f1..756b4fb 100644
--- a/tests/unittests/test_ds_identify.py
+++ b/tests/unittests/test_ds_identify.py
@@ -138,6 +138,9 @@ class DsIdentifyBase(CiTestCase):
             {'name': 'detect_virt', 'RET': 'none', 'ret': 1},
             {'name': 'uname', 'out': UNAME_MYSYS},
             {'name': 'blkid', 'out': BLKID_EFI_ROOT},
+            {'name': 'ovf_vmware_transport_guestinfo',
+             'out': 'No value found', 'ret': 1},
+
         ]
 
         written = [d['name'] for d in mocks]
@@ -475,6 +478,10 @@ class TestDsIdentify(DsIdentifyBase):
         """OVF is identified when iso9660 cdrom path contains ovf schema."""
         self._test_ds_found('OVF')
 
+    def test_ovf_on_vmware_guestinfo_found(self):
+        """OVF guest info is found on vmware."""
+        self._test_ds_found('OVF-guestinfo')
+
     def test_ovf_on_vmware_iso_found_when_vmware_customization(self):
         """OVF is identified when vmware customization is enabled."""
         self._test_ds_found('OVF-vmware-customization')
@@ -773,6 +780,14 @@ VALID_CFG = {
             'dev/sr0': 'pretend ovf iso has ' + OVF_MATCH_STRING + '\n',
         }
     },
+    'OVF-guestinfo': {
+        'ds': 'OVF',
+        'mocks': [
+            {'name': 'ovf_vmware_transport_guestinfo', 'ret': 0,
+             'out': '<?xml version="1.0" encoding="UTF-8"?>\n<Environment'},
+            MOCK_VIRT_IS_VMWARE,
+        ],
+    },
     'ConfigDrive': {
         'ds': 'ConfigDrive',
         'mocks': [
diff --git a/tools/ds-identify b/tools/ds-identify
index 1acfeeb..7de3ae3 100755
--- a/tools/ds-identify
+++ b/tools/ds-identify
@@ -726,6 +726,25 @@ ovf_vmware_guest_customization() {
     return 1
 }
 
+ovf_vmware_transport_guestinfo() {
+    [ "${DI_VIRT}" = "vmware" ] || return 1
+    command -v vmware-rpctool >/dev/null 2>&1 || return 1
+    local out="" ret=""
+    out=$(vmware-rpctool "info-get guestinfo.ovfEnv" 2>&1)
+    ret=$?
+    if [ $ret -ne 0 ]; then
+        debug 1 "Running on vmware but rpctool query returned $ret"
+        return 1
+    fi
+    case "$1" in
+        "<?xml"*|"<?XML"*) :;;
+        *) debug 1 "guestinfo.ovfEnv had non-xml content: $out";
+           return 1;;
+    esac
+    debug 1 "Found guestinfo transport."
+    return 0
+}
+
 is_cdrom_ovf() {
     local dev="$1" label="$2"
     # skip devices that don't look like cdrom paths.
@@ -758,6 +777,10 @@ dscheck_OVF() {
     # Azure provides ovf. Skip false positive by dis-allowing.
     is_azure_chassis && return $DS_NOT_FOUND
 
+    if [ "${DI_VIRT}" = "vmware" ]; then
+        ovf_vmware_transport_guestinfo && return "${DS_FOUND}"
+    fi
+
     # DI_ISO9660_DEVS is <device>=label,<device>=label2
     # like /dev/sr0=OVF-TRANSPORT,/dev/other=with spaces
     if [ "${DI_ISO9660_DEVS#${UNAVAILABLE}:}" = "${DI_ISO9660_DEVS}" ]; then

References