diff options
author | Chad Smith <chad.smith@canonical.com> | 2018-03-14 23:38:07 -0600 |
---|---|---|
committer | Chad Smith <chad.smith@canonical.com> | 2018-03-14 23:38:07 -0600 |
commit | 133ad2cb327ad17b7b81319fac8f9f14577c04df (patch) | |
tree | ca14c7c958537e00f1c7ce93405eb77cee85b81e /cloudinit/config | |
parent | 76460b63f9c310c7de4e5f0c11d1525bedd277e1 (diff) | |
download | vyos-cloud-init-133ad2cb327ad17b7b81319fac8f9f14577c04df.tar.gz vyos-cloud-init-133ad2cb327ad17b7b81319fac8f9f14577c04df.zip |
set_hostname: When present in metadata, set it before network bringup.
When instance meta-data provides hostname information, run
cc_set_hostname in the init-local or init-net stage before network
comes up.
Prevent an initial DHCP request which leaks the stock cloud-image default
hostname before the meta-data provided hostname was processed.
A leaked cloud-image hostname adversely affects Dynamic DNS which
would reallocate 'ubuntu' hostname in DNS to every instance brought up by
cloud-init. These instances would only update DNS to the cloud-init
configured hostname upon DHCP lease renewal.
This branch extends the get_hostname methods in datasource, cloud and
util to limit results to metadata_only to avoid extra cost of querying
the distro for hostname information if metadata does not provide that
information.
LP: #1746455
Diffstat (limited to 'cloudinit/config')
-rw-r--r-- | cloudinit/config/cc_set_hostname.py | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/cloudinit/config/cc_set_hostname.py b/cloudinit/config/cc_set_hostname.py index aa3dfe5f..3d2b2da3 100644 --- a/cloudinit/config/cc_set_hostname.py +++ b/cloudinit/config/cc_set_hostname.py @@ -32,22 +32,51 @@ will be used. hostname: <fqdn/hostname> """ +import os + + +from cloudinit.atomic_helper import write_json from cloudinit import util +class SetHostnameError(Exception): + """Raised when the distro runs into an exception when setting hostname. + + This may happen if we attempt to set the hostname early in cloud-init's + init-local timeframe as certain services may not be running yet. + """ + pass + + def handle(name, cfg, cloud, log, _args): if util.get_cfg_option_bool(cfg, "preserve_hostname", False): log.debug(("Configuration option 'preserve_hostname' is set," " not setting the hostname in module %s"), name) return - (hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud) + # Check for previous successful invocation of set-hostname + + # set-hostname artifact file accounts for both hostname and fqdn + # deltas. As such, it's format is different than cc_update_hostname's + # previous-hostname file which only contains the base hostname. + # TODO consolidate previous-hostname and set-hostname artifact files and + # distro._read_hostname implementation so we only validate one artifact. + prev_fn = os.path.join(cloud.get_cpath('data'), "set-hostname") + prev_hostname = {} + if os.path.exists(prev_fn): + prev_hostname = util.load_json(util.load_file(prev_fn)) + hostname_changed = (hostname != prev_hostname.get('hostname') or + fqdn != prev_hostname.get('fqdn')) + if not hostname_changed: + log.debug('No hostname changes. Skipping set-hostname') + return + log.debug("Setting the hostname to %s (%s)", fqdn, hostname) try: - log.debug("Setting the hostname to %s (%s)", fqdn, hostname) cloud.distro.set_hostname(hostname, fqdn) - except Exception: - util.logexc(log, "Failed to set the hostname to %s (%s)", fqdn, - hostname) - raise + except Exception as e: + msg = "Failed to set the hostname to %s (%s)" % (fqdn, hostname) + util.logexc(log, msg) + raise SetHostnameError("%s: %s" % (msg, e)) + write_json(prev_fn, {'hostname': hostname, 'fqdn': fqdn}) # vi: ts=4 expandtab |