Merge "Added service profile UI support."

This commit is contained in:
Jenkins 2015-08-17 05:37:04 +00:00 committed by Gerrit Code Review
commit 360e81b4df
11 changed files with 284 additions and 11 deletions

View File

@ -144,6 +144,15 @@ class ServiceChainInstance(neutron.NeutronAPIDictWrapper):
return sc_instance_dict
class ServiceProfile(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron service profile."""
def get_dict(self):
sc_profile_dict = self._apidict
return sc_profile_dict
def policy_target_create(request, **kwargs):
body = {'policy_target_group': kwargs}
policy_target = gbpclient(request).create_policy_target_group(
@ -505,3 +514,26 @@ def update_servicechain_instance(request, scinstance_id, **kwargs):
def delete_servicechain_instance(request, scinstance_id):
gbpclient(request).delete_servicechain_instance(scinstance_id)
def serviceprofile_list(request, **kwargs):
sc_profile = gbpclient(request).list_service_profiles(True,
**kwargs).get('service_profiles')
return [ServiceProfile(item) for item in sc_profile]
def get_service_profile(request, service_profile_id):
service_profile = gbpclient(request).show_service_profile(
service_profile_id).get('service_profile')
return ServiceProfile(service_profile)
def create_service_profile(request, **kwargs):
body = {'service_profile': kwargs}
service_profile = gbpclient(request).create_service_profile(
body).get('service_profile')
return ServiceProfile(service_profile)
def delete_service_profile(request, service_profile_id):
gbpclient(request).delete_service_profile(service_profile_id)

View File

@ -154,17 +154,41 @@ def update_sc_spec_attributes(request, scspec):
scn_url = "horizon:project:network_services:sc_node_details"
for n in nodes:
url = reverse(scn_url, kwargs={'scnode_id': n.id})
service_profile_id = n.service_profile_id
try:
service_profile = client.get_service_profile(request,
service_profile_id)
service_type = service_profile.service_type
except Exception:
pass
val.append(
"<td><span class='glyphicon glyphicon-arrow-right'></span></td>")
scnode = "<td><a href='" + url + "' style='font-size: 9px;' >" \
+ "<img src='" + img_src + n.service_type + ".png'>" \
+ "<br>" + n.name + " (" + n.service_type + ")</a></td>"
+ "<img src='" + img_src + service_type + ".png'>" \
+ "<br>" + n.name + " (" + service_type + ")</a></td>"
val.append(scnode)
val.append("</tr></table>")
setattr(scspec, 'nodes', mark_safe("".join(val)))
return scspec
def update_sc_node_attributes(request, scnode):
t = "<p style='margin-bottom:0px'>"
val = [t]
sp_url = "horizon:project:network_services:service_profile_details"
url = reverse(sp_url, kwargs={'sp_id': scnode.service_profile_id})
try:
service_profile = client.get_service_profile(request,
scnode.service_profile_id)
sp = "<a href='" + url + "'>" + service_profile.name + ' : ' + \
service_profile.service_type + '</a></p>'
val.append(sp)
except Exception:
return scnode
setattr(scnode, 'service_profile', mark_safe("".join(val)))
return scnode
def update_sc_instance_attributes(request, scinstance):
ptg_url = "horizon:project:policytargets:policy_targetdetails"
clsurl = "horizon:project:application_policy:policyclassifierdetails"

View File

@ -42,12 +42,49 @@ class BaseUpdateForm(forms.SelfHandlingForm):
return updated_data
class CreateServiceProfileForm(forms.SelfHandlingForm):
name = forms.CharField(max_length=80, label=_("Name"))
description = forms.CharField(
max_length=80, label=_("Description"), required=False)
vendor = forms.CharField(
max_length=80, label=_("Vendor"), required=True)
service_flavor = forms.CharField(
max_length=80, label=_("Service Flavor"), required=False)
service_type = forms.ChoiceField(
label=_("Service Type"), choices=SERVICE_TYPES)
insertion_mode = forms.ChoiceField(
label=_("Insertion Mode"), choices=[('l3', 'L3'), ('l2', 'L2')])
shared = forms.BooleanField(label=_("Shared"),
initial=False, required=False)
def handle(self, request, context):
url = reverse("horizon:project:network_services:index")
try:
if context.get('name'):
context['name'] = html.escape(context['name'])
if context.get('description'):
context['description'] = html.escape(context['description'])
if context.get('vendor'):
context['vendor'] = html.escape(context['vendor'])
if context.get('service_flavor'):
context['service_flavor'] = html.escape(
context['service_flavor'])
client.create_service_profile(request, **context)
msg = _("Service Profile Created Successfully")
messages.success(request, msg)
return http.HttpResponseRedirect(url)
except Exception as e:
msg = _("Failed to create Service Profile. %s") % (str(e))
LOG.error(msg)
exceptions.handle(request, msg, redirect=shortcuts.redirect)
class CreateServiceChainNodeForm(forms.SelfHandlingForm):
name = forms.CharField(max_length=80, label=_("Name"))
description = forms.CharField(
max_length=80, label=_("Description"), required=False)
service_type = forms.ChoiceField(
label=_("Service Type"), choices=SERVICE_TYPES)
service_profile_id = forms.ChoiceField(
label=_("Service Profile"))
config_type = forms.ChoiceField(label=_("Config Type"),
choices=[('file', 'Heat Template'),
('string', 'Config String')],
@ -70,6 +107,21 @@ class CreateServiceChainNodeForm(forms.SelfHandlingForm):
shared = forms.BooleanField(label=_("Shared"),
initial=False, required=False)
def __init__(self, request, *args, **kwargs):
super(CreateServiceChainNodeForm, self).__init__(
request, *args, **kwargs)
try:
service_profile_tuples = []
service_profile_list = client.serviceprofile_list(self.request)
for service_profile in service_profile_list:
sp = (service_profile.id,
service_profile.name + ' : ' + service_profile.service_type)
service_profile_tuples.append(sp)
self.fields['service_profile_id'].choices = service_profile_tuples
except Exception:
msg = _("Failed to retrive Service profile details.")
LOG.error(msg)
def clean(self):
cleaned_data = super(CreateServiceChainNodeForm, self).clean()
files = self.request.FILES

View File

@ -91,8 +91,8 @@ class ServiceChainNodeTable(tables.DataTable):
link="horizon:project:network_services:sc_node_details")
description = tables.Column("description",
verbose_name=_("Description"))
service_type = tables.Column("service_type",
verbose_name=_("Service Type"))
service_profile = tables.Column("service_profile",
verbose_name=_("Service Profile"))
class Meta(object):
name = "service_chain_node_table"
@ -149,3 +149,37 @@ class ServiceChainInstanceTable(tables.DataTable):
table_actions = (CreateServiceChainInstanceLink,)
row_actions = (
EditServiceChainInstanceLink, DeleteServiceChainInstanceLink,)
class CreateServiceProfileLink(tables.LinkAction):
name = "create_service_profile_link"
verbose_name = _("Create Service Profile")
url = "horizon:project:network_services:create_service_profile"
classes = ("ajax-modal", "btn-create_service_profile")
class DeleteServiceProfileLink(tables.DeleteAction):
name = "deleteserviceprofile"
action_present = _("Delete")
action_past = _("Scheduled deletion of %(data_type)s")
data_type_singular = _("ServiceProfile")
data_type_plural = _("ServiceProfiles")
class ServiceProfileTable(tables.DataTable):
name = tables.Column("name", verbose_name=_("Name"),
link="horizon:project:network_services:service_profile_details")
description = tables.Column("description",
verbose_name=_("Description"))
service_type = tables.Column("service_type",
verbose_name=_("Service Type"))
insertion_mode = tables.Column("insertion_mode",
verbose_name=_("Insertion Mode"))
vendor = tables.Column("vendor", verbose_name=_("Vendor"))
class Meta(object):
name = "service_profile_table"
verbose_name = _("Service Profile")
table_actions = (CreateServiceProfileLink,
DeleteServiceProfileLink,)
row_actions = (DeleteServiceProfileLink,)

View File

@ -55,6 +55,8 @@ class ServiceChainNodeTab(tabs.TableTab):
try:
nodes = client.servicechainnode_list(self.request,
tenant_id=self.request.user.tenant_id)
nodes = [gfilters.update_sc_node_attributes(
self.request, item) for item in nodes]
except Exception:
pass
return nodes
@ -78,12 +80,50 @@ class ServiceChainInstanceTab(tabs.TableTab):
return instances
class ServiceProfileTab(tabs.TableTab):
name = _("Service Profiles")
table_classes = (ns_tables.ServiceProfileTable,)
slug = "service_profile"
template_name = "horizon/common/_detail_table.html"
def get_service_profile_table_data(self):
service_profiles = []
try:
service_profiles = client.serviceprofile_list(self.request)
except Exception:
pass
return service_profiles
class ServiceChainTabs(tabs.TabGroup):
slug = "service_chain_spec_tabs"
tabs = (ServiceChainSpecTab, ServiceChainNodeTab,)
tabs = (ServiceChainSpecTab, ServiceChainNodeTab, ServiceProfileTab,)
sticky = True
class ServiceProfileDetailsTab(tabs.Tab):
name = _("Service Profile Details")
slug = "serviceprofile_details"
template_name = "project/network_services/_serviceprofile_details.html"
failure_url = reverse_lazy('horizon:project:network_services:index')
def get_context_data(self, request):
service_profile_id = self.tab_group.kwargs['sp_id']
try:
service_profile = client.get_service_profile(
request, service_profile_id)
except Exception:
exceptions.handle(request, _(
'Unable to retrieve service profile details.'),
redirect=self.failure_url)
return {'service_profile': service_profile}
class ServiceProfileDetailsTabGroup(tabs.TabGroup):
slug = 'scnode_details'
tabs = (ServiceProfileDetailsTab,)
class ServiceChainNodeDetailsTab(tabs.Tab):
name = _("Service Chain Node Details")
slug = "scnode_details"

View File

@ -0,0 +1,26 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% load url from future %}
{% block form_id %}create_service_profile_form{% endblock %}
{% block form_action %}{% url "horizon:project:network_services:create_service_profile" %}{% endblock %}
{% block modal_id %}create_service_profile_modal{% endblock %}
{% block modal-header %}{% trans "Create Service Profile" %}{% endblock %}
{% block modal-body %}
<div class="left">
<fieldset>
{% include "horizon/common/_form_fields.html" %}
</fieldset>
</div>
<div class="right">
<h3>{% trans "Description" %}:</h3>
<p>{% trans "Create Service Profile." %}</p>
</div>
{% endblock %}
{% block modal-footer %}
<input class="btn btn-primary pull-right" type="submit" value="{% trans "Save changes" %}" />
<a href="{% url "horizon:project:network_services:index" %}" class="btn btn-default secondary cancel close">{% trans "Cancel" %}</a>
{% endblock %}

View File

@ -16,8 +16,8 @@
<dt>{% trans "ID" %}</dt>
<dd>{{ scnode.id }} </dd>
<dt>{% trans "Service Type" %}</dt>
<dd>{{ scnode.service_type }} </dd>
<dt>{% trans "Service Profile" %}</dt>
<dd><a href="{% url 'horizon:project:network_services:service_profile_details' sp_id=scnode.service_profile_id %}">{{ scnode.service_profile_id }}</a></dd>
<dt>{% trans "Shared" %}</dt>
<dd>{{ scnode.shared }}</dd>

View File

@ -24,7 +24,7 @@
<thead>
<tr>
<th>Name</th>
<th>Service Type</th>
<th>Service Profile</th>
<th>Config</th>
</tr>
</thead>
@ -34,7 +34,10 @@
<a href="{% url 'horizon:project:network_services:sc_node_details' scnode_id=node.id %}">
{{node.name}}</a>
</td>
<td>{{node.service_type}}</td>
<td>
<a href="{% url 'horizon:project:network_services:service_profile_details' sp_id=node.service_profile_id %}">
{{ node.service_profile_id }}</a>
</td>
<td>
<div style ="white-space:pre;overflow-y: scroll;height:300px;background-color:#EEEEEE">{{node.config}}</div>
</td>

View File

@ -0,0 +1,32 @@
{% load i18n sizeformat parse_date %}
{% load url from future %}
<div class="info row detail">
<hr class="header_rule">
<dl style="font-size:14px">
<dt>{% trans "Name" %}</dt>
<dd>{{ service_profile.name|default:_("-") }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ service_profile.description|default:_("-") }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ service_profile.id }} </dd>
<dt>{% trans "Service Type" %}</dt>
<dd>{{ service_profile.service_type }} </dd>
<dt>{% trans "Insertion Mode" %}</dt>
<dd>{{ service_profile.insertion_mode }}</dd>
<dt>{% trans "Vendor" %}</dt>
<dd>{{ service_profile.vendor }}</dd>
<dt>{% trans "Service Flavor" %}</dt>
<dd>{{ service_profile.service_flavor|default:_("-") }}</dd>
<dt>{% trans "Shared" %}</dt>
<dd>{{ service_profile.shared }}</dd>
</dl>
</div>

View File

@ -18,6 +18,12 @@ import views
urlpatterns = patterns('',
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^create_service_profile$',
views.CreateServiceProfileView.as_view(),
name='create_service_profile'),
url(r'^serviceprofile/(?P<sp_id>[^/]+)/$',
views.ServiceProfileDetailsView.as_view(),
name='service_profile_details'),
url(r'^create_sc_node$',
views.CreateServiceChainNodeView.as_view(),
name='create_sc_node'),

View File

@ -60,9 +60,33 @@ class IndexView(tabs.TabView):
except Exception as e:
exceptions.handle(request,
_('Unable to delete . %s') % e)
if obj_type == 'serviceprofile':
for obj_id in obj_ids:
try:
client.delete_service_profile(request, obj_id)
messages.success(request,
_('Deleted %s') % obj_id)
except Exception as e:
exceptions.handle(request,
_('Unable to delete . %s') % e)
return self.get(request, *args, **kwargs)
class ServiceProfileDetailsView(tabs.TabView):
tab_group_class = (ns_tabs.ServiceProfileDetailsTabGroup)
template_name = 'project/network_services/details_tabs.html'
class CreateServiceProfileView(forms.ModalFormView):
form_class = ns_forms.CreateServiceProfileForm
template_name = "project/network_services/create_service_profile.html"
def get_context_data(self, **kwargs):
context = super(
CreateServiceProfileView, self).get_context_data(**kwargs)
return context
class CreateServiceChainNodeView(forms.ModalFormView):
form_class = ns_forms.CreateServiceChainNodeForm
template_name = "project/network_services/create_service_chain_node.html"