Skip to content

Commit

Permalink
add prefer_fqdn_over_hostname config option
Browse files Browse the repository at this point in the history
the above option allow the user to control the
behavior of a distro hostname selection
so if the user send hostname, FQDN Configs
if prefer_fqdn_over_hostname is true the
The FQDN will be selected as hostname
if false the hostname will be selected

LP: canonical#859
  • Loading branch information
hamzah alqtaishat authored and hamalq committed Apr 15, 2021
1 parent 3b7e2e8 commit 99d00b4
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 16 deletions.
14 changes: 13 additions & 1 deletion cloudinit/config/cc_set_hostname.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
key, and the fqdn of the cloud wil be used. If a fqdn specified with the
``hostname`` key, it will be handled properly, although it is better to use
the ``fqdn`` config key. If both ``fqdn`` and ``hostname`` are set,
it is distro dependent whether ``hostname`` or ``fqdn`` is used.
it is distro dependent whether ``hostname`` or ``fqdn`` is used,
unless the ``prefer_fqdn_over_hostname`` option is true and fqdn is set
it will force the use of FQDN in all distros, and if false then it will
force the hostname use.
This module will run in the init-local stage before networking is configured
if the hostname is set by metadata or user data on the local system.
Expand All @@ -38,6 +41,7 @@
**Config keys**::
preserve_hostname: <true/false>
prefer_fqdn_over_hostname: <true/false>
fqdn: <fqdn>
hostname: <fqdn/hostname>
"""
Expand All @@ -62,6 +66,14 @@ def handle(name, cfg, cloud, log, _args):
log.debug(("Configuration option 'preserve_hostname' is set,"
" not setting the hostname in module %s"), name)
return

# Set prefer_fqdn_over_hostname value in distro
hostname_fqdn = util.get_cfg_option_bool(cfg,
"prefer_fqdn_over_hostname",
None)
if hostname_fqdn is not None:
cloud.distro.set_option('prefer_fqdn_over_hostname', hostname_fqdn)

(hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud)
# Check for previous successful invocation of set-hostname

Expand Down
7 changes: 7 additions & 0 deletions cloudinit/config/cc_update_hostname.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ def handle(name, cfg, cloud, log, _args):
" not updating the hostname in module %s"), name)
return

# Set prefer_fqdn_over_hostname value in distro
hostname_fqdn = util.get_cfg_option_bool(cfg,
"prefer_fqdn_over_hostname",
None)
if hostname_fqdn is not None:
cloud.distro.set_option('prefer_fqdn_over_hostname', hostname_fqdn)

(hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud)
try:
prev_fn = os.path.join(cloud.get_cpath('data'), "previous-hostname")
Expand Down
7 changes: 7 additions & 0 deletions cloudinit/distros/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta):
shutdown_options_map = {'halt': '-H', 'poweroff': '-P', 'reboot': '-r'}

_ci_pkl_version = 1
prefer_fqdn = False

def __init__(self, name, cfg, paths):
self._paths = paths
Expand Down Expand Up @@ -131,6 +132,9 @@ def _find_tz_file(self, tz):
def get_option(self, opt_name, default=None):
return self._cfg.get(opt_name, default)

def set_option(self, opt_name, value=None):
self._cfg[opt_name] = value

def set_hostname(self, hostname, fqdn=None):
writeable_hostname = self._select_hostname(hostname, fqdn)
self._write_hostname(writeable_hostname, self.hostname_conf_fn)
Expand Down Expand Up @@ -259,6 +263,9 @@ def _apply_hostname(self, hostname):
def _select_hostname(self, hostname, fqdn):
# Prefer the short hostname over the long
# fully qualified domain name
if util.get_cfg_option_bool(self._cfg, "prefer_fqdn_over_hostname",
self.prefer_fqdn) and fqdn:
return fqdn
if not hostname:
return fqdn
return hostname
Expand Down
7 changes: 1 addition & 6 deletions cloudinit/distros/freebsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,7 @@ class Distro(cloudinit.distros.bsd.BSD):
pkg_cmd_remove_prefix = ["pkg", "remove"]
pkg_cmd_update_prefix = ["pkg", "update"]
pkg_cmd_upgrade_prefix = ["pkg", "upgrade"]

def _select_hostname(self, hostname, fqdn):
# Should be FQDN if available. See rc.conf(5) in FreeBSD
if fqdn:
return fqdn
return hostname
prefer_fqdn = True # See rc.conf(5) in FreeBSD

def _get_add_member_to_group_cmd(self, member_name, group_name):
return ['pw', 'usermod', '-n', member_name, '-G', group_name]
Expand Down
11 changes: 4 additions & 7 deletions cloudinit/distros/rhel.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ class Distro(distros.Distro):
}
}

# Should be fqdn if we can use it
# See: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/deployment_guide/ch-sysconfig # noqa: E501
prefer_fqdn = True

def __init__(self, name, cfg, paths):
distros.Distro.__init__(self, name, cfg, paths)
# This will be used to restrict certain
Expand Down Expand Up @@ -91,13 +95,6 @@ def _write_hostname(self, hostname, out_fn):
}
rhel_util.update_sysconfig_file(out_fn, host_cfg)

def _select_hostname(self, hostname, fqdn):
# Should be fqdn if we can use it
# See: https://www.centos.org/docs/5/html/Deployment_Guide-en-US/ch-sysconfig.html#s2-sysconfig-network # noqa
if fqdn:
return fqdn
return hostname

def _read_system_hostname(self):
if self.uses_systemd():
host_fn = self.systemd_hostname_conf_fn
Expand Down
12 changes: 12 additions & 0 deletions tests/integration_tests/modules/test_set_hostname.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@
fqdn: cloudinit2.i9n.cloud-init.io
"""

USER_DATA_PREFER_FQDN = """\
#cloud-config
prefer_fqdn_over_hostname: true
hostname: cloudinit1
fqdn: cloudinit2.test.io
"""


@pytest.mark.ci
class TestHostname:
Expand All @@ -33,6 +40,11 @@ def test_hostname(self, client):
hostname_output = client.execute("hostname")
assert "cloudinit2" in hostname_output.strip()

@pytest.mark.user_data(USER_DATA_PREFER_FQDN)
def test_prefer_fqdn(self, client):
hostname_output = client.execute("hostname")
assert "cloudinit2.test.io" in hostname_output.strip()

@pytest.mark.user_data(USER_DATA_FQDN)
def test_hostname_and_fqdn(self, client):
hostname_output = client.execute("hostname")
Expand Down
40 changes: 38 additions & 2 deletions tests/unittests/test_handler/test_handler_set_hostname.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,46 @@ def setUp(self):
util.ensure_dir(os.path.join(self.tmp, 'data'))
self.addCleanup(shutil.rmtree, self.tmp)

def _fetch_distro(self, kind):
def _fetch_distro(self, kind, conf=None):
cls = distros.fetch(kind)
paths = helpers.Paths({'cloud_dir': self.tmp})
return cls(kind, {}, paths)
conf = {} if conf is None else conf
return cls(kind, conf, paths)

def test_debian_write_hostname_prefer_fqdn(self):
cfg = {
'hostname': 'blah',
'prefer_fqdn_over_hostname': True,
'fqdn': 'blah.yahoo.com',
}
distro = self._fetch_distro('debian', cfg)
paths = helpers.Paths({'cloud_dir': self.tmp})
ds = None
cc = cloud.Cloud(ds, paths, {}, distro, None)
self.patchUtils(self.tmp)
cc_set_hostname.handle('cc_set_hostname',
cfg, cc, LOG, [])
contents = util.load_file("/etc/hostname")
self.assertEqual('blah.yahoo.com', contents.strip())

def test_rhel_write_hostname_prefer_hostname(self):
cfg = {
'hostname': 'blah',
'prefer_fqdn_over_hostname': False,
'fqdn': 'blah.yahoo.com',
}
distro = self._fetch_distro('rhel', cfg)
paths = helpers.Paths({'cloud_dir': self.tmp})
ds = None
cc = cloud.Cloud(ds, paths, {}, distro, None)
self.patchUtils(self.tmp)
cc_set_hostname.handle('cc_set_hostname',
cfg, cc, LOG, [])
if not distro.uses_systemd():
contents = util.load_file("/etc/sysconfig/network", decode=False)
n_cfg = ConfigObj(BytesIO(contents))
self.assertEqual({'HOSTNAME': 'blah'},
dict(n_cfg))

def test_write_hostname_rhel(self):
cfg = {
Expand Down

0 comments on commit 99d00b4

Please sign in to comment.