diff options
author | Dmitry Tantsur <divius.inside@gmail.com> | 2016-08-10 14:46:37 +0200 |
---|---|---|
committer | Dmitry Tantsur <divius.inside@gmail.com> | 2016-08-11 12:56:42 +0200 |
commit | f4ff926ab161297d2281394689ea25a7ef10cbb1 (patch) | |
tree | decf403f6175b288b5333036a906391dc4c721fe /ironic/dhcp/neutron.py | |
parent | 98d373afe8045378c00cbd72a1637ca7a146936f (diff) | |
download | ironic-f4ff926ab161297d2281394689ea25a7ef10cbb1.tar.gz |
Fix updating port MAC address for active nodes
Current update fails with HTTP 500 when trying to update a bound Neutron
port. Remove the binding before update and restore it during update.
For nodes in "active" state (or with instance_uuid assigned) only allow
such update in maintenance mode. This is not a breaking change, as previously
it did not work at all.
Change-Id: I356fc0eb3702eb16b7f8e675ea416473c65af7e3
Closes-Bug: #1611744
Diffstat (limited to 'ironic/dhcp/neutron.py')
-rw-r--r-- | ironic/dhcp/neutron.py | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/ironic/dhcp/neutron.py b/ironic/dhcp/neutron.py index 0ebe00042..021af95b7 100644 --- a/ironic/dhcp/neutron.py +++ b/ironic/dhcp/neutron.py @@ -70,6 +70,16 @@ class NeutronDHCPApi(base.BaseDHCP): LOG.exception(_LE("Failed to update Neutron port %s."), port_id) raise exception.FailedToUpdateDHCPOptOnPort(port_id=port_id) + def _get_binding(self, client, port_id): + """Get binding:host_id property from Neutron.""" + try: + return client.show_port(port_id).get('port', {}).get( + 'binding:host_id') + except neutron_client_exc.NeutronClientException: + LOG.exception(_LE('Failed to get the current binding on Neutron ' + 'port %s.'), port_id) + raise exception.FailedToUpdateMacOnPort(port_id=port_id) + def update_port_address(self, port_id, address, token=None): """Update a port's mac address. @@ -78,7 +88,21 @@ class NeutronDHCPApi(base.BaseDHCP): :param token: optional auth token. :raises: FailedToUpdateMacOnPort """ + client = neutron.get_client(token) port_req_body = {'port': {'mac_address': address}} + + current_binding = self._get_binding(client, port_id) + if current_binding: + binding_clean_body = {'port': {'binding:host_id': ''}} + try: + client.update_port(port_id, binding_clean_body) + except neutron_client_exc.NeutronClientException: + LOG.exception(_LE("Failed to remove the current binding from " + "Neutron port %s."), port_id) + raise exception.FailedToUpdateMacOnPort(port_id=port_id) + + port_req_body['port']['binding:host_id'] = current_binding + try: neutron.get_client(token).update_port(port_id, port_req_body) except neutron_client_exc.NeutronClientException: |