diff --git a/src/cli/oneflow b/src/cli/oneflow index 9c02a546fd..c7a345c7f6 100755 --- a/src/cli/oneflow +++ b/src/cli/oneflow @@ -309,7 +309,7 @@ CommandParser::CmdParser.new(ARGV) do params = {} params[:period] = options[:period].to_i if options[:period] params[:number] = options[:number].to_i if options[:number] - params[:args] = options[:args] + params[:args] = options[:args] if options[:args] json = Service.build_json_action(args[2], params) client = helper.client(options) @@ -318,4 +318,29 @@ CommandParser::CmdParser.new(ARGV) do json) end end + + ### + + action_desc = <<-EOT.unindent + Perform an action on all the Virtual Machines of a given service. + Actions supported: #{Role::SCHEDULE_ACTIONS.join(',')} + EOT + + command [:service, :action], + action_desc, + :service_id, + :vm_action, + :options => [Service::PERIOD, Service::NUMBER, ARGS] do + Service.perform_action(args[0]) do |service_id| + params = {} + params[:period] = options[:period].to_i if options[:period] + params[:number] = options[:number].to_i if options[:number] + params[:args] = options[:args] if options[:args] + + json = Service.build_json_action(args[1], params) + client = helper.client(options) + + client.post("#{RESOURCE_PATH}/#{service_id}/action", json) + end + end end diff --git a/src/flow/lib/LifeCycleManager.rb b/src/flow/lib/LifeCycleManager.rb index 75d30e03ee..e7937203d8 100644 --- a/src/flow/lib/LifeCycleManager.rb +++ b/src/flow/lib/LifeCycleManager.rb @@ -151,6 +151,30 @@ class ServiceLCM rc end + # Add shced action to service + # + # @param client [OpenNebula::Client] Client executing action + # @param service_id [Integer] Service ID + # @param action [String] Action to perform + # @param period [Integer] When to execute the action + # @param number [Integer] How many VMs per period + # @param args [String] Action arguments + # + # @return [OpenNebula::Error] Error if any + # rubocop:disable Metrics/ParameterLists + def service_sched_action(client, service_id, action, period, number, args) + # rubocop:enable Metrics/ParameterLists + rc = @srv_pool.get(service_id, client) do |service| + service.roles.each do |_, role| + role.batch_action(action, period, number, args) + end + end + + Log.error LOG_COMP, rc.message if OpenNebula.is_error?(rc) + + rc + end + # Add shced action to service role # # @param client [OpenNebula::Client] Client executing action diff --git a/src/flow/oneflow-server.rb b/src/flow/oneflow-server.rb index de4e1d1a24..3bcd020da0 100644 --- a/src/flow/oneflow-server.rb +++ b/src/flow/oneflow-server.rb @@ -297,7 +297,22 @@ post '/service/:id/action' do # 'Only supported for append') # end else - rc = OpenNebula::Error.new("Action #{action['perform']} not supported") + if Role::SCHEDULE_ACTIONS.include?(action['perform']) + # Use defaults only if one of the options is supplied + opts['period'] ||= conf[:action_period] + opts['number'] ||= conf[:action_number] + + rc = lcm.service_sched_action(@client, + params[:id], + action['perform'], + opts['period'], + opts['number'], + opts['args']) + else + rc = OpenNebula::Error.new( + "Action #{action['perform']} not supported" + ) + end end if OpenNebula.is_error?(rc) diff --git a/src/sunstone/public/app/opennebula/action.js b/src/sunstone/public/app/opennebula/action.js index 32b6155d6c..d2752e9352 100644 --- a/src/sunstone/public/app/opennebula/action.js +++ b/src/sunstone/public/app/opennebula/action.js @@ -345,9 +345,12 @@ define(function(require) { var roleName = params && params.data && params.data.roleName var action = params && params.data && params.data.action var cacheName = params.cacheName ? params.cacheName : resource; - if(id!==undefined && roleName && action && resource){ + if(id!==undefined && action && resource){ $.ajax({ - url: resource.toLowerCase()+"/"+id+"/role/"+roleName+"/action", + url: roleName? + resource.toLowerCase()+"/"+id+"/role/"+roleName+"/action" + : + resource.toLowerCase()+"/"+id+"/action", type: "POST", contentType: "application/json; charset=utf-8", data: JSON.stringify({action: action}), diff --git a/src/sunstone/public/app/tabs/oneflow-services-tab/panels/sched-actions/html.hbs b/src/sunstone/public/app/tabs/oneflow-services-tab/panels/sched-actions/html.hbs index 1c41ac6341..9a692a9578 100644 --- a/src/sunstone/public/app/tabs/oneflow-services-tab/panels/sched-actions/html.hbs +++ b/src/sunstone/public/app/tabs/oneflow-services-tab/panels/sched-actions/html.hbs @@ -23,6 +23,7 @@ the License for the specific language governing permissions and }} {{! limitatio
+
diff --git a/src/sunstone/public/app/tabs/oneflow-services-tab/panels/sched_actions.js b/src/sunstone/public/app/tabs/oneflow-services-tab/panels/sched_actions.js index 986f45522e..e165d91ee3 100644 --- a/src/sunstone/public/app/tabs/oneflow-services-tab/panels/sched_actions.js +++ b/src/sunstone/public/app/tabs/oneflow-services-tab/panels/sched_actions.js @@ -92,8 +92,9 @@ define(function(require) { return role && role.name; }).map(function(role){ return ""; - }).join(""); - + }); + optionsRoles.unshift(""); + optionsRoles = optionsRoles.join(""); return TemplateHTML({ actions: optionsActions, res: RESOURCE, @@ -155,7 +156,7 @@ define(function(require) { var snap_id = $("#snapid").val(); var disk_id = $("#diskid").val(); - if(new_action && role){ + if(new_action){ var actionJSON = {}; actionJSON.error = function(e){ Notifier.notifyError((e && e.error && e.error.message) || Locale.tr("Error")); @@ -165,7 +166,6 @@ define(function(require) { }; actionJSON.data = {}; actionJSON.data.id = that.id; - actionJSON.data.roleName = role; actionJSON.data.action = {perform: new_action}; actionJSON.data.action.params = {}; if(period!=='' && period!==undefined){ @@ -181,6 +181,9 @@ define(function(require) { actionJSON.data.action.params.args = args; } } + if(role!=='' && role!==undefined){ + actionJSON.data.roleName = role; + } Actions.addFlowAction(actionJSON,RESOURCE); } return false;