openstack-chef-repo/Rakefile

244 lines
7.7 KiB
Ruby

current_dir = File.dirname(__FILE__)
client_opts = "--force-formatter --no-color -z --config #{current_dir}/.chef/knife.rb"
task default: ["test"]
desc "Default gate tests to run"
task :test => [:rubocop, :berks_vendor, :json_check]
def run_command(command)
if File.exist?('Gemfile.lock')
sh %(bundle exec #{command})
else
sh %(chef exec #{command})
end
end
task :destroy_all do
Rake::Task[:destroy_machines].invoke
run_command('rm -rf Gemfile.lock && rm -rf Berksfile.lock && rm -rf cookbooks/')
end
desc "Destroy machines"
task :destroy_machines do
run_command("chef-client #{client_opts} -o 'provisioning::destroy_all'")
end
desc "Vendor your cookbooks/"
task :berks_vendor do
run_command('berks vendor cookbooks')
end
desc "Create Chef Key"
task :create_key do
if not File.exist?('.chef/validator.pem')
require 'openssl'
File.binwrite('.chef/validator.pem', OpenSSL::PKey::RSA.new(2048).to_pem)
end
end
desc "All-in-One build"
task :allinone => :create_key do
run_command("chef-client #{client_opts} -o 'provisioning::vagrant_linux,provisioning::allinone'")
end
desc "Multi-Node build"
task :multi_node => :create_key do
run_command("chef-client #{client_opts} -o 'provisioning::vagrant_linux,provisioning::multi-node'")
end
desc "Blow everything away"
task clean: [:destroy_all]
# CI tasks
require 'rubocop/rake_task'
desc 'Run RuboCop'
RuboCop::RakeTask.new(:rubocop)
desc "Validate data bags, environments and roles"
task :json_check do
require 'json'
['data_bags/*', 'environments', 'roles'].each do |sub_dir|
Dir.glob(sub_dir + '/*.json') do |env_file|
puts "Checking #{env_file}"
JSON.parse(File.read(env_file))
end
end
end
# Helper for running various testing commands
def _run_commands(desc, commands, openstack=true)
puts "## Running #{desc}"
commands.each do |command, options|
options.each do |option|
if openstack
sh %(sudo bash -c '. /root/openrc && #{command} #{option}')
else
sh %(#{command} #{option})
end
end
end
puts "## Finished #{desc}"
end
# use the correct environment depending on platform
if File.exist?('/usr/bin/apt-get')
@platform = 'ubuntu16'
elsif File.exist?('/usr/bin/yum')
@platform = 'centos7'
end
# Helper for looking at the starting environment
def _run_env_queries # rubocop:disable Metrics/MethodLength
_run_commands('basic common env queries', {
'uname' => ['-a'],
'pwd' => [''],
'env' => ['']},
false
)
case @platform
when 'ubuntu16'
_run_commands('basic debian env queries', {
'ifconfig' => [''],
'cat' => ['/etc/apt/sources.list']},
false
)
when 'centos7'
_run_commands('basic rhel env queries', {
'/usr/sbin/ip' => ['addr'],
'cat' => ['/etc/yum.repos.d/*']},
false
)
end
end
# Helper for setting up basic query tests
def _run_basic_queries # rubocop:disable Metrics/MethodLength
_run_commands('basic common test queries', {
'curl' => ['-v http://localhost', '-kv https://localhost'],
'sudo netstat' => ['-nlp'],
'nova-manage' => ['version', 'db version'],
'nova' => %w(--version service-list hypervisor-list flavor-list),
'glance-manage' => %w(db_version),
'glance' => %w(--version image-list),
'keystone-manage' => %w(db_version),
'openstack' => ['--version', 'user list', 'endpoint list', 'role list', 'service list', 'project list'],
'cinder-manage' => ['version list', 'db version'],
'cinder' => %w(--version list),
'heat-manage' => ['db_version', 'service list'],
'heat' => %w(--version stack-list),
'neutron' => %w(agent-list ext-list net-list port-list subnet-list quota-list),
'ovs-vsctl' => %w(show) }
)
case @platform
when 'ubuntu16'
_run_commands('basic debian test queries', {
'rabbitmqctl' => %w(cluster_status),
'ifconfig' => ['']}
)
when 'centos7'
_run_commands('basic rhel test queries', {
'/usr/sbin/rabbitmqctl' => %w(cluster_status),
'/usr/sbin/ip' => ['addr']}
)
end
end
# Helper for setting up basic ceilometer tests
def _run_ceilometer_tests(pass) # rubocop:disable Metrics/MethodLength
_run_commands('ceilometer api query', {
'ceilometer' => ['meter-list', 'resource-list', 'sample-list']
}
)
end
# Helper for setting up basic nova tests
def _run_nova_tests(pass) # rubocop:disable Metrics/MethodLength
_run_commands('cinder storage volume create', {
'openstack' => ['volume list', "volume create --description test_volume_#{pass} --size 1 test_volume_#{pass}"],
'sleep' => ['10'] }
)
_run_commands('cinder storage volume query', {
'openstack' => ['volume list'] }
)
uuid = `sudo bash -c ". /root/openrc && openstack volume show --format yaml test_volume_#{pass} | grep "^id:" | cut -d ':' -f 2"`
_run_commands('nova server create', {
'openstack' => ['server list', "server create --image cirros --flavor m1.nano --block-device-mapping vdb=#{uuid.strip}:::1 test#{pass}"],
'sleep' => ['40'] }
)
_run_commands('nova server cleanup', {
'openstack' => ['server list', "server show test#{pass}", "server delete test#{pass}"],
'sleep' => ['25']}
)
_run_commands('nova server query', {
'openstack' => ['volume list', 'server list'] }
)
end
# Helper for setting up neutron local network
# due to https://bugs.launchpad.net/nova/+bug/1616240
# we temporarily need to install/update oslo-privsep explicitly for ubuntu
def _setup_local_network # rubocop:disable Metrics/MethodLength
case @platform
when 'ubuntu16'
_run_commands('install oslo.privsep for ubuntu', {
'sudo pip' => ['install oslo-privsep'],
'sudo systemctl' => ['restart neutron-*', 'restart nova-*']},
)
end
_run_commands('neutron local network setup', {
'openstack' => ['network create --share local_net', 'subnet create --network local_net --subnet-range 192.168.180.0/24 local_subnet'] }
)
end
# Helper for setting up tempest and upload the default cirros image. Tempest
# itself is not yet used for integration tests.
def _setup_tempest(client_opts)
sh %(sudo chef-client #{client_opts} -E allinone-#{@platform} -r 'recipe[openstack-integration-test::setup]')
end
def _save_logs(prefix, log_dir)
sh %(sleep 25)
%w(nova neutron keystone cinder glance heat apache2 rabbitmq mysql-default openvswitch mariadb ceilometer).each do |project|
sh %(mkdir -p #{log_dir}/#{prefix}/#{project})
sh %(sudo cp -rL /etc/#{project} #{log_dir}/#{prefix}/#{project}/etc || true)
sh %(sudo cp -rL /var/log/#{project} #{log_dir}/#{prefix}/#{project}/log || true)
end
end
desc "Integration test on Infra"
task :integration => [:create_key, :berks_vendor] do
log_dir = ENV['WORKSPACE']+'/logs'
# This is a workaround for allowing chef-client to run in local mode
sh %(sudo mkdir -p /etc/chef && sudo cp .chef/encrypted_data_bag_secret /etc/chef/openstack_data_bag_secret)
_run_env_queries
# Three passes to make sure of cookbooks idempotency
for i in 1..3
begin
puts "####### Pass #{i}"
# Kick off chef client in local mode, will converge OpenStack right on the gate job "in place"
sh %(sudo chef-client #{client_opts} -E allinone-#{@platform} -r 'role[allinone]')
if i == 1
_setup_tempest(client_opts)
_setup_local_network
end
_run_basic_queries
_run_nova_tests(i)
_run_ceilometer_tests(i)
rescue => e
raise "####### Pass #{i} failed with #{e.message}"
ensure
# make sure logs are saved, pass or fail
_save_logs("pass#{i}", log_dir)
sh %(sudo chown -R $USER #{log_dir}/pass#{i})
sh %(sudo chmod -R go+rx #{log_dir}/pass#{i})
end
end
# Run the tempest formal tests, setup with the openstack-integration-test cookbook
Dir.chdir('/opt/tempest') do
sh %(sudo -H /opt/tempest-venv/tempest.sh)
end
end