1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-21 14:50:08 +03:00

Feature #3748: Oneflow template create wizard

This commit is contained in:
Carlos Martín 2015-06-10 12:34:31 +02:00
parent 017f0dcef9
commit 8f5256f887
10 changed files with 944 additions and 2 deletions

View File

@ -18,7 +18,7 @@ define(function(require) {
];
var _formPanels = [
//require('./oneflow-templates-tab/form-panels/create')
require('./oneflow-templates-tab/form-panels/create')
];
var Tab = {

View File

@ -6,7 +6,7 @@ define(function(require) {
var CommonActions = require('utils/common-actions');
var TAB_ID = require('./tabId');
//var CREATE_DIALOG_ID = require('./form-panels/create/formPanelId');
var CREATE_DIALOG_ID = require('./form-panels/create/formPanelId');
//var INSTANTIATE_DIALOG_ID = require('./dialogs/instantiate/dialogId');
var XML_ROOT = "DOCUMENT";
var RESOURCE = "ServiceTemplate";

View File

@ -0,0 +1,354 @@
define(function(require) {
/*
DEPENDENCIES
*/
require('foundation.tab');
var BaseFormPanel = require('utils/form-panels/form-panel');
var Sunstone = require('sunstone');
var Locale = require('utils/locale');
var Tips = require('utils/tips');
var RoleTab = require('tabs/oneflow-templates-tab/utils/role-tab');
/*
TEMPLATES
*/
var TemplateWizardHTML = require('hbs!./create/wizard');
var TemplateAdvancedHTML = require('hbs!./create/advanced');
/*
CONSTANTS
*/
var FORM_PANEL_ID = require('./create/formPanelId');
var TAB_ID = require('../tabId');
/*
CONSTRUCTOR
*/
function FormPanel() {
this.formPanelId = FORM_PANEL_ID;
this.tabId = TAB_ID;
this.actions = {
'create': {
'title': Locale.tr("Create Service Template"),
'buttonText': Locale.tr("Create"),
'resetButton': true
},
'update': {
'title': Locale.tr("Update Service Template"),
'buttonText': Locale.tr("Update"),
'resetButton': false
}
};
BaseFormPanel.call(this);
}
FormPanel.FORM_PANEL_ID = FORM_PANEL_ID;
FormPanel.prototype = Object.create(BaseFormPanel.prototype);
FormPanel.prototype.constructor = FormPanel;
FormPanel.prototype.htmlWizard = _htmlWizard;
FormPanel.prototype.htmlAdvanced = _htmlAdvanced;
FormPanel.prototype.submitWizard = _submitWizard;
FormPanel.prototype.submitAdvanced = _submitAdvanced;
FormPanel.prototype.onShow = _onShow;
FormPanel.prototype.fill = _fill;
FormPanel.prototype.setup = _setup;
FormPanel.prototype.addRoleTab = _add_role_tab;
return FormPanel;
/*
FUNCTION DEFINITIONS
*/
function _htmlWizard() {
return TemplateWizardHTML({
'formPanelId': this.formPanelId
});
}
function _htmlAdvanced() {
return TemplateAdvancedHTML({
'formPanelId': this.formPanelId
});
}
function _setup(context) {
this.roleTabObjects = {};
var that = this;
var roles_index = 0;
$(".add_service_network", context).on("click", function(){
$(".service_networks tbody").append(
'<tr>\
<td>\
<input class="service_network_name" type="text" pattern="[\\w]+"/>\
<small class="error">'+Locale.tr("Only word characters are allowed")+'</small>\
</td>\
<td>\
<textarea class="service_network_description"/>\
</td>\
<td>\
<a href="#"><i class="fa fa-times-circle remove-tab"></i></a>\
</td>\
</tr>');
});
$(".add_service_network", context).trigger("click");
context.on("change", ".service_network_name", function(){
_redo_service_networks_selector(context);
});
context.on("click", ".service_networks i.remove-tab", function(){
var tr = $(this).closest('tr');
tr.remove();
_redo_service_networks_selector(context);
});
$("#tf_btn_roles", context).bind("click", function(){
that.addRoleTab(roles_index, context);
roles_index++;
context.foundation();
return false;
});
// close icon: removing the tab on click
$("#roles_tabs", context).on("click", "i.remove-tab", function() {
var target = $(this).parent().attr("href");
var dd = $(this).closest('dd');
var dl = $(this).closest('dl');
var content = $(target);
var role_id = content.attr("role_id");
dd.remove();
content.remove();
if (dd.attr("class") == 'active') {
$('a', dl.children('dd').last()).click();
}
delete that.roleTabObjects[role_id];
return false;
});
// Fill parents table
// Each time a tab is clicked the table is filled with existing tabs (roles)
// Selected roles are kept
// TODO If the name of a role is changed and is selected, selection will be lost
$("#roles_tabs", context).on("click", "a", function() {
var tab_id = "#"+this.id+"Tab";
var str = "";
$(tab_id+" .parent_roles").hide();
var parent_role_available = false;
$("#roles_tabs_content #role_name", context).each(function(){
if ($(this).val() && ($(this).val() != $(tab_id+" #role_name", context).val())) {
parent_role_available = true;
str += "<tr>\
<td style='width:10%'>\
<input class='check_item' type='checkbox' value='"+$(this).val()+"' id='"+$(this).val()+"'/>\
</td>\
<td>"+$(this).val()+"</td>\
</tr>";
}
});
if (parent_role_available) {
$(tab_id+" .parent_roles", context).show();
}
var selected_parents = [];
$(tab_id+" .parent_roles_body input:checked", context).each(function(){
selected_parents.push($(this).val());
});
$(tab_id+" .parent_roles_body", context).html(str);
$.each(selected_parents, function(){
$(tab_id+" .parent_roles_body #"+this, context).attr('checked', true);
});
});
// Add first role
$("#tf_btn_roles", context).trigger("click");
$(document).foundation('reflow', 'tab');
Tips.setup(context);
return false;
}
function _submitWizard(context) {
var that = this;
var name = $('input[name="service_name"]', context).val();
var description = $('#description', context).val();
var deployment = $('select[name="deployment"]', context).val();
var shutdown_action_service = $('select[name="shutdown_action_service"]', context).val();
var ready_status_gate = $('input[name="ready_status_gate"]', context).prop("checked");
var custom_attrs = {};
$(".service_networks tbody tr").each(function(){
if ($(".service_network_name", $(this)).val()) {
var attr_name = $(".service_network_name", $(this)).val();
var attr_type = "vnet_id";
var attr_desc = $(".service_network_description", $(this)).val();
custom_attrs[attr_name] = "M|" + attr_type + "|" + attr_desc;
}
});
var roles = [];
$('.role_content', context).each(function() {
var role_id = $(this).attr("role_id");
roles.push( that.roleTabObjects[role_id].retrieve($(this)) );
});
var json_template = {
name: name,
deployment: deployment,
description: description,
roles: roles
};
if (!$.isEmptyObject(custom_attrs)){
json_template['custom_attrs'] = custom_attrs;
}
if (shutdown_action_service){
json_template['shutdown_action'] = shutdown_action_service;
}
json_template['ready_status_gate'] = ready_status_gate;
if (this.action == "create") {
Sunstone.runAction("ServiceTemplate.create", json_template );
return false;
} else if (this.action == "update") {
Sunstone.runAction("ServiceTemplate.update",this.resourceId, JSON.stringify(json_template));
return false;
}
}
function _submitAdvanced(context) {
var json_template = $('textarea#template', context).val();
if (this.action == "create") {
Sunstone.runAction("ServiceTemplate.create", JSON.parse(json_template) );
return false;
} else if (this.action == "update") {
Sunstone.runAction("ServiceTemplate.update", this.resourceId, json_template);
return false;
}
}
function _onShow(context) {
var that = this;
$('.role_content', context).each(function() {
var role_id = $(this).attr("role_id");
that.roleTabObjects[role_id].onShow();
});
}
function _fill(context, element) {
// TODO
}
//----------------------------------------------------------------------------
function _redo_service_networks_selector(dialog){
$('#roles_tabs_content .role_content', dialog).each(function(){
var role_section = this;
_redo_service_networks_selector_role(dialog, role_section);
});
}
function _redo_service_networks_selector_role(dialog, role_section){
$('#roles_tabs_content .role_content', dialog).each(function(){
var role_section = this;
var selected_networks = [];
$(".service_network_checkbox:checked", role_section).each(function(){
selected_networks.push($(this).val());
});
$(".networks_role", role_section).hide();
var service_networks = false;
var role_tab_id = $(role_section).attr('id');
var str = "";
$(".service_networks .service_network_name", dialog).each(function(){
if ($(this).val()) {
service_networks = true;
str += "<tr>\
<td style='width:10%'>\
<input class='service_network_checkbox check_item' type='checkbox' value='"+$(this).val()+"' id='"+role_tab_id+"_"+$(this).val()+"'/>\
</td>\
<td>\
<label for='"+role_tab_id+"_"+$(this).val()+"'>"+$(this).val()+"</label>\
</td>\
</tr>";
}
});
$(".networks_role_body", role_section).html(str);
if (service_networks) {
$(".networks_role", role_section).show();
}
$(".vm_template_contents", role_section).val("");
$.each(selected_networks, function(){
$(".service_network_checkbox[value='"+this+"']", role_section).attr('checked', true).change();
});
});
}
function _add_role_tab(role_id, dialog) {
var html_role_id = 'role' + role_id;
var role_tab = new RoleTab(html_role_id);
this.roleTabObjects[role_id] = role_tab;
// Append the new div containing the tab and add the tab to the list
var role_section = $('<div id="'+html_role_id+'Tab" class="content role_content wizard_internal_tab" role_id="'+role_id+'">'+
role_tab.html() +
'</div>').appendTo($("#roles_tabs_content", dialog));
_redo_service_networks_selector_role(dialog, role_section);
var a = $("<dd>\
<a class='text-center' id='"+html_role_id+"' href='#"+html_role_id+"Tab'>\
<span>\
<i class='off-color fa fa-cube fa-3x'/>\
<br>\
<span id='role_name_text'>"+Locale.tr("Role ")+role_id+"</span>\
</span>\
<i class='fa fa-times-circle remove-tab'></i>\
</a>\
</dd>").appendTo($("dl#roles_tabs", dialog));
$("a", a).trigger("click");
role_tab.setup(role_section);
role_tab.onShow();
}
});

View File

@ -0,0 +1,12 @@
<form data-abide="ajax" id="{{formPanelId}}Advanced" class="custom creation">
<div class="row">
<div class="large-12 columns">
<p>{{tr "Write the Service template here"}}</p>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<textarea id="template" rows="15" required></textarea>
</div>
</div>
</form>

View File

@ -0,0 +1,3 @@
define(function(require){
return 'createServiceTemplateForm';
});

View File

@ -0,0 +1,100 @@
<form data-abide="ajax" id="{{formPanelId}}Wizard" class="custom creation">
<div class="row">
<div class="service_template_param st_man large-6 columns">
<label for="service_name">
{{tr "Name"}}
<span class="tip">{{tr "Name for this template"}}</span>
</label>
<input type="text" id="service_name" name="service_name" required/>
</div>
<div class="service_template_param st_man large-6 columns">
</div>
</div>
<div class="row">
<div class="service_template_param st_man large-12 columns">
<label for="description">
{{tr "Description"}}
<span class="tip">{{tr "Description of the service"}}</span>
</label>
<textarea type="text" id="description" name="description"/>
</div>
</div>
<br>
{{#advancedSection (tr "Network Configuration") }}
<div class="row">
<div class="large-12 columns">
<table class="service_networks policies_table dataTable">
<thead>
<tr>
<th style="width:30%">{{tr "Name"}}</th>
<th style="width:70%">{{tr "Description"}}</th>
<th style="width:3%"></th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="3">
<a type="button" class="add_service_network button small large-12 secondary radius"><i class="fa fa-plus"></i>{{tr "Add another Network"}}</a>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
{{/advancedSection}}
<br>
{{#advancedSection (tr "Advanced Service Parameters") }}
<div class="row">
<div class="service_template_param st_man large-6 columns">
<label for="deployment">
{{tr "Strategy"}}
<span class="tip">{{tr "Straight strategy will instantiate each role in order: parents role will be deployed before their children. None strategy will instantiate the roles regardless of their relationships."}}</span>
</label>
<select name="deployment">
<option value="straight">{{tr "Straight"}}</option>
<option value="none">{{tr "None"}}</option>
</select>
</div>
<div class="service_template_param st_man large-6 columns">
<label for="shutdown_action_service">
{{tr "Shutdown action"}}
<span class="tip">{{tr "VM shutdown action: 'shutdown' or 'shutdown-hard'."}}</span>
</label>
<select name="shutdown_action_service">
<option value=""></option>
<option value="shutdown">{{tr "Shutdown"}}</option>
<option value="shutdown-hard">{{tr "Shutdown hard"}}</option>
</select>
</div>
</div>
<div class="row">
<div class="service_template_param st_man large-6 columns">
<input type="checkbox" name="ready_status_gate" id="ready_status_gate"/>
<label for="ready_status_gate">
{{tr "Wait for VMs to report that they are READY"}}
<span class="tip">{{tr "Before deploying any child roles, wait for all VMs of the parent roles to report via OneGate that they are READY=YES"}}</span>
</label>
</div>
</div>
{{/advancedSection}}
<br>
<div class="row">
<div class="large-12 columns">
<h4>{{tr "Roles"}}</h4>
</div>
</div>
<br>
<div class="row">
<div id="new_role" class="bordered-tabs large-12 columns">
<dl class="tabs" id="roles_tabs" data-tab>
<a class="button small right radius" id="tf_btn_roles">
<span class="fa fa-plus"></span>{{tr "Add another role"}}
</a>
</dl>
<div class="tabs-content" id="roles_tabs_content">
</div>
</div>
</div>
</form>

View File

@ -0,0 +1,211 @@
define(function(require) {
// Dependencies
var Locale = require('utils/locale');
var Tips = require('utils/tips');
var TemplatesTable = require('tabs/templates-tab/datatable');
var TemplateHTML = require('hbs!./role-tab/html');
var TemplateElasticityRowHTML = require('hbs!./role-tab/elasticity-row');
var TemplateScheRowHTML = require('hbs!./role-tab/sche-row');
function RoleTab(html_role_id) {
this.html_role_id = html_role_id;
return this;
}
RoleTab.prototype = {
'html': _role_tab_content,
'setup': _setup_role_tab_content,
'onShow': _onShow,
'retrieve': _retrieve,
//'fill': _fill
};
RoleTab.prototype.constructor = RoleTab;
return RoleTab;
function _role_tab_content(){
var opts = {
info: false,
select: true
};
this.templatesTable = new TemplatesTable("roleTabTemplates"+this.html_role_id, opts);
return TemplateHTML({
'templatesTableHTML': this.templatesTable.dataTableHTML
});
}
function _setup_role_tab_content(role_section) {
var that = this;
Tips.setup(role_section);
this.templatesTable.initialize();
this.templatesTable.idInput().attr("required", "");
role_section.on("change", "#role_name", function(){
$("#" + that.html_role_id +" #role_name_text").html($(this).val());
});
role_section.on("change", "select#type", function(){
var new_tr = $(this).closest('tr');
if ($(this).val() == "PERCENTAGE_CHANGE") {
$("#min_adjust_step_td", new_tr).html('<input type="text" id="min_adjust_step" name="min_adjust_step"/>');
} else {
$("#min_adjust_step_td", new_tr).empty();
}
});
$("#tf_btn_elas_policies", role_section).bind("click", function(){
$( TemplateElasticityRowHTML({}) ).appendTo($("#elasticity_policies_tbody", role_section));
});
role_section.on("click", "#elasticity_policies_table i.remove-tab", function() {
var tr = $(this).closest('tr');
tr.remove();
});
$("#tf_btn_sche_policies", role_section).bind("click", function(){
$( TemplateScheRowHTML({}) ).appendTo($("#scheduled_policies_tbody", role_section));
});
role_section.on("click", "#scheduled_policies_table i.remove-tab", function() {
var tr = $(this).closest('tr');
tr.remove();
});
$("#tf_btn_elas_policies", role_section).trigger("click");
$("#tf_btn_sche_policies", role_section).trigger("click");
role_section.on("change", ".service_network_checkbox", function(){
var vm_template_contents = "";
$(".service_network_checkbox:checked", role_section).each(function(){
vm_template_contents += "NIC=[NETWORK_ID=\"$"+$(this).val()+"\"]\n";
});
$(".vm_template_contents", role_section).val(vm_template_contents);
});
}
function _onShow(){
this.templatesTable.refreshResourceTableSelect();
}
function _retrieve(context){
var role = {};
role['name'] = $('input[name="name"]', context).val();
role['cardinality'] = $('input[name="cardinality"]', context).val();
role['vm_template'] = this.templatesTable.retrieveResourceTableSelect();
role['shutdown_action'] = $('select[name="shutdown_action_role"]', context).val();
role['parents'] = [];
role['vm_template_contents'] = $(".vm_template_contents", context).val();
$('.parent_roles_body input.check_item:checked', context).each(function(){
role['parents'].push($(this).val());
});
var shutdown_action = $('select[name="shutdown_action_role"]', context).val();
if (shutdown_action) {
role['shutdown_action'] = shutdown_action;
}
var min_vms = $('input[name="min_vms"]', context).val();
if (min_vms) {
role['min_vms'] = min_vms;
}
var max_vms = $('input[name="max_vms"]', context).val();
if (max_vms) {
role['max_vms'] = max_vms;
}
var cooldown = $('input[name="cooldown"]', context).val();
if (cooldown) {
role['cooldown'] = cooldown;
}
role = _removeEmptyObjects(role);
role['elasticity_policies'] = [];
$("#elasticity_policies_tbody tr", context).each(function(){
if ($("#type" ,this).val()) {
var policy = {};
policy['type'] = $("#type" ,this).val();
policy['adjust'] = $("#adjust" ,this).val();
policy['min_adjust_step'] = $("#min_adjust_step" ,this).val();
policy['expression'] = $("#expression" ,this).val();
policy['period_number'] = $("#period_number" ,this).val();
policy['period'] = $("#period" ,this).val();
policy['cooldown'] = $("#cooldown" ,this).val();
// TODO remove empty policies
role['elasticity_policies'].push(_removeEmptyObjects(policy));
}
});
role['scheduled_policies'] = [];
$("#scheduled_policies_tbody tr", context).each(function(){
if ($("#type" ,this).val()) {
var policy = {};
policy['type'] = $("#type" ,this).val();
policy['adjust'] = $("#adjust" ,this).val();
policy['min_adjust_step'] = $("#min_adjust_step" ,this).val();
var time_format = $("#time_format" ,this).val();
policy[time_format] = $("#time" ,this).val();
// TODO remove empty policies
role['scheduled_policies'].push(_removeEmptyObjects(policy));
}
});
return role;
}
//----------------------------------------------------------------------------
function _removeEmptyObjects(obj){
for (var elem in obj){
var remove = false;
var value = obj[elem];
if (value instanceof Array){
if (value.length == 0)
remove = true;
else if (value.length > 0){
value = jQuery.grep(value, function (n) {
var obj_length = 0;
for (e in n)
obj_length += 1;
if (obj_length == 0)
return false;
return true;
});
if (value.length == 0)
remove = true;
}
}
else if (value instanceof Object){
var obj_length = 0;
for (e in value)
obj_length += 1;
if (obj_length == 0)
remove = true;
}else{
value = String(value);
if (value.length == 0)
remove = true;
}
if (remove)
delete obj[elem];
}
return obj;
}
});

View File

@ -0,0 +1,30 @@
<tr>
<td>
<select id="type" name="type">
<option value=""></option>
<option value="CHANGE">{{tr "Change"}}</option>
<option value="CARDINALITY">{{tr "Cardinality"}}</option>
<option value="PERCENTAGE_CHANGE">{{tr "Percentage"}}</option>
</select>
</td>
<td>
<input type="text" id="adjust" name="adjust"/>
</td>
<td id="min_adjust_step_td">
</td>
<td>
<input type="text" id="expression" name="expression"/>
</td>
<td>
<input type="text" id="period_number" name="period_number"/>
</td>
<td>
<input type="text" id="period" name="period"/>
</td>
<td>
<input type="text" id="cooldown" name="cooldown"/>
</td>
<td>
<a href="#"><i class="fa fa-times-circle remove-tab"></i></a>
</td>
</tr>

View File

@ -0,0 +1,205 @@
<div class="row">
<div class="service_template_param service_role st_man large-6 columns">
<label for="name">{{tr "Role Name"}}
<span class="tip">{{tr "Name of the role"}}</span>
</label>
<input type="text" id="role_name" name="name" required/>
</div>
<div class="service_template_param service_role large-2 columns end">
<label for="cardinality">{{tr "VMs"}}
<span class="tip">{{tr "Number of VMs to instantiate with this role"}}</span>
</label>
<input type="text" id="cardinality" name="cardinality" value="1"/>
</div>
</div>
<div class="row">
<div class="service_template_param service_role small-12 columns">
<label for="vm_template">{{tr "VM template"}}
<span class="tip">{{tr "Template associated to this role"}}</span>
</label>
{{{templatesTableHTML}}}
<div id="vm_template">
</div>
</div>
</div>
<div class="row">
<div class="service_template_param service_role large-6 columns">
<table class="networks_role extended_table dataTable">
<thead>
<tr>
<th colspan="2">
<i class="fa fa-lg fa-fw fa-globe off-color"/>{{tr "Network Interfaces"}}
</th>
</tr>
</thead>
<tbody class="networks_role_body">
</tbody>
</table>
</div>
<div class="service_template_param service_role large-6 columns">
<table class="parent_roles extended_table dataTable">
<thead>
<tr>
<th colspan="2">
{{tr "Parent roles"}}
</th>
</tr>
</thead>
<tbody class="parent_roles_body">
</tbody>
</table>
</div>
</div>
<br>
<div class="row">
<div class="large-12 columns elasticity_accordion">
{{#advancedSection (tr "Role Elasticity") }}
<div class="row">
<div class="large-4 columns">
<label for="min_vms">{{tr "Min VMs"}}
<span class="tip">{{tr "Minimum number of VMs for elasticity adjustments"}}</span>
</label>
<input type="text" id="min_vms" name="min_vms" value="" />
</div>
<div class="large-4 columns">
<label for="max_vms">{{tr "Max VMs"}}
<span class="tip">{{tr "Maximum number of VMs for elasticity adjustments"}}</span>
</label>
<input type="text" id="max_vms" name="max_vms" value="" />
</div>
<div class="service_template_param service_role large-4 columns">
<label for="cooldown">{{tr "Cooldown"}}
<span class="tip">{{tr "Cooldown time after an elasticity operation (secs)"}}</span>
</label>
<input type="text" id="cooldown" name="cooldown" value="" />
</div>
</div>
<div class="row">
<div class="large-12 columns">
<table id="elasticity_policies_table" class="policies_table dataTable">
<thead style="background:#dfdfdf">
<tr>
<th colspan="8" style="font-size: 16px !important">
{{tr "Elasticity policies"}}
</th>
</tr>
</thead>
<thead>
<tr>
<th class="has-tip" data-tooltip title="{{tr "Type of adjustment."}}<br><br>
{{tr "CHANGE: Add/substract the given number of VMs."}}<br>
{{tr "CARDINALITY: Set the cardinality to the given number."}}<br>
{{tr "PERCENTAGE_CHANGE: Add/substract the given percentage to the current cardinality."}}
" style="width:14%">{{tr "Type"}}
</th>
<th class="has-tip" data-tooltip title="{{tr "Positive or negative adjustment. Its meaning depends on 'type'"}}<br><br>
{{tr "CHANGE: -2, will substract 2 VMs from the role"}}<br>
{{tr "CARDINALITY: 8, will set carditanilty to 8"}}<br>
{{tr "PERCENTAGE_CHANGE: 20, will increment cardinality by 20%"}}" style="width:12%">{{tr "Adjust"}}
</th>
<th class="has-tip" data-tooltip title="{{tr "Optional parameter for PERCENTAGE_CHANGE adjustment type."}}<br>
{{tr " If present, the policy will change the cardinality by at least the number of VMs set in this attribute."}}" style="width:9%">{{tr "Min"}}
</th>
<th class="has-tip" data-tooltip title="{{tr "Expression to trigger the elasticity"}}<br><br>
{{tr "Example: ATT < 20"}}" style="width:30%">{{tr "Expression"}}
</th>
<th class="has-tip" data-tooltip title="{{tr "Number of periods that the expression must be true before the elasticity is triggered"}}" style="width:8%">#
</th>
<th class="has-tip" data-tooltip title="{{tr "Duration, in seconds, of each period in '# Periods'"}}" style="width:9%">{{tr "Period"}}
</th>
<th class="has-tip" data-tooltip title="{{tr "Cooldown period duration after a scale operation, in seconds"}}" style="width:15%">{{tr "Cooldown"}}
</th>
<th style="width:3%"></th>
</tr>
</thead>
<tbody id="elasticity_policies_tbody">
</tbody>
<tfoot>
<tr>
<td colspan="8">
<a type="button" class="button small radius right" id="tf_btn_elas_policies"><i class="fa fa-plus"></i> {{tr "Add another policy"}}</a>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
<br>
<div class="row">
<div class="large-12 columns">
<table id="scheduled_policies_table" class="policies_table dataTable">
<thead style="background:#dfdfdf">
<tr>
<th colspan="6" style="font-size: 16px !important">
{{tr "Scheduled policies"}}
</th>
</tr>
</thead>
<thead>
<tr>
<th class="has-tip" data-tooltip title="{{tr "Type of adjustment."}}<br><br>
{{tr "CHANGE: Add/substract the given number of VMs."}}<br>
{{tr "CARDINALITY: Set the cardinality to the given number."}}<br>
{{tr "PERCENTAGE_CHANGE: Add/substract the given percentage to the current cardinality."}}" style="width:14%">{{tr "Type"}}
</th>
<th class="has-tip" data-tooltip title="{{tr "Positive or negative adjustment. Its meaning depends on 'type'"}}<br><br>
{{tr "CHANGE: -2, will substract 2 VMs from the role"}}<br>
{{tr "CARDINALITY: 8, will set carditanilty to 8"}}<br>
{{tr "PERCENTAGE_CHANGE: 20, will increment cardinality by 20%"}}" style="width:12%">{{tr "Adjust"}}
</th>
<th class="has-tip" data-tooltip title="{{tr "Optional parameter for PERCENTAGE_CHANGE adjustment type. If present, the policy will change the cardinality by at least the number of VMs set in this attribute."}}" style="width:9%">{{tr "Min"}}
</th>
<th class="has-tip" data-tooltip title="{{tr "Recurrence: Time for recurring adjustements. Time is specified with the Unix cron syntax"}}<br><br>
{{tr "Start time: Exact time for the adjustement"}}" style="width:28%">{{tr "Time format"}}
</th>
<th class="has-tip" data-tooltip title="{{tr "Time expression depends on the the time formar selected"}}<br><br>
{{tr "Recurrence: Time for recurring adjustements. Time is specified with the Unix cron syntax"}}<br>
{{tr "Start time: Exact time for the adjustement"}}" style="width:33%">{{tr "Time expression"}}
</th>
<th style="width:3%"></th>
</tr>
</thead>
<tbody id="scheduled_policies_tbody">
</tbody>
<tfoot>
<tr>
<td colspan="6">
<a type="button" class="button small radius right" id="tf_btn_sche_policies"><i class="fa fa-plus"></i> {{tr "Add another policy"}}</a>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
{{/advancedSection}}
</div>
</div>
<br>
<div class="row">
<div class="large-12 columns advanced_role_accordion">
{{#advancedSection (tr "Advanced Role Parameters") }}
<div class="row">
<div class="service_template_param service_role large-6 columns">
<label for="shutdown_action_role">{{tr "Shutdown action"}}
<span class="tip">{{tr "VM shutdown action: 'shutdown' or 'shutdown-hard'. If it is not set, the one set for the Service will be used"}}</span>
</label>
<select name="shutdown_action_role">
<option value=""></option>
<option value="shutdown">{{tr "Shutdown"}}</option>
<option value="shutdown-hard">{{tr "Shutdown hard"}}</option>
</select>
</div>
<div class="large-6 columns">
</div>
</div>
<div class="row">
<div class="service_template_param st_man large-12 columns">
<label for="vm_template_contents">{{tr "VM Template Content"}}
<span class="tip">{{tr "This information will be merged with the original Virtual Machine template. Configuration attributes and network interfaces will be replaced by those provided by the user when the template is instantiated"}}</span>
</label>
<textarea type="text" class="vm_template_contents" name="vm_template_contents"/>
</div>
</div>
{{/advancedSection}}
</div>
</div>

View File

@ -0,0 +1,27 @@
<tr>
<td>
<select id="type" name="type">
<option value=""></option>
<option value="CHANGE">{{tr "Change"}}</option>
<option value="CARDINALITY">{{tr "Cardinality"}}</option>
<option value="PERCENTAGE_CHANGE">{{tr "Percentage"}}</option>
</select>
</td>
<td>
<input type="text" id="adjust" name="adjust"/>
</td>
<td id="min_adjust_step_td">
</td>
<td>
<select id="time_format" name="time_format">
<option value="start_time">{{tr "Start time"}}</option>
<option value="recurrence">{{tr "Recurrence"}}</option>
</select>
</td>
<td>
<input type="text" id="time" name="time"/>
</td>
<td>
<a href="#"><i class="fa fa-times-circle remove-tab"></i></a>
</td>
</tr>