summaryrefslogtreecommitdiff
path: root/tests/unittests/test_datasource
diff options
context:
space:
mode:
authorChad Smith <chad.smith@canonical.com>2018-03-28 12:29:04 -0600
committerChad Smith <chad.smith@canonical.com>2018-03-28 12:29:04 -0600
commitcf3eaed2e01062f9b5d47042d7a76b092970e0cf (patch)
tree53f7c52c5a76bb586da0483699fd6d188e72f457 /tests/unittests/test_datasource
parent9f159f3a55a7bba7868e03d9cccd898678381f03 (diff)
parent8caa3bcf8f2c5b3a448b9d892d4cf53ed8db9be9 (diff)
downloadvyos-cloud-init-cf3eaed2e01062f9b5d47042d7a76b092970e0cf.tar.gz
vyos-cloud-init-cf3eaed2e01062f9b5d47042d7a76b092970e0cf.zip
merge from master at 18.2
Diffstat (limited to 'tests/unittests/test_datasource')
-rw-r--r--tests/unittests/test_datasource/test_azure.py37
-rw-r--r--tests/unittests/test_datasource/test_common.py4
-rw-r--r--tests/unittests/test_datasource/test_gce.py20
-rw-r--r--tests/unittests/test_datasource/test_hetzner.py117
-rw-r--r--tests/unittests/test_datasource/test_ibmcloud.py262
-rw-r--r--tests/unittests/test_datasource/test_opennebula.py266
6 files changed, 601 insertions, 105 deletions
diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py
index 254e9876..3e8b7913 100644
--- a/tests/unittests/test_datasource/test_azure.py
+++ b/tests/unittests/test_datasource/test_azure.py
@@ -643,6 +643,21 @@ 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")
+ 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")
+ 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")
+ def test_get_hostname_with_iterable_arg(self, subp):
+ dsaz.get_hostname(hostname_command=("hostname",))
+ subp.assert_called_once_with(("hostname",), capture=True)
+
class TestAzureBounce(CiTestCase):
@@ -1162,7 +1177,8 @@ class TestAzureDataSourcePreprovisioning(CiTestCase):
url = 'http://{0}/metadata/reprovisiondata?api-version=2017-04-02'
host = "169.254.169.254"
full_url = url.format(host)
- fake_resp.return_value = mock.MagicMock(status_code=200, text="ovf")
+ fake_resp.return_value = mock.MagicMock(status_code=200, text="ovf",
+ content="ovf")
dsa = dsaz.DataSourceAzure({}, distro=None, paths=self.paths)
self.assertTrue(len(dsa._poll_imds()) > 0)
self.assertEqual(fake_resp.call_args_list,
@@ -1170,13 +1186,8 @@ class TestAzureDataSourcePreprovisioning(CiTestCase):
headers={'Metadata': 'true',
'User-Agent':
'Cloud-Init/%s' % vs()
- }, method='GET', timeout=60.0,
- url=full_url),
- mock.call(allow_redirects=True,
- headers={'Metadata': 'true',
- 'User-Agent':
- 'Cloud-Init/%s' % vs()
- }, method='GET', url=full_url)])
+ }, method='GET', timeout=1,
+ url=full_url)])
self.assertEqual(m_dhcp.call_count, 1)
m_net.assert_any_call(
broadcast='192.168.2.255', interface='eth9', ip='192.168.2.9',
@@ -1202,7 +1213,8 @@ class TestAzureDataSourcePreprovisioning(CiTestCase):
username = "myuser"
odata = {'HostName': hostname, 'UserName': username}
content = construct_valid_ovf_env(data=odata)
- fake_resp.return_value = mock.MagicMock(status_code=200, text=content)
+ fake_resp.return_value = mock.MagicMock(status_code=200, text=content,
+ content=content)
dsa = dsaz.DataSourceAzure({}, distro=None, paths=self.paths)
md, ud, cfg, d = dsa._reprovision()
self.assertEqual(md['local-hostname'], hostname)
@@ -1212,12 +1224,7 @@ class TestAzureDataSourcePreprovisioning(CiTestCase):
headers={'Metadata': 'true',
'User-Agent':
'Cloud-Init/%s' % vs()},
- method='GET', timeout=60.0, url=full_url),
- mock.call(allow_redirects=True,
- headers={'Metadata': 'true',
- 'User-Agent':
- 'Cloud-Init/%s' % vs()},
- method='GET', url=full_url)])
+ method='GET', timeout=1, url=full_url)])
self.assertEqual(m_dhcp.call_count, 1)
m_net.assert_any_call(
broadcast='192.168.2.255', interface='eth9', ip='192.168.2.9',
diff --git a/tests/unittests/test_datasource/test_common.py b/tests/unittests/test_datasource/test_common.py
index 80b9c650..ec333888 100644
--- a/tests/unittests/test_datasource/test_common.py
+++ b/tests/unittests/test_datasource/test_common.py
@@ -14,6 +14,8 @@ from cloudinit.sources import (
DataSourceDigitalOcean as DigitalOcean,
DataSourceEc2 as Ec2,
DataSourceGCE as GCE,
+ DataSourceHetzner as Hetzner,
+ DataSourceIBMCloud as IBMCloud,
DataSourceMAAS as MAAS,
DataSourceNoCloud as NoCloud,
DataSourceOpenNebula as OpenNebula,
@@ -31,6 +33,8 @@ DEFAULT_LOCAL = [
CloudSigma.DataSourceCloudSigma,
ConfigDrive.DataSourceConfigDrive,
DigitalOcean.DataSourceDigitalOcean,
+ Hetzner.DataSourceHetzner,
+ IBMCloud.DataSourceIBMCloud,
NoCloud.DataSourceNoCloud,
OpenNebula.DataSourceOpenNebula,
OVF.DataSourceOVF,
diff --git a/tests/unittests/test_datasource/test_gce.py b/tests/unittests/test_datasource/test_gce.py
index f77c2c40..eb3cec42 100644
--- a/tests/unittests/test_datasource/test_gce.py
+++ b/tests/unittests/test_datasource/test_gce.py
@@ -38,11 +38,20 @@ GCE_META_ENCODING = {
'instance/hostname': 'server.project-baz.local',
'instance/zone': 'baz/bang',
'instance/attributes': {
- 'user-data': b64encode(b'/bin/echo baz\n').decode('utf-8'),
+ 'user-data': b64encode(b'#!/bin/echo baz\n').decode('utf-8'),
'user-data-encoding': 'base64',
}
}
+GCE_USER_DATA_TEXT = {
+ 'instance/id': '12345',
+ 'instance/hostname': 'server.project-baz.local',
+ 'instance/zone': 'baz/bang',
+ 'instance/attributes': {
+ 'user-data': '#!/bin/sh\necho hi mom\ntouch /run/up-now\n',
+ }
+}
+
HEADERS = {'Metadata-Flavor': 'Google'}
MD_URL_RE = re.compile(
r'http://metadata.google.internal/computeMetadata/v1/.*')
@@ -135,7 +144,16 @@ class TestDataSourceGCE(test_helpers.HttprettyTestCase):
shostname = GCE_META_PARTIAL.get('instance/hostname').split('.')[0]
self.assertEqual(shostname, self.ds.get_hostname())
+ def test_userdata_no_encoding(self):
+ """check that user-data is read."""
+ _set_mock_metadata(GCE_USER_DATA_TEXT)
+ self.ds.get_data()
+ self.assertEqual(
+ GCE_USER_DATA_TEXT['instance/attributes']['user-data'].encode(),
+ self.ds.get_userdata_raw())
+
def test_metadata_encoding(self):
+ """user-data is base64 encoded if user-data-encoding is 'base64'."""
_set_mock_metadata(GCE_META_ENCODING)
self.ds.get_data()
diff --git a/tests/unittests/test_datasource/test_hetzner.py b/tests/unittests/test_datasource/test_hetzner.py
new file mode 100644
index 00000000..a9c12597
--- /dev/null
+++ b/tests/unittests/test_datasource/test_hetzner.py
@@ -0,0 +1,117 @@
+# Copyright (C) 2018 Jonas Keidel
+#
+# Author: Jonas Keidel <jonas.keidel@hetzner.com>
+#
+# This file is part of cloud-init. See LICENSE file for license information.
+
+from cloudinit.sources import DataSourceHetzner
+from cloudinit import util, settings, helpers
+
+from cloudinit.tests.helpers import mock, CiTestCase
+
+METADATA = util.load_yaml("""
+hostname: cloudinit-test
+instance-id: 123456
+local-ipv4: ''
+network-config:
+ config:
+ - mac_address: 96:00:00:08:19:da
+ name: eth0
+ subnets:
+ - dns_nameservers:
+ - 213.133.99.99
+ - 213.133.100.100
+ - 213.133.98.98
+ ipv4: true
+ type: dhcp
+ type: physical
+ - name: eth0:0
+ subnets:
+ - address: 2a01:4f8:beef:beef::1/64
+ gateway: fe80::1
+ ipv6: true
+ routes:
+ - gateway: fe80::1%eth0
+ netmask: 0
+ network: '::'
+ type: static
+ type: physical
+ version: 1
+network-sysconfig: "DEVICE='eth0'\nTYPE=Ethernet\nBOOTPROTO=dhcp\n\
+ ONBOOT='yes'\nHWADDR=96:00:00:08:19:da\n\
+ IPV6INIT=yes\nIPV6ADDR=2a01:4f8:beef:beef::1/64\n\
+ IPV6_DEFAULTGW=fe80::1%eth0\nIPV6_AUTOCONF=no\n\
+ DNS1=213.133.99.99\nDNS2=213.133.100.100\n"
+public-ipv4: 192.168.0.1
+public-keys:
+- ssh-ed25519 \
+ AAAAC3Nzac1lZdI1NTE5AaaAIaFrcac0yVITsmRrmueq6MD0qYNKlEvW8O1Ib4nkhmWh \
+ test-key@workstation
+vendor_data: "test"
+""")
+
+USERDATA = b"""#cloud-config
+runcmd:
+- [touch, /root/cloud-init-worked ]
+"""
+
+
+class TestDataSourceHetzner(CiTestCase):
+ """
+ Test reading the meta-data
+ """
+ def setUp(self):
+ super(TestDataSourceHetzner, self).setUp()
+ self.tmp = self.tmp_dir()
+
+ def get_ds(self):
+ ds = DataSourceHetzner.DataSourceHetzner(
+ settings.CFG_BUILTIN, None, helpers.Paths({'run_dir': self.tmp}))
+ return ds
+
+ @mock.patch('cloudinit.net.EphemeralIPv4Network')
+ @mock.patch('cloudinit.net.find_fallback_nic')
+ @mock.patch('cloudinit.sources.helpers.hetzner.read_metadata')
+ @mock.patch('cloudinit.sources.helpers.hetzner.read_userdata')
+ @mock.patch('cloudinit.sources.DataSourceHetzner.on_hetzner')
+ def test_read_data(self, m_on_hetzner, m_usermd, m_readmd, m_fallback_nic,
+ m_net):
+ m_on_hetzner.return_value = True
+ m_readmd.return_value = METADATA.copy()
+ m_usermd.return_value = USERDATA
+ m_fallback_nic.return_value = 'eth0'
+
+ ds = self.get_ds()
+ ret = ds.get_data()
+ self.assertTrue(ret)
+
+ m_net.assert_called_once_with(
+ 'eth0', '169.254.0.1',
+ 16, '169.254.255.255'
+ )
+
+ self.assertTrue(m_readmd.called)
+
+ self.assertEqual(METADATA.get('hostname'), ds.get_hostname())
+
+ self.assertEqual(METADATA.get('public-keys'),
+ ds.get_public_ssh_keys())
+
+ self.assertIsInstance(ds.get_public_ssh_keys(), list)
+ self.assertEqual(ds.get_userdata_raw(), USERDATA)
+ self.assertEqual(ds.get_vendordata_raw(), METADATA.get('vendor_data'))
+
+ @mock.patch('cloudinit.sources.helpers.hetzner.read_metadata')
+ @mock.patch('cloudinit.net.find_fallback_nic')
+ @mock.patch('cloudinit.sources.DataSourceHetzner.on_hetzner')
+ def test_not_on_hetzner_returns_false(self, m_on_hetzner, m_find_fallback,
+ m_read_md):
+ """If helper 'on_hetzner' returns False, return False from get_data."""
+ m_on_hetzner.return_value = False
+ ds = self.get_ds()
+ ret = ds.get_data()
+
+ self.assertFalse(ret)
+ # These are a white box attempt to ensure it did not search.
+ m_find_fallback.assert_not_called()
+ m_read_md.assert_not_called()
diff --git a/tests/unittests/test_datasource/test_ibmcloud.py b/tests/unittests/test_datasource/test_ibmcloud.py
new file mode 100644
index 00000000..621cfe49
--- /dev/null
+++ b/tests/unittests/test_datasource/test_ibmcloud.py
@@ -0,0 +1,262 @@
+# This file is part of cloud-init. See LICENSE file for license information.
+
+from cloudinit.sources import DataSourceIBMCloud as ibm
+from cloudinit.tests import helpers as test_helpers
+
+import base64
+import copy
+import json
+import mock
+from textwrap import dedent
+
+D_PATH = "cloudinit.sources.DataSourceIBMCloud."
+
+
+class TestIBMCloud(test_helpers.CiTestCase):
+ """Test the datasource."""
+ def setUp(self):
+ super(TestIBMCloud, self).setUp()
+ pass
+
+
+@mock.patch(D_PATH + "_is_xen", return_value=True)
+@mock.patch(D_PATH + "_is_ibm_provisioning")
+@mock.patch(D_PATH + "util.blkid")
+class TestGetIBMPlatform(test_helpers.CiTestCase):
+ """Test the get_ibm_platform helper."""
+
+ blkid_base = {
+ "/dev/xvda1": {
+ "DEVNAME": "/dev/xvda1", "LABEL": "cloudimg-bootfs",
+ "TYPE": "ext3"},
+ "/dev/xvda2": {
+ "DEVNAME": "/dev/xvda2", "LABEL": "cloudimg-rootfs",
+ "TYPE": "ext4"},
+ }
+
+ blkid_metadata_disk = {
+ "/dev/xvdh1": {
+ "DEVNAME": "/dev/xvdh1", "LABEL": "METADATA", "TYPE": "vfat",
+ "SEC_TYPE": "msdos", "UUID": "681B-8C5D",
+ "PARTUUID": "3d631e09-01"},
+ }
+
+ blkid_oscode_disk = {
+ "/dev/xvdh": {
+ "DEVNAME": "/dev/xvdh", "LABEL": "config-2", "TYPE": "vfat",
+ "SEC_TYPE": "msdos", "UUID": ibm.IBM_CONFIG_UUID}
+ }
+
+ def setUp(self):
+ self.blkid_metadata = copy.deepcopy(self.blkid_base)
+ self.blkid_metadata.update(copy.deepcopy(self.blkid_metadata_disk))
+
+ self.blkid_oscode = copy.deepcopy(self.blkid_base)
+ self.blkid_oscode.update(copy.deepcopy(self.blkid_oscode_disk))
+
+ def test_id_template_live_metadata(self, m_blkid, m_is_prov, _m_xen):
+ """identify TEMPLATE_LIVE_METADATA."""
+ m_blkid.return_value = self.blkid_metadata
+ m_is_prov.return_value = False
+ self.assertEqual(
+ (ibm.Platforms.TEMPLATE_LIVE_METADATA, "/dev/xvdh1"),
+ ibm.get_ibm_platform())
+
+ def test_id_template_prov_metadata(self, m_blkid, m_is_prov, _m_xen):
+ """identify TEMPLATE_PROVISIONING_METADATA."""
+ m_blkid.return_value = self.blkid_metadata
+ m_is_prov.return_value = True
+ self.assertEqual(
+ (ibm.Platforms.TEMPLATE_PROVISIONING_METADATA, "/dev/xvdh1"),
+ ibm.get_ibm_platform())
+
+ def test_id_template_prov_nodata(self, m_blkid, m_is_prov, _m_xen):
+ """identify TEMPLATE_PROVISIONING_NODATA."""
+ m_blkid.return_value = self.blkid_base
+ m_is_prov.return_value = True
+ self.assertEqual(
+ (ibm.Platforms.TEMPLATE_PROVISIONING_NODATA, None),
+ ibm.get_ibm_platform())
+
+ def test_id_os_code(self, m_blkid, m_is_prov, _m_xen):
+ """Identify OS_CODE."""
+ m_blkid.return_value = self.blkid_oscode
+ m_is_prov.return_value = False
+ self.assertEqual((ibm.Platforms.OS_CODE, "/dev/xvdh"),
+ ibm.get_ibm_platform())
+
+ def test_id_os_code_must_match_uuid(self, m_blkid, m_is_prov, _m_xen):
+ """Test against false positive on openstack with non-ibm UUID."""
+ blkid = self.blkid_oscode
+ blkid["/dev/xvdh"]["UUID"] = "9999-9999"
+ m_blkid.return_value = blkid
+ m_is_prov.return_value = False
+ self.assertEqual((None, None), ibm.get_ibm_platform())
+
+
+@mock.patch(D_PATH + "_read_system_uuid", return_value=None)
+@mock.patch(D_PATH + "get_ibm_platform")
+class TestReadMD(test_helpers.CiTestCase):
+ """Test the read_datasource helper."""
+
+ template_md = {
+ "files": [],
+ "network_config": {"content_path": "/content/interfaces"},
+ "hostname": "ci-fond-ram",
+ "name": "ci-fond-ram",
+ "domain": "testing.ci.cloud-init.org",
+ "meta": {"dsmode": "net"},
+ "uuid": "8e636730-9f5d-c4a5-327c-d7123c46e82f",
+ "public_keys": {"1091307": "ssh-rsa AAAAB3NzaC1...Hw== ci-pubkey"},
+ }
+
+ oscode_md = {
+ "hostname": "ci-grand-gannet.testing.ci.cloud-init.org",
+ "name": "ci-grand-gannet",
+ "uuid": "2f266908-8e6c-4818-9b5c-42e9cc66a785",
+ "random_seed": "bm90LXJhbmRvbQo=",
+ "crypt_key": "ssh-rsa AAAAB3NzaC1yc2..n6z/",
+ "configuration_token": "eyJhbGciOi..M3ZA",
+ "public_keys": {"1091307": "ssh-rsa AAAAB3N..Hw== ci-pubkey"},
+ }
+
+ content_interfaces = dedent("""\
+ auto lo
+ iface lo inet loopback
+
+ auto eth0
+ allow-hotplug eth0
+ iface eth0 inet static
+ address 10.82.43.5
+ netmask 255.255.255.192
+ """)
+
+ userdata = b"#!/bin/sh\necho hi mom\n"
+ # meta.js file gets json encoded userdata as a list.
+ meta_js = '["#!/bin/sh\necho hi mom\n"]'
+ vendor_data = {
+ "cloud-init": "#!/bin/bash\necho 'root:$6$5ab01p1m1' | chpasswd -e"}
+
+ network_data = {
+ "links": [
+ {"id": "interface_29402281", "name": "eth0", "mtu": None,
+ "type": "phy", "ethernet_mac_address": "06:00:f1:bd:da:25"},
+ {"id": "interface_29402279", "name": "eth1", "mtu": None,
+ "type": "phy", "ethernet_mac_address": "06:98:5e:d0:7f:86"}
+ ],
+ "networks": [
+ {"id": "network_109887563", "link": "interface_29402281",
+ "type": "ipv4", "ip_address": "10.82.43.2",
+ "netmask": "255.255.255.192",
+ "routes": [
+ {"network": "10.0.0.0", "netmask": "255.0.0.0",
+ "gateway": "10.82.43.1"},
+ {"network": "161.26.0.0", "netmask": "255.255.0.0",
+ "gateway": "10.82.43.1"}]},
+ {"id": "network_109887551", "link": "interface_29402279",
+ "type": "ipv4", "ip_address": "108.168.194.252",
+ "netmask": "255.255.255.248",
+ "routes": [
+ {"network": "0.0.0.0", "netmask": "0.0.0.0",
+ "gateway": "108.168.194.249"}]}
+ ],
+ "services": [
+ {"type": "dns", "address": "10.0.80.11"},
+ {"type": "dns", "address": "10.0.80.12"}
+ ],
+ }
+
+ sysuuid = '7f79ebf5-d791-43c3-a723-854e8389d59f'
+
+ def _get_expected_metadata(self, os_md):
+ """return expected 'metadata' for data loaded from meta_data.json."""
+ os_md = copy.deepcopy(os_md)
+ renames = (
+ ('hostname', 'local-hostname'),
+ ('uuid', 'instance-id'),
+ ('public_keys', 'public-keys'))
+ ret = {}
+ for osname, mdname in renames:
+ if osname in os_md:
+ ret[mdname] = os_md[osname]
+ if 'random_seed' in os_md:
+ ret['random_seed'] = base64.b64decode(os_md['random_seed'])
+
+ return ret
+
+ def test_provisioning_md(self, m_platform, m_sysuuid):
+ """Provisioning env with a metadata disk should return None."""
+ m_platform.return_value = (
+ ibm.Platforms.TEMPLATE_PROVISIONING_METADATA, "/dev/xvdh")
+ self.assertIsNone(ibm.read_md())
+
+ def test_provisioning_no_metadata(self, m_platform, m_sysuuid):
+ """Provisioning env with no metadata disk should return None."""
+ m_platform.return_value = (
+ ibm.Platforms.TEMPLATE_PROVISIONING_NODATA, None)
+ self.assertIsNone(ibm.read_md())
+
+ def test_provisioning_not_ibm(self, m_platform, m_sysuuid):
+ """Provisioning env but not identified as IBM should return None."""
+ m_platform.return_value = (None, None)
+ self.assertIsNone(ibm.read_md())
+
+ def test_template_live(self, m_platform, m_sysuuid):
+ """Template live environment should be identified."""
+ tmpdir = self.tmp_dir()
+ m_platform.return_value = (
+ ibm.Platforms.TEMPLATE_LIVE_METADATA, tmpdir)
+ m_sysuuid.return_value = self.sysuuid
+
+ test_helpers.populate_dir(tmpdir, {
+ 'openstack/latest/meta_data.json': json.dumps(self.template_md),
+ 'openstack/latest/user_data': self.userdata,
+ 'openstack/content/interfaces': self.content_interfaces,
+ 'meta.js': self.meta_js})
+
+ ret = ibm.read_md()
+ self.assertEqual(ibm.Platforms.TEMPLATE_LIVE_METADATA,
+ ret['platform'])
+ self.assertEqual(tmpdir, ret['source'])
+ self.assertEqual(self.userdata, ret['userdata'])
+ self.assertEqual(self._get_expected_metadata(self.template_md),
+ ret['metadata'])
+ self.assertEqual(self.sysuuid, ret['system-uuid'])
+
+ def test_os_code_live(self, m_platform, m_sysuuid):
+ """Verify an os_code metadata path."""
+ tmpdir = self.tmp_dir()
+ m_platform.return_value = (ibm.Platforms.OS_CODE, tmpdir)
+ netdata = json.dumps(self.network_data)
+ test_helpers.populate_dir(tmpdir, {
+ 'openstack/latest/meta_data.json': json.dumps(self.oscode_md),
+ 'openstack/latest/user_data': self.userdata,
+ 'openstack/latest/vendor_data.json': json.dumps(self.vendor_data),
+ 'openstack/latest/network_data.json': netdata,
+ })
+
+ ret = ibm.read_md()
+ self.assertEqual(ibm.Platforms.OS_CODE, ret['platform'])
+ self.assertEqual(tmpdir, ret['source'])
+ self.assertEqual(self.userdata, ret['userdata'])
+ self.assertEqual(self._get_expected_metadata(self.oscode_md),
+ ret['metadata'])
+
+ def test_os_code_live_no_userdata(self, m_platform, m_sysuuid):
+ """Verify os_code without user-data."""
+ tmpdir = self.tmp_dir()
+ m_platform.return_value = (ibm.Platforms.OS_CODE, tmpdir)
+ test_helpers.populate_dir(tmpdir, {
+ 'openstack/latest/meta_data.json': json.dumps(self.oscode_md),
+ 'openstack/latest/vendor_data.json': json.dumps(self.vendor_data),
+ })
+
+ ret = ibm.read_md()
+ self.assertEqual(ibm.Platforms.OS_CODE, ret['platform'])
+ self.assertEqual(tmpdir, ret['source'])
+ self.assertIsNone(ret['userdata'])
+ self.assertEqual(self._get_expected_metadata(self.oscode_md),
+ ret['metadata'])
+
+
+# vi: ts=4 expandtab
diff --git a/tests/unittests/test_datasource/test_opennebula.py b/tests/unittests/test_datasource/test_opennebula.py
index 5c3ba012..ab42f344 100644
--- a/tests/unittests/test_datasource/test_opennebula.py
+++ b/tests/unittests/test_datasource/test_opennebula.py
@@ -4,7 +4,6 @@ from cloudinit import helpers
from cloudinit.sources import DataSourceOpenNebula as ds
from cloudinit import util
from cloudinit.tests.helpers import mock, populate_dir, CiTestCase
-from textwrap import dedent
import os
import pwd
@@ -33,6 +32,11 @@ HOSTNAME = 'foo.example.com'
PUBLIC_IP = '10.0.0.3'
MACADDR = '02:00:0a:12:01:01'
IP_BY_MACADDR = '10.18.1.1'
+IP4_PREFIX = '24'
+IP6_GLOBAL = '2001:db8:1:0:400:c0ff:fea8:1ba'
+IP6_ULA = 'fd01:dead:beaf:0:400:c0ff:fea8:1ba'
+IP6_GW = '2001:db8:1::ffff'
+IP6_PREFIX = '48'
DS_PATH = "cloudinit.sources.DataSourceOpenNebula"
@@ -221,7 +225,9 @@ class TestOpenNebulaDataSource(CiTestCase):
results = ds.read_context_disk_dir(self.seed_dir)
self.assertTrue('network-interfaces' in results)
- self.assertTrue(IP_BY_MACADDR in results['network-interfaces'])
+ self.assertTrue(
+ IP_BY_MACADDR + '/' + IP4_PREFIX in
+ results['network-interfaces']['ethernets'][dev]['addresses'])
# ETH0_IP and ETH0_MAC
populate_context_dir(
@@ -229,7 +235,9 @@ class TestOpenNebulaDataSource(CiTestCase):
results = ds.read_context_disk_dir(self.seed_dir)
self.assertTrue('network-interfaces' in results)
- self.assertTrue(IP_BY_MACADDR in results['network-interfaces'])
+ self.assertTrue(
+ IP_BY_MACADDR + '/' + IP4_PREFIX in
+ results['network-interfaces']['ethernets'][dev]['addresses'])
# ETH0_IP with empty string and ETH0_MAC
# in the case of using Virtual Network contains
@@ -239,55 +247,91 @@ class TestOpenNebulaDataSource(CiTestCase):
results = ds.read_context_disk_dir(self.seed_dir)
self.assertTrue('network-interfaces' in results)
- self.assertTrue(IP_BY_MACADDR in results['network-interfaces'])
+ self.assertTrue(
+ IP_BY_MACADDR + '/' + IP4_PREFIX in
+ results['network-interfaces']['ethernets'][dev]['addresses'])
- # ETH0_NETWORK
+ # ETH0_MASK
populate_context_dir(
self.seed_dir, {
'ETH0_IP': IP_BY_MACADDR,
'ETH0_MAC': MACADDR,
- 'ETH0_NETWORK': '10.18.0.0'
+ 'ETH0_MASK': '255.255.0.0'
})
results = ds.read_context_disk_dir(self.seed_dir)
self.assertTrue('network-interfaces' in results)
- self.assertTrue('10.18.0.0' in results['network-interfaces'])
+ self.assertTrue(
+ IP_BY_MACADDR + '/16' in
+ results['network-interfaces']['ethernets'][dev]['addresses'])
- # ETH0_NETWORK with empty string
+ # ETH0_MASK with empty string
populate_context_dir(
self.seed_dir, {
'ETH0_IP': IP_BY_MACADDR,
'ETH0_MAC': MACADDR,
- 'ETH0_NETWORK': ''
+ 'ETH0_MASK': ''
})
results = ds.read_context_disk_dir(self.seed_dir)
self.assertTrue('network-interfaces' in results)
- self.assertTrue('10.18.1.0' in results['network-interfaces'])
+ self.assertTrue(
+ IP_BY_MACADDR + '/' + IP4_PREFIX in
+ results['network-interfaces']['ethernets'][dev]['addresses'])
- # ETH0_MASK
+ # ETH0_IP6
populate_context_dir(
self.seed_dir, {
- 'ETH0_IP': IP_BY_MACADDR,
+ 'ETH0_IP6': IP6_GLOBAL,
'ETH0_MAC': MACADDR,
- 'ETH0_MASK': '255.255.0.0'
})
results = ds.read_context_disk_dir(self.seed_dir)
self.assertTrue('network-interfaces' in results)
- self.assertTrue('255.255.0.0' in results['network-interfaces'])
+ self.assertTrue(
+ IP6_GLOBAL + '/64' in
+ results['network-interfaces']['ethernets'][dev]['addresses'])
- # ETH0_MASK with empty string
+ # ETH0_IP6_ULA
populate_context_dir(
self.seed_dir, {
- 'ETH0_IP': IP_BY_MACADDR,
+ 'ETH0_IP6_ULA': IP6_ULA,
+ 'ETH0_MAC': MACADDR,
+ })
+ results = ds.read_context_disk_dir(self.seed_dir)
+
+ self.assertTrue('network-interfaces' in results)
+ self.assertTrue(
+ IP6_ULA + '/64' in
+ results['network-interfaces']['ethernets'][dev]['addresses'])
+
+ # ETH0_IP6 and ETH0_IP6_PREFIX_LENGTH
+ populate_context_dir(
+ self.seed_dir, {
+ 'ETH0_IP6': IP6_GLOBAL,
+ 'ETH0_IP6_PREFIX_LENGTH': IP6_PREFIX,
+ 'ETH0_MAC': MACADDR,
+ })
+ results = ds.read_context_disk_dir(self.seed_dir)
+
+ self.assertTrue('network-interfaces' in results)
+ self.assertTrue(
+ IP6_GLOBAL + '/' + IP6_PREFIX in
+ results['network-interfaces']['ethernets'][dev]['addresses'])
+
+ # ETH0_IP6 and ETH0_IP6_PREFIX_LENGTH with empty string
+ populate_context_dir(
+ self.seed_dir, {
+ 'ETH0_IP6': IP6_GLOBAL,
+ 'ETH0_IP6_PREFIX_LENGTH': '',
'ETH0_MAC': MACADDR,
- 'ETH0_MASK': ''
})
results = ds.read_context_disk_dir(self.seed_dir)
self.assertTrue('network-interfaces' in results)
- self.assertTrue('255.255.255.0' in results['network-interfaces'])
+ self.assertTrue(
+ IP6_GLOBAL + '/64' in
+ results['network-interfaces']['ethernets'][dev]['addresses'])
def test_find_candidates(self):
def my_devs_with(criteria):
@@ -310,108 +354,152 @@ class TestOpenNebulaNetwork(unittest.TestCase):
system_nics = ('eth0', 'ens3')
- def test_lo(self):
- net = ds.OpenNebulaNetwork(context={}, system_nics_by_mac={})
- self.assertEqual(net.gen_conf(), u'''\
-auto lo
-iface lo inet loopback
-''')
-
@mock.patch(DS_PATH + ".get_physical_nics_by_mac")
def test_eth0(self, m_get_phys_by_mac):
for nic in self.system_nics:
m_get_phys_by_mac.return_value = {MACADDR: nic}
net = ds.OpenNebulaNetwork({})
- self.assertEqual(net.gen_conf(), dedent("""\
- auto lo
- iface lo inet loopback
-
- auto {dev}
- iface {dev} inet static
- #hwaddress {macaddr}
- address 10.18.1.1
- network 10.18.1.0
- netmask 255.255.255.0
- """.format(dev=nic, macaddr=MACADDR)))
+ expected = {
+ 'version': 2,
+ 'ethernets': {
+ nic: {
+ 'match': {'macaddress': MACADDR},
+ 'addresses': [IP_BY_MACADDR + '/' + IP4_PREFIX]}}}
+
+ self.assertEqual(net.gen_conf(), expected)
def test_eth0_override(self):
+ self.maxDiff = None
context = {
'DNS': '1.2.3.8',
- 'ETH0_IP': '10.18.1.1',
- 'ETH0_NETWORK': '10.18.0.0',
- 'ETH0_MASK': '255.255.0.0',
+ 'ETH0_DNS': '1.2.3.6 1.2.3.7',
'ETH0_GATEWAY': '1.2.3.5',
- 'ETH0_DOMAIN': 'example.com',
+ 'ETH0_GATEWAY6': '',
+ 'ETH0_IP': IP_BY_MACADDR,
+ 'ETH0_IP6': '',
+ 'ETH0_IP6_PREFIX_LENGTH': '',
+ 'ETH0_IP6_ULA': '',
+ 'ETH0_MAC': '02:00:0a:12:01:01',
+ 'ETH0_MASK': '255.255.0.0',
+ 'ETH0_MTU': '',
+ 'ETH0_NETWORK': '10.18.0.0',
+ 'ETH0_SEARCH_DOMAIN': '',
+ }
+ for nic in self.system_nics:
+ net = ds.OpenNebulaNetwork(context,
+ system_nics_by_mac={MACADDR: nic})
+ expected = {
+ 'version': 2,
+ 'ethernets': {
+ nic: {
+ 'match': {'macaddress': MACADDR},
+ 'addresses': [IP_BY_MACADDR + '/16'],
+ 'gateway4': '1.2.3.5',
+ 'gateway6': None,
+ 'nameservers': {
+ 'addresses': ['1.2.3.6', '1.2.3.7', '1.2.3.8']}}}}
+
+ self.assertEqual(expected, net.gen_conf())
+
+ def test_eth0_v4v6_override(self):
+ self.maxDiff = None
+ context = {
+ 'DNS': '1.2.3.8',
'ETH0_DNS': '1.2.3.6 1.2.3.7',
- 'ETH0_MAC': '02:00:0a:12:01:01'
+ 'ETH0_GATEWAY': '1.2.3.5',
+ 'ETH0_GATEWAY6': IP6_GW,
+ 'ETH0_IP': IP_BY_MACADDR,
+ 'ETH0_IP6': IP6_GLOBAL,
+ 'ETH0_IP6_PREFIX_LENGTH': IP6_PREFIX,
+ 'ETH0_IP6_ULA': IP6_ULA,
+ 'ETH0_MAC': '02:00:0a:12:01:01',
+ 'ETH0_MASK': '255.255.0.0',
+ 'ETH0_MTU': '1280',
+ 'ETH0_NETWORK': '10.18.0.0',
+ 'ETH0_SEARCH_DOMAIN': 'example.com example.org',
}
for nic in self.system_nics:
- expected = dedent("""\
- auto lo
- iface lo inet loopback
-
- auto {dev}
- iface {dev} inet static
- #hwaddress {macaddr}
- address 10.18.1.1
- network 10.18.0.0
- netmask 255.255.0.0
- gateway 1.2.3.5
- dns-search example.com
- dns-nameservers 1.2.3.8 1.2.3.6 1.2.3.7
- """).format(dev=nic, macaddr=MACADDR)
net = ds.OpenNebulaNetwork(context,
system_nics_by_mac={MACADDR: nic})
+
+ expected = {
+ 'version': 2,
+ 'ethernets': {
+ nic: {
+ 'match': {'macaddress': MACADDR},
+ 'addresses': [
+ IP_BY_MACADDR + '/16',
+ IP6_GLOBAL + '/' + IP6_PREFIX,
+ IP6_ULA + '/' + IP6_PREFIX],
+ 'gateway4': '1.2.3.5',
+ 'gateway6': IP6_GW,
+ 'nameservers': {
+ 'addresses': ['1.2.3.6', '1.2.3.7', '1.2.3.8'],
+ 'search': ['example.com', 'example.org']},
+ 'mtu': '1280'}}}
+
self.assertEqual(expected, net.gen_conf())
def test_multiple_nics(self):
"""Test rendering multiple nics with names that differ from context."""
+ self.maxDiff = None
MAC_1 = "02:00:0a:12:01:01"
MAC_2 = "02:00:0a:12:01:02"
context = {
'DNS': '1.2.3.8',
- 'ETH0_IP': '10.18.1.1',
- 'ETH0_NETWORK': '10.18.0.0',
- 'ETH0_MASK': '255.255.0.0',
- 'ETH0_GATEWAY': '1.2.3.5',
- 'ETH0_DOMAIN': 'example.com',
'ETH0_DNS': '1.2.3.6 1.2.3.7',
+ 'ETH0_GATEWAY': '1.2.3.5',
+ 'ETH0_GATEWAY6': IP6_GW,
+ 'ETH0_IP': '10.18.1.1',
+ 'ETH0_IP6': IP6_GLOBAL,
+ 'ETH0_IP6_PREFIX_LENGTH': '',
+ 'ETH0_IP6_ULA': IP6_ULA,
'ETH0_MAC': MAC_2,
- 'ETH3_IP': '10.3.1.3',
- 'ETH3_NETWORK': '10.3.0.0',
- 'ETH3_MASK': '255.255.0.0',
- 'ETH3_GATEWAY': '10.3.0.1',
- 'ETH3_DOMAIN': 'third.example.com',
+ 'ETH0_MASK': '255.255.0.0',
+ 'ETH0_MTU': '1280',
+ 'ETH0_NETWORK': '10.18.0.0',
+ 'ETH0_SEARCH_DOMAIN': 'example.com',
'ETH3_DNS': '10.3.1.2',
+ 'ETH3_GATEWAY': '10.3.0.1',
+ 'ETH3_GATEWAY6': '',
+ 'ETH3_IP': '10.3.1.3',
+ 'ETH3_IP6': '',
+ 'ETH3_IP6_PREFIX_LENGTH': '',
+ 'ETH3_IP6_ULA': '',
'ETH3_MAC': MAC_1,
+ 'ETH3_MASK': '255.255.0.0',
+ 'ETH3_MTU': '',
+ 'ETH3_NETWORK': '10.3.0.0',
+ 'ETH3_SEARCH_DOMAIN': 'third.example.com third.example.org',
}
net = ds.OpenNebulaNetwork(
context, system_nics_by_mac={MAC_1: 'enp0s25', MAC_2: 'enp1s2'})
- expected = dedent("""\
- auto lo
- iface lo inet loopback
-
- auto enp0s25
- iface enp0s25 inet static
- #hwaddress 02:00:0a:12:01:01
- address 10.3.1.3
- network 10.3.0.0
- netmask 255.255.0.0
- gateway 10.3.0.1
- dns-search third.example.com
- dns-nameservers 1.2.3.8 10.3.1.2
-
- auto enp1s2
- iface enp1s2 inet static
- #hwaddress 02:00:0a:12:01:02
- address 10.18.1.1
- network 10.18.0.0
- netmask 255.255.0.0
- gateway 1.2.3.5
- dns-search example.com
- dns-nameservers 1.2.3.8 1.2.3.6 1.2.3.7
- """)
+ expected = {
+ 'version': 2,
+ 'ethernets': {
+ 'enp1s2': {
+ 'match': {'macaddress': MAC_2},
+ 'addresses': [
+ '10.18.1.1/16',
+ IP6_GLOBAL + '/64',
+ IP6_ULA + '/64'],
+ 'gateway4': '1.2.3.5',
+ 'gateway6': IP6_GW,
+ 'nameservers': {
+ 'addresses': ['1.2.3.6', '1.2.3.7', '1.2.3.8'],
+ 'search': ['example.com']},
+ 'mtu': '1280'},
+ 'enp0s25': {
+ 'match': {'macaddress': MAC_1},
+ 'addresses': ['10.3.1.3/16'],
+ 'gateway4': '10.3.0.1',
+ 'gateway6': None,
+ 'nameservers': {
+ 'addresses': ['10.3.1.2', '1.2.3.8'],
+ 'search': [
+ 'third.example.com',
+ 'third.example.org']}}}}
self.assertEqual(expected, net.gen_conf())