fuel-astute/lib/astute/server/dispatcher.rb

301 lines
8.8 KiB
Ruby

# Copyright 2013 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
require 'astute/server/reporter'
module Astute
module Server
class Dispatcher
def initialize(producer)
@orchestrator = Astute::Orchestrator.new(log_parsing=true)
@producer = producer
@provisionLogParser = Astute::LogParser::ParseProvisionLogs.new
end
def echo(args)
Astute.logger.info('Running echo command')
args
end
#
# Main worker actions
#
def image_provision(data)
provision(data, 'image')
end
def native_provision(data)
provision(data, 'native')
end
def provision(data, provision_method)
Astute.logger.info("'provision' method called with data:\n"\
"#{data.pretty_inspect}")
reporter = create_reporter(data)
begin
result = @orchestrator.provision(
reporter,
data['args']['task_uuid'],
data['args']['provisioning_info'],
provision_method
)
rescue => e
Astute.logger.error("Error running provisioning: #{e.message}, "\
"trace: #{e.format_backtrace}")
raise StopIteration
end
raise StopIteration if result && result['status'] == 'error'
end
def deploy(data)
Astute.logger.info("'deploy' method called with data:\n"\
"#{data.pretty_inspect}")
reporter = create_reporter(data)
begin
@orchestrator.deploy(
reporter,
data['args']['task_uuid'],
data['args']['deployment_info'],
data['args']['pre_deployment'] || [],
data['args']['post_deployment'] || []
)
reporter.report('status' => 'ready', 'progress' => 100)
rescue Timeout::Error
msg = "Timeout of deployment is exceeded."
Astute.logger.error(msg)
reporter.report('status' => 'error', 'error' => msg)
end
end
def granular_deploy(data)
Astute.logger.info("'granular_deploy' method called with data:\n"\
"#{data.pretty_inspect}")
reporter = create_reporter(data)
begin
@orchestrator.granular_deploy(
reporter,
data['args']['task_uuid'],
data['args']['deployment_info'],
data['args']['pre_deployment'] || [],
data['args']['post_deployment'] || []
)
reporter.report('status' => 'ready', 'progress' => 100)
rescue Timeout::Error
msg = "Timeout of deployment is exceeded."
Astute.logger.error(msg)
reporter.report('status' => 'error', 'error' => msg)
end
end
def verify_networks(data)
data.fetch('subtasks', []).each do |subtask|
if self.respond_to?(subtask['method'])
self.send(subtask['method'], subtask)
else
Astute.logger.warn("No method for #{subtask}")
end
end
reporter = create_reporter(data)
result = @orchestrator.verify_networks(
reporter,
data['args']['task_uuid'],
data['args']['nodes']
)
report_result(result, reporter)
end
def check_dhcp(data)
reporter = create_reporter(data)
result = @orchestrator.check_dhcp(
reporter,
data['args']['task_uuid'],
data['args']['nodes']
)
report_result(result, reporter)
end
def multicast_verification(data)
reporter = create_reporter(data)
result = @orchestrator.multicast_verification(
reporter,
data['args']['task_uuid'],
data['args']['nodes']
)
report_result(result, reporter)
end
def check_repositories(data)
reporter = create_reporter(data)
result = @orchestrator.check_repositories(
reporter,
data['args']['task_uuid'],
data['args']['nodes'],
data['args']['urls']
)
report_result(result, reporter)
end
def check_repositories_with_setup(data)
reporter = create_reporter(data)
result = @orchestrator.check_repositories_with_setup(
reporter,
data['args']['task_uuid'],
data['args']['nodes']
)
report_result(result, reporter)
end
def dump_environment(data)
@orchestrator.dump_environment(
create_reporter(data),
data['args']['task_uuid'],
data['args']['settings']
)
end
def remove_nodes(data, reset=false)
task_uuid = data['args']['task_uuid']
reporter = create_reporter(data)
result = if data['args']['nodes'].empty?
Astute.logger.debug("#{task_uuid} Node list is empty")
nil
else
@orchestrator.remove_nodes(
reporter,
task_uuid,
data['args']['engine'],
data['args']['nodes'],
{
:reboot => true,
:check_ceph => data['args']['check_ceph'],
:reset => reset
}
)
end
report_result(result, reporter)
end
def reset_environment(data)
remove_nodes(data, reset=true)
end
def execute_tasks(data)
@orchestrator.execute_tasks(
create_reporter(data),
data['args']['task_uuid'],
data['args']['tasks']
)
end
#
# Service worker actions
#
def stop_deploy_task(data, service_data)
Astute.logger.debug("'stop_deploy_task' service method called with"\
"data:\n#{data.pretty_inspect}")
target_task_uuid = data['args']['stop_task_uuid']
task_uuid = data['args']['task_uuid']
return unless task_in_queue?(target_task_uuid,
service_data[:tasks_queue])
Astute.logger.debug("Cancel task #{target_task_uuid}. Start")
if target_task_uuid == service_data[:tasks_queue].current_task_id
reporter = create_reporter(data)
result = stop_current_task(data, service_data, reporter)
report_result(result, reporter)
else
replace_future_task(data, service_data)
end
end
private
def create_reporter(data)
Astute::Server::Reporter.new(
@producer,
data['respond_to'],
data['args']['task_uuid']
)
end
def task_in_queue?(task_uuid, tasks_queue)
tasks_queue.task_in_queue?(task_uuid)
end
def replace_future_task(data, service_data)
target_task_uuid = data['args']['stop_task_uuid']
task_uuid = data['args']['task_uuid']
new_task_data = data_for_rm_nodes(data)
Astute.logger.info("Replace running task #{target_task_uuid} to "\
"new #{task_uuid} with data:\n"\
"#{new_task_data.pretty_inspect}")
service_data[:tasks_queue].replace_task(
target_task_uuid,
new_task_data
)
end
def stop_current_task(data, service_data, reporter)
target_task_uuid = data['args']['stop_task_uuid']
task_uuid = data['args']['task_uuid']
nodes = data['args']['nodes']
Astute.logger.info("Try to kill running task #{target_task_uuid}")
service_data[:main_work_thread].kill
result = if ['deploy', 'task_deployment', 'granular_deploy'].include? (
service_data[:tasks_queue].current_task_method)
@orchestrator.stop_puppet_deploy(reporter, task_uuid, nodes)
@orchestrator.remove_nodes(
reporter,
task_uuid,
data['args']['engine'],
nodes
)
else
@orchestrator.stop_provision(
reporter,
task_uuid,
data['args']['engine'],
nodes
)
end
end
def data_for_rm_nodes(data)
data['method'] = 'remove_nodes'
data
end
def report_result(result, reporter)
result = {} unless result.instance_of?(Hash)
status = {'status' => 'ready', 'progress' => 100}.merge(result)
reporter.report(status)
end
end
end #Server
end #Astute