# Encoding: utf-8 require_relative 'spec_helper' shared_examples 'core plugin common configurator' do |plugin_name, file_name, attrs| describe "#{plugin_name} config file" do let(:cfg_file) { chef_run.template("/etc/neutron/plugins/#{plugin_name}/#{file_name}") } before do node.set['openstack']['network']['core_plugin'] = plugin_name end it 'creates the file' do expect(chef_run).to create_template(cfg_file.name).with( user: 'neutron', group: 'neutron', mode: 0644 ) end context 'template contents' do it_behaves_like 'custom template banner displayer' do let(:file_name) { cfg_file.name } end attrs.each do |attr, default_value| it "sets the default #{attr} value" do expect(chef_run).to render_file(cfg_file.name).with_content(/^#{attr} = #{default_value}$/) end it "sets the #{attr} attribute" do node.set['openstack']['network'][plugin_name][attr] = "#{attr}_value" expect(chef_run).to render_file(cfg_file.name).with_content(/^#{attr} = #{attr}_value$/) end end end end end describe 'openstack-network' do describe 'ubuntu' do let(:runner) { ChefSpec::SoloRunner.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 'includes openstack-identity::client' do expect(chef_run).to include_recipe('openstack-identity::client') end context 'plugins' do before do PLUGIN_MAP.each do |key, _value| node.set['openstack']['network']['core_plugin_map'][key] = key end end it_behaves_like 'core plugin common configurator', 'bigswitch', PLUGIN_MAP['bigswitch'], servers: 'localhost:8080' it_behaves_like 'core plugin common configurator', 'brocade', PLUGIN_MAP['brocade'], physical_interface_mappings: '' describe 'ml2' do let(:file) { chef_run.template('/etc/neutron/plugins/ml2/ml2_conf.ini') } it_behaves_like 'core plugin common configurator', 'ml2', PLUGIN_MAP['ml2'], 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', enable_ipset: 'True' it 'sets related attributes for openvswitch section' do [ /^tenant_network_type = local$/, /^enable_tunneling = False$/, /^tunnel_type = $/, /^integration_bridge = br-int$/, /^tunnel_bridge = br-tun$/, /^local_ip = 127.0.0.1$/ ].each do |line| expect(chef_run).to render_config_file(file.name).with_section_content('OVS', line) end end it 'sets related attributes for agent section' do [ /^polling_interval = 2$/, /^tunnel_types = $/, /^veth_mtu = 1500$/, /^l2_population = False$/, /^enable_distributed_routing = False$/ ].each do |line| expect(chef_run).to render_config_file(file.name).with_section_content('agent', line) end end it 'sets related attributes for securitygroup section' do [ /^firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver$/, /^enable_security_group = True$/ ].each do |line| expect(chef_run).to render_config_file(file.name).with_section_content('securitygroup', line) end end end describe 'cisco' do let(:nexus_switch_value) do { 'ip0' => { 'hosts' => ['host_info00', 'host_info01'], 'ssh_port' => 'ssh_port0', 'username' => 'username0', 'password' => 'password0' }, 'ip1' => { 'hosts' => ['host_info10', 'host_info11'], 'ssh_port' => 'ssh_port1', 'username' => 'username1', 'password' => 'password1' } } end let(:file) { chef_run.template('/etc/neutron/plugins/cisco/cisco_plugins.ini') } before do node.set['openstack']['network']['cisco']['nexus_switch'] = nexus_switch_value node.set['openstack']['network']['core_plugin'] = 'cisco' end it_behaves_like 'core plugin common configurator', 'cisco', PLUGIN_MAP['cisco'], nexus_plugin: 'neutron.plugins.cisco.nexus.cisco_nexus_plugin_v2.NexusPlugin', vswitch_plugin: 'neutron.plugins.openvswitch.ovs_neutron_plugin.OVSNeutronPluginV2', vlan_start: '100', vlan_end: '3000', vlan_name_prefix: 'q-', max_ports: '100', max_port_profiles: '65568', max_networks: '65568', model_class: 'neutron.plugins.cisco.models.virt_phy_sw_v2.VirtualPhysicalSwitchModelV2', manager_class: 'neutron.plugins.cisco.segmentation.l2network_vlan_mgr_v2.L2NetworkVLANMgr', nexus_driver: 'neutron.plugins.cisco.tests.unit.v2.nexus.fake_nexus_driver.CiscoNEXUSFakeDriver' context 'nexus_switch' do it 'shows the ip' do nexus_switch_value.each do |ip, _info| expect(chef_run).to render_file(file.name).with_content(/^\[NEXUS_SWITCH:#{ip}\]$/) end end it 'shows the host_info' do nexus_switch_value.each do |_ip, info| info['hosts'].each do |host_info| expect(chef_run).to render_file(file.name).with_content(/^#{host_info[0]} = #{host_info[1]}$/) end end end %w(ssh_port username password).each do |attr| it "shows the #{attr}" do nexus_switch_value.each do |_ip, info| expect(chef_run).to render_file(file.name).with_content(/^#{attr} = #{info[attr]}$/) end end end end end it_behaves_like 'core plugin common configurator', 'hyperv', PLUGIN_MAP['hyperv'], tenant_network_type: 'local', network_vlan_ranges: '', polling_interval: '2', physical_network_vswitch_mappings: '\*\:external', firewall_driver: 'neutron.plugins.hyperv.agent.security_groups_driver.HyperVSecurityGroupsDriver' describe 'linuxbridge' do let(:file) { chef_run.template('/etc/neutron/plugins/linuxbridge/linuxbridge_conf.ini') } before do node.set['openstack']['network']['core_plugin'] = 'linuxbridge' end it_behaves_like 'core plugin common configurator', 'linuxbridge', PLUGIN_MAP['linuxbridge'], tenant_network_type: 'local', network_vlan_ranges: '', physical_interface_mappings: '', enable_vxlan: 'false', ttl: '', tos: '', vxlan_group: '224.0.0.1', l2_population: 'false', polling_interval: '2', rpc_support_old_agents: 'false', firewall_driver: 'neutron.agent.firewall.NoopFirewallDriver', enable_security_group: 'True' it 'sets the local_ip' do expect(chef_run).to render_file(file.name).with_content(/^local_ip = 127.0.0.1$/) end end it_behaves_like 'core plugin common configurator', 'metaplugin', PLUGIN_MAP['metaplugin'], plugin_list: 'openvswitch:neutron.plugins.openvswitch.ovs_neutron_plugin.OVSNeutronPluginV2,linuxbridge:neutron.plugins.linuxbridge.lb_neutron_plugin.LinuxBridgePluginV2', l3_plugin_list: 'openvswitch:neutron.plugins.openvswitch.ovs_neutron_plugin.OVSNeutronPluginV2,linuxbridge:neutron.plugins.linuxbridge.lb_neutron_plugin.LinuxBridgePluginV2', default_flavor: 'openvswitch', default_l3_flavor: 'openvswitch' it_behaves_like 'core plugin common configurator', 'midonet', PLUGIN_MAP['midonet'], midonet_uri: 'http://localhost:8080/midonet-api', username: 'admin', password: 'passw0rd', project_id: '77777777-7777-7777-7777-777777777777', provider_router_id: '00112233-0011-0011-0011-001122334455', metadata_router_id: 'ffeeddcc-ffee-ffee-ffee-ffeeddccbbaa' describe 'nec' do let(:file) { chef_run.template('/etc/neutron/plugins/nec/nec.ini') } before do node.set['openstack']['network']['core_plugin'] = 'nec' end it_behaves_like 'core plugin common configurator', 'nec', PLUGIN_MAP['nec'], integration_bridge: 'br-int', polling_interval: '2', firewall_driver: 'neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver' context 'OpenFlow Controller settings' do { host: '127.0.0.1', port: '8888', driver: 'trema', enable_packet_filter: 'true' }.each do |attr, value| it "sets the default #{attr} ofc value" do expect(chef_run).to render_file(file.name).with_content(/^#{attr} = #{value}$/) end it "sets the #{attr} ofc attribute" do node.set['openstack']['network']['nec']["ofc_#{attr}"] = "ofc_#{attr}_value" expect(chef_run).to render_file(file.name).with_content(/^#{attr} = ofc_#{attr}_value$/) end end end end describe 'nicira' do let(:file) { chef_run.template('/etc/neutron/plugins/nicira/nvp.ini') } before do node.set['openstack']['network']['core_plugin'] = 'nicira' end it_behaves_like 'core plugin common configurator', 'nicira', PLUGIN_MAP['nicira'], nvp_user: 'admin', nvp_password: 'admin', req_timeout: '30', http_timeout: '10', retries: '2', redirects: '2', nvp_controllers: 'xx.yy.zz.ww:443, aa.bb.cc.dd, ee.ff.gg.hh.ee:80', default_tz_uuid: '1e8e52cf-fa7f-46b0-a14a-f99835a9cb53', nvp_cluster_uuid: '615be8e4-82e9-4fd2-b4b3-fd141e51a5a7', default_iface_name: 'breth0', quota_network_gateway: '5', max_lp_per_bridged_ls: '64', max_lp_per_overlay_ls: '256', concurrent_connections: '3', metadata_mode: 'access_network' %w(l3 l2).each do |attr| it "sets the default #{attr} default gateway attribute" do expect(chef_run).to render_file(file.name).with_content(/^default_#{attr}_gw_service_uuid = $/) end it "sets the #{attr} default gateway attribute" do node.set['openstack']['network']['nicira']["default_#{attr}_gateway_service_uuid"] = "#{attr}_value" expect(chef_run).to render_file(file.name).with_content(/^default_#{attr}_gw_service_uuid = #{attr}_value$/) end end end describe 'openvswitch' do let(:file) { chef_run.template('/etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini') } before do node.set['openstack']['network']['core_plugin'] = 'openvswitch' end before do node.set['openstack']['network']['core_plugin'] = 'openvswitch' end it_behaves_like 'core plugin common configurator', 'openvswitch', PLUGIN_MAP['openvswitch'], tenant_network_type: 'local', enable_tunneling: 'False', polling_interval: '2', veth_mtu: '1500', enable_security_group: 'True' { network_vlan_ranges: '', tunnel_id_ranges: '', integration_bridge: 'br-int', tunnel_bridge: 'br-tun', int_peer_patch_port: '', tun_peer_patch_port: '', bridge_mappings: '' }.each do |attr, value| it "sets the default #{attr} when present" do if value.present? expect(chef_run).to render_file(file.name).with_content(/^#{attr} = #{value}$/) end end it "sets the #{attr} when present" do node.set['openstack']['network']['openvswitch'][attr] = "#{attr}_value" expect(chef_run).to render_file(file.name).with_content(/^#{attr} = #{attr}_value$/) end it "does not show the #{attr} when not present" do node.set['openstack']['network']['openvswitch'][attr] = nil expect(chef_run).not_to render_file(file.name).with_content(/^#{attr} = $/) end end it 'sets the local_ip' do expect(chef_run).to render_file(file.name).with_content(/^local_ip = 127.0.0.1$/) end it 'sets the default firewall_driver attribute' do expect(chef_run).to render_file(file.name).with_content(/^firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver$/) end it 'sets the firewall_driver attribute' do node.set['openstack']['network']['openvswitch']['fw_driver'] = 'fw_driver_value' expect(chef_run).to render_file(file.name).with_content(/^firewall_driver = fw_driver_value$/) end it 'sets related attributes for distributed routers' do node.set['openstack']['network']['l3']['router_distributed'] = true [ /^enable_distributed_routing = True$/, /^l2_population = True$/, /^tunnel_types = gre, vxlan$/ ].each do |line| expect(chef_run).to render_config_file(file.name).with_section_content('agent', line) end end end it_behaves_like 'core plugin common configurator', 'plumgrid', PLUGIN_MAP['plumgrid'], nos_server: '127.0.0.1', nos_server_port: '', username: '', password: '', servertimeout: '5', topologyname: '' it_behaves_like 'core plugin common configurator', 'ryu', PLUGIN_MAP['ryu'], integration_bridge: 'br-int', openflow_rest_api: '127.0.0.1:8080', tunnel_key_min: '1', tunnel_key_max: '0xffffff', tunnel_ip: '', tunnel_interface: 'eth0', ovsdb_port: '6634', ovsdb_ip: '', ovsdb_interface: 'eth0', firewall_driver: 'neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver', polling_interval: '2' end it 'does not upgrade python-neutronclient when nova networking' do node.override['openstack']['compute']['network']['service_type'] = 'nova' expect(chef_run).to_not upgrade_package('python-neutronclient') end it 'upgrades python neutronclient package' do expect(chef_run).to upgrade_package('python-neutronclient') end it 'upgrades python pyparsing package' do expect(chef_run).to upgrade_package('python-pyparsing') end it 'upgrades mysql python package' do expect(chef_run).to upgrade_package('python-mysqldb') 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: 0640 ) end it 'sends a notification to the service' do allow_any_instance_of(Chef::Recipe).to receive(:role_included?).with('os-network-server').and_return(true) expect(file).to notify('service[neutron-server]').to(:restart).delayed end it 'not sends a notification to the service' do allow_any_instance_of(Chef::Recipe).to receive(:role_included?).with('os-network-server').and_return(false) expect(file).not_to notify('service[neutron-server]').to(:restart).delayed end context 'template contents' do it_behaves_like 'custom template banner displayer' do let(:file_name) { file.name } end %w(debug verbose state_path log_dir auth_strategy dhcp_lease_duration rpc_thread_pool_size rpc_conn_pool_size rpc_response_timeout control_exchange allow_overlapping_ips notification_driver api_workers rpc_workers).each do |attr| it "sets the #{attr} common attribute" do node.set['openstack']['network'][attr] = "#{attr}_value" expect(chef_run).to render_file(file.name).with_content(/^#{attr} = #{attr}_value$/) end end it 'sets the lock_path attribute' do node.set['openstack']['network']['lock_path'] = 'lock_path_value' expect(chef_run).to render_config_file(file.name).with_section_content('oslo_concurrency', /^lock_path = lock_path_value$/) end it 'sets the log_config attribute if using syslog' do node.set['openstack']['network']['syslog']['use'] = true expect(chef_run).to render_file(file.name).with_content(%r{^log_config = /etc/openstack/logging.conf$}) end it 'does not set the log config attribute if not using syslog' do node.set['openstack']['network']['syslog']['use'] = false expect(chef_run).not_to render_file(file.name).with_content(%r{^log_config = /etc/openstack/logging.conf$}) end it 'set the router_distributed attribute for network node' do node.set['openstack']['network']['l3']['router_distributed'] = true allow_any_instance_of(Chef::Recipe).to receive(:recipe_included?).with('openstack-network::server').and_return(true) expect(chef_run).to render_config_file(file.name).with_section_content('DEFAULT', /^router_distributed = True$/) end it 'set the router_distributed attribute for compute node' do node.set['openstack']['network']['l3']['router_distributed'] = true allow_any_instance_of(Chef::Recipe).to receive(:recipe_included?).with('openstack-network::server').and_return(false) expect(chef_run).to render_config_file(file.name).with_section_content('DEFAULT', /^router_distributed = False$/) end it 'sets port and host attributes' do [ /^bind_port = 9696$/, /^bind_host = 127.0.0.1$/ ].each do |line| expect(chef_run).to render_config_file(file.name)\ .with_section_content('DEFAULT', line) end end it 'sets the core_plugin attribute' do core_plugin_value = PLUGIN_MAP.keys.first node.set['openstack']['network']['core_plugin'] = core_plugin_value node.set['openstack']['network']['core_plugin_map'][core_plugin_value] = core_plugin_value expect(chef_run).to render_file(file.name).with_content(/^core_plugin = #{core_plugin_value}$/) end it 'sets the service_plugins attribute if any present' do node.set['openstack']['network']['service_plugins'] = %w(service_plugin1 service_plugin2) expect(chef_run).to render_file(file.name).with_content(/^service_plugins = service_plugin1,service_plugin2$/) end it 'does not set the service_plugins attribute if not present' do node.set['openstack']['network']['service_plugins'] = [] expect(chef_run).not_to render_file(file.name).with_content(/^service_plugins = $/) end context 'rabbitmq service' do let(:userid) { 'rabbit_userid_value' } let(:password) { 'rabbit_password' } before do node.set['openstack']['mq']['network']['service_type'] = 'rabbitmq' node.set['openstack']['mq']['network']['rabbit']['userid'] = userid allow_any_instance_of(Chef::Recipe).to receive(:get_password) .with('user', userid) .and_return(password) end %w(durable_queues auto_delete).each do |attr| it "sets the ampq queue #{attr} attribute" do node.set['openstack']['mq']['network'][attr] = "#{attr}_value" expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_rabbit', /^amqp_#{attr}=#{attr}_value$/) end end it 'has default heartbeat options set' do [/^heartbeat_timeout_threshold=0$/, /^heartbeat_rate=2$/].each do |line| expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_rabbit', line) end end it 'sets the rabbit_userid attribute' do expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_rabbit', /^rabbit_userid=#{userid}$/) end it 'sets the rabbit_password attribute' do expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_rabbit', /^rabbit_password=#{password}$/) end it 'sets the rabbit_virtual_host attribute' do node.set['openstack']['mq']['network']['rabbit']['vhost'] = 'rabbit_virtual_host_value' expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_rabbit', /^rabbit_virtual_host=rabbit_virtual_host_value$/) end it 'sets the rabbit_retry_interval' do expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_rabbit', /^rabbit_retry_interval=1$/) end it 'sets the rabbit_max_retries' do expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_rabbit', /^rabbit_max_retries=0$/) end context 'rabbit ha enabled' do before do node.set['openstack']['mq']['network']['rabbit']['ha'] = true end it 'sets the rabbit_hosts attribute' do allow_any_instance_of(Chef::Recipe).to receive(:rabbit_servers) .and_return('rabbit_servers_value') expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_rabbit', /^rabbit_hosts=rabbit_servers_value$/) end it 'sets the rabbit_ha_queues attribute' do expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_rabbit', /^rabbit_ha_queues=True$/) end it 'sets the rabbit_use_ssl attribute' do expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_rabbit', /^rabbit_use_ssl=false$/) end end context 'rabbit ha disabled' do before do node.set['openstack']['mq']['network']['rabbit']['ha'] = false end %w(host port use_ssl).each do |attr| it "sets the non-ha rabbit_#{attr} attribute" do node.set['openstack']['mq']['network']['rabbit'][attr] = "rabbit_#{attr}_value" expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_rabbit', /^rabbit_#{attr}=rabbit_#{attr}_value$/) end end end it 'does not have kombu ssl version set' do expect(chef_run).not_to render_config_file(file.name).with_section_content('oslo_messaging_rabbit', /^kombu_ssl_version=TLSv1.2$/) end it 'sets kombu ssl version' do node.set['openstack']['mq']['network']['rabbit']['use_ssl'] = true node.set['openstack']['mq']['network']['rabbit']['kombu_ssl_version'] = 'TLSv1.2' expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_rabbit', /^kombu_ssl_version=TLSv1.2$/) end end context 'qpid service' do before do node.set['openstack']['mq']['network']['service_type'] = 'qpid' allow_any_instance_of(Chef::Recipe).to receive(:get_password) .with('user', 'qpid_username_value') .and_return('qpid_password_value') end %w(durable_queues auto_delete).each do |attr| it "sets the ampq queue #{attr} attribute" do node.set['openstack']['mq']['network'][attr] = "#{attr}_value" expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_qpid', /^amqp_#{attr}=#{attr}_value$/) end end %w(port username sasl_mechanisms reconnect reconnect_timeout reconnect_limit reconnect_interval_min reconnect_interval_max reconnect_interval heartbeat protocol tcp_nodelay topology_version).each do |attr| it "sets the common qpid #{attr} attribute" do node.set['openstack']['mq']['network']['qpid'][attr] = "qpid_#{attr}_value" expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_qpid', /^qpid_#{attr}=qpid_#{attr}_value$/) end end it 'sets the qpid_hostname attribute' do node.set['openstack']['mq']['network']['qpid']['host'] = 'qpid_hostname_value' expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_qpid', /^qpid_hostname=qpid_hostname_value$/) end it 'sets the qpid_password attribute' do node.set['openstack']['mq']['network']['qpid']['username'] = 'qpid_username_value' expect(chef_run).to render_config_file(file.name).with_section_content('oslo_messaging_qpid', /^qpid_password=qpid_password_value$/) end end it 'sets the notification_topics attribute' do node.set['openstack']['mq']['network']['notification_topics'] = 'notification_topics_value' expect(chef_run).to render_file(file.name).with_content(/^notification_topics = notification_topics_value$/) end it 'sets the agent_down_time attribute' do node.set['openstack']['network']['api']['agent']['agent_down_time'] = 'agent_down_time_value' expect(chef_run).to render_file(file.name).with_content(/^agent_down_time = agent_down_time_value$/) end it 'sets the network_scheduler_driver attribute' do node.set['openstack']['network']['dhcp']['scheduler'] = 'network_scheduler_driver_value' expect(chef_run).to render_file(file.name).with_content(/^network_scheduler_driver = network_scheduler_driver_value$/) end it 'sets the router_scheduler_driver attribute' do node.set['openstack']['network']['l3']['scheduler'] = 'router_scheduler_driver_value' expect(chef_run).to render_file(file.name).with_content(/^router_scheduler_driver = router_scheduler_driver_value$/) end it 'sets the dhcp_agents_per_network attribute' do node.set['openstack']['network']['dhcp']['dhcp_agents_per_network'] = 'dhcp_agents_per_network_value' expect(chef_run).to render_config_file(file.name).with_section_content('DEFAULT', /^dhcp_agents_per_network = dhcp_agents_per_network_value$/) end %w(l3_ha max_l3_agents_per_router).each do |attr| it "sets the #{attr} attribute" do node.set['openstack']['network']['l3']['ha'][attr] = "#{attr}_value" expect(chef_run).to render_config_file(file.name).with_section_content('DEFAULT', /^#{attr} = #{attr}_value$/) end end %w(notify_nova_on_port_status_changes notify_nova_on_port_data_changes send_events_interval).each do |attr| it "sets the #{attr} nova attribute" do node.set['openstack']['network']['nova'][attr] = "#{attr}_value" expect(chef_run).to render_file(file.name).with_content(/^#{attr} = #{attr}_value$/) end end it 'has default nova auth_plugin attribute' do expect(chef_run).to render_config_file(file.name).with_section_content('nova', /^auth_plugin = v2password/) end it 'does not set the sets admin_tenant_id' do expect(chef_run).not_to render_config_file(file.name).with_section_content('nova', /^admin_tenant_id =/) end it 'sets the nova admin_tenant_id' do node.set['openstack']['network']['nova']['admin_tenant_id'] = 'admin_tenant_id_value' expect(chef_run).to render_config_file(file.name).with_section_content('nova', /^admin_tenant_id = admin_tenant_id_value/) end it 'has default nova user and project attributes' do [ /^username = nova$/, /^user_domain_id = default$/, /^tenant_name = service$/, /^project_name = service$/, /^project_domain_id = default$/ ].each do |line| expect(chef_run).to render_config_file(file.name).with_section_content('nova', line) end end it 'sets the nova region_name attribute' do node.set['openstack']['network']['nova']['region_name'] = 'nova_region_name_value' expect(chef_run).to render_config_file(file.name).with_section_content('nova', /^region_name = nova_region_name_value$/) end it 'sets the nova password attribute' do expect(chef_run).to render_config_file(file.name).with_section_content('nova', /^password = nova-pass$/) end it 'sets the nova auth_url attribute when auth_plugin is password' do node.set['openstack']['network']['nova']['auth_plugin'] = 'password' expect(chef_run).to render_config_file(file.name).with_section_content('nova', %r{^auth_url = http://127.0.0.1:35357/$}) end it 'sets the nova auth_url attribute when auth_plugin is v2password by default' do expect(chef_run).to render_config_file(file.name).with_section_content('nova', %r{^auth_url = http://127.0.0.1:35357/v2.0$}) end it 'sets the nova auth_url attribute when auth_plugin is v3password' do node.set['openstack']['network']['nova']['auth_plugin'] = 'v3password' expect(chef_run).to render_config_file(file.name).with_section_content('nova', %r{^auth_url = http://127.0.0.1:35357/v3$}) end it 'has default nova api insecure' do expect(chef_run).to render_config_file(file.name).with_section_content('nova', /^insecure = false$/) end it 'sets nova api insecure' do node.set['openstack']['network']['nova']['insecure'] = true expect(chef_run).to render_config_file(file.name).with_section_content('nova', /^insecure = true$/) end it 'has no nova ca certificates file set by default' do expect(chef_run).not_to render_config_file(file.name).with_section_content('nova', /^cafile =/) end it 'sets nova_ca_certificates_file' do node.set['openstack']['network']['nova']['cafile'] = 'dir/to/path' expect(chef_run).to render_config_file(file.name).with_section_content('nova', %r{^cafile = dir/to/path$}) end it 'sets the misc_neutron values' do misc_neutron = %w(misc1 misc2) node.set['openstack']['network']['misc_neutron'] = misc_neutron misc_neutron.each do |misc| expect(chef_run).to render_file(file.name).with_content(/^#{misc}$/) end end %w(items network subnet port security_group security_group_rule driver router floatingip).each do |attr| it "sets the quota #{attr} attribute" do node.set['openstack']['network']['quota'][attr] = "quota_#{attr}_value" expect(chef_run).to render_file(file.name).with_content(/^quota_#{attr} = quota_#{attr}_value$/) end end it 'sets the default_quota attribute' do node.set['openstack']['network']['quota']['default'] = 'default_quota_value' expect(chef_run).to render_file(file.name).with_content(/^default_quota = default_quota_value$/) end it 'sets the root_helper attribute if enabled' do node.set['openstack']['network']['use_rootwrap'] = true expect(chef_run).to render_file(file.name).with_content(%r{^root_helper = "sudo neutron-rootwrap /etc/neutron/rootwrap.conf"$}) end it 'does not set the root_helper attribute if disabled' do node.set['openstack']['network']['use_rootwrap'] = false expect(chef_run).not_to render_file(file.name).with_content(%r{^root_helper = "sudo neutron-rootwrap /etc/neutron/rootwrap.conf"$}) end it 'sets the report_interval attribute' do node.set['openstack']['network']['api']['agent']['agent_report_interval'] = 'report_interval_value' expect(chef_run).to render_file(file.name).with_content(/^report_interval = report_interval_value$/) end it 'sets the auth_uri attribute' do expect(chef_run).to render_file(file.name).with_content(%r{^auth_uri = http://127.0.0.1:5000/v2.0$}) end it 'sets the identity_uri attribute' do expect(chef_run).to render_file(file.name).with_content(%r{^identity_uri = http://127.0.0.1:35357/$}) end it 'sets the auth_version attribute if not equal to v2.0' do node.set['openstack']['network']['api']['auth']['version'] = 'auth_version_value' expect(chef_run).to render_file(file.name).with_content(/^auth_version = auth_version_value$/) end %w(tenant_name user).each do |attr| it "sets the admin_#{attr} attribute" do node.set['openstack']['network']["service_#{attr}"] = "admin_#{attr}_value" expect(chef_run).to render_file(file.name).with_content(/^admin_#{attr} = admin_#{attr}_value$/) end end it 'sets the admin_password attribute' do expect(chef_run).to render_file(file.name).with_content(/^admin_password = neutron-pass$/) end it 'sets the signing_dir attribute' do node.set['openstack']['network']['api']['agent']['signing_dir'] = 'signing_dir_value' expect(chef_run).to render_file(file.name).with_content(/^signing_dir = signing_dir_value$/) end it 'uses default values for attributes' do expect(chef_run).not_to render_file(file.name).with_content( /^memcached_servers =/) expect(chef_run).not_to render_file(file.name).with_content( /^memcache_security_strategy =/) expect(chef_run).not_to render_file(file.name).with_content( /^memcache_secret_key =/) expect(chef_run).not_to render_file(file.name).with_content( /^cafile =/) expect(chef_run).to render_file(file.name).with_content(/^hash_algorithms = md5$/) expect(chef_run).to render_file(file.name).with_content(/^insecure = false$/) expect(chef_run).to render_file(file.name).with_content(/^auth_version = v2.0$/) end it 'sets memcached server(s)' do node.set['openstack']['network']['api']['auth']['memcached_servers'] = 'localhost:11211' expect(chef_run).to render_file(file.name).with_content(/^memcached_servers = localhost:11211$/) end it 'sets memcache security strategy' do node.set['openstack']['network']['api']['auth']['memcache_security_strategy'] = 'MAC' expect(chef_run).to render_file(file.name).with_content(/^memcache_security_strategy = MAC$/) end it 'sets memcache secret key' do node.set['openstack']['network']['api']['auth']['memcache_secret_key'] = '0123456789ABCDEF' expect(chef_run).to render_file(file.name).with_content(/^memcache_secret_key = 0123456789ABCDEF$/) end it 'sets cafile' do node.set['openstack']['network']['api']['auth']['cafile'] = 'dir/to/path' expect(chef_run).to render_file(file.name).with_content(%r{^cafile = dir/to/path$}) end it 'sets token hash algorithms' do node.set['openstack']['network']['api']['auth']['hash_algorithms'] = 'sha2' expect(chef_run).to render_file(file.name).with_content(/^hash_algorithms = sha2$/) end it 'sets insecure' do node.set['openstack']['network']['api']['auth']['insecure'] = true expect(chef_run).to render_file(file.name).with_content(/^insecure = true$/) end it 'sets the connection attribute' do node.set['openstack']['db']['network']['username'] = 'db_username_value' allow_any_instance_of(Chef::Recipe).to receive(:db_uri) .with('network', 'db_username_value', 'neutron') .and_return('connection_value') expect(chef_run).to render_file(file.name).with_content(/^connection = connection_value$/) end %w(slave_connection max_retries retry_interval min_pool_size max_pool_size idle_timeout max_overflow connection_debug connection_trace pool_timeout).each do |attr| it "sets the #{attr} attribute" do node.set['openstack']['db']['network'][attr] = "#{attr}_value" expect(chef_run).to render_file(file.name).with_content(/^#{attr} = #{attr}_value$/) end end it 'sets the service_provider attribute if present' do service_providers = %w(service_provider1 service_provider2) node.set['openstack']['network']['service_provider'] = service_providers service_providers.each do |service_provider_value| expect(chef_run).to render_file(file.name).with_content(/^service_provider = #{service_provider_value}$/) end end it 'does not show the service_provider key if none present' do node.set['openstack']['network']['service_provider'] = [] expect(chef_run).not_to render_file(file.name).with_content(/^service_provider = /) end end end describe 'policy file' do it 'does not manage policy file unless specified' do expect(chef_run).not_to create_remote_file('/etc/neutron/policy.json') end describe 'policy file specified' do before { node.set['openstack']['network']['policyfile_url'] = 'http://server/mypolicy.json' } let(:remote_policy) { chef_run.remote_file('/etc/neutron/policy.json') } it 'manages policy file when remote file is specified' do expect(chef_run).to create_remote_file('/etc/neutron/policy.json').with( user: 'neutron', group: 'neutron', mode: 00644) end end end describe '/etc/default/neutron-server' do let(:file) { chef_run.template('/etc/default/neutron-server') } it 'neutron-server config file' do expect(chef_run).to create_template(file.name).with( user: 'root', group: 'root', mode: 0644 ) end context 'template contents' do it_behaves_like 'custom template banner displayer' do let(:file_name) { file.name } end PLUGIN_MAP.each do |plugin_name, plugin_cfg| it "sets the path to the #{plugin_name} plugin config" do node.set['openstack']['network']['core_plugin'] = plugin_name node.set['openstack']['network']['core_plugin_map'][plugin_name] = plugin_name expect(chef_run).to render_file(file.name).with_content(%r{^NEUTRON_PLUGIN_CONFIG=/etc/neutron/plugins/#{plugin_name}/#{plugin_cfg}$}) end end end end describe '/etc/neutron/rootwrap.conf' do let(:file) { chef_run.template('/etc/neutron/rootwrap.conf') } it 'rootwrap config file' do expect(chef_run).to create_template(file.name).with( user: 'neutron', group: 'neutron', mode: 0644 ) end it_behaves_like 'custom template banner displayer' do let(:file_name) { file.name } end end end end