1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-23 22:50:09 +03:00

Feature #3748: Marketplace import dialog

This commit is contained in:
Carlos Martín 2015-06-08 16:58:38 +02:00
parent 34ea6e7f20
commit 4b22d563b2
7 changed files with 389 additions and 3 deletions

View File

@ -2,6 +2,8 @@ define(function(require) {
var OpenNebulaAction = require('./action');
var OpenNebulaError = require('./error');
var OpenNebulaHelper = require('./helper');
var Notifier = require('utils/notifier');
var Locale = require('utils/locale');
var RESOURCE = "MARKETPLACE";
@ -9,7 +11,7 @@ define(function(require) {
"resource": RESOURCE,
"show" : function(params) {
params.error = function() {
return notifyError(Locale.tr("Cannot connect to OpenNebula Marketplace"));
return Notifier.notifyError(Locale.tr("Cannot connect to OpenNebula Marketplace"));
};
OpenNebulaAction.show(params, RESOURCE);
},

View File

@ -8,6 +8,7 @@ define(function(require) {
var DATATABLE_ID = "dataTableMarketplace";
var _dialogs = [
require('./marketplace-tab/dialogs/import')
];
var _panels = [

View File

@ -7,7 +7,7 @@ define(function(require) {
var RESOURCE = "Marketplace";
var TAB_ID = require('./tabId');
//var IMPORT_DIALOG_ID = require('./dialogs/import/dialogId');
var IMPORT_DIALOG_ID = require('./dialogs/import/dialogId');
var _actions = {
"Marketplace.list" : {
@ -32,7 +32,22 @@ define(function(require) {
},
"Marketplace.import" : {
// TODO
type: "multiple",
call: OpenNebulaResource.show,
callback: function(request, response) {
if (response['status'] && response['status'] != 'ready') {
Notifier.notifyError(Locale.tr("The appliance is not ready"));
return;
}
Sunstone.getDialog(IMPORT_DIALOG_ID).setParams({element: response});
Sunstone.getDialog(IMPORT_DIALOG_ID).reset();
Sunstone.getDialog(IMPORT_DIALOG_ID).show();
},
elements: function() {
return Sunstone.getDataTable(TAB_ID).elements();
},
error: Notifier.onError
},
"Marketplace.show" : {

View File

@ -0,0 +1,285 @@
define(function(require) {
/*
DEPENDENCIES
*/
var BaseDialog = require('utils/dialogs/dialog');
var TemplateHTML = require('hbs!./import/html');
var ContentHTML = require('hbs!./import/content');
var Sunstone = require('sunstone');
var Notifier = require('utils/notifier');
var Locale = require('utils/locale');
var ResourceSelect = require('utils/resource-select');
var OpenNebulaImage = require('opennebula/image');
var OpenNebulaTemplate = require('opennebula/template');
/*
CONSTANTS
*/
var DIALOG_ID = require('./import/dialogId');
var TAB_ID = require('../tabId');
/*
CONSTRUCTOR
*/
function Dialog() {
this.dialogId = DIALOG_ID;
BaseDialog.call(this);
}
Dialog.DIALOG_ID = DIALOG_ID;
Dialog.prototype = Object.create(BaseDialog.prototype);
Dialog.prototype.constructor = Dialog;
Dialog.prototype.html = _html;
Dialog.prototype.onShow = _onShow;
Dialog.prototype.setup = _setup;
Dialog.prototype.setParams = _setParams;
Dialog.prototype.try_to_create_template = _try_to_create_template;
return Dialog;
/*
FUNCTION DEFINITIONS
*/
function _html() {
return TemplateHTML({
'dialogId': this.dialogId
});
}
function _setup(context) {
var that = this;
$("#market_import_dialog_content", context).html(
ContentHTML({'element': this.element})
);
// Filter out DS with type system (1) or file (2)
var filter_att = ["TYPE", "TYPE"];
var filter_val = ["1", "2"];
ResourceSelect.insert('div#market_img_datastore', context, "Datastore",
null, false, null, filter_att, filter_val);
context.off('invalid.fndtn.abide', '#' + DIALOG_ID + 'Form');
context.off('valid.fndtn.abide', '#' + DIALOG_ID + 'Form');
context.on('invalid.fndtn.abide', '#' + DIALOG_ID + 'Form', function(e) {
// Fix for valid event firing twice
if (e.namespace != 'abide.fndtn') { return; }
Notifier.notifyError(Locale.tr("One or more required fields are missing or malformed."));
}).on('valid.fndtn.abide', '#' + DIALOG_ID + 'Form', function(e) {
// Fix for valid event firing twice
if (e.namespace != 'abide.fndtn') { return; }
that.number_of_files = that.element['files'].length;
that.template_created = false;
that.images_information = [];
$("input, button", context).attr("disabled", "disabled");
$(".market_image_result:not(.success)", context).html(
'<span class="fa-stack fa-2x" style="color: #dfdfdf">'+
'<i class="fa fa-cloud fa-stack-2x"></i>'+
'<i class="fa fa-spinner fa-spin fa-stack-1x fa-inverse"></i>'+
'</span>');
$(".market_template_result", context).html(
'<span class="fa-stack fa-2x" style="color: #dfdfdf">'+
'<i class="fa fa-cloud fa-stack-2x"></i>'+
'<i class="fa fa-spinner fa-spin fa-stack-1x fa-inverse"></i>'+
'</span>');
var template_context = $("#market_import_file_template", context);
$.each(that.element['files'], function(index, value){
var local_context = $("#market_import_file_"+index, local_context);
if ($(".market_image_result:not(.success)", local_context).length > 0) {
img_obj = {
"image" : {
"NAME": $("input.name",local_context).val(),
"PATH": that.element['links']['download']['href']+'/'+index,
"TYPE": value['type'],
"MD5": value['md5'],
"SHA1": value['sha1'],
"DRIVER": value['driver'],
"DEV_PREFIX": value['dev_prefix'],
"FROM_APP": that.element['_id']["$oid"],
"FROM_APP_NAME": that.element['name'],
"FROM_APP_FILE": index
},
"ds_id" : $("#market_img_datastore select", context).val()
};
OpenNebulaImage.create({
timeout: true,
data: img_obj,
success: function (file_index, file_context){
return function(request, response) {
$(".market_image_result", file_context).addClass("success").html(
'<span class="fa-stack fa-2x" style="color: #dfdfdf">'+
'<i class="fa fa-cloud fa-stack-2x"></i>'+
'<i class="fa fa-check fa-stack-1x fa-inverse"></i>'+
'</span>');
$(".market_image_response", file_context).html(
'<p style="font-size:12px" class="running-color">'+
Locale.tr("Image created successfully")+' ID:'+response.IMAGE.ID+
'</p>');
that.images_information[file_index] = response;
that.try_to_create_template(context);
};
}(index, local_context),
error: function (request, error_json){
$(".market_template_result", template_context).html('');
$(".market_image_result", local_context).html(
'<span class="fa-stack fa-2x" style="color: #dfdfdf">'+
'<i class="fa fa-cloud fa-stack-2x"></i>'+
'<i class="fa fa-warning fa-stack-1x fa-inverse"></i>'+
'</span>');
$(".market_image_response", local_context).html(
'<p style="font-size:12px" class="error-color">'+
(error_json.error.message || Locale.tr("Cannot contact server: is it running and reachable?"))+
'</p>');
$("input", template_context).removeAttr("disabled");
$("input", local_context).removeAttr("disabled");
$("button", context).removeAttr("disabled");
}
});
}
});
that.try_to_create_template(context);
return false;
});
context.foundation('reflow', 'abide');
return false;
}
function _onShow(context) {
return false;
}
/**
* @param {object} params
* - params.element : Marketplace appliance as returned by a .show call
*/
function _setParams(params) {
this.element = params.element;
}
function _try_to_create_template(context){
var that = this;
var template_context = $("#market_import_file_template", context);
var images_created = $(".market_image_result.success", context).length;
if ((images_created == this.number_of_files) && !that.template_created) {
that.template_created = true;
if (that.element['opennebula_template'] && that.element['opennebula_template'] !== "CPU=1") {
var vm_template;
try {
vm_template = JSON.parse(that.element['opennebula_template']);
} catch (error) {
$(".market_template_result", template_context).html(
'<span class="fa-stack fa-2x" style="color: #dfdfdf">'+
'<i class="fa fa-cloud fa-stack-2x"></i>'+
'<i class="fa fa-warning fa-stack-1x fa-inverse"></i>'+
'</span>');
$(".market_template_response", template_context).html(
'<p style="font-size:12px" class="error-color">'+
(error.message || Locale.tr("Cannot contact server: is it running and reachable?"))+
'</p>');
$("input", template_context).removeAttr("disabled");
$("button", context).removeAttr("disabled");
that.template_created = false;
return;
}
if ($.isEmptyObject(vm_template.DISK)){
vm_template.DISK = [];
} else if (!$.isArray(vm_template.DISK)){
vm_template.DISK = [vm_template.DISK];
}
vm_template.NAME = $("input", template_context).val();
if (!vm_template.CPU){
vm_template.CPU = "1";
}
if (!vm_template.MEMORY){
vm_template.MEMORY = "1024";
}
$.each(that.images_information, function(image_index, image_info){
if (!vm_template.DISK[image_index]) {
vm_template.DISK[image_index] = {};
}
vm_template.DISK[image_index].IMAGE = image_info.IMAGE.NAME;
vm_template.DISK[image_index].IMAGE_UNAME = image_info.IMAGE.UNAME;
});
vm_template.FROM_APP = that.element['_id']["$oid"];
vm_template.FROM_APP_NAME = that.element['name'];
OpenNebulaTemplate.create({
timeout: true,
data: {vmtemplate: vm_template},
success: function (request, response){
$(".market_template_result", template_context).addClass("success").html(
'<span class="fa-stack fa-2x" style="color: #dfdfdf">'+
'<i class="fa fa-cloud fa-stack-2x"></i>'+
'<i class="fa fa-check fa-stack-1x fa-inverse"></i>'+
'</span>');
$(".market_template_response", template_context).html(
'<p style="font-size:12px" class="running-color">'+
Locale.tr("Template created successfully")+' ID:'+response.VMTEMPLATE.ID+
'</p>');
$("button", context).hide();
},
error: function (request, error_json){
$(".market_template_result", template_context).html(
'<span class="fa-stack fa-2x" style="color: #dfdfdf">'+
'<i class="fa fa-cloud fa-stack-2x"></i>'+
'<i class="fa fa-warning fa-stack-1x fa-inverse"></i>'+
'</span>');
$(".market_template_response", template_context).html(
'<p style="font-size:12px" class="error-color">'+
(error_json.error.message || Locale.tr("Cannot contact server: is it running and reachable?"))+
'</p>');
$("input", template_context).removeAttr("disabled");
$("button", context).removeAttr("disabled");
that.template_created = false;
}
});
} else {
$("button", context).hide();
}
}
}
});

View File

@ -0,0 +1,65 @@
<div class="row">
<div class="large-12 columns">
<p style="font-size:14px">{{tr "The following images will be created in OpenNebula."}} {{tr "If you want to edit parameters of the image you can do it later in the images tab"}} </p>
</div>
</div>
<div class="row">
<div class="large-10 large-centered columns">
<div class="large-10 columns">
<label for="market_img_datastore">{{tr "Select the datastore for the images"}}
</label>
<div id="market_img_datastore" name="market_img_datastore">
</div>
</div>
<div class="large-2 columns">
</div>
</div>
</div>
{{#each element.files}}
<div class="row" id="market_import_file_{{@index}}">
<div class="large-10 large-centered columns">
<div class="large-10 columns">
<label>
<i class="fa fa-fw fa-download"/>
&emsp;{{@index}} - {{tr "Image Name"}}
<span class="right">{{humanizeSize "B" size}}</span>
</label>
{{#if name}}
<input type="text" class="name" value="{{name}}"/>
{{else}}
<input type="text" class="name" value="{{element.name}}"/>
{{/if}}
</div>
<div class="large-2 columns market_image_result">
</div>
</div>
<div class="large-10 columns market_image_response">
</div>
</div>
{{/each}}
{{#if element.opennebula_template}}
<br>
<div class="row">
<div class="large-12 columns">
<p style="font-size:14px">{{tr "The following template will be created in OpenNebula and the previous images will be referenced in the disks"}} {{tr "If you want to edit parameters of the template you can do it later in the templates tab"}} </p>
</div>
</div>
<div class="row" id="market_import_file_template">
<div class="large-10 large-centered columns">
<div class="large-10 columns">
<label>
<i class="fa fa-fw fa-file-text-o"/>&emsp;{{tr "Template Name"}}
</label>
{{#if NAME}}
<input type="text" class="name" value="NAME"/>
{{else}}
<input type="text" class="name" value="{{element.name}}"/>
{{/if}}
</div>
<div class="large-2 columns market_template_result">
</div>
</div>
<div class="large-10 columns market_template_response">
</div>
</div>
{{/if}}

View File

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

View File

@ -0,0 +1,15 @@
<div id="{{dialogId}}" class="reveal-modal medium" role="dialog" data-reveal >
<div class="row">
<h3 class="subheader">{{tr "Import Appliance"}}</h3>
</div>
<form data-abide="ajax" id="{{dialogId}}Form">
<div id="market_import_dialog_content">
</div>
<div class="form_buttons row">
<button type="submit" class="button radius right">
{{tr "Import"}}
</button>
</div>
<a class="close-reveal-modal">&#215;</a>
</form>
</div>