Merge ~bbaude/cloud-init:azure_bounce into cloud-init:master

Proposed by Brent Baude
Status: Merged
Approved by: Scott Moser
Approved revision: 34b9adebdb26c1b3e68da5a3ad484d513c4e004d
Merged at revision: 86715c88aab8561e1ddadac95671f6095d16f9e7
Proposed branch: ~bbaude/cloud-init:azure_bounce
Merge into: cloud-init:master
Diff against target: 121 lines (+47/-33)
2 files modified
cloudinit/sources/DataSourceAzure.py (+46/-32)
cloudinit/sources/__init__.py (+1/-1)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
Dan Watkins Approve
Review via email: mp+320411@code.launchpad.net

Commit message

Bounce network interface for Azure

When deploying on Azure and using only cloud-init, you must "bounce"
the network interface to trigger a DDNS update. This allows dhclient
to register the hostname with Azure so that DNS works correctly on their
private networks (i.e. between vm and vm).

The agent path was already doing the bounce so this creates parity between the built-in path and the agent.

Description of the change

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.

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Joshua Powers (powersj) wrote :

After adding commit 9040e78, this ran integration tests successfully:
https://paste.ubuntu.com/24217659/

Revision history for this message
Dan Watkins (oddbloke) wrote :

One step closer to killing the agent, I like it!

review: Approve
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
2index c5af8b8..48a3e1d 100644
3--- a/cloudinit/sources/DataSourceAzure.py
4+++ b/cloudinit/sources/DataSourceAzure.py
5@@ -111,50 +111,62 @@ class DataSourceAzureNet(sources.DataSource):
6 root = sources.DataSource.__str__(self)
7 return "%s [seed=%s]" % (root, self.seed)
8
9- def get_metadata_from_agent(self):
10- temp_hostname = self.metadata.get('local-hostname')
11+ def bounce_network_with_azure_hostname(self):
12+ # When using cloud-init to provision, we have to set the hostname from
13+ # the metadata and "bounce" the network to force DDNS to update via
14+ # dhclient
15+ azure_hostname = self.metadata.get('local-hostname')
16+ LOG.debug("Hostname in metadata is {}".format(azure_hostname))
17 hostname_command = self.ds_cfg['hostname_bounce']['hostname_command']
18- agent_cmd = self.ds_cfg['agent_command']
19- LOG.debug("Getting metadata via agent. hostname=%s cmd=%s",
20- temp_hostname, agent_cmd)
21- with temporary_hostname(temp_hostname, self.ds_cfg,
22+
23+ with temporary_hostname(azure_hostname, self.ds_cfg,
24 hostname_command=hostname_command) \
25 as previous_hostname:
26 if (previous_hostname is not None and
27- util.is_true(self.ds_cfg.get('set_hostname'))):
28+ util.is_true(self.ds_cfg.get('set_hostname'))):
29 cfg = self.ds_cfg['hostname_bounce']
30+
31+ # "Bouncing" the network
32 try:
33- perform_hostname_bounce(hostname=temp_hostname,
34+ perform_hostname_bounce(hostname=azure_hostname,
35 cfg=cfg,
36 prev_hostname=previous_hostname)
37 except Exception as e:
38 LOG.warn("Failed publishing hostname: %s", e)
39 util.logexc(LOG, "handling set_hostname failed")
40
41- try:
42- invoke_agent(agent_cmd)
43- except util.ProcessExecutionError:
44- # claim the datasource even if the command failed
45- util.logexc(LOG, "agent command '%s' failed.",
46- self.ds_cfg['agent_command'])
47-
48- ddir = self.ds_cfg['data_dir']
49-
50- fp_files = []
51- key_value = None
52- for pk in self.cfg.get('_pubkeys', []):
53- if pk.get('value', None):
54- key_value = pk['value']
55- LOG.debug("ssh authentication: using value from fabric")
56- else:
57- bname = str(pk['fingerprint'] + ".crt")
58- fp_files += [os.path.join(ddir, bname)]
59- LOG.debug("ssh authentication: "
60- "using fingerprint from fabirc")
61-
62- missing = util.log_time(logfunc=LOG.debug, msg="waiting for files",
63- func=wait_for_files,
64- args=(fp_files,))
65+ def get_metadata_from_agent(self):
66+ temp_hostname = self.metadata.get('local-hostname')
67+ agent_cmd = self.ds_cfg['agent_command']
68+ LOG.debug("Getting metadata via agent. hostname=%s cmd=%s",
69+ temp_hostname, agent_cmd)
70+
71+ self.bounce_network_with_azure_hostname()
72+
73+ try:
74+ invoke_agent(agent_cmd)
75+ except util.ProcessExecutionError:
76+ # claim the datasource even if the command failed
77+ util.logexc(LOG, "agent command '%s' failed.",
78+ self.ds_cfg['agent_command'])
79+
80+ ddir = self.ds_cfg['data_dir']
81+
82+ fp_files = []
83+ key_value = None
84+ for pk in self.cfg.get('_pubkeys', []):
85+ if pk.get('value', None):
86+ key_value = pk['value']
87+ LOG.debug("ssh authentication: using value from fabric")
88+ else:
89+ bname = str(pk['fingerprint'] + ".crt")
90+ fp_files += [os.path.join(ddir, bname)]
91+ LOG.debug("ssh authentication: "
92+ "using fingerprint from fabirc")
93+
94+ missing = util.log_time(logfunc=LOG.debug, msg="waiting for files",
95+ func=wait_for_files,
96+ args=(fp_files,))
97 if len(missing):
98 LOG.warn("Did not find files, but going on: %s", missing)
99
100@@ -220,6 +232,8 @@ class DataSourceAzureNet(sources.DataSource):
101 write_files(ddir, files, dirmode=0o700)
102
103 if self.ds_cfg['agent_command'] == AGENT_START_BUILTIN:
104+ self.bounce_network_with_azure_hostname()
105+
106 metadata_func = partial(get_metadata_from_fabric,
107 fallback_lease_file=self.
108 dhclient_lease_file)
109diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py
110index 3d01072..1829450 100644
111--- a/cloudinit/sources/__init__.py
112+++ b/cloudinit/sources/__init__.py
113@@ -210,7 +210,7 @@ class DataSource(object):
114 else:
115 hostname = toks[0]
116
117- if fqdn:
118+ if fqdn and domain != defdomain:
119 return "%s.%s" % (hostname, domain)
120 else:
121 return hostname

Subscribers

People subscribed via source and target branches