
According to the Django architecture, all fields are grouped in the django.form module, Horizon fields were dispatched in two modules utils and form. This patch cleanup the loading of Horizon specific fields. Change-Id: Ib18848a8cc06dbd5984ec02d7cd647145124ced4 Closes-Bug: #1287634
316 lines
12 KiB
Python
316 lines
12 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
# Copyright 2013, Big Switch Networks, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
#
|
|
# @author: KC Wang, Big Switch Networks
|
|
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
from horizon import exceptions
|
|
from horizon import forms
|
|
from horizon.utils import validators
|
|
from horizon import workflows
|
|
|
|
from openstack_dashboard import api
|
|
|
|
port_validator = validators.validate_port_or_colon_separated_port_range
|
|
|
|
|
|
class AddRuleAction(workflows.Action):
|
|
name = forms.CharField(
|
|
max_length=80,
|
|
label=_("Name"),
|
|
required=False)
|
|
description = forms.CharField(
|
|
max_length=80,
|
|
label=_("Description"),
|
|
required=False)
|
|
protocol = forms.ChoiceField(
|
|
label=_("Protocol"),
|
|
choices=[('tcp', _('TCP')),
|
|
('udp', _('UDP')),
|
|
('icmp', _('ICMP')),
|
|
('any', _('ANY'))],)
|
|
action = forms.ChoiceField(
|
|
label=_("Action"),
|
|
choices=[('allow', _('ALLOW')),
|
|
('deny', _('DENY'))],)
|
|
source_ip_address = forms.IPField(
|
|
label=_("Source IP Address/Subnet"),
|
|
version=forms.IPv4 | forms.IPv6,
|
|
required=False, mask=True)
|
|
destination_ip_address = forms.IPField(
|
|
label=_("Destination IP Address/Subnet"),
|
|
version=forms.IPv4 | forms.IPv6,
|
|
required=False, mask=True)
|
|
source_port = forms.CharField(
|
|
max_length=80,
|
|
label=_("Source Port/Port Range"),
|
|
required=False,
|
|
validators=[port_validator])
|
|
destination_port = forms.CharField(
|
|
max_length=80,
|
|
label=_("Destination Port/Port Range"),
|
|
required=False,
|
|
validators=[port_validator])
|
|
shared = forms.BooleanField(
|
|
label=_("Shared"), initial=False, required=False)
|
|
enabled = forms.BooleanField(
|
|
label=_("Enabled"), initial=True, required=False)
|
|
|
|
def __init__(self, request, *args, **kwargs):
|
|
super(AddRuleAction, self).__init__(request, *args, **kwargs)
|
|
|
|
class Meta:
|
|
name = _("AddRule")
|
|
permissions = ('openstack.services.network',)
|
|
help_text = _("Create a firewall rule.\n\n"
|
|
"Protocol and action must be specified. "
|
|
"Other fields are optional.")
|
|
|
|
|
|
class AddRuleStep(workflows.Step):
|
|
action_class = AddRuleAction
|
|
contributes = ("name", "description", "protocol", "action",
|
|
"source_ip_address", "source_port",
|
|
"destination_ip_address", "destination_port",
|
|
"enabled", "shared")
|
|
|
|
def contribute(self, data, context):
|
|
context = super(AddRuleStep, self).contribute(data, context)
|
|
if data:
|
|
if context['protocol'] == 'any':
|
|
del context['protocol']
|
|
for field in ['source_port',
|
|
'destination_port',
|
|
'source_ip_address',
|
|
'destination_ip_address']:
|
|
if not context[field]:
|
|
del context[field]
|
|
return context
|
|
|
|
|
|
class AddRule(workflows.Workflow):
|
|
slug = "addrule"
|
|
name = _("Add Rule")
|
|
finalize_button_name = _("Add")
|
|
success_message = _('Added Rule "%s".')
|
|
failure_message = _('Unable to add Rule "%s".')
|
|
success_url = "horizon:project:firewalls:index"
|
|
# fwaas is designed to support a wide range of vendor
|
|
# firewalls. Considering the multitude of vendor firewall
|
|
# features in place today, firewall_rule definition can
|
|
# involve more complex configuration over time. Hence,
|
|
# a workflow instead of a single form is used for
|
|
# firewall_rule add to be ready for future extension.
|
|
default_steps = (AddRuleStep,)
|
|
|
|
def format_status_message(self, message):
|
|
return message % self.context.get('name')
|
|
|
|
def handle(self, request, context):
|
|
try:
|
|
api.fwaas.rule_create(request, **context)
|
|
return True
|
|
except Exception as e:
|
|
msg = self.format_status_message(self.failure_message) + str(e)
|
|
exceptions.handle(request, msg)
|
|
return False
|
|
|
|
|
|
class SelectRulesAction(workflows.Action):
|
|
rule = forms.MultipleChoiceField(
|
|
label=_("Rules"),
|
|
required=False,
|
|
widget=forms.CheckboxSelectMultiple(),
|
|
help_text=_("Create a policy with selected rules."))
|
|
|
|
class Meta:
|
|
name = _("Rules")
|
|
permissions = ('openstack.services.network',)
|
|
help_text = _("Select rules for your policy.")
|
|
|
|
def populate_rule_choices(self, request, context):
|
|
try:
|
|
tenant_id = self.request.user.tenant_id
|
|
rules = api.fwaas.rule_list(request, tenant_id=tenant_id)
|
|
for r in rules:
|
|
r.set_id_as_name_if_empty()
|
|
rules = sorted(rules,
|
|
key=lambda rule: rule.name)
|
|
rule_list = [(rule.id, rule.name) for rule in rules
|
|
if not rule.firewall_policy_id]
|
|
except Exception as e:
|
|
rule_list = []
|
|
exceptions.handle(request,
|
|
_('Unable to retrieve rules (%(error)s).') % {
|
|
'error': str(e)})
|
|
return rule_list
|
|
|
|
|
|
class SelectRulesStep(workflows.Step):
|
|
action_class = SelectRulesAction
|
|
template_name = "project/firewalls/_update_rules.html"
|
|
contributes = ("firewall_rules",)
|
|
|
|
def contribute(self, data, context):
|
|
if data:
|
|
rules = self.workflow.request.POST.getlist("rule")
|
|
if rules:
|
|
rules = [r for r in rules if r != '']
|
|
context['firewall_rules'] = rules
|
|
return context
|
|
|
|
|
|
class AddPolicyAction(workflows.Action):
|
|
name = forms.CharField(max_length=80,
|
|
label=_("Name"),
|
|
required=True)
|
|
description = forms.CharField(max_length=80,
|
|
label=_("Description"),
|
|
required=False)
|
|
shared = forms.BooleanField(label=_("Shared"),
|
|
initial=False,
|
|
required=False)
|
|
audited = forms.BooleanField(label=_("Audited"),
|
|
initial=False,
|
|
required=False)
|
|
|
|
def __init__(self, request, *args, **kwargs):
|
|
super(AddPolicyAction, self).__init__(request, *args, **kwargs)
|
|
|
|
class Meta:
|
|
name = _("AddPolicy")
|
|
permissions = ('openstack.services.network',)
|
|
help_text = _("Create a firewall policy with an ordered list "
|
|
"of firewall rules.\n\n"
|
|
"A name must be given. Firewall rules are "
|
|
"added in the order placed under the Rules tab.")
|
|
|
|
|
|
class AddPolicyStep(workflows.Step):
|
|
action_class = AddPolicyAction
|
|
contributes = ("name", "description", "shared", "audited")
|
|
|
|
def contribute(self, data, context):
|
|
context = super(AddPolicyStep, self).contribute(data, context)
|
|
if data:
|
|
return context
|
|
|
|
|
|
class AddPolicy(workflows.Workflow):
|
|
slug = "addpolicy"
|
|
name = _("Add Policy")
|
|
finalize_button_name = _("Add")
|
|
success_message = _('Added Policy "%s".')
|
|
failure_message = _('Unable to add Policy "%s".')
|
|
success_url = "horizon:project:firewalls:index"
|
|
default_steps = (AddPolicyStep, SelectRulesStep)
|
|
|
|
def format_status_message(self, message):
|
|
return message % self.context.get('name')
|
|
|
|
def handle(self, request, context):
|
|
try:
|
|
api.fwaas.policy_create(request, **context)
|
|
return True
|
|
except Exception as e:
|
|
msg = self.format_status_message(self.failure_message) + str(e)
|
|
exceptions.handle(request, msg)
|
|
return False
|
|
|
|
|
|
class AddFirewallAction(workflows.Action):
|
|
name = forms.CharField(max_length=80,
|
|
label=_("Name"),
|
|
required=False)
|
|
description = forms.CharField(max_length=80,
|
|
label=_("Description"),
|
|
required=False)
|
|
firewall_policy_id = forms.ChoiceField(label=_("Policy"),
|
|
required=True)
|
|
shared = forms.BooleanField(label=_("Shared"),
|
|
initial=False,
|
|
required=False)
|
|
admin_state_up = forms.BooleanField(label=_("Admin State"),
|
|
initial=True,
|
|
required=False)
|
|
|
|
def __init__(self, request, *args, **kwargs):
|
|
super(AddFirewallAction, self).__init__(request, *args, **kwargs)
|
|
|
|
firewall_policy_id_choices = [('', _("Select a Policy"))]
|
|
try:
|
|
tenant_id = self.request.user.tenant_id
|
|
policies = api.fwaas.policy_list(request, tenant_id=tenant_id)
|
|
policies = sorted(policies, key=lambda policy: policy.name)
|
|
except Exception as e:
|
|
exceptions.handle(
|
|
request,
|
|
_('Unable to retrieve policy list (%(error)s).') % {
|
|
'error': str(e)})
|
|
policies = []
|
|
for p in policies:
|
|
p.set_id_as_name_if_empty()
|
|
firewall_policy_id_choices.append((p.id, p.name))
|
|
self.fields['firewall_policy_id'].choices = firewall_policy_id_choices
|
|
# only admin can set 'shared' attribute to True
|
|
if not request.user.is_superuser:
|
|
self.fields['shared'].widget.attrs['disabled'] = 'disabled'
|
|
|
|
class Meta:
|
|
name = _("AddFirewall")
|
|
permissions = ('openstack.services.network',)
|
|
help_text = _("Create a firewall based on a policy.\n\n"
|
|
"A policy must be selected. "
|
|
"Other fields are optional.")
|
|
|
|
|
|
class AddFirewallStep(workflows.Step):
|
|
action_class = AddFirewallAction
|
|
contributes = ("name", "firewall_policy_id", "description",
|
|
"shared", "admin_state_up")
|
|
|
|
def contribute(self, data, context):
|
|
context = super(AddFirewallStep, self).contribute(data, context)
|
|
return context
|
|
|
|
|
|
class AddFirewall(workflows.Workflow):
|
|
slug = "addfirewall"
|
|
name = _("Add Firewall")
|
|
finalize_button_name = _("Add")
|
|
success_message = _('Added Firewall "%s".')
|
|
failure_message = _('Unable to add Firewall "%s".')
|
|
success_url = "horizon:project:firewalls:index"
|
|
# fwaas is designed to support a wide range of vendor
|
|
# firewalls. Considering the multitude of vendor firewall
|
|
# features in place today, firewall definition can
|
|
# involve more complex configuration over time. Hence,
|
|
# a workflow instead of a single form is used for
|
|
# firewall_rule add to be ready for future extension.
|
|
default_steps = (AddFirewallStep,)
|
|
|
|
def format_status_message(self, message):
|
|
return message % self.context.get('name')
|
|
|
|
def handle(self, request, context):
|
|
try:
|
|
api.fwaas.firewall_create(request, **context)
|
|
return True
|
|
except Exception as e:
|
|
msg = self.format_status_message(self.failure_message) + str(e)
|
|
exceptions.handle(request, msg)
|
|
return False
|