* refactoring (rename 'fast_provision' to 'provision', 'provision' to 'watch_provision_progress' and more)

* fix bug with ignoring node status for provision operation (+ test);
* small test refactoring.
This commit is contained in:
Vladmir Sharhsov(warpc) 2013-09-16 15:31:55 +04:00
parent 8b54068de0
commit ba1c303b72
4 changed files with 91 additions and 82 deletions

View File

@ -97,14 +97,11 @@ if [:deploy, :provision, :provision_and_deploy].include? opts[:command]
end
def console_provision(orchestrator, reporter, environment)
res = orchestrator.fast_provision(reporter, environment['engine'], environment['nodes'])
if res == Astute::SUCCESS
puts "restarting nodes..."
sleep 5
puts "start watching progress"
res = orchestrator.provision(reporter, environment['task_uuid'], environment['nodes'])
end
res
orchestrator.provision(reporter, environment['engine'], environment['nodes'])
puts "restarting nodes..."
sleep 5
puts "start watching progress"
orchestrator.watch_provision_progress(reporter, environment['task_uuid'], environment['nodes'])
end
result = Astute::SUCCESS

View File

@ -43,15 +43,17 @@ module Astute
context.status
end
def fast_provision(reporter, engine_attrs, nodes)
raise "Nodes to provision are not provided!" if nodes.empty?
def provision(reporter, engine_attrs, nodes_for_provision)
raise "Nodes to provision are not provided!" if nodes_for_provision.empty?
# We need only those which are not ready/provisioned yet
nodes = nodes_for_provision.select { |n| !['provisioned', 'ready'].include?(n['status']) }
engine = create_engine(engine_attrs, reporter)
begin
add_nodes_to_cobbler(engine, nodes)
reboot_events = reboot_nodes(engine, nodes)
failed_nodes = check_reboot_nodes(engine, reboot_events)
rescue RuntimeError => e
Astute.logger.error("Error occured while provisioning: #{e.inspect}")
reporter.report({
@ -59,14 +61,13 @@ module Astute
'error' => 'Cobbler error',
'progress' => 100
})
raise StopIteration
raise e
ensure
engine.sync
end
if failed_nodes.empty?
report_result({}, reporter)
return SUCCESS
else
Astute.logger.error("Nodes failed to reboot: #{failed_nodes.inspect}")
reporter.report({
@ -74,18 +75,12 @@ module Astute
'error' => "Nodes failed to reboot: #{failed_nodes.inspect}",
'progress' => 100
})
raise StopIteration
raise e
end
end
def provision(reporter, task_id, nodes_up)
raise "Nodes to provision are not provided!" if nodes_up.empty?
# We need only those which are not ready/provisioned yet
nodes = []
nodes_up.each do |n|
nodes << n unless ['provisioned', 'ready'].include?(n['status'])
end
def watch_provision_progress(reporter, task_id, nodes)
raise "Nodes to provision are not provided!" if nodes.empty?
nodes_uids = nodes.map { |n| n['uid'] }
@ -198,10 +193,10 @@ module Astute
Astute::RedhatChecker.new(ctx, credentials).check_redhat_credentials
rescue Astute::RedhatCheckingError => e
Astute.logger.error("Error #{e.message}")
raise StopIteration
raise e
rescue Exception => e
Astute.logger.error("Unexpected error #{e.message} traceback #{e.format_backtrace}")
raise StopIteration
raise e
end
end
@ -211,10 +206,10 @@ module Astute
Astute::RedhatChecker.new(ctx, credentials).check_redhat_licenses(nodes)
rescue Astute::RedhatCheckingError => e
Astute.logger.error("Error #{e.message}")
raise StopIteration
raise e
rescue Exception => e
Astute.logger.error("Unexpected error #{e.message} traceback #{e.format_backtrace}")
raise StopIteration
raise e
end
end
@ -236,23 +231,23 @@ module Astute
end
def create_engine(engine_attrs, reporter)
raise "Settings for Cobbler must be set" if engine_attrs.blank?
begin
Astute.logger.info("Trying to instantiate cobbler engine: #{engine_attrs.inspect}")
Astute::Provision::Cobbler.new(engine_attrs)
rescue
rescue => e
Astute.logger.error("Error occured during cobbler initializing")
reporter.report({
'status' => 'error',
'error' => 'Cobbler can not be initialized',
'progress' => 100
})
raise StopIteration
raise e
end
end
def reboot_nodes(engine, nodes)
reboot_events = {}
def add_nodes_to_cobbler(engine, nodes)
nodes.each do |node|
begin
Astute.logger.info("Adding #{node['name']} into cobbler")
@ -262,6 +257,12 @@ module Astute
Astute.logger.error("Error occured while adding system #{node['name']} to cobbler")
raise e
end
end # end iteration
end
def reboot_nodes(engine, nodes)
reboot_events = {}
nodes.each do |node|
Astute.logger.debug("Trying to reboot node: #{node['name']}")
reboot_events[node['name']] = engine.power_reboot(node['name'])
end

View File

@ -45,12 +45,11 @@ describe Cobbler do
end
it "should be able to be initialized with 'host', 'port', 'path'" do
host = "host.domain.tld"
port = "1234"
path = "/api"
username = 'user'
password = 'pass'
host = "host.domain.tld"
path = "/api"
port = "1234"
remote = mock() do
expects(:call).with('login', username, password)
end
@ -78,8 +77,10 @@ describe Cobbler do
XMLRPC::Client = mock() do
stubs(:new).returns(remote)
end
@data = {
end
let(:data) do
{
'profile' => 'centos-x86_64',
'power_type' => 'ssh',
'power_user' => 'root',
@ -146,7 +147,7 @@ describe Cobbler do
end
it "item_from_hash should modify item with cobblerized data" do
cobblerized_data = Astute::Provision::Cobsh.new(@data.merge({'what' => 'system', 'name' => 'name'})).cobblerized
cobblerized_data = Astute::Provision::Cobsh.new(data.merge({'what' => 'system', 'name' => 'name'})).cobblerized
cobbler = Astute::Provision::Cobbler.new
cobbler.stubs(:get_item_id).with('system', 'name').returns('itemid')
cobblerized_data.each do |opt, value|
@ -160,11 +161,11 @@ describe Cobbler do
'remotetoken'
)
end
cobbler.item_from_hash('system', 'name', @data, :item_preremove => true)
cobbler.item_from_hash('system', 'name', data, :item_preremove => true)
end
it "item_from_hash should modify 'system' interfaces with cobblerized['interfaces']" do
cobblerized_data = Astute::Provision::Cobsh.new(@data.merge({'what' => 'system', 'name' => 'name'})).cobblerized
cobblerized_data = Astute::Provision::Cobsh.new(data.merge({'what' => 'system', 'name' => 'name'})).cobblerized
cobbler = Astute::Provision::Cobbler.new
cobbler.stubs(:get_item_id).with('system', 'name').returns('itemid')
cobbler.remote.expects(:call).with(
@ -173,7 +174,7 @@ describe Cobbler do
'modify_interface',
cobblerized_data['interfaces'],
'remotetoken')
cobbler.item_from_hash('system', 'name', @data, :item_preremove => true)
cobbler.item_from_hash('system', 'name', data, :item_preremove => true)
end
end

View File

@ -215,10 +215,10 @@ describe Astute::Orchestrator do
res.should eql({'nodes' => [{'uid' => '1'}, {'uid' => '2'}]})
end
it "remove_nodes do not fail if any of nodes failed"
xit "remove_nodes do not fail if any of nodes failed"
before(:all) do
@data = {
let(:data) do
{
"engine"=>{
"url"=>"http://localhost/cobbler_api",
"username"=>"cobbler",
@ -266,33 +266,31 @@ describe Astute::Orchestrator do
}
}
]
}.freeze
}
end
describe '#fast_provision' do
describe '#provision' do
context 'cobler cases' do
it "raise error if cobler settings empty" do
expect {@orchestrator.fast_provision(@reporter, {}, @data['nodes'])}.
to raise_error(StopIteration)
expect {@orchestrator.provision(@reporter, {}, data['nodes'])}.
to raise_error(/Settings for Cobbler must be set/)
end
end
context 'node state cases' do
before(:each) do
remote = mock() do
stubs(:call)
stubs(:call).with('login', 'cobbler', 'cobbler').returns('remotetoken')
end
@tmp = XMLRPC::Client
XMLRPC::Client = mock() do
stubs(:new).returns(remote)
end
end
it "raises error if nodes list is empty" do
expect {@orchestrator.fast_provision(@reporter, @data['engine'], {})}.
expect {@orchestrator.provision(@reporter, data['engine'], {})}.
to raise_error(/Nodes to provision are not provided!/)
end
@ -301,13 +299,28 @@ describe Astute::Orchestrator do
expects(:power_reboot).with('controller-1')
end
@orchestrator.stubs(:check_reboot_nodes).returns([])
@orchestrator.fast_provision(@reporter, @data['engine'], @data['nodes'])
@orchestrator.provision(@reporter, data['engine'], data['nodes'])
end
it "should not provision nodes that ready for deploy" do
nodes = deep_copy data['nodes']
nodes << {'uid' => '2', 'status' => 'ready'}
nodes << {'uid' => '3', 'status' => 'provisioned'}
engine = mock
engine.stubs(:sync)
@orchestrator.stubs(:create_engine).returns(engine)
@orchestrator.stubs(:reboot_nodes).returns([])
@orchestrator.stubs(:check_reboot_nodes).returns([])
@orchestrator.expects(:add_nodes_to_cobbler).with(engine, data['nodes'])
@orchestrator.provision(@reporter, data['engine'], nodes)
end
before(:each) { Astute::Provision::Cobbler.any_instance.stubs(:power_reboot).returns(333) }
context 'node reboot success' do
before(:each) { Astute::Provision::Cobbler.any_instance.stubs(:event_status).
returns([Time.now.to_f, 'controller-1', 'complete'])}
@ -315,47 +328,44 @@ describe Astute::Orchestrator do
Astute::Provision::Cobbler.any_instance.stubs(:event_status).
returns([Time.now.to_f, 'controller-1', 'complete'])
@orchestrator.fast_provision(@reporter, @data['engine'], @data['nodes'])
@orchestrator.provision(@reporter, data['engine'], data['nodes'])
end
it "report about success" do
@reporter.expects(:report).with({'status' => 'ready', 'progress' => 100}).returns(true)
@orchestrator.fast_provision(@reporter, @data['engine'], @data['nodes'])
@orchestrator.provision(@reporter, data['engine'], data['nodes'])
end
it "sync engine state" do
Astute::Provision::Cobbler.any_instance do
expects(:sync).once
end
@orchestrator.fast_provision(@reporter, @data['engine'], @data['nodes'])
@orchestrator.provision(@reporter, data['engine'], data['nodes'])
end
end
context 'node reboot fail' do
before(:each) { Astute::Provision::Cobbler.any_instance.stubs(:event_status).
returns([Time.now.to_f, 'controller-1', 'failed'])}
it "should sync engine state" do
Astute::Provision::Cobbler.any_instance do
expects(:sync).once
end
begin
@orchestrator.fast_provision(@reporter, @data['engine'], @data['nodes'])
@orchestrator.provision(@reporter, data['engine'], data['nodes'])
rescue
end
end
it "raise error if failed node find" do
expect {@orchestrator.fast_provision(@reporter, @data['engine'], @data['nodes'])}.to raise_error(StopIteration)
expect {@orchestrator.provision(@reporter, data['engine'], data['nodes'])}.to raise_error(TypeError)
end
end
end
end
describe '#provision' do
describe '#watch_provision_progress' do
before(:each) do
# Disable sleeping in test env (doubles the test speed)
@ -365,36 +375,36 @@ describe Astute::Orchestrator do
end
it "raises error if nodes list is empty" do
expect {@orchestrator.provision(@reporter, @data['task_uuid'], {})}.
expect {@orchestrator.watch_provision_progress(@reporter, data['task_uuid'], {})}.
to raise_error(/Nodes to provision are not provided!/)
end
it "prepare provision log for parsing" do
Astute::LogParser::ParseProvisionLogs.any_instance do
expects(:prepare).with(@data['nodes']).once
expects(:prepare).with(data['nodes']).once
end
@orchestrator.stubs(:report_about_progress).returns()
@orchestrator.stubs(:node_type).returns([{'uid' => '1', 'node_type' => 'target' }])
@orchestrator.provision(@reporter, @data['task_uuid'], @data['nodes'])
@orchestrator.watch_provision_progress(@reporter, data['task_uuid'], data['nodes'])
end
it "ignore problem with parsing provision log" do
Astute::LogParser::ParseProvisionLogs.any_instance do
stubs(:prepare).with(@data['nodes']).raises
stubs(:prepare).with(data['nodes']).raises
end
@orchestrator.stubs(:report_about_progress).returns()
@orchestrator.stubs(:node_type).returns([{'uid' => '1', 'node_type' => 'target' }])
@orchestrator.provision(@reporter, @data['task_uuid'], @data['nodes'])
@orchestrator.watch_provision_progress(@reporter, data['task_uuid'], data['nodes'])
end
it 'provision nodes using mclient' do
@orchestrator.stubs(:report_about_progress).returns()
@orchestrator.expects(:node_type).returns([{'uid' => '1', 'node_type' => 'target' }])
@orchestrator.provision(@reporter, @data['task_uuid'], @data['nodes'])
@orchestrator.watch_provision_progress(@reporter, data['task_uuid'], data['nodes'])
end
it "fail if timeout of provisioning is exceeded" do
@ -412,7 +422,7 @@ describe Astute::Orchestrator do
'error_type' => 'provision'}]}
@reporter.expects(:report).with(error_mgs).once
@orchestrator.provision(@reporter, @data['task_uuid'], @data['nodes'])
@orchestrator.watch_provision_progress(@reporter, data['task_uuid'], data['nodes'])
end
end
@ -439,32 +449,32 @@ describe Astute::Orchestrator do
describe '#check_redhat_credentials' do
it 'Should raise StopIteration in case of errors ' do
it 'should raise StopIteration in case of errors ' do
stub_rpc("Before\nInvalid username or password\nAfter")
expect do
@orchestrator.check_redhat_credentials(@reporter, @data['task_uuid'], credentials)
end.to raise_error(StopIteration)
@orchestrator.check_redhat_credentials(@reporter, data['task_uuid'], credentials)
end.to raise_error(/Invalid username or password/)
end
it 'Should not raise errors ' do
it 'should not raise errors' do
stub_rpc
@orchestrator.check_redhat_credentials(@reporter, @data['task_uuid'], credentials)
@orchestrator.check_redhat_credentials(@reporter, data['task_uuid'], credentials)
end
end
describe '#check_redhat_licenses' do
it 'Should raise StopIteration in case of errors ' do
it 'should raise StopIteration in case of errors ' do
stub_rpc('{"openstack_licenses_physical_hosts_count":0}')
expect do
@orchestrator.check_redhat_licenses(@reporter, @data['task_uuid'], credentials)
end.to raise_error(StopIteration)
@orchestrator.check_redhat_licenses(@reporter, data['task_uuid'], credentials)
end.to raise_error(/Could not find any valid Red Hat OpenStack subscriptions/)
end
it 'Should not raise errors ' do
it 'should not raise errors ' do
stub_rpc('{"openstack_licenses_physical_hosts_count":1}')
@orchestrator.check_redhat_licenses(@reporter, @data['task_uuid'], credentials)
@orchestrator.check_redhat_licenses(@reporter, data['task_uuid'], credentials)
end
end
end