Source code for openstack_dashboard.dashboards.project.firewalls.workflows

# 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


[docs]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.")
[docs]class AddRuleStep(workflows.Step): action_class = AddRuleAction contributes = ("name", "description", "protocol", "action", "source_ip_address", "source_port", "destination_ip_address", "destination_port", "enabled", "shared")
[docs] 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
[docs]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,)
[docs] def format_status_message(self, message): return message % self.context.get('name')
[docs] 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
[docs]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.")
[docs] 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
[docs]class SelectRulesStep(workflows.Step): action_class = SelectRulesAction template_name = "project/firewalls/_update_rules.html" contributes = ("firewall_rules",)
[docs] 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
[docs]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.")
[docs]class AddPolicyStep(workflows.Step): action_class = AddPolicyAction contributes = ("name", "description", "shared", "audited")
[docs] def contribute(self, data, context): context = super(AddPolicyStep, self).contribute(data, context) if data: return context
[docs]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)
[docs] def format_status_message(self, message): return message % self.context.get('name')
[docs] 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
[docs]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.")
[docs]class AddFirewallStep(workflows.Step): action_class = AddFirewallAction contributes = ("name", "firewall_policy_id", "description", "shared", "admin_state_up")
[docs] def contribute(self, data, context): context = super(AddFirewallStep, self).contribute(data, context) return context
[docs]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,)
[docs] def format_status_message(self, message): return message % self.context.get('name')
[docs] 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