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
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
index c5af8b8..48a3e1d 100644
--- a/cloudinit/sources/DataSourceAzure.py
+++ b/cloudinit/sources/DataSourceAzure.py
@@ -111,50 +111,62 @@ class DataSourceAzureNet(sources.DataSource):
111 root = sources.DataSource.__str__(self)111 root = sources.DataSource.__str__(self)
112 return "%s [seed=%s]" % (root, self.seed)112 return "%s [seed=%s]" % (root, self.seed)
113113
114 def get_metadata_from_agent(self):114 def bounce_network_with_azure_hostname(self):
115 temp_hostname = self.metadata.get('local-hostname')115 # When using cloud-init to provision, we have to set the hostname from
116 # the metadata and "bounce" the network to force DDNS to update via
117 # dhclient
118 azure_hostname = self.metadata.get('local-hostname')
119 LOG.debug("Hostname in metadata is {}".format(azure_hostname))
116 hostname_command = self.ds_cfg['hostname_bounce']['hostname_command']120 hostname_command = self.ds_cfg['hostname_bounce']['hostname_command']
117 agent_cmd = self.ds_cfg['agent_command']121
118 LOG.debug("Getting metadata via agent. hostname=%s cmd=%s",122 with temporary_hostname(azure_hostname, self.ds_cfg,
119 temp_hostname, agent_cmd)
120 with temporary_hostname(temp_hostname, self.ds_cfg,
121 hostname_command=hostname_command) \123 hostname_command=hostname_command) \
122 as previous_hostname:124 as previous_hostname:
123 if (previous_hostname is not None and125 if (previous_hostname is not None and
124 util.is_true(self.ds_cfg.get('set_hostname'))):126 util.is_true(self.ds_cfg.get('set_hostname'))):
125 cfg = self.ds_cfg['hostname_bounce']127 cfg = self.ds_cfg['hostname_bounce']
128
129 # "Bouncing" the network
126 try:130 try:
127 perform_hostname_bounce(hostname=temp_hostname,131 perform_hostname_bounce(hostname=azure_hostname,
128 cfg=cfg,132 cfg=cfg,
129 prev_hostname=previous_hostname)133 prev_hostname=previous_hostname)
130 except Exception as e:134 except Exception as e:
131 LOG.warn("Failed publishing hostname: %s", e)135 LOG.warn("Failed publishing hostname: %s", e)
132 util.logexc(LOG, "handling set_hostname failed")136 util.logexc(LOG, "handling set_hostname failed")
133137
134 try:138 def get_metadata_from_agent(self):
135 invoke_agent(agent_cmd)139 temp_hostname = self.metadata.get('local-hostname')
136 except util.ProcessExecutionError:140 agent_cmd = self.ds_cfg['agent_command']
137 # claim the datasource even if the command failed141 LOG.debug("Getting metadata via agent. hostname=%s cmd=%s",
138 util.logexc(LOG, "agent command '%s' failed.",142 temp_hostname, agent_cmd)
139 self.ds_cfg['agent_command'])143
140144 self.bounce_network_with_azure_hostname()
141 ddir = self.ds_cfg['data_dir']145
142146 try:
143 fp_files = []147 invoke_agent(agent_cmd)
144 key_value = None148 except util.ProcessExecutionError:
145 for pk in self.cfg.get('_pubkeys', []):149 # claim the datasource even if the command failed
146 if pk.get('value', None):150 util.logexc(LOG, "agent command '%s' failed.",
147 key_value = pk['value']151 self.ds_cfg['agent_command'])
148 LOG.debug("ssh authentication: using value from fabric")152
149 else:153 ddir = self.ds_cfg['data_dir']
150 bname = str(pk['fingerprint'] + ".crt")154
151 fp_files += [os.path.join(ddir, bname)]155 fp_files = []
152 LOG.debug("ssh authentication: "156 key_value = None
153 "using fingerprint from fabirc")157 for pk in self.cfg.get('_pubkeys', []):
154158 if pk.get('value', None):
155 missing = util.log_time(logfunc=LOG.debug, msg="waiting for files",159 key_value = pk['value']
156 func=wait_for_files,160 LOG.debug("ssh authentication: using value from fabric")
157 args=(fp_files,))161 else:
162 bname = str(pk['fingerprint'] + ".crt")
163 fp_files += [os.path.join(ddir, bname)]
164 LOG.debug("ssh authentication: "
165 "using fingerprint from fabirc")
166
167 missing = util.log_time(logfunc=LOG.debug, msg="waiting for files",
168 func=wait_for_files,
169 args=(fp_files,))
158 if len(missing):170 if len(missing):
159 LOG.warn("Did not find files, but going on: %s", missing)171 LOG.warn("Did not find files, but going on: %s", missing)
160172
@@ -220,6 +232,8 @@ class DataSourceAzureNet(sources.DataSource):
220 write_files(ddir, files, dirmode=0o700)232 write_files(ddir, files, dirmode=0o700)
221233
222 if self.ds_cfg['agent_command'] == AGENT_START_BUILTIN:234 if self.ds_cfg['agent_command'] == AGENT_START_BUILTIN:
235 self.bounce_network_with_azure_hostname()
236
223 metadata_func = partial(get_metadata_from_fabric,237 metadata_func = partial(get_metadata_from_fabric,
224 fallback_lease_file=self.238 fallback_lease_file=self.
225 dhclient_lease_file)239 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):
210 else:210 else:
211 hostname = toks[0]211 hostname = toks[0]
212212
213 if fqdn:213 if fqdn and domain != defdomain:
214 return "%s.%s" % (hostname, domain)214 return "%s.%s" % (hostname, domain)
215 else:215 else:
216 return hostname216 return hostname

Subscribers

People subscribed via source and target branches