[FUEL-813] Add provision to CI, tests and small refactoring
This commit is contained in:
parent
1a000f42f2
commit
45ddbfa8bc
|
@ -11,7 +11,7 @@ Gem::Specification.new do |s|
|
|||
s.email = ['mscherbakov@mirantis.com']
|
||||
|
||||
s.add_dependency 'activesupport', '3.0.10'
|
||||
s.add_dependency 'mcollective-client', '2.3.1'
|
||||
s.add_dependency 'mcollective-client', '~> 2.2.4'
|
||||
s.add_dependency 'symboltable', '1.0.2'
|
||||
|
||||
s.add_development_dependency 'rspec', '2.13.0'
|
||||
|
|
15
bin/astute
15
bin/astute
|
@ -42,6 +42,11 @@ optparse = OptionParser.new do |o|
|
|||
end
|
||||
|
||||
o.on("-h") { puts o; exit }
|
||||
|
||||
o.on("-c", "--command [COMMAND]", [:deploy, :provision], "Select operation (deploy, provision)") do |c|
|
||||
opts[:command] = c || :deploy
|
||||
end
|
||||
|
||||
end
|
||||
optparse.parse!(ARGV)
|
||||
|
||||
|
@ -65,5 +70,11 @@ case environment['attributes']['deployment_engine']
|
|||
deploy_engine = nil # Orchestrator will use it's default
|
||||
end
|
||||
|
||||
orchestrator = Astute::Orchestrator.new(deploy_engine, log_parsing=false)
|
||||
orchestrator.deploy(reporter, environment['task_uuid'], environment['nodes'], environment['attributes'])
|
||||
case opts[:command]
|
||||
when :deploy
|
||||
orchestrator = Astute::Orchestrator.new(deploy_engine, log_parsing=false)
|
||||
orchestrator.deploy(reporter, environment['task_uuid'], environment['nodes'], environment['attributes'])
|
||||
when :provision
|
||||
orchestrator = Astute::Orchestrator.new(deploy_engine, log_parsing=false)
|
||||
orchestrator.provision(reporter, environment['engine'], environment['nodes'])
|
||||
end
|
|
@ -0,0 +1,74 @@
|
|||
---
|
||||
task_uuid: deployment_task
|
||||
|
||||
attributes:
|
||||
deployment_engine: simplepuppet
|
||||
|
||||
engine:
|
||||
url: http://localhost/cobbler_api
|
||||
username: cobbler
|
||||
password: cobbler
|
||||
|
||||
nodes:
|
||||
- profile: centos-x86_64
|
||||
name_servers_search: domain.tld
|
||||
ks_meta:
|
||||
mco_enable: 1
|
||||
mco_vhost: mcollective
|
||||
mco_pskey: unset
|
||||
ks_spaces: '"[{\"type\": \"disk\", \"id\": \"disk/by-path/pci-0000:00:0d.0-scsi-0:0:0:0\",
|
||||
\"volumes\": [{\"mount\": \"/boot\", \"type\": \"partition\", \"size\": 209715200},
|
||||
{\"type\": \"mbr\"}, {\"size\": 16959668224, \"type\": \"pv\", \"vg\": \"os\"}],
|
||||
\"size\": 17179869184}, {\"type\": \"disk\", \"id\": \"disk/by-path/pci-0000:00:0d.0-scsi-1:0:0:0\",
|
||||
\"volumes\": [{\"size\": 536860426240, \"type\": \"pv\", \"vg\": \"os\"}], \"size\":
|
||||
536870912000}, {\"type\": \"disk\", \"id\": \"disk/by-path/pci-0000:00:0d.0-scsi-2:0:0:0\",
|
||||
\"volumes\": [{\"size\": 2411714314240, \"type\": \"pv\", \"vg\": \"os\"}],
|
||||
\"size\": 2411724800000}, {\"type\": \"vg\", \"id\": \"os\", \"volumes\": [{\"mount\":
|
||||
\"/\", \"type\": \"lv\", \"name\": \"root\", \"size\": 2963243016192}, {\"mount\":
|
||||
\"swap\", \"type\": \"lv\", \"name\": \"swap\", \"size\": 2090065920}]}]"'
|
||||
mco_user: mcollective
|
||||
puppet_enable: 0
|
||||
install_log_2_syslog: 1
|
||||
mco_password: marionette
|
||||
puppet_auto_setup: 1
|
||||
puppet_master: fuelweb.domain.tld
|
||||
mco_auto_setup: 1
|
||||
auth_key: '""'
|
||||
puppet_version: 2.7.19
|
||||
mco_connector: rabbitmq
|
||||
mco_host: 10.20.0.2
|
||||
interfaces:
|
||||
eth2:
|
||||
ip_address: 10.20.0.129
|
||||
netmask: 255.255.255.0
|
||||
static: 0
|
||||
mac_address: 08:00:27:4E:1D:DD
|
||||
eth1:
|
||||
ip_address: 10.20.0.130
|
||||
netmask: 255.255.255.0
|
||||
static: 0
|
||||
mac_address: 08:00:27:86:97:99
|
||||
eth0:
|
||||
ip_address: 10.20.0.131
|
||||
netmask: 255.255.255.0
|
||||
dns_name: controller-1.domain.tld
|
||||
static: 0
|
||||
mac_address: 08:00:27:0B:2E:DD
|
||||
interfaces_extra:
|
||||
eth2:
|
||||
onboot: no
|
||||
peerdns: no
|
||||
eth1:
|
||||
onboot: no
|
||||
peerdns: no
|
||||
eth0:
|
||||
onboot: yes
|
||||
peerdns: no
|
||||
power_type: ssh
|
||||
power_user: root
|
||||
power_address: 10.20.0.78
|
||||
name_servers: 10.20.0.2
|
||||
name: controller-1
|
||||
hostname: controller-1.domain.tld
|
||||
power_pass: /root/.ssh/bootstrap.rsa
|
||||
netboot_enabled: 1
|
|
@ -55,19 +55,8 @@ module Astute
|
|||
end
|
||||
|
||||
def provision(reporter, engine_attrs, nodes)
|
||||
begin
|
||||
Astute.logger.info("Trying to instantiate cobbler engine: #{engine_attrs.inspect}")
|
||||
engine = Astute::Provision::Cobbler.new(engine_attrs)
|
||||
rescue
|
||||
Astute.logger.error("Error occured during cobbler initializing")
|
||||
|
||||
reporter.report({
|
||||
'status' => 'error',
|
||||
'error' => 'Cobbler can not be initialized',
|
||||
'progress' => 100
|
||||
})
|
||||
raise StopIteration
|
||||
end
|
||||
raise "Nodes to provision are not provided!" if nodes.empty?
|
||||
engine = create_engine(engine_attrs, reporter)
|
||||
|
||||
begin
|
||||
reboot_events = reboot_nodes(engine, nodes)
|
||||
|
@ -119,7 +108,7 @@ module Astute
|
|||
Timeout::timeout(Astute.config.PROVISIONING_TIMEOUT) do # Timeout for booting target OS
|
||||
while true
|
||||
time = Time::now.to_f
|
||||
types = self.node_type(reporter, task_id, nodes, 2)
|
||||
types = node_type(reporter, task_id, nodes, 2)
|
||||
types.each do |t|
|
||||
Astute.logger.debug("Got node types: uid=#{t['uid']} type=#{t['node_type']}")
|
||||
end
|
||||
|
@ -169,7 +158,7 @@ module Astute
|
|||
reporter.report({'nodes' => nodes_progress})
|
||||
|
||||
begin
|
||||
result = self.deploy(reporter, task_id, nodes, attrs)
|
||||
result = deploy(reporter, task_id, nodes, attrs)
|
||||
rescue Timeout::Error
|
||||
msg = "Timeout of deployment is exceeded."
|
||||
Astute.logger.error msg
|
||||
|
@ -199,6 +188,22 @@ module Astute
|
|||
reporter.report(status)
|
||||
end
|
||||
|
||||
def create_engine(engine_attrs, reporter)
|
||||
begin
|
||||
Astute.logger.info("Trying to instantiate cobbler engine: #{engine_attrs.inspect}")
|
||||
engine = Astute::Provision::Cobbler.new(engine_attrs)
|
||||
rescue
|
||||
Astute.logger.error("Error occured during cobbler initializing")
|
||||
|
||||
reporter.report({
|
||||
'status' => 'error',
|
||||
'error' => 'Cobbler can not be initialized',
|
||||
'progress' => 100
|
||||
})
|
||||
raise StopIteration
|
||||
end
|
||||
end
|
||||
|
||||
def reboot_nodes(engine, nodes)
|
||||
reboot_events = {}
|
||||
nodes.each do |node|
|
||||
|
|
|
@ -217,5 +217,142 @@ describe Astute::Orchestrator do
|
|||
end
|
||||
|
||||
it "remove_nodes do not fail if any of nodes failed"
|
||||
|
||||
describe '#provision' do
|
||||
|
||||
before(:all) do
|
||||
@data = {
|
||||
"engine"=>{
|
||||
"url"=>"http://localhost/cobbler_api",
|
||||
"username"=>"cobbler",
|
||||
"password"=>"cobbler"
|
||||
},
|
||||
"task_uuid"=>"a5c44b9a-285a-4a0c-ae65-2ed6b3d250f4",
|
||||
"nodes" => [
|
||||
{
|
||||
'profile' => 'centos-x86_64',
|
||||
"name"=>"controller-1",
|
||||
'power_type' => 'ssh',
|
||||
'power_user' => 'root',
|
||||
'power_pass' => '/root/.ssh/bootstrap.rsa',
|
||||
'power-address' => '1.2.3.5',
|
||||
'hostname' => 'name.domain.tld',
|
||||
'name_servers' => '1.2.3.4 1.2.3.100',
|
||||
'name_servers_search' => 'some.domain.tld domain.tld',
|
||||
'netboot_enabled' => '1',
|
||||
'ks_meta' => 'some_param=1 another_param=2',
|
||||
'interfaces' => {
|
||||
'eth0' => {
|
||||
'mac_address' => '00:00:00:00:00:00',
|
||||
'static' => '1',
|
||||
'netmask' => '255.255.255.0',
|
||||
'ip_address' => '1.2.3.5',
|
||||
'dns_name' => 'node.mirantis.net',
|
||||
},
|
||||
'eth1' => {
|
||||
'mac_address' => '00:00:00:00:00:01',
|
||||
'static' => '0',
|
||||
'netmask' => '255.255.255.0',
|
||||
'ip_address' => '1.2.3.6',
|
||||
}
|
||||
},
|
||||
'interfaces_extra' => {
|
||||
'eth0' => {
|
||||
'peerdns' => 'no',
|
||||
'onboot' => 'yes',
|
||||
},
|
||||
'eth1' => {
|
||||
'peerdns' => 'no',
|
||||
'onboot' => 'yes',
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}.freeze
|
||||
end
|
||||
|
||||
context 'cobler cases' do
|
||||
it "raise error if cobler settings empty" do
|
||||
expect {@orchestrator.provision(@reporter, {}, @data['nodes'])}.
|
||||
to raise_error(StopIteration)
|
||||
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.provision(@reporter, @data['engine'], {})}.
|
||||
to raise_error(/Nodes to provision are not provided!/)
|
||||
end
|
||||
|
||||
it "try to reboot nodes from list" do
|
||||
Astute::Provision::Cobbler.any_instance do
|
||||
expects(:power_reboot).with('controller-1')
|
||||
end
|
||||
@orchestrator.stubs(:check_reboot_nodes).returns([])
|
||||
@orchestrator.provision(@reporter, @data['engine'], @data['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'])}
|
||||
|
||||
it "does not find failed nodes" do
|
||||
Astute::Provision::Cobbler.any_instance.stubs(:event_status).
|
||||
returns([Time.now.to_f, 'controller-1', 'complete'])
|
||||
|
||||
@orchestrator.provision(@reporter, @data['engine'], @data['nodes'])
|
||||
end
|
||||
|
||||
it "report about success" do
|
||||
@reporter.expects(:report).with({'status' => 'ready', 'progress' => 100}).returns(true)
|
||||
@orchestrator.provision(@reporter, @data['engine'], @data['nodes'])
|
||||
end
|
||||
|
||||
it "sync engine state" do
|
||||
Astute::Provision::Cobbler.any_instance do
|
||||
expects(:sync).once
|
||||
end
|
||||
@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.provision(@reporter, @data['engine'], @data['nodes'])
|
||||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
it "raise error if failed node find" do
|
||||
expect {@orchestrator.provision(@reporter, @data['engine'], @data['nodes'])}.to raise_error(StopIteration)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue