Adds a "simplified" floating IP management option.

Provides one-click associate and disassociated actions when in
"simple" floating IP management mode. Complex floating IP
management is still allowed via the access & security panel,
but in general it's not necessary except when managing multiple
floating IP pools or with complex network requirements.

Implements blueprint associate-ip-one-click.

Change-Id: Iaa9333b4f9a0c1590fcee50d1e56fcbaa21a84dc
This commit is contained in:
Gabriel Hurley 2012-12-10 00:27:29 -08:00
parent e0c43a488a
commit 13e5c15387
5 changed files with 84 additions and 8 deletions

View File

@ -26,5 +26,8 @@ HORIZON_CONFIG = {
# Password configuration. # Password configuration.
'password_validator': {'regex': '.*', 'password_validator': {'regex': '.*',
'help_text': _("Password is not accepted")} 'help_text': _("Password is not accepted")},
# Enable or disable simplified floating IP address management.
'simple_ip_management': True
} }

View File

@ -524,7 +524,7 @@ class BatchAction(Action):
action_failure.append(datum_display) action_failure.append(datum_display)
exceptions.handle(request, ignore=ignore) exceptions.handle(request, ignore=ignore)
#Begin with success message class, downgrade to info if problems # Begin with success message class, downgrade to info if problems.
success_message_level = messages.success success_message_level = messages.success
if action_not_allowed: if action_not_allowed:
msg = _('You do not have permission to %(action)s: %(objs)s') msg = _('You do not have permission to %(action)s: %(objs)s')

View File

@ -7,10 +7,6 @@
{% endblock page_header %} {% endblock page_header %}
{% block main %} {% block main %}
<div id="floating_ips">
{{ floating_ips_table.render }}
</div>
<div id="security_groups"> <div id="security_groups">
{{ security_groups_table.render }} {{ security_groups_table.render }}
</div> </div>
@ -18,4 +14,8 @@
<div id="keypairs"> <div id="keypairs">
{{ keypairs_table.render }} {{ keypairs_table.render }}
</div> </div>
<div id="floating_ips">
{{ floating_ips_table.render }}
</div>
{% endblock %} {% endblock %}

View File

@ -16,12 +16,16 @@
import logging import logging
from django import shortcuts
from django import template from django import template
from django.core import urlresolvers from django.core import urlresolvers
from django.template.defaultfilters import title from django.template.defaultfilters import title
from django.utils.http import urlencode from django.utils.http import urlencode
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from horizon.conf import HORIZON_CONFIG
from horizon import exceptions
from horizon import messages
from horizon import tables from horizon import tables
from horizon.templatetags import sizeformat from horizon.templatetags import sizeformat
from horizon.utils.filters import replace_underscores from horizon.utils.filters import replace_underscores
@ -221,6 +225,8 @@ class AssociateIP(tables.LinkAction):
classes = ("ajax-modal", "btn-associate") classes = ("ajax-modal", "btn-associate")
def allowed(self, request, instance): def allowed(self, request, instance):
if HORIZON_CONFIG["simple_ip_management"]:
return False
return not _is_deleting(instance) return not _is_deleting(instance)
def get_link_url(self, datum): def get_link_url(self, datum):
@ -232,6 +238,68 @@ class AssociateIP(tables.LinkAction):
return "?".join([base_url, params]) return "?".join([base_url, params])
class SimpleAssociateIP(tables.Action):
name = "associate"
verbose_name = _("Associate Floating IP")
classes = ("btn-associate",)
def allowed(self, request, instance):
if not HORIZON_CONFIG["simple_ip_management"]:
return False
return not _is_deleting(instance)
def single(self, table, request, instance):
try:
fip = api.nova.tenant_floating_ip_allocate(request)
api.nova.server_add_floating_ip(request, instance, fip.id)
messages.success(request,
_("Successfully associated floating IP: %s")
% fip.ip)
except:
exceptions.handle(request,
_("Unable to associate floating IP."))
return shortcuts.redirect("horizon:project:instances:index")
if HORIZON_CONFIG["simple_ip_management"]:
CurrentAssociateIP = SimpleAssociateIP
else:
CurrentAssociateIP = AssociateIP
class SimpleDisassociateIP(tables.Action):
name = "disassociate"
verbose_name = _("Disassociate Floating IP")
classes = ("btn-danger", "btn-disassociate",)
def allowed(self, request, instance):
if not HORIZON_CONFIG["simple_ip_management"]:
return False
return not _is_deleting(instance)
def single(self, table, request, instance_id):
try:
fips = [fip for fip in api.nova.tenant_floating_ip_list(request)
if fip.instance_id == instance_id]
# Removing multiple floating IPs at once doesn't work, so this pops
# off the first one.
if fips:
fip = fips.pop()
api.nova.server_remove_floating_ip(request,
instance_id,
fip.id)
api.nova.tenant_floating_ip_release(request, fip.id)
messages.success(request,
_("Successfully disassociated "
"floating IP: %s") % fip.ip)
else:
messages.info(request, _("No floating IPs to disassociate."))
except:
exceptions.handle(request,
_("Unable to disassociate floating IP."))
return shortcuts.redirect("horizon:project:instances:index")
class UpdateRow(tables.Row): class UpdateRow(tables.Row):
ajax = True ajax = True
@ -314,6 +382,7 @@ class InstancesTable(tables.DataTable):
status_columns = ["status", "task"] status_columns = ["status", "task"]
row_class = UpdateRow row_class = UpdateRow
table_actions = (LaunchLink, TerminateInstance) table_actions = (LaunchLink, TerminateInstance)
row_actions = (CreateSnapshot, AssociateIP, EditInstance, ConsoleLink, row_actions = (CreateSnapshot, CurrentAssociateIP,
SimpleDisassociateIP, EditInstance, ConsoleLink,
LogLink, TogglePause, ToggleSuspend, RebootInstance, LogLink, TogglePause, ToggleSuspend, RebootInstance,
TerminateInstance) TerminateInstance)

View File

@ -30,7 +30,11 @@ HORIZON_CONFIG = {
# HORIZON_CONFIG["password_validator"] = { # HORIZON_CONFIG["password_validator"] = {
# "regex": '.*', # "regex": '.*',
# "help_text": _("Your password does not meet the requirements.") # "help_text": _("Your password does not meet the requirements.")
# }, # }
# Disable simplified floating IP address management for deployments with
# multiple floating IP pools or complex network requirements.
# HORIZON_CONFIG["simple_ip_management"] = False
LOCAL_PATH = os.path.dirname(os.path.abspath(__file__)) LOCAL_PATH = os.path.dirname(os.path.abspath(__file__))