fuel-library/tests/noop/spec/hosts/roles/compute_spec.rb

520 lines
18 KiB
Ruby

# ROLE: compute
require 'spec_helper'
require 'shared-examples'
manifest = 'roles/compute.pp'
describe manifest do
before(:each) do
Noop.puppet_function_load :is_pkg_installed
MockFunction.new(:is_pkg_installed) do |function|
allow(function).to receive(:call).and_return false
end
end
shared_examples 'catalog' do
kombu_compression = Noop.hiera 'kombu_compression', ''
ironic_enabled = Noop.hiera_structure 'ironic/enabled'
let(:facts) {
Noop.ubuntu_facts.merge({
:libvirt_uuid => '0251bf3e0a3f48da8cdf8daad5473a7f',
:allocated_hugepages => '{"1G":true,"2M":true}',
})
}
let (:memcached_servers) { Noop.hiera 'memcached_servers' }
let(:nova_hash) do
Noop.hiera_structure 'nova'
end
let(:compute_hash) do
Noop.hiera_hash 'compute', {}
end
let(:storage_hash) do
Noop.hiera_structure 'storage'
end
let(:rhost_mem) do
{ 'reserved_host_memory' => [[Float(facts[:memorysize_mb]).floor * 0.2, 512].max, 1536].min }
end
let(:network_scheme) do
Noop.hiera_hash('network_scheme', {})
end
let(:prepare) do
Noop.puppet_function('prepare_network_config', network_scheme)
end
let(:nic_passthrough_whitelist) do
prepare
Noop.puppet_function('get_nic_passthrough_whitelist', 'sriov')
end
let(:nova_report_interval) { Noop.hiera 'nova_report_interval', '60' }
let(:nova_service_down_time) { Noop.hiera 'nova_service_down_time', '180' }
let(:verbose) { Noop.puppet_function 'pick', compute_hash['verbose'], 'true' }
let(:global_debug) { Noop.hiera 'debug', 'true' }
let(:debug) { Noop.puppet_function 'pick', compute_hash['debug'], global_debug }
let(:config_drive_format) { Noop.puppet_function 'pick', compute_hash['config_drive_format'], 'vfat' }
let(:log_facility) { Noop.hiera 'syslog_log_facility_nova', 'LOG_LOCAL6' }
let(:use_cache) { Noop.puppet_function 'pick', nova_hash['use_cache'], true }
let(:region_name) { Noop.hiera 'region', 'RegionOne' }
# Legacy openstack-compute tests
if ironic_enabled
compute_driver = 'ironic.IronicDriver'
else
compute_driver = 'libvirt.LibvirtDriver'
end
it 'should configure region name in cinder section' do
should contain_nova_config('cinder/os_region_name').with_value(region_name)
end
it 'should explicitly disable libvirt_inject_partition for compute node' do
libvirt_inject_partition = '-2'
should contain_class('nova::compute::libvirt').with(
'libvirt_inject_partition' => libvirt_inject_partition,
)
end
it 'should force instances to have config drives' do
should contain_class('nova::compute').with(
'force_config_drive' => true
)
end
it 'should enable migration support for libvirt with vncserver listen on 0.0.0.0' do
should contain_class('nova::compute::libvirt').with('vncserver_listen' => '0.0.0.0')
should contain_class('nova::migration::libvirt')
end
it 'nova config should have proper compute_driver' do
should contain_nova_config('DEFAULT/compute_driver').with(:value => 'libvirt.LibvirtDriver')
end
it 'should declare class nova::compute with neutron_enabled set to true' do
should contain_class('nova::compute').with(
'neutron_enabled' => true,
)
end
# Libvirtd.conf
it 'should configure listen_tls in libvirtd.conf' do
should contain_file_line('/etc/libvirt/libvirtd.conf listen_tls').with(
'path' => '/etc/libvirt/libvirtd.conf',
'line' => 'listen_tls = 0',
'match' => 'listen_tls =',
)
end
it 'should configure listen_tcp in libvirtd.conf' do
should contain_file_line('/etc/libvirt/libvirtd.conf listen_tcp').with(
'path' => '/etc/libvirt/libvirtd.conf',
'line' => 'listen_tcp = 1',
'match' => 'listen_tcp =',
)
end
it 'should configure auth_tcp in libvirtd.conf' do
should contain_file_line('/etc/libvirt/libvirtd.conf auth_tcp').with(
'path' => '/etc/libvirt/libvirtd.conf',
'line' => 'auth_tcp = "none"',
'match' => 'auth_tcp =',
)
end
it 'should configure libvirt host_uuid' do
host_uuid = facts[:libvirt_uuid]
should contain_augeas('libvirt-conf-uuid').with(
'context' => '/files/etc/libvirt/libvirtd.conf',
'changes' => "set host_uuid #{host_uuid}"
).that_notifies('Service[libvirt]')
end
it 'should install qemu-kvm package' do
should contain_package('qemu-kvm').with('ensure' => 'present')
end
enable_dpdk = Noop.hiera_structure 'dpdk/enabled', false
if enable_dpdk
network_device_mtu = false
else
network_device_mtu = 65000
end
it 'should configure network_device_mtu for nova-compute' do
should contain_class('nova::compute').with(
'network_device_mtu' => network_device_mtu
)
end
let(:node_hash) { Noop.hiera_hash 'node' }
let(:enable_hugepages) { node_hash.fetch('nova_hugepages_enabled', false) }
let(:enable_cpu_pinning) { node_hash.fetch('nova_cpu_pinning_enabled', false) }
let(:allocated_hugepages) { Noop.puppet_function 'parsejson', facts[:allocated_hugepages] }
let(:use_1g_huge_pages) { allocated_hugepages['1G'] }
let(:use_2m_huge_pages) { allocated_hugepages['2M'] }
it 'should configure vcpu_pin_set for nova' do
if enable_cpu_pinning
vcpu_pin_set = Noop.hiera_structure 'nova/cpu_pinning', false
should contain_class('nova::compute').with(
'vcpu_pin_set' => vcpu_pin_set
)
end
end
it 'should set up huge pages support for qemu-kvm' do
if enable_hugepages
if use_1g_huge_pages
hugepages_1g_opts_ensure = 'present'
should contain_file('/mnt/hugepages_1GB').with(
'ensure' => 'directory',
'owner' => 'root',
'group' => 'kvm',
'require' => 'Package[qemu-kvm]',
)
should contain_exec('mount_hugetlbfs_1g').with(
'command' => 'mount -t hugetlbfs hugetlbfs-kvm -o mode=775,gid=kvm,pagesize=1GB /mnt/hugepages_1GB',
'unless' => 'grep -q /mnt/hugepages_1GB /proc/mounts',
'path' => '/usr/sbin:/usr/bin:/sbin:/bin',
'require' => 'File[/mnt/hugepages_1GB]',
)
if use_2m_huge_pages
libvirt_hugetlbfs_mount = 'hugetlbfs_mount = ["/run/hugepages/kvm", "/mnt/hugepages_1GB"]'
qemu_hugepages_value = 'set KVM_HUGEPAGES 1'
else
libvirt_hugetlbfs_mount = 'hugetlbfs_mount = "/mnt/hugepages_1GB"'
qemu_hugepages_value = 'rm KVM_HUGEPAGES'
end
else
qemu_hugepages_value = 'set KVM_HUGEPAGES 1'
libvirt_hugetlbfs_mount = 'hugetlbfs_mount = "/run/hugepages/kvm"'
hugepages_1g_opts_ensure = 'absent'
end
else
qemu_hugepages_value = 'rm KVM_HUGEPAGES'
libvirt_hugetlbfs_mount = 'hugetlbfs_mount = ""'
hugepages_1g_opts_ensure = 'absent'
end
if facts[:osfamily] == 'Debian'
should contain_augeas('qemu_hugepages').with(
'context' => '/files/etc/default/qemu-kvm',
'changes' => qemu_hugepages_value,
).that_notifies('Service[libvirt]')
should contain_file_line('libvirt_hugetlbfs_mount').with(
'path' => '/etc/libvirt/qemu.conf',
'line' => libvirt_hugetlbfs_mount,
'match' => '^hugetlbfs_mount =.*$',
'require' => 'Package[libvirt-bin]',
).that_notifies('Service[libvirt]')
should contain_file_line('libvirt_1g_hugepages_apparmor').with(
'path' => '/etc/apparmor.d/abstractions/libvirt-qemu',
'after' => 'owner "/run/hugepages/kvm/libvirt/qemu/',
'line' => ' owner "/mnt/hugepages_1GB/libvirt/qemu/**" rw,',
'require' => 'Package[libvirt-bin]',
'ensure' => hugepages_1g_opts_ensure,
).that_notifies('Exec[refresh_apparmor]')
should contain_file_line('1g_hugepages_fstab').with(
'path' => '/etc/fstab',
'line' => 'hugetlbfs-kvm /mnt/hugepages_1GB hugetlbfs mode=775,gid=kvm,pagesize=1GB 0 0',
'ensure' => hugepages_1g_opts_ensure,
)
should contain_augeas('qemu_hugepages').that_notifies('Service[qemu-kvm]')
should contain_service('qemu-kvm').that_comes_before('Service[libvirt]')
end
end
# libvirt/qemu with(out) selinux/apparmor
it 'libvirt/qemu config should have proper security_driver and apparmor configuration' do
if facts[:osfamily] == 'RedHat'
should contain_file_line('qemu_selinux').with(
'path' => '/etc/libvirt/qemu.conf',
'line' => 'security_driver = "selinux"',
).that_notifies('Service[libvirt]')
elsif facts[:osfamily] == 'Debian'
should contain_file_line('qemu_apparmor').with(
'path' => '/etc/libvirt/qemu.conf',
'line' => 'security_driver = "apparmor"',
).that_notifies('Service[libvirt]')
should contain_file_line('apparmor_libvirtd').with(
'path' => '/etc/apparmor.d/usr.sbin.libvirtd',
'line' => "# unix, # shouldn't be used for libvirt/qemu",
)
should contain_exec('refresh_apparmor').that_subscribes_to('File_line[apparmor_libvirtd]')
end
end
libvirt_type = Noop.hiera 'libvirt_type', nil
it 'should manage libvirt-services under Ubuntu UCA' do
if facts[:os_package_type] == 'ubuntu'
should contain_service('virtlogd').that_comes_before('Service[libvirt]')
should contain_service('virtlockd').that_comes_before('Service[libvirt]')
end
end
it 'should set permissions for /dev/kvm under Ubuntu' do
if facts[:operatingsystem] == 'Ubuntu' and libvirt_type == 'kvm'
should contain_file('/dev/kvm').with(
:ensure => 'present',
:group => 'kvm',
:mode => '0660',
)
should contain_service('qemu-kvm').that_comes_before('File[/dev/kvm]')
end
end
# Nova.config options
it 'nova config should have proper live_migration_flag' do
should contain_nova_config('libvirt/live_migration_flag').with(
'value' => 'VIR_MIGRATE_UNDEFINE_SOURCE,VIR_MIGRATE_PEER2PEER,VIR_MIGRATE_LIVE,VIR_MIGRATE_PERSIST_DEST',
)
end
it 'nova config should have proper block_migration_flag' do
should contain_nova_config('libvirt/block_migration_flag').with(
'value' => 'VIR_MIGRATE_UNDEFINE_SOURCE,VIR_MIGRATE_PEER2PEER,VIR_MIGRATE_LIVE,VIR_MIGRATE_NON_SHARED_INC',
)
end
it 'nova config should have proper catalog_info' do
should contain_nova_config('cinder/catalog_info').with(
'value' => 'volumev2:cinderv2:internalURL'
)
end
it 'nova config should have proper use_syslog_rfc_format' do
should contain_nova_config('DEFAULT/use_syslog_rfc_format').with(
'value' => 'true',
)
end
it 'nova config should have proper connection_type' do
should contain_nova_config('DEFAULT/connection_type').with(
'value' => 'libvirt',
)
end
it 'nova config should have proper allow_resize_to_same_host' do
should contain_nova_config('DEFAULT/allow_resize_to_same_host').with(
'value' => 'true',
)
end
it 'nova config should have report_interval' do
should contain_nova_config('DEFAULT/report_interval').with(
'value' => nova_report_interval,
)
end
it 'nova config should have service_down_time' do
should contain_nova_config('DEFAULT/service_down_time').with(
'value' => nova_service_down_time,
)
end
it 'nova config should have use_stderr set to false' do
should contain_nova_config('DEFAULT/use_stderr').with(
'value' => 'false',
)
end
it 'nova config should contain right memcached servers list' do
should contain_class('nova').with(
:memcached_servers => memcached_servers
)
end
it 'should include memcache when use_cache is enabled' do
if use_cache
should contain_package('python-memcache')
else
should_not contain_package('python-memcache')
end
end
it 'should configure nova cache correctly' do
should contain_class('nova::cache').with(
:enabled => use_cache,
:backend => 'oslo_cache.memcache_pool',
:memcache_servers => memcached_servers,
)
end
it 'should install fping for nova API extension' do
should contain_package('fping').with('ensure' => 'present')
end
it 'nova config should have config_drive_format set to vfat' do
should contain_nova_config('DEFAULT/config_drive_format').with(
'value' => config_drive_format
)
end
it 'nova config should not have database connection' do
should_not contain_nova_config('database/connection')
end
# SSL support
management_vip = Noop.hiera('management_vip')
vncproxy_protocol = 'https'
ssl_hash = Noop.hiera_hash 'use_ssl', {}
let(:glance_endpoint_default) { Noop.hiera 'glance_endpoint', management_vip }
let(:glance_protocol) { Noop.puppet_function 'get_ssl_property',ssl_hash,{},'glance','internal','protocol','http' }
let(:glance_endpoint) { Noop.puppet_function 'get_ssl_property',ssl_hash,{},'glance','internal','hostname', glance_endpoint_default}
let(:glance_api_servers) { Noop.hiera 'glance_api_servers', "#{glance_protocol}://#{glance_endpoint}:9292" }
if !ssl_hash.empty?
vncproxy_host = Noop.hiera_structure('use_ssl/nova_public_hostname')
elsif Noop.hiera_structure('public_ssl/services')
vncproxy_host = Noop.hiera_structure('public_ssl/hostname')
else
vncproxy_host = Noop.hiera('public_vip')
vncproxy_protocol = 'http'
end
let(:vncproxy_port) { Noop.puppet_function 'pick', nova_hash['vncproxy_port'], '6080' }
it 'should properly configure vncproxy with (non-)ssl' do
should contain_class('nova::compute').with(
'vncproxy_protocol' => vncproxy_protocol,
'vncproxy_host' => vncproxy_host,
'vncproxy_port' => vncproxy_port,
)
end
it 'should properly configure glance api servers with (non-)ssl' do
should contain_class('nova').with(
'glance_api_servers' => glance_api_servers
)
end
enable_sriov = Noop.hiera_structure 'quantum_settings/supported_pci_vendor_devs', false
it 'should pass pci_passthrough_whitelist to nova::compute' , :if => enable_sriov do
pci_passthrough_json = Noop.puppet_function 'nic_whitelist_to_json', nic_passthrough_whitelist
should contain_class('nova::compute').with('pci_passthrough' => pci_passthrough_json)
end
it 'should configure logging when debug is enabled' do
if debug
default_log_levels = {
'oslo.messaging' => 'DEBUG',
}
should contain_class('nova::logging').with(
'default_log_levels' => default_log_levels,
)
end
end
# Check out nova config params
it 'should properly configure nova' do
node_name = Noop.hiera('node_name')
network_metadata = Noop.hiera_hash('network_metadata')
roles = network_metadata['nodes'][node_name]['node_roles']
if roles.include? 'ceph-osd'
nova_compute_rhostmem = rhost_mem['reserved_host_memory']
else
rhost_mem['reserved_host_memory'] = :undef
nova_compute_rhostmem = 512 # default
end
should contain_class('nova::compute').with(
'reserved_host_memory' => nova_compute_rhostmem
)
end
let(:default_availability_zone) { Noop.puppet_function 'pick', nova_hash['default_availability_zone'], facts[:os_service_default] }
let(:default_schedule_zone) { Noop.puppet_function 'pick', nova_hash['default_schedule_zone'], facts[:os_service_default] }
it 'should configure availability zones' do
should contain_class('nova::availability_zone').with(
'default_availability_zone' => default_availability_zone,
'default_schedule_zone' => default_schedule_zone,
)
end
it 'configures with the default params' do
should contain_class('nova').with(
'verbose' => verbose,
'debug' => debug,
'log_facility' => log_facility,
'state_path' => nova_hash['state_path'],
'notify_on_state_change' => 'vm_and_task_state',
)
should contain_class('nova::compute').with(
'enabled' => 'false',
'instance_usage_audit' => 'true',
'instance_usage_audit_period' => 'hour',
'config_drive_format' => 'vfat'
)
min_age = Noop.puppet_function 'pick', nova_hash['remove_unused_original_minimum_age_seconds'], '86400'
should contain_class('nova::compute::libvirt').with(
'libvirt_virt_type' => libvirt_type,
'vncserver_listen' => '0.0.0.0',
'remove_unused_original_minimum_age_seconds' => min_age,
)
end
it 'should contain migration basics' do
should contain_class('nova::client')
should contain_install_ssh_keys('nova_ssh_key_for_migration')
should contain_file('/var/lib/nova/.ssh/config')
end
it 'should contain cpufrequtils' do
if facts[:operatingsystem] == 'Ubuntu'
should contain_package('cpufrequtils').with(
'ensure' => 'present'
)
should contain_file('/etc/default/cpufrequtils').with(
'content' => "GOVERNOR=\"performance\"\n",
'require' => 'Package[cpufrequtils]',
'notify' => 'Service[cpufrequtils]',
)
should contain_service('cpufrequtils').with(
'ensure' => 'running',
'enable' => 'true',
'status' => '/bin/true',
)
end
end
if ['gzip', 'bz2'].include?(kombu_compression)
it 'should configure kombu compression' do
should contain_nova_config('oslo_messaging_rabbit/kombu_compression').with(:value => kombu_compression)
end
end
it 'should enable RabbitMQ heartbeats' do
should contain_nova_config('oslo_messaging_rabbit/heartbeat_timeout_threshold').with(:value => '<SERVICE DEFAULT>')
end
end
it 'should contain ssh and multipath packages' do
if facts[:osfamily] == 'Debian'
packages = ['openssh-client', 'multipath-tools']
elsif facts[:osfamily] == 'RedHat'
packages = ['openssh-clients', 'device-mapper-multipath']
end
packages.each do |p|
should contain_package(p)
end
end
test_ubuntu_and_centos manifest
end