diff --git a/lib/puppet/provider/ironic_neutron_agent_config/ini_setting.rb b/lib/puppet/provider/ironic_neutron_agent_config/ini_setting.rb new file mode 100644 index 000000000..1ba69b5ef --- /dev/null +++ b/lib/puppet/provider/ironic_neutron_agent_config/ini_setting.rb @@ -0,0 +1,15 @@ +Puppet::Type.type(:ironic_neutron_agent_config).provide( + :ini_setting, + :parent => Puppet::Type.type(:openstack_config).provider(:ini_setting) +) do + + def self.file_path + '/etc/neutron/plugins/ml2/ironic_neutron_agent.ini' + end + + # added for backwards compatibility with older versions of inifile + def file_path + self.class.file_path + end + +end diff --git a/lib/puppet/type/ironic_neutron_agent_config.rb b/lib/puppet/type/ironic_neutron_agent_config.rb new file mode 100644 index 000000000..23798cc0c --- /dev/null +++ b/lib/puppet/type/ironic_neutron_agent_config.rb @@ -0,0 +1,28 @@ +Puppet::Type.newtype(:ironic_neutron_agent_config) do + + ensurable + + newparam(:name, :namevar => true) do + desc 'Section/setting name to manage from networking-baremetal ironic-neutron-agent config.' + newvalues(/\S+\/\S+/) + end + + newproperty(:value) do + desc 'The value of the setting to be defined.' + munge do |value| + value = value.to_s.strip + value.capitalize! if value =~ /^(true|false)$/i + value + end + end + + newparam(:ensure_absent_val) do + desc 'A value that is specified as the value property will behave as if ensure => absent was specified' + defaultto('') + end + + autorequire(:package) do + 'python2-ironic-neutron-agent' + end + +end diff --git a/manifests/agents/ml2/networking_baremetal.pp b/manifests/agents/ml2/networking_baremetal.pp new file mode 100644 index 000000000..e1cefd175 --- /dev/null +++ b/manifests/agents/ml2/networking_baremetal.pp @@ -0,0 +1,179 @@ +# == Class: neutron::agents::ml2::networking_baremetal +# +# Setups networking-baremetal Neutron agent for ML2 plugin. +# +# === Parameters +# +# [*enabled*] +# (required) Whether or not to enable the agent. +# Defaults to true. +# +# [*password*] +# (required) Password for connection to ironic in admin context. +# +# [*manage_service*] +# (optional) Whether to start/stop the service +# Defaults to true +# +# [*package_ensure*] +# (optional) Package ensure state. +# Defaults to 'present'. +# +# [*auth_strategy*] +# (optional) Method to use for authentication: noauth or keystone. +# Defaults to $::os_service_default +# +# [*ironic_url*] +# (optional) Ironic API URL, used to set Ironic API URL when auth_strategy +# option is noauth to work with standalone Ironic without keystone. +# Defaults to $::os_service_default +# +# [*cafile*] +# (optional) PEM encoded Certificate Authority to use when verifying HTTPs +# connections. +# Defaults to $::os_service_default +# +# [*certfile*] +# (optional) PEM encoded client certificate cert file +# Defaults to $::os_service_default +# +# [*keyfile*] +# (optional) PEM encoded client certificate key file +# Defaults to $::os_service_default +# +# [*insecure*] +# (optional) Verify HTTPS connections. (boolean) +# Defaults to $::os_service_default +# +# [*auth_type*] +# (optional) An authentication type to use with an OpenStack Identity server. +# The value should contain auth plugin name +# Defaults to 'password' +# +# [*auth_url*] +# (optional) Authorization URL for connection to ironic in admin context. +# If version independent identity plugin is used available versions will be +# determined using auth_url +# Defaults to 'http://127.0.0.1:35357' +# +# [*username*] +# (optional) Username for connection to ironic in admin context +# Defaults to 'ironic' +# +# [*project_domain_id*] +# (optional) Domain ID containing project +# Defaults to 'default' +# +# [*project_domain_name*] +# (Optional) Domain name containing project +# Defaults to 'Default' +# +# [*project_name*] +# (optional) Project name to scope to +# Defaults to 'services' +# +# [*user_domain_id*] +# (optional) User's domain ID for connection to ironic in admin context +# Defaults to 'default' +# +# [*user_domain_name*] +# (Optional) Name of domain for $username +# Defaults to 'Default' +# +# [*region_name*] +# (optional) Name of region to use. Useful if keystone manages more than one +# region. +# Defaults to $::os_service_default +# +# [*retry_interval*] +# (optional) Interval between retries in case of conflict error (HTTP 409). +# Defaults to $::os_service_default +# +# [*max_retries*] +# (optional) Maximum number of retries in case of conflict error (HTTP 409). +# Defaults to $::os_service_default +# +# [*purge_config*] +# (optional) Whether to set only the specified config options in the +# ironic-neutron-agent config. +# Defaults to false. +# +class neutron::agents::ml2::networking_baremetal ( + $password, + $enabled = true, + $manage_service = true, + $package_ensure = 'present', + $auth_strategy = $::os_service_default, + $ironic_url = $::os_service_default, + $cafile = $::os_service_default, + $certfile = $::os_service_default, + $keyfile = $::os_service_default, + $insecure = $::os_service_default, + $auth_type = 'password', + $auth_url = 'http://127.0.0.1:35357', + $username = 'ironic', + $project_domain_id = 'default', + $project_domain_name = 'Default', + $project_name = 'services', + $user_domain_id = 'default', + $user_domain_name = 'Default', + $region_name = $::os_service_default, + $retry_interval = $::os_service_default, + $max_retries = $::os_service_default, + $purge_config = false, +) { + + include ::neutron::deps + include ::neutron::params + + if($::osfamily != 'RedHat') { + # Drivers are only packaged for RedHat at this time + fail("Unsupported osfamily ${::osfamily}") + } + + resources { 'ironic_neutron_agent_config': + purge => $purge_config, + } + + ironic_neutron_agent_config { + 'ironic/auth_strategy': value => $auth_strategy; + 'ironic/ironic_url': value => $ironic_url; + 'ironic/cafile': value => $cafile; + 'ironic/certfile': value => $certfile; + 'ironic/keyfile': value => $keyfile; + 'ironic/insecure': value => $insecure; + 'ironic/auth_type': value => $auth_type; + 'ironic/auth_url': value => $auth_url; + 'ironic/username': value => $username; + 'ironic/password': value => $password; + 'ironic/project_domain_id': value => $project_domain_id; + 'ironic/project_domain_name': value => $project_domain_name; + 'ironic/project_name': value => $project_name; + 'ironic/user_domain_id': value => $user_domain_id; + 'ironic/user_domain_name': value => $user_domain_name; + 'ironic/region_name': value => $region_name; + 'ironic/retry_interval': value => $retry_interval; + 'ironic/max_retries': value => $max_retries; + } + + package { 'python2-ironic-neutron-agent': + ensure => $package_ensure, + name => $::neutron::params::networking_baremetal_agent_package, + tag => ['openstack', 'neutron-package'], + } + + if $manage_service { + if $enabled { + $service_ensure = 'running' + } else { + $service_ensure = 'stopped' + } + service { 'ironic-neutron-agent-service': + ensure => $service_ensure, + name => $::neutron::params::networking_baremetal_agent_service, + enable => $enabled, + tag => 'neutron-service', + } + } + +} diff --git a/manifests/deps.pp b/manifests/deps.pp index c22fff1f5..e6378b8d8 100644 --- a/manifests/deps.pp +++ b/manifests/deps.pp @@ -70,6 +70,7 @@ class neutron::deps { Anchor['neutron::config::begin'] -> Neutron_plugin_nsx<||> ~> Anchor['neutron::config::end'] Anchor['neutron::config::begin'] -> Neutron_rootwrap_config<||> ~> Anchor['neutron::config::end'] Anchor['neutron::config::begin'] -> Ovn_metadata_agent_config<||> ~> Anchor['neutron::config::end'] + Anchor['neutron::config::begin'] -> Ironic_neutron_agent_config<||> ~> Anchor['neutron::config::end'] # Support packages need to be installed in the install phase, but we don't # put them in the chain above because we don't want any false dependencies diff --git a/manifests/params.pp b/manifests/params.pp index b51e8e032..52aff7e9d 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -41,43 +41,45 @@ class neutron::params { $group = 'neutron' if($::osfamily == 'Redhat') { - $nobody_user_group = 'nobody' - $package_name = 'openstack-neutron' - $server_package = false - $ml2_server_package = 'openstack-neutron-ml2' - $ovs_agent_package = false - $ovs_server_package = 'openstack-neutron-openvswitch' - $ovs_cleanup_service = 'neutron-ovs-cleanup' - $libnl_package = 'libnl' - $package_provider = 'rpm' - $linuxbridge_agent_package = false - $linuxbridge_server_package = 'openstack-neutron-linuxbridge' - $sriov_nic_agent_service = 'neutron-sriov-nic-agent' - $sriov_nic_agent_package = 'openstack-neutron-sriov-nic-agent' - $bigswitch_lldp_package = 'openstack-neutron-bigswitch-lldp' - $bigswitch_agent_package = 'openstack-neutron-bigswitch-agent' - $bigswitch_lldp_service = 'neutron-bsn-lldp' - $bigswitch_agent_service = 'neutron-bsn-agent' - $cisco_server_package = 'openstack-neutron-cisco' - $nvp_server_package = 'openstack-neutron-nicira' - $dhcp_agent_package = false - $lbaasv2_agent_package = 'openstack-neutron-lbaas' - $metering_agent_package = 'openstack-neutron-metering-agent' - $vpnaas_agent_package = 'openstack-neutron-vpnaas' - $l2gw_agent_package = 'openstack-neutron-l2gw-agent' - $l2gw_package = 'python2-networking-l2gw' - $ovn_metadata_agent_package = 'networking-ovn-metadata-agent' + $nobody_user_group = 'nobody' + $package_name = 'openstack-neutron' + $server_package = false + $ml2_server_package = 'openstack-neutron-ml2' + $ovs_agent_package = false + $ovs_server_package = 'openstack-neutron-openvswitch' + $ovs_cleanup_service = 'neutron-ovs-cleanup' + $libnl_package = 'libnl' + $package_provider = 'rpm' + $linuxbridge_agent_package = false + $linuxbridge_server_package = 'openstack-neutron-linuxbridge' + $sriov_nic_agent_service = 'neutron-sriov-nic-agent' + $sriov_nic_agent_package = 'openstack-neutron-sriov-nic-agent' + $bigswitch_lldp_package = 'openstack-neutron-bigswitch-lldp' + $bigswitch_agent_package = 'openstack-neutron-bigswitch-agent' + $bigswitch_lldp_service = 'neutron-bsn-lldp' + $bigswitch_agent_service = 'neutron-bsn-agent' + $cisco_server_package = 'openstack-neutron-cisco' + $nvp_server_package = 'openstack-neutron-nicira' + $dhcp_agent_package = false + $lbaasv2_agent_package = 'openstack-neutron-lbaas' + $metering_agent_package = 'openstack-neutron-metering-agent' + $vpnaas_agent_package = 'openstack-neutron-vpnaas' + $l2gw_agent_package = 'openstack-neutron-l2gw-agent' + $l2gw_package = 'python2-networking-l2gw' + $ovn_metadata_agent_package = 'networking-ovn-metadata-agent' if $::operatingsystemrelease =~ /^7.*/ or $::operatingsystem == 'Fedora' { $openswan_package = 'libreswan' } else { $openswan_package = 'openswan' } - $libreswan_package = 'libreswan' - $l3_agent_package = false - $fwaas_package = 'openstack-neutron-fwaas' - $neutron_wsgi_script_path = '/var/www/cgi-bin/neutron' - $neutron_wsgi_script_source = '/usr/bin/neutron-api' - $networking_baremetal_package = 'python2-networking-baremetal' + $libreswan_package = 'libreswan' + $l3_agent_package = false + $fwaas_package = 'openstack-neutron-fwaas' + $neutron_wsgi_script_path = '/var/www/cgi-bin/neutron' + $neutron_wsgi_script_source = '/usr/bin/neutron-api' + $networking_baremetal_package = 'python2-networking-baremetal' + $networking_baremetal_agent_package = 'python2-ironic-neutron-agent' + $networking_baremetal_agent_service = 'ironic-neutron-agent' } elsif($::osfamily == 'Debian') { $nobody_user_group = 'nogroup' $package_name = 'neutron-common' diff --git a/releasenotes/notes/networking-baremetal-ironic-neutron-agent-9259b452d6cfa9af.yaml b/releasenotes/notes/networking-baremetal-ironic-neutron-agent-9259b452d6cfa9af.yaml new file mode 100644 index 000000000..df73f9bba --- /dev/null +++ b/releasenotes/notes/networking-baremetal-ironic-neutron-agent-9259b452d6cfa9af.yaml @@ -0,0 +1,5 @@ +--- +features: + - Adds support for baremetal. Installation and configuration of + networking-baremetal ironic-neutron-agent ml2 agent. + diff --git a/spec/classes/neutron_agents_ml2_networking_baremetal_spec.rb b/spec/classes/neutron_agents_ml2_networking_baremetal_spec.rb new file mode 100644 index 000000000..408b37d75 --- /dev/null +++ b/spec/classes/neutron_agents_ml2_networking_baremetal_spec.rb @@ -0,0 +1,128 @@ +require 'spec_helper' + +describe 'neutron::agents::ml2::networking_baremetal' do + + let :default_params do + { :enabled => true, + :manage_service => true, + :package_ensure => 'present', + :auth_type => 'password', + :auth_url => 'http://127.0.0.1:35357', + :username => 'ironic', + :project_domain_id => 'default', + :project_domain_name => 'Default', + :project_name => 'services', + :user_domain_id => 'default', + :user_domain_name => 'Default', + :purge_config => false, + } + end + + let :test_facts do + { :operatingsystem => 'default', + :operatingsystemrelease => 'default' + } + end + + let :params do + { :password => 'passw0rd', + } + end + + shared_examples_for 'networking-baremetal ironic-neutron-agent with ml2 plugin' do + let :p do + default_params.merge(params) + end + + it { is_expected.to contain_class('neutron::params') } + + it 'passes purge to resource' do + is_expected.to contain_resources('ironic_neutron_agent_config').with({ + :purge => false + }) + end + + it 'configures /etc/neutron/plugins/ml2/ironic_neutron_agent.ini' do + is_expected.to contain_ironic_neutron_agent_config('ironic/auth_strategy').with_value('') + is_expected.to contain_ironic_neutron_agent_config('ironic/ironic_url').with_value('') + is_expected.to contain_ironic_neutron_agent_config('ironic/cafile').with_value('') + is_expected.to contain_ironic_neutron_agent_config('ironic/certfile').with_value('') + is_expected.to contain_ironic_neutron_agent_config('ironic/keyfile').with_value('') + is_expected.to contain_ironic_neutron_agent_config('ironic/auth_type').with_value(p[:auth_type]) + is_expected.to contain_ironic_neutron_agent_config('ironic/auth_url').with_value(p[:auth_url]) + is_expected.to contain_ironic_neutron_agent_config('ironic/username').with_value(p[:username]) + is_expected.to contain_ironic_neutron_agent_config('ironic/password').with_value(p[:password]) + is_expected.to contain_ironic_neutron_agent_config('ironic/project_domain_id').with_value(p[:project_domain_id]) + is_expected.to contain_ironic_neutron_agent_config('ironic/project_domain_name').with_value(p[:project_domain_name]) + is_expected.to contain_ironic_neutron_agent_config('ironic/project_name').with_value(p[:project_name]) + is_expected.to contain_ironic_neutron_agent_config('ironic/user_domain_id').with_value(p[:user_domain_id]) + is_expected.to contain_ironic_neutron_agent_config('ironic/user_domain_name').with_value(p[:user_domain_name]) + is_expected.to contain_ironic_neutron_agent_config('ironic/region_name').with_value('') + is_expected.to contain_ironic_neutron_agent_config('ironic/retry_interval').with_value('') + is_expected.to contain_ironic_neutron_agent_config('ironic/max_retries').with_value('') + end + + it 'installs ironic-neutron-agent agent package' do + is_expected.to contain_package('python2-ironic-neutron-agent').with( + :name => platform_params[:networking_baremetal_agent_package], + :ensure => p[:package_ensure], + :tag => ['openstack', 'neutron-package'], + ) + is_expected.to contain_package('python2-ironic-neutron-agent').that_requires('Anchor[neutron::install::begin]') + is_expected.to contain_package('python2-ironic-neutron-agent').that_notifies('Anchor[neutron::install::end]') + end + + it 'configures networking-baremetal ironic-neutron-agent service' do + is_expected.to contain_service('ironic-neutron-agent-service').with( + :name => platform_params[:networking_baremetal_agent_service], + :enable => true, + :ensure => 'running', + :tag => 'neutron-service', + ) + is_expected.to contain_service('ironic-neutron-agent-service').that_subscribes_to('Anchor[neutron::service::begin]') + is_expected.to contain_service('ironic-neutron-agent-service').that_notifies('Anchor[neutron::service::end]') + end + + context 'with enabled as false' do + before :each do + params.merge!(:enabled => false) + end + it 'should not start service' do + is_expected.to contain_service('ironic-neutron-agent-service').with( + :name => platform_params[:networking_baremetal_agent_service], + :enable => false, + :ensure => 'stopped', + :tag => 'neutron-service', + ) + is_expected.to contain_service('ironic-neutron-agent-service').that_subscribes_to('Anchor[neutron::service::begin]') + is_expected.to contain_service('ironic-neutron-agent-service').that_notifies('Anchor[neutron::service::end]') + end + end + end + + on_supported_os({ + :supported_os => OSDefaults.get_supported_os + }).each do |os,facts| + context "on #{os}" do + let (:facts) do + facts.merge!(OSDefaults.get_facts()) + end + let (:platform_params) do + case facts[:osfamily] + when 'RedHat' + { :networking_baremetal_agent_package => 'python2-ironic-neutron-agent', + :networking_baremetal_agent_service => 'ironic-neutron-agent' } + end + end + case facts[:osfamily] + when 'RedHat' + it_behaves_like 'networking-baremetal ironic-neutron-agent with ml2 plugin' + when facts[:osfamily] != 'RedHat' + it 'fails with unsupported osfamily' do + is_expected.to raise_error(Puppet::Error, /Unsupported osfamily.*/) + end + end + end + end + +end diff --git a/spec/unit/provider/ironic_neutron_agent_config/ini_settings_spec.rb b/spec/unit/provider/ironic_neutron_agent_config/ini_settings_spec.rb new file mode 100644 index 000000000..2574a9d07 --- /dev/null +++ b/spec/unit/provider/ironic_neutron_agent_config/ini_settings_spec.rb @@ -0,0 +1,74 @@ +$LOAD_PATH.push( + File.join( + File.dirname(__FILE__), + '..', + '..', + '..', + 'fixtures', + 'modules', + 'inifile', + 'lib') +) +$LOAD_PATH.push( + File.join( + File.dirname(__FILE__), + '..', + '..', + '..', + 'fixtures', + 'modules', + 'openstacklib', + 'lib') +) + +require 'spec_helper' + +provider_class = Puppet::Type.type(:ironic_neutron_agent_config).provider(:ini_setting) + +describe provider_class do + + it 'should default to the default setting when no other one is specified' do + resource = Puppet::Type::Ironic_neutron_agent_config.new( + { + :name => 'DEFAULT/foo', + :value => 'bar' + } + ) + provider = provider_class.new(resource) + expect(provider.section).to eq('DEFAULT') + expect(provider.setting).to eq('foo') + expect(provider.file_path).to eq('/etc/neutron/plugins/ml2/ironic_neutron_agent.ini') + end + + it 'should allow setting to be set explicitly' do + resource = Puppet::Type::Ironic_neutron_agent_config.new( + { + :name => 'dude/foo', + :value => 'bar' + } + ) + provider = provider_class.new(resource) + expect(provider.section).to eq('dude') + expect(provider.setting).to eq('foo') + expect(provider.file_path).to eq('/etc/neutron/plugins/ml2/ironic_neutron_agent.ini') + end + + it 'should ensure absent when is specified as a value' do + resource = Puppet::Type::Ironic_neutron_agent_config.new( + {:name => 'dude/foo', :value => ''} + ) + provider = provider_class.new(resource) + provider.exists? + expect(resource[:ensure]).to eq :absent + end + + it 'should ensure absent when value matches ensure_absent_val' do + resource = Puppet::Type::Ironic_neutron_agent_config.new( + {:name => 'dude/foo', :value => 'foo', :ensure_absent_val => 'foo' } + ) + provider = provider_class.new(resource) + provider.exists? + expect(resource[:ensure]).to eq :absent + end + +end diff --git a/spec/unit/type/ironic_neutron_agent_config_spec.rb b/spec/unit/type/ironic_neutron_agent_config_spec.rb new file mode 100644 index 000000000..ded894ec4 --- /dev/null +++ b/spec/unit/type/ironic_neutron_agent_config_spec.rb @@ -0,0 +1,20 @@ +require 'puppet' +require 'puppet/type/ironic_neutron_agent_config' + +describe 'Puppet::Type.type(:ironic_neutron_agent_config)' do + + before :each do + @ironic_neutron_agent_config = Puppet::Type.type(:ironic_neutron_agent_config).new(:name => 'DEFAULT/foo', :value => 'bar') + end + + it 'should autorequire the package that install the file' do + catalog = Puppet::Resource::Catalog.new + package = Puppet::Type.type(:package).new(:name => 'python2-ironic-neutron-agent') + catalog.add_resource package, @ironic_neutron_agent_config + dependency = @ironic_neutron_agent_config.autorequire + expect(dependency.size).to eq(1) + expect(dependency[0].target).to eq(@ironic_neutron_agent_config) + expect(dependency[0].source).to eq(package) + end + +end