mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-23 22:50:09 +03:00
parent
15a5c1e76d
commit
2bba9e1b8f
src
cli
flow
oca/ruby/opennebula/flow
@ -428,4 +428,76 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
###
|
||||
|
||||
add_role_desc = <<-EOT.unindent
|
||||
Add new role to running service
|
||||
EOT
|
||||
|
||||
command :'add-role', add_role_desc, :service_id, [:file, nil] do
|
||||
service_id = args[0]
|
||||
client = helper.client(options)
|
||||
|
||||
if args[1]
|
||||
path = args[1]
|
||||
else
|
||||
tmp = Tempfile.new(service_id.to_s)
|
||||
path = tmp.path
|
||||
|
||||
if ENV['EDITOR']
|
||||
editor_path = ENV['EDITOR']
|
||||
else
|
||||
editor_path = OpenNebulaHelper::EDITOR_PATH
|
||||
end
|
||||
|
||||
system("#{editor_path} #{path}")
|
||||
|
||||
unless $CHILD_STATUS.exitstatus.zero?
|
||||
STDERR.puts 'Editor not defined'
|
||||
exit(-1)
|
||||
end
|
||||
|
||||
tmp.close
|
||||
end
|
||||
|
||||
params = {}
|
||||
params[:role] = File.read(path)
|
||||
params[:add] = true
|
||||
json = Service.build_json_action('add_role', params)
|
||||
|
||||
response = client.post("#{RESOURCE_PATH}/#{service_id}/role_action",
|
||||
json)
|
||||
|
||||
if CloudClient.is_error?(response)
|
||||
[response.code.to_i, response.to_s]
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
###
|
||||
|
||||
remove_role_desc = <<-EOT.unindent
|
||||
Remove role from running service
|
||||
EOT
|
||||
|
||||
command :'remove-role', remove_role_desc, :service_id, :role_name do
|
||||
service_id = args[0]
|
||||
client = helper.client(options)
|
||||
|
||||
params = {}
|
||||
params[:role] = args[1]
|
||||
params[:add] = false
|
||||
json = Service.build_json_action('remove_role', params)
|
||||
|
||||
response = client.post("#{RESOURCE_PATH}/#{service_id}/role_action",
|
||||
json)
|
||||
|
||||
if CloudClient.is_error?(response)
|
||||
[response.code.to_i, response.to_s]
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -31,6 +31,8 @@ class EventManager
|
||||
'WAIT_UNDEPLOY' => :wait_undeploy,
|
||||
'WAIT_SCALEUP' => :wait_scaleup,
|
||||
'WAIT_SCALEDOWN' => :wait_scaledown,
|
||||
'WAIT_ADD' => :wait_add,
|
||||
'WAIT_REMOVE' => :wait_remove,
|
||||
'WAIT_COOLDOWN' => :wait_cooldown
|
||||
}
|
||||
|
||||
@ -86,6 +88,10 @@ class EventManager
|
||||
method('wait_cooldown'))
|
||||
@am.register_action(ACTIONS['WAIT_SCALEUP'],
|
||||
method('wait_scaleup_action'))
|
||||
@am.register_action(ACTIONS['WAIT_ADD'],
|
||||
method('wait_add_action'))
|
||||
@am.register_action(ACTIONS['WAIT_REMOVE'],
|
||||
method('wait_remove_action'))
|
||||
@am.register_action(ACTIONS['WAIT_SCALEDOWN'],
|
||||
method('wait_scaledown_action'))
|
||||
|
||||
@ -204,6 +210,56 @@ class EventManager
|
||||
end
|
||||
end
|
||||
|
||||
def wait_add_action(client, service_id, role_name, nodes, report)
|
||||
if report
|
||||
Log.info LOG_COMP, "Waiting #{nodes} to report ready"
|
||||
rc = wait_report_ready(nodes)
|
||||
else
|
||||
Log.info LOG_COMP, "Waiting #{nodes} to be (ACTIVE, RUNNING)"
|
||||
rc = wait(nodes, 'ACTIVE', 'RUNNING')
|
||||
end
|
||||
|
||||
if rc[0]
|
||||
@lcm.trigger_action(:add_cb,
|
||||
service_id,
|
||||
client,
|
||||
service_id,
|
||||
role_name,
|
||||
rc[1])
|
||||
else
|
||||
@lcm.trigger_action(:add_failure_cb,
|
||||
service_id,
|
||||
client,
|
||||
service_id,
|
||||
role_name)
|
||||
end
|
||||
end
|
||||
|
||||
# Wait for nodes to be in DONE
|
||||
# @param [service_id] the service id
|
||||
# @param [role_name] the role name of the role which contains the VMs
|
||||
# @param [nodes] the list of nodes (VMs) to wait for
|
||||
def wait_remove_action(client, service_id, role_name, nodes)
|
||||
Log.info LOG_COMP, "Waiting #{nodes} to be (DONE, LCM_INIT)"
|
||||
rc = wait(nodes, 'DONE', 'LCM_INIT')
|
||||
|
||||
if rc[0]
|
||||
@lcm.trigger_action(:remove_cb,
|
||||
service_id,
|
||||
client,
|
||||
service_id,
|
||||
role_name,
|
||||
rc[1])
|
||||
else
|
||||
@lcm.trigger_action(:remove_failure_cb,
|
||||
service_id,
|
||||
client,
|
||||
service_id,
|
||||
role_name,
|
||||
rc[1])
|
||||
end
|
||||
end
|
||||
|
||||
# Wait for nodes to be in DONE
|
||||
# @param [service_id] the service id
|
||||
# @param [role_name] the role name of the role which contains the VMs
|
||||
|
@ -39,6 +39,10 @@ class ServiceLCM
|
||||
'SCALEUP_FAILURE_CB' => :scaleup_failure_cb,
|
||||
'SCALEDOWN_CB' => :scaledown_cb,
|
||||
'SCALEDOWN_FAILURE_CB' => :scaledown_failure_cb,
|
||||
'ADD_CB' => :add_cb,
|
||||
'ADD_FAILURE_CB' => :add_failure_cb,
|
||||
'REMOVE_CB' => :remove_cb,
|
||||
'REMOVE_FAILURE_CB' => :remove_failure_cb,
|
||||
|
||||
# WD callbacks
|
||||
'ERROR_WD_CB' => :error_wd_cb,
|
||||
@ -79,6 +83,14 @@ class ServiceLCM
|
||||
method('scaledown_failure_cb'))
|
||||
@am.register_action(ACTIONS['COOLDOWN_CB'],
|
||||
method('cooldown_cb'))
|
||||
@am.register_action(ACTIONS['ADD_CB'],
|
||||
method('add_cb'))
|
||||
@am.register_action(ACTIONS['add_FAILURE_CB'],
|
||||
method('add_failure_cb'))
|
||||
@am.register_action(ACTIONS['REMOVE_CB'],
|
||||
method('remove_cb'))
|
||||
@am.register_action(ACTIONS['REMOVE_FAILURE_CB'],
|
||||
method('remove_failure_cb'))
|
||||
@am.register_action(ACTIONS['ERROR_WD_CB'],
|
||||
method('error_wd_cb'))
|
||||
@am.register_action(ACTIONS['DONE_WD_CB'],
|
||||
@ -252,7 +264,7 @@ class ServiceLCM
|
||||
roles,
|
||||
'DEPLOYING',
|
||||
'FAILED_DEPLOYING',
|
||||
false,
|
||||
:wait_deploy,
|
||||
service.report_ready?)
|
||||
|
||||
if !OpenNebula.is_error?(rc)
|
||||
@ -304,7 +316,7 @@ class ServiceLCM
|
||||
roles,
|
||||
'UNDEPLOYING',
|
||||
'FAILED_UNDEPLOYING',
|
||||
false)
|
||||
:wait_undeploy)
|
||||
|
||||
if !OpenNebula.is_error?(rc)
|
||||
service.set_state(Service::STATE['UNDEPLOYING'])
|
||||
@ -371,7 +383,7 @@ class ServiceLCM
|
||||
{ role_name => role },
|
||||
'SCALING',
|
||||
'FAILED_SCALING',
|
||||
true,
|
||||
:wait_scaleup,
|
||||
service.report_ready?)
|
||||
elsif cardinality_diff < 0
|
||||
role.scale_way('DOWN')
|
||||
@ -380,7 +392,7 @@ class ServiceLCM
|
||||
{ role_name => role },
|
||||
'SCALING',
|
||||
'FAILED_SCALING',
|
||||
true)
|
||||
:wait_scaledown)
|
||||
else
|
||||
break OpenNebula::Error.new(
|
||||
"Cardinality of #{role_name} is already at #{cardinality}"
|
||||
@ -515,6 +527,69 @@ class ServiceLCM
|
||||
rc
|
||||
end
|
||||
|
||||
# Add role from running service
|
||||
#
|
||||
# @param client [OpenNebula::Client] Client executing action
|
||||
# @param service_id [Integer] Service ID
|
||||
# @param role [Hash] Role information
|
||||
def add_role_action(client, service_id, role)
|
||||
rc = @srv_pool.get(service_id, client) do |service|
|
||||
unless service.running?
|
||||
break OpenNebula::Error.new(
|
||||
"Cannot modify roles in state: #{service.state_str}"
|
||||
)
|
||||
end
|
||||
|
||||
role = service.add_role(role)
|
||||
|
||||
break role if OpenNebula.is_error?(role)
|
||||
|
||||
service.update
|
||||
|
||||
rc = service.deploy_networks(false)
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
service.set_state(Service::STATE['FAILED_DEPLOYING'])
|
||||
service.update
|
||||
|
||||
break rc
|
||||
end
|
||||
|
||||
service.update
|
||||
|
||||
add_role(client, service, role)
|
||||
end
|
||||
|
||||
Log.error LOG_COMP, rc.message if OpenNebula.is_error?(rc)
|
||||
|
||||
rc
|
||||
end
|
||||
|
||||
# Remove role from running service
|
||||
#
|
||||
# @param client [OpenNebula::Client] Client executing action
|
||||
# @param service_id [Integer] Service ID
|
||||
# @param role [Hash] Role information
|
||||
def remove_role_action(client, service_id, role)
|
||||
rc = @srv_pool.get(service_id, client) do |service|
|
||||
unless service.running?
|
||||
break OpenNebula::Error.new(
|
||||
"Cannot modify roles in state: #{service.state_str}"
|
||||
)
|
||||
end
|
||||
|
||||
unless service.roles[role]
|
||||
break OpenNebula::Error.new("Role #{role} does not exist")
|
||||
end
|
||||
|
||||
remove_role(client, service, service.roles[role])
|
||||
end
|
||||
|
||||
Log.error LOG_COMP, rc.message if OpenNebula.is_error?(rc)
|
||||
|
||||
rc
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
############################################################################
|
||||
@ -547,7 +622,7 @@ class ServiceLCM
|
||||
service.roles_deploy,
|
||||
'DEPLOYING',
|
||||
'FAILED_DEPLOYING',
|
||||
false,
|
||||
:wait_deploy,
|
||||
service.report_ready?)
|
||||
end
|
||||
|
||||
@ -608,7 +683,7 @@ class ServiceLCM
|
||||
service.roles_shutdown,
|
||||
'UNDEPLOYING',
|
||||
'FAILED_UNDEPLOYING',
|
||||
false)
|
||||
:wait_undeploy)
|
||||
end
|
||||
|
||||
service.update
|
||||
@ -749,6 +824,72 @@ class ServiceLCM
|
||||
undeploy_action(client, service_id)
|
||||
end
|
||||
|
||||
def add_cb(client, service_id, role_name, _)
|
||||
rc = @srv_pool.get(service_id, client) do |service|
|
||||
service.roles[role_name].set_state(Role::STATE['RUNNING'])
|
||||
|
||||
service.set_state(Service::STATE['RUNNING'])
|
||||
|
||||
rc = service.update
|
||||
|
||||
return rc if OpenNebula.is_error?(rc)
|
||||
|
||||
@wd.add_service(service) if service.all_roles_running?
|
||||
end
|
||||
|
||||
Log.error LOG_COMP, rc.message if OpenNebula.is_error?(rc)
|
||||
end
|
||||
|
||||
def add_failure_cb(client, service_id, role_name)
|
||||
rc = @srv_pool.get(service_id, client) do |service|
|
||||
# stop actions for the service if deploy fails
|
||||
@event_manager.cancel_action(service_id)
|
||||
|
||||
service.set_state(Service::STATE['FAILED_DEPLOYING'])
|
||||
service.roles[role_name].set_state(Role::STATE['FAILED_DEPLOYING'])
|
||||
|
||||
service.update
|
||||
end
|
||||
|
||||
Log.error LOG_COMP, rc.message if OpenNebula.is_error?(rc)
|
||||
end
|
||||
|
||||
def remove_cb(client, service_id, role_name, _)
|
||||
rc = @srv_pool.get(service_id, client) do |service|
|
||||
service.remove_role(role_name)
|
||||
|
||||
service.set_state(Service::STATE['RUNNING'])
|
||||
|
||||
rc = service.update
|
||||
|
||||
return rc if OpenNebula.is_error?(rc)
|
||||
|
||||
@wd.add_service(service) if service.all_roles_running?
|
||||
end
|
||||
|
||||
Log.error LOG_COMP, rc.message if OpenNebula.is_error?(rc)
|
||||
end
|
||||
|
||||
def remove_failure_cb(client, service_id, role_name, nodes)
|
||||
rc = @srv_pool.get(service_id, client) do |service|
|
||||
# stop actions for the service if deploy fails
|
||||
@event_manager.cancel_action(service_id)
|
||||
|
||||
service.set_state(Service::STATE['FAILED_UNDEPLOYING'])
|
||||
service.roles[role_name]
|
||||
.set_state(Role::STATE['FAILED_UNDEPLOYING'])
|
||||
|
||||
service.roles[role_name].nodes.delete_if do |node|
|
||||
!nodes[:failure].include?(node['deploy_id']) &&
|
||||
nodes[:successful].include?(node['deploy_id'])
|
||||
end
|
||||
|
||||
service.update
|
||||
end
|
||||
|
||||
Log.error LOG_COMP, rc.message if OpenNebula.is_error?(rc)
|
||||
end
|
||||
|
||||
############################################################################
|
||||
# WatchDog Callbacks
|
||||
############################################################################
|
||||
@ -773,7 +914,10 @@ class ServiceLCM
|
||||
undeploy = false
|
||||
|
||||
rc = @srv_pool.get(service_id, client) do |service|
|
||||
role = service.roles[role_name]
|
||||
role = service.roles[role_name]
|
||||
|
||||
next unless role
|
||||
|
||||
cardinality = role.cardinality - 1
|
||||
|
||||
next unless role.nodes.find {|n| n['deploy_id'] == node }
|
||||
@ -857,14 +1001,8 @@ class ServiceLCM
|
||||
# @param [Role::STATE] error_state new state of the role
|
||||
# if deployed unsuccessfuly
|
||||
# rubocop:disable Metrics/ParameterLists
|
||||
def deploy_roles(client, roles, success_state, error_state, scale, report)
|
||||
def deploy_roles(client, roles, success_state, error_state, action, report)
|
||||
# rubocop:enable Metrics/ParameterLists
|
||||
if scale
|
||||
action = :wait_scaleup
|
||||
else
|
||||
action = :wait_deploy
|
||||
end
|
||||
|
||||
roles.each do |name, role|
|
||||
rc = role.deploy
|
||||
|
||||
@ -887,13 +1025,7 @@ class ServiceLCM
|
||||
end
|
||||
end
|
||||
|
||||
def undeploy_roles(client, roles, success_state, error_state, scale)
|
||||
if scale
|
||||
action = :wait_scaledown
|
||||
else
|
||||
action = :wait_undeploy
|
||||
end
|
||||
|
||||
def undeploy_roles(client, roles, success_state, error_state, action)
|
||||
roles.each do |name, role|
|
||||
rc = role.shutdown(false)
|
||||
|
||||
@ -981,5 +1113,54 @@ class ServiceLCM
|
||||
end
|
||||
end
|
||||
|
||||
def add_role(client, service, role)
|
||||
@wd.remove_service(service.id)
|
||||
|
||||
set_deploy_strategy(service)
|
||||
|
||||
rc = deploy_roles(client,
|
||||
{ role.name => role },
|
||||
'DEPLOYING',
|
||||
'FAILED_DEPLOYING',
|
||||
:wait_add,
|
||||
service.report_ready?)
|
||||
|
||||
if !OpenNebula.is_error?(rc)
|
||||
service.set_state(Service::STATE['DEPLOYING'])
|
||||
else
|
||||
service.set_state(Service::STATE['FAILED_DEPLOYING'])
|
||||
end
|
||||
|
||||
service.update
|
||||
|
||||
Log.error LOG_COMP, rc.message if OpenNebula.is_error?(rc)
|
||||
|
||||
rc
|
||||
end
|
||||
|
||||
def remove_role(client, service, role)
|
||||
@wd.remove_service(service.id)
|
||||
|
||||
set_deploy_strategy(service)
|
||||
|
||||
rc = undeploy_roles(client,
|
||||
{ role.name => role },
|
||||
'UNDEPLOYING',
|
||||
'FAILED_UNDEPLOYING',
|
||||
:wait_remove)
|
||||
|
||||
if !OpenNebula.is_error?(rc)
|
||||
service.set_state(Service::STATE['UNDEPLOYING'])
|
||||
else
|
||||
service.set_state(Service::STATE['FAILED_UNDEPLOYING'])
|
||||
end
|
||||
|
||||
service.update
|
||||
|
||||
Log.error LOG_COMP, rc.message if OpenNebula.is_error?(rc)
|
||||
|
||||
rc
|
||||
end
|
||||
|
||||
end
|
||||
# rubocop:enable Naming/FileName
|
||||
|
@ -43,7 +43,8 @@ class ServiceAutoScaler
|
||||
monitoring = vm_pool.monitoring_xml(-2, 0)
|
||||
monitoring = XMLElement.new(XMLElement.build_xml(monitoring,
|
||||
'MONITORING_DATA'))
|
||||
monitoring = monitoring.to_hash['MONITORING_DATA']['MONITORING']
|
||||
monitoring = monitoring.to_hash['MONITORING_DATA']
|
||||
monitoring = monitoring['MONITORING'] if monitoring
|
||||
monitoring = [monitoring].flatten
|
||||
|
||||
vm_pool.info_all_extended
|
||||
|
@ -141,7 +141,7 @@ module OpenNebula
|
||||
# @return true if the service can be undeployed, false otherwise
|
||||
def can_undeploy?
|
||||
if (transient_state? && state != Service::STATE['UNDEPLOYING']) ||
|
||||
state == Service::STATE['DONE'] || failed_state?
|
||||
state == Service::STATE['DONE'] || failed_state?
|
||||
false
|
||||
else
|
||||
true
|
||||
@ -166,6 +166,12 @@ module OpenNebula
|
||||
RECOVER_SCALE_STATES.include? STATE_STR[state]
|
||||
end
|
||||
|
||||
# Return true if the service is running
|
||||
# @return true if the service is runnning, false otherwise
|
||||
def running?
|
||||
state_str == 'RUNNING'
|
||||
end
|
||||
|
||||
# Returns the running_status_vm option
|
||||
# @return [true, false] true if the running_status_vm option is enabled
|
||||
def report_ready?
|
||||
@ -323,6 +329,36 @@ module OpenNebula
|
||||
nil
|
||||
end
|
||||
|
||||
# Adds a role to the service
|
||||
#
|
||||
# @param template [Hash] Role information
|
||||
#
|
||||
# @return [OpenNebula::Role] New role
|
||||
def add_role(template)
|
||||
template['state'] ||= Role::STATE['PENDING']
|
||||
role = Role.new(template, self)
|
||||
|
||||
if @roles[role.name]
|
||||
return OpenNebula::Error.new("Role #{role.name} already exists")
|
||||
end
|
||||
|
||||
@roles[role.name] = role
|
||||
@body['roles'] << template if @body && @body['roles']
|
||||
|
||||
role
|
||||
end
|
||||
|
||||
# Removes a role from the service
|
||||
#
|
||||
# @param name [String] Role name to delete
|
||||
def remove_role(name)
|
||||
@roles.delete(name)
|
||||
|
||||
@body['roles'].delete_if do |role|
|
||||
role['name'] == name
|
||||
end
|
||||
end
|
||||
|
||||
# Retrieves the information of the Service and all its Nodes.
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
@ -514,8 +550,12 @@ module OpenNebula
|
||||
[true, nil]
|
||||
end
|
||||
|
||||
def deploy_networks
|
||||
body = JSON.parse(self['TEMPLATE/BODY'])
|
||||
def deploy_networks(deploy = true)
|
||||
if deploy
|
||||
body = JSON.parse(self['TEMPLATE/BODY'])
|
||||
else
|
||||
body = @body
|
||||
end
|
||||
|
||||
return if body['networks_values'].nil?
|
||||
|
||||
@ -531,7 +571,7 @@ module OpenNebula
|
||||
if OpenNebula.is_error?(rc)
|
||||
return rc
|
||||
end
|
||||
end
|
||||
end if deploy
|
||||
|
||||
# Replace $attibute by the corresponding value
|
||||
resolve_attributes(body)
|
||||
|
@ -403,6 +403,38 @@ post '/service/:id/scale' do
|
||||
status 204
|
||||
end
|
||||
|
||||
post '/service/:id/role_action' do
|
||||
action = JSON.parse(request.body.read)['action']
|
||||
opts = action['params']
|
||||
|
||||
case action['perform']
|
||||
when 'add_role'
|
||||
begin
|
||||
# Check that the JSON is valid
|
||||
json_template = JSON.parse(opts['role'])
|
||||
|
||||
# Check the schema of the new template
|
||||
ServiceTemplate.validate_role(json_template)
|
||||
rescue Validator::ParseException, JSON::ParserError => e
|
||||
return internal_error(e.message, VALIDATION_EC)
|
||||
end
|
||||
|
||||
rc = lcm.add_role_action(@client, params[:id], json_template)
|
||||
when 'remove_role'
|
||||
rc = lcm.remove_role_action(@client, params[:id], opts['role'])
|
||||
else
|
||||
rc = OpenNebula::Error.new(
|
||||
"Action #{action['perform']} not supported"
|
||||
)
|
||||
end
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
return internal_error(rc.message, one_error_to_http(rc.errno))
|
||||
end
|
||||
|
||||
status 204
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Service Pool
|
||||
##############################################################################
|
||||
|
@ -451,6 +451,16 @@ module OpenNebula
|
||||
validate_values(template)
|
||||
end
|
||||
|
||||
def self.validate_role(template)
|
||||
validator = Validator::Validator.new(
|
||||
:default_values => true,
|
||||
:delete_extra_properties => false,
|
||||
:allow_extra_properties => true
|
||||
)
|
||||
|
||||
validator.validate!(template, ROLE_SCHEMA)
|
||||
end
|
||||
|
||||
def instantiate(merge_template)
|
||||
rc = nil
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user