cloud-init-dev team mailing list archive
-
cloud-init-dev team
-
Mailing list archive
-
Message #06306
[Merge] ~chad.smith/cloud-init:ubuntu/xenial into cloud-init:ubuntu/xenial
Chad Smith has proposed merging ~chad.smith/cloud-init:ubuntu/xenial into cloud-init:ubuntu/xenial.
Requested reviews:
cloud-init commiters (cloud-init-dev)
Related bugs:
Bug #1645824 in cloud-init: "NoCloud source doesn't work on FreeBSD"
https://bugs.launchpad.net/cloud-init/+bug/1645824
Bug #1669875 in cloud-init: "identify openstack vmware platform"
https://bugs.launchpad.net/cloud-init/+bug/1669875
Bug #1827238 in cloud-init: "Machines fail to deploy because cloud-init needs to accept both netplan spellings for grat arp"
https://bugs.launchpad.net/cloud-init/+bug/1827238
For more details, see:
https://code.launchpad.net/~chad.smith/cloud-init/+git/cloud-init/+merge/368355
--
Your team cloud-init commiters is requested to review the proposed merge of ~chad.smith/cloud-init:ubuntu/xenial into cloud-init:ubuntu/xenial.
diff --git a/cloudinit/config/cc_growpart.py b/cloudinit/config/cc_growpart.py
index bafca9d..564f376 100644
--- a/cloudinit/config/cc_growpart.py
+++ b/cloudinit/config/cc_growpart.py
@@ -215,7 +215,8 @@ def device_part_info(devpath):
# FreeBSD doesn't know of sysfs so just get everything we need from
# the device, like /dev/vtbd0p2.
if util.is_FreeBSD():
- m = re.search('^(/dev/.+)p([0-9])$', devpath)
+ freebsd_part = "/dev/" + util.find_freebsd_part(devpath)
+ m = re.search('^(/dev/.+)p([0-9])$', freebsd_part)
return (m.group(1), m.group(2))
if not os.path.exists(syspath):
diff --git a/cloudinit/config/cc_resizefs.py b/cloudinit/config/cc_resizefs.py
index 076b9d5..afd2e06 100644
--- a/cloudinit/config/cc_resizefs.py
+++ b/cloudinit/config/cc_resizefs.py
@@ -81,7 +81,7 @@ def _resize_xfs(mount_point, devpth):
def _resize_ufs(mount_point, devpth):
- return ('growfs', '-y', devpth)
+ return ('growfs', '-y', mount_point)
def _resize_zfs(mount_point, devpth):
@@ -101,7 +101,7 @@ def _can_skip_resize_ufs(mount_point, devpth):
"""
# dumpfs -m /
# newfs command for / (/dev/label/rootfs)
- newfs -O 2 -U -a 4 -b 32768 -d 32768 -e 4096 -f 4096 -g 16384
+ newfs -L rootf -O 2 -U -a 4 -b 32768 -d 32768 -e 4096 -f 4096 -g 16384
-h 64 -i 8192 -j -k 6408 -m 8 -o time -s 58719232 /dev/label/rootf
"""
cur_fs_sz = None
@@ -110,7 +110,7 @@ def _can_skip_resize_ufs(mount_point, devpth):
for line in dumpfs_res.splitlines():
if not line.startswith('#'):
newfs_cmd = shlex.split(line)
- opt_value = 'O:Ua:s:b:d:e:f:g:h:i:jk:m:o:'
+ opt_value = 'O:Ua:s:b:d:e:f:g:h:i:jk:m:o:L:'
optlist, _args = getopt.getopt(newfs_cmd[1:], opt_value)
for o, a in optlist:
if o == "-s":
diff --git a/cloudinit/config/cc_ubuntu_advantage.py b/cloudinit/config/cc_ubuntu_advantage.py
index f488123..f846e9a 100644
--- a/cloudinit/config/cc_ubuntu_advantage.py
+++ b/cloudinit/config/cc_ubuntu_advantage.py
@@ -36,7 +36,7 @@ schema = {
"""),
'distros': distros,
'examples': [dedent("""\
- # Attach the machine to a Ubuntu Advantage support contract with a
+ # Attach the machine to an Ubuntu Advantage support contract with a
# UA contract token obtained from %s.
ubuntu_advantage:
token: <ua_contract_token>
diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py
index 4d19f56..3702130 100644
--- a/cloudinit/net/network_state.py
+++ b/cloudinit/net/network_state.py
@@ -707,6 +707,14 @@ class NetworkStateInterpreter(object):
item_params = dict((key, value) for (key, value) in
item_cfg.items() if key not in
NETWORK_V2_KEY_FILTER)
+ # we accept the fixed spelling, but write the old for compatability
+ # Xenial does not have an updated netplan which supports the
+ # correct spelling. LP: #1756701
+ params = item_params['parameters']
+ grat_value = params.pop('gratuitous-arp', None)
+ if grat_value:
+ params['gratuitious-arp'] = grat_value
+
v1_cmd = {
'type': cmd_type,
'name': item_name,
diff --git a/cloudinit/sources/DataSourceNoCloud.py b/cloudinit/sources/DataSourceNoCloud.py
index fcf5d58..8a9e5dd 100644
--- a/cloudinit/sources/DataSourceNoCloud.py
+++ b/cloudinit/sources/DataSourceNoCloud.py
@@ -35,6 +35,26 @@ class DataSourceNoCloud(sources.DataSource):
root = sources.DataSource.__str__(self)
return "%s [seed=%s][dsmode=%s]" % (root, self.seed, self.dsmode)
+ def _get_devices(self, label):
+ if util.is_FreeBSD():
+ devlist = [
+ p for p in ['/dev/msdosfs/' + label, '/dev/iso9660/' + label]
+ if os.path.exists(p)]
+ else:
+ # Query optical drive to get it in blkid cache for 2.6 kernels
+ util.find_devs_with(path="/dev/sr0")
+ util.find_devs_with(path="/dev/sr1")
+
+ fslist = util.find_devs_with("TYPE=vfat")
+ fslist.extend(util.find_devs_with("TYPE=iso9660"))
+
+ label_list = util.find_devs_with("LABEL=%s" % label.upper())
+ label_list.extend(util.find_devs_with("LABEL=%s" % label.lower()))
+
+ devlist = list(set(fslist) & set(label_list))
+ devlist.sort(reverse=True)
+ return devlist
+
def _get_data(self):
defaults = {
"instance-id": "nocloud",
@@ -99,20 +119,7 @@ class DataSourceNoCloud(sources.DataSource):
label = self.ds_cfg.get('fs_label', "cidata")
if label is not None:
- # Query optical drive to get it in blkid cache for 2.6 kernels
- util.find_devs_with(path="/dev/sr0")
- util.find_devs_with(path="/dev/sr1")
-
- fslist = util.find_devs_with("TYPE=vfat")
- fslist.extend(util.find_devs_with("TYPE=iso9660"))
-
- label_list = util.find_devs_with("LABEL=%s" % label.upper())
- label_list.extend(util.find_devs_with("LABEL=%s" % label.lower()))
-
- devlist = list(set(fslist) & set(label_list))
- devlist.sort(reverse=True)
-
- for dev in devlist:
+ for dev in self._get_devices(label):
try:
LOG.debug("Attempting to use data from %s", dev)
@@ -120,9 +127,8 @@ class DataSourceNoCloud(sources.DataSource):
seeded = util.mount_cb(dev, _pp2d_callback,
pp2d_kwargs)
except ValueError:
- if dev in label_list:
- LOG.warning("device %s with label=%s not a"
- "valid seed.", dev, label)
+ LOG.warning("device %s with label=%s not a"
+ "valid seed.", dev, label)
continue
mydata = _merge_new_seed(mydata, seeded)
diff --git a/cloudinit/util.py b/cloudinit/util.py
index ea4199c..aa23b3f 100644
--- a/cloudinit/util.py
+++ b/cloudinit/util.py
@@ -2337,17 +2337,21 @@ def parse_mtab(path):
return None
-def find_freebsd_part(label_part):
- if label_part.startswith("/dev/label/"):
- target_label = label_part[5:]
- (label_part, _err) = subp(['glabel', 'status', '-s'])
- for labels in label_part.split("\n"):
+def find_freebsd_part(fs):
+ splitted = fs.split('/')
+ if len(splitted) == 3:
+ return splitted[2]
+ elif splitted[2] in ['label', 'gpt', 'ufs']:
+ target_label = fs[5:]
+ (part, _err) = subp(['glabel', 'status', '-s'])
+ for labels in part.split("\n"):
items = labels.split()
- if len(items) > 0 and items[0].startswith(target_label):
- label_part = items[2]
+ if len(items) > 0 and items[0] == target_label:
+ part = items[2]
break
- label_part = str(label_part)
- return label_part
+ return str(part)
+ else:
+ LOG.warning("Unexpected input in find_freebsd_part: %s", fs)
def get_path_dev_freebsd(path, mnt_list):
diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl
index 25db43e..684c747 100644
--- a/config/cloud.cfg.tmpl
+++ b/config/cloud.cfg.tmpl
@@ -32,8 +32,8 @@ preserve_hostname: false
{% if variant in ["freebsd"] %}
# This should not be required, but leave it in place until the real cause of
-# not beeing able to find -any- datasources is resolved.
-datasource_list: ['ConfigDrive', 'Azure', 'OpenStack', 'Ec2']
+# not finding -any- datasources is resolved.
+datasource_list: ['NoCloud', 'ConfigDrive', 'Azure', 'OpenStack', 'Ec2']
{% endif %}
# Example datasource config
# datasource:
diff --git a/debian/changelog b/debian/changelog
index 270b0f3..d05a3d4 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+cloud-init (19.1-1-gbaa47854-0ubuntu1~16.04.2) UNRELEASED; urgency=medium
+
+ * refresh patches:
+ + debian/patches/ubuntu-advantage-revert-tip.patch
+
+ -- Chad Smith <chad.smith@xxxxxxxxxxxxx> Tue, 04 Jun 2019 14:17:46 -0600
+
cloud-init (19.1-1-gbaa47854-0ubuntu1~16.04.1) xenial; urgency=medium
* debian/patches/ubuntu-advantage-revert-tip.patch
diff --git a/debian/patches/ubuntu-advantage-revert-tip.patch b/debian/patches/ubuntu-advantage-revert-tip.patch
index 08bdc81..5f1e043 100644
--- a/debian/patches/ubuntu-advantage-revert-tip.patch
+++ b/debian/patches/ubuntu-advantage-revert-tip.patch
@@ -9,257 +9,9 @@ Forwarded: not-needed
Last-Update: 2019-05-10
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
-Index: cloud-init/cloudinit/config/cc_ubuntu_advantage.py
-===================================================================
---- cloud-init.orig/cloudinit/config/cc_ubuntu_advantage.py
-+++ cloud-init/cloudinit/config/cc_ubuntu_advantage.py
-@@ -1,143 +1,150 @@
-+# Copyright (C) 2018 Canonical Ltd.
-+#
- # This file is part of cloud-init. See LICENSE file for license information.
-
--"""ubuntu_advantage: Configure Ubuntu Advantage support services"""
-+"""Ubuntu advantage: manage ubuntu-advantage offerings from Canonical."""
-
-+import sys
- from textwrap import dedent
-
--import six
--
-+from cloudinit import log as logging
- from cloudinit.config.schema import (
- get_schema_doc, validate_cloudconfig_schema)
--from cloudinit import log as logging
- from cloudinit.settings import PER_INSTANCE
-+from cloudinit.subp import prepend_base_command
- from cloudinit import util
-
-
--UA_URL = 'https://ubuntu.com/advantage'
--
- distros = ['ubuntu']
-+frequency = PER_INSTANCE
-+
-+LOG = logging.getLogger(__name__)
-
- schema = {
- 'id': 'cc_ubuntu_advantage',
- 'name': 'Ubuntu Advantage',
-- 'title': 'Configure Ubuntu Advantage support services',
-+ 'title': 'Install, configure and manage ubuntu-advantage offerings',
- 'description': dedent("""\
-- Attach machine to an existing Ubuntu Advantage support contract and
-- enable or disable support services such as Livepatch, ESM,
-- FIPS and FIPS Updates. When attaching a machine to Ubuntu Advantage,
-- one can also specify services to enable. When the 'enable'
-- list is present, any named service will be enabled and all absent
-- services will remain disabled.
--
-- Note that when enabling FIPS or FIPS updates you will need to schedule
-- a reboot to ensure the machine is running the FIPS-compliant kernel.
-- See :ref:`Power State Change` for information on how to configure
-- cloud-init to perform this reboot.
-+ This module provides configuration options to setup ubuntu-advantage
-+ subscriptions.
-+
-+ .. note::
-+ Both ``commands`` value can be either a dictionary or a list. If
-+ the configuration provided is a dictionary, the keys are only used
-+ to order the execution of the commands and the dictionary is
-+ merged with any vendor-data ubuntu-advantage configuration
-+ provided. If a ``commands`` is provided as a list, any vendor-data
-+ ubuntu-advantage ``commands`` are ignored.
-+
-+ Ubuntu-advantage ``commands`` is a dictionary or list of
-+ ubuntu-advantage commands to run on the deployed machine.
-+ These commands can be used to enable or disable subscriptions to
-+ various ubuntu-advantage products. See 'man ubuntu-advantage' for more
-+ information on supported subcommands.
-+
-+ .. note::
-+ Each command item can be a string or list. If the item is a list,
-+ 'ubuntu-advantage' can be omitted and it will automatically be
-+ inserted as part of the command.
- """),
- 'distros': distros,
- 'examples': [dedent("""\
-- # Attach the machine to a Ubuntu Advantage support contract with a
-- # UA contract token obtained from %s.
-- ubuntu_advantage:
-- token: <ua_contract_token>
-- """ % UA_URL), dedent("""\
-- # Attach the machine to an Ubuntu Advantage support contract enabling
-- # only fips and esm services. Services will only be enabled if
-- # the environment supports said service. Otherwise warnings will
-- # be logged for incompatible services specified.
-+ # Enable Extended Security Maintenance using your service auth token
-+ ubuntu-advantage:
-+ commands:
-+ 00: ubuntu-advantage enable-esm <token>
-+ """), dedent("""\
-+ # Enable livepatch by providing your livepatch token
- ubuntu-advantage:
-- token: <ua_contract_token>
-- enable:
-- - fips
-- - esm
-+ commands:
-+ 00: ubuntu-advantage enable-livepatch <livepatch-token>
-+
- """), dedent("""\
-- # Attach the machine to an Ubuntu Advantage support contract and enable
-- # the FIPS service. Perform a reboot once cloud-init has
-- # completed.
-- power_state:
-- mode: reboot
-+ # Convenience: the ubuntu-advantage command can be omitted when
-+ # specifying commands as a list and 'ubuntu-advantage' will
-+ # automatically be prepended.
-+ # The following commands are equivalent
- ubuntu-advantage:
-- token: <ua_contract_token>
-- enable:
-- - fips
-- """)],
-+ commands:
-+ 00: ['enable-livepatch', 'my-token']
-+ 01: ['ubuntu-advantage', 'enable-livepatch', 'my-token']
-+ 02: ubuntu-advantage enable-livepatch my-token
-+ 03: 'ubuntu-advantage enable-livepatch my-token'
-+ """)],
- 'frequency': PER_INSTANCE,
- 'type': 'object',
- 'properties': {
-- 'ubuntu_advantage': {
-+ 'ubuntu-advantage': {
- 'type': 'object',
- 'properties': {
-- 'enable': {
-- 'type': 'array',
-- 'items': {'type': 'string'},
-- },
-- 'token': {
-- 'type': 'string',
-- 'description': (
-- 'A contract token obtained from %s.' % UA_URL)
-+ 'commands': {
-+ 'type': ['object', 'array'], # Array of strings or dict
-+ 'items': {
-+ 'oneOf': [
-+ {'type': 'array', 'items': {'type': 'string'}},
-+ {'type': 'string'}]
-+ },
-+ 'additionalItems': False, # Reject non-string & non-list
-+ 'minItems': 1,
-+ 'minProperties': 1,
- }
- },
-- 'required': ['token'],
-- 'additionalProperties': False
-+ 'additionalProperties': False, # Reject keys not in schema
-+ 'required': ['commands']
- }
- }
- }
-
-+# TODO schema for 'assertions' and 'commands' are too permissive at the moment.
-+# Once python-jsonschema supports schema draft 6 add support for arbitrary
-+# object keys with 'patternProperties' constraint to validate string values.
-+
- __doc__ = get_schema_doc(schema) # Supplement python help()
-
--LOG = logging.getLogger(__name__)
-+UA_CMD = "ubuntu-advantage"
-
-
--def configure_ua(token=None, enable=None):
-- """Call ua commandline client to attach or enable services."""
-- error = None
-- if not token:
-- error = ('ubuntu_advantage: token must be provided')
-- LOG.error(error)
-- raise RuntimeError(error)
--
-- if enable is None:
-- enable = []
-- elif isinstance(enable, six.string_types):
-- LOG.warning('ubuntu_advantage: enable should be a list, not'
-- ' a string; treating as a single enable')
-- enable = [enable]
-- elif not isinstance(enable, list):
-- LOG.warning('ubuntu_advantage: enable should be a list, not'
-- ' a %s; skipping enabling services',
-- type(enable).__name__)
-- enable = []
-+def run_commands(commands):
-+ """Run the commands provided in ubuntu-advantage:commands config.
-
-- attach_cmd = ['ua', 'attach', token]
-- LOG.debug('Attaching to Ubuntu Advantage. %s', ' '.join(attach_cmd))
-- try:
-- util.subp(attach_cmd)
-- except util.ProcessExecutionError as e:
-- msg = 'Failure attaching Ubuntu Advantage:\n{error}'.format(
-- error=str(e))
-- util.logexc(LOG, msg)
-- raise RuntimeError(msg)
-- enable_errors = []
-- for service in enable:
-+ Commands are run individually. Any errors are collected and reported
-+ after attempting all commands.
-+
-+ @param commands: A list or dict containing commands to run. Keys of a
-+ dict will be used to order the commands provided as dict values.
-+ """
-+ if not commands:
-+ return
-+ LOG.debug('Running user-provided ubuntu-advantage commands')
-+ if isinstance(commands, dict):
-+ # Sort commands based on dictionary key
-+ commands = [v for _, v in sorted(commands.items())]
-+ elif not isinstance(commands, list):
-+ raise TypeError(
-+ 'commands parameter was not a list or dict: {commands}'.format(
-+ commands=commands))
-+
-+ fixed_ua_commands = prepend_base_command('ubuntu-advantage', commands)
-+
-+ cmd_failures = []
-+ for command in fixed_ua_commands:
-+ shell = isinstance(command, str)
- try:
-- cmd = ['ua', 'enable', service]
-- util.subp(cmd, capture=True)
-+ util.subp(command, shell=shell, status_cb=sys.stderr.write)
- except util.ProcessExecutionError as e:
-- enable_errors.append((service, e))
-- if enable_errors:
-- for service, error in enable_errors:
-- msg = 'Failure enabling "{service}":\n{error}'.format(
-- service=service, error=str(error))
-- util.logexc(LOG, msg)
-- raise RuntimeError(
-- 'Failure enabling Ubuntu Advantage service(s): {}'.format(
-- ', '.join('"{}"'.format(service)
-- for service, _ in enable_errors)))
-+ cmd_failures.append(str(e))
-+ if cmd_failures:
-+ msg = (
-+ 'Failures running ubuntu-advantage commands:\n'
-+ '{cmd_failures}'.format(
-+ cmd_failures=cmd_failures))
-+ util.logexc(LOG, msg)
-+ raise RuntimeError(msg)
-
-
- def maybe_install_ua_tools(cloud):
- """Install ubuntu-advantage-tools if not present."""
-- if util.which('ua'):
-+ if util.which('ubuntu-advantage'):
- return
- try:
- cloud.distro.update_package_sources()
-@@ -152,28 +159,14 @@ def maybe_install_ua_tools(cloud):
+--- a/cloudinit/config/cc_ubuntu_advantage.py
++++ b/cloudinit/config/cc_ubuntu_advantage.py
+@@ -152,28 +152,14 @@ def maybe_install_ua_tools(cloud):
def handle(name, cfg, cloud, log, args):
@@ -294,10 +46,8 @@ Index: cloud-init/cloudinit/config/cc_ubuntu_advantage.py
+ run_commands(cfgin.get('commands', []))
# vi: ts=4 expandtab
-Index: cloud-init/cloudinit/config/tests/test_ubuntu_advantage.py
-===================================================================
---- cloud-init.orig/cloudinit/config/tests/test_ubuntu_advantage.py
-+++ cloud-init/cloudinit/config/tests/test_ubuntu_advantage.py
+--- a/cloudinit/config/tests/test_ubuntu_advantage.py
++++ b/cloudinit/config/tests/test_ubuntu_advantage.py
@@ -1,7 +1,10 @@
# This file is part of cloud-init. See LICENSE file for license information.
diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py
index 427ab7e..afb614e 100644
--- a/tests/unittests/test_datasource/test_azure.py
+++ b/tests/unittests/test_datasource/test_azure.py
@@ -6,7 +6,6 @@ from cloudinit import url_helper
from cloudinit.sources import (
UNSET, DataSourceAzure as dsaz, InvalidMetaDataException)
from cloudinit.util import (b64e, decode_binary, load_file, write_file,
- find_freebsd_part, get_path_dev_freebsd,
MountFailedError, json_dumps, load_json)
from cloudinit.version import version_string as vs
from cloudinit.tests.helpers import (
@@ -391,29 +390,6 @@ scbus-1 on xpt0 bus 0
dev = ds.get_resource_disk_on_freebsd(1)
self.assertEqual("da1", dev)
- @mock.patch('cloudinit.util.subp')
- def test_find_freebsd_part_on_Azure(self, mock_subp):
- glabel_out = '''
-gptid/fa52d426-c337-11e6-8911-00155d4c5e47 N/A da0p1
- label/rootfs N/A da0p2
- label/swap N/A da0p3
-'''
- mock_subp.return_value = (glabel_out, "")
- res = find_freebsd_part("/dev/label/rootfs")
- self.assertEqual("da0p2", res)
-
- def test_get_path_dev_freebsd_on_Azure(self):
- mnt_list = '''
-/dev/label/rootfs / ufs rw 1 1
-devfs /dev devfs rw,multilabel 0 0
-fdescfs /dev/fd fdescfs rw 0 0
-/dev/da1s1 /mnt/resource ufs rw 2 2
-'''
- with mock.patch.object(os.path, 'exists',
- return_value=True):
- res = get_path_dev_freebsd('/etc', mnt_list)
- self.assertIsNotNone(res)
-
@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."""
diff --git a/tests/unittests/test_datasource/test_nocloud.py b/tests/unittests/test_datasource/test_nocloud.py
index b785362..18bea0b 100644
--- a/tests/unittests/test_datasource/test_nocloud.py
+++ b/tests/unittests/test_datasource/test_nocloud.py
@@ -278,6 +278,24 @@ class TestNoCloudDataSource(CiTestCase):
self.assertEqual(netconf, dsrc.network_config)
self.assertNotIn(gateway, str(dsrc.network_config))
+ @mock.patch("cloudinit.util.blkid")
+ def test_nocloud_get_devices_freebsd(self, m_is_lxd, fake_blkid):
+ populate_dir(os.path.join(self.paths.seed_dir, "nocloud"),
+ {'user-data': b"ud", 'meta-data': "instance-id: IID\n"})
+
+ sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}
+
+ self.mocks.enter_context(
+ mock.patch.object(util, 'is_FreeBSD', return_value=True))
+
+ self.mocks.enter_context(
+ mock.patch.object(os.path, 'exists', return_value=True))
+
+ dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
+ ret = dsrc._get_devices('foo')
+ self.assertEqual(['/dev/msdosfs/foo', '/dev/iso9660/foo'], ret)
+ fake_blkid.assert_not_called()
+
class TestParseCommandLineData(CiTestCase):
diff --git a/tests/unittests/test_distros/test_freebsd.py b/tests/unittests/test_distros/test_freebsd.py
new file mode 100644
index 0000000..8af253a
--- /dev/null
+++ b/tests/unittests/test_distros/test_freebsd.py
@@ -0,0 +1,45 @@
+# This file is part of cloud-init. See LICENSE file for license information.
+
+from cloudinit.util import (find_freebsd_part, get_path_dev_freebsd)
+from cloudinit.tests.helpers import (CiTestCase, mock)
+
+import os
+
+
+class TestDeviceLookUp(CiTestCase):
+
+ @mock.patch('cloudinit.util.subp')
+ def test_find_freebsd_part_label(self, mock_subp):
+ glabel_out = '''
+gptid/fa52d426-c337-11e6-8911-00155d4c5e47 N/A da0p1
+ label/rootfs N/A da0p2
+ label/swap N/A da0p3
+'''
+ mock_subp.return_value = (glabel_out, "")
+ res = find_freebsd_part("/dev/label/rootfs")
+ self.assertEqual("da0p2", res)
+
+ @mock.patch('cloudinit.util.subp')
+ def test_find_freebsd_part_gpt(self, mock_subp):
+ glabel_out = '''
+ gpt/bootfs N/A vtbd0p1
+gptid/3f4cbe26-75da-11e8-a8f2-002590ec6166 N/A vtbd0p1
+ gpt/swapfs N/A vtbd0p2
+ gpt/rootfs N/A vtbd0p3
+ iso9660/cidata N/A vtbd2
+'''
+ mock_subp.return_value = (glabel_out, "")
+ res = find_freebsd_part("/dev/gpt/rootfs")
+ self.assertEqual("vtbd0p3", res)
+
+ def test_get_path_dev_freebsd_label(self):
+ mnt_list = '''
+/dev/label/rootfs / ufs rw 1 1
+devfs /dev devfs rw,multilabel 0 0
+fdescfs /dev/fd fdescfs rw 0 0
+/dev/da1s1 /mnt/resource ufs rw 2 2
+'''
+ with mock.patch.object(os.path, 'exists',
+ return_value=True):
+ res = get_path_dev_freebsd('/etc', mnt_list)
+ self.assertIsNotNone(res)
diff --git a/tests/unittests/test_ds_identify.py b/tests/unittests/test_ds_identify.py
index 8c18aa1..7575223 100644
--- a/tests/unittests/test_ds_identify.py
+++ b/tests/unittests/test_ds_identify.py
@@ -435,6 +435,14 @@ class TestDsIdentify(DsIdentifyBase):
"""Open Telecom identification."""
self._test_ds_found('OpenStack-OpenTelekom')
+ def test_openstack_asset_tag_nova(self):
+ """OpenStack identification via asset tag OpenStack Nova."""
+ self._test_ds_found('OpenStack-AssetTag-Nova')
+
+ def test_openstack_asset_tag_copute(self):
+ """OpenStack identification via asset tag OpenStack Compute."""
+ self._test_ds_found('OpenStack-AssetTag-Compute')
+
def test_openstack_on_non_intel_is_maybe(self):
"""On non-Intel, openstack without dmi info is maybe.
@@ -759,6 +767,18 @@ VALID_CFG = {
'files': {P_CHASSIS_ASSET_TAG: 'OpenTelekomCloud\n'},
'mocks': [MOCK_VIRT_IS_XEN],
},
+ 'OpenStack-AssetTag-Nova': {
+ # VMware vSphere can't modify product-name, LP: #1669875
+ 'ds': 'OpenStack',
+ 'files': {P_CHASSIS_ASSET_TAG: 'OpenStack Nova\n'},
+ 'mocks': [MOCK_VIRT_IS_XEN],
+ },
+ 'OpenStack-AssetTag-Compute': {
+ # VMware vSphere can't modify product-name, LP: #1669875
+ 'ds': 'OpenStack',
+ 'files': {P_CHASSIS_ASSET_TAG: 'OpenStack Compute\n'},
+ 'mocks': [MOCK_VIRT_IS_XEN],
+ },
'OVF-seed': {
'ds': 'OVF',
'files': {
diff --git a/tests/unittests/test_handler/test_handler_resizefs.py b/tests/unittests/test_handler/test_handler_resizefs.py
index 3518784..db9a041 100644
--- a/tests/unittests/test_handler/test_handler_resizefs.py
+++ b/tests/unittests/test_handler/test_handler_resizefs.py
@@ -147,7 +147,7 @@ class TestResizefs(CiTestCase):
def test_resize_ufs_cmd_return(self):
mount_point = '/'
devpth = '/dev/sda2'
- self.assertEqual(('growfs', '-y', devpth),
+ self.assertEqual(('growfs', '-y', mount_point),
_resize_ufs(mount_point, devpth))
@mock.patch('cloudinit.util.is_container', return_value=False)
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index e85e964..b936bc9 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -407,6 +407,37 @@ network:
- maas
"""
+NETPLAN_BOND_GRAT_ARP = """
+network:
+ bonds:
+ bond0:
+ interfaces:
+ - ens3
+ macaddress: 68:05:ca:64:d3:6c
+ mtu: 9000
+ parameters:
+ gratuitious-arp: 1
+ bond1:
+ interfaces:
+ - ens4
+ macaddress: 68:05:ca:64:d3:6d
+ mtu: 9000
+ parameters:
+ gratuitous-arp: 2
+ ethernets:
+ ens3:
+ dhcp4: false
+ dhcp6: false
+ match:
+ macaddress: 52:54:00:ab:cd:ef
+ ens4:
+ dhcp4: false
+ dhcp6: false
+ match:
+ macaddress: 52:54:00:11:22:ff
+ version: 2
+"""
+
NETPLAN_DHCP_FALSE = """
version: 2
ethernets:
@@ -3589,6 +3620,21 @@ class TestNetplanRoundTrip(CiTestCase):
entry['expected_netplan'].splitlines(),
files['/etc/netplan/50-cloud-init.yaml'].splitlines())
+ def test_render_output_supports_both_grat_arp_spelling(self):
+ entry = {
+ 'yaml': NETPLAN_BOND_GRAT_ARP,
+ 'expected_netplan': NETPLAN_BOND_GRAT_ARP.replace('gratuitous',
+ 'gratuitious'),
+ }
+ network_config = yaml.load(entry['yaml']).get('network')
+ files = self._render_and_read(network_config=network_config)
+ print(entry['expected_netplan'])
+ print('-- expected ^ | v rendered --')
+ print(files['/etc/netplan/50-cloud-init.yaml'])
+ self.assertEqual(
+ entry['expected_netplan'].splitlines(),
+ files['/etc/netplan/50-cloud-init.yaml'].splitlines())
+
class TestEniRoundTrip(CiTestCase):
diff --git a/tools/ds-identify b/tools/ds-identify
index 6518901..e16708f 100755
--- a/tools/ds-identify
+++ b/tools/ds-identify
@@ -979,6 +979,14 @@ dscheck_OpenStack() {
return ${DS_FOUND}
fi
+ # LP: #1669875 : allow identification of OpenStack by asset tag
+ if dmi_chassis_asset_tag_matches "$nova"; then
+ return ${DS_FOUND}
+ fi
+ if dmi_chassis_asset_tag_matches "$compute"; then
+ return ${DS_FOUND}
+ fi
+
# LP: #1715241 : arch other than intel are not identified properly.
case "$DI_UNAME_MACHINE" in
i?86|x86_64) :;;
diff --git a/tools/render-cloudcfg b/tools/render-cloudcfg
index 8b7cb87..0957c32 100755
--- a/tools/render-cloudcfg
+++ b/tools/render-cloudcfg
@@ -4,7 +4,7 @@ import argparse
import os
import sys
-VARIANTS = ["bsd", "centos", "fedora", "rhel", "suse", "ubuntu", "unknown"]
+VARIANTS = ["freebsd", "centos", "fedora", "rhel", "suse", "ubuntu", "unknown"]
if "avoid-pep8-E402-import-not-top-of-file":
_tdir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
diff --git a/tools/run-container b/tools/run-container
index 852f4d1..1d24e15 100755
--- a/tools/run-container
+++ b/tools/run-container
@@ -373,7 +373,7 @@ wait_for_boot() {
inside "$name" sh -c "echo proxy=$http_proxy >> /etc/yum.conf"
inside "$name" sed -i s/enabled=1/enabled=0/ \
/etc/yum/pluginconf.d/fastestmirror.conf
- inside "$name" sh -c "sed -i '/^#baseurl=/s/#//' /etc/yum.repos.d/*.repo"
+ inside "$name" sh -c "sed -i '/^#baseurl=/s/#// ; s/^mirrorlist/#mirrorlist/' /etc/yum.repos.d/*.repo"
else
debug 1 "do not know how to configure proxy on $OS_NAME"
fi
Follow ups