diff --git a/gbpui/client.py b/gbpui/client.py index e064c91..835b13c 100644 --- a/gbpui/client.py +++ b/gbpui/client.py @@ -58,6 +58,26 @@ class PTG(neutron.NeutronAPIDictWrapper): return epg_dict +class ExternalPTG(neutron.NeutronAPIDictWrapper): + + """Wrapper for neutron external endpoint group.""" + + def get_dict(self): + eepg_dict = self._apidict + eepg_dict['eepg_id'] = eepg_dict['id'] + return eepg_dict + + +class ExternalConnectivity(neutron.NeutronAPIDictWrapper): + + """Wrapper for neutron external segment.""" + + def get_dict(self): + ec_dict = self._apidict + ec_dict['ec_id'] = ec_dict['id'] + return ec_dict + + class Contract(neutron.NeutronAPIDictWrapper): """Wrapper for neutron policy_rule_set.""" @@ -204,6 +224,38 @@ def policy_target_update(request, policy_target_id, **kwargs): return PTG(policy_target) +def ext_policy_target_create(request, **kwargs): + body = {'external_policy': kwargs} + policy_target = gbpclient(request).create_external_policy( + body).get('endpoint_group') + return ExternalPTG(policy_target) + + +def ext_policy_target_list(request, tenant_id, **kwargs): + policy_targets = gbpclient(request).list_external_policies( + tenant_id=tenant_id, shared=False, **kwargs).get('external_policies') + policy_targets.extend(gbpclient(request).list_external_policies( + shared=True, **kwargs).get('external_policies')) + return [ExternalPTG(policy_target) for policy_target in policy_targets] + + +def ext_policy_target_get(request, ext_policy_target_id): + policy_target = gbpclient(request).show_external_policy( + ext_policy_target_id).get('external_policy') + return ExternalPTG(policy_target) + + +def ext_policy_target_delete(request, ext_policy_target_id): + gbpclient(request).delete_external_policy(ext_policy_target_id) + + +def ext_policy_target_update(request, ext_policy_target_id, **kwargs): + body = {'external_policy': kwargs} + policy_target = gbpclient(request).update_external_policy( + ext_policy_target_id, body).get('external_policy') + return ExternalPTG(policy_target) + + def policy_rule_set_create(request, **kwargs): body = {'policy_rule_set': kwargs} policy_rule_set = gbpclient(request).create_policy_rule_set( @@ -357,6 +409,39 @@ def networkservicepolicy_list(request, tenant_id, **kwargs): return [NetworkServicePolicy(item) for item in policies] +def externalconnectivity_list(request, tenant_id, **kwargs): + external_connectivities = gbpclient(request).list_external_segments( + tenant_id=tenant_id, shared=False, **kwargs).get('external_segments') + external_connectivities.extend(gbpclient(request).list_external_segments( + shared=True, **kwargs).get('external_segments')) + return [ExternalConnectivity(external_connectivity) + for external_connectivity in external_connectivities] + + +def create_externalconnectivity(request, **kwargs): + body = {'external_segment': kwargs} + es = gbpclient(request).create_external_segment( + body).get('external_segment') + return ExternalConnectivity(es) + + +def get_externalconnectivity(request, external_connectivity_id): + es = gbpclient(request).show_external_segment( + external_connectivity_id).get('external_segment') + return ExternalConnectivity(es) + + +def delete_externalconnectivity(request, external_connectivity_id, **kwargs): + gbpclient(request).delete_external_segment(external_connectivity_id) + + +def update_externalconnectivity(request, external_connectivity_id, **kwargs): + body = {'external_segment': kwargs} + ec = gbpclient(request).update_external_segment( + external_connectivity_id, body).get('external_segment') + return NetworkServicePolicy(ec) + + def create_networkservice_policy(request, **kwargs): body = {'network_service_policy': kwargs} spolicy = gbpclient(request).create_network_service_policy( diff --git a/gbpui/column_filters.py b/gbpui/column_filters.py index 2765c96..b02c8f8 100644 --- a/gbpui/column_filters.py +++ b/gbpui/column_filters.py @@ -82,12 +82,20 @@ def update_policy_target_attributes(request, pt): 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: + if hasattr(pt, 'l2_policy_id') and pt.l2_policy_id is not None: policy = client.l2policy_get(request, pt.l2_policy_id) u = reverse(l2url, kwargs={'l2policy_id': policy.id}) atag = mark_safe( "" + policy.name + "") setattr(pt, 'l2_policy_id', atag) + if hasattr(pt, 'external_segments'): + exturl = "horizon:project:network_policy:external_connectivity_details" + ext_policy = client.get_externalconnectivity(request, + pt.external_segments[0]) + u = reverse(exturl, kwargs={'external_connectivity_id': ext_policy.id}) + exttag = mark_safe( + "" + ext_policy.name + "") + setattr(pt, 'external_segments', exttag) return pt @@ -234,3 +242,23 @@ def update_classifier_attributes(classifiers): in port_protocol_map: classifiers.protocol = port_protocol_map[classifiers.port_range] return classifiers + + +def update_l3_policy_attributes(request, l3_policy): + url = "horizon:project:network_policy:external_connectivity_details" + if bool(l3_policy.external_segments): + external_connectivity_id = l3_policy.external_segments.keys()[0] + try: + external_connectivity = client.get_externalconnectivity(request, + external_connectivity_id) + segment_name = external_connectivity.name + except Exception: + segment_name = external_connectivity_id + u = reverse(url, + kwargs={'external_connectivity_id': external_connectivity_id}) + tag = mark_safe("" + segment_name + "" + + " : " + l3_policy.external_segments.values()[0][0]) + else: + tag = '-' + setattr(l3_policy, 'external_segments', tag) + return l3_policy diff --git a/gbpui/panels/network_policy/forms.py b/gbpui/panels/network_policy/forms.py index ce2f9f6..43abce6 100644 --- a/gbpui/panels/network_policy/forms.py +++ b/gbpui/panels/network_policy/forms.py @@ -21,6 +21,7 @@ from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import messages +from openstack_dashboard import api from gbpui import client from gbpui import fields @@ -28,6 +29,7 @@ from gbpui import fields LOG = logging.getLogger(__name__) NETWORK_PARAM_URL = "horizon:project:network_policy:add_network_service_param" +ROUTE_URL = "horizon:project:network_policy:add_external_route_param" class BaseUpdateForm(forms.SelfHandlingForm): @@ -60,11 +62,21 @@ class AddL3PolicyForm(forms.SelfHandlingForm): label=_("Subnet Prefix Length"), help_text=_("Between 2 - 30 for IP4" "and 2-127 for IP6."),) + external_segments = forms.ChoiceField(label=_("External Segment"), + required=False) + segment_ip = forms.IPField(label=_("External Segment IP"), initial="", + required=False) shared = forms.BooleanField(label=_("Shared"), - initial=False, required=False) + initial=False, + required=False) def __init__(self, request, *args, **kwargs): super(AddL3PolicyForm, self).__init__(request, *args, **kwargs) + ec_list = client.externalconnectivity_list(request, + tenant_id=request.user.tenant_id) + external_segments_options = [(ec.id, ec.name) for ec in ec_list] + external_segments_options.insert(0, (None, "Select")) + self.fields['external_segments'].choices = external_segments_options def clean(self): cleaned_data = super(AddL3PolicyForm, self).clean() @@ -76,11 +88,23 @@ class AddL3PolicyForm(forms.SelfHandlingForm): raise forms.ValidationError(msg) if ipversion == 6 and subnet_prefix_length not in range(2, 128): raise forms.ValidationError(msg) + if cleaned_data['external_segments'] != '': + if cleaned_data['segment_ip'] == '': + self.add_error('segment_ip', 'This field is required') return cleaned_data def handle(self, request, context): url = reverse("horizon:project:network_policy:index") + external_segment_dic = {} + l = [] try: + if context['external_segments'] != '': + l.append(context['segment_ip']) + external_segment_dic[context['external_segments']] = l + context['external_segments'] = external_segment_dic + else: + del context['external_segments'] + del context['segment_ip'] if context.get('name'): context['name'] = html.escape(context['name']) if context.get('description'): @@ -97,18 +121,34 @@ class UpdateL3PolicyForm(AddL3PolicyForm): def __init__(self, request, *args, **kwargs): super(UpdateL3PolicyForm, self).__init__(request, *args, **kwargs) try: + ec_list = client.externalconnectivity_list(request, + tenant_id=request.user.tenant_id) + external_segments_options = [(ec.id, ec.name) for ec in ec_list] + external_segments_options.insert(0, (None, "Select")) + self.fields['external_segments'].choices = \ + external_segments_options l3policy_id = self.initial['l3policy_id'] l3 = client.l3policy_get(request, l3policy_id) for item in ['name', 'description', 'ip_version', 'ip_pool', 'subnet_prefix_length']: self.fields[item].initial = str(l3[item]) self.fields['shared'].initial = l3['shared'] + if bool(l3['external_segments']): + self.fields['external_segments'].initial = \ + l3['external_segments'].keys()[0] + self.fields['segment_ip'].initial = \ + l3['external_segments'].values()[0][0] + else: + self.fields['external_segments'].initial = None + self.fields['segment_ip'].initial = '' except Exception: msg = _("Failed to get L3 policy") LOG.error(msg) exceptions.handle(request, msg, redirect=shortcuts.redirect) def clean(self): + external_segment_dict = {} + l = [] cleaned_data = super(UpdateL3PolicyForm, self).clean() if self.is_valid(): ipversion = int(cleaned_data['ip_version']) @@ -118,6 +158,20 @@ class UpdateL3PolicyForm(AddL3PolicyForm): raise forms.ValidationError(msg) if ipversion == 6 and subnet_prefix_length not in range(2, 128): raise forms.ValidationError(msg) + if cleaned_data['external_segments'] != '': + if cleaned_data['segment_ip'] == '': + self.add_error('segment_ip', 'This field is required') + if 'external_segments' in self.changed_data or \ + 'segment_ip' in self.changed_data: + if cleaned_data['external_segments'] != '': + l.append(cleaned_data['segment_ip']) + external_segment_dict[cleaned_data['external_segments']] = \ + l + cleaned_data['external_segments'] = external_segment_dict + else: + cleaned_data['external_segments'] = {} + del cleaned_data['segment_ip'] + self.changed_data.append('external_segments') updated_data = {d: cleaned_data[d] for d in cleaned_data if d in self.changed_data} cleaned_data = updated_data @@ -324,3 +378,129 @@ class UpdateServicePolicyForm(BaseUpdateForm): msg = _("Failed to update service policy") LOG.error(msg) exceptions.handle(request, msg, redirect=shortcuts.redirect) + + +class UpdateExternalConnectivityForm(forms.SelfHandlingForm): + name = forms.CharField(max_length=80, label=_("Name")) + description = forms.CharField( + max_length=80, label=_("Description"), required=False) + shared = forms.BooleanField(label=_("Shared"), required=False) + + def __init__(self, request, *args, **kwargs): + super(UpdateExternalConnectivityForm, self).__init__(request, + *args, **kwargs) + try: + external_connectivity_id = \ + self.initial['external_connectivity_id'] + external_connectivity = client.get_externalconnectivity(request, + external_connectivity_id) + self.fields['name'].initial = external_connectivity.name + self.fields['description'].initial = \ + external_connectivity.description + self.fields['shared'].initial = external_connectivity.shared + except Exception as e: + msg = _("Failed to retrive external connectivity details. %s") % \ + (str(e)) + LOG.debug(msg) + + def handle(self, request, context): + url = reverse("horizon:project:network_policy:index") + try: + external_connectivity_id = self.initial['external_connectivity_id'] + client.update_externalconnectivity( + request, external_connectivity_id, **context) + msg = _("External Connectivity updated successfully!") + LOG.debug(msg) + return http.HttpResponseRedirect(url) + except Exception: + msg = _("Failed to update External Connectivity") + LOG.error(msg) + exceptions.handle(request, msg, redirect=shortcuts.redirect) + + +class CreateExternalConnectivityForm(forms.SelfHandlingForm): + name = forms.CharField(max_length=80, label=_("Name")) + description = forms.CharField( + max_length=80, label=_("Description"), required=False) + ip_version = forms.ChoiceField(choices=[(4, 'IPv4'), (6, 'IPv6')], + widget=forms.Select(attrs={ + 'class': 'switchable', + 'data-slug': 'ipversion', + }), + label=_("IP Version")) + cidr = forms.IPField(label=_("CIDR"), + initial="", + help_text=_("Network address in CIDR format " + "(e.g. 192.168.0.0/24," + "2001:DB8::/48)"), + version=forms.IPv4 | forms.IPv6, mask=True) + external_routes = fields.CustomMultiChoiceField( + label=_("External Routes"), add_item_link=ROUTE_URL, + required=False) + subnet_id = forms.ChoiceField(label=_("Subnet ID"), required=False) + port_address_translation = forms.BooleanField( + label=_("Port Address Translation"), + initial=False, required=False) + shared = forms.BooleanField(label=_("Shared"), + initial=False, required=False) + + def __init__(self, request, *args, **kwargs): + super(CreateExternalConnectivityForm, self).__init__(request, + *args, **kwargs) + net_id_list = [] + dic = {"router:external": True} + try: + net_list = api.neutron.network_list(request, **dic) + subnet_list = api.neutron.subnet_list(request) + net_id_list = [net.id for net in net_list] + self.fields['subnet_id'].choices = [(subnet.id, subnet.name) + for subnet in subnet_list if subnet.network_id in net_id_list] + except Exception: + msg = _("Failed to get Subnet ID list.") + exceptions.handle(request, msg) + + def handle(self, request, context): + url = reverse("horizon:project:network_policy:index") + try: + routes = context['external_routes'] + p = [] + if len(routes) > 0: + for item in routes: + values = [i.split(":")[1] for i in item.split(",")] + values = {'destination': values[0], + 'nexthop': values[1]} + p.append(values) + context['external_routes'] = p + client.create_externalconnectivity( + request, **context) + msg = _("External Connectivity updatedsuccessfully!") + LOG.debug(msg) + return http.HttpResponseRedirect(url) + except Exception as e: + msg = str(e) + LOG.error(msg) + exceptions.handle(request, msg, redirect=shortcuts.redirect) + + +class ExternalRouteParam(object): + + def __init__(self, context): + self.destination = context['destination'] + self.next_hop = context['next_hop'] + self.name = 'destination:%s,next_hop:%s' % ( + self.destination, self.next_hop) + self.id = self.name + + +class CreateExternalRouteParamForm(forms.SelfHandlingForm): + destination = forms.IPField(label=_("Destination"), + initial="", + help_text=_( + "(e.g. 192.168.0.0/24," + "2001:DB8::/48)"), + version=forms.IPv4 | forms.IPv6, + mask=True) + next_hop = forms.IPField(label=_("Next hop")) + + def handle(self, request, context): + return ExternalRouteParam(context) diff --git a/gbpui/panels/network_policy/tables.py b/gbpui/panels/network_policy/tables.py index a7699a2..e9de49e 100644 --- a/gbpui/panels/network_policy/tables.py +++ b/gbpui/panels/network_policy/tables.py @@ -94,6 +94,8 @@ class L3PolicyTable(tables.DataTable): ip_pool = tables.Column("ip_pool", verbose_name=_("IP Pool")) subnet_prefix_length = tables.Column( "subnet_prefix_length", verbose_name=_("Subnet Prefix Length")) + external_segments = tables.Column("external_segments", + verbose_name=_("External Segment")) class Meta(object): name = "l3policy_table" @@ -140,3 +142,47 @@ class ServicePolicyTable(tables.DataTable): verbose_name = _("Service Policies") table_actions = (CreateServicePolicyLink, DeleteServicePolicyLink,) row_actions = (EditServicePolicyLink, DeleteServicePolicyLink,) + + +class CreateExternalConnectivityLink(tables.LinkAction): + name = "create_external_connectivity" + verbose_name = _("Create External Connectivity") + url = "horizon:project:network_policy:create_external_connectivity" + classes = ("ajax-modal", "btn-addexternalconnectivity") + + +class EditExternalConnectivityLink(tables.LinkAction): + name = "update_external_connectivity" + verbose_name = _("Edit") + classes = ("ajax-modal", "btn-update",) + + def get_link_url(self, external_connectivity): + urlstring = \ + "horizon:project:network_policy:update_externalconnectivity" + base_url = reverse(urlstring, + kwargs={'external_connectivity_id': external_connectivity.id}) + return base_url + + +class DeleteExternalConnectivityLink(tables.DeleteAction): + name = "deleteexternalconnectivity" + action_present = _("Delete") + action_past = _("Scheduled deletion of %(data_type)s") + data_type_singular = _("ExternalConnectivity") + data_type_plural = _("ExternalConnectivities") + + +class ExternalConnectivityTable(tables.DataTable): + name = tables.Column("name", verbose_name=_("Name"), + link="horizon:project:network_policy:external_connectivity_details") + description = tables.Column("description", verbose_name=_("Description")) + ip_version = tables.Column("ip_version", verbose_name=_("IP Version")) + cidr = tables.Column("cidr", verbose_name=_("CIDR")) + + class Meta(object): + name = "external_connectivity_table" + verbose_name = _("External Connectivity") + table_actions = (CreateExternalConnectivityLink, + DeleteExternalConnectivityLink,) + row_actions = (EditExternalConnectivityLink, + DeleteExternalConnectivityLink,) diff --git a/gbpui/panels/network_policy/tabs.py b/gbpui/panels/network_policy/tabs.py index 3ee67c0..3db81d7 100644 --- a/gbpui/panels/network_policy/tabs.py +++ b/gbpui/panels/network_policy/tabs.py @@ -50,6 +50,9 @@ class L3PolicyTab(tabs.TableTab): try: policies = client.l3policy_list(self.request, tenant_id=self.request.user.tenant_id) + update = lambda x: gfilters.update_l3_policy_attributes( + self.request, x) + policies = [update(item) for item in policies] except Exception: policies = [] exceptions.handle(self.tab_group.request, @@ -111,15 +114,59 @@ class ServicePolicyDetailsTab(tabs.Tab): return {'policy': policy} +class ExternalConnectivityTab(tabs.TableTab): + table_classes = (tables.ExternalConnectivityTable,) + name = _("External Connectivity") + slug = "external_connectivity" + template_name = "horizon/common/_detail_table.html" + + def get_external_connectivity_table_data(self): + external_segment_list = [] + try: + external_segment_list = \ + client.externalconnectivity_list(self.request, + self.request.user.tenant_id) + except Exception: + exceptions.handle(self.tab_group.request, + _('Unable to retrieve network service policy list.')) + return external_segment_list + + +class ExternalConnectivityDetailsTab(tabs.Tab): + name = _("External Connectivity Details") + slug = "external_connectivity_details" + template_name = \ + "project/network_policy/_external_connectivity_details.html" + failure_url = reverse_lazy('horizon:project:network_policy:index') + + def get_context_data(self, request): + external_connectivity_id = \ + self.tab_group.kwargs['external_connectivity_id'] + try: + external_connectivity = client.get_externalconnectivity(request, + external_connectivity_id) + except Exception: + exceptions.handle( + request, _('Unable to retrieve service policy details.'), + redirect=self.failure_url) + return {'external_connectivity': external_connectivity} + + class ServicePolicyDetailsTabs(tabs.TabGroup): slug = "service_policy_details_tab" tabs = (ServicePolicyDetailsTab,) sticky = True +class ExternalConnectivityDetailsTabs(tabs.TabGroup): + slug = "external_connectivity_details_tab" + tabs = (ExternalConnectivityDetailsTab,) + sticky = True + + class L3PolicyTabs(tabs.TabGroup): slug = "l3policy_tab" - tabs = (L3PolicyTab, ServicePolicyTab,) + tabs = (L3PolicyTab, ServicePolicyTab, ExternalConnectivityTab,) sticky = True diff --git a/gbpui/panels/network_policy/templates/network_policy/_add_l3policy.html b/gbpui/panels/network_policy/templates/network_policy/_add_l3policy.html index 8f4aea0..7a08de4 100644 --- a/gbpui/panels/network_policy/templates/network_policy/_add_l3policy.html +++ b/gbpui/panels/network_policy/templates/network_policy/_add_l3policy.html @@ -19,6 +19,26 @@ {% endblock %} + +{% block modal-js %} + +{% endblock %} + + + {% block modal-footer %} {% trans "Cancel" %} diff --git a/gbpui/panels/network_policy/templates/network_policy/_create_external_connectivity.html b/gbpui/panels/network_policy/templates/network_policy/_create_external_connectivity.html new file mode 100644 index 0000000..f36e8d7 --- /dev/null +++ b/gbpui/panels/network_policy/templates/network_policy/_create_external_connectivity.html @@ -0,0 +1,24 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} +{% load url from future %} + +{% block form_id %}create_external_connectivity{% endblock %} +{% block form_action %}{% url 'horizon:project:network_policy:create_external_connectivity' %}{% endblock %} + +{% block modal-header %}{% trans "Create External Connectivity" %}{% endblock %} + +{% block modal-body %} +
+
+ {% include "horizon/common/_form_fields.html" %} +
+
+
+

{% trans "Description:" %}

+
+{% endblock %} + +{% block modal-footer %} + + {% trans "Cancel" %} +{% endblock %} diff --git a/gbpui/panels/network_policy/templates/network_policy/_create_external_route_param.html b/gbpui/panels/network_policy/templates/network_policy/_create_external_route_param.html new file mode 100644 index 0000000..5704638 --- /dev/null +++ b/gbpui/panels/network_policy/templates/network_policy/_create_external_route_param.html @@ -0,0 +1,24 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} +{% load url from future %} + +{% block form_id %}add_external_route_param_form{% endblock %} +{% block form_action %}{% url 'horizon:project:network_policy:add_external_route_param' %}{% endblock %} + +{% block modal-header %}{% trans "Add External Route Parameter" %}{% endblock %} + +{% block modal-body %} +
+
+ {% include "horizon/common/_form_fields.html" %} +
+
+
+

{% trans "Description:" %}

+
+{% endblock %} + +{% block modal-footer %} + + {% trans "Cancel" %} +{% endblock %} diff --git a/gbpui/panels/network_policy/templates/network_policy/_external_connectivity_details.html b/gbpui/panels/network_policy/templates/network_policy/_external_connectivity_details.html new file mode 100644 index 0000000..f648e3f --- /dev/null +++ b/gbpui/panels/network_policy/templates/network_policy/_external_connectivity_details.html @@ -0,0 +1,32 @@ +{% load i18n sizeformat parse_date %} +{% load url from future %} + +
+
+
+
{% trans "Name" %}
+
{{ external_connectivity.name|default:_("-") }}
+ +
{% trans "Description" %}
+
{{ external_connectivity.description|default:_("-") }}
+ +
{% trans "ID" %}
+
{{ external_connectivity.id }}
+ +
{% trans "Ip Version" %}
+
{{ external_connectivity.ip_version }}
+ +
{% trans "CIDR" %}
+
{{ external_connectivity.cidr }}
+ +
{% trans "External Routes" %}
+
{{ external_connectivity.external_routes|default:_("-") }}
+ + +
{% trans "Port Address Translation" %}
+
{{ external_connectivity.port_address_translation }}
+ +
{% trans "Shared" %}
+
{{ external_connectivity.shared }}
+
+
diff --git a/gbpui/panels/network_policy/templates/network_policy/_update_external_connectivity.html b/gbpui/panels/network_policy/templates/network_policy/_update_external_connectivity.html new file mode 100644 index 0000000..cca6285 --- /dev/null +++ b/gbpui/panels/network_policy/templates/network_policy/_update_external_connectivity.html @@ -0,0 +1,25 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} +{% load url from future %} + +{% block form_id %}update_external_connectivity_form{% endblock %} +{% block form_action %}{% url 'horizon:project:network_policy:update_externalconnectivity' external_connectivity_id %}{% endblock %} + +{% block modal-header %}{% trans "Update External Connectivity" %}{% endblock %} + +{% block modal-body %} +
+
+ {% include "horizon/common/_form_fields.html" %} +
+
+
+

{% trans "Description:" %}

+

{% trans "Update Service Policy." %}

+
+{% endblock %} + +{% block modal-footer %} + + {% trans "Cancel" %} +{% endblock %} diff --git a/gbpui/panels/network_policy/templates/network_policy/_update_l3policy.html b/gbpui/panels/network_policy/templates/network_policy/_update_l3policy.html index 5a1297a..927464c 100644 --- a/gbpui/panels/network_policy/templates/network_policy/_update_l3policy.html +++ b/gbpui/panels/network_policy/templates/network_policy/_update_l3policy.html @@ -19,6 +19,25 @@ {% endblock %} + +{% block modal-js %} + +{% endblock %} + + {% block modal-footer %} {% trans "Cancel" %} diff --git a/gbpui/panels/network_policy/urls.py b/gbpui/panels/network_policy/urls.py index e1233a8..1e32b8e 100644 --- a/gbpui/panels/network_policy/urls.py +++ b/gbpui/panels/network_policy/urls.py @@ -21,18 +21,32 @@ urlpatterns = patterns('', url(r'^addl3policy$', views.AddL3policyView.as_view(), name='addl3policy'), - url(r'^addserviceolicy$', + url(r'^addservicepolicy$', views.CreateServicePolicyView.as_view(), name='create_servicepolicy'), url(r'^addnetworkserviceparam$', views.AddNetworkServiceParamView.as_view(), name='add_network_service_param'), + url(r'^addexternalrouteparam$', + views.AddExternalRouteParamView.as_view(), + name='add_external_route_param'), + url(r'^createexternalconnectivity$', + views.CreateExternalConnectivityView.as_view(), + name='create_external_connectivity'), url(r'^update_servicepolicy/(?P[^/]+)/$', views.UpdateServicePolicyView.as_view(), name='update_service_policy'), + url(r'^update_externalconnectivity/' + '(?P[^/]+)/$', + views.UpdateExternalConnectivityView.as_view(), + name='update_externalconnectivity'), url(r'^servicepolicy/(?P[^/]+)/$', views.ServicePolicyDetailsView.as_view(), name='service_policy_details'), + url(r'^externalconnectivity/' + '(?P[^/]+)/$', + views.ExternalConnectivityDetailsView.as_view(), + name='external_connectivity_details'), url(r'^addl2policy$', views.AddL2policyView.as_view(), name='addl2policy'), diff --git a/gbpui/panels/network_policy/views.py b/gbpui/panels/network_policy/views.py index edcf707..b246e4e 100644 --- a/gbpui/panels/network_policy/views.py +++ b/gbpui/panels/network_policy/views.py @@ -55,6 +55,15 @@ class IndexView(tabs.TabView): except Exception as e: msg = _('Unable to delete action. %s') % (str(e)) exceptions.handle(request, msg) + if obj_type == 'externalconnectivity': + for obj_id in obj_ids: + try: + client.delete_externalconnectivity(request, obj_id) + messages.success(request, + _('Deleted External Connectivity %s') % obj_id) + except Exception as e: + msg = _('Unable to delete action. %s') % (str(e)) + exceptions.handle(request, msg) return self.get(request, *args, **kwargs) @@ -170,6 +179,29 @@ class AddNetworkServiceParamView(forms.ModalFormView): return params.name +class AddExternalRouteParamView(forms.ModalFormView): + form_class = np_forms.CreateExternalRouteParamForm + template_name = "project/network_policy/create_external_route_param.html" + + def get_object_id(self, params): + return params.name + + +class UpdateExternalConnectivityView(forms.ModalFormView): + form_class = np_forms.UpdateExternalConnectivityForm + template_name = "project/network_policy/update_external_connectivity.html" + + def get_context_data(self, **kwargs): + context = super( + UpdateExternalConnectivityView, self).get_context_data(**kwargs) + context['external_connectivity_id'] = \ + self.kwargs['external_connectivity_id'] + return context + + def get_initial(self): + return self.kwargs + + class UpdateServicePolicyView(forms.ModalFormView): form_class = np_forms.UpdateServicePolicyForm template_name = "project/network_policy/update_service_policy.html" @@ -187,3 +219,18 @@ class UpdateServicePolicyView(forms.ModalFormView): class ServicePolicyDetailsView(tabs.TabView): tab_group_class = (np_tabs.ServicePolicyDetailsTabs) template_name = 'project/network_policy/details_tabs.html' + + +class CreateExternalConnectivityView(forms.ModalFormView): + form_class = np_forms.CreateExternalConnectivityForm + template_name = "project/network_policy/create_external_connectivity.html" + + def get_context_data(self, **kwargs): + context = super( + CreateExternalConnectivityView, self).get_context_data(**kwargs) + return context + + +class ExternalConnectivityDetailsView(tabs.TabView): + tab_group_class = (np_tabs.ExternalConnectivityDetailsTabs) + template_name = 'project/network_policy/details_tabs.html' diff --git a/gbpui/panels/policytargets/forms.py b/gbpui/panels/policytargets/forms.py index 3937218..bfa904c 100644 --- a/gbpui/panels/policytargets/forms.py +++ b/gbpui/panels/policytargets/forms.py @@ -134,6 +134,103 @@ class UpdatePolicyTargetForm(forms.SelfHandlingForm): exceptions.handle(request, msg, redirect=redirect) +class UpdateExternalPolicyTargetForm(forms.SelfHandlingForm): + name = forms.CharField(max_length=80, + label=_("Name"), required=False) + description = forms.CharField(max_length=80, + label=_("Description"), required=False) + provided_policy_rule_sets = forms.MultipleChoiceField( + label=_("Provided Policy Rule Set"), required=False) + consumed_policy_rule_sets = forms.MultipleChoiceField( + label=_("Consumed Policy Rule Set"), required=False) + external_segments = forms.ChoiceField( + label=_("External Connectivity"), + help_text=_("Select external segment for Group.")) + shared = forms.BooleanField(label=_("Shared"), required=False) + failure_url = 'horizon:project:policytargets:index' + + def __init__(self, request, *args, **kwargs): + super(UpdateExternalPolicyTargetForm, self).__init__(request, + *args, **kwargs) + try: + ext_policy_target_id = self.initial['ext_policy_target_id'] + ext_policy_target = client.ext_policy_target_get(request, + ext_policy_target_id) + policy_rule_sets = client.policy_rule_set_list( + request, tenant_id=request.user.tenant_id) + external_connectivities = client.externalconnectivity_list( + request, tenant_id=request.user.tenant_id) + for c in policy_rule_sets: + c.set_id_as_name_if_empty() + ext_conn_list = [(e.id, e.name)for e in external_connectivities] + policy_rule_sets = sorted( + policy_rule_sets, key=lambda rule: rule.name) + policy_rule_set_list = [(c.id, c.name) for c in policy_rule_sets] + self.fields[ + 'provided_policy_rule_sets'].choices = policy_rule_set_list + self.fields[ + 'consumed_policy_rule_sets'].choices = policy_rule_set_list + self.fields[ + 'external_segments'].choices = ext_conn_list + provided_init = [] + consumed_init = [] + for item in policy_rule_set_list: + if item[0] in ext_policy_target.provided_policy_rule_sets: + provided_init.append(item[0]) + if item[0] in ext_policy_target.consumed_policy_rule_sets: + consumed_init.append(item[0]) + self.fields['provided_policy_rule_sets'].initial = provided_init + self.fields['consumed_policy_rule_sets'].initial = consumed_init + for attr in ['name', 'description', 'shared']: + self.fields[attr].initial = getattr(ext_policy_target, attr) + self.fields['external_segments'].initial = \ + ext_policy_target.external_segments[0] + except Exception as e: + msg = _('Unable to retrieve policy_rule_set details. %s') % ( + str(e)) + exceptions.handle(request, msg) + pass + + def clean(self): + cleaned_data = super(UpdateExternalPolicyTargetForm, self).clean() + updated_data = {d: cleaned_data[d] for d in cleaned_data + if d in self.changed_data} + return updated_data + + def handle(self, request, context): + ext_policy_target_id = self.initial['ext_policy_target_id'] + name_or_id = context.get('name') or ext_policy_target_id + external_segment_list = [] + try: + if context.get('provided_policy_rule_sets'): + context['provided_policy_rule_sets'] = dict( + [(i, 'string') + for i in context['provided_policy_rule_sets']]) + if context.get('consumed_policy_rule_sets'): + context['consumed_policy_rule_sets'] = dict( + [(i, 'string') + for i in context['consumed_policy_rule_sets']]) + if 'external_segments' in context: + external_segment_list.append(context['external_segments']) + context['external_segments'] = external_segment_list + if context.get('name'): + context['name'] = html.escape(context['name']) + if context.get('description'): + context['description'] = html.escape(context['description']) + ext_policy_target = client.ext_policy_target_update( + request, ext_policy_target_id, **context) + msg = _('External Group %s was successfully updated.') % name_or_id + LOG.debug(msg) + messages.success(request, msg) + return ext_policy_target + except Exception as e: + msg = _('Failed to update Group %(name)s. %(reason)s') % {'name': + name_or_id, 'reason': str(e)} + LOG.error(msg) + redirect = reverse(self.failure_url) + exceptions.handle(request, msg, redirect=redirect) + + class AddProvidedPRSForm(forms.SelfHandlingForm): policy_rule_set = forms.MultipleChoiceField( label=_("Provided Policy Rule Sets"),) @@ -184,6 +281,57 @@ class AddProvidedPRSForm(forms.SelfHandlingForm): exceptions.handle(request, msg, redirect=redirect) +class ExtAddProvidedPRSForm(forms.SelfHandlingForm): + policy_rule_set = forms.MultipleChoiceField( + label=_("Provided Policy Rule Sets"),) + + def __init__(self, request, *args, **kwargs): + super(ExtAddProvidedPRSForm, self).__init__(request, *args, **kwargs) + policy_rule_sets = [] + try: + ext_policy_target_id = kwargs['initial']['ext_policy_target_id'] + ext_policy_target = client.ext_policy_target_get(request, + ext_policy_target_id) + providedpolicy_rule_sets = ext_policy_target.get( + "provided_policy_rule_sets") + items = client.policy_rule_set_list(request, + tenant_id=request.user.tenant_id) + policy_rule_sets = [ + (p.id, p.name) for p in items + if p.id not in providedpolicy_rule_sets] + except Exception as e: + msg = _('Unable to retrieve policy rule set list.') % (str(e)) + LOG.debug(msg) + self.fields['policy_rule_set'].choices = policy_rule_sets + + def handle(self, request, context): + ext_policy_target_id = self.initial['ext_policy_target_id'] + ext_policy_target = client.ext_policy_target_get(request, + ext_policy_target_id) + url = reverse("horizon:project:policytargets:ext_policy_targetdetails", + kwargs={'ext_policy_target_id': ext_policy_target_id}) + try: + for policy_rule_set in ext_policy_target.get( + "provided_policy_rule_sets"): + context['policy_rule_set'].append(policy_rule_set) + policy_rule_sets = dict([(item, 'string') + for item in context['policy_rule_set']]) + client.ext_policy_target_update( + request, ext_policy_target_id, + provided_policy_rule_sets=policy_rule_sets) + msg = _('Policy Rule Set added successfully!') + messages.success(request, msg) + LOG.debug(msg) + return http.HttpResponseRedirect(url) + except Exception: + u = "horizon:project:policytargets:ext_policy_targetdetails" + msg = _('Failed to add policy_rule_set!') + redirect = reverse(u, kwargs={'ext_policy_target_id': + ext_policy_target_id}) + LOG.error(msg) + exceptions.handle(request, msg, redirect=redirect) + + class RemoveProvidedPRSForm(forms.SelfHandlingForm): policy_rule_set = forms.MultipleChoiceField( label=_("Provided Policy Rule Sets"),) @@ -235,6 +383,60 @@ class RemoveProvidedPRSForm(forms.SelfHandlingForm): exceptions.handle(request, msg, redirect=redirect) +class ExtRemoveProvidedPRSForm(forms.SelfHandlingForm): + policy_rule_set = forms.MultipleChoiceField( + label=_("Provided Policy Rule Sets"),) + + def __init__(self, request, *args, **kwargs): + super(ExtRemoveProvidedPRSForm, self).__init__(request, + *args, **kwargs) + policy_rule_sets = [] + try: + ext_policy_target_id = kwargs['initial']['ext_policy_target_id'] + ext_policy_target = client.ext_policy_target_get(request, + ext_policy_target_id) + providedpolicy_rule_sets = ext_policy_target.get( + "provided_policy_rule_sets") + items = client.policy_rule_set_list(request, + tenant_id=request.user.tenant_id) + policy_rule_sets = [(p.id, p.name) + for p in items if p.id in + providedpolicy_rule_sets] + except Exception as e: + msg = _('Unable to retrieve policy rule set list.') % (str(e)) + LOG.debug(msg) + self.fields['policy_rule_set'].choices = policy_rule_sets + + def handle(self, request, context): + ext_policy_target_id = self.initial['ext_policy_target_id'] + url = reverse( + "horizon:project:policytargets:ext_policy_targetdetails", + kwargs={'ext_policy_target_id': ext_policy_target_id}) + try: + ext_policy_target = client.ext_policy_target_get(request, + ext_policy_target_id) + old_policy_rule_sets = ext_policy_target.get( + "provided_policy_rule_sets") + for policy_rule_set in context['policy_rule_set']: + old_policy_rule_sets.remove(policy_rule_set) + policy_rule_sets = dict([(item, 'string') + for item in old_policy_rule_sets]) + client.ext_policy_target_update( + request, ext_policy_target_id, + provided_policy_rule_sets=policy_rule_sets) + msg = _('Policy Rule Set removed successfully!') + messages.success(request, msg) + LOG.debug(msg) + return http.HttpResponseRedirect(url) + except Exception: + msg = _('Failed to remove policy_rule_set!') + u = "horizon:project:policytargets:ext_policy_targetdetails" + redirect = reverse(u, + kwargs={'ext_policy_target_id': ext_policy_target_id}) + LOG.error(msg) + exceptions.handle(request, msg, redirect=redirect) + + class AddConsumedPRSForm(forms.SelfHandlingForm): policy_rule_set = forms.MultipleChoiceField( label=_("Consumed Policy Rule Sets"),) @@ -283,6 +485,56 @@ class AddConsumedPRSForm(forms.SelfHandlingForm): exceptions.handle(request, msg, redirect=redirect) +class ExtAddConsumedPRSForm(forms.SelfHandlingForm): + policy_rule_set = forms.MultipleChoiceField( + label=_("Consumed Policy Rule Sets"),) + + def __init__(self, request, *args, **kwargs): + super(ExtAddConsumedPRSForm, self).__init__(request, *args, **kwargs) + policy_rule_sets = [] + try: + ext_policy_target_id = kwargs['initial']['ext_policy_target_id'] + ext_policy_target = client.ext_policy_target_get(request, + ext_policy_target_id) + consumedpolicy_rule_sets = ext_policy_target.get( + "consumed_policy_rule_sets") + items = items = client.policy_rule_set_list(request, + tenant_id=request.user.tenant_id) + policy_rule_sets = [ + (p.id, p.name) for p in items + if p.id not in consumedpolicy_rule_sets] + except Exception: + pass + self.fields['policy_rule_set'].choices = policy_rule_sets + + def handle(self, request, context): + ext_policy_target_id = self.initial['ext_policy_target_id'] + url = reverse("horizon:project:policytargets:ext_policy_targetdetails", + kwargs={'ext_policy_target_id': ext_policy_target_id}) + try: + ext_policy_target = client.ext_policy_target_get(request, + ext_policy_target_id) + for policy_rule_set in ext_policy_target.get( + "consumed_policy_rule_sets"): + context['policy_rule_set'].append(policy_rule_set) + consumed = dict([(item, 'string') + for item in context['policy_rule_set']]) + client.ext_policy_target_update( + request, + ext_policy_target_id, consumed_policy_rule_sets=consumed) + msg = _('Policy Rule Set Added successfully!') + messages.success(request, msg) + LOG.debug(msg) + return http.HttpResponseRedirect(url) + except Exception: + msg = _('Failed to add policy_rule_set!') + u = "horizon:project:policytargets:ext_policy_targetdetails" + redirect = reverse(u, + kwargs={'ext_policy_target_id': ext_policy_target_id}) + LOG.error(msg) + exceptions.handle(request, msg, redirect=redirect) + + class RemoveConsumedPRSForm(forms.SelfHandlingForm): policy_rule_set = forms.MultipleChoiceField( label=_("Consumed Policy Rule Sets"),) @@ -327,3 +579,53 @@ class RemoveConsumedPRSForm(forms.SelfHandlingForm): redirect = url LOG.error(msg) exceptions.handle(request, msg, redirect=redirect) + + +class ExtRemoveConsumedPRSForm(forms.SelfHandlingForm): + policy_rule_set = forms.MultipleChoiceField( + label=_("Consumed Policy Rule Sets"),) + + def __init__(self, request, *args, **kwargs): + super(ExtRemoveConsumedPRSForm, self).__init__(request, + *args, **kwargs) + policy_rule_sets = [] + try: + ext_policy_target_id = kwargs['initial']['ext_policy_target_id'] + ext_policy_target = client.ext_policy_target_get(request, + ext_policy_target_id) + consumedpolicy_rule_sets = ext_policy_target.get( + "consumed_policy_rule_sets") + items = client.policy_rule_set_list(request, + tenant_id=request.user.tenant_id) + policy_rule_sets = [(p.id, p.name) + for p in items if p.id + in consumedpolicy_rule_sets] + except Exception: + pass + self.fields['policy_rule_set'].choices = policy_rule_sets + + def handle(self, request, context): + ext_policy_target_id = self.initial['ext_policy_target_id'] + url = reverse("horizon:project:policytargets:ext_policy_targetdetails", + kwargs={'ext_policy_target_id': ext_policy_target_id}) + try: + ext_policy_target = client.ext_policy_target_get(request, + ext_policy_target_id) + old_policy_rule_sets = ext_policy_target.get( + "consumed_policy_rule_sets") + for policy_rule_set in context['policy_rule_set']: + old_policy_rule_sets.remove(policy_rule_set) + consumed = dict([(item, 'string') + for item in old_policy_rule_sets]) + client.ext_policy_target_update( + request, ext_policy_target_id, + consumed_policy_rule_sets=consumed) + msg = _('Policy Rule Set removed successfully!') + messages.success(request, msg) + LOG.debug(msg) + return http.HttpResponseRedirect(url) + except Exception: + msg = _('Failed to remove policy_rule_set!') + redirect = url + LOG.error(msg) + exceptions.handle(request, msg, redirect=redirect) diff --git a/gbpui/panels/policytargets/tables.py b/gbpui/panels/policytargets/tables.py index 84c48f4..dc6ec33 100644 --- a/gbpui/panels/policytargets/tables.py +++ b/gbpui/panels/policytargets/tables.py @@ -40,7 +40,7 @@ class UpdatePTGLink(tables.LinkAction): class DeletePTGLink(tables.DeleteAction): - name = "deletepolicy_target" + name = "deletepolicytarget" action_present = _("Delete") action_past = _("Scheduled deletion of %(data_type)s") data_type_singular = _("Group") @@ -49,7 +49,7 @@ class DeletePTGLink(tables.DeleteAction): class AddPTGLink(tables.LinkAction): name = "addpolicy_target" - verbose_name = _("Create Group") + verbose_name = _("Create Internal Group") url = "horizon:project:policytargets:addpolicy_target" classes = ("ajax-modal", "btn-addpolicy_target",) @@ -70,11 +70,59 @@ class PTGsTable(tables.DataTable): class Meta(object): name = "policy_targetstable" - verbose_name = _("Groups") + verbose_name = _("Internal Groups") table_actions = (AddPTGLink, DeletePTGLink) row_actions = (UpdatePTGLink, DeletePTGLink) +class UpdateExternalPTGLink(tables.LinkAction): + name = "updateexternal_policy_target" + verbose_name = _("Edit") + classes = ("ajax-modal", "btn-update",) + + def get_link_url(self, ext_policy_target): + u = "horizon:project:policytargets:update_ext_policy_target" + base_url = reverse(u, kwargs={'ext_policy_target_id': + ext_policy_target.id}) + return base_url + + +class AddExternalPTGLink(tables.LinkAction): + name = "addexternal_policy_target" + verbose_name = _("Create External Group") + url = "horizon:project:policytargets:addexternal_policy_target" + classes = ("ajax-modal", "btn-addexternal_policy_target",) + + +class DeleteExternalPTGLink(tables.DeleteAction): + name = "deleteexternalpolicytarget" + action_present = _("Delete") + action_past = _("Scheduled deletion of %(data_type)s") + data_type_singular = _("Group") + data_type_plural = _("Groups") + + +class ExternalPTGsTable(tables.DataTable): + name = tables.Column("name", + verbose_name=_("Name"), + link="horizon:project:policytargets:ext_policy_targetdetails") + description = tables.Column("description", verbose_name=_("Description")) + provided_policy_rule_sets = tables.Column("provided_policy_rule_sets", + sortable=False, + verbose_name=_("Provided Rule Sets")) + consumed_policy_rule_sets = tables.Column("consumed_policy_rule_sets", + sortable=False, + verbose_name=_("Consumed Rule Sets")) + external_segments = tables.Column("external_segments", + verbose_name=_("External Connectivity")) + + class Meta(object): + name = "external_policy_targetstable" + verbose_name = _("External Group") + table_actions = (AddExternalPTGLink, DeleteExternalPTGLink) + row_actions = (UpdateExternalPTGLink, DeleteExternalPTGLink,) + + class LaunchVMLink(tables.LinkAction): name = "launch_vm" verbose_name = _("Create Member") @@ -166,8 +214,8 @@ class AddProvidedLink(tables.LinkAction): def get_link_url(self): return reverse("horizon:project:policytargets:add_provided_prs", - kwargs={'policy_target_id': - self.table.kwargs['policy_target_id']}) + kwargs={'policy_target_id': + self.table.kwargs['policy_target_id']}) class RemoveProvidedLink(tables.LinkAction): @@ -196,6 +244,28 @@ class ProvidedContractsTable(tables.DataTable): table_actions = (AddProvidedLink, RemoveProvidedLink,) +class ExtAddProvidedLink(AddProvidedLink): + + def get_link_url(self): + return reverse("horizon:project:policytargets:ext_add_provided_prs", + kwargs={'ext_policy_target_id': + self.table.kwargs['ext_policy_target_id']}) + + +class ExtRemoveProvidedLink(RemoveProvidedLink): + + def get_link_url(self): + return reverse("horizon:project:policytargets:ext_remove_provided_prs", + kwargs={'ext_policy_target_id': + self.table.kwargs['ext_policy_target_id']}) + + +class ExtProvidedContractsTable(ProvidedContractsTable): + + class Meta(ProvidedContractsTable.Meta): + table_actions = (ExtAddProvidedLink, ExtRemoveProvidedLink,) + + class AddConsumedLink(tables.LinkAction): name = "add_consumed" verbose_name = _("Add Consumed Policy Rule Set") @@ -232,3 +302,25 @@ class ConsumedContractsTable(tables.DataTable): name = 'consumed_policy_rule_sets' verbose_name = _("Consumed Policy Rule Set") table_actions = (AddConsumedLink, RemoveConsumedLink,) + + +class ExtAddConsumedLink(AddConsumedLink): + + def get_link_url(self): + return reverse("horizon:project:policytargets:ext_add_consumed_prs", + kwargs={'ext_policy_target_id': + self.table.kwargs['ext_policy_target_id']}) + + +class ExtRemoveConsumedLink(RemoveConsumedLink): + + def get_link_url(self): + return reverse("horizon:project:policytargets:ext_remove_consumed_prs", + kwargs={'ext_policy_target_id': + self.table.kwargs['ext_policy_target_id']}) + + +class ExtConsumedContractsTable(ConsumedContractsTable): + + class Meta(ConsumedContractsTable.Meta): + table_actions = (ExtAddConsumedLink, ExtRemoveConsumedLink,) diff --git a/gbpui/panels/policytargets/tabs.py b/gbpui/panels/policytargets/tabs.py index 1485779..4f81292 100644 --- a/gbpui/panels/policytargets/tabs.py +++ b/gbpui/panels/policytargets/tabs.py @@ -25,11 +25,12 @@ from gbpui import column_filters as gfilters import tables PTGsTable = tables.PTGsTable +External_PTGsTable = tables.ExternalPTGsTable class PTGsTab(tabs.TableTab): table_classes = (PTGsTable,) - name = _("Groups") + name = _("Internal") slug = "policytargets" template_name = "horizon/common/_detail_table.html" @@ -48,9 +49,32 @@ class PTGsTab(tabs.TableTab): return policy_targets +class ExternalPTGsTab(tabs.TableTab): + table_classes = (External_PTGsTable,) + name = _("External") + slug = "externalpolicytargets" + template_name = "horizon/common/_detail_table.html" + + def get_external_policy_targetstable_data(self): + external_policy_targets = [] + try: + external_policy_targets = client.ext_policy_target_list( + self.tab_group.request, + tenant_id=self.tab_group.request.user.tenant_id) + a = lambda x, y: gfilters.update_policy_target_attributes(x, y) + external_policy_targets = [a(self.request, item) + for item in external_policy_targets] + except Exception as e: + msg = _('Unable to retrieve policy_target list. %s') % (str(e)) + exceptions.handle(self.tab_group.request, msg) + for policy_target in external_policy_targets: + policy_target.set_id_as_name_if_empty() + return external_policy_targets + + class PTGTabs(tabs.TabGroup): slug = "policy_targettabs" - tabs = (PTGsTab,) + tabs = (PTGsTab, ExternalPTGsTab) sticky = True @@ -186,3 +210,55 @@ class PTGMemberTabs(tabs.TabGroup): slug = 'member_tabs' tabs = (InstancesTab, ProvidedTab, ConsumedTab, PTGDetailsTab,) stiky = True + + +class ExtProvidedTab(ProvidedTab): + table_classes = (tables.ExtProvidedContractsTable,) + + def get_provided_policy_rule_sets_data(self): + try: + ext_policy_targetid = self.tab_group.kwargs['ext_policy_target_id'] + ext_policy_target = client.ext_policy_target_get( + self.request, ext_policy_targetid) + provided_policy_rule_set_ids = ext_policy_target.get( + 'provided_policy_rule_sets') + provided_policy_rule_sets = [] + for _id in provided_policy_rule_set_ids: + provided_policy_rule_sets.append( + client.policy_rule_set_get(self.request, _id)) + provided_policy_rule_sets = [gfilters.update_pruleset_attributes( + self.request, item) for item in provided_policy_rule_sets] + return provided_policy_rule_sets + except Exception: + error_message = _('Unable to get provided rule sets') + exceptions.handle(self.request, error_message) + return [] + + +class ExtConsumedTab(ConsumedTab): + table_classes = (tables.ExtConsumedContractsTable,) + + def get_consumed_policy_rule_sets_data(self): + try: + ext_policy_targetid = self.tab_group.kwargs['ext_policy_target_id'] + ext_policy_target = client.ext_policy_target_get( + self.request, ext_policy_targetid) + consumed_policy_rule_set_ids = ext_policy_target.get( + 'consumed_policy_rule_sets') + consumed_policy_rule_sets = [] + for _id in consumed_policy_rule_set_ids: + consumed_policy_rule_sets.append( + client.policy_rule_set_get(self.request, _id)) + consumed_policy_rule_sets = [gfilters.update_pruleset_attributes( + self.request, item) for item in consumed_policy_rule_sets] + return consumed_policy_rule_sets + except Exception: + error_message = _('Unable to get consumed rule sets') + exceptions.handle(self.request, error_message) + return [] + + +class ExternalPTGMemberTabs(tabs.TabGroup): + slug = 'members' + tabs = (ExtProvidedTab, ExtConsumedTab) + sticky = True diff --git a/gbpui/panels/policytargets/templates/policytargets/_ext_add_consumed_prs.html b/gbpui/panels/policytargets/templates/policytargets/_ext_add_consumed_prs.html new file mode 100644 index 0000000..14aa82f --- /dev/null +++ b/gbpui/panels/policytargets/templates/policytargets/_ext_add_consumed_prs.html @@ -0,0 +1,25 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} +{% load url from future %} + +{% block form_id %}add_consumed_form{% endblock %} +{% block form_action %}{% url 'horizon:project:policytargets:ext_add_consumed_prs' ext_policy_target_id %}{% endblock %} + +{% block modal-header %}{% trans "Add " %}{% endblock %} + +{% block modal-body %} +
+
+ {% include "horizon/common/_form_fields.html" %} +
+
+
+

{% trans "Description:" %}

+

{% trans "Add Consumed Policy Rule Set. Press Ctrl to select multiple items." %}

+
+{% endblock %} + +{% block modal-footer %} + + {% trans "Cancel" %} +{% endblock %} diff --git a/gbpui/panels/policytargets/templates/policytargets/_ext_add_provided_prs.html b/gbpui/panels/policytargets/templates/policytargets/_ext_add_provided_prs.html new file mode 100644 index 0000000..2686d72 --- /dev/null +++ b/gbpui/panels/policytargets/templates/policytargets/_ext_add_provided_prs.html @@ -0,0 +1,25 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} +{% load url from future %} + +{% block form_id %}ext_add_provider_form{% endblock %} +{% block form_action %}{% url 'horizon:project:policytargets:ext_add_provided_prs' ext_policy_target_id %}{% endblock %} + +{% block modal-header %}{% trans "Add Provided PRS" %}{% endblock %} + +{% block modal-body %} +
+
+ {% include "horizon/common/_form_fields.html" %} +
+
+
+

{% trans "Description:" %}

+

{% trans "Add Consumed Policy Rule Set. Press Ctrl to select multiple items." %}

+
+{% endblock %} + +{% block modal-footer %} + + {% trans "Cancel" %} +{% endblock %} diff --git a/gbpui/panels/policytargets/templates/policytargets/_ext_remove_consumed_prs.html b/gbpui/panels/policytargets/templates/policytargets/_ext_remove_consumed_prs.html new file mode 100644 index 0000000..1f78cfd --- /dev/null +++ b/gbpui/panels/policytargets/templates/policytargets/_ext_remove_consumed_prs.html @@ -0,0 +1,25 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} +{% load url from future %} + +{% block form_id %}remove_contract_form{% endblock %} +{% block form_action %}{% url 'horizon:project:policytargets:ext_remove_consumed_prs' ext_policy_target_id %}{% endblock %} + +{% block modal-header %}{% trans "Remove Policy Rule Set" %}{% endblock %} + +{% block modal-body %} +
+
+ {% include "horizon/common/_form_fields.html" %} +
+
+
+

{% trans "Description:" %}

+

{% trans "Remove Consumed Policy Rule Set. Press Ctrl to select multiple items." %}

+
+{% endblock %} + +{% block modal-footer %} + + {% trans "Cancel" %} +{% endblock %} diff --git a/gbpui/panels/policytargets/templates/policytargets/_ext_remove_provided_prs.html b/gbpui/panels/policytargets/templates/policytargets/_ext_remove_provided_prs.html new file mode 100644 index 0000000..84ab3ea --- /dev/null +++ b/gbpui/panels/policytargets/templates/policytargets/_ext_remove_provided_prs.html @@ -0,0 +1,25 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} +{% load url from future %} + +{% block form_id %}add_consumed_form{% endblock %} +{% block form_action %}{% url 'horizon:project:policytargets:ext_remove_provided_prs' ext_policy_target_id %}{% endblock %} + +{% block modal-header %}{% trans "Remove Provided PRS" %}{% endblock %} + +{% block modal-body %} +
+
+ {% include "horizon/common/_form_fields.html" %} +
+
+
+

{% trans "Description:" %}

+

{% trans "Remove Consumed Policy Rule Set. Press Ctrl to select multiple items." %}

+
+{% endblock %} + +{% block modal-footer %} + + {% trans "Cancel" %} +{% endblock %} diff --git a/gbpui/panels/policytargets/templates/policytargets/_update_external_policy_target.html b/gbpui/panels/policytargets/templates/policytargets/_update_external_policy_target.html new file mode 100644 index 0000000..809a7ed --- /dev/null +++ b/gbpui/panels/policytargets/templates/policytargets/_update_external_policy_target.html @@ -0,0 +1,25 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} +{% load url from future %} + +{% block form_id %}update_external_policy_target_form{% endblock %} +{% block form_action %}{% url 'horizon:project:policytargets:update_ext_policy_target' ext_policy_target_id %}{% endblock %} + +{% block modal-header %}{% trans "Edit Group" %}{% endblock %} + +{% block modal-body %} +
+
+ {% include "horizon/common/_form_fields.html" %} +
+
+
+

{% trans "Description:" %}

+

{% trans "You may update External Policy details here." %}

+
+{% endblock %} + +{% block modal-footer %} + + {% trans "Cancel" %} +{% endblock %} diff --git a/gbpui/panels/policytargets/urls.py b/gbpui/panels/policytargets/urls.py index 4f0693e..21cf3ac 100644 --- a/gbpui/panels/policytargets/urls.py +++ b/gbpui/panels/policytargets/urls.py @@ -23,19 +23,38 @@ urlpatterns = patterns('', url(r'^addpolicy_target$', views.AddPTGView.as_view(), name='addpolicy_target'), + url(r'^addexternal_policy_target$', + views.AddExternalPTGView.as_view(), + name='addexternal_policy_target'), url(r'^updatepolicy_target/' '(?P[^/]+)/$', views.UpdatePTGView.as_view(), name='updatepolicy_target'), + url(r'^update_ext_policy_target/' + '(?P[^/]+)/$', + views.UpdateExternalPTGView.as_view(), + name='update_ext_policy_target'), url(r'^policy_target/(?P[^/]+)/$', views.PTGDetailsView.as_view(), name='policy_targetdetails'), + url(r'^ext_policy_target/' + '(?P[^/]+)/$', + views.ExternalPTGDetailsView.as_view(), + name='ext_policy_targetdetails'), url(r'^addvm/(?P[^/]+)/$', views.LaunchVMView.as_view(), name='addvm'), + url(r'^ext_add_policy_rule_set/' + '(?P[^/]+)/$', + views.ExtAddProvidedPRSView.as_view(), + name='ext_add_provided_prs'), url(r'^add_policy_rule_set/' '(?P[^/]+)/$', views.AddProvidedPRSView.as_view(), name='add_provided_prs'), + url(r'^ext_remove_policy_rule_set/' + '(?P[^/]+)/$', + views.ExtRemoveProvidedPRSView.as_view(), + name='ext_remove_provided_prs'), url(r'^remove_policy_rule_set/' '(?P[^/]+)/$', views.RemoveProvidedPRSView.as_view(), @@ -43,7 +62,15 @@ urlpatterns = patterns('', url(r'^add_consumed/(?P[^/]+)/$', views.AddConsumedPRSView.as_view(), name='add_consumed_prs'), + url(r'^ext_add_consumed/' + '(?P[^/]+)/$', + views.ExtAddConsumedPRSView.as_view(), + name='ext_add_consumed_prs'), url(r'^remove_consumed/(?P[^/]+)/$', views.RemoveConsumedPRSView.as_view(), name='remove_consumed_prs'), + url(r'^ext_remove_consumed/' + '(?P[^/]+)/$', + views.ExtRemoveConsumedPRSView.as_view(), + name='ext_remove_consumed_prs'), ) diff --git a/gbpui/panels/policytargets/views.py b/gbpui/panels/policytargets/views.py index a931f88..8cd3093 100644 --- a/gbpui/panels/policytargets/views.py +++ b/gbpui/panels/policytargets/views.py @@ -32,6 +32,7 @@ PTGTabs = policy_target_tabs.PTGTabs PTGDetailsTabs = policy_target_tabs.PTGDetailsTabs AddPTG = policy_target_workflows.AddPTG +AddExternalPTG = policy_target_workflows.AddExternalPTG class IndexView(tabs.TabView): @@ -41,16 +42,27 @@ class IndexView(tabs.TabView): 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)) - for obj_id in obj_ids: - try: - client.policy_target_delete(request, obj_id) - messages.success(request, + if obj_type == 'policytarget': + for obj_id in obj_ids: + try: + client.policy_target_delete(request, obj_id) + messages.success(request, _('Deleted Group %s') % obj_id) - except Exception as e: - exceptions.handle(request, + except Exception as e: + exceptions.handle(request, _('Unable to delete Group. %s') % e) + if obj_type == 'externalpolicytarget': + for obj_id in obj_ids: + try: + client.ext_policy_target_delete(request, obj_id) + messages.success(request, + _('Deleted External Group %s') % obj_id) + except Exception as e: + exceptions.handle(request, + _('Unable to delete External Group. %s') % e) return self.get(request, *args, **kwargs) @@ -59,6 +71,10 @@ class AddPTGView(workflows.WorkflowView): template_name = "project/policytargets/addpolicy_target.html" +class AddExternalPTGView(workflows.WorkflowView): + workflow_class = AddExternalPTG + + class PTGDetailsView(tabs.TabbedTableView): tab_group_class = (policy_target_tabs.PTGMemberTabs) template_name = 'project/policytargets/group_details.html' @@ -74,6 +90,22 @@ class PTGDetailsView(tabs.TabbedTableView): return context +class ExternalPTGDetailsView(tabs.TabbedTableView): + tab_group_class = (policy_target_tabs.ExternalPTGMemberTabs) + template_name = 'project/policytargets/group_details.html' + + def get_context_data(self, **kwargs): + context = super(ExternalPTGDetailsView, self).get_context_data( + **kwargs) + try: + ext_policy_target = client.ext_policy_target_get( + self.request, context['ext_policy_target_id']) + context['policy_target'] = ext_policy_target + except Exception: + pass + return context + + class LaunchVMView(workflows.WorkflowView): workflow_class = policy_target_workflows.LaunchInstance template_name = "project/policytargets/add_vm.html" @@ -116,6 +148,65 @@ class UpdatePTGView(forms.ModalFormView): return self.kwargs +class UpdateExternalPTGView(forms.ModalFormView): + form_class = policy_target_forms.UpdateExternalPolicyTargetForm + template_name = "project/policytargets/update_external_policy_target.html" + context_object_name = 'external_policy_target' + success_url = reverse_lazy("horizon:project:policytargets:index") + + def get_context_data(self, **kwargs): + context = super(UpdateExternalPTGView, self).get_context_data(**kwargs) + context["ext_policy_target_id"] = self.kwargs['ext_policy_target_id'] + obj = self._get_object() + if obj: + context['name'] = obj.name + return context + + @memoized.memoized_method + def _get_object(self, *args, **kwargs): + ext_policy_target_id = self.kwargs['ext_policy_target_id'] + try: + ext_policy_target = client.ext_policy_target_get( + self.request, ext_policy_target_id) + ext_policy_target.set_id_as_name_if_empty() + return ext_policy_target + except Exception: + redirect = self.success_url + msg = _('Unable to retrieve policy_target details.') + exceptions.handle(self.request, msg, redirect=redirect) + + def get_initial(self): + return self.kwargs + + +class ExtAddProvidedPRSView(forms.ModalFormView): + form_class = policy_target_forms.ExtAddProvidedPRSForm + template_name = "project/policytargets/ext_add_provided_prs.html" + + def get_context_data(self, **kwargs): + context = super(ExtAddProvidedPRSView, self).get_context_data(**kwargs) + context["ext_policy_target_id"] = self.kwargs['ext_policy_target_id'] + return context + + def get_initial(self): + return self.kwargs + + +class ExtRemoveProvidedPRSView(forms.ModalFormView): + form_class = policy_target_forms.ExtRemoveProvidedPRSForm + template_name = \ + "project/policytargets/ext_remove_provided_prs.html" + + def get_context_data(self, **kwargs): + context = super(ExtRemoveProvidedPRSView, self).get_context_data( + **kwargs) + context["ext_policy_target_id"] = self.kwargs['ext_policy_target_id'] + return context + + def get_initial(self): + return self.kwargs + + class AddProvidedPRSView(forms.ModalFormView): form_class = policy_target_forms.AddProvidedPRSForm template_name = "project/policytargets/add_provided_prs.html" @@ -142,6 +233,34 @@ class RemoveProvidedPRSView(forms.ModalFormView): return self.kwargs +class ExtAddConsumedPRSView(forms.ModalFormView): + form_class = policy_target_forms.ExtAddConsumedPRSForm + template_name = "project/policytargets/ext_add_consumed_prs.html" + + def get_context_data(self, **kwargs): + context = super(ExtAddConsumedPRSView, self).get_context_data(**kwargs) + context["ext_policy_target_id"] = self.kwargs['ext_policy_target_id'] + return context + + def get_initial(self): + return self.kwargs + + +class ExtRemoveConsumedPRSView(forms.ModalFormView): + form_class = policy_target_forms.ExtRemoveConsumedPRSForm + template_name = \ + "project/policytargets/ext_remove_consumed_prs.html" + + def get_context_data(self, **kwargs): + context = super(ExtRemoveConsumedPRSView, self).get_context_data( + **kwargs) + context["ext_policy_target_id"] = self.kwargs['ext_policy_target_id'] + return context + + def get_initial(self): + return self.kwargs + + class AddConsumedPRSView(forms.ModalFormView): form_class = policy_target_forms.AddConsumedPRSForm template_name = "project/policytargets/add_consumed_prs.html" diff --git a/gbpui/panels/policytargets/workflows.py b/gbpui/panels/policytargets/workflows.py index 89f4ccc..3e09c8a 100644 --- a/gbpui/panels/policytargets/workflows.py +++ b/gbpui/panels/policytargets/workflows.py @@ -187,8 +187,8 @@ class AddPTGAction(workflows.Action): super(AddPTGAction, self).__init__(request, *args, **kwargs) class Meta(object): - name = _("Create Group") - help_text = _("Create a new Group") + name = _("Group") + help_text = _("Create Internal Group") class AddPTGStep(workflows.Step): @@ -202,7 +202,7 @@ class AddPTGStep(workflows.Step): class AddPTG(workflows.Workflow): slug = "addpolicy_target" - name = _("Create Group") + name = _("Create Internal Group") finalize_button_name = _("Create") success_message = _('Create Group "%s".') failure_message = _('Unable to create Group "%s".') @@ -229,6 +229,101 @@ class AddPTG(workflows.Workflow): return False +class ExternalConnectivityAction(workflows.Action): + external_segments = forms.ChoiceField( + label=_("External Connectivity"), + help_text=_("Select external segment for Group.")) + + class Meta(object): + name = _("External Connectivity") + help_text = _( + "Select External Connectivity for Group.") + + def populate_external_segments_choices(self, request, context): + external_connectivities = [] + try: + external_connectivities = client.externalconnectivity_list( + request, tenant_id=request.user.tenant_id) + for p in external_connectivities: + p.set_id_as_name_if_empty() + ext_conn_list = sorted(external_connectivities, + key=lambda segment: segment.name) + ext_conn_list = \ + [(p.id, p.name + ":" + p.id) for p in ext_conn_list] + except Exception as e: + exceptions.handle(request, + _("Unable to retrieve policies (%(error)s).") + % {'error': str(e)}) + return ext_conn_list + + +class ExternalConnectivityStep(workflows.Step): + action_class = ExternalConnectivityAction + name = _("External Connectivity") + contributes = ("external_segments",) + + def contribute(self, data, context): + ext_seg_list = [] + ext_seg_list.append(data['external_segments']) + context['external_segments'] = ext_seg_list + return context + + +class ExtAddPTGAction(workflows.Action): + name = forms.CharField(max_length=80, + label=_("Name")) + description = forms.CharField(max_length=80, + label=_("Description"), + required=False) + shared = forms.BooleanField(label=_("Shared"), + initial=False, required=False) + + def __init__(self, request, *args, **kwargs): + super(ExtAddPTGAction, self).__init__(request, *args, **kwargs) + + class Meta(object): + name = _("Group") + help_text = _("Create External Group") + + +class ExtAddPTGStep(workflows.Step): + action_class = ExtAddPTGAction + contributes = ("name", "description", "shared") + + def contribute(self, data, context): + context = super(ExtAddPTGStep, self).contribute(data, context) + return context + + +class AddExternalPTG(workflows.Workflow): + slug = "addexternal_policy_target" + name = _("Create External Group") + finalize_button_name = _("Create") + success_message = _('Create External Group "%s".') + failure_message = _('Unable to create External Group "%s".') + success_url = "horizon:project:policytargets:index" + default_steps = (ExtAddPTGStep, + SelectPolicyRuleSetStep, + ExternalConnectivityStep,) + wizard = True + + def format_status_message(self, message): + return message % self.context.get('name') + + def handle(self, request, context): + try: + if context.get('name'): + context['name'] = html.escape(context['name']) + if context.get('description'): + context['description'] = html.escape(context['description']) + group = client.ext_policy_target_create(request, **context) + return group + except Exception as e: + msg = self.format_status_message(self.failure_message) + str(e) + exceptions.handle(request, msg) + return False + + KEYPAIR_IMPORT_URL = "horizon:project:access_and_security:keypairs:import"