Plan edit - change resource and parameters

User is unable to update the Protection Plan from the dashboard
- updating name, status, resources and parameters.

Change-Id: I5dfcc9507689a27d1a6bfdc9ca8f9f4711ba797a
Closes-Bug: #1643338
This commit is contained in:
zhangshuai 2017-01-16 13:46:05 +08:00
parent f3eec93b83
commit d3f3c06a05
7 changed files with 366 additions and 2 deletions

View File

@ -22,6 +22,9 @@ from horizon import messages
import json
from karbor_dashboard.api import karbor as karborclient
STATUS_CHOICE = [("suspended", "suspended"),
("started", "started")]
class CreateProtectionPlanForm(horizon_forms.SelfHandlingForm):
name = forms.CharField(label=_("Name"))
@ -78,6 +81,50 @@ class CreateProtectionPlanForm(horizon_forms.SelfHandlingForm):
exceptions.handle(request, _('Unable to create protection plan.'))
class UpdateProtectionPlanForm(horizon_forms.SelfHandlingForm):
name = forms.CharField(label=_("Name"), max_length=255, required=False)
status = forms.ChoiceField(label=_('Status'),
choices=STATUS_CHOICE,
widget=forms.Select(attrs={
'class': 'switchable'}))
plan = forms.CharField(
widget=forms.HiddenInput(attrs={"class": "plan"}))
provider = forms.CharField(
widget=forms.HiddenInput(attrs={"class": "provider"}))
resources = forms.CharField(
widget=forms.HiddenInput(attrs={"class": "resources"}))
parameters = forms.CharField(
widget=forms.HiddenInput(attrs={"class": "parameters"}))
def handle(self, request, data):
plan_id = self.initial['plan_id']
status = data["status"]
data_ = {"status": status}
name = data["name"]
if name:
data_.update({"name": name})
resources = json.loads(data["resources"])
if resources:
resources_ = []
for resource in resources:
if resource not in resources_:
resources_.append(resource)
data_.update({"resources": resources_})
try:
new_plan = karborclient.plan_update(request,
plan_id,
data_)
messages.success(request,
_("Protection Plan updated successfully."))
return new_plan
except Exception as e:
msg = _('Unable to update protection plan. ') + e.message
exceptions.handle(request, msg)
class ScheduleProtectForm(horizon_forms.SelfHandlingForm):
id = forms.CharField(label=_("ID"), widget=forms.HiddenInput)
name = forms.CharField(label=_("Name"), widget=forms.HiddenInput)

View File

@ -43,6 +43,16 @@ class ScheduleProtectLink(tables.LinkAction):
return True
class EditPlanLink(tables.LinkAction):
name = "editplan"
verbose_name = _("Edit Plan")
url = "horizon:karbor:protectionplans:update"
classes = ("ajax-modal",)
def allowed(self, request, protectionplan):
return True
class ProtectNowLink(tables.Action):
name = "protectnow"
verbose_name = _("Protect Now")
@ -110,7 +120,7 @@ class ProtectionPlansTable(tables.DataTable):
class Meta(object):
name = 'protectionplans'
verbose_name = _('Protection Plans')
row_actions = (ScheduleProtectLink, ProtectNowLink,
row_actions = (ScheduleProtectLink, EditPlanLink, ProtectNowLink,
DeleteProtectionPlansAction)
table_actions = (ProtectionPlanFilterAction, CreateProtectionPlanLink,
DeleteProtectionPlansAction)

View File

@ -23,4 +23,6 @@ urlpatterns = [
views.ScheduleProtectView.as_view(), name='scheduleprotect'),
url(r'^(?P<plan_id>[^/]+)/detail/$',
views.DetailView.as_view(), name='detail'),
url(r'^(?P<plan_id>[^/]+)/update/$',
views.UpdateView.as_view(), name='update'),
]

View File

@ -12,6 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
import json
import uuid
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _
@ -26,7 +29,6 @@ from karbor_dashboard.api import karbor as karborclient
from karbor_dashboard.protectionplans import forms
from karbor_dashboard.protectionplans import tables
from karborclient.v1 import protectables
import uuid
class IndexView(horizon_tables.DataTableView):
@ -123,6 +125,87 @@ class CreateView(horizon_forms.ModalFormView):
self.get_results([dependent], result.showid, results)
class UpdateView(horizon_forms.ModalFormView):
template_name = 'protectionplans/update.html'
modal_header = _("Update Protection Plan")
form_id = "update_protectionplan_form"
form_class = forms.UpdateProtectionPlanForm
submit_label = _("Update Protection Plan")
submit_url = "horizon:karbor:protectionplans:update"
success_url = reverse_lazy('horizon:karbor:protectionplans:index')
page_title = _("Update Protection Plan")
def get_context_data(self, **kwargs):
context = super(UpdateView, self).get_context_data(**kwargs)
context["instances"] = self.get_protectable_objects()
args = (self.kwargs['plan_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
return context
@memoized.memoized_method
def get_protectable_objects(self):
try:
instances = karborclient.protectable_list_instances(
self.request, "OS::Keystone::Project")
results = []
self.get_results(instances, None, results)
return results
except Exception:
exceptions.handle(
self.request,
_('Unable to retrieve protection resources.'),
redirect=reverse("horizon:karbor:protectionplans:index"))
def get_results(self, instances, showparentid, results):
for instance in instances:
if instance is not None:
resource = {}
resource["id"] = instance.id
resource["type"] = instance.type
resource["name"] = instance.name
resource["showid"] = str(uuid.uuid4())
resource["showparentid"] = showparentid
result = protectables.Instances(self, resource)
results.append(result)
for dependent_resource in instance.dependent_resources:
if dependent_resource is not None:
dependent = karborclient.protectable_get_instance(
self.request,
dependent_resource["type"],
dependent_resource["id"])
self.get_results([dependent], result.showid, results)
@memoized.memoized_method
def get_plan_object(self, *args, **kwargs):
plan_id = self.kwargs['plan_id']
try:
return karborclient.plan_get(self.request, plan_id)
except Exception:
redirect = reverse("horizon:karbor:protectionplans:index")
msg = _('Unable to retrieve protection plan details.')
exceptions.handle(self.request, msg, redirect=redirect)
@memoized.memoized_method
def get_provider_object(self, provider_id):
try:
return karborclient.provider_get(self.request, provider_id)
except Exception:
redirect = reverse("horizon:karbor:protectionplans:index")
msg = _('Unable to retrieve provider details.')
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
initial = super(UpdateView, self).get_initial()
plan = self.get_plan_object()
provider = self.get_provider_object(plan.provider_id)
initial.update({'plan_id': self.kwargs['plan_id'],
'name': getattr(plan, 'name', ''),
'plan': json.dumps(plan._info),
'provider': json.dumps(provider._info)})
return initial
class ScheduleProtectView(horizon_forms.ModalFormView):
template_name = 'protectionplans/scheduleprotect.html'
modal_header = _("Schedule Protect")

View File

@ -0,0 +1,143 @@
/* Copyright (c) 2016 Huawei, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may
not use this file except in compliance with the License. You may obtain
a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
*/
/* set the children check */
function setChecked(node, isChecked) {
if(isChecked) {
node.row.find("input[type=checkbox]").prop("checked", true);
}
else {
node.row.find("input[type=checkbox]").removeAttr("checked");
}
for(var i = 0; i<node.children.length;i++) {
var resourceChild = node.children[i];
setChecked(resourceChild, isChecked);
}
}
/* set the choose resources */
function setProtectedResource() {
var resources = [];
var cbResources = $(".cbresource:checked");
var provider = getProvider($("select[name='provider_id']").val());
var parameters = $.Karbor.getResourceDefaultParameters(provider, "options_schema");
if(cbResources != null) {
cbResources.each(function() {
var cbResource = $(this);
var resource = {};
resource.id = cbResource.closest("tr").attr("resource-id");
resource.type = cbResource.closest("td").next().find("span").html();
resource.name = cbResource.closest("span").nextAll("span.spanresource").eq(0).html();
resources.push(resource);
var parameterbtn = cbResource.closest("tr").find(".editparameters");
var userdata = parameterbtn.data("userdata");
if(userdata!=null) {
parameters[resource.type + "#" + resource.id] = userdata;
}
});
}
$(".resources").val(angular.toJson(resources));
$(".parameters").val(angular.toJson(parameters));
}
horizon.protectionplans_update = {
/* init create plan dialog */
init: function(){
/* init resource tree */
$("#protectionplanUpdateResource").treetable({ expandable: true });
/* init plan resources*/
(function(){
plan = $.parseJSON($(".plan").val());
if(plan.resources != null){
resources = plan.resources
$(resources).each(function() {
resource_id = this.id
node = $("#protectionplanUpdateResource").find("tr[resource-id='"+ resource_id +"']");
node.find("input[type=checkbox]").prop("checked", true);
});
}
})();
/* init protection provider */
(function() {
provider = $.parseJSON($(".provider").val());
$("#protectionplanUpdateResource").find("input[resourcetype]").data("schema", null);
$("#protectionplanUpdateResource").find("input[resourcetype]").data("userdata", null);
if(provider != null) {
if(provider.extended_info_schema != null) {
var result = provider.extended_info_schema['options_schema'];
for(var r in result) {
$("#protectionplanUpdateResource").find("input[resourcetype='" + r + "']").data("schema", result[r]);
$("#protectionplanUpdateResource").find("input[resourcetype='" + r + "']").data("userdata", null);
}
}
}
})();
/* live resource check event */
$(document).on('click', ".cbresource", function() {
var tr = $(this).closest("tr");
var node = $("#protectionplanUpdateResource").treetable("node", tr.attr("data-tt-id"));
setChecked(node, $(this).is(":checked"));
});
/* live resource parameters event */
$(document).on('click',".editparameters", function() {
var schema = $(this).data("schema");
var userdata = $(this).data("userdata");
var resourceid = $(this).closest("tr").attr("resource-id");
if(schema != null) {
var exist_ui_dialogs = $("body").has(".ui-dialog");
if(exist_ui_dialogs.length == 0){
var dialog_data = $.Karbor.createDialog(schema, userdata, resourceid);
$.Karbor.openDialog(dialog_data, "#parametersdialog", "div.dialog_wrapper");
}
}
});
/* bind parameters dialog save button event */
$(document).on('click', "#parametersdialog .btn.btn-primary", function() {
var flag = $.Karbor.check_required($("#parametersdialog"));
if(flag) {
var resourceid = $("#parametersdialog .modal-body").attr("resourceid");
var form_controls = $("#parametersdialog .modal-body .form-control");
var userdata = $.Karbor.getDynamicValue(form_controls);
$("#protectionplanUpdateResource").find("tr[resource-id='" + resourceid + "']")
.find(".editparameters")
.data("userdata", userdata);
$.Karbor.closeDialog("#parametersdialog");
}
});
/* bind create button event */
$(".btn-primary.save").bind("click", function() {
setProtectedResource();
return true;
});
/* bind parameters dialog cancel button event */
$(document).on('click', "#parametersdialog .btn.cancel", function() {
$.Karbor.closeDialog("#parametersdialog");
});
/* bind parameters dialog close button event */
$(document).on('click', "#parametersdialog a.close", function() {
$.Karbor.closeDialog("#parametersdialog");
});
}
};

View File

@ -0,0 +1,69 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% load static %}
{% load compress %}
{% block modal-body %}
{% block css %}
{% compress css %}
<link rel="stylesheet" href="{% static 'karbordashboard/css/jquery.treetable.css' %}">
{% endcompress %}
{% endblock %}
<div class="left" style="width:100%">
<fieldset>
{% include "horizon/common/_form_fields.html" %}
</fieldset>
<div class="table_wrapper">
<table id="protectionplanUpdateResource" class="{% block table_css_classes %}table table-striped datatable {{ table.css_classes }}{% endblock %}">
<thead>
<tr class="table_column_header">
<th {{ column.attr_string|safe }}>
Resource Name
</th>
<th {{ column.attr_string|safe }}>
Resource Type
</th>
<th {{ column.attr_string|safe }}>
Actions
</th>
</tr>
</thead>
<tbody>
{% for instance in instances %}
<tr data-tt-id="{{ instance.showid }}"
resource-id="{{ instance.id }}"
{% if instance.showparentid != None %}
data-tt-parent-id="{{ instance.showparentid }}"
{% endif %}>
<td>
<span class="spanresource"><input type="checkbox" class="cbresource"/></span>
<span class="logoresource"></span>
<span class="spanresource">{{instance.name}}</span>
</td>
<td>
<span class="spanresource">{{instance.type}}</span>
</td>
<td>
<input type="button" class="btn btn-default editparameters" value="Edit Parameters" resourcetype="{{instance.type}}">
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="dialog_wrapper"></div>
</div>
<script type="text/javascript">
(window.$ || window.addHorizonLoadEvent)(function () {
horizon.protectionplans_update.init();
});
</script>
{% endblock %}
{% block modal-footer %}
<a class="btn btn-default cancel">Cancel</a>
<input class="btn btn-primary save" type="submit" value="Save">
{% endblock %}

View File

@ -0,0 +1,10 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}
{% trans "Update Protection Plan" %}
{% endblock %}
{% block main %}
{% include 'protectionplans/_update.html' %}
{% endblock %}