From e2967c2885ca533d15ec448a71416448c9011ddd Mon Sep 17 00:00:00 2001 From: uday bhaskar Date: Mon, 24 Nov 2014 12:51:15 +0530 Subject: [PATCH] GBP UI - added application policy UI Change-Id: I56879f4b97f24b3449ce2bf849d4236facf6da4d --- gbpui/client.py | 1 + gbpui/column_filters.py | 132 +++++++ gbpui/fields.py | 65 ++++ gbpui/panels/__init__.py | 0 gbpui/panels/application_policy/__init__.py | 0 gbpui/panels/application_policy/forms.py | 274 +++++++++++++++ gbpui/panels/application_policy/panel.py | 20 ++ gbpui/panels/application_policy/tables.py | 197 +++++++++++ gbpui/panels/application_policy/tabs.py | 255 ++++++++++++++ .../_add_policy_action.html | 25 ++ .../_add_policy_classifier.html | 25 ++ .../_policy_rule_set_details.html | 54 +++ .../_policyaction_details.html | 26 ++ .../_policyclassifier_details.html | 29 ++ .../_policyrules_details.html | 39 +++ .../_update_policy_action.html | 25 ++ .../_update_policy_classifier.html | 25 ++ .../_update_policy_rule.html | 25 ++ .../_update_policy_rule_set.html | 26 ++ .../addpolicy_rule_set.html | 11 + .../application_policy/addpolicyaction.html | 11 + .../addpolicyclassifier.html | 11 + .../application_policy/addpolicyrule.html | 11 + .../application_policy/details_tabs.html | 15 + gbpui/panels/application_policy/urls.py | 51 +++ gbpui/panels/application_policy/views.py | 199 +++++++++++ gbpui/panels/application_policy/workflows.py | 323 ++++++++++++++++++ 27 files changed, 1875 insertions(+) create mode 100644 gbpui/column_filters.py create mode 100644 gbpui/fields.py create mode 100644 gbpui/panels/__init__.py create mode 100644 gbpui/panels/application_policy/__init__.py create mode 100644 gbpui/panels/application_policy/forms.py create mode 100644 gbpui/panels/application_policy/panel.py create mode 100644 gbpui/panels/application_policy/tables.py create mode 100644 gbpui/panels/application_policy/tabs.py create mode 100644 gbpui/panels/application_policy/templates/application_policy/_add_policy_action.html create mode 100644 gbpui/panels/application_policy/templates/application_policy/_add_policy_classifier.html create mode 100644 gbpui/panels/application_policy/templates/application_policy/_policy_rule_set_details.html create mode 100644 gbpui/panels/application_policy/templates/application_policy/_policyaction_details.html create mode 100644 gbpui/panels/application_policy/templates/application_policy/_policyclassifier_details.html create mode 100644 gbpui/panels/application_policy/templates/application_policy/_policyrules_details.html create mode 100644 gbpui/panels/application_policy/templates/application_policy/_update_policy_action.html create mode 100644 gbpui/panels/application_policy/templates/application_policy/_update_policy_classifier.html create mode 100644 gbpui/panels/application_policy/templates/application_policy/_update_policy_rule.html create mode 100644 gbpui/panels/application_policy/templates/application_policy/_update_policy_rule_set.html create mode 100644 gbpui/panels/application_policy/templates/application_policy/addpolicy_rule_set.html create mode 100644 gbpui/panels/application_policy/templates/application_policy/addpolicyaction.html create mode 100644 gbpui/panels/application_policy/templates/application_policy/addpolicyclassifier.html create mode 100644 gbpui/panels/application_policy/templates/application_policy/addpolicyrule.html create mode 100644 gbpui/panels/application_policy/templates/application_policy/details_tabs.html create mode 100644 gbpui/panels/application_policy/urls.py create mode 100644 gbpui/panels/application_policy/views.py create mode 100644 gbpui/panels/application_policy/workflows.py diff --git a/gbpui/client.py b/gbpui/client.py index 1a937f7..396b977 100644 --- a/gbpui/client.py +++ b/gbpui/client.py @@ -12,6 +12,7 @@ # 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 import logging diff --git a/gbpui/column_filters.py b/gbpui/column_filters.py new file mode 100644 index 0000000..a617d68 --- /dev/null +++ b/gbpui/column_filters.py @@ -0,0 +1,132 @@ +# Copyright 2010-2011 OpenStack Foundation +# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. +# +# 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. + +import logging + +from django.core.urlresolvers import reverse +from django.utils.safestring import mark_safe + +from gbpui import client + +LOG = logging.getLogger(__name__) + + +def list_column_filter(items): + if len(items) == 0: + return "" + return items + + +def update_pruleset_attributes(request, prset): + rules = prset.policy_rules + url = "horizon:project:application_policy:policyruledetails" + value = ["") + value = "".join(value) + setattr(prset, 'policy_rules', mark_safe(value)) + return prset + + +def update_policy_target_attributes(request, pt): + url = "horizon:project:application_policy:policy_rule_set_details" + provided = pt.provided_policy_rule_sets + consumed = pt.consumed_policy_rule_sets + provided = [client.policy_rule_set_get(request, item) for item in provided] + consumed = [client.policy_rule_set_get(request, item) for item in consumed] + p = ["") + p = "".join(p) + c = ["") + c = "".join(c) + consumed = [item.name for item in consumed] + setattr(pt, 'provided_policy_rule_sets', mark_safe(p)) + setattr(pt, 'consumed_policy_rule_sets', mark_safe(c)) + l2url = "horizon:project:network_policy:l2policy_details" + if pt.l2_policy_id is not None: + policy = client.l2policy_get(request, pt.l2_policy_id) + u = reverse(l2url, {'l2policy_id': policy.id}) + atag = mark_safe( + "" + policy.name + "") + setattr(pt, 'l2_policy_id', atag) + return pt + + +def update_policyrule_attributes(request, prule): + url = "horizon:project:application_policy:policyclassifierdetails" + classifier_id = prule.policy_classifier_id + classifier = client. policyclassifier_get(request, classifier_id) + u = reverse(url, kwargs={'policyclassifier_id': classifier.id}) + tag = mark_safe("" + classifier.name + "") + setattr(prule, 'policy_classifier_id', tag) + return prule + + +def update_sc_spec_attributes(request, scspec): + nodes = scspec.nodes + nodes = [client.get_servicechain_node(request, item) for item in nodes] + value = [" \ + "] + for n in nodes: + value.append( + "") + value.append("") + value.append("
< /span>" + n.name + "(" + n.service_type + ")
") + setattr(scspec, 'nodes', mark_safe("".join(value))) + return scspec + + +def update_sc_instance_attributes(request, scinstance): + ptg_url = "horizon:project:policytargets:policy_targetdetails" + clsurl = "horizon:project:application_policy:policyclassifierdetails" + scspec_url = "horizon:project:network_services:sc_spec_details" + consumer_ptg = scinstance.consumer_ptg + provider_ptg = scinstance.provider_ptg + scspec = scinstance.servicechain_spec + classifier = scinstance.classifier + if consumer_ptg is not None: + ptg = client.policy_target_get(request, consumer_ptg) + u = reverse(ptg_url, kwargs={'policy_target_id': ptg.id}) + atag = "%s" % (u, ptg.name) + setattr(scinstance, 'consumer_ptg', mark_safe(atag)) + if provider_ptg is not None: + ptg = client.policy_target_get(request, consumer_ptg) + u = reverse(ptg_url, kwargs={'policy_target_id': ptg.id}) + atag = "%s" % (u, ptg.name) + setattr(scinstance, 'provider_ptg', mark_safe(atag)) + if classifier is not None: + cls = client.policyclassifier_get(request, classifier) + u = reverse(clsurl, kwargs={'policyclassifier_id': cls.id}) + atag = "%s" % (u, cls.name) + setattr(scinstance, 'classifier', mark_safe(atag)) + if scspec is not None: + sc = client.get_servicechain_spec(request, scspec) + u = reverse(scspec_url, kwargs={'scspec_id': sc.id}) + atag = "%s" % (u, sc.name) + setattr(scinstance, 'servicechain_spec', mark_safe(atag)) + return scinstance diff --git a/gbpui/fields.py b/gbpui/fields.py new file mode 100644 index 0000000..b197b5f --- /dev/null +++ b/gbpui/fields.py @@ -0,0 +1,65 @@ +# Copyright 2010-2011 OpenStack Foundation +# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. +# +# 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 django.core import urlresolvers +from django.forms import fields +from django.forms import widgets + + +class DynamicMultiSelectWidget(widgets.SelectMultiple): + + """A subclass of the ``Select`` widget which renders extra attributes for + use in callbacks to handle dynamic changes to the available choices. + """ + _data_add_url_attr = "data-add-item-url" + + def render(self, *args, **kwargs): + add_item_url = self.get_add_item_url() + if add_item_url is not None: + self.attrs[self._data_add_url_attr] = add_item_url + return super(DynamicMultiSelectWidget, self).render(*args, **kwargs) + + def get_add_item_url(self): + if callable(self.add_item_link): + return self.add_item_link() + try: + if self.add_item_link_args: + return urlresolvers.reverse(self.add_item_link, + args=self.add_item_link_args) + else: + return urlresolvers.reverse(self.add_item_link) + except urlresolvers.NoReverseMatch: + return self.add_item_link + + +class DynamicMultiChoiceField(fields.MultipleChoiceField): + + """A subclass of ``ChoiceField`` with additional properties that make + dynamically updating its elements easier. + + Notably, the field declaration takes an extra argument, ``add_item_link`` + which may be a string or callable defining the URL that should be used + for the "add" link associated with the field. + """ + widget = DynamicMultiSelectWidget + + def __init__(self, + add_item_link=None, + add_item_link_args=None, + *args, + **kwargs): + super(DynamicMultiChoiceField, self).__init__(*args, **kwargs) + self.widget.add_item_link = add_item_link + self.widget.add_item_link_args = add_item_link_args diff --git a/gbpui/panels/__init__.py b/gbpui/panels/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gbpui/panels/application_policy/__init__.py b/gbpui/panels/application_policy/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gbpui/panels/application_policy/forms.py b/gbpui/panels/application_policy/forms.py new file mode 100644 index 0000000..09445d9 --- /dev/null +++ b/gbpui/panels/application_policy/forms.py @@ -0,0 +1,274 @@ +# Copyright 2010-2011 OpenStack Foundation +# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. +# +# 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 django.core.urlresolvers import reverse +from django import http +from django.template.defaultfilters import filesizeformat # noqa +from django.utils.translation import ugettext_lazy as _ +from django.views.decorators.debug import sensitive_variables # noqa + +from horizon import exceptions +from horizon import forms +from horizon import messages + +from gbpui import client + +PROTOCOLS = [('tcp', _('TCP')), + ('udp', _('UDP')), + ('icmp', _('ICMP')), + ('http', _('HTTP')), + ('https', _('HTTPS')), + ('smtp', _('SMTP')), + ('dns', _('DNS')), + ('ftp', _('FTP')), + ('any', _('ANY')) + ] +DIRECTIONS = [('in', _('IN')), + ('out', _('OUT')), + ('bi', _('BI'))] +POLICY_ACTION_TYPES = [('allow', _('ALLOW')), + ('redirect', _('REDIRECT')), + ('copy', _('COPY')), + ('log', _('LOG')), + ('qos', _('QoS'))] + + +class UpdatePolicyRuleSetForm(forms.SelfHandlingForm): + name = forms.CharField(label=_("Name")) + description = forms.CharField(label=_("Description"), required=False) + rules = forms.MultipleChoiceField(label=_("Policy Rules"),) + + def __init__(self, request, *args, **kwargs): + super(UpdatePolicyRuleSetForm, self).__init__(request, *args, **kwargs) + rules = [] + try: + items = client.policyrule_list(request) + rules = [(p.id, p.name) for p in items] + policy_rule_set = client.policy_rule_set_get( + request, self.initial['policy_rule_set_id']) + if policy_rule_set: + self.fields['name'].initial = policy_rule_set.name + self.fields[ + 'description'].initial = policy_rule_set.description + existing = [item for item in policy_rule_set.policy_rules] + self.fields['rules'].initial = existing + except Exception: + exceptions.handle(request, _('Unable to retrieve policy rules')) + self.fields['rules'].choices = rules + + def handle(self, request, context): + try: + policy_rule_set_id = self.initial['policy_rule_set_id'] + client.policy_rule_set_update(request, + policy_rule_set_id, + name=context['name'], + description=context[ + 'description'], + policy_rules=context['rules'], + ) + messages.success(request, _('PolicyRuleSet successfully updated.')) + url = reverse('horizon:project:application_policy:index') + return http.HttpResponseRedirect(url) + except Exception: + redirect = reverse('horizon:project:policy_rule_sets:index') + exceptions.handle( + request, _("Unable to update policy_rule_set."), + redirect=redirect) + + +class AddPolicyActionForm(forms.SelfHandlingForm): + name = forms.CharField(label=_("Name")) + description = forms.CharField(label=_("Description"), + required=False) + action_type = forms.ChoiceField(label=_("Action"), + choices=POLICY_ACTION_TYPES, + widget=forms.Select(attrs={ + 'class': 'switchable', + 'data-slug': 'source' + })) + action_value = forms.ChoiceField(label=_("Action Value"), + required=False, + choices=[], + widget=forms.Select(attrs={ + 'class': 'switched', + 'data-switch-on': 'source', + 'data-source-redirect': + _('Action Value') + })) + + def __init__(self, request, *args, **kwargs): + super(AddPolicyActionForm, self).__init__(request, *args, **kwargs) + url = reverse('horizon:project:application_policy:index') + try: + sc_specs = client.servicechainspec_list(request, + tenant_id=request.user.tenant_id) + self.fields['action_value'].choices = \ + [(spec.id, + (spec.name if spec.name is not None else "") + ":" + spec.id) + for spec in sc_specs] + except Exception: + exceptions.handle( + request, _("Unable to retrieve action values."), redirect=url) + + def handle(self, request, context): + url = reverse('horizon:project:application_policy:index') + try: + if not context['action_value']: + del context['action_value'] + action = client.policyaction_create(request, **context) + messages.success(request, _('Policy Action successfully created.')) + return action + except Exception: + exceptions.handle( + request, _("Unable to create policy action."), redirect=url) + + +class UpdatePolicyActionForm(forms.SelfHandlingForm): + name = forms.CharField(label=_("Name")) + description = forms.CharField(label=_("Description"), required=False) + action_type = forms.ChoiceField(label=_("Action")) + action_value = forms.CharField(label=_("Action Value"), required=False) + + def __init__(self, request, *args, **kwargs): + super(UpdatePolicyActionForm, self).__init__(request, *args, **kwargs) + + try: + policyaction_id = self.initial['policyaction_id'] + pa = client.policyaction_get(request, policyaction_id) + self.fields['name'].initial = pa.name + self.fields['action_value'].initial = pa.action_value + self.fields['action_type'].initial = pa.action_type + except Exception: + pass + self.fields['action_type'].choices = POLICY_ACTION_TYPES + + def handle(self, request, context): + url = reverse('horizon:project:application_policy:index') + try: + # policyaction_id = self.initial['policyaction_id'] + messages.success(request, _('Policy Action successfully updated.')) + return http.HttpResponseRedirect(url) + except Exception: + exceptions.handle( + request, _("Unable to update policy action."), redirect=url) + + +class AddPolicyClassifierForm(forms.SelfHandlingForm): + name = forms.CharField(max_length=80, label=_("Name"), required=False) + protocol = forms.ChoiceField( + label=_("Protocol"), + choices=PROTOCOLS) + port_range = forms.CharField( + max_length=80, + label=_("Port/Range(min:max)"), + required=False) + direction = forms.ChoiceField( + label=_("Direction"), + choices=[('in', _('IN')), + ('out', _('OUT')), + ('bi', _('BI'))]) + + def __init__(self, request, *args, **kwargs): + super(AddPolicyClassifierForm, self).__init__(request, *args, **kwargs) + + def handle(self, request, context): + url = reverse('horizon:project:application_policy:index') + try: + classifier = client.policyclassifier_create(request, **context) + messages.success( + request, _('Policy Classifier successfully created.')) + return classifier + except Exception: + exceptions.handle( + request, _("Unable to create policy classifier."), + redirect=url) + + +class UpdatePolicyClassifierForm(forms.SelfHandlingForm): + name = forms.CharField(max_length=80, label=_("Name"), required=False) + description = forms.CharField(label=_("Description"), required=False) + protocol = forms.ChoiceField(label=_("Protocol"), choices=PROTOCOLS) + port_range = forms.CharField( + max_length=80, label=_("Port/Range(min:max)"), required=False) + direction = forms.ChoiceField(label=_("Direction"), choices=DIRECTIONS) + + def __init__(self, request, *args, **kwargs): + super(UpdatePolicyClassifierForm, self).__init__( + request, *args, **kwargs) + try: + policyclassifier_id = self.initial['policyclassifier_id'] + classifier = client.policyclassifier_get( + request, policyclassifier_id) + for item in ['name', 'description', + 'protocol', 'port_range', 'direction']: + self.fields[item].initial = getattr(classifier, item) + except Exception: + exceptions.handle( + request, _("Unable to retrive policy classifier details.")) + + def handle(self, request, context): + url = reverse('horizon:project:application_policy:index') + try: + policyclassifier_id = self.initial['policyclassifier_id'] + client.policyclassifier_update(self.request, + policyclassifier_id, context) + messages.success( + request, _('Policy classifier successfully updated.')) + return http.HttpResponseRedirect(url) + except Exception: + exceptions.handle( + request, _("Unable to update policy classifier."), + redirect=url) + + +class UpdatePolicyRuleForm(forms.SelfHandlingForm): + name = forms.CharField(max_length=80, label=_("Name"), required=False) + description = forms.CharField(label=_("Description"), required=False) + policy_classifier_id = forms.ChoiceField(label=_("Policy Classifier")) + policy_actions = forms.MultipleChoiceField(label=_("Policy Actions")) + + def __init__(self, request, *args, **kwargs): + super(UpdatePolicyRuleForm, self).__init__(request, *args, **kwargs) + try: + tenant_id = request.user.tenant_id + policyrule_id = self.initial['policyrule_id'] + rule = client.policyrule_get(request, policyrule_id) + for item in ['name', 'description', + 'policy_classifier_id', 'policy_actions']: + self.fields[item].initial = getattr(rule, item) + actions = client.policyaction_list(request, tenant_id=tenant_id) + action_list = [a.id for a in actions] + for action in actions: + action.set_id_as_name_if_empty() + actions = sorted(actions, key=lambda action: action.name) + action_list = [(a.id, a.name) for a in actions] + self.fields['policy_actions'].choices = action_list + classifiers = client.policyclassifier_list( + request, tenant_id=tenant_id) + classifier_list = [(c.id, c.name) for c in classifiers] + self.fields['policy_classifier_id'].choices = classifier_list + except Exception: + exceptions.handle( + request, _("Unable to retrive policy rule details.")) + + def handle(self, request, context): + url = reverse('horizon:project:application_policy:index') + try: + self.initial['policyrule_id'] + messages.success(request, _('Policy rule successfully updated.')) + return http.HttpResponseRedirect(url) + except Exception: + exceptions.handle( + request, _("Unable to update policy rule."), redirect=url) diff --git a/gbpui/panels/application_policy/panel.py b/gbpui/panels/application_policy/panel.py new file mode 100644 index 0000000..b550968 --- /dev/null +++ b/gbpui/panels/application_policy/panel.py @@ -0,0 +1,20 @@ +# 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 django.utils.translation import ugettext_lazy as _ + +import horizon + + +class ApplicationPolicy(horizon.Panel): + name = _("Application Policy") + slug = "application_policy" diff --git a/gbpui/panels/application_policy/tables.py b/gbpui/panels/application_policy/tables.py new file mode 100644 index 0000000..4a78fa3 --- /dev/null +++ b/gbpui/panels/application_policy/tables.py @@ -0,0 +1,197 @@ +# 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 django.core.urlresolvers import reverse +from django.utils.translation import ugettext_lazy as _ + +from horizon import tables + + +class AddAppPolicyLink(tables.LinkAction): + name = "addpolicy_rule_set" + verbose_name = _("Create Policy Rule Set") + url = "horizon:project:application_policy:addpolicy_rule_set" + classes = ("ajax-modal", "btn-addpolicy_rule_set",) + + +class UpdateAppPolicyLink(tables.LinkAction): + name = "updatepolicy_rule_set" + verbose_name = _("Edit") + classes = ("ajax-modal", 'edit_policy_rule_set') + + def get_link_url(self, policy_rule_set): + urlpath = "horizon:project:application_policy:updatepolicy_rule_set" + base_url = reverse(urlpath, kwargs={ + 'policy_rule_set_id': policy_rule_set.id}) + return base_url + + +class DeleteAppPolicyLink(tables.DeleteAction): + name = "deletepolicy_rule_set" + action_present = _("Delete") + action_past = _("Scheduled deletion of %(data_type)s") + data_type_singular = _("Policy Rule Set") + data_type_plural = _("Policy Rule Set") + + +class AddPolicyRuleLink(tables.LinkAction): + name = "addpolicyrules" + verbose_name = _("Create Policy-Rule") + url = "horizon:project:application_policy:addpolicyrule" + classes = ("ajax-modal", "btn-addpolicyrule",) + + +class UpdatePolicyRuleLink(tables.LinkAction): + name = "updatepolicyrule" + verbose_name = _("Edit PolicyRule") + classes = ("ajax-modal", "btn-update",) + + def get_link_url(self, policy_rule): + urlstring = "horizon:project:application_policy:updatepolicyrule" + base_url = reverse(urlstring, + kwargs={'policyrule_id': policy_rule.id}) + return base_url + + +class DeletePolicyRuleLink(tables.DeleteAction): + name = "deletepolicyrule" + action_present = _("Delete") + action_past = _("Scheduled deletion of %(data_type)s") + data_type_singular = _("PolicyRule") + data_type_plural = _("PolicyRules") + + +class AddPolicyClassifierLink(tables.LinkAction): + name = "addpolicyclassifiers" + verbose_name = _("Create Policy-Classifier") + url = "horizon:project:application_policy:addpolicyclassifier" + classes = ("ajax-modal", "btn-addpolicyclassifier",) + + +class UpdatePolicyClassifierLink(tables.LinkAction): + name = "updatepolicyclassifier" + verbose_name = _("Edit") + classes = ("ajax-modal", "btn-update",) + + def get_link_url(self, policy_classifier): + base_url = reverse( + "horizon:project:application_policy:updatepolicyclassifier", + kwargs={'policyclassifier_id': policy_classifier.id}) + return base_url + + +class DeletePolicyClassifierLink(tables.DeleteAction): + name = "deletepolicyclassifier" + action_present = _("Delete") + action_past = _("Scheduled deletion of %(data_type)s") + data_type_singular = _("PolicyClassifier") + data_type_plural = _("PolicyClassifiers") + + +class AddPolicyActionLink(tables.LinkAction): + name = "addpolicyactions" + verbose_name = _("Create Policy-Action") + url = "horizon:project:application_policy:addpolicyaction" + classes = ("ajax-modal", "btn-addpolicyaction",) + + +class UpdatePolicyActionLink(tables.LinkAction): + name = "updatepolicyaction" + verbose_name = _("Edit PolicyAction") + classes = ("ajax-modal", "btn-update",) + + def get_link_url(self, policy_action): + urlstring = "horizon:project:application_policy:updatepolicyaction" + base_url = reverse(urlstring, + kwargs={'policyaction_id': policy_action.id}) + return base_url + + +class DeletePolicyActionLink(tables.DeleteAction): + name = "deletepolicyaction" + action_present = _("Delete") + action_past = _("Scheduled deletion of %(data_type)s") + data_type_singular = _("PolicyAction") + data_type_plural = _("PolicyActions") + + +class ApplicationPoliciesTable(tables.DataTable): + name = tables.Column("name", + verbose_name=_("Name"), + link="horizon:project:application_policy:policy_rule_set_details") + description = tables.Column("description", + verbose_name=_("Description")) + policy_rules = tables.Column("policy_rules", + sortable=False, + verbose_name=_("Policy Rules")) + + class Meta: + name = "application_policies_table" + verbose_name = _("Policy Rule Set") + table_actions = (AddAppPolicyLink, DeleteAppPolicyLink) + row_actions = (UpdateAppPolicyLink, DeleteAppPolicyLink) + + +class PolicyRulesTable(tables.DataTable): + name = tables.Column("name", + verbose_name=_("Name"), + link="horizon:project:application_policy:policyruledetails") + description = tables.Column("description", + verbose_name=_("Description")) + enabled = tables.Column("enabled", + verbose_name=_("Enabled")) + policy_classifier = tables.Column("policy_classifier_id", + verbose_name=_("Policy Classifier")) + + class Meta: + name = "policyrulestable" + verbose_name = _("Policy Rules") + table_actions = (AddPolicyRuleLink, DeletePolicyRuleLink) + row_actions = (UpdatePolicyRuleLink, DeletePolicyRuleLink) + + +class PolicyClassifiersTable(tables.DataTable): + name = tables.Column("name", + verbose_name=_("Name"), + link="horizon:project:application_policy:policyclassifierdetails") + description = tables.Column("description", + verbose_name=_("Description")) + protocol = tables.Column("protocol", + verbose_name=_("Protocol")) + port_range = tables.Column("port_range", + verbose_name=_("Port Range")) + direction = tables.Column("direction", + verbose_name=_("Direction")) + + class Meta: + name = "policyclassifierstable" + verbose_name = _("Policy Classifiers") + table_actions = (AddPolicyClassifierLink, DeletePolicyClassifierLink) + row_actions = (UpdatePolicyClassifierLink, DeletePolicyClassifierLink) + + +class PolicyActionsTable(tables.DataTable): + name = tables.Column("name", + verbose_name=_("Name"), + link="horizon:project:application_policy:policyactiondetails") + description = tables.Column("description", + verbose_name=_("Description")) + action_type = tables.Column("action_type", + verbose_name=_("Type")) + action_value = tables.Column("action_value", + verbose_name=_("Value")) + + class Meta: + name = "policyactionstable" + verbose_name = _("Policy Actions") + table_actions = (AddPolicyActionLink, DeletePolicyActionLink) + row_actions = (UpdatePolicyActionLink, DeletePolicyActionLink) diff --git a/gbpui/panels/application_policy/tabs.py b/gbpui/panels/application_policy/tabs.py new file mode 100644 index 0000000..8e457be --- /dev/null +++ b/gbpui/panels/application_policy/tabs.py @@ -0,0 +1,255 @@ +# 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 django.core.urlresolvers import reverse_lazy +from django.utils.translation import ugettext_lazy as _ + +from horizon import exceptions +from horizon import tabs + +from gbpui import client +from gbpui import column_filters as gfilters + +import tables + +PolicyRulesTable = tables.PolicyRulesTable +PolicyClassifiersTable = tables.PolicyClassifiersTable +PolicyActionsTable = tables.PolicyActionsTable + + +class PolicyActionsTab(tabs.TableTab): + table_classes = (PolicyActionsTable,) + name = _("Policy-Actions") + slug = "policyactions" + template_name = "horizon/common/_detail_table.html" + + def get_policyactionstable_data(self): + try: + tenant_id = self.request.user.tenant_id + actions = client.policyaction_list( + self.tab_group.request, + tenant_id=tenant_id) + except Exception: + actions = [] + exceptions.handle(self.tab_group.request, + _('Unable to retrieve actions list.')) + + for action in actions: + action.set_id_as_name_if_empty() + + return actions + + +class PolicyClassifiersTab(tabs.TableTab): + table_classes = (PolicyClassifiersTable,) + name = _("Policy-Classifiers") + slug = "policyclassifiers" + template_name = "horizon/common/_detail_table.html" + + def get_policyclassifierstable_data(self): + try: + tenant_id = self.request.user.tenant_id + classifiers = client.policyclassifier_list( + self.tab_group.request, + tenant_id=tenant_id) + except Exception: + classifiers = [] + exceptions.handle(self.tab_group.request, + _('Unable to retrieve classifier list.')) + + for classifier in classifiers: + classifier.set_id_as_name_if_empty() + + return classifiers + + +class PolicyRulesTab(tabs.TableTab): + table_classes = (PolicyRulesTable,) + name = _("Policy-Rules") + slug = "policyrules" + template_name = "horizon/common/_detail_table.html" + + def get_policyrulestable_data(self): + try: + tenant_id = self.request.user.tenant_id + policy_rules = client.policyrule_list( + self.tab_group.request, + tenant_id=tenant_id) + policy_rules = [gfilters.update_policyrule_attributes( + self.request, item) for item in policy_rules] + except Exception: + policy_rules = [] + exceptions.handle(self.tab_group.request, + _('Unable to retrieve policy-rule list.')) + + for rule in policy_rules: + rule.set_id_as_name_if_empty() + + return policy_rules + + +class ApplicationPoliciesTab(tabs.TableTab): + table_classes = (tables.ApplicationPoliciesTable,) + name = _("Policy Rule Set") + slug = "application_policies" + template_name = "horizon/common/_detail_table.html" + + def get_application_policies_table_data(self): + policy_rule_sets = [] + try: + tenant_id = self.request.user.tenant_id + policy_rule_sets = client.policy_rule_set_list( + self.tab_group.request, tenant_id=tenant_id) + policy_rule_sets = [gfilters.update_pruleset_attributes( + self.request, item) for item in policy_rule_sets] + except Exception: + exceptions.handle( + self.tab_group.request, + _('Unable to retrieve policy rule set list.')) + + for policy_rule_set in policy_rule_sets: + policy_rule_set.set_id_as_name_if_empty() + return policy_rule_sets + + +class ApplicationPoliciesTabs(tabs.TabGroup): + slug = "application_policies_tabs" + tabs = (ApplicationPoliciesTab, + PolicyRulesTab, + PolicyClassifiersTab, + PolicyActionsTab) + sticky = True + + +class ContractDetailsTab(tabs.Tab): + name = _("Policy Rule Set Details") + slug = "policy_rule_setdetails" + template_name = "project/application_policy/_policy_rule_set_details.html" + failure_url = reverse_lazy('horizon:project:policy_rule_set:index') + + def get_context_data(self, request): + cid = self.tab_group.kwargs['policy_rule_set_id'] + try: + policy_rule_set = client.policy_rule_set_get(request, cid) + rules = client.policyrule_list( + request, policy_rule_set_id=policy_rule_set.id) + rules = [ + item for item in rules if item.id in + policy_rule_set.policy_rules] + rules_with_details = [] + for rule in rules: + r = {} + r['name'] = rule.name + r['id'] = rule.id + action_list = [] + for aid in rule.policy_actions: + action = client.policyaction_get(request, aid) + if action.action_value: + action_list.append( + str(action.action_type) + ":" + + str(action.action_value)) + else: + action_list.append(str(action.action_type)) + r['actions'] = action_list + r['classifier'] = client.policyclassifier_get( + request, rule.policy_classifier_id) + rules_with_details.append(r) + except Exception: + exceptions.handle(request, + _('Unable to retrieve policy_rule_set details.'), + redirect=self.failure_url) + return {'policy_rule_set': policy_rule_set, + 'rules_with_details': rules_with_details} + + +class ContractDetailsTabs(tabs.TabGroup): + slug = "policy_rule_settabs" + tabs = (ContractDetailsTab,) + + +class PolicyRulesDetailsTab(tabs.Tab): + name = _("PolicyRule Details") + slug = "policyruledetails" + template_name = "project/application_policy/_policyrules_details.html" + failure_url = reverse_lazy('horizon:project:policyrule:index') + + def get_context_data(self, request): + ruleid = self.tab_group.kwargs['policyrule_id'] + actions = [] + classifiers = [] + try: + policyrule = client.policyrule_get(request, ruleid) + actions = client.policyaction_list(request, policyrule_id=ruleid) + actions = [ + item for item in actions if item.id in + policyrule.policy_actions] + classifiers = client.policyclassifier_list( + request, policyrule_id=ruleid) + classifiers = [ + item for item in classifiers if + item.id == policyrule.policy_classifier_id] + except Exception: + exceptions.handle(request, + _('Unable to retrieve policyrule details.'), + redirect=self.failure_url) + return {'policyrule': policyrule, + 'classifiers': classifiers, + 'actions': actions} + + +class PolicyRuleDetailsTabs(tabs.TabGroup): + slug = "policyruletabs" + tabs = (PolicyRulesDetailsTab,) + + +class PolicyClassifierDetailsTab(tabs.Tab): + name = _("Policyclassifier Details") + slug = "policyclassifierdetails" + template_name = "project/application_policy/_policyclassifier_details.html" + failure_url = reverse_lazy('horizon:project:policy_rule_set:index') + + def get_context_data(self, request): + pcid = self.tab_group.kwargs['policyclassifier_id'] + try: + policyclassifier = client.policyclassifier_get(request, pcid) + except Exception: + exceptions.handle(request, + _('Unable to retrieve policy_rule_set details.'), + redirect=self.failure_url) + return {'policyclassifier': policyclassifier} + + +class PolicyClassifierDetailsTabs(tabs.TabGroup): + slug = "policyclassifiertabs" + tabs = (PolicyClassifierDetailsTab,) + + +class PolicyActionDetailsTab(tabs.Tab): + name = _("PolicyAction Details") + slug = "policyactiondetails" + template_name = "project/application_policy/_policyaction_details.html" + failure_url = reverse_lazy('horizon:project:policy_rule_set:index') + + def get_context_data(self, request): + paid = self.tab_group.kwargs['policyaction_id'] + try: + policyaction = client.policyaction_get(request, paid) + except Exception: + exceptions.handle(request, + _('Unable to retrieve policyaction details.'), + redirect=self.failure_url) + return {'policyaction': policyaction} + + +class PolicyActionDetailsTabs(tabs.TabGroup): + slug = "policyactiontabs" + tabs = (PolicyActionDetailsTab,) diff --git a/gbpui/panels/application_policy/templates/application_policy/_add_policy_action.html b/gbpui/panels/application_policy/templates/application_policy/_add_policy_action.html new file mode 100644 index 0000000..f07ae3d --- /dev/null +++ b/gbpui/panels/application_policy/templates/application_policy/_add_policy_action.html @@ -0,0 +1,25 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} +{% load url from future %} + +{% block form_id %}add_policy_action_form{% endblock %} +{% block form_action %}{% url "horizon:project:application_policy:addpolicyaction" %}{% endblock %} + +{% block modal_id %}add_policy_action_modal{% endblock %} +{% block modal-header %}{% trans "Create Policy Action" %}{% endblock %} + +{% block modal-body %} +
+
+ {% include "horizon/common/_form_fields.html" %} +
+
+
+

{% trans "Description" %}:

+
+{% endblock %} + +{% block modal-footer %} + + {% trans "Cancel" %} +{% endblock %} diff --git a/gbpui/panels/application_policy/templates/application_policy/_add_policy_classifier.html b/gbpui/panels/application_policy/templates/application_policy/_add_policy_classifier.html new file mode 100644 index 0000000..d0037bb --- /dev/null +++ b/gbpui/panels/application_policy/templates/application_policy/_add_policy_classifier.html @@ -0,0 +1,25 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} +{% load url from future %} + +{% block form_id %}add_policy_classifier_form{% endblock %} +{% block form_action %}{% url "horizon:project:application_policy:addpolicyclassifier" %}{% endblock %} + +{% block modal_id %}add_policy_classifier_modal{% endblock %} +{% block modal-header %}{% trans "Create Policy Classifier" %}{% endblock %} + +{% block modal-body %} +
+
+ {% include "horizon/common/_form_fields.html" %} +
+
+
+

{% trans "Description" %}:

+
+{% endblock %} + +{% block modal-footer %} + + {% trans "Cancel" %} +{% endblock %} diff --git a/gbpui/panels/application_policy/templates/application_policy/_policy_rule_set_details.html b/gbpui/panels/application_policy/templates/application_policy/_policy_rule_set_details.html new file mode 100644 index 0000000..29147cb --- /dev/null +++ b/gbpui/panels/application_policy/templates/application_policy/_policy_rule_set_details.html @@ -0,0 +1,54 @@ +{% load i18n sizeformat parse_date %} +{% load url from future %} +
+
+
+
{% trans "Name" %}
+
{{ contract.name|default:_("-") }}
+ +
{% trans "Description" %}
+
{{ contract.description|default:_("-") }}
+ +
{% trans "ID" %}
+
{{ contract.id }}
+ +
{% trans "Project ID" %}
+
{{ contract.tenant_id }}
+
+
+{% if contract.policy_rules %} +
+
{% trans "Policy Rules" %}
+
+ + + + + + + + + + + {% for rule in rules_with_details %} + + + + + + + + + {% endfor %} + +
NameIDProtocolPortDirectionAction
{{rule.name|default:_("-") }}{{rule.id}}{{rule.classifier.protocol}}{{rule.classifier.port_range}}{{rule.classifier.direction}}  + {% for a in rule.actions %} + {{a}}
+ {% endfor %} +
+
+
+{% else %} +{% trans "-" %} +{% endif %} + diff --git a/gbpui/panels/application_policy/templates/application_policy/_policyaction_details.html b/gbpui/panels/application_policy/templates/application_policy/_policyaction_details.html new file mode 100644 index 0000000..da05417 --- /dev/null +++ b/gbpui/panels/application_policy/templates/application_policy/_policyaction_details.html @@ -0,0 +1,26 @@ +{% load i18n sizeformat parse_date %} +{% load url from future %} + +
+
+
+
{% trans "Name" %}
+
{{ policyaction.name|default:_("-") }}
+ +
{% trans "Description" %}
+
{{ policyaction.description|default:_("-") }}
+ +
{% trans "ID" %}
+
{{ policyaction.id }}
+ +
{% trans "Project ID" %}
+
{{ policyaction.tenant_id }}
+ +
{% trans "Action Value" %}
+
{{ policyaction.action_value|default:_("-") }}
+ +
{% trans "Action Type" %}
+
{{ policyaction.action_type|default:_("-") }}
+ +
+
diff --git a/gbpui/panels/application_policy/templates/application_policy/_policyclassifier_details.html b/gbpui/panels/application_policy/templates/application_policy/_policyclassifier_details.html new file mode 100644 index 0000000..08f4313 --- /dev/null +++ b/gbpui/panels/application_policy/templates/application_policy/_policyclassifier_details.html @@ -0,0 +1,29 @@ +{% load i18n sizeformat parse_date %} +{% load url from future %} + +
+
+
+
{% trans "Name" %}
+
{{ policyclassifier.name|default:_("-") }}
+ +
{% trans "Description" %}
+
{{ policyclassifier.description|default:_("-") }}
+ +
{% trans "ID" %}
+
{{ policyclassifier.id }}
+ +
{% trans "Project ID" %}
+
{{ policyclassifier.tenant_id }}
+ +
{% trans "Direction" %}
+
{{ policyclassifier.direction|default:_("-") }}
+ +
{% trans "Protocol" %}
+
{{ policyclassifier.protocol|default:_("-") }}
+ +
{% trans "Port Range" %}
+
{{ policyclassifier.port_range }}
+ +
+
diff --git a/gbpui/panels/application_policy/templates/application_policy/_policyrules_details.html b/gbpui/panels/application_policy/templates/application_policy/_policyrules_details.html new file mode 100644 index 0000000..f24e791 --- /dev/null +++ b/gbpui/panels/application_policy/templates/application_policy/_policyrules_details.html @@ -0,0 +1,39 @@ +{% load i18n sizeformat parse_date %} +{% load url from future %} + +
+
+
+
{% trans "Name" %}
+
{{ policyrule.name|default:_("-") }}
+ +
{% trans "Description" %}
+
{{ policyrule.description|default:_("-") }}
+ +
{% trans "ID" %}
+
{{ policyrule.id }}
+ +
{% trans "Project ID" %}
+
{{ policyrule.tenant_id }}
+ +
{% trans "Enabled" %}
+
{{ policyrule.enabled|default:_("-") }}
+ +
{% trans "Policy Actions" %}
+
+ {% for action in actions%} + {{action.name}} + {% url 'horizon:project:application_policy:policyactiondetails' action as action_url %} + {{ action.position }} : {{ action.id }}
+ {% endfor %} +
+
{% trans "Policy Classifier" %}
+
+ {% for classifier in classifiers %} + {{classifier.name}}: + {% url 'horizon:project:application_policy:policyclassifierdetails' classifier.id as classifier_url %} + {{ classifier.id }}
+ {% endfor %} +
+
+
diff --git a/gbpui/panels/application_policy/templates/application_policy/_update_policy_action.html b/gbpui/panels/application_policy/templates/application_policy/_update_policy_action.html new file mode 100644 index 0000000..ba299ef --- /dev/null +++ b/gbpui/panels/application_policy/templates/application_policy/_update_policy_action.html @@ -0,0 +1,25 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} +{% load url from future %} + +{% block form_id %}update_policy_action_form{% endblock %} +{% block form_action %}{% url "horizon:project:application_policy:updatepolicyaction" policyaction_id %}{% endblock %} + +{% block modal_id %}update_policy_action_modal{% endblock %} +{% block modal-header %}{% trans "Edit Policy Action" %}{% endblock %} + +{% block modal-body %} +
+
+ {% include "horizon/common/_form_fields.html" %} +
+
+
+

{% trans "Description" %}:

+
+{% endblock %} + +{% block modal-footer %} + + {% trans "Cancel" %} +{% endblock %} diff --git a/gbpui/panels/application_policy/templates/application_policy/_update_policy_classifier.html b/gbpui/panels/application_policy/templates/application_policy/_update_policy_classifier.html new file mode 100644 index 0000000..b5d40fe --- /dev/null +++ b/gbpui/panels/application_policy/templates/application_policy/_update_policy_classifier.html @@ -0,0 +1,25 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} +{% load url from future %} + +{% block form_id %}update_policy_classifier_form{% endblock %} +{% block form_action %}{% url "horizon:project:application_policy:updatepolicyclassifier" policyclassifier_id %}{% endblock %} + +{% block modal_id %}update_policy_classifier_modal{% endblock %} +{% block modal-header %}{% trans "Edit Policy Classifier" %}{% endblock %} + +{% block modal-body %} +
+
+ {% include "horizon/common/_form_fields.html" %} +
+
+
+

{% trans "Description" %}:

+
+{% endblock %} + +{% block modal-footer %} + + {% trans "Cancel" %} +{% endblock %} diff --git a/gbpui/panels/application_policy/templates/application_policy/_update_policy_rule.html b/gbpui/panels/application_policy/templates/application_policy/_update_policy_rule.html new file mode 100644 index 0000000..4756a68 --- /dev/null +++ b/gbpui/panels/application_policy/templates/application_policy/_update_policy_rule.html @@ -0,0 +1,25 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} +{% load url from future %} + +{% block form_id %}update_policy_rule_form{% endblock %} +{% block form_action %}{% url "horizon:project:application_policy:updatepolicyrule" policyrule_id %}{% endblock %} + +{% block modal_id %}update_policy_rule_modal{% endblock %} +{% block modal-header %}{% trans "Edit Policy Rule" %}{% endblock %} + +{% block modal-body %} +
+
+ {% include "horizon/common/_form_fields.html" %} +
+
+
+

{% trans "Description" %}:

+
+{% endblock %} + +{% block modal-footer %} + + {% trans "Cancel" %} +{% endblock %} diff --git a/gbpui/panels/application_policy/templates/application_policy/_update_policy_rule_set.html b/gbpui/panels/application_policy/templates/application_policy/_update_policy_rule_set.html new file mode 100644 index 0000000..3a3e4cd --- /dev/null +++ b/gbpui/panels/application_policy/templates/application_policy/_update_policy_rule_set.html @@ -0,0 +1,26 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} +{% load url from future %} + +{% block form_id %}update_policy_rule_set_form{% endblock %} +{% block form_action %}{% url "horizon:project:application_policy:updatepolicy_rule_set" policy_rule_set_id %}{% endblock %} + +{% block modal_id %}update_policy_rule_set_modal{% endblock %} +{% block modal-header %}{% trans "Edit Policy Rule Set" %}{% endblock %} + +{% block modal-body %} +
+
+ {% include "horizon/common/_form_fields.html" %} +
+
+
+

{% trans "Description" %}:

+

{% trans "Select one or multiple rules by pressing Ctrl" %}

+
+{% endblock %} + +{% block modal-footer %} + + {% trans "Cancel" %} +{% endblock %} diff --git a/gbpui/panels/application_policy/templates/application_policy/addpolicy_rule_set.html b/gbpui/panels/application_policy/templates/application_policy/addpolicy_rule_set.html new file mode 100644 index 0000000..b25277a --- /dev/null +++ b/gbpui/panels/application_policy/templates/application_policy/addpolicy_rule_set.html @@ -0,0 +1,11 @@ +{% extends 'base.html' %} +{% load i18n %} +{% block title %}{% trans "Create Policy Rule Set" %}{% endblock %} + +{% block page_header %} + {% include "horizon/common/_page_header.html" with title=_("Create Policy Rule Set") %} +{% endblock page_header %} + +{% block main %} + {% include 'horizon/common/_workflow.html' %} +{% endblock %} diff --git a/gbpui/panels/application_policy/templates/application_policy/addpolicyaction.html b/gbpui/panels/application_policy/templates/application_policy/addpolicyaction.html new file mode 100644 index 0000000..2834cc1 --- /dev/null +++ b/gbpui/panels/application_policy/templates/application_policy/addpolicyaction.html @@ -0,0 +1,11 @@ +{% extends 'base.html' %} +{% load i18n %} +{% block title %}{% trans "Create New Action" %}{% endblock %} + +{% block page_header %} + {% include "horizon/common/_page_header.html" with title=_("Create New Action") %} +{% endblock page_header %} + +{% block main %} + {% include 'horizon/common/_workflow.html' %} +{% endblock %} diff --git a/gbpui/panels/application_policy/templates/application_policy/addpolicyclassifier.html b/gbpui/panels/application_policy/templates/application_policy/addpolicyclassifier.html new file mode 100644 index 0000000..4e7492c --- /dev/null +++ b/gbpui/panels/application_policy/templates/application_policy/addpolicyclassifier.html @@ -0,0 +1,11 @@ +{% extends 'base.html' %} +{% load i18n %} +{% block title %}{% trans "Create New Classifier" %}{% endblock %} + +{% block page_header %} + {% include "horizon/common/_page_header.html" with title=_("Create New Classifier") %} +{% endblock page_header %} + +{% block main %} + {% include 'horizon/common/_workflow.html' %} +{% endblock %} diff --git a/gbpui/panels/application_policy/templates/application_policy/addpolicyrule.html b/gbpui/panels/application_policy/templates/application_policy/addpolicyrule.html new file mode 100644 index 0000000..23148c2 --- /dev/null +++ b/gbpui/panels/application_policy/templates/application_policy/addpolicyrule.html @@ -0,0 +1,11 @@ +{% extends 'base.html' %} +{% load i18n %} +{% block title %}{% trans "Create New Policy Rule Set" %}{% endblock %} + +{% block page_header %} + {% include "horizon/common/_page_header.html" with title=_("Create New Policy Rule Set") %} +{% endblock page_header %} + +{% block main %} + {% include 'horizon/common/_workflow.html' %} +{% endblock %} diff --git a/gbpui/panels/application_policy/templates/application_policy/details_tabs.html b/gbpui/panels/application_policy/templates/application_policy/details_tabs.html new file mode 100644 index 0000000..32a19a5 --- /dev/null +++ b/gbpui/panels/application_policy/templates/application_policy/details_tabs.html @@ -0,0 +1,15 @@ +{% extends 'base.html' %} +{% load i18n %} +{% block title %}{% trans "Application Policies" %}{% endblock %} + +{% block page_header %} + {% include "horizon/common/_page_header.html" with title=_("Application Policies") %} +{% endblock page_header %} + +{% block main %} +
+
+ {{ tab_group.render }} +
+
+{% endblock %} diff --git a/gbpui/panels/application_policy/urls.py b/gbpui/panels/application_policy/urls.py new file mode 100644 index 0000000..838b715 --- /dev/null +++ b/gbpui/panels/application_policy/urls.py @@ -0,0 +1,51 @@ +# 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 django.conf.urls import patterns # noqa +from django.conf.urls import url # noqa + +import views + +urlpatterns = patterns( + '', + url(r'^$', views.IndexView.as_view(), name='index'), + url(r'^addpolicy_rule_set$', views.AddPolicyRuleSetView.as_view(), + name='addpolicy_rule_set'), + url(r'^addpolicyrule$', views.AddPolicyRuleView.as_view(), + name='addpolicyrule'), + url(r'^addpolicyclassifier$', views.AddPolicyClassifierView.as_view(), + name='addpolicyclassifier'), + url(r'^addpolicyaction$', views.AddPolicyActionView.as_view(), + name='addpolicyaction'), + url(r'^updatepolicy_rule_set/(?P[^/]+)/$', + views.UpdatePolicyRuleSetView.as_view(), name='updatepolicy_rule_set'), + url(r'^updatepolicyrule/(?P[^/]+)/$', + views.UpdatePolicyRuleView.as_view(), name='updatepolicyrule'), + url(r'^updatepolicyclassifier/(?P[^/]+)/$', + views.UpdatePolicyClassifierView.as_view(), + name='updatepolicyclassifier'), + url(r'^updatepolicyaction/(?P[^/]+)/$', + views.UpdatePolicyActionView.as_view(), + name='updatepolicyaction'), + url(r'^policyrule/(?P[^/]+)/$', + views.PolicyRuleDetailsView.as_view(), name='policyruledetails'), + url(r'^policyclassifier/(?P[^/]+)/$', + views.PolicyClassifierDetailsView.as_view(), + name='policyclassifierdetails'), + url(r'^policyaction/(?P[^/]+)/$', + views.PolicyActionDetailsView.as_view(), + name='policyactiondetails'), + url(r'^policy_rule_set/(?P[^/]+)/$', + views.PolicyRuleSetDetailsView.as_view(), + name='policy_rule_set_details'), +) diff --git a/gbpui/panels/application_policy/views.py b/gbpui/panels/application_policy/views.py new file mode 100644 index 0000000..1795b0e --- /dev/null +++ b/gbpui/panels/application_policy/views.py @@ -0,0 +1,199 @@ +# 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. + +import re + +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext_lazy as _ + +from horizon import exceptions +from horizon import forms +from horizon import messages +from horizon import tabs +from horizon import workflows + +from gbpui import client + +import forms as policy_rule_set_forms +import tabs as policy_rule_set_tabs +import workflows as policy_rule_set_workflows + +PolicyRuleSetTabs = policy_rule_set_tabs.ApplicationPoliciesTabs +PolicyRuleSetDetailsTabs = policy_rule_set_tabs.ContractDetailsTabs +PolicyRuleDetailsTabs = policy_rule_set_tabs.PolicyRuleDetailsTabs +PolicyClassifierDetailsTabs = policy_rule_set_tabs.PolicyClassifierDetailsTabs +PolicyActionDetailsTabs = policy_rule_set_tabs.PolicyActionDetailsTabs +AddPolicyRuleSet = policy_rule_set_workflows.AddContract +AddPolicyRule = policy_rule_set_workflows.AddPolicyRule +AddPolicyClassifier = policy_rule_set_workflows.AddPolicyClassifier + + +class IndexView(tabs.TabView): + tab_group_class = (PolicyRuleSetTabs) + template_name = 'project/application_policy/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 == 'policyaction': + for obj_id in obj_ids: + try: + client.policyaction_delete(request, obj_id) + messages.success(request, _('Deleted action %s') % obj_id) + except Exception as e: + exceptions.handle(request, + _('Unable to delete action. %s') % e) + if obj_type == 'policyclassifier': + for obj_id in obj_ids: + try: + client.policyclassifier_delete(request, obj_id) + messages.success( + request, _('Deleted classifer %s') % obj_id) + except Exception as e: + exceptions.handle(request, + _('Unable to delete classifier. %s') % e) + if obj_type == 'policyrule': + for obj_id in obj_ids: + try: + client.policyrule_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_rule_set': + for obj_id in obj_ids: + try: + client.policy_rule_set_delete(request, obj_id) + messages.success(request, + _('Deleted rule %s') % obj_id) + except Exception as e: + exceptions.handle(request, + _('Unabled to delete policy_rule_set. %s') % e) + + return self.get(request, *args, **kwargs) + + +class AddPolicyRuleSetView(workflows.WorkflowView): + workflow_class = AddPolicyRuleSet + template_name = "project/application_policy/addpolicy_rule_set.html" + + def get_object_id(self, policy_rule_set): + return [policy_rule_set.id] + + +class UpdatePolicyRuleSetView(forms.ModalFormView): + form_class = policy_rule_set_forms.UpdatePolicyRuleSetForm + template_name = 'project/application_policy/update_policy_rule_set.html' + + def get_context_data(self, **kwargs): + context = super( + UpdatePolicyRuleSetView, self).get_context_data(**kwargs) + context['policy_rule_set_id'] = self.kwargs['policy_rule_set_id'] + return context + + def get_initial(self): + return {'policy_rule_set_id': self.kwargs['policy_rule_set_id']} + + +class AddPolicyRuleView(workflows.WorkflowView): + workflow_class = AddPolicyRule + template_name = "project/application_policy/addpolicyrule.html" + + def get_object_id(self, rule): + return [rule.id] + + +class AddPolicyClassifierView(forms.ModalFormView): + form_class = policy_rule_set_forms.AddPolicyClassifierForm + template_name = "project/application_policy/add_policy_classifier.html" + + def get_success_url(self): + return reverse('horizon:project:application_policy:index') + + def get_object_id(self, classifier): + return [classifier.id] + + +class AddPolicyActionView(forms.ModalFormView): + form_class = policy_rule_set_forms.AddPolicyActionForm + template_name = "project/application_policy/add_policy_action.html" + + def get_success_url(self): + return reverse('horizon:project:application_policy:index') + + def get_object_id(self, policyaction): + return [policyaction.id] + + +class UpdatePolicyActionView(forms.ModalFormView): + form_class = policy_rule_set_forms.UpdatePolicyActionForm + template_name = "project/application_policy/update_policy_action.html" + + def get_context_data(self, **kwargs): + context = super( + UpdatePolicyActionView, self).get_context_data(**kwargs) + context['policyaction_id'] = self.kwargs['policyaction_id'] + return context + + def get_initial(self): + return {'policyaction_id': self.kwargs['policyaction_id']} + + +class PolicyRuleSetDetailsView(tabs.TabView): + tab_group_class = (PolicyRuleSetDetailsTabs) + template_name = 'project/application_policy/details_tabs.html' + + +class PolicyRuleDetailsView(tabs.TabView): + tab_group_class = (PolicyRuleDetailsTabs) + template_name = 'project/application_policy/details_tabs.html' + + +class UpdatePolicyRuleView(forms.ModalFormView): + form_class = policy_rule_set_forms.UpdatePolicyRuleForm + template_name = "project/application_policy/update_policy_rule.html" + + def get_context_data(self, **kwargs): + context = super(UpdatePolicyRuleView, self).get_context_data(**kwargs) + context['policyrule_id'] = self.kwargs['policyrule_id'] + return context + + def get_initial(self): + return {'policyrule_id': self.kwargs['policyrule_id']} + + +class PolicyClassifierDetailsView(tabs.TabView): + tab_group_class = (PolicyClassifierDetailsTabs) + template_name = 'project/application_policy/details_tabs.html' + + +class UpdatePolicyClassifierView(forms.ModalFormView): + form_class = policy_rule_set_forms.UpdatePolicyClassifierForm + template_name = "project/application_policy/update_policy_classifier.html" + + def get_context_data(self, **kwargs): + context = super( + UpdatePolicyClassifierView, self).get_context_data(**kwargs) + context['policyclassifier_id'] = self.kwargs['policyclassifier_id'] + return context + + def get_initial(self): + return {'policyclassifier_id': self.kwargs['policyclassifier_id']} + + +class PolicyActionDetailsView(tabs.TabView): + tab_group_class = (PolicyActionDetailsTabs) + template_name = 'project/application_policy/details_tabs.html' diff --git a/gbpui/panels/application_policy/workflows.py b/gbpui/panels/application_policy/workflows.py new file mode 100644 index 0000000..78779e8 --- /dev/null +++ b/gbpui/panels/application_policy/workflows.py @@ -0,0 +1,323 @@ +# 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 django.core.urlresolvers import reverse +from django.utils.translation import ugettext_lazy as _ + +from horizon import exceptions +from horizon import forms +from horizon import workflows + +from gbpui import client +from gbpui import fields + +ADD_POLICY_ACTION_URL = "horizon:project:application_policy:addpolicyaction" +ADD_POLICY_CLASSIFIER_URL = "horizon:project:application_policy:\ + addpolicyclassifier" +ADD_POLICY_RULE_URL = "horizon:project:application_policy:addpolicyrule" + + +class SelectPolicyRuleAction(workflows.Action): + policy_rules = fields.DynamicMultiChoiceField( + label=_("Policy Rules"), + required=False, + add_item_link=ADD_POLICY_RULE_URL, + help_text=_("Create a policy rule set with selected rules.")) + + class Meta: + name = _("Rules") + help_text = _("Select policy rules for your policy rule set.") + + def populate_policy_rules_choices(self, request, context): + try: + tenant_id = self.request.user.tenant_id + rules = client.policyrule_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] + except Exception as e: + rule_list = [] + exceptions.handle(request, + _('Unable to retrieve rules (%(error)s).') % { + 'error': str(e)}) + return rule_list + + +class SelectPolicyRuleStep(workflows.Step): + action_class = SelectPolicyRuleAction + contributes = ("policy_rules",) + + def contribute(self, data, context): + if data: + rules = self.workflow.request.POST.getlist("policy_rules") + if rules: + rules = [r for r in rules if r != ''] + context['policy_rules'] = rules + return context + + +class AddContractAction(workflows.Action): + name = forms.CharField(max_length=80, + label=_("Name"), + required=False) + description = forms.CharField(max_length=80, + label=_("Description"), + required=False) + + def __init__(self, request, *args, **kwargs): + super(AddContractAction, self).__init__(request, *args, **kwargs) + + class Meta: + name = _("Create Policy Rule Set") + help_text = _("Create a new Policy Rule Set") + + +class AddContractStep(workflows.Step): + action_class = AddContractAction + contributes = ("name", "description") + + def contribute(self, data, context): + context = super(AddContractStep, self).contribute(data, context) + return context + + +class AddContract(workflows.Workflow): + slug = "addpolicy_rule_set" + name = _("Create Policy Rule Set") + finalize_button_name = _("Create") + success_message = _('Created Policy Rule Set "%s".') + failure_message = _('Unable to create Policy Rule Set "%s".') + default_steps = (AddContractStep, + SelectPolicyRuleStep) + wizard = True + + def get_success_url(self): + return reverse("horizon:project:application_policy:index") + + def format_status_message(self, message): + return message % self.context.get('name') + + def _create_policy_rule_set(self, request, context): + try: + return client.policy_rule_set_create(request, **context) + except Exception as e: + msg = self.format_status_message(self.failure_message) + str(e) + exceptions.handle(request, msg) + return False + + def handle(self, request, context): + policy_rule_set = self._create_policy_rule_set(request, context) + self.object = policy_rule_set + return policy_rule_set + + +class SelectPolicyClassifierAction(workflows.Action): + classifier = forms.DynamicChoiceField( + label=_("Policy Classifier"), + required=False, + help_text=_("Create a policy with selected classifier."), + add_item_link=ADD_POLICY_CLASSIFIER_URL) + + class Meta: + name = _("Classifiers") + help_text = _("Select classifiers for your policy-rule.") + + def populate_classifier_choices(self, request, context): + try: + tenant_id = self.request.user.tenant_id + classifiers = client.policyclassifier_list(request, + tenant_id=tenant_id) + for classifier in classifiers: + classifier.set_id_as_name_if_empty() + classifiers = sorted(classifiers, + key=lambda classifier: classifier.name) + classifier_list = [(c.id, c.name) for c in classifiers] + except Exception as e: + classifier_list = [] + exceptions.handle(request, + _('Unable to retrieve classifiers (%(error)s).') + % {'error': str(e)}) + return classifier_list + + +class SelectPolicyActionAction(workflows.Action): + actions = fields.DynamicMultiChoiceField( + label=_("Policy Action"), + required=False, + help_text=_("Create a policy-rule with selected action."), + add_item_link=ADD_POLICY_ACTION_URL) + + class Meta: + name = _("actions") + help_text = _("Select actions for your policy-rule.") + + def populate_actions_choices(self, request, context): + try: + tenant_id = self.request.user.tenant_id + actions = client.policyaction_list(request, + tenant_id=tenant_id) + action_list = [a.id for a in actions] + for action in actions: + action.set_id_as_name_if_empty() + actions = sorted(actions, + key=lambda action: action.name) + action_list = [(a.id, a.name) for a in actions] + except Exception as e: + action_list = [] + exceptions.handle(request, + _('Unable to retrieve actions (%(error)s).') + % {'error': str(e)}) + return action_list + + +class SelectPolicyActionStep(workflows.Step): + action_class = SelectPolicyActionAction + contributes = ("policy_actions",) + + def contribute(self, data, context): + if data: + actions = self.workflow.request.POST.getlist( + "actions") + if actions: + actions = [a for a in actions if a != ''] + context['policy_actions'] = actions + return context + + +class SelectPolicyClassifierStep(workflows.Step): + action_class = SelectPolicyClassifierAction + contributes = ("policy_classifier_id",) + + def contribute(self, data, context): + context = super(SelectPolicyClassifierStep, self).contribute(data, + context) + if data: + context['policy_classifier_id'] = data['classifier'] + return context + + +class AddPolicyRuleAction(workflows.Action): + name = forms.CharField(max_length=80, + label=_("Name")) + description = forms.CharField(max_length=80, + label=_("Description"), + required=False) + + def __init__(self, request, *args, **kwargs): + super(AddPolicyRuleAction, self).__init__(request, *args, **kwargs) + + class Meta: + name = _("Create Policy-Rule") + help_text = _("Create a new Policy-Rule") + + +class AddPolicyRuleStep(workflows.Step): + action_class = AddPolicyRuleAction + contributes = ("name", "description") + + def contribute(self, data, context): + context = super(AddPolicyRuleStep, self).contribute(data, context) + return context + + +class AddPolicyRule(workflows.Workflow): + slug = "addpolicyrule" + name = _("Create Policy-Rule") + finalize_button_name = _("Create") + success_message = _('Created Policy-Rule "%s".') + failure_message = _('Unable to create Policy-Rule "%s".') + default_steps = (AddPolicyRuleStep, + SelectPolicyClassifierStep, + SelectPolicyActionStep) + wizard = True + + def get_success_url(self): + return reverse("horizon:project:application_policy:index") + + def format_status_message(self, message): + return message % self.context.get('name') + + def handle(self, request, context): + try: + rule = client.policyrule_create(request, **context) + self.object = rule + return rule + except Exception as e: + msg = self.format_status_message(self.failure_message) + str(e) + exceptions.handle(request, msg) + return False + + +class AddClassifierAction(workflows.Action): + name = forms.CharField(max_length=80, label=_("Name"), required=False) + protocol = forms.ChoiceField( + label=_("Protocol"), + choices=[('tcp', _('TCP')), + ('udp', _('UDP')), + ('icmp', _('ICMP')), + ('any', _('ANY'))],) + port_range = forms.CharField( + max_length=80, + label=_("Port/Range(min:max)"), + required=False) + direction = forms.ChoiceField( + label=_("Direction"), + choices=[('in', _('IN')), + ('out', _('OUT')), + ('bi', _('BI'))]) + + def __init__(self, request, *args, **kwargs): + super(AddClassifierAction, self).__init__(request, *args, **kwargs) + + class Meta: + name = _("Create Classifier") + help_text = _("Create a new Classifier") + + +class AddClassifierStep(workflows.Step): + action_class = AddClassifierAction + contributes = ("name", "protocol", "port_range", "direction") + + def contribute(self, data, context): + context = super(AddClassifierStep, self).contribute(data, context) + return context + + +class AddPolicyClassifier(workflows.Workflow): + slug = "addpolicyclassifier" + name = _("Create Classifier") + finalize_button_name = _("Create") + success_message = _('Created Classifier "%s".') + failure_message = _('Unable to create Classifier "%s".') + success_url = "horizon:project:application_policy:index" + default_steps = (AddClassifierStep,) + + def format_status_message(self, message): + return message % self.context.get('name') + + def _create_classifer(self, request, context): + try: + client.policyclassifier_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 + + def handle(self, request, context): + classifier = self._create_classifer(request, context) + if not classifier: + return False + return classifier