diff --git a/doc/source/configuration/settings.rst b/doc/source/configuration/settings.rst index 0596f0d26d..c09e2e2576 100644 --- a/doc/source/configuration/settings.rst +++ b/doc/source/configuration/settings.rst @@ -428,31 +428,6 @@ there are any. This setting allows you to set rules for passwords if your organization requires them. -simple_ip_management -~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 2013.1(Grizzly) - -Default: ``True`` - -Enable or disable simplified floating IP address management. - -"Simple" floating IP address management means that the user does not ever have -to select the specific IP addresses they wish to use, and the process of -allocating an IP and assigning it to an instance is one-click. - -The "advanced" floating IP management allows users to select the floating IP -pool from which the IP should be allocated and to select a specific IP address -when associating one with an instance. - -.. note:: - - Currently "simple" floating IP address management is not compatible with - Neutron. There are two reasons for this. First, Neutron does not support - the default floating IP pool at the moment. Second, a Neutron floating IP - can be associated with each VIF and we need to check whether there is only - one VIF for an instance to enable simple association support. - user_home ~~~~~~~~~ diff --git a/horizon/conf/default.py b/horizon/conf/default.py index e6828dd3ed..f740d534aa 100644 --- a/horizon/conf/default.py +++ b/horizon/conf/default.py @@ -45,9 +45,6 @@ HORIZON_CONFIG = { 'password_autocomplete': 'off', - # Enable or disable simplified floating IP address management. - 'simple_ip_management': True, - 'integration_tests_support': getattr(settings, 'INTEGRATION_TESTS_SUPPORT', False) } diff --git a/openstack_dashboard/dashboards/project/instances/forms.py b/openstack_dashboard/dashboards/project/instances/forms.py index d73e14bcc4..6ba71cac2a 100644 --- a/openstack_dashboard/dashboards/project/instances/forms.py +++ b/openstack_dashboard/dashboards/project/instances/forms.py @@ -15,6 +15,7 @@ from django.template.defaultfilters import filesizeformat from django.urls import reverse +from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ from django.views.decorators.debug import sensitive_variables @@ -418,3 +419,54 @@ class DetachInterface(forms.SelfHandlingForm): exceptions.handle(request, _("Unable to detach interface."), redirect=redirect) return True + + +class Disassociate(forms.SelfHandlingForm): + fip = forms.ThemableChoiceField(label=_('Floating IP')) + is_release = forms.BooleanField(label=_('Release Floating IP'), + required=False) + + def __init__(self, request, *args, **kwargs): + super(Disassociate, self).__init__(request, *args, **kwargs) + instance_id = self.initial['instance_id'] + targets = api.neutron.floating_ip_target_list_by_instance( + request, instance_id) + + target_ids = [t.port_id for t in targets] + + self.fips = [fip for fip + in api.neutron.tenant_floating_ip_list(request) + if fip.port_id in target_ids] + + fip_choices = [(fip.id, fip.ip) for fip in self.fips] + fip_choices.insert(0, ('', _('Select a floating IP to disassociate'))) + self.fields['fip'].choices = fip_choices + self.fields['fip'].initial = self.fips[0].id + + def handle(self, request, data): + redirect = reverse_lazy('horizon:project:instances:index') + fip_id = data['fip'] + fips = [fip for fip in self.fips if fip.id == fip_id] + if not fips: + messages.error(request, + _("The specified floating IP no longer exists."), + redirect=redirect) + fip = fips[0] + try: + if data['is_release']: + api.neutron.tenant_floating_ip_release(request, fip_id) + messages.success( + request, + _("Successfully disassociated and released " + "floating IP %s") % fip.ip) + else: + api.neutron.floating_ip_disassociate(request, fip_id) + messages.success( + request, + _("Successfully disassociated floating IP %s") % fip.ip) + except Exception: + exceptions.handle( + request, + _('Unable to disassociate floating IP %s') % fip.ip, + redirect=redirect) + return True diff --git a/openstack_dashboard/dashboards/project/instances/tables.py b/openstack_dashboard/dashboards/project/instances/tables.py index cc76326ee7..7de62a3ef4 100644 --- a/openstack_dashboard/dashboards/project/instances/tables.py +++ b/openstack_dashboard/dashboards/project/instances/tables.py @@ -17,7 +17,6 @@ import logging from django.conf import settings from django.http import HttpResponse -from django import shortcuts from django import template from django.template.defaultfilters import title from django import urls @@ -29,7 +28,6 @@ from django.utils.translation import string_concat from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy -from horizon import conf from horizon import exceptions from horizon import messages from horizon import tables @@ -655,14 +653,11 @@ class AssociateIP(policy.PolicyTargetMixin, tables.LinkAction): return "?".join([base_url, params]) -# TODO(amotoki): [drop-nova-network] The current SimpleDisassociateIP -# just disassociates the first found FIP. It looks better to have a form -# which allows to choose which FIP should be disassociated. -# HORIZON_CONFIG['simple_ip_management'] can be dropped then. -class SimpleDisassociateIP(policy.PolicyTargetMixin, tables.Action): +class DisassociateIP(tables.LinkAction): name = "disassociate" verbose_name = _("Disassociate Floating IP") - classes = ("btn-disassociate",) + url = "horizon:project:instances:disassociate" + classes = ("btn-disassociate", 'ajax-modal') policy_rules = (("network", "update_floatingip"),) action_type = "danger" @@ -671,38 +666,12 @@ class SimpleDisassociateIP(policy.PolicyTargetMixin, tables.Action): return False if not api.neutron.floating_ip_supported(request): return False - if not conf.HORIZON_CONFIG["simple_ip_management"]: - return False for addresses in instance.addresses.values(): for address in addresses: if address.get('OS-EXT-IPS:type') == "floating": return not is_deleting(instance) return False - def single(self, table, request, instance_id): - try: - targets = api.neutron.floating_ip_target_list_by_instance( - request, instance_id) - - target_ids = [t.port_id for t in targets] - - fips = [fip for fip in api.neutron.tenant_floating_ip_list(request) - if fip.port_id in target_ids] - # Removing multiple floating IPs at once doesn't work, so this pops - # off the first one. - if fips: - fip = fips.pop() - api.neutron.floating_ip_disassociate(request, fip.id) - messages.success(request, - _("Successfully disassociated " - "floating IP: %s") % fip.ip) - else: - messages.info(request, _("No floating IPs to disassociate.")) - except Exception: - exceptions.handle(request, - _("Unable to disassociate floating IP.")) - return shortcuts.redirect(request.get_full_path()) - class UpdateMetadata(policy.PolicyTargetMixin, tables.LinkAction): name = "update_metadata" @@ -1280,10 +1249,10 @@ class InstancesTable(tables.DataTable): table_actions = launch_actions + (DeleteInstance, InstancesFilterAction) row_actions = (StartInstance, ConfirmResize, RevertResize, - CreateSnapshot, AssociateIP, - SimpleDisassociateIP, AttachInterface, - DetachInterface, EditInstance, AttachVolume, - DetachVolume, UpdateMetadata, DecryptInstancePassword, + CreateSnapshot, AssociateIP, DisassociateIP, + AttachInterface, DetachInterface, EditInstance, + AttachVolume, DetachVolume, + UpdateMetadata, DecryptInstancePassword, EditInstanceSecurityGroups, ConsoleLink, LogLink, TogglePause, ToggleSuspend, ToggleShelve, ResizeLink, LockInstance, UnlockInstance, diff --git a/openstack_dashboard/dashboards/project/instances/templates/instances/_disassociate.html b/openstack_dashboard/dashboards/project/instances/templates/instances/_disassociate.html new file mode 100644 index 0000000000..63007e9432 --- /dev/null +++ b/openstack_dashboard/dashboards/project/instances/templates/instances/_disassociate.html @@ -0,0 +1,28 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} + +{% block form_id %}disassociate_fip_form{% endblock %} +{% block form_action %}{% url "horizon:project:instances:disassociate" instance_id %}{% endblock %} + +{% block modal_id %}disassocaite_fip_modal{% endblock %} +{% block modal-header %}{% trans "Disassociate Floating IP" %}{% endblock %} + +{% block modal-body %} +
{% blocktrans trimmed %} + Select the floating IP to be disassociated from the instance. + {% endblocktrans %}
+