diff --git a/install.sh b/install.sh
index 52d719274f..542f02ca1f 100755
--- a/install.sh
+++ b/install.sh
@@ -1908,7 +1908,7 @@ do_file() {
if [ "$LINK" = "yes" ]; then
ln -s $SRC_DIR/$1 $DESTDIR$2
else
- cp -R $SRC_DIR/$1 $DESTDIR$2
+ cp -RL $SRC_DIR/$1 $DESTDIR$2
fi
fi
}
diff --git a/src/im_mad/remotes/az.d/poll b/src/im_mad/remotes/az.d/poll
index 0aca1b10bf..50692211cc 100755
--- a/src/im_mad/remotes/az.d/poll
+++ b/src/im_mad/remotes/az.d/poll
@@ -16,7 +16,15 @@
# limitations under the License. #
# -------------------------------------------------------------------------- #
-$: << File.join(File.dirname(__FILE__), '../../vmm/az')
+ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION)
+
+if !ONE_LOCATION
+ RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION)
+else
+ RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION)
+end
+
+$: << RUBY_LIB_LOCATION
require 'az_driver'
diff --git a/src/im_mad/remotes/ec2.d/poll b/src/im_mad/remotes/ec2.d/poll
index d49c0cb2da..8e7e0abd19 100755
--- a/src/im_mad/remotes/ec2.d/poll
+++ b/src/im_mad/remotes/ec2.d/poll
@@ -16,7 +16,15 @@
# limitations under the License. #
# -------------------------------------------------------------------------- #
-$: << File.join(File.dirname(__FILE__), '../../vmm/ec2')
+ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION)
+
+if !ONE_LOCATION
+ RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION)
+else
+ RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION)
+end
+
+$: << RUBY_LIB_LOCATION
require 'ec2_driver'
diff --git a/src/im_mad/remotes/sl.d/poll b/src/im_mad/remotes/sl.d/poll
index 74c2a68c05..40c28ab74e 100755
--- a/src/im_mad/remotes/sl.d/poll
+++ b/src/im_mad/remotes/sl.d/poll
@@ -16,7 +16,15 @@
# limitations under the License. #
# -------------------------------------------------------------------------- #
-$: << File.join(File.dirname(__FILE__), '../../vmm/sl')
+ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION)
+
+if !ONE_LOCATION
+ RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION)
+else
+ RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION)
+end
+
+$: << RUBY_LIB_LOCATION
require 'sl_driver'
diff --git a/src/sunstone/models/OpenNebulaJSON/TemplateJSON.rb b/src/sunstone/models/OpenNebulaJSON/TemplateJSON.rb
index 1ca880f37e..80680e3837 100644
--- a/src/sunstone/models/OpenNebulaJSON/TemplateJSON.rb
+++ b/src/sunstone/models/OpenNebulaJSON/TemplateJSON.rb
@@ -50,6 +50,10 @@ module OpenNebulaJSON
when "instantiate" then self.instantiate(action_hash['params'])
when "clone" then self.clone(action_hash['params'])
when "rename" then self.rename(action_hash['params'])
+ when "delete_from_provision"
+ then self.delete_from_provision(action_hash['params'])
+ when "chmod_from_provision"
+ then self.chmod_from_provision(action_hash['params'])
else
error_msg = "#{action_hash['perform']} action not " <<
" available for this resource"
@@ -115,5 +119,37 @@ module OpenNebulaJSON
def rename(params=Hash.new)
super(params['name'])
end
+
+ def delete_from_provision(params=Hash.new)
+ # Delete associated images
+ self.each("TEMPLATE/DISK/IMAGE_ID"){|image_id|
+ img = OpenNebula::Image.new_with_id(image_id.text, @client)
+ rc = img.delete
+ if OpenNebula::is_error?(rc)
+ error_msg = "Some of the resources associated with " <<
+ "this template couldn't be deleted. Error: " << rc.message
+ return OpenNebula::Error.new(error_msg)
+ end
+ }
+
+ # Delete template
+ self.delete
+ end
+
+ def chmod_from_provision(params=Hash.new)
+ # Chmod associated images
+ self.each("TEMPLATE/DISK/IMAGE_ID"){|image_id|
+ img = OpenNebulaJSON::ImageJSON.new_with_id(image_id.text, @client)
+ rc = img.chmod_json(params)
+ if OpenNebula::is_error?(rc)
+ error_msg = "Some of the resources associated with " <<
+ "this template couldn't be published. Error: " << rc.message
+ return OpenNebula::Error.new(error_msg)
+ end
+ }
+
+ # Chmod template
+ self.chmod_json(params)
+ end
end
end
diff --git a/src/sunstone/public/README.md b/src/sunstone/public/README.md
index b72a700582..d626a41fee 100644
--- a/src/sunstone/public/README.md
+++ b/src/sunstone/public/README.md
@@ -1,30 +1,41 @@
-Sunstone depnedencies
+Sunstone dependencies
=====================
1. Install nodejs and npm
2. Install the following npm packages:
- `sudo npm install -g bower`
- `sudo npm install -g grunt`
- `sudo npm install -g grunt-cli`
+
+ ```
+ sudo npm install -g bower
+ sudo npm install -g grunt
+ sudo npm install -g grunt-cli
+ ```
+
3. Move to the Sunstone public folder and run:
- `npm install`
- `bower install`
+
+ ```
+ npm install
+ bower install
+ ```
Building minified JS and CSS files
==================================
4. Run the following command to generate the app.css file in the css folder:
- `grunt sass`
+ ```
+ grunt sass
+ ```
5. Run the following command to generate the minified js files in the dist foler
and the app.min.css in the css folder:
- `grunt requirejs`
+ ```
+ grunt requirejs
+ ```
These are the files generate by the grunt requirejs command:
```
css
app.min.css
dist
- login.js, login.js.map main.js main.js.map
+ login.js, login.js.map main.js main.js.map
console
spice.js spice.js.map vnc.js vnc.js.map
```
@@ -33,9 +44,11 @@ Scons
=====
Scons includes an option to build the minified JS and CSS files. Steps 1, 2 and 3 have to be performed before running this command
- `scons sunstone=yes`
+ ```
+ scons sunstone=yes
+ ```
Install.sh
==========
-By default the install.sh script will install all the files, including the non-minified ones. Providing the -p option, only the minified files will be installed.
\ No newline at end of file
+By default the install.sh script will install all the files, including the non-minified ones. Providing the -p option, only the minified files will be installed.
diff --git a/src/sunstone/public/app/opennebula/template.js b/src/sunstone/public/app/opennebula/template.js
index b202e0d114..d2a8fb091a 100644
--- a/src/sunstone/public/app/opennebula/template.js
+++ b/src/sunstone/public/app/opennebula/template.js
@@ -11,6 +11,9 @@ define(function(require) {
"del" : function(params) {
OpenNebulaAction.del(params, RESOURCE);
},
+ "delete_from_provision": function(params) {
+ OpenNebulaAction.simple_action(params, RESOURCE, "delete_from_provision");
+ },
"list" : function(params) {
OpenNebulaAction.list(params, RESOURCE);
},
@@ -27,6 +30,10 @@ define(function(require) {
var action_obj = params.data.extra_param;
OpenNebulaAction.simple_action(params, RESOURCE, "chmod", action_obj);
},
+ "chmod_from_provision": function(params) {
+ var action_obj = params.data.extra_param;
+ OpenNebulaAction.simple_action(params, RESOURCE, "chmod_from_provision", action_obj);
+ },
"update" : function(params) {
var action_obj = params.data.extra_param;
OpenNebulaAction.simple_action(params, RESOURCE, "update", action_obj);
diff --git a/src/sunstone/public/app/tabs/provision-tab/templates/list.js b/src/sunstone/public/app/tabs/provision-tab/templates/list.js
index d053b50591..8e922156df 100644
--- a/src/sunstone/public/app/tabs/provision-tab/templates/list.js
+++ b/src/sunstone/public/app/tabs/provision-tab/templates/list.js
@@ -222,7 +222,6 @@ define(function(require) {
context.on("click", ".provision_confirm_delete_template_button", function(){
var ul_context = $(this).parents(".provision-pricing-table");
var template_id = ul_context.attr("opennebula_id");
- var image_id = ul_context.attr("saved_to_image_id");
var template_name = $(".provision-title", ul_context).text();
$(".provision_confirm_delete_template_div", context).html(
@@ -236,7 +235,7 @@ define(function(require) {
''+
''+
'
'+
''+
'× '+
@@ -244,55 +243,25 @@ define(function(require) {
});
context.on("click", ".provision_delete_template_button", function(){
- /* TODO SAVED_TO_IMAGE_ID does not exists anymore and now all the images of the template
- are cloned instead of only the main disk, therefore all the images should be deleted now.
- Probably this could be done in the core
var button = $(this);
button.attr("disabled", "disabled");
var template_id = $(this).attr("template_id");
- var image_id = $(this).attr("image_id");
- OpenNebula.Image.del({
+ OpenNebula.Template.delete_from_provision({
timeout: true,
data : {
- id : image_id
+ id : template_id
},
success: function (){
- OpenNebula.Template.del({
- timeout: true,
- data : {
- id : template_id
- },
- success: function (){
- $(".provision_templates_list_refresh_button", context).trigger("click");
- },
- error: function (request,error_json, container) {
- Notifier.onError(request, error_json, container);
- }
- })
+ $(".provision_templates_list_refresh_button", context).trigger("click");
},
error: function (request,error_json, container) {
- if (error_json.error.http_status=="404") {
- OpenNebula.Template.del({
- timeout: true,
- data : {
- id : template_id
- },
- success: function (){
- $(".provision_templates_list_refresh_button", context).trigger("click");
- },
- error: function (request,error_json, container) {
- Notifier.onError(request, error_json, container);
- $(".provision_templates_list_refresh_button", context).trigger("click");
- }
- })
- } else {
- Notifier.onError(request, error_json, container);
- }
+ Notifier.onError(request, error_json, container);
+ $(".provision_templates_list_refresh_button", context).trigger("click");
}
- })*/
+ })
});
}
@@ -301,7 +270,6 @@ define(function(require) {
context.on("click", ".provision_confirm_chmod_template_button", function(){
var ul_context = $(this).parents(".provision-pricing-table");
var template_id = ul_context.attr("opennebula_id");
- var image_id = ul_context.attr("saved_to_image_id");
var template_name = $(".provision-title", ul_context).text();
$(".provision_confirm_delete_template_div", context).html(
@@ -315,7 +283,7 @@ define(function(require) {
''+
''+
''+
''+
'× '+
@@ -323,16 +291,13 @@ define(function(require) {
});
context.on("click", ".provision_chmod_template_button", function(){
- /* TODO SAVED_TO_IMAGE_ID does not exists anymore and now all the images of the template
- are cloned instead of only the main disk, therefore all the images should be chmod now.
- Probably this could be done in the core
+
var button = $(this);
button.attr("disabled", "disabled");
var template_id = $(this).attr("template_id");
- var image_id = $(this).attr("image_id");
- OpenNebula.Template.chmod({
+ OpenNebula.Template.chmod_from_provision({
timeout: true,
data : {
id : template_id,
@@ -340,26 +305,14 @@ define(function(require) {
},
success: function (){
$(".provision_templates_list_refresh_button", context).trigger("click");
-
- OpenNebula.Image.chmod({
- timeout: true,
- data : {
- id : image_id,
- extra_param: {'group_u': 1}
- },
- success: function (){
- },
- error: Notifier.onError
- })
},
error: Notifier.onError
- })*/
+ })
});
context.on("click", ".provision_confirm_unshare_template_button", function(){
var ul_context = $(this).parents(".provision-pricing-table");
var template_id = ul_context.attr("opennebula_id");
- var image_id = ul_context.attr("saved_to_image_id");
var template_name = $(".provision-title", ul_context).first().text();
$(".provision_confirm_delete_template_div", context).html(
@@ -373,7 +326,7 @@ define(function(require) {
''+
''+
''+
''+
'× '+
@@ -385,9 +338,8 @@ define(function(require) {
button.attr("disabled", "disabled");
var template_id = $(this).attr("template_id");
- var image_id = $(this).attr("image_id");
- OpenNebula.Template.chmod({
+ OpenNebula.Template.chmod_from_provision({
timeout: true,
data : {
id : template_id,
@@ -395,17 +347,6 @@ define(function(require) {
},
success: function (){
$(".provision_templates_list_refresh_button", context).trigger("click");
-
- OpenNebula.Image.chmod({
- timeout: true,
- data : {
- id : image_id,
- extra_param: {'group_u': 0}
- },
- success: function (){
- },
- error: Notifier.onError
- })
},
error: Notifier.onError
})
diff --git a/src/sunstone/public/app/tabs/provision-tab/vms/list.js b/src/sunstone/public/app/tabs/provision-tab/vms/list.js
index 7bbeb2e8de..bad82d25b6 100644
--- a/src/sunstone/public/app/tabs/provision-tab/vms/list.js
+++ b/src/sunstone/public/app/tabs/provision-tab/vms/list.js
@@ -448,7 +448,7 @@ define(function(require) {
''+
Locale.tr("This Virtual Machine will be saved in a new Template. Only the main disk will be preserved!")+
' '+
- Locale.tr("You can then create a new Virtual Machine using this Template")+
+ Locale.tr("You can then create a new Virtual Machine using this Template.")+
' '+
''+
''+
@@ -483,6 +483,7 @@ define(function(require) {
name : template_name
}
},
+ timeout: false,
success: function(request, response){
OpenNebula.Action.clear_cache("VMTEMPLATE");
Notifier.notifyMessage(Locale.tr("VM Template") + ' ' + request.request.data[0][1].name + ' ' + Locale.tr("saved successfully"))
@@ -490,7 +491,13 @@ define(function(require) {
button.removeAttr("disabled");
},
error: function(request, response){
- Notifier.onError(request, response);
+ if(response.error.http_status == 0){ // Failed due to cloning template taking too long
+ OpenNebula.Action.clear_cache("VMTEMPLATE");
+ update_provision_vm_info(vm_id, context);
+ Notifier.notifyMessage(Locale.tr("VM cloning in the background. The Template will appear as soon as it is ready, and the VM unlocked."));
+ } else {
+ Notifier.onError(request, response);
+ }
button.removeAttr("disabled");
}
})
diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general/capacity-inputs.js b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general/capacity-inputs.js
index 2a9b2ce7ee..7fe30a0633 100644
--- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general/capacity-inputs.js
+++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general/capacity-inputs.js
@@ -38,11 +38,17 @@ define(function(require) {
//cpu_slider.attr('data-options', 'start: 0; end: 1600; step: 50;');
cpu_slider.on('change.fndtn.slider', function(){
- cpu_input.val($(this).attr('data-slider') / 100);
+ if ($(this).attr('data-slider') >= 0) {
+ cpu_input.val($(this).attr('data-slider') / 100);
+ }
});
cpu_input.on('change', function() {
- cpu_slider.foundation('slider', 'set_value', this.value * 100);
+ if (this.value && this.value >= 0) {
+ cpu_slider.foundation('slider', 'set_value', this.value * 100);
+ } else {
+ cpu_slider.foundation('slider', 'set_value', -1);
+ }
});
cpu_slider.foundation('slider', 'set_value', 100);
@@ -64,18 +70,30 @@ define(function(require) {
}
memory_input.on('change', function() {
- $("#memory_slider", context).foundation('slider', 'set_value', this.value * 100);
- update_final_memory_input();
+ if (this.value && this.value >= 0) {
+ $("#memory_slider", context).foundation('slider', 'set_value', this.value * 100);
+ update_final_memory_input();
+ } else {
+ $("#memory_slider", context).foundation('slider', 'set_value', -1);
+ final_memory_input.val("");
+ }
});
final_memory_input.on('change', function() {
- $("#memory_slider", context).foundation('slider', 'set_value', this.value * 100);
- memory_input.val(Math.floor(this.value));
+ if (this.value && this.value >= 0) {
+ $("#memory_slider", context).foundation('slider', 'set_value', this.value * 100);
+ memory_input.val(Math.floor(this.value));
+ } else {
+ $("#memory_slider", context).foundation('slider', 'set_value', -1);
+ memory_input.val("");
+ }
});
$("#memory_slider", context).on('change.fndtn.slider', function() {
- memory_input.val($(this).attr('data-slider') / 100);
- update_final_memory_input();
+ if ($(this).attr('data-slider') >= 0) {
+ memory_input.val($(this).attr('data-slider') / 100);
+ update_final_memory_input();
+ }
});
memory_unit.on('change', function() {
@@ -110,8 +128,10 @@ define(function(require) {
memory_input.val(new_val);
$("#memory_slider", context).foundation('slider', 'set_value', new_val * 100);
$("#memory_slider", context).on('change.fndtn.slider', function() {
- memory_input.val($(this).attr('data-slider') / 100);
- update_final_memory_input();
+ if ($(this).attr('data-slider') >= 0) {
+ memory_input.val($(this).attr('data-slider') / 100);
+ update_final_memory_input();
+ }
});
update_final_memory_input();
@@ -127,13 +147,18 @@ define(function(require) {
var vcpu_slider = $("#vcpu_slider", context)
//vcpu_slider.attr('data-options', 'start: 0; end: 1600; step: 50;');
-
vcpu_slider.on('change.fndtn.slider', function(){
- vcpu_input.val($(this).attr('data-slider') / 100);
+ if ($(this).attr('data-slider') > 0) {
+ vcpu_input.val($(this).attr('data-slider') / 100);
+ }
});
vcpu_input.on('change', function() {
- vcpu_slider.foundation('slider', 'set_value', this.value * 100);
+ if (this.value && this.value > 0) {
+ vcpu_slider.foundation('slider', 'set_value', this.value * 100);
+ } else {
+ vcpu_slider.foundation('slider', 'set_value', -1);
+ }
});
vcpu_slider.foundation('slider', 'set_value', 0);
diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general/capacity-inputs/html.hbs b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general/capacity-inputs/html.hbs
index b154f190d3..c5f77d9122 100644
--- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general/capacity-inputs/html.hbs
+++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general/capacity-inputs/html.hbs
@@ -52,7 +52,7 @@
{{{tip (tr "Number of virtual cpus. This value is optional, the default hypervisor behavior is used, usually one virtual CPU.")}}}
-
+
diff --git a/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-disk.js b/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-disk.js
index 384c6ad8b0..36b7b8d2b9 100644
--- a/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-disk.js
+++ b/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-disk.js
@@ -53,7 +53,7 @@ define(function(require) {
function _setup(context) {
var that = this;
- that.diskTab.setup();
+ that.diskTab.setup(context);
Tips.setup(context);
diff --git a/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-nic.js b/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-nic.js
index 9a31159cb2..16f4c71417 100644
--- a/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-nic.js
+++ b/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-nic.js
@@ -53,7 +53,7 @@ define(function(require) {
function _setup(context) {
var that = this;
- that.nicTab.setup();
+ that.nicTab.setup(context);
Tips.setup(context);
diff --git a/src/vmm_mad/exec/one_vmm_exec.rb b/src/vmm_mad/exec/one_vmm_exec.rb
index 02aeddf73f..9a0a2d602b 100755
--- a/src/vmm_mad/exec/one_vmm_exec.rb
+++ b/src/vmm_mad/exec/one_vmm_exec.rb
@@ -900,7 +900,7 @@ class ExecDriver < VirtualMachineDriver
target_index = target.downcase[-1..-1].unpack('c').first - 97
if @options[:detach_snap]
- disk = xml_data.elements[target_xpath]
+ disk = xml_data.elements[target_xpath].parent
attach = REXML::Element.new('ATTACH')
attach.add_text('YES')
@@ -973,7 +973,7 @@ class ExecDriver < VirtualMachineDriver
target_index = target.downcase[-1..-1].unpack('c').first - 97
if @options[:detach_snap]
- disk = xml_data.elements[target_xpath]
+ disk = xml_data.elements[target_xpath].parent
attach = REXML::Element.new('ATTACH')
attach.add_text('YES')