140
145
"port %s."), port_id)
141
146
raise exception.FailedToUpdateMacOnPort(port_id=port_id)
143
def update_dhcp_opts(self, task, options):
148
def update_dhcp_opts(self, task, options, vifs=None):
144
149
"""Send or update the DHCP BOOT options for this node.
146
151
:param task: A TaskManager instance.
147
:param dhcp_opts: this will be a list of dicts, e.g.
152
:param options: this will be a list of dicts, e.g.
154
159
'opt_value': '123.123.123.456'},
155
160
{'opt_name': 'tftp-server',
156
161
'opt_value': '123.123.123.123'}]
162
:param vifs: a dict of Neutron port dicts to update DHCP options on.
163
The keys should be Ironic port UUIDs, and the values should be
165
If the value is None, will get the list of ports from the Ironic
158
vifs = network.get_node_vif_ids(task)
169
vifs = network.get_node_vif_ids(task)
160
171
raise exception.FailedToUpdateDHCPOptOnPort(
161
172
_("No VIFs found for node %(node)s when attempting "
184
195
# TODO(adam_g): Hack to workaround bug 1334447 until we have a
185
196
# mechanism for synchronizing events with Neutron. We need to sleep
186
197
# only if we are booting VMs, which is implied by SSHPower, to ensure
187
# they do not boot before Neutron agents have setup sufficent DHCP
198
# they do not boot before Neutron agents have setup sufficient DHCP
188
199
# config for netboot.
189
200
if isinstance(task.driver.power, ssh.SSHPower):
190
201
LOG.debug("Waiting 15 seconds for Neutron.")
275
286
{'node': task.node.uuid, 'ports': failures})
277
288
return ip_addresses
290
def create_cleaning_ports(self, task):
291
"""Create neutron ports for each port on task.node to boot the ramdisk.
293
:param task: a TaskManager instance.
294
:raises: InvalidParameterValue if the cleaning network is None
295
:returns: a dictionary in the form {port.uuid: neutron_port['id']}
297
if not CONF.neutron.cleaning_network_uuid:
298
raise exception.InvalidParameterValue(_('Valid cleaning network '
299
'UUID not provided'))
300
neutron_client = _build_client(task.context.auth_token)
303
'network_id': CONF.neutron.cleaning_network_uuid,
304
'admin_state_up': True,
308
for ironic_port in task.ports:
309
body['port']['mac_address'] = ironic_port.address
311
port = neutron_client.create_port(body)
312
except neutron_client_exc.ConnectionFailed as e:
313
msg = (_('Could not create cleaning port on network %(net)s '
314
'from %(node)s. %(exc)s') %
315
{'net': CONF.neutron.cleaning_network_uuid,
316
'node': task.node.uuid,
319
return manager.cleaning_error_handler(task, msg)
320
if not port.get('port') or not port['port'].get('id'):
323
self.delete_cleaning_ports(task)
325
# Log the error, but continue to cleaning error handler
326
LOG.exception(_LE('Failed to rollback cleaning port '
327
'changes for node %s') % task.node.uuid)
328
msg = (_('Failed to create cleaning ports for node '
329
'%(node)s') % task.node.uuid)
331
return manager.cleaning_error_handler(task, msg)
332
# Match return value of get_node_vif_ids()
333
ports[ironic_port.uuid] = port['port']['id']
336
def delete_cleaning_ports(self, task):
337
"""Deletes the neutron port created for booting the ramdisk.
339
:param task: a TaskManager instance.
341
neutron_client = _build_client(task.context.auth_token)
342
macs = [p.address for p in task.ports]
344
'network_id': CONF.neutron.cleaning_network_uuid
347
ports = neutron_client.list_ports(**params)
348
except neutron_client_exc.ConnectionFailed as e:
349
msg = (_('Could not get cleaning network vif for %(node)s '
350
'from Neutron, possible network issue. %(exc)s') %
351
{'node': task.node.uuid,
354
return manager.cleaning_error_handler(task, msg)
356
# Iterate the list of Neutron port dicts, remove the ones we added
357
for neutron_port in ports.get('ports', []):
358
# Only delete ports using the node's mac addresses
359
if neutron_port.get('mac_address') in macs:
361
neutron_client.delete_port(neutron_port.get('id'))
362
except neutron_client_exc.ConnectionFailed as e:
363
msg = (_('Could not remove cleaning ports on network '
364
'%(net)s from %(node)s, possible network issue. '
366
{'net': CONF.neutron.cleaning_network_uuid,
367
'node': task.node.uuid,
370
return manager.cleaning_error_handler(task, msg)