From a12086f1bff2dae69bb510ad9264287a1fb7e5ba Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Sat, 2 Aug 2014 21:13:17 -0700 Subject: [PATCH] Update existing nova instances with current ip During the state check, check IP address information. This gets us two things. The most obvious is that for direct IP management, a change to the config will reflect in the config of the instance. But also, if we succeed in creating the instance but fail in adding an IP, this should let us re-run and arrive in the state we were expecting. --- library/cloud/nova_compute | 47 +++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/library/cloud/nova_compute b/library/cloud/nova_compute index 2df5942a260..933d5714930 100644 --- a/library/cloud/nova_compute +++ b/library/cloud/nova_compute @@ -336,9 +336,9 @@ def _add_floating_ip_from_pool(module, nova, server): module.fail_json(msg = "Error attaching IP %s to instance %s: %s " % (ip, server.id, e.message)) -def _add_floating_ip_list(module, server): +def _add_floating_ip_list(module, server, ips): # add ip(s) to instance - for ip in module.params['floating_ips']: + for ip in ips: try: server.add_floating_ip(ip) except Exception, e: @@ -366,7 +366,7 @@ def _add_floating_ip(module, nova, server): if module.params['floating_ip_pools']: _add_floating_ip_from_pool(module, nova, server) elif module.params['floating_ips']: - _add_floating_ip_list(module, server) + _add_floating_ip_list(module, server, module.params['floating_ips']) elif module.params['auto_floating_ip']: _add_auto_floating_ip(module, nova, server) else: @@ -382,11 +382,11 @@ def _add_floating_ip(module, nova, server): return server -def _get_ips(addresses, ext_tag, key_name): +def _get_ips(addresses, ext_tag, key_name=None): ret = [] for (k, v) in addresses.iteritems(): - if k == key_name: + if key_name and k == key_name: ret.extend([addrs['addr'] for addrs in v]) else: for interface_spec in v: @@ -465,6 +465,40 @@ def _create_server(module, nova): module.exit_json(changed = True, id = info['id'], private_ip=''.join(private), public_ip=''.join(public), status = server.status, info = server._info) +def _delete_floating_ip_list(module, nova, server, extra_ips): + for ip in extra_ips: + nova.servers.remove_floating_ip(server=server.id, address=ip) + + +def _check_floating_ips(module, nova, server): + changed = False + if module.params['floating_ip_pools'] or module.params['floating_ips'] or module.params['auto_floating_ip']: + ips = _get_ips(server.addresses, 'floating') + if not ips: + # If we're configured to have a floating but we don't have one, + # let's add one + server = _add_floating_ip(module, nova, server) + changed = True + elif module.params['floating_ips']: + # we were configured to have specific ips, let's make sure we have + # those + missing_ips = [] + for ip in module.params['floating_ips']: + if ip not in ips: + missing_ips.append(ip) + if missing_ips: + server = _add_floating_ip_list(module, server, missing_ips) + changed = True + extra_ips = [] + for ip in ips: + if ip not in module.params['floating_ips']: + extra_ips.append(ip) + if extra_ips: + _delete_floating_ip_list(module, server, extra_ips) + changed = True + return (changed, server) + + def _get_server_state(module, nova): server = None try: @@ -481,9 +515,10 @@ def _get_server_state(module, nova): if server and module.params['state'] == 'present': if server.status != 'ACTIVE': module.fail_json( msg="The VM is available but not Active. state:" + server.status) + (ip_changed, server) = _check_floating_ips(module, nova, server) private = _get_ips(getattr(server, 'addresses'), 'fixed', 'private') public = _get_ips(getattr(server, 'addresses'), 'floating', 'public') - module.exit_json(changed = False, id = server.id, public_ip = ''.join(public), private_ip = ''.join(private), info = server._info) + module.exit_json(changed = ip_changed, id = server.id, public_ip = ''.join(public), private_ip = ''.join(private), info = server._info) if server and module.params['state'] == 'absent': return True if module.params['state'] == 'absent':