summaryrefslogtreecommitdiff
path: root/tests/unittests
diff options
context:
space:
mode:
authorChad Smith <chad.smith@canonical.com>2018-10-09 21:46:35 +0000
committerServer Team CI Bot <josh.powers+server-team-bot@canonical.com>2018-10-09 21:46:35 +0000
commitf0bc02d7e221c9aa5982b267739481420c761ead (patch)
treefb45cab8d2e9a44564eea23db18b0c3566fabe2a /tests/unittests
parent00e36d3ded0b0f81f352de993036fc9f89e14a7a (diff)
downloadvyos-cloud-init-f0bc02d7e221c9aa5982b267739481420c761ead.tar.gz
vyos-cloud-init-f0bc02d7e221c9aa5982b267739481420c761ead.zip
instance-data: Add standard keys platform and subplatform. Refactor ec2.
Add the following instance-data.json standardized keys: * v1._beta_keys: List any v1 keys in beta development, e.g. ['subplatform']. * v1.public_ssh_keys: List of any cloud-provided ssh keys for the instance. * v1.platform: String representing the cloud platform api supporting the datasource. For example: 'ec2' for aws, aliyun and brightbox cloud names. * v1.subplatform: String with more details about the source of the metadata consumed. For example, metadata uri, config drive device path or seed directory. To support the new platform and subplatform standardized instance-data, DataSource and its subclasses grew platform and subplatform attributes. The platform attribute defaults to the lowercase string datasource name at self.dsname. This method is overridden in NoCloud, Ec2 and ConfigDrive datasources. The subplatform attribute calls a _get_subplatform method which will return a string containing a simple slug for subplatform type such as metadata, seed-dir or config-drive followed by a detailed uri, device or directory path where the datasource consumed its configuration. As part of this work, DatasourceEC2 methods _get_data and _crawl_metadata have been refactored for a few reasons: - crawl_metadata is now a read-only operation, persisting no attributes on the datasource instance and returns a dictionary of consumed metadata. - crawl_metadata now closely represents the raw stucture of the ec2 metadata consumed, so that end-users can leverage public ec2 metadata documentation where possible. - crawl_metadata adds a '_metadata_api_version' key to the crawled ds.metadata to advertise what version of EC2's api was consumed by cloud-init. - _get_data now does all the processing of crawl_metadata and saves datasource instance attributes userdata_raw, metadata etc. Additional drive-bys: * unit test rework for test_altcloud and test_azure to simplify mocks and make use of existing util and test_helpers functions.
Diffstat (limited to 'tests/unittests')
-rw-r--r--tests/unittests/test_datasource/test_aliyun.py4
-rw-r--r--tests/unittests/test_datasource/test_altcloud.py118
-rw-r--r--tests/unittests/test_datasource/test_azure.py110
-rw-r--r--tests/unittests/test_datasource/test_cloudsigma.py6
-rw-r--r--tests/unittests/test_datasource/test_configdrive.py3
-rw-r--r--tests/unittests/test_datasource/test_ec2.py20
-rw-r--r--tests/unittests/test_datasource/test_ibmcloud.py40
-rw-r--r--tests/unittests/test_datasource/test_nocloud.py45
-rw-r--r--tests/unittests/test_datasource/test_opennebula.py4
-rw-r--r--tests/unittests/test_datasource/test_ovf.py52
-rw-r--r--tests/unittests/test_datasource/test_smartos.py7
11 files changed, 289 insertions, 120 deletions
diff --git a/tests/unittests/test_datasource/test_aliyun.py b/tests/unittests/test_datasource/test_aliyun.py
index 1e77842f..e9213ca1 100644
--- a/tests/unittests/test_datasource/test_aliyun.py
+++ b/tests/unittests/test_datasource/test_aliyun.py
@@ -140,6 +140,10 @@ class TestAliYunDatasource(test_helpers.HttprettyTestCase):
self._test_get_sshkey()
self._test_get_iid()
self._test_host_name()
+ self.assertEqual('aliyun', self.ds.cloud_name)
+ self.assertEqual('ec2', self.ds.platform)
+ self.assertEqual(
+ 'metadata (http://100.100.100.200)', self.ds.subplatform)
@mock.patch("cloudinit.sources.DataSourceAliYun._is_aliyun")
def test_returns_false_when_not_on_aliyun(self, m_is_aliyun):
diff --git a/tests/unittests/test_datasource/test_altcloud.py b/tests/unittests/test_datasource/test_altcloud.py
index ff35904e..3119bfac 100644
--- a/tests/unittests/test_datasource/test_altcloud.py
+++ b/tests/unittests/test_datasource/test_altcloud.py
@@ -10,7 +10,6 @@
This test file exercises the code in sources DataSourceAltCloud.py
'''
-import mock
import os
import shutil
import tempfile
@@ -18,32 +17,13 @@ import tempfile
from cloudinit import helpers
from cloudinit import util
-from cloudinit.tests.helpers import CiTestCase
+from cloudinit.tests.helpers import CiTestCase, mock
import cloudinit.sources.DataSourceAltCloud as dsac
OS_UNAME_ORIG = getattr(os, 'uname')
-def _write_cloud_info_file(value):
- '''
- Populate the CLOUD_INFO_FILE which would be populated
- with a cloud backend identifier ImageFactory when building
- an image with ImageFactory.
- '''
- cifile = open(dsac.CLOUD_INFO_FILE, 'w')
- cifile.write(value)
- cifile.close()
- os.chmod(dsac.CLOUD_INFO_FILE, 0o664)
-
-
-def _remove_cloud_info_file():
- '''
- Remove the test CLOUD_INFO_FILE
- '''
- os.remove(dsac.CLOUD_INFO_FILE)
-
-
def _write_user_data_files(mount_dir, value):
'''
Populate the deltacloud_user_data_file the user_data_file
@@ -98,13 +78,15 @@ def _dmi_data(expected):
class TestGetCloudType(CiTestCase):
- '''
- Test to exercise method: DataSourceAltCloud.get_cloud_type()
- '''
+ '''Test to exercise method: DataSourceAltCloud.get_cloud_type()'''
+
+ with_logs = True
def setUp(self):
'''Set up.'''
- self.paths = helpers.Paths({'cloud_dir': '/tmp'})
+ super(TestGetCloudType, self).setUp()
+ self.tmp = self.tmp_dir()
+ self.paths = helpers.Paths({'cloud_dir': self.tmp})
self.dmi_data = util.read_dmi_data
# We have a different code path for arm to deal with LP1243287
# We have to switch arch to x86_64 to avoid test failure
@@ -115,6 +97,26 @@ class TestGetCloudType(CiTestCase):
util.read_dmi_data = self.dmi_data
force_arch()
+ def test_cloud_info_file_ioerror(self):
+ """Return UNKNOWN when /etc/sysconfig/cloud-info exists but errors."""
+ self.assertEqual('/etc/sysconfig/cloud-info', dsac.CLOUD_INFO_FILE)
+ dsrc = dsac.DataSourceAltCloud({}, None, self.paths)
+ # Attempting to read the directory generates IOError
+ with mock.patch.object(dsac, 'CLOUD_INFO_FILE', self.tmp):
+ self.assertEqual('UNKNOWN', dsrc.get_cloud_type())
+ self.assertIn(
+ "[Errno 21] Is a directory: '%s'" % self.tmp,
+ self.logs.getvalue())
+
+ def test_cloud_info_file(self):
+ """Return uppercase stripped content from /etc/sysconfig/cloud-info."""
+ dsrc = dsac.DataSourceAltCloud({}, None, self.paths)
+ cloud_info = self.tmp_path('cloud-info', dir=self.tmp)
+ util.write_file(cloud_info, ' OverRiDdeN CloudType ')
+ # Attempting to read the directory generates IOError
+ with mock.patch.object(dsac, 'CLOUD_INFO_FILE', cloud_info):
+ self.assertEqual('OVERRIDDEN CLOUDTYPE', dsrc.get_cloud_type())
+
def test_rhev(self):
'''
Test method get_cloud_type() for RHEVm systems.
@@ -153,60 +155,57 @@ class TestGetDataCloudInfoFile(CiTestCase):
self.tmp = self.tmp_dir()
self.paths = helpers.Paths(
{'cloud_dir': self.tmp, 'run_dir': self.tmp})
- self.cloud_info_file = tempfile.mkstemp()[1]
- self.dmi_data = util.read_dmi_data
- dsac.CLOUD_INFO_FILE = self.cloud_info_file
-
- def tearDown(self):
- # Reset
-
- # Attempt to remove the temp file ignoring errors
- try:
- os.remove(self.cloud_info_file)
- except OSError:
- pass
-
- util.read_dmi_data = self.dmi_data
- dsac.CLOUD_INFO_FILE = '/etc/sysconfig/cloud-info'
+ self.cloud_info_file = self.tmp_path('cloud-info', dir=self.tmp)
def test_rhev(self):
'''Success Test module get_data() forcing RHEV.'''
- _write_cloud_info_file('RHEV')
+ util.write_file(self.cloud_info_file, 'RHEV')
dsrc = dsac.DataSourceAltCloud({}, None, self.paths)
dsrc.user_data_rhevm = lambda: True
- self.assertEqual(True, dsrc.get_data())
+ with mock.patch.object(dsac, 'CLOUD_INFO_FILE', self.cloud_info_file):
+ self.assertEqual(True, dsrc.get_data())
+ self.assertEqual('altcloud', dsrc.cloud_name)
+ self.assertEqual('altcloud', dsrc.platform_type)
+ self.assertEqual('rhev (/dev/fd0)', dsrc.subplatform)
def test_vsphere(self):
'''Success Test module get_data() forcing VSPHERE.'''
- _write_cloud_info_file('VSPHERE')
+ util.write_file(self.cloud_info_file, 'VSPHERE')
dsrc = dsac.DataSourceAltCloud({}, None, self.paths)
dsrc.user_data_vsphere = lambda: True
- self.assertEqual(True, dsrc.get_data())
+ with mock.patch.object(dsac, 'CLOUD_INFO_FILE', self.cloud_info_file):
+ self.assertEqual(True, dsrc.get_data())
+ self.assertEqual('altcloud', dsrc.cloud_name)
+ self.assertEqual('altcloud', dsrc.platform_type)
+ self.assertEqual('vsphere (unknown)', dsrc.subplatform)
def test_fail_rhev(self):
'''Failure Test module get_data() forcing RHEV.'''
- _write_cloud_info_file('RHEV')
+ util.write_file(self.cloud_info_file, 'RHEV')
dsrc = dsac.DataSourceAltCloud({}, None, self.paths)
dsrc.user_data_rhevm = lambda: False
- self.assertEqual(False, dsrc.get_data())
+ with mock.patch.object(dsac, 'CLOUD_INFO_FILE', self.cloud_info_file):
+ self.assertEqual(False, dsrc.get_data())
def test_fail_vsphere(self):
'''Failure Test module get_data() forcing VSPHERE.'''
- _write_cloud_info_file('VSPHERE')
+ util.write_file(self.cloud_info_file, 'VSPHERE')
dsrc = dsac.DataSourceAltCloud({}, None, self.paths)
dsrc.user_data_vsphere = lambda: False
- self.assertEqual(False, dsrc.get_data())
+ with mock.patch.object(dsac, 'CLOUD_INFO_FILE', self.cloud_info_file):
+ self.assertEqual(False, dsrc.get_data())
def test_unrecognized(self):
'''Failure Test module get_data() forcing unrecognized.'''
- _write_cloud_info_file('unrecognized')
+ util.write_file(self.cloud_info_file, 'unrecognized')
dsrc = dsac.DataSourceAltCloud({}, None, self.paths)
- self.assertEqual(False, dsrc.get_data())
+ with mock.patch.object(dsac, 'CLOUD_INFO_FILE', self.cloud_info_file):
+ self.assertEqual(False, dsrc.get_data())
class TestGetDataNoCloudInfoFile(CiTestCase):
@@ -322,7 +321,8 @@ class TestUserDataVsphere(CiTestCase):
'''
def setUp(self):
'''Set up.'''
- self.paths = helpers.Paths({'cloud_dir': '/tmp'})
+ self.tmp = self.tmp_dir()
+ self.paths = helpers.Paths({'cloud_dir': self.tmp})
self.mount_dir = tempfile.mkdtemp()
_write_user_data_files(self.mount_dir, 'test user data')
@@ -363,6 +363,22 @@ class TestUserDataVsphere(CiTestCase):
self.assertEqual(1, m_find_devs_with.call_count)
self.assertEqual(1, m_mount_cb.call_count)
+ @mock.patch("cloudinit.sources.DataSourceAltCloud.util.find_devs_with")
+ @mock.patch("cloudinit.sources.DataSourceAltCloud.util.mount_cb")
+ def test_user_data_vsphere_success(self, m_mount_cb, m_find_devs_with):
+ """Test user_data_vsphere() where successful."""
+ m_find_devs_with.return_value = ["/dev/mock/cdrom"]
+ m_mount_cb.return_value = 'raw userdata from cdrom'
+ dsrc = dsac.DataSourceAltCloud({}, None, self.paths)
+ cloud_info = self.tmp_path('cloud-info', dir=self.tmp)
+ util.write_file(cloud_info, 'VSPHERE')
+ self.assertEqual(True, dsrc.user_data_vsphere())
+ m_find_devs_with.assert_called_once_with('LABEL=CDROM')
+ m_mount_cb.assert_called_once_with(
+ '/dev/mock/cdrom', dsac.read_user_data_callback)
+ with mock.patch.object(dsrc, 'get_cloud_type', return_value='VSPHERE'):
+ self.assertEqual('vsphere (/dev/mock/cdrom)', dsrc.subplatform)
+
class TestReadUserDataCallback(CiTestCase):
'''
diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py
index 4e428b71..0f4b7bf7 100644
--- a/tests/unittests/test_datasource/test_azure.py
+++ b/tests/unittests/test_datasource/test_azure.py
@@ -110,6 +110,8 @@ NETWORK_METADATA = {
}
}
+MOCKPATH = 'cloudinit.sources.DataSourceAzure.'
+
class TestGetMetadataFromIMDS(HttprettyTestCase):
@@ -119,9 +121,9 @@ class TestGetMetadataFromIMDS(HttprettyTestCase):
super(TestGetMetadataFromIMDS, self).setUp()
self.network_md_url = dsaz.IMDS_URL + "instance?api-version=2017-12-01"
- @mock.patch('cloudinit.sources.DataSourceAzure.readurl')
- @mock.patch('cloudinit.sources.DataSourceAzure.EphemeralDHCPv4')
- @mock.patch('cloudinit.sources.DataSourceAzure.net.is_up')
+ @mock.patch(MOCKPATH + 'readurl')
+ @mock.patch(MOCKPATH + 'EphemeralDHCPv4')
+ @mock.patch(MOCKPATH + 'net.is_up')
def test_get_metadata_does_not_dhcp_if_network_is_up(
self, m_net_is_up, m_dhcp, m_readurl):
"""Do not perform DHCP setup when nic is already up."""
@@ -138,9 +140,9 @@ class TestGetMetadataFromIMDS(HttprettyTestCase):
"Crawl of Azure Instance Metadata Service (IMDS) took", # log_time
self.logs.getvalue())
- @mock.patch('cloudinit.sources.DataSourceAzure.readurl')
- @mock.patch('cloudinit.sources.DataSourceAzure.EphemeralDHCPv4')
- @mock.patch('cloudinit.sources.DataSourceAzure.net.is_up')
+ @mock.patch(MOCKPATH + 'readurl')
+ @mock.patch(MOCKPATH + 'EphemeralDHCPv4')
+ @mock.patch(MOCKPATH + 'net.is_up')
def test_get_metadata_performs_dhcp_when_network_is_down(
self, m_net_is_up, m_dhcp, m_readurl):
"""Perform DHCP setup when nic is not up."""
@@ -163,7 +165,7 @@ class TestGetMetadataFromIMDS(HttprettyTestCase):
headers={'Metadata': 'true'}, retries=2, timeout=1)
@mock.patch('cloudinit.url_helper.time.sleep')
- @mock.patch('cloudinit.sources.DataSourceAzure.net.is_up')
+ @mock.patch(MOCKPATH + 'net.is_up')
def test_get_metadata_from_imds_empty_when_no_imds_present(
self, m_net_is_up, m_sleep):
"""Return empty dict when IMDS network metadata is absent."""
@@ -380,7 +382,7 @@ fdescfs /dev/fd fdescfs rw 0 0
res = get_path_dev_freebsd('/etc', mnt_list)
self.assertIsNotNone(res)
- @mock.patch('cloudinit.sources.DataSourceAzure._is_platform_viable')
+ @mock.patch(MOCKPATH + '_is_platform_viable')
def test_call_is_platform_viable_seed(self, m_is_platform_viable):
"""Check seed_dir using _is_platform_viable and return False."""
# Return a non-matching asset tag value
@@ -401,6 +403,24 @@ fdescfs /dev/fd fdescfs rw 0 0
self.assertEqual(dsrc.metadata['local-hostname'], odata['HostName'])
self.assertTrue(os.path.isfile(
os.path.join(self.waagent_d, 'ovf-env.xml')))
+ self.assertEqual('azure', dsrc.cloud_name)
+ self.assertEqual('azure', dsrc.platform_type)
+ self.assertEqual(
+ 'seed-dir (%s/seed/azure)' % self.tmp, dsrc.subplatform)
+
+ def test_basic_dev_file(self):
+ """When a device path is used, present that in subplatform."""
+ data = {'sys_cfg': {}, 'dsdevs': ['/dev/cd0']}
+ dsrc = self._get_ds(data)
+ with mock.patch(MOCKPATH + 'util.mount_cb') as m_mount_cb:
+ m_mount_cb.return_value = (
+ {'local-hostname': 'me'}, 'ud', {'cfg': ''}, {})
+ self.assertTrue(dsrc.get_data())
+ self.assertEqual(dsrc.userdata_raw, 'ud')
+ self.assertEqual(dsrc.metadata['local-hostname'], 'me')
+ self.assertEqual('azure', dsrc.cloud_name)
+ self.assertEqual('azure', dsrc.platform_type)
+ self.assertEqual('config-disk (/dev/cd0)', dsrc.subplatform)
def test_get_data_non_ubuntu_will_not_remove_network_scripts(self):
"""get_data on non-Ubuntu will not remove ubuntu net scripts."""
@@ -769,8 +789,8 @@ fdescfs /dev/fd fdescfs rw 0 0
ds.get_data()
self.assertEqual(self.instance_id, ds.metadata['instance-id'])
- @mock.patch("cloudinit.sources.DataSourceAzure.util.is_FreeBSD")
- @mock.patch("cloudinit.sources.DataSourceAzure._check_freebsd_cdrom")
+ @mock.patch(MOCKPATH + 'util.is_FreeBSD')
+ @mock.patch(MOCKPATH + '_check_freebsd_cdrom')
def test_list_possible_azure_ds_devs(self, m_check_fbsd_cdrom,
m_is_FreeBSD):
"""On FreeBSD, possible devs should show /dev/cd0."""
@@ -885,17 +905,17 @@ fdescfs /dev/fd fdescfs rw 0 0
expected_config['config'].append(blacklist_config)
self.assertEqual(netconfig, expected_config)
- @mock.patch("cloudinit.sources.DataSourceAzure.util.subp")
+ @mock.patch(MOCKPATH + 'util.subp')
def test_get_hostname_with_no_args(self, subp):
dsaz.get_hostname()
subp.assert_called_once_with(("hostname",), capture=True)
- @mock.patch("cloudinit.sources.DataSourceAzure.util.subp")
+ @mock.patch(MOCKPATH + 'util.subp')
def test_get_hostname_with_string_arg(self, subp):
dsaz.get_hostname(hostname_command="hostname")
subp.assert_called_once_with(("hostname",), capture=True)
- @mock.patch("cloudinit.sources.DataSourceAzure.util.subp")
+ @mock.patch(MOCKPATH + 'util.subp')
def test_get_hostname_with_iterable_arg(self, subp):
dsaz.get_hostname(hostname_command=("hostname",))
subp.assert_called_once_with(("hostname",), capture=True)
@@ -949,7 +969,7 @@ class TestAzureBounce(CiTestCase):
self.set_hostname = self.patches.enter_context(
mock.patch.object(dsaz, 'set_hostname'))
self.subp = self.patches.enter_context(
- mock.patch('cloudinit.sources.DataSourceAzure.util.subp'))
+ mock.patch(MOCKPATH + 'util.subp'))
self.find_fallback_nic = self.patches.enter_context(
mock.patch('cloudinit.net.find_fallback_nic', return_value='eth9'))
@@ -989,7 +1009,7 @@ class TestAzureBounce(CiTestCase):
ds.get_data()
self.assertEqual(0, self.set_hostname.call_count)
- @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
+ @mock.patch(MOCKPATH + 'perform_hostname_bounce')
def test_disabled_bounce_does_not_perform_bounce(
self, perform_hostname_bounce):
cfg = {'hostname_bounce': {'policy': 'off'}}
@@ -1005,7 +1025,7 @@ class TestAzureBounce(CiTestCase):
ds.get_data()
self.assertEqual(0, self.set_hostname.call_count)
- @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
+ @mock.patch(MOCKPATH + 'perform_hostname_bounce')
def test_unchanged_hostname_does_not_perform_bounce(
self, perform_hostname_bounce):
host_name = 'unchanged-host-name'
@@ -1015,7 +1035,7 @@ class TestAzureBounce(CiTestCase):
ds.get_data()
self.assertEqual(0, perform_hostname_bounce.call_count)
- @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
+ @mock.patch(MOCKPATH + 'perform_hostname_bounce')
def test_force_performs_bounce_regardless(self, perform_hostname_bounce):
host_name = 'unchanged-host-name'
self.get_hostname.return_value = host_name
@@ -1032,7 +1052,7 @@ class TestAzureBounce(CiTestCase):
cfg = {'hostname_bounce': {'policy': 'force'}}
dsrc = self._get_ds(self.get_ovf_env_with_dscfg(host_name, cfg),
agent_command=['not', '__builtin__'])
- patch_path = 'cloudinit.sources.DataSourceAzure.util.which'
+ patch_path = MOCKPATH + 'util.which'
with mock.patch(patch_path) as m_which:
m_which.return_value = None
ret = self._get_and_setup(dsrc)
@@ -1053,7 +1073,7 @@ class TestAzureBounce(CiTestCase):
self.assertEqual(expected_hostname,
self.set_hostname.call_args_list[0][0][0])
- @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
+ @mock.patch(MOCKPATH + 'perform_hostname_bounce')
def test_different_hostnames_performs_bounce(
self, perform_hostname_bounce):
expected_hostname = 'azure-expected-host-name'
@@ -1076,7 +1096,7 @@ class TestAzureBounce(CiTestCase):
self.assertEqual(initial_host_name,
self.set_hostname.call_args_list[-1][0][0])
- @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
+ @mock.patch(MOCKPATH + 'perform_hostname_bounce')
def test_failure_in_bounce_still_resets_host_name(
self, perform_hostname_bounce):
perform_hostname_bounce.side_effect = Exception
@@ -1117,7 +1137,7 @@ class TestAzureBounce(CiTestCase):
self.assertEqual(
dsaz.BOUNCE_COMMAND_IFUP, bounce_args)
- @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
+ @mock.patch(MOCKPATH + 'perform_hostname_bounce')
def test_set_hostname_option_can_disable_bounce(
self, perform_hostname_bounce):
cfg = {'set_hostname': False, 'hostname_bounce': {'policy': 'force'}}
@@ -1218,12 +1238,12 @@ class TestCanDevBeReformatted(CiTestCase):
def has_ntfs_fs(device):
return bypath.get(device, {}).get('fs') == 'ntfs'
- p = 'cloudinit.sources.DataSourceAzure'
- self._domock(p + "._partitions_on_device", 'm_partitions_on_device')
- self._domock(p + "._has_ntfs_filesystem", 'm_has_ntfs_filesystem')
- self._domock(p + ".util.mount_cb", 'm_mount_cb')
- self._domock(p + ".os.path.realpath", 'm_realpath')
- self._domock(p + ".os.path.exists", 'm_exists')
+ p = MOCKPATH
+ self._domock(p + "_partitions_on_device", 'm_partitions_on_device')
+ self._domock(p + "_has_ntfs_filesystem", 'm_has_ntfs_filesystem')
+ self._domock(p + "util.mount_cb", 'm_mount_cb')
+ self._domock(p + "os.path.realpath", 'm_realpath')
+ self._domock(p + "os.path.exists", 'm_exists')
self.m_exists.side_effect = lambda p: p in bypath
self.m_realpath.side_effect = realpath
@@ -1488,7 +1508,7 @@ class TestPreprovisioningShouldReprovision(CiTestCase):
self.paths = helpers.Paths({'cloud_dir': tmp})
dsaz.BUILTIN_DS_CONFIG['data_dir'] = self.waagent_d
- @mock.patch('cloudinit.sources.DataSourceAzure.util.write_file')
+ @mock.patch(MOCKPATH + 'util.write_file')
def test__should_reprovision_with_true_cfg(self, isfile, write_f):
"""The _should_reprovision method should return true with config
flag present."""
@@ -1512,7 +1532,7 @@ class TestPreprovisioningShouldReprovision(CiTestCase):
dsa = dsaz.DataSourceAzure({}, distro=None, paths=self.paths)
self.assertFalse(dsa._should_reprovision((None, None, {}, None)))
- @mock.patch('cloudinit.sources.DataSourceAzure.DataSourceAzure._poll_imds')
+ @mock.patch(MOCKPATH + 'DataSourceAzure._poll_imds')
def test_reprovision_calls__poll_imds(self, _poll_imds, isfile):
"""_reprovision will poll IMDS."""
isfile.return_value = False
@@ -1528,8 +1548,7 @@ class TestPreprovisioningShouldReprovision(CiTestCase):
@mock.patch('cloudinit.net.dhcp.EphemeralIPv4Network')
@mock.patch('cloudinit.net.dhcp.maybe_perform_dhcp_discovery')
@mock.patch('requests.Session.request')
-@mock.patch(
- 'cloudinit.sources.DataSourceAzure.DataSourceAzure._report_ready')
+@mock.patch(MOCKPATH + 'DataSourceAzure._report_ready')
class TestPreprovisioningPollIMDS(CiTestCase):
def setUp(self):
@@ -1539,7 +1558,7 @@ class TestPreprovisioningPollIMDS(CiTestCase):
self.paths = helpers.Paths({'cloud_dir': self.tmp})
dsaz.BUILTIN_DS_CONFIG['data_dir'] = self.waagent_d
- @mock.patch('cloudinit.sources.DataSourceAzure.util.write_file')
+ @mock.patch(MOCKPATH + 'util.write_file')
def test_poll_imds_calls_report_ready(self, write_f, report_ready_func,
fake_resp, m_dhcp, m_net):
"""The poll_imds will call report_ready after creating marker file."""
@@ -1550,8 +1569,7 @@ class TestPreprovisioningPollIMDS(CiTestCase):
'unknown-245': '624c3620'}
m_dhcp.return_value = [lease]
dsa = dsaz.DataSourceAzure({}, distro=None, paths=self.paths)
- mock_path = (
- 'cloudinit.sources.DataSourceAzure.REPORTED_READY_MARKER_FILE')
+ mock_path = (MOCKPATH + 'REPORTED_READY_MARKER_FILE')
with mock.patch(mock_path, report_marker):
dsa._poll_imds()
self.assertEqual(report_ready_func.call_count, 1)
@@ -1561,23 +1579,21 @@ class TestPreprovisioningPollIMDS(CiTestCase):
fake_resp, m_dhcp, m_net):
"""The poll_imds should not call reporting ready
when flag is false"""
- report_marker = self.tmp_path('report_marker', self.tmp)
- write_file(report_marker, content='dont run report_ready :)')
+ report_file = self.tmp_path('report_marker', self.tmp)
+ write_file(report_file, content='dont run report_ready :)')
m_dhcp.return_value = [{
'interface': 'eth9', 'fixed-address': '192.168.2.9',
'routers': '192.168.2.1', 'subnet-mask': '255.255.255.0',
'unknown-245': '624c3620'}]
dsa = dsaz.DataSourceAzure({}, distro=None, paths=self.paths)
- mock_path = (
- 'cloudinit.sources.DataSourceAzure.REPORTED_READY_MARKER_FILE')
- with mock.patch(mock_path, report_marker):
+ with mock.patch(MOCKPATH + 'REPORTED_READY_MARKER_FILE', report_file):
dsa._poll_imds()
self.assertEqual(report_ready_func.call_count, 0)
-@mock.patch('cloudinit.sources.DataSourceAzure.util.subp')
-@mock.patch('cloudinit.sources.DataSourceAzure.util.write_file')
-@mock.patch('cloudinit.sources.DataSourceAzure.util.is_FreeBSD')
+@mock.patch(MOCKPATH + 'util.subp')
+@mock.patch(MOCKPATH + 'util.write_file')
+@mock.patch(MOCKPATH + 'util.is_FreeBSD')
@mock.patch('cloudinit.net.dhcp.EphemeralIPv4Network')
@mock.patch('cloudinit.net.dhcp.maybe_perform_dhcp_discovery')
@mock.patch('requests.Session.request')
@@ -1688,7 +1704,7 @@ class TestRemoveUbuntuNetworkConfigScripts(CiTestCase):
self.tmp_path('notfilehere', dir=self.tmp)])
self.assertNotIn('/not/a', self.logs.getvalue()) # No delete logs
- @mock.patch('cloudinit.sources.DataSourceAzure.os.path.exists')
+ @mock.patch(MOCKPATH + 'os.path.exists')
def test_remove_network_scripts_default_removes_stock_scripts(self,
m_exists):
"""Azure's stock ubuntu image scripts and artifacts are removed."""
@@ -1704,14 +1720,14 @@ class TestWBIsPlatformViable(CiTestCase):
"""White box tests for _is_platform_viable."""
with_logs = True
- @mock.patch('cloudinit.sources.DataSourceAzure.util.read_dmi_data')
+ @mock.patch(MOCKPATH + 'util.read_dmi_data')
def test_true_on_non_azure_chassis(self, m_read_dmi_data):
"""Return True if DMI chassis-asset-tag is AZURE_CHASSIS_ASSET_TAG."""
m_read_dmi_data.return_value = dsaz.AZURE_CHASSIS_ASSET_TAG
self.assertTrue(dsaz._is_platform_viable('doesnotmatter'))
- @mock.patch('cloudinit.sources.DataSourceAzure.os.path.exists')
- @mock.patch('cloudinit.sources.DataSourceAzure.util.read_dmi_data')
+ @mock.patch(MOCKPATH + 'os.path.exists')
+ @mock.patch(MOCKPATH + 'util.read_dmi_data')
def test_true_on_azure_ovf_env_in_seed_dir(self, m_read_dmi_data, m_exist):
"""Return True if ovf-env.xml exists in known seed dirs."""
# Non-matching Azure chassis-asset-tag
@@ -1729,7 +1745,7 @@ class TestWBIsPlatformViable(CiTestCase):
and no devices have a label starting with prefix 'rd_rdfe_'.
"""
self.assertFalse(wrap_and_call(
- 'cloudinit.sources.DataSourceAzure',
+ MOCKPATH,
{'os.path.exists': False,
# Non-matching Azure chassis-asset-tag
'util.read_dmi_data': dsaz.AZURE_CHASSIS_ASSET_TAG + 'X',
diff --git a/tests/unittests/test_datasource/test_cloudsigma.py b/tests/unittests/test_datasource/test_cloudsigma.py
index 380ad1b5..3bf52e69 100644
--- a/tests/unittests/test_datasource/test_cloudsigma.py
+++ b/tests/unittests/test_datasource/test_cloudsigma.py
@@ -68,6 +68,12 @@ class DataSourceCloudSigmaTest(test_helpers.CiTestCase):
self.assertEqual(SERVER_CONTEXT['uuid'],
self.datasource.get_instance_id())
+ def test_platform(self):
+ """All platform-related attributes are set."""
+ self.assertEqual(self.datasource.cloud_name, 'cloudsigma')
+ self.assertEqual(self.datasource.platform_type, 'cloudsigma')
+ self.assertEqual(self.datasource.subplatform, 'cepko (/dev/ttyS1)')
+
def test_metadata(self):
self.assertEqual(self.datasource.metadata, SERVER_CONTEXT)
diff --git a/tests/unittests/test_datasource/test_configdrive.py b/tests/unittests/test_datasource/test_configdrive.py
index 231619c9..dcdabea5 100644
--- a/tests/unittests/test_datasource/test_configdrive.py
+++ b/tests/unittests/test_datasource/test_configdrive.py
@@ -478,6 +478,9 @@ class TestConfigDriveDataSource(CiTestCase):
myds = cfg_ds_from_dir(self.tmp, files=CFG_DRIVE_FILES_V2)
self.assertEqual(myds.get_public_ssh_keys(),
[OSTACK_META['public_keys']['mykey']])
+ self.assertEqual('configdrive', myds.cloud_name)
+ self.assertEqual('openstack', myds.platform)
+ self.assertEqual('seed-dir (%s/seed)' % self.tmp, myds.subplatform)
class TestNetJson(CiTestCase):
diff --git a/tests/unittests/test_datasource/test_ec2.py b/tests/unittests/test_datasource/test_ec2.py
index 497e7610..9f81255a 100644
--- a/tests/unittests/test_datasource/test_ec2.py
+++ b/tests/unittests/test_datasource/test_ec2.py
@@ -351,7 +351,9 @@ class TestEc2(test_helpers.HttprettyTestCase):
m_get_interface_mac.return_value = mac1
nc = ds.network_config # Will re-crawl network metadata
self.assertIsNotNone(nc)
- self.assertIn('Re-crawl of metadata service', self.logs.getvalue())
+ self.assertIn(
+ 'Refreshing stale metadata from prior to upgrade',
+ self.logs.getvalue())
expected = {'version': 1, 'config': [
{'mac_address': '06:17:04:d7:26:09',
'name': 'eth9',
@@ -386,7 +388,7 @@ class TestEc2(test_helpers.HttprettyTestCase):
register_mock_metaserver(
'{0}/{1}/dynamic/'.format(ds.metadata_address, all_versions[-1]),
DYNAMIC_METADATA)
- ds._cloud_platform = ec2.Platforms.AWS
+ ds._cloud_name = ec2.CloudNames.AWS
# Setup cached metadata on the Datasource
ds.metadata = DEFAULT_METADATA
self.assertEqual('my-identity-id', ds.get_instance_id())
@@ -401,6 +403,9 @@ class TestEc2(test_helpers.HttprettyTestCase):
ret = ds.get_data()
self.assertTrue(ret)
self.assertEqual(0, m_dhcp.call_count)
+ self.assertEqual('aws', ds.cloud_name)
+ self.assertEqual('ec2', ds.platform_type)
+ self.assertEqual('metadata (%s)' % ds.metadata_address, ds.subplatform)
def test_valid_platform_with_strict_false(self):
"""Valid platform data should return true with strict_id false."""
@@ -439,16 +444,17 @@ class TestEc2(test_helpers.HttprettyTestCase):
sys_cfg={'datasource': {'Ec2': {'strict_id': False}}},
md=DEFAULT_METADATA)
platform_attrs = [
- attr for attr in ec2.Platforms.__dict__.keys()
+ attr for attr in ec2.CloudNames.__dict__.keys()
if not attr.startswith('__')]
for attr_name in platform_attrs:
- platform_name = getattr(ec2.Platforms, attr_name)
- if platform_name != 'AWS':
- ds._cloud_platform = platform_name
+ platform_name = getattr(ec2.CloudNames, attr_name)
+ if platform_name != 'aws':
+ ds._cloud_name = platform_name
ret = ds.get_data()
+ self.assertEqual('ec2', ds.platform_type)
self.assertFalse(ret)
message = (
- "Local Ec2 mode only supported on ('AWS',),"
+ "Local Ec2 mode only supported on ('aws',),"
' not {0}'.format(platform_name))
self.assertIn(message, self.logs.getvalue())
diff --git a/tests/unittests/test_datasource/test_ibmcloud.py b/tests/unittests/test_datasource/test_ibmcloud.py
index e639ae47..0b54f585 100644
--- a/tests/unittests/test_datasource/test_ibmcloud.py
+++ b/tests/unittests/test_datasource/test_ibmcloud.py
@@ -1,14 +1,17 @@
# This file is part of cloud-init. See LICENSE file for license information.
+from cloudinit.helpers import Paths
from cloudinit.sources import DataSourceIBMCloud as ibm
from cloudinit.tests import helpers as test_helpers
+from cloudinit import util
import base64
import copy
import json
-import mock
from textwrap import dedent
+mock = test_helpers.mock
+
D_PATH = "cloudinit.sources.DataSourceIBMCloud."
@@ -309,4 +312,39 @@ class TestIsIBMProvisioning(test_helpers.FilesystemMockingTestCase):
self.assertIn("no reference file", self.logs.getvalue())
+class TestDataSourceIBMCloud(test_helpers.CiTestCase):
+
+ def setUp(self):
+ super(TestDataSourceIBMCloud, self).setUp()
+ self.tmp = self.tmp_dir()
+ self.cloud_dir = self.tmp_path('cloud', dir=self.tmp)
+ util.ensure_dir(self.cloud_dir)
+ paths = Paths({'run_dir': self.tmp, 'cloud_dir': self.cloud_dir})
+ self.ds = ibm.DataSourceIBMCloud(
+ sys_cfg={}, distro=None, paths=paths)
+
+ def test_get_data_false(self):
+ """When read_md returns None, get_data returns False."""
+ with mock.patch(D_PATH + 'read_md', return_value=None):
+ self.assertFalse(self.ds.get_data())
+
+ def test_get_data_processes_read_md(self):
+ """get_data processes and caches content returned by read_md."""
+ md = {
+ 'metadata': {}, 'networkdata': 'net', 'platform': 'plat',
+ 'source': 'src', 'system-uuid': 'uuid', 'userdata': 'ud',
+ 'vendordata': 'vd'}
+ with mock.patch(D_PATH + 'read_md', return_value=md):
+ self.assertTrue(self.ds.get_data())
+ self.assertEqual('src', self.ds.source)
+ self.assertEqual('plat', self.ds.platform)
+ self.assertEqual({}, self.ds.metadata)
+ self.assertEqual('ud', self.ds.userdata_raw)
+ self.assertEqual('net', self.ds.network_json)
+ self.assertEqual('vd', self.ds.vendordata_pure)
+ self.assertEqual('uuid', self.ds.system_uuid)
+ self.assertEqual('ibmcloud', self.ds.cloud_name)
+ self.assertEqual('ibmcloud', self.ds.platform_type)
+ self.assertEqual('plat (src)', self.ds.subplatform)
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/test_datasource/test_nocloud.py b/tests/unittests/test_datasource/test_nocloud.py
index 21931eb7..b6468b6d 100644
--- a/tests/unittests/test_datasource/test_nocloud.py
+++ b/tests/unittests/test_datasource/test_nocloud.py
@@ -10,6 +10,7 @@ import textwrap
import yaml
+@mock.patch('cloudinit.sources.DataSourceNoCloud.util.is_lxd')
class TestNoCloudDataSource(CiTestCase):
def setUp(self):
@@ -28,10 +29,11 @@ class TestNoCloudDataSource(CiTestCase):
self.mocks.enter_context(
mock.patch.object(util, 'read_dmi_data', return_value=None))
- def test_nocloud_seed_dir(self):
+ def test_nocloud_seed_dir_on_lxd(self, m_is_lxd):
md = {'instance-id': 'IID', 'dsmode': 'local'}
ud = b"USER_DATA_HERE"
- populate_dir(os.path.join(self.paths.seed_dir, "nocloud"),
+ seed_dir = os.path.join(self.paths.seed_dir, "nocloud")
+ populate_dir(seed_dir,
{'user-data': ud, 'meta-data': yaml.safe_dump(md)})
sys_cfg = {
@@ -44,9 +46,32 @@ class TestNoCloudDataSource(CiTestCase):
ret = dsrc.get_data()
self.assertEqual(dsrc.userdata_raw, ud)
self.assertEqual(dsrc.metadata, md)
+ self.assertEqual(dsrc.platform_type, 'lxd')
+ self.assertEqual(
+ dsrc.subplatform, 'seed-dir (%s)' % seed_dir)
self.assertTrue(ret)
- def test_fs_label(self):
+ def test_nocloud_seed_dir_non_lxd_platform_is_nocloud(self, m_is_lxd):
+ """Non-lxd environments will list nocloud as the platform."""
+ m_is_lxd.return_value = False
+ md = {'instance-id': 'IID', 'dsmode': 'local'}
+ seed_dir = os.path.join(self.paths.seed_dir, "nocloud")
+ populate_dir(seed_dir,
+ {'user-data': '', 'meta-data': yaml.safe_dump(md)})
+
+ sys_cfg = {
+ 'datasource': {'NoCloud': {'fs_label': None}}
+ }
+
+ ds = DataSourceNoCloud.DataSourceNoCloud
+
+ dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
+ self.assertTrue(dsrc.get_data())
+ self.assertEqual(dsrc.platform_type, 'nocloud')
+ self.assertEqual(
+ dsrc.subplatform, 'seed-dir (%s)' % seed_dir)
+
+ def test_fs_label(self, m_is_lxd):
# find_devs_with should not be called ff fs_label is None
ds = DataSourceNoCloud.DataSourceNoCloud
@@ -68,7 +93,7 @@ class TestNoCloudDataSource(CiTestCase):
ret = dsrc.get_data()
self.assertFalse(ret)
- def test_no_datasource_expected(self):
+ def test_no_datasource_expected(self, m_is_lxd):
# no source should be found if no cmdline, config, and fs_label=None
sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}
@@ -76,7 +101,7 @@ class TestNoCloudDataSource(CiTestCase):
dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
self.assertFalse(dsrc.get_data())
- def test_seed_in_config(self):
+ def test_seed_in_config(self, m_is_lxd):
ds = DataSourceNoCloud.DataSourceNoCloud
data = {
@@ -92,7 +117,7 @@ class TestNoCloudDataSource(CiTestCase):
self.assertEqual(dsrc.metadata.get('instance-id'), 'IID')
self.assertTrue(ret)
- def test_nocloud_seed_with_vendordata(self):
+ def test_nocloud_seed_with_vendordata(self, m_is_lxd):
md = {'instance-id': 'IID', 'dsmode': 'local'}
ud = b"USER_DATA_HERE"
vd = b"THIS IS MY VENDOR_DATA"
@@ -114,7 +139,7 @@ class TestNoCloudDataSource(CiTestCase):
self.assertEqual(dsrc.vendordata_raw, vd)
self.assertTrue(ret)
- def test_nocloud_no_vendordata(self):
+ def test_nocloud_no_vendordata(self, m_is_lxd):
populate_dir(os.path.join(self.paths.seed_dir, "nocloud"),
{'user-data': b"ud", 'meta-data': "instance-id: IID\n"})
@@ -128,7 +153,7 @@ class TestNoCloudDataSource(CiTestCase):
self.assertFalse(dsrc.vendordata)
self.assertTrue(ret)
- def test_metadata_network_interfaces(self):
+ def test_metadata_network_interfaces(self, m_is_lxd):
gateway = "103.225.10.1"
md = {
'instance-id': 'i-abcd',
@@ -157,7 +182,7 @@ class TestNoCloudDataSource(CiTestCase):
# very simple check just for the strings above
self.assertIn(gateway, str(dsrc.network_config))
- def test_metadata_network_config(self):
+ def test_metadata_network_config(self, m_is_lxd):
# network-config needs to get into network_config
netconf = {'version': 1,
'config': [{'type': 'physical', 'name': 'interface0',
@@ -177,7 +202,7 @@ class TestNoCloudDataSource(CiTestCase):
self.assertTrue(ret)
self.assertEqual(netconf, dsrc.network_config)
- def test_metadata_network_config_over_interfaces(self):
+ def test_metadata_network_config_over_interfaces(self, m_is_lxd):
# network-config should override meta-data/network-interfaces
gateway = "103.225.10.1"
md = {
diff --git a/tests/unittests/test_datasource/test_opennebula.py b/tests/unittests/test_datasource/test_opennebula.py
index 61591017..bb399f6d 100644
--- a/tests/unittests/test_datasource/test_opennebula.py
+++ b/tests/unittests/test_datasource/test_opennebula.py
@@ -123,6 +123,10 @@ class TestOpenNebulaDataSource(CiTestCase):
self.assertTrue(ret)
finally:
util.find_devs_with = orig_find_devs_with
+ self.assertEqual('opennebula', dsrc.cloud_name)
+ self.assertEqual('opennebula', dsrc.platform_type)
+ self.assertEqual(
+ 'seed-dir (%s/seed/opennebula)' % self.tmp, dsrc.subplatform)
def test_seed_dir_non_contextdisk(self):
self.assertRaises(ds.NonContextDiskDir, ds.read_context_disk_dir,
diff --git a/tests/unittests/test_datasource/test_ovf.py b/tests/unittests/test_datasource/test_ovf.py
index 9d52eb99..a226c032 100644
--- a/tests/unittests/test_datasource/test_ovf.py
+++ b/tests/unittests/test_datasource/test_ovf.py
@@ -11,7 +11,7 @@ from collections import OrderedDict
from textwrap import dedent
from cloudinit import util
-from cloudinit.tests.helpers import CiTestCase, wrap_and_call
+from cloudinit.tests.helpers import CiTestCase, mock, wrap_and_call
from cloudinit.helpers import Paths
from cloudinit.sources import DataSourceOVF as dsovf
from cloudinit.sources.helpers.vmware.imc.config_custom_script import (
@@ -120,7 +120,7 @@ class TestDatasourceOVF(CiTestCase):
def test_get_data_false_on_none_dmi_data(self):
"""When dmi for system-product-name is None, get_data returns False."""
- paths = Paths({'seed_dir': self.tdir})
+ paths = Paths({'cloud_dir': self.tdir})
ds = self.datasource(sys_cfg={}, distro={}, paths=paths)
retcode = wrap_and_call(
'cloudinit.sources.DataSourceOVF',
@@ -134,7 +134,7 @@ class TestDatasourceOVF(CiTestCase):
def test_get_data_no_vmware_customization_disabled(self):
"""When vmware customization is disabled via sys_cfg log a message."""
- paths = Paths({'seed_dir': self.tdir})
+ paths = Paths({'cloud_dir': self.tdir})
ds = self.datasource(
sys_cfg={'disable_vmware_customization': True}, distro={},
paths=paths)
@@ -153,7 +153,7 @@ class TestDatasourceOVF(CiTestCase):
"""When cloud-init workflow for vmware is enabled via sys_cfg log a
message.
"""
- paths = Paths({'seed_dir': self.tdir})
+ paths = Paths({'cloud_dir': self.tdir})
ds = self.datasource(
sys_cfg={'disable_vmware_customization': False}, distro={},
paths=paths)
@@ -178,6 +178,50 @@ class TestDatasourceOVF(CiTestCase):
self.assertIn('Script %s not found!!' % customscript,
str(context.exception))
+ def test_get_data_non_vmware_seed_platform_info(self):
+ """Platform info properly reports when on non-vmware platforms."""
+ paths = Paths({'cloud_dir': self.tdir, 'run_dir': self.tdir})
+ # Write ovf-env.xml seed file
+ seed_dir = self.tmp_path('seed', dir=self.tdir)
+ ovf_env = self.tmp_path('ovf-env.xml', dir=seed_dir)
+ util.write_file(ovf_env, OVF_ENV_CONTENT)
+ ds = self.datasource(sys_cfg={}, distro={}, paths=paths)
+
+ self.assertEqual('ovf', ds.cloud_name)
+ 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_iso9660') as m_iso9660:
+ m_iso9660.return_value = (None, 'ignored', 'ignored')
+ m_guestd.return_value = (None, 'ignored', 'ignored')
+ self.assertTrue(ds.get_data())
+ self.assertEqual(
+ 'ovf (%s/seed/ovf-env.xml)' % self.tdir,
+ ds.subplatform)
+
+ def test_get_data_vmware_seed_platform_info(self):
+ """Platform info properly reports when on VMware platform."""
+ paths = Paths({'cloud_dir': self.tdir, 'run_dir': self.tdir})
+ # Write ovf-env.xml seed file
+ seed_dir = self.tmp_path('seed', dir=self.tdir)
+ ovf_env = self.tmp_path('ovf-env.xml', dir=seed_dir)
+ util.write_file(ovf_env, OVF_ENV_CONTENT)
+ ds = self.datasource(sys_cfg={}, distro={}, paths=paths)
+
+ self.assertEqual('ovf', ds.cloud_name)
+ 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_iso9660') as m_iso9660:
+ m_iso9660.return_value = (None, 'ignored', 'ignored')
+ m_guestd.return_value = (None, 'ignored', 'ignored')
+ self.assertTrue(ds.get_data())
+ self.assertEqual(
+ 'vmware (%s/seed/ovf-env.xml)' % self.tdir,
+ ds.subplatform)
+
class TestTransportIso9660(CiTestCase):
diff --git a/tests/unittests/test_datasource/test_smartos.py b/tests/unittests/test_datasource/test_smartos.py
index 46d67b94..42ac6971 100644
--- a/tests/unittests/test_datasource/test_smartos.py
+++ b/tests/unittests/test_datasource/test_smartos.py
@@ -426,6 +426,13 @@ class TestSmartOSDataSource(FilesystemMockingTestCase):
self.assertEqual(MOCK_RETURNS['sdc:uuid'],
dsrc.metadata['instance-id'])
+ def test_platform_info(self):
+ """All platform-related attributes are properly set."""
+ dsrc = self._get_ds(mockdata=MOCK_RETURNS)
+ self.assertEqual('joyent', dsrc.cloud_name)
+ self.assertEqual('joyent', dsrc.platform_type)
+ self.assertEqual('serial (/dev/ttyS1)', dsrc.subplatform)
+
def test_root_keys(self):
dsrc = self._get_ds(mockdata=MOCK_RETURNS)
ret = dsrc.get_data()