diff --git a/manifests/compute/provider.pp b/manifests/compute/provider.pp new file mode 100644 index 000000000..38af39060 --- /dev/null +++ b/manifests/compute/provider.pp @@ -0,0 +1,102 @@ +# == Class: nova::compute::provider +# +# Managing Resource Providers Using Config File +# +# === Parameters +# +# [*schema_version*] +# (optional) Version ($Major, $minor) of the schema must successfully +# parse documents conforming to ($Major, *) +# Default to '1.0' +# +# [*custom_inventories*] +# Array of hashes describing the custom provider inventory added via +# the $config_file config file. +# Format: +# name/uuid - Resource providers to target can be identified by either +# UUID or name. In addition, the value $COMPUTE_NODE can be used in +# the UUID field to identify all nodes managed by the service. +# Exactly one of uuid or name is mandatory. If neither uuid or name +# is provided, the special uuid $COMPUTE_NODE gets set in the template +# +# inventories - (Optional) Hash of custom provider inventories. 'total' is +# a mandatory property. Any other optional properties not populated will +# be given a default value by placement. If overriding a pre-existing +# provider values will not be preserved from the existing inventory. +# +# traits - (Optional) Array of additional traits. +# +# Example : +# [ +# { +# uuid => '$COMPUTE_NODE', +# inventories => { +# 'CUSTOM_EXAMPLE_RESOURCE_CLASS' => { +# total => '100', +# reserved => '0', +# min_unit => '1', +# max_unit => '10', +# step_size => '1', +# allocation_ratio => '1.0' +# }, +# 'CUSTOM_ANOTHER_EXAMPLE_RESOURCE_CLASS' => { +# total => '100', +# }, +# }, +# traits => ['CUSTOM_P_STATE_ENABLED','CUSTOM_C_STATE_ENABLED'], +# }, +# { +# name => 'EXAMPLE_RESOURCE_PROVIDER', +# inventories => { +# 'CUSTOM_EXAMPLE_RESOURCE_CLASS' => { +# total => '10000', +# reserved => '100', +# }, +# }, +# }, +# ] +# Defaults to []. +# +# [*config_location*] +# (Optional) Location of YAML files containing resource provider +# configuration data. +# Defaults to /etc/nova/provider_config +# +# [*config_file*] +# (Optional) File name of the provider YAML file. +# Defaults to 'provider.yaml' +# +class nova::compute::provider ( + $schema_version = '1.0', + $custom_inventories = [], + $config_location = '/etc/nova/provider_config', + $config_file = 'provider.yaml', +) { + + include nova::deps + include nova::params + + nova_config { + 'compute/provider_config_location': value => $config_location; + } + + file { "${config_location}": + ensure => directory, + mode => '0750', + owner => $::nova::params::nova_user, + group => $::nova::params::nova_group, + require => Anchor['nova::config::begin'], + before => Anchor['nova::config::end'], + } + + if !empty($custom_inventories) { + file { "${config_location}/${config_file}": + ensure => file, + mode => '0640', + owner => $::nova::params::nova_user, + group => $::nova::params::nova_group, + content => template('nova/provider.yaml.erb'), + require => Anchor['nova::config::begin'], + } + } +} diff --git a/releasenotes/notes/custom_provider-29467d209802707d.yaml b/releasenotes/notes/custom_provider-29467d209802707d.yaml new file mode 100644 index 000000000..d2d1b0544 --- /dev/null +++ b/releasenotes/notes/custom_provider-29467d209802707d.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + Nova supports to configure resource provider inventory and traits using a + standardized YAML file format starting victoria release [1]. This adds the + nova::compute::provider class to configure the custom provider yaml file + via puppet-nova. + [1] https://docs.openstack.org/nova/latest/admin/managing-resource-providers.html diff --git a/spec/classes/nova_compute_provider_spec.rb b/spec/classes/nova_compute_provider_spec.rb new file mode 100644 index 000000000..a20cfd3bf --- /dev/null +++ b/spec/classes/nova_compute_provider_spec.rb @@ -0,0 +1,282 @@ +# Unit tests for nova::compute::provider class +# + +require 'spec_helper' + +describe 'nova::compute::provider' do + + let :params do + {} + end + + shared_examples_for 'nova custom resource providers' do + + it 'configure nova.conf with default parameters' do + is_expected.to contain_nova_config('compute/provider_config_location').with_value('/etc/nova/provider_config') + end + + context 'when overriding default parameters' do + before :each do + params.merge!( + :config_location => '/etc/nova/custom_provider_config', + ) + end + + it 'configure nova.conf with overridden parameters' do + is_expected.to contain_nova_config('compute/provider_config_location').with_value('/etc/nova/custom_provider_config') + end + end + + context 'when providing custom inventory single inventory without uuid or name set' do + before :each do + params.merge!( + :custom_inventories => [ + { + 'inventories' => { + 'CUSTOM_EXAMPLE_RESOURCE_CLASS_1' => { + 'total' => '100', + 'reserved' => '0', + 'min_unit' => '1', + 'max_unit' => '10', + 'step_size' => '1', + 'allocation_ratio' => '1.0' + }, + 'CUSTOM_EXAMPLE_RESOURCE_CLASS_2' => { + 'total' => '100', + }, + }, + 'traits' => [ + 'CUSTOM_P_STATE_ENABLED', + 'CUSTOM_C_STATE_ENABLED', + ], + }, + ] + ) + end + + it 'configure provider.yaml on compute nodes' do + is_expected.to contain_file('/etc/nova/provider_config/provider.yaml') + verify_contents(catalogue, '/etc/nova/provider_config/provider.yaml', [ + "meta:", + " schema_version: \'1.0\'", + "providers:", + " # for details check https://docs.openstack.org/nova/latest/admin/managing-resource-providers.html", + " - identification:", + " uuid: \'$COMPUTE_NODE\'", + " inventories:", + " additional:", + " - CUSTOM_EXAMPLE_RESOURCE_CLASS_1:", + " allocation_ratio: 1.0", + " max_unit: 10", + " min_unit: 1", + " reserved: 0", + " step_size: 1", + " total: 100", + " - CUSTOM_EXAMPLE_RESOURCE_CLASS_2:", + " total: 100", + " traits:", + " additional:", + " - \'CUSTOM_P_STATE_ENABLED\'", + " - \'CUSTOM_C_STATE_ENABLED\'" + ]) + end + end + + context 'when providing custom inventory single inventory with uuid set' do + before :each do + params.merge!( + :custom_inventories => [ + { + 'uuid' => '5213b75d-9260-42a6-b236-f39b0fd10561', + 'inventories' => { + 'CUSTOM_EXAMPLE_RESOURCE_CLASS_1' => { + 'total' => '100', + 'reserved' => '0', + 'min_unit' => '1', + 'max_unit' => '10', + 'step_size' => '1', + 'allocation_ratio' => '1.0' + }, + 'CUSTOM_EXAMPLE_RESOURCE_CLASS_2' => { + 'total' => '100', + }, + }, + 'traits' => [ + 'CUSTOM_P_STATE_ENABLED', + 'CUSTOM_C_STATE_ENABLED', + ], + }, + ] + ) + end + + it 'configure provider.yaml on compute nodes' do + is_expected.to contain_file('/etc/nova/provider_config/provider.yaml') + verify_contents(catalogue, '/etc/nova/provider_config/provider.yaml', [ + "meta:", + " schema_version: \'1.0\'", + "providers:", + " # for details check https://docs.openstack.org/nova/latest/admin/managing-resource-providers.html", + " - identification:", + " uuid: \'5213b75d-9260-42a6-b236-f39b0fd10561\'", + " inventories:", + " additional:", + " - CUSTOM_EXAMPLE_RESOURCE_CLASS_1:", + " allocation_ratio: 1.0", + " max_unit: 10", + " min_unit: 1", + " reserved: 0", + " step_size: 1", + " total: 100", + " - CUSTOM_EXAMPLE_RESOURCE_CLASS_2:", + " total: 100", + " traits:", + " additional:", + " - \'CUSTOM_P_STATE_ENABLED\'", + " - \'CUSTOM_C_STATE_ENABLED\'" + ]) + end + end + + context 'when providing custom inventory single inventory with name set' do + before :each do + params.merge!( + :custom_inventories => [ + { + 'name' => 'EXAMPLE_RESOURCE_PROVIDER', + 'inventories' => { + 'CUSTOM_EXAMPLE_RESOURCE_CLASS_1' => { + 'total' => '100', + 'reserved' => '0', + 'min_unit' => '1', + 'max_unit' => '10', + 'step_size' => '1', + 'allocation_ratio' => '1.0' + }, + 'CUSTOM_EXAMPLE_RESOURCE_CLASS_2' => { + 'total' => '100', + }, + }, + 'traits' => [ + 'CUSTOM_P_STATE_ENABLED', + 'CUSTOM_C_STATE_ENABLED', + ], + }, + ] + ) + end + + it 'configure provider.yaml on compute nodes' do + is_expected.to contain_file('/etc/nova/provider_config/provider.yaml') + verify_contents(catalogue, '/etc/nova/provider_config/provider.yaml', [ + "meta:", + " schema_version: \'1.0\'", + "providers:", + " # for details check https://docs.openstack.org/nova/latest/admin/managing-resource-providers.html", + " - identification:", + " name: \'EXAMPLE_RESOURCE_PROVIDER\'", + " inventories:", + " additional:", + " - CUSTOM_EXAMPLE_RESOURCE_CLASS_1:", + " allocation_ratio: 1.0", + " max_unit: 10", + " min_unit: 1", + " reserved: 0", + " step_size: 1", + " total: 100", + " - CUSTOM_EXAMPLE_RESOURCE_CLASS_2:", + " total: 100", + " traits:", + " additional:", + " - \'CUSTOM_P_STATE_ENABLED\'", + " - \'CUSTOM_C_STATE_ENABLED\'" + ]) + end + end + + context 'when providing custom inventory with multiple providers' do + before :each do + params.merge!( + :custom_inventories => [ + { + 'inventories' => { + 'CUSTOM_EXAMPLE_RESOURCE_CLASS_1' => { + 'total' => '100', + 'reserved' => '0', + 'min_unit' => '1', + 'max_unit' => '10', + 'step_size' => '1', + 'allocation_ratio' => '1.0' + }, + 'CUSTOM_EXAMPLE_RESOURCE_CLASS_2' => { + 'total' => '100', + }, + }, + 'traits' => [ + 'CUSTOM_P_STATE_ENABLED', + 'CUSTOM_C_STATE_ENABLED', + ], + }, + { + 'name' => 'EXAMPLE_RESOURCE_PROVIDER', + 'inventories' => { + 'CUSTOM_EXAMPLE_RESOURCE_CLASS' => { + 'total' => '10000', + 'reserved' => '100', + }, + }, + }, + ] + ) + end + + it 'configure provider.yaml on compute nodes' do + is_expected.to contain_file('/etc/nova/provider_config/provider.yaml') + verify_contents(catalogue, '/etc/nova/provider_config/provider.yaml', [ + "meta:", + " schema_version: \'1.0\'", + "providers:", + " # for details check https://docs.openstack.org/nova/latest/admin/managing-resource-providers.html", + " - identification:", + " uuid: \'$COMPUTE_NODE\'", + " inventories:", + " additional:", + " - CUSTOM_EXAMPLE_RESOURCE_CLASS_1:", + " allocation_ratio: 1.0", + " max_unit: 10", + " min_unit: 1", + " reserved: 0", + " step_size: 1", + " total: 100", + " - CUSTOM_EXAMPLE_RESOURCE_CLASS_2:", + " total: 100", + " traits:", + " additional:", + " - \'CUSTOM_P_STATE_ENABLED\'", + " - \'CUSTOM_C_STATE_ENABLED\'", + " - identification:", + " name: \'EXAMPLE_RESOURCE_PROVIDER\'", + " inventories:", + " additional:", + " - CUSTOM_EXAMPLE_RESOURCE_CLASS:", + " reserved: 100", + " total: 10000", + " traits:", + " additional:" + ]) + 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 + + it_configures 'nova custom resource providers' + end + end +end diff --git a/templates/provider.yaml.erb b/templates/provider.yaml.erb new file mode 100644 index 000000000..8278698a6 --- /dev/null +++ b/templates/provider.yaml.erb @@ -0,0 +1,31 @@ +meta: + schema_version: '<%= @schema_version %>' +providers: + # for details check https://docs.openstack.org/nova/latest/admin/managing-resource-providers.html +<% @custom_inventories.each do |provider| -%> + - identification: +<% if provider['name'] -%> + name: '<%= provider['name'] %>' +<% elsif provider['uuid'] -%> + uuid: '<%= provider['uuid'] %>' +<% else -%> + uuid: '$COMPUTE_NODE' +<% end -%> +<% unless provider['inventories'].nil? -%> + inventories: + additional: +<% provider['inventories'].each do |key,inventory| -%> + - <%= key %>: +<% inventory.each do |key,value| -%> + <%= key %>: <%= value %> +<% end -%> +<% end -%> +<% end -%> +<% unless provider['traits'].nil? -%> + traits: + additional: +<% provider['traits'].each do |trait| -%> + - '<%= trait %>' +<% end -%> +<% end -%> +<% end -%>