mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-08 20:58:17 +03:00
Feature #1089: Upload support for images in Sunstone.
Follows the same principles as SelfService. (cherry picked from commit 5dbf040f9c91d3a965aab13e5e39e130a5b5e4f1)
This commit is contained in:
parent
c3931e8fc6
commit
fcb430e4a8
@ -265,6 +265,7 @@ SUNSTONE_DIRS="$SUNSTONE_LOCATION/models \
|
||||
$SUNSTONE_LOCATION/public/vendor/jQuery \
|
||||
$SUNSTONE_LOCATION/public/vendor/jGrowl \
|
||||
$SUNSTONE_LOCATION/public/vendor/flot \
|
||||
$SUNSTONE_LOCATION/public/vendor/fileuploader \
|
||||
$SUNSTONE_LOCATION/public/images \
|
||||
$SUNSTONE_LOCATION/templates \
|
||||
$SUNSTONE_LOCATION/views"
|
||||
@ -455,6 +456,7 @@ INSTALL_SUNSTONE_FILES=(
|
||||
SUNSTONE_PUBLIC_VENDOR_JQUERYUIIMAGES:$SUNSTONE_LOCATION/public/vendor/jQueryUI/images
|
||||
SUNSTONE_PUBLIC_VENDOR_JQUERYLAYOUT:$SUNSTONE_LOCATION/public/vendor/jQueryLayout
|
||||
SUNSTONE_PUBLIC_VENDOR_FLOT:$SUNSTONE_LOCATION/public/vendor/flot
|
||||
SUNSTONE_PUBLIC_VENDOR_FILEUPLOADER:$SUNSTONE_LOCATION/public/vendor/fileuploader
|
||||
SUNSTONE_PUBLIC_IMAGES_FILES:$SUNSTONE_LOCATION/public/images
|
||||
SUNSTONE_PUBLIC_LOCALE_EN_US:$SUNSTONE_LOCATION/public/locale/en_US
|
||||
SUNSTONE_PUBLIC_LOCALE_RU:$SUNSTONE_LOCATION/public/locale/ru
|
||||
|
@ -19,11 +19,16 @@ include OpenNebulaJSON
|
||||
|
||||
require 'acct/watch_client'
|
||||
require 'OpenNebulaVNC'
|
||||
require 'OpenNebulaJSON/JSONUtils'
|
||||
include JSONUtils
|
||||
|
||||
class SunstoneServer
|
||||
# FLAG that will filter the elements retrieved from the Pools
|
||||
POOL_FILTER = Pool::INFO_ALL
|
||||
|
||||
# Secs to sleep between checks to see if image upload to repo is finished
|
||||
IMAGE_POLL_SLEEP_TIME = 5
|
||||
|
||||
def initialize(client)
|
||||
@client = client
|
||||
end
|
||||
@ -113,6 +118,31 @@ class SunstoneServer
|
||||
end
|
||||
end
|
||||
|
||||
############################################################################
|
||||
#
|
||||
############################################################################
|
||||
def upload(template, file_path)
|
||||
image_hash = parse_json(template, 'image')
|
||||
image_hash['PATH'] = file_path
|
||||
|
||||
new_template = {:image => image_hash}.to_json
|
||||
image = ImageJSON.new(Image.build_xml, @client)
|
||||
|
||||
rc = image.create(new_template)
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
return [500, rc.to_json]
|
||||
end
|
||||
|
||||
image.info
|
||||
#wait until image is ready to return
|
||||
while (image.state_str == 'LOCKED') && (image['RUNNING_VMS'] == '0') do
|
||||
sleep IMAGE_POLL_SLEEP_TIME
|
||||
image.info
|
||||
end
|
||||
return [201, image.to_json]
|
||||
end
|
||||
|
||||
############################################################################
|
||||
#
|
||||
############################################################################
|
||||
|
@ -100,14 +100,21 @@ var create_image_tmpl =
|
||||
</fieldset>\
|
||||
<fieldset>\
|
||||
<div class="" id="src_path_select">\
|
||||
<label style="height:3em;">'+tr("Path vs. source")+':</label>\
|
||||
<label style="height:4em;">'+tr("Image location")+':</label>\
|
||||
\
|
||||
<input type="radio" name="src_path" id="path_img" value="path" />\
|
||||
<label style="float:none">'+tr("Provide a path")+'</label><br />\
|
||||
\
|
||||
<input type="radio" name="src_path" id="source_img" value="source" />\
|
||||
<label style="float:none">'+tr("Provide a source")+'</label><br />\
|
||||
\
|
||||
<input type="radio" name="src_path" id="upload_img" value="upload" />\
|
||||
<label style="float:none">'+tr("Upload")+'</label><br />\
|
||||
\
|
||||
<input type="radio" name="src_path" id="datablock_img" value="datablock" />\
|
||||
<label style="float:none;vertical-align:top">'+tr("Create an empty datablock")+'</label>\
|
||||
<div class="tip">'+tr("Please choose path if you have a file-based image. Choose source otherwise or create an empty datablock disk.")+'</div><br />\
|
||||
\
|
||||
</div>\
|
||||
<div class="img_param">\
|
||||
<label for="img_path">'+tr("Path")+':</label>\
|
||||
@ -129,6 +136,11 @@ var create_image_tmpl =
|
||||
<input type="text" name="img_fstype" id="img_fstype" />\
|
||||
<div class="tip">'+tr("Type of file system to be built. This can be any value understood by mkfs unix command.")+'</div>\
|
||||
</div>\
|
||||
<div class="img_param" id="upload_div">\
|
||||
<label for="file-uploader" >'+tr("Upload file")+':</label>\
|
||||
<div id="file-uploader">\
|
||||
</div><div class="clear" />\
|
||||
</div>\
|
||||
</fieldset>\
|
||||
<fieldset>\
|
||||
<div class="">\
|
||||
@ -666,6 +678,7 @@ function updateImageInfo(request,img){
|
||||
function setupCreateImageDialog(){
|
||||
dialogs_context.append('<div title="'+tr("Create Image")+'" id="create_image_dialog"></div>');
|
||||
$create_image_dialog = $('#create_image_dialog',dialogs_context);
|
||||
|
||||
var dialog = $create_image_dialog;
|
||||
dialog.html(create_image_tmpl);
|
||||
|
||||
@ -694,12 +707,12 @@ function setupCreateImageDialog(){
|
||||
default:
|
||||
$('#datablock_img',context).attr('disabled','disabled');
|
||||
$('#path_img',context).attr('checked','checked');
|
||||
$('#img_source,#img_fstype,#img_size',context).parent().hide();
|
||||
$('#img_source,#img_fstype,#img_size,#file-uploader',context).parent().hide();
|
||||
$('#img_path',context).parent().show();
|
||||
}
|
||||
});
|
||||
|
||||
$('#img_source,#img_fstype,#img_size',dialog).parent().hide();
|
||||
$('#img_source,#img_fstype,#img_size,#file-uploader',dialog).parent().hide();
|
||||
$('#path_img',dialog).attr('checked','checked');
|
||||
$('#img_path',dialog).parent().addClass("img_man");
|
||||
|
||||
@ -708,24 +721,30 @@ function setupCreateImageDialog(){
|
||||
var value = $(this).val();
|
||||
switch (value){
|
||||
case "path":
|
||||
$('#img_source,#img_fstype,#img_size',context).parent().hide();
|
||||
$('#img_source,#img_fstype,#img_size',context).parent().removeClass("img_man");
|
||||
$('#img_source,#img_fstype,#img_size,#file-uploader',context).parent().hide();
|
||||
$('#img_source,#img_fstype,#img_size,#file-uploader',context).parent().removeClass("img_man");
|
||||
$('#img_path',context).parent().show();
|
||||
$('#img_path',context).parent().addClass("img_man");
|
||||
break;
|
||||
case "source":
|
||||
$('#img_path,#img_fstype,#img_size',context).parent().hide();
|
||||
$('#img_path,#img_fstype,#img_size',context).parent().removeClass("img_man");
|
||||
$('#img_path,#img_fstype,#img_size,#file-uploader',context).parent().hide();
|
||||
$('#img_path,#img_fstype,#img_size,#file-uploader',context).parent().removeClass("img_man");
|
||||
$('#img_source',context).parent().show();
|
||||
$('#img_source',context).parent().addClass("img_man");
|
||||
break;
|
||||
case "datablock":
|
||||
$('#img_source,#img_path',context).parent().hide();
|
||||
$('#img_source,#img_path',context).parent().removeClass("img_man");
|
||||
$('#img_source,#img_path,#file-uploader',context).parent().hide();
|
||||
$('#img_source,#img_path,#file-uploader',context).parent().removeClass("img_man");
|
||||
$('#img_fstype,#img_size',context).parent().show();
|
||||
$('#img_fstype,#img_size',context).parent().addClass("img_man");
|
||||
break;
|
||||
}
|
||||
case "upload":
|
||||
$('#img_path,#img_source,#img_fstype,#img_size',context).parent().hide();
|
||||
$('#img_path,#img_source,#img_fstype,#img_size',context).parent().removeClass("img_man");
|
||||
$('#file-uploader',context).parent().show();
|
||||
$('#file-uploader',context).parent().addClass("img_man");
|
||||
break;
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@ -752,9 +771,70 @@ function setupCreateImageDialog(){
|
||||
}
|
||||
);
|
||||
|
||||
$('#upload-progress',dialog).css({
|
||||
border: "1px solid #AAAAAA",
|
||||
position: "relative",
|
||||
// bottom: "29px",
|
||||
width: "258px",
|
||||
// left: "133px",
|
||||
height: "15px",
|
||||
display: "inline-block",
|
||||
});
|
||||
$('#upload-progress div',dialog).css("border","1px solid #AAAAAA");
|
||||
|
||||
var img_obj;
|
||||
|
||||
var uploader = new qq.FileUploaderBasic({
|
||||
button: $('#file-uploader',$create_image_dialog)[0],
|
||||
action: 'upload',
|
||||
multiple: false,
|
||||
params: {},
|
||||
showMessage: function(message){
|
||||
//notifyMessage(message);
|
||||
},
|
||||
onSubmit: function(id, fileName){
|
||||
uploader.setParams({
|
||||
img : JSON.stringify(img_obj),
|
||||
file: fileName
|
||||
});
|
||||
var pos_top = $(window).height() - 120;
|
||||
var pos_left = 140;
|
||||
var pb_dialog = $('<div id="pb_dialog" title="'+
|
||||
tr("Uploading...")+'">'+
|
||||
'<div id="upload-progress"></div>'+
|
||||
'</div>').dialog({
|
||||
draggable:true,
|
||||
modal:false,
|
||||
resizable:false,
|
||||
buttons:{},
|
||||
width: 460,
|
||||
minHeight: 50,
|
||||
position: [pos_left, pos_top]
|
||||
});
|
||||
|
||||
$('#upload-progress',pb_dialog).progressbar({value:0});
|
||||
},
|
||||
onProgress: function(id, fileName, loaded, total){
|
||||
$('div#pb_dialog #upload-progress').progressbar("option","value",Math.floor(loaded*100/total));
|
||||
},
|
||||
onComplete: function(id, fileName, responseJSON){
|
||||
notifyMessage("Image uploaded correctly");
|
||||
$('div#pb_dialog').dialog('destroy');
|
||||
Sunstone.runAction("Image.list");
|
||||
return false;
|
||||
},
|
||||
onCancel: function(id, fileName){
|
||||
},
|
||||
});
|
||||
|
||||
var file_input = false;
|
||||
uploader._button._options.onChange = function(input) {
|
||||
file_input = input; return false;
|
||||
};
|
||||
|
||||
$('#create_image_form_easy',dialog).submit(function(){
|
||||
var exit = false;
|
||||
var upload = false;
|
||||
$('.img_man',this).each(function(){
|
||||
if (!$('input',this).val().length){
|
||||
notifyError(tr("There are mandatory parameters missing"));
|
||||
@ -805,6 +885,9 @@ function setupCreateImageDialog(){
|
||||
img_json["SIZE"] = size;
|
||||
img_json["FSTYPE"] = fstype;
|
||||
break;
|
||||
case "upload":
|
||||
upload=true;
|
||||
break;
|
||||
}
|
||||
|
||||
//Time to add custom attributes
|
||||
@ -815,8 +898,13 @@ function setupCreateImageDialog(){
|
||||
});
|
||||
|
||||
|
||||
var obj = { "image" : img_json };
|
||||
Sunstone.runAction("Image.create", obj);
|
||||
img_obj = { "image" : img_json };
|
||||
|
||||
if (upload){
|
||||
uploader._onInputChange(file_input);
|
||||
} else {
|
||||
Sunstone.runAction("Image.create", img_obj);
|
||||
};
|
||||
|
||||
$create_image_dialog.dialog('close');
|
||||
return false;
|
||||
@ -831,6 +919,9 @@ function setupCreateImageDialog(){
|
||||
}
|
||||
|
||||
function popUpCreateImageDialog(){
|
||||
$('#file-uploader input',$create_image_dialog).removeAttr("style");
|
||||
$('#file-uploader input',$create_image_dialog).attr('style','margin:0;width:256px!important');
|
||||
|
||||
$create_image_dialog.dialog('open');
|
||||
}
|
||||
|
||||
|
@ -308,6 +308,13 @@ delete '/:resource/:id' do
|
||||
@SunstoneServer.delete_resource(params[:resource], params[:id])
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Upload image
|
||||
##############################################################################
|
||||
post '/upload'do
|
||||
@SunstoneServer.upload(params[:img], request.env['rack.input'].path)
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Create a new Resource
|
||||
##############################################################################
|
||||
|
@ -17,6 +17,7 @@
|
||||
<script type="text/javascript" src="vendor/jQueryLayout/jquery.layout-latest.min.js"></script>
|
||||
<script type="text/javascript" src="vendor/dataTables/jquery.dataTables.min.js"></script>
|
||||
<script language="javascript" type="text/javascript" src="vendor/flot/jquery.flot.min.js"></script>
|
||||
<script type="text/javascript" src="vendor/fileuploader/fileuploader.js"></script>
|
||||
|
||||
<!-- End Vendor Libraries -->
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user