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 8994dd0
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,11 @@
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
unless the ``prefer_fqdn_over_hostname`` option is true 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 Down Expand Up @@ -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 8994dd0

Please sign in to comment.