cookbook-openstack-network/spec/server_spec.rb

656 lines
24 KiB
Ruby

# Encoding: utf-8
require_relative 'spec_helper'
describe 'openstack-network::server' do
describe 'ubuntu' do
let(:runner) { ChefSpec::Runner.new(UBUNTU_OPTS) }
let(:node) { runner.node }
let(:chef_run) do
node.set['openstack']['compute']['network']['service_type'] = 'neutron'
runner.converge(described_recipe)
end
include_context 'neutron-stubs'
it 'uses release db stamp' do
expect(chef_run).to run_bash('migrate network database').with_code(/stamp icehouse/)
end
it 'does not install neutron-server when nova networking' do
node.override['openstack']['compute']['network']['service_type'] = 'nova'
expect(chef_run).to_not upgrade_package 'neutron-server'
end
describe 'package and services' do
it 'upgrades neutron-server packages' do
expect(chef_run).to upgrade_package 'neutron-server'
end
it 'allows overriding package names' do
cust_pkgs = ['my-neutron', 'my-other-neutron']
node.set['openstack']['network']['platform']['neutron_server_packages'] = cust_pkgs
cust_pkgs.each do |pkg|
expect(chef_run).to upgrade_package(pkg)
end
end
it 'sets the neutron server service to start on boot' do
expect(chef_run).to enable_service 'neutron-server'
end
it 'starts the neutron server service' do
expect(chef_run).to start_service 'neutron-server'
end
it 'allows overriding service names' do
node.set['openstack']['network']['platform']['neutron_server_service'] = 'my-neutron-server'
expect(chef_run).to enable_service 'my-neutron-server'
end
it 'allows overriding package options' do
cust_opts = "-o Dpkg::Options::='--force-confold' -o Dpkg::Options::='--force-confdef' --force-yes"
node.set['openstack']['network']['platform']['package_overrides'] = cust_opts
expect(chef_run).to upgrade_package('neutron-server').with(options: cust_opts)
end
it 'does not upgrade openvswitch package or the agent' do
expect(chef_run).not_to upgrade_package 'openvswitch'
expect(chef_run).not_to upgrade_package 'neutron-plugin-openvswitch-agent'
expect(chef_run).not_to enable_service 'neutron-plugin-openvswitch-agent'
end
end
describe 'api-paste.ini' do
let(:file) { chef_run.template('/etc/neutron/api-paste.ini') }
it 'creates api-paste.ini' do
expect(chef_run).to create_template(file.name).with(
user: 'neutron',
group: 'neutron',
mode: 0640
)
end
end
describe 'neutron-ha-tool.py' do
let(:file) { chef_run.cookbook_file('/usr/local/bin/neutron-ha-tool.py') }
it 'should create neutron-ha-tool.py script' do
expect(chef_run).to create_cookbook_file(file.name)
end
end
describe 'neutron.conf' do
let(:file) { chef_run.template('/etc/neutron/neutron.conf') }
it 'creates neutron.conf' do
expect(chef_run).to create_template(file.name).with(
user: 'neutron',
group: 'neutron',
mode: 0644
)
end
it 'it sets rpc_thread_pool_size correctly' do
expect(chef_run).to render_file(file.name).with_content(
/^rpc_thread_pool_size = 64$/)
end
it 'it sets rpc_conn_pool_size correctly' do
expect(chef_run).to render_file(file.name).with_content(
/^rpc_conn_pool_size = 30$/)
end
it 'it sets rpc_response_timeout correctly' do
expect(chef_run).to render_file(file.name).with_content(
/^rpc_response_timeout = 60$/)
end
it 'it sets control_exchange correctly' do
expect(chef_run).to render_file(file.name).with_content(
/^control_exchange = neutron$/)
end
it 'has default amqp_* queue options set' do
[/^amqp_durable_queues=false$/,
/^amqp_auto_delete=false$/].each do |line|
expect(chef_run).to render_file(file.name).with_content(line)
end
end
it 'it sets agent_down_time correctly' do
expect(chef_run).to render_file(file.name).with_content(
'agent_down_time = 75')
end
it 'writes the quota driver properly' do
node.set['openstack']['network']['quota']['driver'] = 'my.quota.Driver'
expect(chef_run).to render_file(file.name).with_content(
'quota_driver = my.quota.Driver')
end
it 'it sets auth_strategy correctly' do
expect(chef_run).to render_file(file.name).with_content(
'auth_strategy = keystone')
end
it 'it sets state_path correctly' do
expect(chef_run).to render_file(file.name).with_content(
'state_path = /var/lib/neutron')
end
it 'it sets lock_path correctly' do
expect(chef_run).to render_file(file.name).with_content(
'lock_path = $state_path/lock')
end
it 'it sets log_dir correctly' do
expect(chef_run).to render_file(file.name).with_content(
'log_dir = /var/log/neutron')
end
it 'it sets agent report interval correctly' do
expect(chef_run).to render_file(file.name).with_content(
'report_interval = 30')
end
it 'it does not allow overlapping ips by default' do
expect(chef_run).to render_file(file.name).with_content(
/^allow_overlapping_ips = False$/)
end
it 'it has correct default scheduler classes' do
expect(chef_run).to render_file(file.name).with_content(
'network_scheduler_driver = neutron.scheduler.dhcp_agent_scheduler.ChanceScheduler')
expect(chef_run).to render_file(file.name).with_content(
'router_scheduler_driver = neutron.scheduler.l3_agent_scheduler.ChanceScheduler')
end
it 'has the overridable default quota values' do
expect(chef_run).to render_file(file.name).with_content(
/^quota_items = network,subnet,port/)
expect(chef_run).to render_file(file.name).with_content(
/^default_quota = -1/)
expect(chef_run).to render_file(file.name).with_content(
/^quota_network = 10/)
expect(chef_run).to render_file(file.name).with_content(
/^quota_subnet = 10/)
expect(chef_run).to render_file(file.name).with_content(
/^quota_port = 50/)
expect(chef_run).to render_file(file.name).with_content(
/^quota_security_group = 10/)
expect(chef_run).to render_file(file.name).with_content(
/^quota_security_group_rule = 100/)
end
it 'sets rpc_backend correctly' do
expect(chef_run).to render_file(file.name).with_content(
'rpc_backend=neutron.openstack.common.rpc.impl_kombu')
expect(chef_run).not_to render_file(file.name).with_content(
'rpc_backend=neutron.openstack.common.rpc.impl_qpid')
end
it 'it sets root_helper' do
expect(chef_run).to render_file(file.name).with_content(
'root_helper = "sudo neutron-rootwrap /etc/neutron/rootwrap.conf"')
end
it 'binds to appropriate api ip' do
expect(chef_run).to render_file(file.name).with_content(
'bind_host = 127.0.0.1')
end
it 'binds to appropriate api port' do
expect(chef_run).to render_file(file.name).with_content(
'bind_port = 9696')
end
it 'has rabbit_host' do
expect(chef_run).to render_file(file.name).with_content(
'rabbit_host=127.0.0.1')
end
it 'does not have rabbit_hosts' do
expect(chef_run).not_to render_file(file.name).with_content(
'rabbit_hosts=')
end
it 'does not have rabbit_ha_queues' do
expect(chef_run).not_to render_file(file.name).with_content(
'rabbit_ha_queues=')
end
it 'has rabbit_port' do
expect(chef_run).to render_file(file.name).with_content(
'rabbit_port=5672')
end
it 'has rabbit_userid' do
expect(chef_run).to render_file(file.name).with_content(
'rabbit_userid=guest')
end
it 'has rabbit_password' do
expect(chef_run).to render_file(file.name).with_content(
'rabbit_password=mq-pass')
end
it 'has rabbit_virtual_host' do
expect(chef_run).to render_file(file.name).with_content(
'rabbit_virtual_host=/')
end
it 'has default dhcp_lease_duration setting' do
expect(chef_run).to render_file(file.name).with_content(
'dhcp_lease_duration = 86400')
end
it 'has configurable dhcp_lease_duration setting' do
node.set['openstack']['network']['dhcp_lease_duration'] = 3600
expect(chef_run).to render_file(file.name).with_content(
'dhcp_lease_duration = 3600')
end
it 'does not set service_plugins when attribute is []' do
expect(chef_run).not_to render_file(file.name).with_content(
/^service_plugins =/)
end
it 'has default notification_driver setting' do
expect(chef_run).to render_file(file.name).with_content(
'notification_driver = neutron.openstack.common.notifier.rpc_notifier')
end
it 'has configurable notification_driver setting' do
driver = 'neutron.openstack.common.notifier.no_op_notifier'
node.set['openstack']['network']['notification_driver'] = driver
expect(chef_run).to render_file(file.name).with_content(
"notification_driver = #{driver}")
end
it 'has default notification_topics setting' do
expect(chef_run).to render_file(file.name).with_content(
'notification_topics = notifications')
end
it 'has configurable notification_topics setting' do
topics = 'notifications1,notifications2'
node.set['openstack']['mq']['network']['notification_topics'] = topics
expect(chef_run).to render_file(file.name).with_content(
"notification_topics = #{topics}")
end
it 'sets service_plugins' do
node.set['openstack']['network']['service_plugins'] = %w{
neutron.foo
neutron.bar
}
expect(chef_run).to render_file(file.name).with_content(
'service_plugins = neutron.foo,neutron.bar')
end
it 'has neutron pass' do
expect(chef_run).to render_file(file.name).with_content(
'admin_password = neutron-pass')
end
it 'has auth_uri' do
expect(chef_run).to render_file(file.name).with_content(
'auth_uri = http://127.0.0.1:5000/v2.0')
end
it 'has auth_host' do
expect(chef_run).to render_file(file.name).with_content(
'auth_host = 127.0.0.1')
end
it 'has auth_port' do
expect(chef_run).to render_file(file.name).with_content(
'auth_port = 35357')
end
it 'has auth_protocol' do
expect(chef_run).to render_file(file.name).with_content(
'auth_protocol = http')
end
it 'has signing_dir' do
expect(chef_run).to render_file(file.name).with_content(
'signing_dir = /var/lib/neutron/keystone-signing')
end
it 'has correct auth_version' do
expect(chef_run).not_to render_file(file.name).with_content(
'auth_version = v2.0')
end
describe 'qpid' do
before do
node.set['openstack']['mq']['network']['service_type'] = 'qpid'
node.set['openstack']['mq']['network']['qpid']['username'] = 'guest'
end
it 'sets rpc_backend correctly' do
expect(chef_run).to render_file(file.name).with_content(
'rpc_backend=neutron.openstack.common.rpc.impl_qpid')
expect(chef_run).not_to render_file(file.name).with_content(
'rpc_backend=neutron.openstack.common.rpc.impl_kombu')
end
it 'has qpid_hostname' do
expect(chef_run).to render_file(file.name).with_content(
'qpid_hostname=127.0.0.1')
end
it 'has qpid_port' do
expect(chef_run).to render_file(file.name).with_content(
'qpid_port=5672')
end
it 'has qpid_username' do
expect(chef_run).to render_file(file.name).with_content(
'qpid_username=guest')
end
it 'has qpid_password' do
expect(chef_run).to render_file(file.name).with_content(
'qpid_password=mq-pass')
end
it 'has qpid_sasl_mechanisms' do
expect(chef_run).to render_file(file.name).with_content(
'qpid_sasl_mechanisms=')
end
it 'has qpid_reconnect' do
expect(chef_run).to render_file(file.name).with_content(
'qpid_reconnect=true')
end
it 'has qpid_reconnect_timeout' do
expect(chef_run).to render_file(file.name).with_content(
'qpid_reconnect_timeout=0')
end
it 'has qpid_reconnect_limit' do
expect(chef_run).to render_file(file.name).with_content(
'qpid_reconnect_limit=0')
end
it 'has qpid_reconnect_interval_min' do
expect(chef_run).to render_file(file.name).with_content(
'qpid_reconnect_interval_min=0')
end
it 'has qpid_reconnect_interval_max' do
expect(chef_run).to render_file(file.name).with_content(
'qpid_reconnect_interval_max=0')
end
it 'has qpid_reconnect_interval' do
expect(chef_run).to render_file(file.name).with_content(
'qpid_reconnect_interval=0')
end
it 'has qpid_heartbeat' do
expect(chef_run).to render_file(file.name).with_content(
'qpid_heartbeat=60')
end
it 'has qpid_protocol' do
expect(chef_run).to render_file(file.name).with_content(
'qpid_protocol=tcp')
end
it 'has qpid_tcp_nodelay' do
expect(chef_run).to render_file(file.name).with_content(
'qpid_tcp_nodelay=true')
end
it 'has qpid_topology_version set' do
expect(chef_run).to render_file(file.name).with_content(
/^qpid_topology_version=1$/)
end
end
describe 'neutron.conf with rabbit ha' do
before do
node.set['openstack']['mq']['network']['rabbit']['ha'] = true
node.set['chef_client']['splay'] = 300
end
it 'has rabbit_hosts' do
expect(chef_run).to render_file(file.name).with_content(
'rabbit_hosts=1.1.1.1:5672,2.2.2.2:5672')
end
it 'has rabbit_ha_queues' do
expect(chef_run).to render_file(file.name).with_content(
'rabbit_ha_queues=True')
end
it 'does not have rabbit_host' do
expect(chef_run).not_to render_file(file.name).with_content(
'rabbit_host=127.0.0.1')
end
it 'does not have rabbit_port' do
expect(chef_run).not_to render_file(file.name).with_content(
'rabbit_port=5672')
end
end
it 'does not create sysconfig template' do
stub_command(/python/).and_return(true)
expect(chef_run).not_to create_file('/etc/sysconfig/neutron')
end
describe 'database' do
it 'has a correct sql_connection value' do
expect(chef_run).to render_file(file.name).with_content(
'mysql://neutron:neutron@127.0.0.1:3306/neutron')
end
it 'sets sqlalchemy attributes' do
expect(chef_run).to render_file(file.name).with_content(
'slave_connection =')
expect(chef_run).to render_file(file.name).with_content(
'max_retries = 10')
expect(chef_run).to render_file(file.name).with_content(
'retry_interval = 10')
expect(chef_run).to render_file(file.name).with_content(
'min_pool_size = 1')
expect(chef_run).to render_file(file.name).with_content(
'max_pool_size = 10')
expect(chef_run).to render_file(file.name).with_content(
'idle_timeout = 3600')
expect(chef_run).to render_file(file.name).with_content(
'max_overflow = 20')
expect(chef_run).to render_file(file.name).with_content(
'connection_debug = 0')
expect(chef_run).to render_file(file.name).with_content(
'connection_trace = false')
expect(chef_run).to render_file(file.name).with_content(
'pool_timeout = 10')
end
end
it 'sets service_provider attributes' do
node.set['openstack']['network']['service_provider'] = ['provider1', 'provider2']
expect(chef_run).to render_file(file.name).with_content(
'service_provider = provider1')
expect(chef_run).to render_file(file.name).with_content(
'service_provider = provider2')
end
it 'has the overridable default nova interaction values' do
expect(chef_run).to render_file(file.name).with_content(
'notify_nova_on_port_status_changes = True')
expect(chef_run).to render_file(file.name).with_content(
'notify_nova_on_port_data_changes = True')
expect(chef_run).to render_file(file.name).with_content(
'nova_url = http://127.0.0.1:8774/v2')
expect(chef_run).to render_file(file.name).with_content(
'nova_region_name = RegionOne')
expect(chef_run).to render_file(file.name).with_content(
'nova_admin_username = nova')
expect(chef_run).to render_file(file.name).with_content(
'nova_admin_tenant_id =')
expect(chef_run).to render_file(file.name).with_content(
'nova_admin_password = nova-pass')
expect(chef_run).to render_file(file.name).with_content(
'nova_admin_auth_url = http://127.0.0.1:35357/v2.0')
expect(chef_run).to render_file(file.name).with_content(
'send_events_interval = 2')
expect(chef_run).to run_ruby_block('query service tenant uuid')
end
describe 'query service tenant uuid' do
it 'has queried service tenant uuid for nova interactions' do
# run actual ruby_block resource
chef_run.find_resource(:ruby_block, 'query service tenant uuid').old_run_action(:create)
nova_tenant_id = chef_run.node['openstack']['network']['nova']['admin_tenant_id']
expect(nova_tenant_id).to eq('000-UUID-FROM-CLI')
expect(chef_run).to render_file(file.name).with_content(
'nova_admin_tenant_id = 000-UUID-FROM-CLI')
end
it 'has status changes for nova interactions disabled without id override' do
chef_run.node.set['openstack']['network']['nova']['notify_nova_on_port_status_changes'] = 'False'
# run actual ruby_block resource
chef_run.find_resource(:ruby_block, 'query service tenant uuid').old_run_action(:create)
nova_tenant_id = chef_run.node['openstack']['network']['nova']['admin_tenant_id']
expect(nova_tenant_id).to eq('000-UUID-FROM-CLI')
expect(chef_run).to render_file(file.name).with_content(
'nova_admin_tenant_id = 000-UUID-FROM-CLI')
end
it 'has data changes for nova interactions disabled without id override' do
chef_run.node.set['openstack']['network']['nova']['notify_nova_on_port_data_changes'] = 'False'
# run actual ruby_block resource
chef_run.find_resource(:ruby_block, 'query service tenant uuid').old_run_action(:create)
nova_tenant_id = chef_run.node['openstack']['network']['nova']['admin_tenant_id']
expect(nova_tenant_id).to eq('000-UUID-FROM-CLI')
expect(chef_run).to render_file(file.name).with_content(
'nova_admin_tenant_id = 000-UUID-FROM-CLI')
end
it 'has all changes for nova interactions disabled without id override' do
chef_run.node.set['openstack']['network']['nova']['notify_nova_on_port_status_changes'] = 'False'
chef_run.node.set['openstack']['network']['nova']['notify_nova_on_port_data_changes'] = 'False'
# run actual ruby_block resource
chef_run.find_resource(:ruby_block, 'query service tenant uuid').old_run_action(:create)
nova_tenant_id = chef_run.node['openstack']['network']['nova']['admin_tenant_id']
expect(nova_tenant_id).to eq(nil)
expect(chef_run).to render_file(file.name).with_content(
'nova_admin_tenant_id =')
end
it 'has status changes for nova interactions disabled with id override' do
chef_run.node.set['openstack']['network']['nova']['notify_nova_on_port_status_changes'] = 'False'
chef_run.node.set['openstack']['network']['nova']['admin_tenant_id'] = '111-UUID-OVERRIDE'
# run actual ruby_block resource
chef_run.find_resource(:ruby_block, 'query service tenant uuid').old_run_action(:create)
nova_tenant_id = chef_run.node['openstack']['network']['nova']['admin_tenant_id']
expect(nova_tenant_id).to eq('111-UUID-OVERRIDE')
expect(chef_run).to render_file(file.name).with_content(
'nova_admin_tenant_id = 111-UUID-OVERRIDE')
end
it 'has data changes for nova interactions disabled with id override' do
chef_run.node.set['openstack']['network']['nova']['notify_nova_on_port_data_changes'] = 'False'
chef_run.node.set['openstack']['network']['nova']['admin_tenant_id'] = '111-UUID-OVERRIDE'
# run actual ruby_block resource
chef_run.find_resource(:ruby_block, 'query service tenant uuid').old_run_action(:create)
nova_tenant_id = chef_run.node['openstack']['network']['nova']['admin_tenant_id']
expect(nova_tenant_id).to eq('111-UUID-OVERRIDE')
expect(chef_run).to render_file(file.name).with_content(
'nova_admin_tenant_id = 111-UUID-OVERRIDE')
end
it 'has all changes for nova interactions disabled with id override' do
chef_run.node.set['openstack']['network']['nova']['notify_nova_on_port_status_changes'] = 'False'
chef_run.node.set['openstack']['network']['nova']['notify_nova_on_port_data_changes'] = 'False'
chef_run.node.set['openstack']['network']['nova']['admin_tenant_id'] = '111-UUID-OVERRIDE'
# run actual ruby_block resource
chef_run.find_resource(:ruby_block, 'query service tenant uuid').old_run_action(:create)
nova_tenant_id = chef_run.node['openstack']['network']['nova']['admin_tenant_id']
expect(nova_tenant_id).to eq('111-UUID-OVERRIDE')
expect(chef_run).to render_file(file.name).with_content(
'nova_admin_tenant_id = 111-UUID-OVERRIDE')
end
it 'has overriden service tenant uuid for nova interactions' do
chef_run.node.set['openstack']['network']['nova']['admin_tenant_id'] = '111-UUID-OVERRIDE'
# run actual ruby_block resource
chef_run.find_resource(:ruby_block, 'query service tenant uuid').old_run_action(:create)
nova_tenant_id = chef_run.node['openstack']['network']['nova']['admin_tenant_id']
expect(nova_tenant_id).to eq('111-UUID-OVERRIDE')
expect(chef_run).to render_file(file.name).with_content(
'nova_admin_tenant_id = 111-UUID-OVERRIDE')
end
end
end
describe '/etc/default/neutron-server' do
let(:file) { chef_run.template('/etc/default/neutron-server') }
it 'creates /etc/default/neutron-server' do
expect(chef_run).to create_template(file.name).with(
user: 'root',
group: 'root',
mode: 0644
)
end
it 'has a correct plugin config path' do
expect(chef_run).to render_file(file.name).with_content(
'/etc/neutron/plugins/ml2/ml2_conf.ini')
end
end
describe '/etc/neutron/plugins/ml2/ml2_conf.ini' do
let(:file) { chef_run.template('/etc/neutron/plugins/ml2/ml2_conf.ini') }
before do
node.set['openstack']['network']['interface_driver'] = 'neutron.agent.linux.interface.Ml2InterfaceDriver'
end
it 'creates ml2_conf.ini' do
expect(chef_run).to create_template(file.name).with(
user: 'neutron',
group: 'neutron',
mode: 0644
)
end
[
/^type_drivers = local,flat,vlan,gre,vxlan$/,
/^tenant_network_types = local$/,
/^mechanism_drivers = openvswitch$/,
/^flat_networks = $/,
/^network_vlan_ranges = $/,
/^tunnel_id_ranges = $/,
/^vni_ranges = $/,
/^vxlan_group = $/,
/^enable_security_group = True$/
].each do |content|
it "has a #{content.source[1...-1]} line" do
expect(chef_run).to render_file(file.name).with_content(content)
end
end
end
end
end