cloud-init-dev team mailing list archive
-
cloud-init-dev team
-
Mailing list archive
-
Message #01760
[Merge] ~bbaude/cloud-init:azure_bounce into cloud-init:master
Brent Baude has proposed merging ~bbaude/cloud-init:azure_bounce into cloud-init:master.
Requested reviews:
Server Team CI bot (server-team-bot): continuous-integration
cloud init development team (cloud-init-dev)
For more details, see:
https://code.launchpad.net/~bbaude/cloud-init/+git/cloud-init/+merge/320411
This PR adds the ability to set the hostname and bounce the network interfaces when provisioning in Azure with just cloud-init. The hostname must be set and network bounced in order for DNS to work correctly in Azure when communicating between azure vms.
--
Your team cloud init development team is requested to review the proposed merge of ~bbaude/cloud-init:azure_bounce into cloud-init:master.
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
index c5af8b8..9afff95 100644
--- a/cloudinit/sources/DataSourceAzure.py
+++ b/cloudinit/sources/DataSourceAzure.py
@@ -74,28 +74,6 @@ def set_hostname(hostname, hostname_command='hostname'):
util.subp([hostname_command, hostname])
-@contextlib.contextmanager
-def temporary_hostname(temp_hostname, cfg, hostname_command='hostname'):
- """
- Set a temporary hostname, restoring the previous hostname on exit.
-
- Will have the value of the previous hostname when used as a context
- manager, or None if the hostname was not changed.
- """
- policy = cfg['hostname_bounce']['policy']
- previous_hostname = get_hostname(hostname_command)
- if (not util.is_true(cfg.get('set_hostname')) or
- util.is_false(policy) or
- (previous_hostname == temp_hostname and policy != 'force')):
- yield None
- return
- set_hostname(temp_hostname, hostname_command)
- try:
- yield previous_hostname
- finally:
- set_hostname(previous_hostname, hostname_command)
-
-
class DataSourceAzureNet(sources.DataSource):
def __init__(self, sys_cfg, distro, paths):
sources.DataSource.__init__(self, sys_cfg, distro, paths)
@@ -111,50 +89,56 @@ class DataSourceAzureNet(sources.DataSource):
root = sources.DataSource.__str__(self)
return "%s [seed=%s]" % (root, self.seed)
+ def set_hostname_and_bounce(self):
+ # When using cloud-init to provision, we have to set the hostname from
+ # the metadata and "bounce" the network to force DDNS to update via
+ # dhclient
+ hostname_command = self.ds_cfg['hostname_bounce']['hostname_command']
+ prev_hostname, _ = util.subp([hostname_command], capture=True)
+ hostname = self.metadata.get('local-hostname')
+ LOG.debug("Hostname in metadata is {}".format(hostname))
+ self.distro.set_hostname(hostname, hostname)
+ cfg = self.ds_cfg['hostname_bounce']
+
+ # "Bouncing" the network, same as what is done with the agent path
+ try:
+ perform_hostname_bounce(hostname=hostname, cfg=cfg, prev_hostname=prev_hostname)
+ except Exception as e:
+ LOG.warn("Failed publishing hostname: %s", e)
+ util.logexc(LOG, "handling set_hostname failed")
+
def get_metadata_from_agent(self):
temp_hostname = self.metadata.get('local-hostname')
- hostname_command = self.ds_cfg['hostname_bounce']['hostname_command']
agent_cmd = self.ds_cfg['agent_command']
LOG.debug("Getting metadata via agent. hostname=%s cmd=%s",
temp_hostname, agent_cmd)
- with temporary_hostname(temp_hostname, self.ds_cfg,
- hostname_command=hostname_command) \
- as previous_hostname:
- if (previous_hostname is not None and
- util.is_true(self.ds_cfg.get('set_hostname'))):
- cfg = self.ds_cfg['hostname_bounce']
- try:
- perform_hostname_bounce(hostname=temp_hostname,
- cfg=cfg,
- prev_hostname=previous_hostname)
- except Exception as e:
- LOG.warn("Failed publishing hostname: %s", e)
- util.logexc(LOG, "handling set_hostname failed")
- try:
- invoke_agent(agent_cmd)
- except util.ProcessExecutionError:
- # claim the datasource even if the command failed
- util.logexc(LOG, "agent command '%s' failed.",
- self.ds_cfg['agent_command'])
-
- ddir = self.ds_cfg['data_dir']
-
- fp_files = []
- key_value = None
- for pk in self.cfg.get('_pubkeys', []):
- if pk.get('value', None):
- key_value = pk['value']
- LOG.debug("ssh authentication: using value from fabric")
- else:
- bname = str(pk['fingerprint'] + ".crt")
- fp_files += [os.path.join(ddir, bname)]
- LOG.debug("ssh authentication: "
- "using fingerprint from fabirc")
-
- missing = util.log_time(logfunc=LOG.debug, msg="waiting for files",
- func=wait_for_files,
- args=(fp_files,))
+ self.set_hostname_and_bounce()
+
+ try:
+ invoke_agent(agent_cmd)
+ except util.ProcessExecutionError:
+ # claim the datasource even if the command failed
+ util.logexc(LOG, "agent command '%s' failed.",
+ self.ds_cfg['agent_command'])
+
+ ddir = self.ds_cfg['data_dir']
+
+ fp_files = []
+ key_value = None
+ for pk in self.cfg.get('_pubkeys', []):
+ if pk.get('value', None):
+ key_value = pk['value']
+ LOG.debug("ssh authentication: using value from fabric")
+ else:
+ bname = str(pk['fingerprint'] + ".crt")
+ fp_files += [os.path.join(ddir, bname)]
+ LOG.debug("ssh authentication: "
+ "using fingerprint from fabirc")
+
+ missing = util.log_time(logfunc=LOG.debug, msg="waiting for files",
+ func=wait_for_files,
+ args=(fp_files,))
if len(missing):
LOG.warn("Did not find files, but going on: %s", missing)
@@ -220,6 +204,8 @@ class DataSourceAzureNet(sources.DataSource):
write_files(ddir, files, dirmode=0o700)
if self.ds_cfg['agent_command'] == AGENT_START_BUILTIN:
+ self.set_hostname_and_bounce()
+
metadata_func = partial(get_metadata_from_fabric,
fallback_lease_file=self.
dhclient_lease_file)
diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py
index 3d01072..1829450 100644
--- a/cloudinit/sources/__init__.py
+++ b/cloudinit/sources/__init__.py
@@ -210,7 +210,7 @@ class DataSource(object):
else:
hostname = toks[0]
- if fqdn:
+ if fqdn and domain != defdomain:
return "%s.%s" % (hostname, domain)
else:
return hostname