FWaaS Horizon panel
Implements: blueprint fwaas-horizon Change-Id: I1017573887922b4dea0a42d46965de2b86325b0e
This commit is contained in:
parent
46462b122e
commit
1255766344
155
horizon/static/horizon/js/horizon.firewalls.js
Normal file
155
horizon/static/horizon/js/horizon.firewalls.js
Normal file
@ -0,0 +1,155 @@
|
||||
horizon.firewalls = {
|
||||
user_decided_length: false,
|
||||
rules_selected: [],
|
||||
rules_available: [],
|
||||
|
||||
getConsoleLog: function(via_user_submit) {
|
||||
var form_element = $("#tail_length"),
|
||||
data;
|
||||
|
||||
if (!via_user_submit) {
|
||||
via_user_submit = false;
|
||||
}
|
||||
|
||||
if(this.user_decided_length) {
|
||||
data = $(form_element).serialize();
|
||||
} else {
|
||||
data = "length=35";
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: $(form_element).attr('action'),
|
||||
data: data,
|
||||
method: 'get',
|
||||
success: function(response_body) {
|
||||
$('pre.logs').text(response_body);
|
||||
},
|
||||
error: function(response) {
|
||||
if(via_user_submit) {
|
||||
horizon.clearErrorMessages();
|
||||
horizon.alert('error', gettext('There was a problem communicating with the server, please try again.'));
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Gets the html select element associated with a given
|
||||
* rule id for rule_id.
|
||||
**/
|
||||
get_rule_element: function(rule_id) {
|
||||
return $('li > label[for^="id_rule_' + rule_id + '"]');
|
||||
},
|
||||
|
||||
/*
|
||||
* Initializes an associative array of lists of the current
|
||||
* rules.
|
||||
**/
|
||||
init_rule_list: function() {
|
||||
horizon.firewalls.rules_selected = [];
|
||||
horizon.firewalls.rules_available = [];
|
||||
$(this.get_rule_element("")).each(function(){
|
||||
var $this = $(this);
|
||||
var $input = $this.children("input");
|
||||
var rule_property = {
|
||||
name:$this.text().replace(/^\s+/,""),
|
||||
id:$input.attr("id"),
|
||||
value:$input.attr("value")
|
||||
};
|
||||
if($input.is(':checked')) {
|
||||
horizon.firewalls.rules_selected.push(rule_property);
|
||||
} else {
|
||||
horizon.firewalls.rules_available.push(rule_property);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Generates the HTML structure for a rule that will be displayed
|
||||
* as a list item in the rule list.
|
||||
**/
|
||||
generate_rule_element: function(name, id, value) {
|
||||
var $li = $('<li>');
|
||||
$li.attr('name', value).html(name + '<em class="rule_id">(' + value + ')</em><a href="#" class="btn btn-primary"></a>');
|
||||
return $li;
|
||||
},
|
||||
|
||||
/*
|
||||
* Generates the HTML structure for the Rule List.
|
||||
**/
|
||||
generate_rulelist_html: function() {
|
||||
var self = this;
|
||||
var updateForm = function() {
|
||||
var lists = $("#ruleListId div.input li").attr('data-index',100);
|
||||
var active_rules = $("#selected_rule > li").map(function(){
|
||||
return $(this).attr("name");
|
||||
});
|
||||
$("#ruleListId div.input input:checkbox").removeAttr('checked');
|
||||
active_rules.each(function(index, value){
|
||||
$("#ruleListId div.input input:checkbox[value=" + value + "]")
|
||||
.attr('checked','checked')
|
||||
.parents("li").attr('data-index',index);
|
||||
});
|
||||
$("#ruleListId div.input ul").html(
|
||||
lists.sort(function(a,b){
|
||||
if( $(a).data("index") < $(b).data("index")) return -1;
|
||||
if( $(a).data("index") > $(b).data("index")) return 1;
|
||||
return 0;
|
||||
})
|
||||
);
|
||||
};
|
||||
$("#ruleListSortContainer").show();
|
||||
$("#ruleListIdContainer").hide();
|
||||
self.init_rule_list();
|
||||
// Make sure we don't duplicate the rules in the list
|
||||
$("#available_rule").empty();
|
||||
$.each(self.rules_available, function(index, value){
|
||||
$("#available_rule").append(self.generate_rule_element(value.name, value.id, value.value));
|
||||
});
|
||||
// Make sure we don't duplicate the rules in the list
|
||||
$("#selected_rule").empty();
|
||||
$.each(self.rules_selected, function(index, value){
|
||||
$("#selected_rule").append(self.generate_rule_element(value.name, value.id, value.value));
|
||||
});
|
||||
$(".rulelist > li > a.btn").click(function(e){
|
||||
var $this = $(this);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if($this.parents("ul#available_rule").length > 0) {
|
||||
$this.parent().appendTo($("#selected_rule"));
|
||||
} else if ($this.parents("ul#selected_rule").length > 0) {
|
||||
$this.parent().appendTo($("#available_rule"));
|
||||
}
|
||||
updateForm();
|
||||
});
|
||||
if ($("#ruleListId > div.control-group.error").length > 0) {
|
||||
var errortext = $("#ruleListId > div.control-group.error").find("span.help-inline").text();
|
||||
$("#selected_rule_h4").before($('<div class="dynamic-error">').html(errortext));
|
||||
}
|
||||
$(".rulelist").sortable({
|
||||
connectWith: "ul.rulelist",
|
||||
placeholder: "ui-state-highlight",
|
||||
distance: 5,
|
||||
start:function(e,info){
|
||||
$("#selected_rule").addClass("dragging");
|
||||
},
|
||||
stop:function(e,info){
|
||||
$("#selected_rule").removeClass("dragging");
|
||||
updateForm();
|
||||
}
|
||||
}).disableSelection();
|
||||
},
|
||||
|
||||
workflow_init: function(modal) {
|
||||
// Initialise the drag and drop rule list
|
||||
horizon.firewalls.generate_rulelist_html();
|
||||
}
|
||||
};
|
||||
|
||||
horizon.addInitFunction(function () {
|
||||
$(document).on('submit', '#tail_length', function (evt) {
|
||||
horizon.firewalls.user_decided_length = true;
|
||||
horizon.firewalls.getConsoleLog(true);
|
||||
evt.preventDefault();
|
||||
});
|
||||
});
|
@ -41,7 +41,7 @@
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.heattop.js' type='text/javascript' charset='utf-8'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/lib/rickshaw.js' type='text/javascript' charset='utf-8'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.d3linechart.js' type='text/javascript' charset='utf-8'></script>
|
||||
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.firewalls.js' type='text/javascript' charset='utf-8'></script>
|
||||
{% block custom_js_files %}{% endblock %}
|
||||
{% endcompress %}
|
||||
|
||||
|
@ -36,3 +36,16 @@ def password_validator():
|
||||
|
||||
def password_validator_msg():
|
||||
return conf.HORIZON_CONFIG["password_validator"]["help_text"]
|
||||
|
||||
|
||||
def validate_port_or_colon_separated_port_range(port_range):
|
||||
"""accepts a port number or a single-colon separated range"""
|
||||
if port_range.count(':') > 1:
|
||||
raise ValidationError("One colon allowed in port range")
|
||||
ports = port_range.split(':')
|
||||
for port in ports:
|
||||
try:
|
||||
if int(port) not in range(-1, 65536):
|
||||
raise ValidationError("Not a valid port number")
|
||||
except ValueError:
|
||||
raise ValidationError("Port number must be integer")
|
||||
|
@ -36,6 +36,7 @@ Keystone/Nova/Glance/Swift et. al.
|
||||
from openstack_dashboard.api import base
|
||||
from openstack_dashboard.api import ceilometer
|
||||
from openstack_dashboard.api import cinder
|
||||
from openstack_dashboard.api import fwaas
|
||||
from openstack_dashboard.api import glance
|
||||
from openstack_dashboard.api import heat
|
||||
from openstack_dashboard.api import keystone
|
||||
@ -49,13 +50,14 @@ from openstack_dashboard.api import vpn
|
||||
|
||||
assert base
|
||||
assert cinder
|
||||
assert heat
|
||||
assert fwaas
|
||||
assert glance
|
||||
assert heat
|
||||
assert keystone
|
||||
assert network
|
||||
assert nova
|
||||
assert neutron
|
||||
assert lbaas
|
||||
assert network
|
||||
assert neutron
|
||||
assert nova
|
||||
assert swift
|
||||
assert ceilometer
|
||||
assert trove
|
||||
|
184
openstack_dashboard/api/fwaas.py
Normal file
184
openstack_dashboard/api/fwaas.py
Normal file
@ -0,0 +1,184 @@
|
||||
# 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.
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from openstack_dashboard.api import neutron
|
||||
|
||||
neutronclient = neutron.neutronclient
|
||||
|
||||
|
||||
class Rule(neutron.NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron firewall rule"""
|
||||
|
||||
def get_dict(self):
|
||||
rule_dict = self._apidict
|
||||
rule_dict['rule_id'] = rule_dict['id']
|
||||
return rule_dict
|
||||
|
||||
|
||||
class Policy(neutron.NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron firewall policy"""
|
||||
|
||||
def get_dict(self):
|
||||
policy_dict = self._apidict
|
||||
policy_dict['policy_id'] = policy_dict['id']
|
||||
return policy_dict
|
||||
|
||||
|
||||
class Firewall(neutron.NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron firewall"""
|
||||
|
||||
def get_dict(self):
|
||||
firewall_dict = self._apidict
|
||||
firewall_dict['firewall_id'] = firewall_dict['id']
|
||||
return firewall_dict
|
||||
|
||||
|
||||
def rule_create(request, **kwargs):
|
||||
"""Create a firewall rule
|
||||
|
||||
:param request: request context
|
||||
:param name: name for rule
|
||||
:param description: description for rule
|
||||
:param protocol: protocol for rule
|
||||
:param action: action for rule
|
||||
:param source_ip_address: source IP address or subnet
|
||||
:param source_port: integer in [1, 65535] or range in a:b
|
||||
:param destination_ip_address: destination IP address or subnet
|
||||
:param destination_port: integer in [1, 65535] or range in a:b
|
||||
:param shared: boolean (default false)
|
||||
:param enabled: boolean (default true)
|
||||
:return: Rule object
|
||||
"""
|
||||
body = {'firewall_rule': kwargs}
|
||||
rule = neutronclient(request).create_firewall_rule(
|
||||
body).get('firewall_rule')
|
||||
return Rule(rule)
|
||||
|
||||
|
||||
def rules_list(request, **kwargs):
|
||||
rules = neutronclient(request).list_firewall_rules(
|
||||
**kwargs).get('firewall_rules')
|
||||
return [Rule(r) for r in rules]
|
||||
|
||||
|
||||
def rule_get(request, rule_id):
|
||||
rule = neutronclient(request).show_firewall_rule(
|
||||
rule_id).get('firewall_rule')
|
||||
return Rule(rule)
|
||||
|
||||
|
||||
def rule_delete(request, rule_id):
|
||||
neutronclient(request).delete_firewall_rule(rule_id)
|
||||
|
||||
|
||||
def rule_update(request, rule_id, **kwargs):
|
||||
body = {'firewall_rule': kwargs}
|
||||
rule = neutronclient(request).update_firewall_rule(
|
||||
rule_id, body).get('firewall_rule')
|
||||
return Rule(rule)
|
||||
|
||||
|
||||
def policy_create(request, **kwargs):
|
||||
"""Create a firewall policy
|
||||
|
||||
:param request: request context
|
||||
:param name: name for policy
|
||||
:param description: description for policy
|
||||
:param firewall_rules: ordered list of rules in policy
|
||||
:param shared: boolean (default false)
|
||||
:param audited: boolean (default false)
|
||||
:return: Policy object
|
||||
"""
|
||||
body = {'firewall_policy': kwargs}
|
||||
policy = neutronclient(request).create_firewall_policy(
|
||||
body).get('firewall_policy')
|
||||
return Policy(policy)
|
||||
|
||||
|
||||
def policies_list(request, **kwargs):
|
||||
policies = neutronclient(request).list_firewall_policies(
|
||||
**kwargs).get('firewall_policies')
|
||||
return [Policy(p) for p in policies]
|
||||
|
||||
|
||||
def policy_get(request, policy_id):
|
||||
policy = neutronclient(request).show_firewall_policy(
|
||||
policy_id).get('firewall_policy')
|
||||
return Policy(policy)
|
||||
|
||||
|
||||
def policy_delete(request, policy_id):
|
||||
neutronclient(request).delete_firewall_policy(policy_id)
|
||||
|
||||
|
||||
def policy_update(request, policy_id, **kwargs):
|
||||
body = {'firewall_policy': kwargs}
|
||||
policy = neutronclient(request).update_firewall_policy(
|
||||
policy_id, body).get('firewall_policy')
|
||||
return Policy(policy)
|
||||
|
||||
|
||||
def policy_insert_rule(request, policy_id, **kwargs):
|
||||
policy = neutronclient(request).firewall_policy_insert_rule(
|
||||
policy_id, kwargs)
|
||||
return Policy(policy)
|
||||
|
||||
|
||||
def policy_remove_rule(request, policy_id, **kwargs):
|
||||
policy = neutronclient(request).firewall_policy_remove_rule(
|
||||
policy_id, kwargs)
|
||||
return Policy(policy)
|
||||
|
||||
|
||||
def firewall_create(request, **kwargs):
|
||||
"""Create a firewall for specified policy
|
||||
|
||||
:param request: request context
|
||||
:param name: name for firewall
|
||||
:param description: description for firewall
|
||||
:param firewall_policy_id: policy id used by firewall
|
||||
:param shared: boolean (default false)
|
||||
:param admin_state_up: boolean (default true)
|
||||
:return: Firewall object
|
||||
"""
|
||||
body = {'firewall': kwargs}
|
||||
firewall = neutronclient(request).create_firewall(body).get('firewall')
|
||||
return Firewall(firewall)
|
||||
|
||||
|
||||
def firewalls_list(request, **kwargs):
|
||||
firewalls = neutronclient(request).list_firewalls(
|
||||
**kwargs).get('firewalls')
|
||||
return [Firewall(f) for f in firewalls]
|
||||
|
||||
|
||||
def firewall_get(request, firewall_id):
|
||||
firewall = neutronclient(request).show_firewall(
|
||||
firewall_id).get('firewall')
|
||||
return Firewall(firewall)
|
||||
|
||||
|
||||
def firewall_delete(request, firewall_id):
|
||||
neutronclient(request).delete_firewall(firewall_id)
|
||||
|
||||
|
||||
def firewall_update(request, firewall_id, **kwargs):
|
||||
body = {'firewall': kwargs}
|
||||
firewall = neutronclient(request).update_firewall(
|
||||
firewall_id, body).get('firewall')
|
||||
return Firewall(firewall)
|
@ -35,6 +35,7 @@ class NetworkPanels(horizon.PanelGroup):
|
||||
panels = ('networks',
|
||||
'routers',
|
||||
'loadbalancers',
|
||||
'firewalls',
|
||||
'network_topology',
|
||||
'vpn',)
|
||||
|
||||
|
304
openstack_dashboard/dashboards/project/firewalls/forms.py
Normal file
304
openstack_dashboard/dashboards/project/firewalls/forms.py
Normal file
@ -0,0 +1,304 @@
|
||||
# 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
|
||||
|
||||
import logging
|
||||
|
||||
from django.core.urlresolvers import reverse # noqa
|
||||
from django.utils.translation import ugettext_lazy as _ # noqa
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import messages
|
||||
from horizon.utils import fields
|
||||
from horizon.utils import validators
|
||||
|
||||
from openstack_dashboard import api
|
||||
|
||||
port_validator = validators.validate_port_or_colon_separated_port_range
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UpdateRule(forms.SelfHandlingForm):
|
||||
name = forms.CharField(max_length=80, label=_("Name"), required=False)
|
||||
description = forms.CharField(
|
||||
required=False,
|
||||
max_length=80, label=_("Description"))
|
||||
protocol = forms.ChoiceField(
|
||||
label=_("Protocol"), required=False,
|
||||
help_text=_('Protocol for the firewall rule'))
|
||||
action = forms.ChoiceField(
|
||||
label=_("Action"), required=False,
|
||||
help_text=_('Action for the firewall rule'))
|
||||
source_ip_address = fields.IPField(
|
||||
label=_("Source IP Address/Subnet"),
|
||||
version=fields.IPv4 | fields.IPv6,
|
||||
required=False, mask=True,
|
||||
help_text=_('Source IP address or subnet'))
|
||||
destination_ip_address = fields.IPField(
|
||||
label=_('Destination IP Address/Subnet'),
|
||||
version=fields.IPv4 | fields.IPv6,
|
||||
required=False, mask=True,
|
||||
help_text=_('Destination IP address or subnet'))
|
||||
source_port = forms.CharField(
|
||||
max_length=80,
|
||||
label=_("Source Port/Port Range"),
|
||||
required=False,
|
||||
validators=[port_validator],
|
||||
help_text=_('Source port (integer in [1, 65535] or range in a:b)'))
|
||||
destination_port = forms.CharField(
|
||||
max_length=80,
|
||||
label=_("Destination Port/Port Range"),
|
||||
required=False,
|
||||
validators=[port_validator],
|
||||
help_text=_('Destination port (integer in [1, 65535] or range'
|
||||
'in a:b)'))
|
||||
shared = forms.BooleanField(label=_("Shared"), required=False)
|
||||
enabled = forms.BooleanField(label=_("Enabled"), required=False)
|
||||
|
||||
failure_url = 'horizon:project:firewalls:index'
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(UpdateRule, self).__init__(request, *args, **kwargs)
|
||||
|
||||
protocol = kwargs['initial']['protocol'].upper()
|
||||
action = kwargs['initial']['action'].upper()
|
||||
|
||||
protocol_choices = [(protocol, protocol)]
|
||||
for tup in [('TCP', _('TCP')), ('UDP', _('UDP')), ('ICMP', _('ICMP'))]:
|
||||
if tup[0] != protocol:
|
||||
protocol_choices.append(tup)
|
||||
self.fields['protocol'].choices = protocol_choices
|
||||
|
||||
action_choices = [(action, action)]
|
||||
for tup in [('ALLOW', _('ALLOW')), ('DENY', _('DENY'))]:
|
||||
if tup[0] != action:
|
||||
action_choices.append(tup)
|
||||
self.fields['action'].choices = action_choices
|
||||
|
||||
def handle(self, request, context):
|
||||
rule_id = self.initial['rule_id']
|
||||
name_or_id = context.get('name') or rule_id
|
||||
for f in ['source_ip_address', 'destination_ip_address',
|
||||
'source_port', 'destination_port']:
|
||||
if not context[f]:
|
||||
context[f] = None
|
||||
try:
|
||||
rule = api.fwaas.rule_update(request, rule_id, **context)
|
||||
msg = _('Rule %s was successfully updated.') % name_or_id
|
||||
LOG.debug(msg)
|
||||
messages.success(request, msg)
|
||||
return rule
|
||||
except Exception as e:
|
||||
msg = _('Failed to update rule %(name)s: %(reason)s' %
|
||||
{'name': name_or_id, 'reason': e})
|
||||
LOG.error(msg)
|
||||
redirect = reverse(self.failure_url)
|
||||
exceptions.handle(request, msg, redirect=redirect)
|
||||
|
||||
|
||||
class UpdatePolicy(forms.SelfHandlingForm):
|
||||
name = forms.CharField(max_length=80, label=_("Name"), required=False)
|
||||
description = forms.CharField(required=False,
|
||||
max_length=80, label=_("Description"))
|
||||
shared = forms.BooleanField(label=_("Shared"), required=False)
|
||||
audited = forms.BooleanField(label=_("Audited"), required=False)
|
||||
|
||||
failure_url = 'horizon:project:firewalls:index'
|
||||
|
||||
def handle(self, request, context):
|
||||
policy_id = self.initial['policy_id']
|
||||
name_or_id = context.get('name') or policy_id
|
||||
try:
|
||||
policy = api.fwaas.policy_update(request, policy_id, **context)
|
||||
msg = _('Policy %s was successfully updated.') % name_or_id
|
||||
LOG.debug(msg)
|
||||
messages.success(request, msg)
|
||||
return policy
|
||||
except Exception as e:
|
||||
msg = _('Failed to update policy %(name)s: %(reason)s' %
|
||||
{'name': name_or_id, 'reason': e})
|
||||
LOG.error(msg)
|
||||
redirect = reverse(self.failure_url)
|
||||
exceptions.handle(request, msg, redirect=redirect)
|
||||
|
||||
|
||||
class UpdateFirewall(forms.SelfHandlingForm):
|
||||
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)
|
||||
admin_state_up = forms.BooleanField(label=_("Admin State Up"),
|
||||
required=False)
|
||||
|
||||
failure_url = 'horizon:project:firewalls:index'
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(UpdateFirewall, self).__init__(request, *args, **kwargs)
|
||||
|
||||
try:
|
||||
tenant_id = self.request.user.tenant_id
|
||||
policies = api.fwaas.policies_list(request, tenant_id=tenant_id)
|
||||
policies = sorted(policies, key=lambda policy: policy.name)
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_('Unable to retrieve policy list.'))
|
||||
policies = []
|
||||
|
||||
policy_id = kwargs['initial']['firewall_policy_id']
|
||||
policy_name = [p.name for p in policies if p.id == policy_id][0]
|
||||
|
||||
firewall_policy_id_choices = [(policy_id, policy_name)]
|
||||
for p in policies:
|
||||
if p.id != policy_id:
|
||||
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
|
||||
|
||||
def handle(self, request, context):
|
||||
firewall_id = self.initial['firewall_id']
|
||||
name_or_id = context.get('name') or firewall_id
|
||||
try:
|
||||
firewall = api.fwaas.firewall_update(request, firewall_id,
|
||||
**context)
|
||||
msg = _('Firewall %s was successfully updated.') % name_or_id
|
||||
LOG.debug(msg)
|
||||
messages.success(request, msg)
|
||||
return firewall
|
||||
except Exception as e:
|
||||
msg = _('Failed to update firewall %(name)s: %(reason)s' %
|
||||
{'name': name_or_id, 'reason': e})
|
||||
LOG.error(msg)
|
||||
redirect = reverse(self.failure_url)
|
||||
exceptions.handle(request, msg, redirect=redirect)
|
||||
|
||||
|
||||
class InsertRuleToPolicy(forms.SelfHandlingForm):
|
||||
firewall_rule_id = forms.ChoiceField(label=_("Insert Rule"))
|
||||
insert_before = forms.ChoiceField(label=_("Before"),
|
||||
required=False)
|
||||
insert_after = forms.ChoiceField(label=_("After"),
|
||||
required=False)
|
||||
|
||||
failure_url = 'horizon:project:firewalls:index'
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(InsertRuleToPolicy, self).__init__(request, *args, **kwargs)
|
||||
|
||||
tenant_id = self.request.user.tenant_id
|
||||
try:
|
||||
all_rules = api.fwaas.rules_list(request, tenant_id=tenant_id)
|
||||
for r in all_rules:
|
||||
r.set_id_as_name_if_empty()
|
||||
all_rules = sorted(all_rules, key=lambda rule: rule.name)
|
||||
|
||||
available_rules = [r for r in all_rules
|
||||
if not r.firewall_policy_id]
|
||||
|
||||
current_rules = []
|
||||
for r in kwargs['initial']['firewall_rules']:
|
||||
r_obj = [rule for rule in all_rules if r == rule.id][0]
|
||||
current_rules.append(r_obj)
|
||||
|
||||
available_choices = [(r.id, r.name) for r in available_rules]
|
||||
current_choices = [(r.id, r.name) for r in current_rules]
|
||||
|
||||
except Exception as e:
|
||||
msg = _('Failed to retrieve available rules: %s') % e
|
||||
LOG.error(msg)
|
||||
redirect = reverse(self.failure_url)
|
||||
exceptions.handle(request, msg, redirect=redirect)
|
||||
|
||||
self.fields['firewall_rule_id'].choices = available_choices
|
||||
self.fields['insert_before'].choices = [('', '')] + current_choices
|
||||
self.fields['insert_after'].choices = [('', '')] + current_choices
|
||||
|
||||
def handle(self, request, context):
|
||||
policy_id = self.initial['policy_id']
|
||||
try:
|
||||
body = {'firewall_rule_id': context['firewall_rule_id'],
|
||||
'insert_before': context['insert_before'],
|
||||
'insert_after': context['insert_after']}
|
||||
policy = api.fwaas.policy_insert_rule(request, policy_id, **body)
|
||||
msg = _('Rule %(rule)s was successfully inserted to policy '
|
||||
'%(policy)s.' %
|
||||
{'rule': context['firewall_rule_id'], 'policy': policy_id})
|
||||
LOG.debug(msg)
|
||||
messages.success(request, msg)
|
||||
return policy
|
||||
except Exception as e:
|
||||
msg = _('Failed to insert rule to policy %(name)s: %(reason)s' %
|
||||
{'name': policy_id, 'reason': e})
|
||||
LOG.error(msg)
|
||||
redirect = reverse(self.failure_url)
|
||||
exceptions.handle(request, msg, redirect=redirect)
|
||||
|
||||
|
||||
class RemoveRuleFromPolicy(forms.SelfHandlingForm):
|
||||
firewall_rule_id = forms.ChoiceField(label=_("Remove Rule"),
|
||||
required=False)
|
||||
|
||||
failure_url = 'horizon:project:firewalls:index'
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(RemoveRuleFromPolicy, self).__init__(request, *args, **kwargs)
|
||||
|
||||
tenant_id = request.user.tenant_id
|
||||
try:
|
||||
all_rules = api.fwaas.rules_list(request, tenant_id=tenant_id)
|
||||
for r in all_rules:
|
||||
r.set_id_as_name_if_empty()
|
||||
|
||||
current_rules = []
|
||||
for r in kwargs['initial']['firewall_rules']:
|
||||
r_obj = [rule for rule in all_rules if r == rule.id][0]
|
||||
current_rules.append(r_obj)
|
||||
|
||||
current_choices = [(r.id, r.name) for r in current_rules]
|
||||
except Exception as e:
|
||||
msg = _('Failed to retrieve current rules in policy %(name)s: '
|
||||
'%(reason)s' %
|
||||
{'name': self.initial['name'], 'reason': e})
|
||||
LOG.error(msg)
|
||||
redirect = reverse(self.failure_url)
|
||||
exceptions.handle(request, msg, redirect=redirect)
|
||||
|
||||
self.fields['firewall_rule_id'].choices = current_choices
|
||||
|
||||
def handle(self, request, context):
|
||||
policy_id = self.initial['policy_id']
|
||||
try:
|
||||
body = {'firewall_rule_id': context['firewall_rule_id'], }
|
||||
policy = api.fwaas.policy_remove_rule(request, policy_id, **body)
|
||||
msg = _('Rule %(rule)s was successfully removed from policy '
|
||||
'%(policy)s.' %
|
||||
{'rule': context['firewall_rule_id'],
|
||||
'policy': self.initial['name']})
|
||||
LOG.debug(msg)
|
||||
messages.success(request, msg)
|
||||
return policy
|
||||
except Exception as e:
|
||||
msg = _('Failed to remove rule from policy %(name)s: %(reason)s' %
|
||||
{'name': self.initial['name'], 'reason': e})
|
||||
LOG.error(msg)
|
||||
redirect = reverse(self.failure_url)
|
||||
exceptions.handle(request, msg, redirect=redirect)
|
18
openstack_dashboard/dashboards/project/firewalls/panel.py
Normal file
18
openstack_dashboard/dashboards/project/firewalls/panel.py
Normal file
@ -0,0 +1,18 @@
|
||||
from django.conf import settings # noqa
|
||||
from django.utils.translation import ugettext_lazy as _ # noqa
|
||||
|
||||
import horizon
|
||||
|
||||
from openstack_dashboard.dashboards.project import dashboard
|
||||
|
||||
|
||||
class Firewall(horizon.Panel):
|
||||
name = _("Firewalls")
|
||||
slug = "firewalls"
|
||||
permissions = ('openstack.services.network',)
|
||||
|
||||
|
||||
if getattr(settings,
|
||||
'OPENSTACK_NEUTRON_NETWORK',
|
||||
{}).get('enable_firewall', False):
|
||||
dashboard.Project.register(Firewall)
|
187
openstack_dashboard/dashboards/project/firewalls/tables.py
Normal file
187
openstack_dashboard/dashboards/project/firewalls/tables.py
Normal file
@ -0,0 +1,187 @@
|
||||
# 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
|
||||
|
||||
import logging
|
||||
|
||||
from django.core.urlresolvers import reverse # noqa
|
||||
from django.utils.translation import ugettext as _ # noqa
|
||||
|
||||
from horizon import tables
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AddRuleLink(tables.LinkAction):
|
||||
name = "addrule"
|
||||
verbose_name = _("Add Rule")
|
||||
url = "horizon:project:firewalls:addrule"
|
||||
classes = ("ajax-modal", "btn-create",)
|
||||
|
||||
|
||||
class AddPolicyLink(tables.LinkAction):
|
||||
name = "addpolicy"
|
||||
verbose_name = _("Add Policy")
|
||||
url = "horizon:project:firewalls:addpolicy"
|
||||
classes = ("ajax-modal", "btn-addpolicy",)
|
||||
|
||||
|
||||
class AddFirewallLink(tables.LinkAction):
|
||||
name = "addfirewall"
|
||||
verbose_name = _("Create Firewall")
|
||||
url = "horizon:project:firewalls:addfirewall"
|
||||
classes = ("ajax-modal", "btn-addfirewall",)
|
||||
|
||||
|
||||
class DeleteRuleLink(tables.DeleteAction):
|
||||
name = "deleterule"
|
||||
action_present = _("Delete")
|
||||
action_past = _("Scheduled deletion of")
|
||||
data_type_singular = _("Rule")
|
||||
data_type_plural = _("Rules")
|
||||
|
||||
|
||||
class DeletePolicyLink(tables.DeleteAction):
|
||||
name = "deletepolicy"
|
||||
action_present = _("Delete")
|
||||
action_past = _("Scheduled deletion of")
|
||||
data_type_singular = _("Policy")
|
||||
data_type_plural = _("Policies")
|
||||
|
||||
|
||||
class DeleteFirewallLink(tables.DeleteAction):
|
||||
name = "deletefirewall"
|
||||
action_present = _("Delete")
|
||||
action_past = _("Scheduled deletion of")
|
||||
data_type_singular = _("Firewall")
|
||||
data_type_plural = _("Firewalls")
|
||||
|
||||
|
||||
class UpdateRuleLink(tables.LinkAction):
|
||||
name = "updaterule"
|
||||
verbose_name = _("Edit Rule")
|
||||
classes = ("ajax-modal", "btn-update",)
|
||||
|
||||
def get_link_url(self, rule):
|
||||
base_url = reverse("horizon:project:firewalls:updaterule",
|
||||
kwargs={'rule_id': rule.id})
|
||||
return base_url
|
||||
|
||||
|
||||
class UpdatePolicyLink(tables.LinkAction):
|
||||
name = "updatepolicy"
|
||||
verbose_name = _("Edit Policy")
|
||||
classes = ("ajax-modal", "btn-update",)
|
||||
|
||||
def get_link_url(self, policy):
|
||||
base_url = reverse("horizon:project:firewalls:updatepolicy",
|
||||
kwargs={'policy_id': policy.id})
|
||||
return base_url
|
||||
|
||||
|
||||
class UpdateFirewallLink(tables.LinkAction):
|
||||
name = "updatefirewall"
|
||||
verbose_name = _("Edit Firewall")
|
||||
classes = ("ajax-modal", "btn-update",)
|
||||
|
||||
def get_link_url(self, firewall):
|
||||
base_url = reverse("horizon:project:firewalls:updatefirewall",
|
||||
kwargs={'firewall_id': firewall.id})
|
||||
return base_url
|
||||
|
||||
|
||||
class InsertRuleToPolicyLink(tables.LinkAction):
|
||||
name = "insertrule"
|
||||
verbose_name = _("Insert Rule")
|
||||
classes = ("ajax-modal", "btn-update",)
|
||||
|
||||
def get_link_url(self, policy):
|
||||
base_url = reverse("horizon:project:firewalls:insertrule",
|
||||
kwargs={'policy_id': policy.id})
|
||||
return base_url
|
||||
|
||||
|
||||
class RemoveRuleFromPolicyLink(tables.LinkAction):
|
||||
name = "removerule"
|
||||
verbose_name = _("Remove Rule")
|
||||
classes = ("ajax-modal", "btn-update",)
|
||||
|
||||
def get_link_url(self, policy):
|
||||
base_url = reverse("horizon:project:firewalls:removerule",
|
||||
kwargs={'policy_id': policy.id})
|
||||
return base_url
|
||||
|
||||
|
||||
class RulesTable(tables.DataTable):
|
||||
name = tables.Column("name",
|
||||
verbose_name=_("Name"),
|
||||
link="horizon:project:firewalls:ruledetails")
|
||||
protocol = tables.Column("protocol",
|
||||
verbose_name=_("Protocol"))
|
||||
source_ip_address = tables.Column("source_ip_address",
|
||||
verbose_name=_("Source IP"))
|
||||
source_port = tables.Column("source_port",
|
||||
verbose_name=_("Source Port"))
|
||||
destination_ip_address = tables.Column("destination_ip_address",
|
||||
verbose_name=_("Destination IP"))
|
||||
destination_port = tables.Column("destination_port",
|
||||
verbose_name=_("Destination Port"))
|
||||
action = tables.Column("action",
|
||||
verbose_name=_("Action"))
|
||||
enabled = tables.Column("enabled",
|
||||
verbose_name=_("Enabled"))
|
||||
firewall_policy_id = tables.Column("firewall_policy_id",
|
||||
verbose_name=_("In Policy"))
|
||||
|
||||
class Meta:
|
||||
name = "rulestable"
|
||||
verbose_name = _("Rules")
|
||||
table_actions = (AddRuleLink, DeleteRuleLink)
|
||||
row_actions = (UpdateRuleLink, DeleteRuleLink)
|
||||
|
||||
|
||||
class PoliciesTable(tables.DataTable):
|
||||
name = tables.Column("name",
|
||||
verbose_name=_("Name"),
|
||||
link="horizon:project:firewalls:policydetails")
|
||||
firewall_rules = tables.Column("firewall_rules",
|
||||
verbose_name=_("Rules"))
|
||||
audited = tables.Column("audited",
|
||||
verbose_name=_("Audited"))
|
||||
|
||||
class Meta:
|
||||
name = "policiestable"
|
||||
verbose_name = _("Policies")
|
||||
table_actions = (AddPolicyLink, DeletePolicyLink)
|
||||
row_actions = (UpdatePolicyLink, InsertRuleToPolicyLink,
|
||||
RemoveRuleFromPolicyLink, DeletePolicyLink)
|
||||
|
||||
|
||||
class FirewallsTable(tables.DataTable):
|
||||
name = tables.Column("name",
|
||||
verbose_name=_("Name"),
|
||||
link="horizon:project:firewalls:firewalldetails")
|
||||
firewall_policy_id = tables.Column("firewall_policy_id",
|
||||
verbose_name=_("Policy"))
|
||||
status = tables.Column("status",
|
||||
verbose_name=_("Status"))
|
||||
|
||||
class Meta:
|
||||
name = "firewallstable"
|
||||
verbose_name = _("Firewalls")
|
||||
table_actions = (AddFirewallLink, DeleteFirewallLink)
|
||||
row_actions = (UpdateFirewallLink, DeleteFirewallLink)
|
161
openstack_dashboard/dashboards/project/firewalls/tabs.py
Normal file
161
openstack_dashboard/dashboards/project/firewalls/tabs.py
Normal file
@ -0,0 +1,161 @@
|
||||
# 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 as _ # noqa
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tabs
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.project.firewalls import tables
|
||||
|
||||
FirewallsTable = tables.FirewallsTable
|
||||
PoliciesTable = tables.PoliciesTable
|
||||
RulesTable = tables.RulesTable
|
||||
|
||||
|
||||
class RulesTab(tabs.TableTab):
|
||||
table_classes = (RulesTable,)
|
||||
name = _("Firewall Rules")
|
||||
slug = "rules"
|
||||
template_name = "horizon/common/_detail_table.html"
|
||||
|
||||
def get_rulestable_data(self):
|
||||
try:
|
||||
tenant_id = self.request.user.tenant_id
|
||||
rules = api.fwaas.rules_list(self.tab_group.request,
|
||||
tenant_id=tenant_id)
|
||||
except Exception:
|
||||
rules = []
|
||||
exceptions.handle(self.tab_group.request,
|
||||
_('Unable to retrieve rules list.'))
|
||||
for r in rules:
|
||||
r.set_id_as_name_if_empty()
|
||||
|
||||
return rules
|
||||
|
||||
|
||||
class PoliciesTab(tabs.TableTab):
|
||||
table_classes = (PoliciesTable,)
|
||||
name = _("Firewall Policies")
|
||||
slug = "policies"
|
||||
template_name = "horizon/common/_detail_table.html"
|
||||
|
||||
def get_policiestable_data(self):
|
||||
try:
|
||||
tenant_id = self.request.user.tenant_id
|
||||
policies = api.fwaas.policies_list(self.tab_group.request,
|
||||
tenant_id=tenant_id)
|
||||
except Exception:
|
||||
policies = []
|
||||
exceptions.handle(self.tab_group.request,
|
||||
_('Unable to retrieve policies list.'))
|
||||
for p in policies:
|
||||
p.set_id_as_name_if_empty()
|
||||
|
||||
return policies
|
||||
|
||||
|
||||
class FirewallsTab(tabs.TableTab):
|
||||
table_classes = (FirewallsTable,)
|
||||
name = _("Firewalls")
|
||||
slug = "firewalls"
|
||||
template_name = "horizon/common/_detail_table.html"
|
||||
|
||||
def get_firewallstable_data(self):
|
||||
try:
|
||||
tenant_id = self.request.user.tenant_id
|
||||
firewalls = api.fwaas.firewalls_list(self.tab_group.request,
|
||||
tenant_id=tenant_id)
|
||||
except Exception:
|
||||
firewalls = []
|
||||
exceptions.handle(self.tab_group.request,
|
||||
_('Unable to retrieve firewall list.'))
|
||||
|
||||
for f in firewalls:
|
||||
f.set_id_as_name_if_empty()
|
||||
|
||||
return firewalls
|
||||
|
||||
|
||||
class RuleDetailsTab(tabs.Tab):
|
||||
name = _("Firewall Rule Details")
|
||||
slug = "ruledetails"
|
||||
template_name = "project/firewalls/_rule_details.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
rid = self.tab_group.kwargs['rule_id']
|
||||
try:
|
||||
rule = api.fwaas.rule_get(request, rid)
|
||||
except Exception:
|
||||
rule = []
|
||||
exceptions.handle(request,
|
||||
_('Unable to retrieve rule details.'))
|
||||
return {'rule': rule}
|
||||
|
||||
|
||||
class PolicyDetailsTab(tabs.Tab):
|
||||
name = _("Firewall Policy Details")
|
||||
slug = "policydetails"
|
||||
template_name = "project/firewalls/_policy_details.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
pid = self.tab_group.kwargs['policy_id']
|
||||
try:
|
||||
policy = api.fwaas.policy_get(request, pid)
|
||||
except Exception:
|
||||
policy = []
|
||||
exceptions.handle(request,
|
||||
_('Unable to retrieve policy details.'))
|
||||
return {'policy': policy}
|
||||
|
||||
|
||||
class FirewallDetailsTab(tabs.Tab):
|
||||
name = _("Firewall Details")
|
||||
slug = "firewalldetails"
|
||||
template_name = "project/firewalls/_firewall_details.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
fid = self.tab_group.kwargs['firewall_id']
|
||||
try:
|
||||
firewall = api.fwaas.firewall_get(request, fid)
|
||||
except Exception:
|
||||
firewall = []
|
||||
exceptions.handle(self.tab_group.request,
|
||||
_('Unable to retrieve firewall details.'))
|
||||
return {'firewall': firewall}
|
||||
|
||||
|
||||
class FirewallTabs(tabs.TabGroup):
|
||||
slug = "fwtabs"
|
||||
tabs = (FirewallsTab, PoliciesTab, RulesTab)
|
||||
sticky = True
|
||||
|
||||
|
||||
class RuleDetailsTabs(tabs.TabGroup):
|
||||
slug = "ruletabs"
|
||||
tabs = (RuleDetailsTab,)
|
||||
|
||||
|
||||
class PolicyDetailsTabs(tabs.TabGroup):
|
||||
slug = "policytabs"
|
||||
tabs = (PolicyDetailsTab,)
|
||||
|
||||
|
||||
class FirewallDetailsTabs(tabs.TabGroup):
|
||||
slug = "firewalltabs"
|
||||
tabs = (FirewallDetailsTab,)
|
@ -0,0 +1,31 @@
|
||||
{% load i18n sizeformat parse_date %}
|
||||
{% load url from future %}
|
||||
|
||||
<div class="info row-fluid detail">
|
||||
<hr class="header_rule">
|
||||
<dl>
|
||||
<dt>{% trans "Name" %}</dt>
|
||||
<dd>{{ firewall.name|default:_("None") }}</dd>
|
||||
|
||||
<dt>{% trans "Description" %}</dt>
|
||||
<dd>{{ firewall.description|default:_("None") }}</dd>
|
||||
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ firewall.id }} </dd>
|
||||
|
||||
<dt>{% trans "Project ID" %}</dt>
|
||||
<dd>{{ firewall.tenant_id }}</dd>
|
||||
|
||||
<dt>{% trans "Policy ID" %}</dt>
|
||||
<dd>
|
||||
{% url 'horizon:project:firewalls:policydetails' firewall.firewall_policy_id as policy_url%}
|
||||
<a href="{{ policy_url }}">{{ firewall.firewall_policy_id }}</a>
|
||||
</dd>
|
||||
|
||||
<dt>{% trans "Status" %}</dt>
|
||||
<dd>{{ firewall.status }}</dd>
|
||||
|
||||
<dt>{% trans "Admin State Up" %}</dt>
|
||||
<dd>{{ firewall.admin_state_up }}</dd>
|
||||
</dl>
|
||||
</div>
|
@ -0,0 +1,28 @@
|
||||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block form_id %}update_policy_form{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:project:firewalls:insertrule' policy_id %}{% endblock %}
|
||||
|
||||
{% block modal-header %}{% trans "Insert Rule to Policy" %}{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="right">
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% blocktrans %}Choose the rule you want to insert. Specify
|
||||
either the rule you want to insert immediately before, or the rule
|
||||
to insert immediately after. If both are specified, the prior
|
||||
takes precedence.{% endblocktrans %}</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-footer %}
|
||||
<input class="btn btn-primary pull-right" type="submit" value="{% trans "Save Changes" %}" />
|
||||
<a href="{% url 'horizon:project:firewalls:index' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
|
||||
{% endblock %}
|
@ -0,0 +1,27 @@
|
||||
{% load i18n sizeformat parse_date %}
|
||||
|
||||
<div class="info row-fluid detail">
|
||||
<hr class="header_rule">
|
||||
<dl>
|
||||
<dt>{% trans "Name" %}</dt>
|
||||
<dd>{{ policy.name|default:_("None") }}</dd>
|
||||
|
||||
<dt>{% trans "Description" %}</dt>
|
||||
<dd>{{ policy.description|default:_("None") }}</dd>
|
||||
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ policy.id }}</dd>
|
||||
|
||||
<dt>{% trans "Project ID" %}</dt>
|
||||
<dd>{{ policy.tenant_id }}</dd>
|
||||
|
||||
<dt>{% trans "Rules" %}</dt>
|
||||
<dd>{{ policy.firewall_rules }}</dd>
|
||||
|
||||
<dt>{% trans "Shared" %}</dt>
|
||||
<dd>{{ policy.shared }}</dd>
|
||||
|
||||
<dt>{% trans "Audited" %}</dt>
|
||||
<dd>{{ policy.audited }}</dd>
|
||||
</dl>
|
||||
</div>
|
@ -0,0 +1,25 @@
|
||||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block form_id %}update_policy_form{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:project:firewalls:removerule' policy_id %}{% endblock %}
|
||||
|
||||
{% block modal-header %}{% trans "Remove Rule from Policy" %}{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="right">
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Choose the rule you want to remove." %}</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-footer %}
|
||||
<input class="btn btn-primary pull-right" type="submit" value="{% trans "Save Changes" %}" />
|
||||
<a href="{% url 'horizon:project:firewalls:index' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
|
||||
{% endblock %}
|
@ -0,0 +1,52 @@
|
||||
{% load i18n sizeformat parse_date %}
|
||||
{% load url from future %}
|
||||
|
||||
<div class="info row-fluid detail">
|
||||
<hr class="header_rule">
|
||||
<dl>
|
||||
<dt>{% trans "Name" %}</dt>
|
||||
<dd>{{ rule.name|default:_("None") }}</dd>
|
||||
|
||||
<dt>{% trans "Description" %}</dt>
|
||||
<dd>{{ rule.description|default:_("None") }}</dd>
|
||||
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ rule.id }}</dd>
|
||||
|
||||
<dt>{% trans "Project ID" %}</dt>
|
||||
<dd>{{ rule.tenant_id }}</dd>
|
||||
|
||||
<dt>{% trans "Action" %}</dt>
|
||||
<dd>{{ rule.action }}</dd>
|
||||
|
||||
<dt>{% trans "Protocol" %}</dt>
|
||||
<dd>{{ rule.protocol }}</dd>
|
||||
|
||||
<dt>{% trans "Source IP Address" %}</dt>
|
||||
<dd>{{ rule.source_ip_address }}</dd>
|
||||
|
||||
<dt>{% trans "Source Port" %}</dt>
|
||||
<dd>{{ rule.source_port }}</dd>
|
||||
|
||||
<dt>{% trans "Destination IP Address" %}</dt>
|
||||
<dd>{{ rule.destination_ip_address }}</dd>
|
||||
|
||||
<dt>{% trans "Destination Port: "%}</dt>
|
||||
<dd>{{ rule.destination_port }}</dd>
|
||||
|
||||
<dt>{% trans "Used in Policy" %}</dt>
|
||||
<dd>
|
||||
{% url 'horizon:project:firewalls:policydetails' rule.firewall_policy_id as policy_url%}
|
||||
<a href="{{ policy_url }}">{{ rule.firewall_policy_id }}</a>
|
||||
</dd>
|
||||
|
||||
<dt>{% trans "Position in Policy" %}</dt>
|
||||
<dd>{{ rule.position }}</dd>
|
||||
|
||||
<dt>{% trans "Shared" %}</dt>
|
||||
<dd>{{ rule.shared }}</dd>
|
||||
|
||||
<dt>{% trans "Enabled" %}</dt>
|
||||
<dd>{{ rule.enabled }}</dd>
|
||||
</dl>
|
||||
</div>
|
@ -0,0 +1,4 @@
|
||||
{% load i18n horizon %}
|
||||
|
||||
<p>{% blocktrans %}Choose rule(s) from Available Rules to Selected Rule by push button or drag and drop,
|
||||
you may change their order by drag and drop as well. {% endblocktrans %}</p>
|
@ -0,0 +1,45 @@
|
||||
{% load i18n %}
|
||||
|
||||
<noscript><h3>{{ step }}</h3></noscript>
|
||||
<table class="table-fixed" id="ruleListSortContainer">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="actions">
|
||||
<h4 id="selected_rule_h4">{% trans "Selected Rules" %}</h4>
|
||||
<ul id="selected_rule" class="rulelist">
|
||||
</ul>
|
||||
<h4>{% trans "Available Rules" %}</h4>
|
||||
<ul id="available_rule" class="rulelist">
|
||||
</ul>
|
||||
</td>
|
||||
<td class="help_text">
|
||||
{% include "project/firewalls/_update_rule_help.html" %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="table-fixed" id="ruleListIdContainer">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="actions">
|
||||
<div id="ruleListId">
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</div>
|
||||
</td>
|
||||
<td class="help_text">
|
||||
{{ step.get_help_text }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script>
|
||||
if (typeof $ !== 'undefined') {
|
||||
horizon.firewalls.workflow_init($(".workflow"));
|
||||
} else {
|
||||
addHorizonLoadEvent(function() {
|
||||
horizon.firewalls.workflow_init($(".workflow"));
|
||||
});
|
||||
}
|
||||
</script>
|
@ -0,0 +1,25 @@
|
||||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block form_id %}update_firewall_form{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:project:firewalls:updatefirewall' firewall_id %}{% endblock %}
|
||||
|
||||
{% block modal-header %}{% trans "Edit Firewall" %}{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="right">
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "You may update firewall details here." %}</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-footer %}
|
||||
<input class="btn btn-primary pull-right" type="submit" value="{% trans "Save Changes" %}" />
|
||||
<a href="{% url 'horizon:project:firewalls:index' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
|
||||
{% endblock %}
|
@ -0,0 +1,25 @@
|
||||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block form_id %}update_policy_form{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:project:firewalls:updatepolicy' policy_id %}{% endblock %}
|
||||
|
||||
{% block modal-header %}{% trans "Edit Policy" %}{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="right">
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "You may update policy details here. Use 'Insert Rule' or 'Remove Rule' links instead to insert or remove a rule" %}</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-footer %}
|
||||
<input class="btn btn-primary pull-right" type="submit" value="{% trans "Save Changes" %}" />
|
||||
<a href="{% url 'horizon:project:firewalls:index' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
|
||||
{% endblock %}
|
@ -0,0 +1,25 @@
|
||||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block form_id %}update_rule_form{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:project:firewalls:updaterule' rule_id %}{% endblock %}
|
||||
|
||||
{% block modal-header %}{% trans "Edit Rule" %}{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="right">
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "You may update rule details here." %}</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-footer %}
|
||||
<input class="btn btn-primary pull-right" type="submit" value="{% trans "Save Changes" %}" />
|
||||
<a href="{% url 'horizon:project:firewalls:index' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
|
||||
{% endblock %}
|
@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Add New Firewall" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Add New Firewall") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'horizon/common/_workflow.html' %}
|
||||
{% endblock %}
|
@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Add New Policy" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Add New Policy") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'horizon/common/_workflow.html' %}
|
||||
{% endblock %}
|
@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Add New Rule" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Add New Rule") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'horizon/common/_workflow.html' %}
|
||||
{% endblock %}
|
@ -0,0 +1,15 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Firewalls" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Firewalls") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Insert Rule to Policy" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Insert Rule to Policy") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'project/firewalls/_insert_rule_to_policy.html' %}
|
||||
{% endblock %}
|
@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Remove Rule from Policy" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Remove Rule from Policy") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'project/firewalls/_remove_rule_from_policy.html' %}
|
||||
{% endblock %}
|
@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Edit Firewall" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Edit Firewall ")|add:name %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'project/firewalls/_updatefirewall.html' %}
|
||||
{% endblock %}
|
@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Edit Policy" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Edit Policy ")|add:name %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'project/firewalls/_updatepolicy.html' %}
|
||||
{% endblock %}
|
@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Edit Rule" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Edit Rule ")|add:name %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'project/firewalls/_updaterule.html' %}
|
||||
{% endblock %}
|
520
openstack_dashboard/dashboards/project/firewalls/tests.py
Normal file
520
openstack_dashboard/dashboards/project/firewalls/tests.py
Normal file
@ -0,0 +1,520 @@
|
||||
# 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 mox import IsA # noqa
|
||||
|
||||
from django.core.urlresolvers import reverse # noqa
|
||||
from django.core.urlresolvers import reverse_lazy # noqa
|
||||
from django import http
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.api import fwaas
|
||||
from openstack_dashboard.test import helpers as test
|
||||
|
||||
|
||||
class FirewallTests(test.TestCase):
|
||||
class AttributeDict(dict):
|
||||
def __getattr__(self, attr):
|
||||
return self[attr]
|
||||
|
||||
def __setattr__(self, attr, value):
|
||||
self[attr] = value
|
||||
|
||||
DASHBOARD = 'project'
|
||||
INDEX_URL = reverse_lazy('horizon:%s:firewalls:index' % DASHBOARD)
|
||||
|
||||
ADDRULE_PATH = 'horizon:%s:firewalls:addrule' % DASHBOARD
|
||||
ADDPOLICY_PATH = 'horizon:%s:firewalls:addpolicy' % DASHBOARD
|
||||
ADDFIREWALL_PATH = 'horizon:%s:firewalls:addfirewall' % DASHBOARD
|
||||
|
||||
RULE_DETAIL_PATH = 'horizon:%s:firewalls:ruledetails' % DASHBOARD
|
||||
POLICY_DETAIL_PATH = 'horizon:%s:firewalls:policydetails' % DASHBOARD
|
||||
FIREWALL_DETAIL_PATH = 'horizon:%s:firewalls:firewalldetails' % DASHBOARD
|
||||
|
||||
UPDATERULE_PATH = 'horizon:%s:firewalls:updaterule' % DASHBOARD
|
||||
UPDATEPOLICY_PATH = 'horizon:%s:firewalls:updatepolicy' % DASHBOARD
|
||||
UPDATEFIREWALL_PATH = 'horizon:%s:firewalls:updatefirewall' % DASHBOARD
|
||||
|
||||
INSERTRULE_PATH = 'horizon:%s:firewalls:insertrule' % DASHBOARD
|
||||
REMOVERULE_PATH = 'horizon:%s:firewalls:removerule' % DASHBOARD
|
||||
|
||||
def set_up_expect(self):
|
||||
# retrieve rules
|
||||
rule1 = self.fw_rules.first()
|
||||
tenant_id = rule1.tenant_id
|
||||
|
||||
api.fwaas.rules_list(
|
||||
IsA(http.HttpRequest),
|
||||
tenant_id=tenant_id).AndReturn(self.fw_rules.list())
|
||||
|
||||
# retrieves policies
|
||||
policies = self.fw_policies.list()
|
||||
api.fwaas.policies_list(
|
||||
IsA(http.HttpRequest), tenant_id=tenant_id).AndReturn(policies)
|
||||
|
||||
# retrieves firewalls
|
||||
firewalls = self.firewalls.list()
|
||||
api.fwaas.firewalls_list(
|
||||
IsA(http.HttpRequest), tenant_id=tenant_id).AndReturn(firewalls)
|
||||
|
||||
def set_up_expect_with_exception(self):
|
||||
rule1 = self.fw_rules.first()
|
||||
tenant_id = rule1.tenant_id
|
||||
|
||||
api.fwaas.rules_list(
|
||||
IsA(http.HttpRequest),
|
||||
tenant_id=tenant_id).AndRaise(self.exceptions.neutron)
|
||||
api.fwaas.policies_list(
|
||||
IsA(http.HttpRequest),
|
||||
tenant_id=tenant_id).AndRaise(self.exceptions.neutron)
|
||||
api.fwaas.firewalls_list(
|
||||
IsA(http.HttpRequest),
|
||||
tenant_id=tenant_id).AndRaise(self.exceptions.neutron)
|
||||
|
||||
@test.create_stubs({api.fwaas: ('firewalls_list',
|
||||
'policies_list',
|
||||
'rules_list')}, )
|
||||
def test_index_firewalls(self):
|
||||
self.set_up_expect()
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
firewall = self.firewalls.first()
|
||||
tenant_id = firewall.tenant_id
|
||||
|
||||
res = self.client.get(self.INDEX_URL, tenant_id=tenant_id)
|
||||
|
||||
self.assertTemplateUsed(res, '%s/firewalls/details_tabs.html'
|
||||
% self.DASHBOARD)
|
||||
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
|
||||
self.assertEqual(len(res.context['table'].data),
|
||||
len(self.firewalls.list()))
|
||||
|
||||
@test.create_stubs({api.fwaas: ('firewalls_list',
|
||||
'policies_list',
|
||||
'rules_list')}, )
|
||||
def test_index_policies(self):
|
||||
self.set_up_expect()
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
policy = self.fw_policies.first()
|
||||
tenant_id = policy.tenant_id
|
||||
|
||||
res = self.client.get(self.INDEX_URL + '?tab=fwtabs__policies',
|
||||
tenant_id=tenant_id)
|
||||
|
||||
self.assertTemplateUsed(res, '%s/firewalls/details_tabs.html'
|
||||
% self.DASHBOARD)
|
||||
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
|
||||
self.assertEqual(len(res.context['policiestable_table'].data),
|
||||
len(self.fw_policies.list()))
|
||||
|
||||
@test.create_stubs({api.fwaas: ('firewalls_list',
|
||||
'policies_list',
|
||||
'rules_list')}, )
|
||||
def test_index_rules(self):
|
||||
self.set_up_expect()
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
rule = self.fw_rules.first()
|
||||
tenant_id = rule.tenant_id
|
||||
|
||||
res = self.client.get(self.INDEX_URL + '?tab=fwtabs__rules',
|
||||
tenant_id=tenant_id)
|
||||
|
||||
self.assertTemplateUsed(res, '%s/firewalls/details_tabs.html'
|
||||
% self.DASHBOARD)
|
||||
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
|
||||
self.assertEqual(len(res.context['rulestable_table'].data),
|
||||
len(self.fw_rules.list()))
|
||||
|
||||
@test.create_stubs({api.fwaas: ('firewalls_list',
|
||||
'policies_list',
|
||||
'rules_list')}, )
|
||||
def test_index_exception_firewalls(self):
|
||||
self.set_up_expect_with_exception()
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
firewall = self.firewalls.first()
|
||||
tenant_id = firewall.tenant_id
|
||||
|
||||
res = self.client.get(self.INDEX_URL, tenant_id=tenant_id)
|
||||
|
||||
self.assertTemplateUsed(res,
|
||||
'%s/firewalls/details_tabs.html'
|
||||
% self.DASHBOARD)
|
||||
self.assertTemplateUsed(res,
|
||||
'horizon/common/_detail_table.html')
|
||||
self.assertEqual(len(res.context['table'].data), 0)
|
||||
|
||||
@test.create_stubs({api.fwaas: ('firewalls_list',
|
||||
'policies_list',
|
||||
'rules_list')}, )
|
||||
def test_index_exception_policies(self):
|
||||
self.set_up_expect_with_exception()
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
policy = self.fw_policies.first()
|
||||
tenant_id = policy.tenant_id
|
||||
|
||||
res = self.client.get(self.INDEX_URL + '?tab=fwtabs__policies',
|
||||
tenant_id=tenant_id)
|
||||
|
||||
self.assertTemplateUsed(res,
|
||||
'%s/firewalls/details_tabs.html'
|
||||
% self.DASHBOARD)
|
||||
self.assertTemplateUsed(res,
|
||||
'horizon/common/_detail_table.html')
|
||||
self.assertEqual(len(res.context['policiestable_table'].data), 0)
|
||||
|
||||
@test.create_stubs({api.fwaas: ('firewalls_list',
|
||||
'policies_list',
|
||||
'rules_list')}, )
|
||||
def test_index_exception_rules(self):
|
||||
self.set_up_expect_with_exception()
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
rule = self.fw_rules.first()
|
||||
tenant_id = rule.tenant_id
|
||||
|
||||
res = self.client.get(self.INDEX_URL + '?tab=fwtabs__rules',
|
||||
tenant_id=tenant_id)
|
||||
|
||||
self.assertTemplateUsed(res,
|
||||
'%s/firewalls/details_tabs.html'
|
||||
% self.DASHBOARD)
|
||||
self.assertTemplateUsed(res,
|
||||
'horizon/common/_detail_table.html')
|
||||
self.assertEqual(len(res.context['rulestable_table'].data), 0)
|
||||
|
||||
@test.create_stubs({api.fwaas: ('rule_create',), })
|
||||
def test_add_rule_post(self):
|
||||
rule1 = self.fw_rules.first()
|
||||
|
||||
form_data = {'name': rule1.name,
|
||||
'description': rule1.description,
|
||||
'protocol': rule1.protocol,
|
||||
'action': rule1.action,
|
||||
'source_ip_address': rule1.source_ip_address,
|
||||
'source_port': rule1.source_port,
|
||||
'destination_ip_address': rule1.destination_ip_address,
|
||||
'destination_port': rule1.destination_port,
|
||||
'shared': rule1.shared,
|
||||
'enabled': rule1.enabled
|
||||
}
|
||||
|
||||
api.fwaas.rule_create(
|
||||
IsA(http.HttpRequest), **form_data).AndReturn(rule1)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.post(reverse(self.ADDRULE_PATH), form_data)
|
||||
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
|
||||
|
||||
def test_add_rule_post_with_error(self):
|
||||
rule1 = self.fw_rules.first()
|
||||
|
||||
form_data = {'name': rule1.name,
|
||||
'description': rule1.description,
|
||||
'protocol': 'abc',
|
||||
'action': 'pass',
|
||||
'source_ip_address': rule1.source_ip_address,
|
||||
'source_port': rule1.source_port,
|
||||
'destination_ip_address': rule1.destination_ip_address,
|
||||
'destination_port': rule1.destination_port,
|
||||
'shared': rule1.shared,
|
||||
'enabled': rule1.enabled
|
||||
}
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.post(reverse(self.ADDRULE_PATH), form_data)
|
||||
|
||||
self.assertFormErrors(res, 2)
|
||||
|
||||
@test.create_stubs({api.fwaas: ('policy_create', 'rules_list'), })
|
||||
def test_add_policy_post(self):
|
||||
policy = self.fw_policies.first()
|
||||
rules = self.fw_rules.list()
|
||||
tenant_id = policy.tenant_id
|
||||
form_data = {'name': policy.name,
|
||||
'description': policy.description,
|
||||
'firewall_rules': policy.firewall_rules,
|
||||
'shared': policy.shared,
|
||||
'audited': policy.audited
|
||||
}
|
||||
api.fwaas.rules_list(
|
||||
IsA(http.HttpRequest), tenant_id=tenant_id).AndReturn(rules)
|
||||
api.fwaas.policy_create(
|
||||
IsA(http.HttpRequest), **form_data).AndReturn(policy)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.post(reverse(self.ADDPOLICY_PATH), form_data)
|
||||
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
|
||||
|
||||
@test.create_stubs({api.fwaas: ('policy_create', 'rules_list'), })
|
||||
def test_add_policy_post_with_error(self):
|
||||
policy = self.fw_policies.first()
|
||||
rules = self.fw_rules.list()
|
||||
tenant_id = policy.tenant_id
|
||||
form_data = {'description': policy.description,
|
||||
'firewall_rules': None,
|
||||
'shared': policy.shared,
|
||||
'audited': policy.audited
|
||||
}
|
||||
api.fwaas.rules_list(
|
||||
IsA(http.HttpRequest), tenant_id=tenant_id).AndReturn(rules)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.post(reverse(self.ADDPOLICY_PATH), form_data)
|
||||
|
||||
self.assertFormErrors(res, 1)
|
||||
|
||||
@test.create_stubs({api.fwaas: ('firewall_create', 'policies_list'), })
|
||||
def test_add_firewall_post(self):
|
||||
firewall = self.firewalls.first()
|
||||
policies = self.fw_policies.list()
|
||||
tenant_id = firewall.tenant_id
|
||||
form_data = {'name': firewall.name,
|
||||
'description': firewall.description,
|
||||
'firewall_policy_id': firewall.firewall_policy_id,
|
||||
'shared': firewall.shared,
|
||||
'admin_state_up': firewall.admin_state_up
|
||||
}
|
||||
api.fwaas.policies_list(
|
||||
IsA(http.HttpRequest), tenant_id=tenant_id).AndReturn(policies)
|
||||
api.fwaas.firewall_create(
|
||||
IsA(http.HttpRequest), **form_data).AndReturn(firewall)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.post(reverse(self.ADDFIREWALL_PATH), form_data)
|
||||
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
|
||||
|
||||
@test.create_stubs({api.fwaas: ('firewall_create', 'policies_list'), })
|
||||
def test_add_firewall_post_with_error(self):
|
||||
firewall = self.firewalls.first()
|
||||
policies = self.fw_policies.list()
|
||||
tenant_id = firewall.tenant_id
|
||||
form_data = {'name': firewall.name,
|
||||
'description': firewall.description,
|
||||
'firewall_policy_id': None,
|
||||
'shared': firewall.shared,
|
||||
'admin_state_up': firewall.admin_state_up
|
||||
}
|
||||
api.fwaas.policies_list(
|
||||
IsA(http.HttpRequest), tenant_id=tenant_id).AndReturn(policies)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.post(reverse(self.ADDFIREWALL_PATH), form_data)
|
||||
|
||||
self.assertFormErrors(res, 1)
|
||||
|
||||
@test.create_stubs({api.fwaas: ('rule_get', 'rule_update')})
|
||||
def test_update_rule_post(self):
|
||||
rule = self.fw_rules.first()
|
||||
|
||||
api.fwaas.rule_get(IsA(http.HttpRequest), rule.id).AndReturn(rule)
|
||||
|
||||
rule.name = 'new name'
|
||||
rule.description = 'new desc'
|
||||
rule.protocol = 'ICMP'
|
||||
rule.action = 'ALLOW'
|
||||
rule.shared = False
|
||||
rule.enabled = True
|
||||
|
||||
data = {'name': rule.name,
|
||||
'description': rule.description,
|
||||
'protocol': rule.protocol,
|
||||
'action': rule.action,
|
||||
'shared': rule.shared,
|
||||
'enabled': rule.enabled,
|
||||
'source_ip_address': rule.source_ip_address,
|
||||
'destination_ip_address': None,
|
||||
'source_port': None,
|
||||
'destination_port': rule.destination_port,
|
||||
}
|
||||
|
||||
api.fwaas.rule_update(IsA(http.HttpRequest), rule.id, **data)\
|
||||
.AndReturn(rule)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
form_data = {'name': rule.name,
|
||||
'description': rule.description,
|
||||
'protocol': rule.protocol,
|
||||
'action': rule.action,
|
||||
'shared': rule.shared,
|
||||
'enabled': rule.enabled,
|
||||
'source_ip_address': rule.source_ip_address,
|
||||
'destination_ip_address': '',
|
||||
'source_port': '',
|
||||
'destination_port': rule.destination_port,
|
||||
}
|
||||
|
||||
res = self.client.post(
|
||||
reverse(self.UPDATERULE_PATH, args=(rule.id,)), form_data)
|
||||
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
|
||||
|
||||
@test.create_stubs({api.fwaas: ('policy_get', 'policy_update',
|
||||
'rules_list')})
|
||||
def test_update_policy_post(self):
|
||||
policy = self.fw_policies.first()
|
||||
|
||||
api.fwaas.policy_get(IsA(http.HttpRequest),
|
||||
policy.id).AndReturn(policy)
|
||||
|
||||
policy.name = 'new name'
|
||||
policy.description = 'new desc'
|
||||
policy.shared = True
|
||||
policy.audited = False
|
||||
|
||||
data = {'name': policy.name,
|
||||
'description': policy.description,
|
||||
'shared': policy.shared,
|
||||
'audited': policy.audited
|
||||
}
|
||||
|
||||
api.fwaas.policy_update(IsA(http.HttpRequest), policy.id, **data)\
|
||||
.AndReturn(policy)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.post(
|
||||
reverse(self.UPDATEPOLICY_PATH, args=(policy.id,)), data)
|
||||
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
|
||||
|
||||
@test.create_stubs({api.fwaas: ('firewall_get', 'policies_list',
|
||||
'firewall_update')})
|
||||
def test_update_firewall_post(self):
|
||||
firewall = self.firewalls.first()
|
||||
tenant_id = firewall.tenant_id
|
||||
api.fwaas.firewall_get(IsA(http.HttpRequest),
|
||||
firewall.id).AndReturn(firewall)
|
||||
|
||||
firewall.name = 'new name'
|
||||
firewall.description = 'new desc'
|
||||
firewall.admin_state_up = False
|
||||
|
||||
data = {'name': firewall.name,
|
||||
'description': firewall.description,
|
||||
'firewall_policy_id': firewall.firewall_policy_id,
|
||||
'admin_state_up': firewall.admin_state_up
|
||||
}
|
||||
|
||||
policies = self.fw_policies.list()
|
||||
api.fwaas.policies_list(
|
||||
IsA(http.HttpRequest), tenant_id=tenant_id).AndReturn(policies)
|
||||
|
||||
api.fwaas.firewall_update(IsA(http.HttpRequest), firewall.id, **data)\
|
||||
.AndReturn(firewall)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.post(
|
||||
reverse(self.UPDATEFIREWALL_PATH, args=(firewall.id,)), data)
|
||||
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
|
||||
|
||||
@test.create_stubs({api.fwaas: ('policy_get',
|
||||
'policy_insert_rule',
|
||||
'rules_list')})
|
||||
def test_policy_insert_rule(self):
|
||||
policy = self.fw_policies.first()
|
||||
tenant_id = policy.tenant_id
|
||||
rules = self.fw_rules.list()
|
||||
|
||||
new_rule_id = rules[2].id
|
||||
|
||||
data = {'firewall_rule_id': new_rule_id,
|
||||
'insert_before': rules[1].id,
|
||||
'insert_after': rules[0].id}
|
||||
|
||||
api.fwaas.policy_get(IsA(http.HttpRequest),
|
||||
policy.id).AndReturn(policy)
|
||||
|
||||
policy.firewall_rules = [rules[0].id,
|
||||
new_rule_id,
|
||||
rules[1].id]
|
||||
|
||||
api.fwaas.rules_list(
|
||||
IsA(http.HttpRequest), tenant_id=tenant_id).AndReturn(rules)
|
||||
api.fwaas.policy_insert_rule(IsA(http.HttpRequest), policy.id, **data)\
|
||||
.AndReturn(policy)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.post(
|
||||
reverse(self.INSERTRULE_PATH, args=(policy.id,)), data)
|
||||
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
|
||||
|
||||
@test.create_stubs({api.fwaas: ('policy_get', 'policy_remove_rule',
|
||||
'rules_list',)})
|
||||
def test_policy_remove_rule(self):
|
||||
policy = self.fw_policies.first()
|
||||
tenant_id = policy.tenant_id
|
||||
rules = self.fw_rules.list()
|
||||
|
||||
remove_rule_id = policy.firewall_rules[0]
|
||||
left_rule_id = policy.firewall_rules[1]
|
||||
|
||||
data = {'firewall_rule_id': remove_rule_id}
|
||||
|
||||
after_remove_policy_dict = {'id': 'abcdef-c3eb-4fee-9763-12de3338041e',
|
||||
'tenant_id': '1',
|
||||
'name': 'policy1',
|
||||
'description': 'policy description',
|
||||
'firewall_rules': [left_rule_id],
|
||||
'audited': True,
|
||||
'shared': True}
|
||||
after_remove_policy = fwaas.Policy(after_remove_policy_dict)
|
||||
|
||||
api.fwaas.policy_get(IsA(http.HttpRequest),
|
||||
policy.id).AndReturn(policy)
|
||||
api.fwaas.rules_list(
|
||||
IsA(http.HttpRequest), tenant_id=tenant_id).AndReturn(rules)
|
||||
api.fwaas.policy_remove_rule(IsA(http.HttpRequest), policy.id, **data)\
|
||||
.AndReturn(after_remove_policy)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.post(
|
||||
reverse(self.REMOVERULE_PATH, args=(policy.id,)), data)
|
||||
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
|
46
openstack_dashboard/dashboards/project/firewalls/urls.py
Normal file
46
openstack_dashboard/dashboards/project/firewalls/urls.py
Normal file
@ -0,0 +1,46 @@
|
||||
# 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.conf.urls.defaults import patterns # noqa
|
||||
from django.conf.urls.defaults import url # noqa
|
||||
|
||||
from openstack_dashboard.dashboards.project.firewalls import views
|
||||
|
||||
urlpatterns = patterns(
|
||||
'openstack_dashboard.dashboards.project.firewalls.views',
|
||||
url(r'^$', views.IndexView.as_view(), name='index'),
|
||||
url(r'^addrule$', views.AddRuleView.as_view(), name='addrule'),
|
||||
url(r'^addpolicy$', views.AddPolicyView.as_view(), name='addpolicy'),
|
||||
url(r'^addfirewall/(?P<policy_id>[^/]+)/$',
|
||||
views.AddFirewallView.as_view(), name='addfirewall'),
|
||||
url(r'^addfirewall$', views.AddFirewallView.as_view(), name='addfirewall'),
|
||||
url(r'^insertrule/(?P<policy_id>[^/]+)/$',
|
||||
views.InsertRuleToPolicyView.as_view(), name='insertrule'),
|
||||
url(r'^removerule/(?P<policy_id>[^/]+)/$',
|
||||
views.RemoveRuleFromPolicyView.as_view(), name='removerule'),
|
||||
url(r'^updaterule/(?P<rule_id>[^/]+)/$',
|
||||
views.UpdateRuleView.as_view(), name='updaterule'),
|
||||
url(r'^updatepolicy/(?P<policy_id>[^/]+)/$',
|
||||
views.UpdatePolicyView.as_view(), name='updatepolicy'),
|
||||
url(r'^updatefirewall/(?P<firewall_id>[^/]+)/$',
|
||||
views.UpdateFirewallView.as_view(), name='updatefirewall'),
|
||||
url(r'^rule/(?P<rule_id>[^/]+)/$',
|
||||
views.RuleDetailsView.as_view(), name='ruledetails'),
|
||||
url(r'^policy/(?P<policy_id>[^/]+)/$',
|
||||
views.PolicyDetailsView.as_view(), name='policydetails'),
|
||||
url(r'^firewall/(?P<firewall_id>[^/]+)/$',
|
||||
views.FirewallDetailsView.as_view(), name='firewalldetails'))
|
285
openstack_dashboard/dashboards/project/firewalls/views.py
Normal file
285
openstack_dashboard/dashboards/project/firewalls/views.py
Normal file
@ -0,0 +1,285 @@
|
||||
# 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
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
from django.core.urlresolvers import reverse_lazy # noqa
|
||||
from django.utils.translation import ugettext as _ # noqa
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import messages
|
||||
from horizon import tabs
|
||||
from horizon import workflows
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.project.firewalls \
|
||||
import forms as fw_forms
|
||||
from openstack_dashboard.dashboards.project.firewalls \
|
||||
import tabs as fw_tabs
|
||||
from openstack_dashboard.dashboards.project.firewalls \
|
||||
import workflows as fw_workflows
|
||||
|
||||
InsertRuleToPolicy = fw_forms.InsertRuleToPolicy
|
||||
RemoveRuleFromPolicy = fw_forms.RemoveRuleFromPolicy
|
||||
UpdateFirewall = fw_forms.UpdateFirewall
|
||||
UpdatePolicy = fw_forms.UpdatePolicy
|
||||
UpdateRule = fw_forms.UpdateRule
|
||||
|
||||
FirewallDetailsTabs = fw_tabs.FirewallDetailsTabs
|
||||
FirewallTabs = fw_tabs.FirewallTabs
|
||||
PolicyDetailsTabs = fw_tabs.PolicyDetailsTabs
|
||||
RuleDetailsTabs = fw_tabs.RuleDetailsTabs
|
||||
|
||||
AddFirewall = fw_workflows.AddFirewall
|
||||
AddPolicy = fw_workflows.AddPolicy
|
||||
AddRule = fw_workflows.AddRule
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class IndexView(tabs.TabView):
|
||||
tab_group_class = (FirewallTabs)
|
||||
template_name = 'project/firewalls/details_tabs.html'
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
obj_ids = request.POST.getlist('object_ids')
|
||||
action = request.POST['action']
|
||||
obj_type = re.search('.delete([a-z]+)', action).group(1)
|
||||
if not obj_ids:
|
||||
obj_ids.append(re.search('([0-9a-z-]+)$', action).group(1))
|
||||
if obj_type == 'rule':
|
||||
for obj_id in obj_ids:
|
||||
try:
|
||||
api.fwaas.rule_delete(request, obj_id)
|
||||
messages.success(request, 'Deleted rule %s' % obj_id)
|
||||
except Exception as e:
|
||||
exceptions.handle(request,
|
||||
_('Unable to delete rule. %s' % e))
|
||||
if obj_type == 'policy':
|
||||
for obj_id in obj_ids:
|
||||
try:
|
||||
api.fwaas.policy_delete(request, obj_id)
|
||||
messages.success(request, 'Deleted policy %s' % obj_id)
|
||||
except Exception as e:
|
||||
exceptions.handle(request,
|
||||
_('Unable to delete policy. %s' % e))
|
||||
if obj_type == 'firewall':
|
||||
for obj_id in obj_ids:
|
||||
try:
|
||||
api.fwaas.firewall_delete(request, obj_id)
|
||||
messages.success(request, 'Deleted firewall %s' % obj_id)
|
||||
except Exception as e:
|
||||
exceptions.handle(request,
|
||||
_('Unable to delete firewall. %s' % e))
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
|
||||
class AddRuleView(workflows.WorkflowView):
|
||||
workflow_class = AddRule
|
||||
template_name = "project/firewalls/addrule.html"
|
||||
|
||||
|
||||
class AddPolicyView(workflows.WorkflowView):
|
||||
workflow_class = AddPolicy
|
||||
template_name = "project/firewalls/addpolicy.html"
|
||||
|
||||
|
||||
class AddFirewallView(workflows.WorkflowView):
|
||||
workflow_class = AddFirewall
|
||||
template_name = "project/firewalls/addfirewall.html"
|
||||
|
||||
|
||||
class RuleDetailsView(tabs.TabView):
|
||||
tab_group_class = (RuleDetailsTabs)
|
||||
template_name = 'project/firewalls/details_tabs.html'
|
||||
|
||||
|
||||
class PolicyDetailsView(tabs.TabView):
|
||||
tab_group_class = (PolicyDetailsTabs)
|
||||
template_name = 'project/firewalls/details_tabs.html'
|
||||
|
||||
|
||||
class FirewallDetailsView(tabs.TabView):
|
||||
tab_group_class = (FirewallDetailsTabs)
|
||||
template_name = 'project/firewalls/details_tabs.html'
|
||||
|
||||
|
||||
class UpdateRuleView(forms.ModalFormView):
|
||||
form_class = UpdateRule
|
||||
template_name = "project/firewalls/updaterule.html"
|
||||
context_object_name = 'rule'
|
||||
success_url = reverse_lazy("horizon:project:firewalls:index")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(UpdateRuleView, self).get_context_data(**kwargs)
|
||||
context['rule_id'] = self.kwargs['rule_id']
|
||||
obj = self._get_object()
|
||||
if obj:
|
||||
context['name'] = obj.name
|
||||
return context
|
||||
|
||||
def _get_object(self, *args, **kwargs):
|
||||
if not hasattr(self, "_object"):
|
||||
rule_id = self.kwargs['rule_id']
|
||||
try:
|
||||
self._object = api.fwaas.rule_get(self.request, rule_id)
|
||||
self._object.set_id_as_name_if_empty()
|
||||
except Exception:
|
||||
redirect = self.success_url
|
||||
msg = _('Unable to retrieve rule details.')
|
||||
exceptions.handle(self.request, msg, redirect=redirect)
|
||||
return self._object
|
||||
|
||||
def get_initial(self):
|
||||
rule = self._get_object()
|
||||
initial = rule.get_dict()
|
||||
return initial
|
||||
|
||||
|
||||
class UpdatePolicyView(forms.ModalFormView):
|
||||
form_class = UpdatePolicy
|
||||
template_name = "project/firewalls/updatepolicy.html"
|
||||
context_object_name = 'policy'
|
||||
success_url = reverse_lazy("horizon:project:firewalls:index")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(UpdatePolicyView, self).get_context_data(**kwargs)
|
||||
context["policy_id"] = self.kwargs['policy_id']
|
||||
obj = self._get_object()
|
||||
if obj:
|
||||
context['name'] = obj.name
|
||||
return context
|
||||
|
||||
def _get_object(self, *args, **kwargs):
|
||||
if not hasattr(self, "_object"):
|
||||
policy_id = self.kwargs['policy_id']
|
||||
try:
|
||||
self._object = api.fwaas.policy_get(self.request, policy_id)
|
||||
self._object.set_id_as_name_if_empty()
|
||||
except Exception:
|
||||
redirect = self.success_url
|
||||
msg = _('Unable to retrieve policy details.')
|
||||
exceptions.handle(self.request, msg, redirect=redirect)
|
||||
return self._object
|
||||
|
||||
def get_initial(self):
|
||||
policy = self._get_object()
|
||||
initial = policy.get_dict()
|
||||
return initial
|
||||
|
||||
|
||||
class UpdateFirewallView(forms.ModalFormView):
|
||||
form_class = UpdateFirewall
|
||||
template_name = "project/firewalls/updatefirewall.html"
|
||||
context_object_name = 'firewall'
|
||||
success_url = reverse_lazy("horizon:project:firewalls:index")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(UpdateFirewallView, self).get_context_data(**kwargs)
|
||||
context["firewall_id"] = self.kwargs['firewall_id']
|
||||
obj = self._get_object()
|
||||
if obj:
|
||||
context['name'] = obj.name
|
||||
return context
|
||||
|
||||
def _get_object(self, *args, **kwargs):
|
||||
if not hasattr(self, "_object"):
|
||||
firewall_id = self.kwargs['firewall_id']
|
||||
try:
|
||||
self._object = api.fwaas.firewall_get(self.request,
|
||||
firewall_id)
|
||||
self._object.set_id_as_name_if_empty()
|
||||
except Exception:
|
||||
redirect = self.success_url
|
||||
msg = _('Unable to retrieve firewall details.')
|
||||
exceptions.handle(self.request, msg, redirect=redirect)
|
||||
return self._object
|
||||
|
||||
def get_initial(self):
|
||||
firewall = self._get_object()
|
||||
initial = firewall.get_dict()
|
||||
return initial
|
||||
|
||||
|
||||
class InsertRuleToPolicyView(forms.ModalFormView):
|
||||
form_class = InsertRuleToPolicy
|
||||
template_name = "project/firewalls/insert_rule_to_policy.html"
|
||||
context_object_name = 'policy'
|
||||
success_url = reverse_lazy("horizon:project:firewalls:index")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(InsertRuleToPolicyView,
|
||||
self).get_context_data(**kwargs)
|
||||
context["policy_id"] = self.kwargs['policy_id']
|
||||
obj = self._get_object()
|
||||
if obj:
|
||||
context['name'] = obj.name
|
||||
return context
|
||||
|
||||
def _get_object(self, *args, **kwargs):
|
||||
if not hasattr(self, "_object"):
|
||||
policy_id = self.kwargs['policy_id']
|
||||
try:
|
||||
self._object = api.fwaas.policy_get(self.request, policy_id)
|
||||
self._object.set_id_as_name_if_empty()
|
||||
except Exception:
|
||||
redirect = self.success_url
|
||||
msg = _('Unable to retrieve policy details.')
|
||||
exceptions.handle(self.request, msg, redirect=redirect)
|
||||
return self._object
|
||||
|
||||
def get_initial(self):
|
||||
policy = self._get_object()
|
||||
initial = policy.get_dict()
|
||||
initial['policy_id'] = initial['id']
|
||||
return initial
|
||||
|
||||
|
||||
class RemoveRuleFromPolicyView(forms.ModalFormView):
|
||||
form_class = RemoveRuleFromPolicy
|
||||
template_name = "project/firewalls/remove_rule_from_policy.html"
|
||||
context_object_name = 'policy'
|
||||
success_url = reverse_lazy("horizon:project:firewalls:index")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(RemoveRuleFromPolicyView,
|
||||
self).get_context_data(**kwargs)
|
||||
context["policy_id"] = self.kwargs['policy_id']
|
||||
obj = self._get_object()
|
||||
if obj:
|
||||
context['name'] = obj.name
|
||||
return context
|
||||
|
||||
def _get_object(self, *args, **kwargs):
|
||||
if not hasattr(self, "_object"):
|
||||
policy_id = self.kwargs['policy_id']
|
||||
try:
|
||||
self._object = api.fwaas.policy_get(self.request, policy_id)
|
||||
self._object.set_id_as_name_if_empty()
|
||||
except Exception:
|
||||
redirect = self.success_url
|
||||
msg = _('Unable to retrieve policy details.')
|
||||
exceptions.handle(self.request, msg, redirect=redirect)
|
||||
return self._object
|
||||
|
||||
def get_initial(self):
|
||||
policy = self._get_object()
|
||||
initial = policy.get_dict()
|
||||
initial['policy_id'] = initial['id']
|
||||
return initial
|
315
openstack_dashboard/dashboards/project/firewalls/workflows.py
Normal file
315
openstack_dashboard/dashboards/project/firewalls/workflows.py
Normal file
@ -0,0 +1,315 @@
|
||||
# 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
|
||||
|
||||
import logging
|
||||
|
||||
from django.utils.translation import ugettext as _ # noqa
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon.utils import fields
|
||||
from horizon.utils import validators
|
||||
from horizon import workflows
|
||||
|
||||
from openstack_dashboard import api
|
||||
|
||||
port_validator = validators.validate_port_or_colon_separated_port_range
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
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')),
|
||||
(None, _('ANY'))],)
|
||||
action = forms.ChoiceField(
|
||||
label=_("Action"),
|
||||
choices=[('allow', _('ALLOW')),
|
||||
('deny', _('DENY'))],)
|
||||
source_ip_address = fields.IPField(
|
||||
label=_("Source IP Address/Subnet"),
|
||||
version=fields.IPv4 | fields.IPv6,
|
||||
required=False, mask=True)
|
||||
destination_ip_address = fields.IPField(
|
||||
label=_("Destination IP Address/Subnet"),
|
||||
version=fields.IPv4 | fields.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:
|
||||
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.rules_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.') + 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("firewall_rules")
|
||||
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.policies_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.') + 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
|
@ -158,6 +158,7 @@ OPENSTACK_HYPERVISOR_FEATURES = {
|
||||
# balancer service, security groups, quotas, VPN service.
|
||||
OPENSTACK_NEUTRON_NETWORK = {
|
||||
'enable_lb': False,
|
||||
'enable_firewall': False,
|
||||
'enable_quotas': True,
|
||||
'enable_security_group': True,
|
||||
'enable_vpn': False,
|
||||
|
@ -2080,3 +2080,116 @@ label.log-length {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Styling for draged firewall rule object */
|
||||
#ruleListSortContainer {
|
||||
display: none;
|
||||
}
|
||||
.rulelist {
|
||||
padding: 6px;
|
||||
background: #eee;
|
||||
border: 1px solid #ccc;
|
||||
min-height: 2em;
|
||||
width: auto !important;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
li {
|
||||
width: 226px;
|
||||
list-style-type: none;
|
||||
margin: 6px auto;
|
||||
padding: 3px;
|
||||
background: #fff;
|
||||
border: 1px solid #aaa;
|
||||
line-height: 18px;
|
||||
border-radius: 3px;
|
||||
cursor: move;
|
||||
padding-left: 23px;
|
||||
background: white url(/static/dashboard/img/drag.png) no-repeat 11px 50%;
|
||||
em {
|
||||
font-size: 0.5em;
|
||||
line-height: 1em;
|
||||
color:#999;
|
||||
font-style: normal;
|
||||
margin-left: 0.8em;
|
||||
}
|
||||
i {
|
||||
margin-right: 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
a.btn {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
font-size: 11px;
|
||||
line-height: 12px;
|
||||
padding: 2px 5px 3px;
|
||||
margin-right: 1px;
|
||||
width: 18px;
|
||||
text-align: center;
|
||||
//position: absolute;
|
||||
right:5px;
|
||||
vertical-align: middle;
|
||||
float: right;
|
||||
&:before {
|
||||
content: "+";
|
||||
}
|
||||
}
|
||||
}
|
||||
li.ui-sortable-helper {
|
||||
background-color: #def;
|
||||
}
|
||||
li.ui-state-highlight {
|
||||
border: 1px dotted #ccc;
|
||||
background: #efefef;
|
||||
height: 0.5em;
|
||||
}
|
||||
li:after {
|
||||
visibility: hidden;
|
||||
display: block;
|
||||
font-size: 0;
|
||||
content: " ";
|
||||
clear: both;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
#selected_rule {
|
||||
margin-bottom: 1.5em;
|
||||
counter-reset:v1 0;
|
||||
background: #edf9ff;
|
||||
border:1px solid #c0d9e4;
|
||||
li {
|
||||
position: relative;
|
||||
a.btn {
|
||||
&:before {
|
||||
content: "-";
|
||||
}
|
||||
}
|
||||
}
|
||||
li:before {
|
||||
content:"rule:"counter(v1);
|
||||
counter-increment:v1;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
background: #666;
|
||||
color:#fff;
|
||||
font-size: 90%;
|
||||
padding: 0px 4px;
|
||||
vertical-align: middle;
|
||||
border-radius: 2px;
|
||||
position: absolute;
|
||||
left: -2em;
|
||||
}
|
||||
&.dragging {
|
||||
li:before {
|
||||
content:"rule:";
|
||||
background-color:rgba(102,102,102,0.5);
|
||||
padding-right: 10px;
|
||||
}
|
||||
li.ui-state-highlight:before {
|
||||
content:"";
|
||||
background:transparent;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
321
openstack_dashboard/test/api_tests/fwaas_tests.py
Normal file
321
openstack_dashboard/test/api_tests/fwaas_tests.py
Normal file
@ -0,0 +1,321 @@
|
||||
# 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 openstack_dashboard import api
|
||||
from openstack_dashboard.test import helpers as test
|
||||
|
||||
from neutronclient.v2_0.client import Client as neutronclient # noqa
|
||||
|
||||
|
||||
class FwaasApiTests(test.APITestCase):
|
||||
@test.create_stubs({neutronclient: ('create_firewall_rule',)})
|
||||
def test_rule_create(self):
|
||||
rule1 = self.fw_rules.first()
|
||||
rule1_dict = self.api_fw_rules.first()
|
||||
form_data = {'name': rule1.name,
|
||||
'description': rule1.description,
|
||||
'protocol': rule1.protocol,
|
||||
'action': rule1.action,
|
||||
'source_ip_address': rule1.source_ip_address,
|
||||
'source_port': rule1.source_port,
|
||||
'destination_ip_address': rule1.destination_ip_address,
|
||||
'destination_port': rule1.destination_port,
|
||||
'shared': rule1.shared,
|
||||
'enabled': rule1.enabled
|
||||
}
|
||||
form_dict = {'firewall_rule': form_data}
|
||||
ret_dict = {'firewall_rule': rule1_dict}
|
||||
neutronclient.create_firewall_rule(form_dict).AndReturn(ret_dict)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.fwaas.rule_create(self.request, **form_data)
|
||||
self.assertIsInstance(ret_val, api.fwaas.Rule)
|
||||
self.assertEqual(rule1.name, ret_val.name)
|
||||
self.assertTrue(ret_val.id)
|
||||
|
||||
@test.create_stubs({neutronclient: ('list_firewall_rules',)})
|
||||
def test_rules_list(self):
|
||||
rules = {'firewall_rules': self.fw_rules.list()}
|
||||
rules_dict = {'firewall_rules': self.api_fw_rules.list()}
|
||||
neutronclient.list_firewall_rules().AndReturn(rules_dict)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.fwaas.rules_list(self.request)
|
||||
for (v, d) in zip(ret_val, rules['firewall_rules']):
|
||||
self.assertIsInstance(v, api.fwaas.Rule)
|
||||
self.assertTrue(v.name, d.name)
|
||||
self.assertTrue(v.id)
|
||||
|
||||
@test.create_stubs({neutronclient: ('show_firewall_rule',)})
|
||||
def test_rule_get(self):
|
||||
rule = self.fw_rules.first()
|
||||
rule_dict = self.api_fw_rules.first()
|
||||
ret_dict = {'firewall_rule': rule_dict}
|
||||
|
||||
neutronclient.show_firewall_rule(rule.id).AndReturn(ret_dict)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.fwaas.rule_get(self.request, rule.id)
|
||||
self.assertIsInstance(ret_val, api.fwaas.Rule)
|
||||
self.assertEqual(rule.name, ret_val.name)
|
||||
self.assertTrue(ret_val.id)
|
||||
|
||||
@test.create_stubs({neutronclient: ('update_firewall_rule',)})
|
||||
def test_rule_update(self):
|
||||
rule = self.fw_rules.first()
|
||||
rule_dict = self.api_fw_rules.first()
|
||||
|
||||
rule.name = 'new name'
|
||||
rule.description = 'new desc'
|
||||
rule.protocol = 'icmp'
|
||||
rule.action = 'deny'
|
||||
rule.shared = True
|
||||
rule.enabled = False
|
||||
|
||||
rule_dict['name'] = 'new name'
|
||||
rule_dict['description'] = 'new desc'
|
||||
rule_dict['protocol'] = 'icmp'
|
||||
rule_dict['action'] = 'deny'
|
||||
rule_dict['shared'] = True
|
||||
rule_dict['enabled'] = False
|
||||
|
||||
form_data = {'name': rule.name,
|
||||
'description': rule.description,
|
||||
'protocol': rule.protocol,
|
||||
'action': rule.action,
|
||||
'shared': rule.shared,
|
||||
'enabled': rule.enabled
|
||||
}
|
||||
form_dict = {'firewall_rule': form_data}
|
||||
ret_dict = {'firewall_rule': rule_dict}
|
||||
|
||||
neutronclient.update_firewall_rule(
|
||||
rule.id, form_dict).AndReturn(ret_dict)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.fwaas.rule_update(self.request,
|
||||
rule.id, **form_data)
|
||||
self.assertIsInstance(ret_val, api.fwaas.Rule)
|
||||
self.assertEqual(rule.name, ret_val.name)
|
||||
self.assertTrue(ret_val.id)
|
||||
|
||||
@test.create_stubs({neutronclient: ('create_firewall_policy', )})
|
||||
def test_policy_create(self):
|
||||
policy1 = self.fw_policies.first()
|
||||
policy1_dict = self.api_fw_policies.first()
|
||||
|
||||
form_data = {'name': policy1.name,
|
||||
'description': policy1.description,
|
||||
'firewall_rules': policy1.firewall_rules,
|
||||
'shared': policy1.shared,
|
||||
'audited': policy1.audited
|
||||
}
|
||||
form_dict = {'firewall_policy': form_data}
|
||||
ret_dict = {'firewall_policy': policy1_dict}
|
||||
|
||||
neutronclient.create_firewall_policy(form_dict).AndReturn(ret_dict)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.fwaas.policy_create(self.request, **form_data)
|
||||
self.assertIsInstance(ret_val, api.fwaas.Policy)
|
||||
self.assertEqual(policy1.name, ret_val.name)
|
||||
self.assertTrue(ret_val.id)
|
||||
|
||||
@test.create_stubs({neutronclient: ('list_firewall_policies',)})
|
||||
def test_policies_list(self):
|
||||
policies = {'firewall_policies': self.fw_policies.list()}
|
||||
policies_dict = {'firewall_policies': self.api_fw_policies.list()}
|
||||
|
||||
neutronclient.list_firewall_policies().AndReturn(policies_dict)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.fwaas.policies_list(self.request)
|
||||
for (v, d) in zip(ret_val, policies['firewall_policies']):
|
||||
self.assertIsInstance(v, api.fwaas.Policy)
|
||||
self.assertTrue(v.name, d.name)
|
||||
self.assertTrue(v.id)
|
||||
|
||||
@test.create_stubs({neutronclient: ('show_firewall_policy',)})
|
||||
def test_policy_get(self):
|
||||
policy = self.fw_policies.first()
|
||||
policy_dict = self.api_fw_policies.first()
|
||||
|
||||
ret_dict = {'firewall_policy': policy_dict}
|
||||
neutronclient.show_firewall_policy(policy.id).AndReturn(ret_dict)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.fwaas.policy_get(self.request, policy.id)
|
||||
self.assertIsInstance(ret_val, api.fwaas.Policy)
|
||||
self.assertEqual(policy.name, ret_val.name)
|
||||
self.assertTrue(ret_val.id)
|
||||
|
||||
@test.create_stubs({neutronclient: ('update_firewall_policy',)})
|
||||
def test_policy_update(self):
|
||||
policy = self.fw_policies.first()
|
||||
policy_dict = self.api_fw_policies.first()
|
||||
|
||||
policy.name = 'new name'
|
||||
policy.description = 'new desc'
|
||||
policy.shared = True
|
||||
policy.audited = False
|
||||
|
||||
policy_dict['name'] = 'new name'
|
||||
policy_dict['description'] = 'new desc'
|
||||
policy_dict['shared'] = True
|
||||
policy_dict['audited'] = False
|
||||
|
||||
form_data = {'name': policy.name,
|
||||
'description': policy.description,
|
||||
'shared': policy.shared,
|
||||
'audited': policy.audited
|
||||
}
|
||||
|
||||
form_dict = {'firewall_policy': form_data}
|
||||
ret_dict = {'firewall_policy': policy_dict}
|
||||
|
||||
neutronclient.update_firewall_policy(
|
||||
policy.id, form_dict).AndReturn(ret_dict)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.fwaas.policy_update(self.request,
|
||||
policy.id, **form_data)
|
||||
self.assertIsInstance(ret_val, api.fwaas.Policy)
|
||||
self.assertEqual(policy.name, ret_val.name)
|
||||
self.assertTrue(ret_val.id)
|
||||
|
||||
@test.create_stubs({neutronclient: ('firewall_policy_insert_rule',)})
|
||||
def test_policy_insert_rule(self):
|
||||
policy = self.fw_policies.first()
|
||||
policy_dict = self.api_fw_policies.first()
|
||||
|
||||
new_rule_id = 'h0881d38-c3eb-4fee-9763-12de3338041d'
|
||||
policy.firewall_rules.append(new_rule_id)
|
||||
policy_dict['firewall_rules'].append(new_rule_id)
|
||||
|
||||
body = {'firewall_rule_id': new_rule_id,
|
||||
'insert_before': policy.firewall_rules[1],
|
||||
'insert_after': policy.firewall_rules[0]}
|
||||
|
||||
neutronclient.firewall_policy_insert_rule(
|
||||
policy.id, body).AndReturn(policy_dict)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.fwaas.policy_insert_rule(self.request,
|
||||
policy.id, **body)
|
||||
self.assertTrue(new_rule_id in ret_val.firewall_rules)
|
||||
|
||||
@test.create_stubs({neutronclient: ('firewall_policy_remove_rule',)})
|
||||
def test_policy_remove_rule(self):
|
||||
policy = self.fw_policies.first()
|
||||
policy_dict = self.api_fw_policies.first()
|
||||
|
||||
remove_rule_id = policy.firewall_rules[0]
|
||||
policy.firewall_rules.remove(remove_rule_id)
|
||||
|
||||
body = {'firewall_rule_id': remove_rule_id}
|
||||
|
||||
neutronclient.firewall_policy_remove_rule(
|
||||
policy.id, body).AndReturn(policy_dict)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.fwaas.policy_remove_rule(self.request,
|
||||
policy.id, **body)
|
||||
self.assertFalse(remove_rule_id in ret_val.firewall_rules)
|
||||
|
||||
@test.create_stubs({neutronclient: ('create_firewall', )})
|
||||
def test_firewall_create(self):
|
||||
firewall = self.firewalls.first()
|
||||
firewall_dict = self.api_firewalls.first()
|
||||
|
||||
form_data = {'name': firewall.name,
|
||||
'description': firewall.description,
|
||||
'firewall_policy_id': firewall.firewall_policy_id,
|
||||
'shared': firewall.shared,
|
||||
'admin_state_up': firewall.admin_state_up
|
||||
}
|
||||
|
||||
form_dict = {'firewall': form_data}
|
||||
ret_dict = {'firewall': firewall_dict}
|
||||
neutronclient.create_firewall(form_dict).AndReturn(ret_dict)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.fwaas.firewall_create(self.request, **form_data)
|
||||
self.assertIsInstance(ret_val, api.fwaas.Firewall)
|
||||
self.assertEqual(firewall.name, ret_val.name)
|
||||
self.assertTrue(ret_val.id)
|
||||
|
||||
@test.create_stubs({neutronclient: ('list_firewalls',)})
|
||||
def test_firewalls_list(self):
|
||||
firewalls = {'firewalls': self.firewalls.list()}
|
||||
firewalls_dict = {'firewalls': self.api_firewalls.list()}
|
||||
|
||||
neutronclient.list_firewalls().AndReturn(firewalls_dict)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.fwaas.firewalls_list(self.request)
|
||||
for (v, d) in zip(ret_val, firewalls['firewalls']):
|
||||
self.assertIsInstance(v, api.fwaas.Firewall)
|
||||
self.assertTrue(v.name, d.name)
|
||||
self.assertTrue(v.id)
|
||||
|
||||
@test.create_stubs({neutronclient: ('show_firewall',)})
|
||||
def test_firewall_get(self):
|
||||
firewall = self.firewalls.first()
|
||||
firewall_dict = self.api_firewalls.first()
|
||||
|
||||
ret_dict = {'firewall': firewall_dict}
|
||||
|
||||
neutronclient.show_firewall(firewall.id).AndReturn(ret_dict)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.fwaas.firewall_get(self.request, firewall.id)
|
||||
self.assertIsInstance(ret_val, api.fwaas.Firewall)
|
||||
self.assertEqual(firewall.name, ret_val.name)
|
||||
self.assertTrue(ret_val.id)
|
||||
|
||||
@test.create_stubs({neutronclient: ('update_firewall',)})
|
||||
def test_firewall_update(self):
|
||||
firewall = self.firewalls.first()
|
||||
firewall_dict = self.api_firewalls.first()
|
||||
|
||||
firewall.name = 'new name'
|
||||
firewall.description = 'new desc'
|
||||
firewall.admin_state_up = False
|
||||
|
||||
firewall_dict['name'] = 'new name'
|
||||
firewall_dict['description'] = 'new desc'
|
||||
firewall_dict['admin_state_up'] = False
|
||||
|
||||
form_data = {'name': firewall.name,
|
||||
'description': firewall.description,
|
||||
'admin_state_up': firewall.admin_state_up
|
||||
}
|
||||
|
||||
form_dict = {'firewall': form_data}
|
||||
ret_dict = {'firewall': firewall_dict}
|
||||
|
||||
neutronclient.update_firewall(
|
||||
firewall.id, form_dict).AndReturn(ret_dict)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.fwaas.firewall_update(self.request,
|
||||
firewall.id, **form_data)
|
||||
self.assertIsInstance(ret_val, api.fwaas.Firewall)
|
||||
self.assertEqual(firewall.name, ret_val.name)
|
||||
self.assertTrue(ret_val.id)
|
@ -97,6 +97,7 @@ OPENSTACK_KEYSTONE_BACKEND = {
|
||||
|
||||
OPENSTACK_NEUTRON_NETWORK = {
|
||||
'enable_lb': True,
|
||||
'enable_firewall': True,
|
||||
'enable_quotas': False, # Enabled in specific tests only
|
||||
'enable_vpn': True
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import copy
|
||||
import uuid
|
||||
|
||||
from openstack_dashboard.api import base
|
||||
from openstack_dashboard.api import fwaas
|
||||
from openstack_dashboard.api import lbaas
|
||||
from openstack_dashboard.api import neutron
|
||||
from openstack_dashboard.api import vpn
|
||||
@ -46,6 +47,9 @@ def data(TEST):
|
||||
TEST.ikepolicies = utils.TestDataContainer()
|
||||
TEST.ipsecpolicies = utils.TestDataContainer()
|
||||
TEST.ipsecsiteconnections = utils.TestDataContainer()
|
||||
TEST.firewalls = utils.TestDataContainer()
|
||||
TEST.fw_policies = utils.TestDataContainer()
|
||||
TEST.fw_rules = utils.TestDataContainer()
|
||||
|
||||
# data return by neutronclient
|
||||
TEST.api_agents = utils.TestDataContainer()
|
||||
@ -69,6 +73,9 @@ def data(TEST):
|
||||
TEST.api_ikepolicies = utils.TestDataContainer()
|
||||
TEST.api_ipsecpolicies = utils.TestDataContainer()
|
||||
TEST.api_ipsecsiteconnections = utils.TestDataContainer()
|
||||
TEST.api_firewalls = utils.TestDataContainer()
|
||||
TEST.api_fw_policies = utils.TestDataContainer()
|
||||
TEST.api_fw_rules = utils.TestDataContainer()
|
||||
|
||||
#------------------------------------------------------------
|
||||
# 1st network
|
||||
@ -703,3 +710,83 @@ def data(TEST):
|
||||
TEST.api_ipsecsiteconnections.add(ipsecsiteconnection_dict)
|
||||
TEST.ipsecsiteconnections.add(
|
||||
vpn.IPSecSiteConnection(ipsecsiteconnection_dict))
|
||||
|
||||
# FWaaS
|
||||
|
||||
# 1st rule
|
||||
rule1_dict = {'id': 'f0881d38-c3eb-4fee-9763-12de3338041d',
|
||||
'tenant_id': '1',
|
||||
'name': 'rule1',
|
||||
'description': 'rule1 description',
|
||||
'protocol': 'tcp',
|
||||
'action': 'allow',
|
||||
'source_ip_address': '1.2.3.0/24',
|
||||
'source_port': '80',
|
||||
'destination_ip_address': '4.5.6.7/32',
|
||||
'destination_port': '1:65535',
|
||||
'firewall_policy_id': 'abcdef-c3eb-4fee-9763-12de3338041e',
|
||||
'position': 1,
|
||||
'shared': True,
|
||||
'enabled': True}
|
||||
TEST.api_fw_rules.add(rule1_dict)
|
||||
TEST.fw_rules.add(fwaas.Rule(rule1_dict))
|
||||
|
||||
# 2nd rule
|
||||
rule2_dict = {'id': 'g0881d38-c3eb-4fee-9763-12de3338041d',
|
||||
'tenant_id': '1',
|
||||
'name': 'rule2',
|
||||
'description': 'rule2 description',
|
||||
'protocol': 'udp',
|
||||
'action': 'deny',
|
||||
'source_ip_address': '1.2.3.0/24',
|
||||
'source_port': '80',
|
||||
'destination_ip_address': '4.5.6.7/32',
|
||||
'destination_port': '1:65535',
|
||||
'firewall_policy_id': 'abcdef-c3eb-4fee-9763-12de3338041e',
|
||||
'position': 2,
|
||||
'shared': True,
|
||||
'enabled': True}
|
||||
TEST.api_fw_rules.add(rule2_dict)
|
||||
TEST.fw_rules.add(fwaas.Rule(rule2_dict))
|
||||
|
||||
# 3rd rule
|
||||
rule3_dict = {'id': 'h0881d38-c3eb-4fee-9763-12de3338041d',
|
||||
'tenant_id': '1',
|
||||
'name': 'rule3',
|
||||
'description': 'rule3 description',
|
||||
'protocol': 'icmp',
|
||||
'action': 'allow',
|
||||
'source_ip_address': '1.2.3.0/24',
|
||||
'source_port': '80',
|
||||
'destination_ip_address': '4.5.6.7/32',
|
||||
'destination_port': '1:65535',
|
||||
'firewall_policy_id': None,
|
||||
'position': None,
|
||||
'shared': True,
|
||||
'enabled': True}
|
||||
TEST.api_fw_rules.add(rule3_dict)
|
||||
TEST.fw_rules.add(fwaas.Rule(rule3_dict))
|
||||
|
||||
# 1st policy
|
||||
policy_dict = {'id': 'abcdef-c3eb-4fee-9763-12de3338041e',
|
||||
'tenant_id': '1',
|
||||
'name': 'policy1',
|
||||
'description': 'policy description',
|
||||
'firewall_rules': [rule1_dict['id'], rule2_dict['id']],
|
||||
'audited': True,
|
||||
'shared': True}
|
||||
TEST.api_fw_policies.add(policy_dict)
|
||||
TEST.fw_policies.add(fwaas.Policy(policy_dict))
|
||||
|
||||
# 1st firewall
|
||||
firewall_dict = {'id': '8913dde8-4915-4b90-8d3e-b95eeedb0d49',
|
||||
'tenant_id': '1',
|
||||
'firewall_policy_id':
|
||||
'abcdef-c3eb-4fee-9763-12de3338041e',
|
||||
'name': 'firewall1',
|
||||
'description': 'firewall description',
|
||||
'status': 'PENDING_CREATE',
|
||||
'shared': True,
|
||||
'admin_state_up': True}
|
||||
TEST.api_firewalls.add(firewall_dict)
|
||||
TEST.firewalls.add(fwaas.Firewall(firewall_dict))
|
||||
|
Loading…
x
Reference in New Issue
Block a user