Added hugepages configuration

- Hugepages kernel settings
- Tasks
- Defaults for HugePages setting
- Mount added for HugePages
- Flavor for HugePages creation

Change-Id: I7ee9504e3c47db7a6a6e587636afb56e57541b65
Signed-off-by: Oleksandr Martsyniuk <omartsyniuk@mirantis.com>
This commit is contained in:
Andrey Kirilochkin 2016-02-20 11:14:32 +03:00 committed by Oleksandr Martsyniuk
parent 22ef5b8237
commit d11ff91c79
14 changed files with 1441 additions and 5 deletions

View File

@ -0,0 +1,19 @@
# Copyright 2016 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
notice('MODULAR: contrail/contrail-compute-aggregate.pp')
include contrail
class { 'contrail::compute::aggregate': }

View File

@ -0,0 +1,18 @@
# Copyright 2016 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
notice('MODULAR: contrail/contrail-compute-hugepages.pp')
include contrail
class { 'contrail::compute::hugepages': }

View File

View File

@ -0,0 +1,959 @@
require 'augeas' if Puppet.features.augeas?
# Base Augeas provider
# Handles basics such as opening, accessing and saving changes via an Augeas
# handle, plus standard configuration from a Puppet resource (e.g. the `target`
# parameter).
#
# To use, include as parent provider:
#
# Puppet::Type.type(:example).provide(
# :augeas,
# :parent => Puppet::Type.type(:augeasprovider).provider(:default)
# ) do
# # [..]
# end
#
Puppet::Type.type(:augeasprovider).provide(:default) do
# Class methods automatically added to a Puppet provider by including the
# {AugeasProviders::Provider} mixin.
# Returns the Augeas version used
#
# @return [String] Augeas version in use
# @api public
def self.aug_version
@aug_version ||= Augeas.open(nil, nil, Augeas::NO_MODL_AUTOLOAD) { |aug| aug.get('/augeas/version') }
end
# Returns whether a feature is supported.
#
# The following features are currently supported:
#
# * `:regexpi`: whether Augeas supports an 'i' flag in regexp expressions
# * `:post_resource_eval`: whether Puppet supports `post_resource_eval` hooks
#
# @param [Symbol] feature the feature to check
# @return [Boolean] whether feature is supported
# @api public
def self.supported?(feature)
case feature
when :regexpi
Puppet::Util::Package.versioncmp(aug_version, '1.0.0') >= 0
when :post_resource_eval
Puppet::Util::Package.versioncmp(Puppet.version, '3.4.0') >= 0
else
raise Puppet::Error, "Unknown feature '#{feature}'"
end
end
# Returns a node label to use for creating a new entry in an Augeas sequence
# (seq), given the current list, e.g. '1' if it's the first. Supply
# aug.match('$target/*') or similar.
#
# @param [Array<String>] existing paths, from Augeas#match
# @return [String] new node label
def self.next_seq(matches)
last = matches.map {|p| path_label(nil, p).to_i }.max || 0
(last + 1).to_s
end
# Returns an Augeas handler.
#
# On Puppet >= 3.4, stores and returns a shared Augeas handler
# for all instances of the class
#
# @return [Augeas] Augeas shared Augeas handle
# @api private
def self.aug_handler
if supported?(:post_resource_eval)
@aug ||= Augeas.open(nil, loadpath, Augeas::NO_MODL_AUTOLOAD)
else
Augeas.open(nil, loadpath, Augeas::NO_MODL_AUTOLOAD)
end
end
# Close the shared Augeas handler.
#
# @param [Augeas] aug open Augeas handle
# @api public
def self.augclose!(aug)
aug.close
end
# Opens Augeas and returns a handle to use. It loads only the file
# identified by {#target} (and the supplied `resource`) using {#lens}.
#
# If called with a block, this will be yielded to and the Augeas handle
# closed after the block has executed (on Puppet < 3.4.0).
# Otherwise, the handle will be returned and not closed automatically.
# On Puppet >= 3.4, the handle will be closed by `post_resource_eval`.
# On older versions, the caller is responsible for closing it to free
# resources.
#
# If `yield_resource` is set to true, the supplied `resource` will be passed
# as a yieldparam to the block, after the `aug` handle. Any arguments passed
# after `yield_resource` will be added as yieldparams to the block.
#
# @param [Puppet::Resource] resource resource being evaluated
# @param [Boolean] yield_resource whether to send `resource` as a yieldparam
# @param [Splat] yield_params a splat of parameters to pass as yieldparams if `yield_resource` is true
# @return [Augeas] Augeas handle if no block is given
# @yield [aug, resource, *yield_params] block that uses the Augeas handle
# @yieldparam [Augeas] aug open Augeas handle
# @yieldparam [Puppet::Resource] resource the supplied Puppet resource, passed if `yield_resource` is set to true
# @yieldparam [Splat] *yield_params a splat of additional arguments sent to the block, if `yield_resource` is set to true
# @raise [Puppet::Error] if Augeas did not load the file
# @api public
def self.augopen(resource = nil, yield_resource = false, *yield_params, &block)
augopen_internal(resource, false, yield_resource, *yield_params, &block)
end
# Opens Augeas and returns a handle to use. It loads only the file
# for the current Puppet resource using {AugeasProviders::Provider::ClassMethods#lens}.
# #augsave! is called after the block is evaluated.
#
# If called with a block, this will be yielded to and the Augeas handle
# closed after the block has executed (on Puppet < 3.4.0).
# Otherwise, the handle will be returned and not closed automatically.
# On Puppet >= 3.4, the handle will be closed by `post_resource_eval`.
# On older versions, the caller is responsible for closing it to free
# resources.
#
# If `yield_resource` is set to true, the supplied `resource` will be passed
# as a yieldparam to the block, after the `aug` handle. Any arguments passed
# after `yield_resource` will be added as yieldparams to the block.
#
# @param [Puppet::Resource] resource resource being evaluated
# @param [Boolean] yield_resource whether to send `resource` as a yieldparam
# @param [Splat] yield_params a splat of parameters to pass as yieldparams if `yield_resource` is true
# @return [Augeas] Augeas handle if no block is given
# @yield [aug, resource, *yield_params] block that uses the Augeas handle
# @yieldparam [Augeas] aug open Augeas handle
# @yieldparam [Puppet::Resource] resource the supplied Puppet resource, passed if `yield_resource` is set to true
# @yieldparam [Splat] *yield_params a splat of additional arguments sent to the block, if `yield_resource` is set to true
# @raise [Puppet::Error] if Augeas did not load the file
# @api public
def self.augopen!(resource = nil, yield_resource = false, *yield_params, &block)
augopen_internal(resource, true, yield_resource, *yield_params, &block)
end
# Saves all changes made in the current Augeas handle and checks for any
# errors while doing so.
# Reloads the tree afterwards to remove specific changes for next resource.
#
# @param [Augeas] aug open Augeas handle
# @param [Boolean] reload whether to reload the tree after saving
# @raise [Augeas::Error] if saving fails
# @api public
def self.augsave!(aug, reload = false)
begin
aug.save!
rescue Augeas::Error
errors = []
aug.match("/augeas//error").each do |errnode|
aug.match("#{errnode}/*").each do |subnode|
subvalue = aug.get(subnode)
errors << "#{subnode} = #{subvalue}"
end
end
debug("Save failure details:\n" + errors.join("\n"))
raise Augeas::Error, 'Failed to save Augeas tree to file. See debug logs for details.'
ensure
aug.load! if reload
end
end
# Define a method with a block passed to #augopen
#
# @param [Symbol] method the name of the method to create
# @yield [aug, resource, *args] block that uses the Augeas handle
# @yieldparam [Augeas] aug open Augeas handle
# @yieldparam [Puppet::Resource] resource the supplied Puppet resource
# @yieldparam [Splat] *args a splat of additional arguments sent to the block
# @api public
def self.define_aug_method(method, &block)
define_method(method) do |*args|
# We are calling the resource's augopen here, not the class
augopen(true, *args, &block)
end
end
# Define a method with a block passed to #augopen!
#
# @param [Symbol] method the name of the method to create
# @yield [aug, resource, *args] block that uses the Augeas handle
# @yieldparam [Augeas] aug open Augeas handle
# @yieldparam [Puppet::Resource] resource the supplied Puppet resource
# @yieldparam [Splat] *args a splat of additional arguments sent to the block
# @api public
def self.define_aug_method!(method, &block)
define_method(method) do |*args|
# We are calling the resource's augopen! here, not the class
augopen!(true, *args, &block)
end
end
# Defines a property getter with a provided implementation. It works from
# a node identified with the given `label` beneath the resource.
#
# Supports three implementations based on the type specified:
#
# :string causes the getter to return the value of the node below
# resource with the label given in opts
#
# :array causes the getter to return an array of values matching the label.
# If sublabel is given, values of matching nodes beneath the
# label node will be returned in an array. If sublabel is :seq, values of
# nodes matching a numbered seq will be returned.
#
# :hash causes the getter to return a hash of the value of each matching
# label node against the value of each sublabel node.
#
# @param [String] name the name of the property
# @param [Hash] opts the options to create the setter
# @option opts [String] label node label to match beneath resource, default is `name.to_s`. When the value is `:resource`, `$resource` will be used as the path to the node
# @option opts [Symbol] type either :string, :array or :hash
# @option opts [String] default default value for hash values if sublabel doesn't exist
# @option opts [String] sublabel label of next node(s) beneath node label, used in array and hash values, or :seq for array values representing a numbered seq
# @api public
def self.attr_aug_reader(name, opts = {})
label = opts[:label] || name.to_s
default = opts[:default] || nil
type = opts[:type] || :string
sublabel = opts[:sublabel] || nil
rpath = label == :resource ? '$resource' : "$resource/#{label}"
if type == :hash and sublabel.nil?
fail "You must provide a sublabel for type hash"
end
unless [:string, :array, :hash].include? type
fail "Invalid type: #{type}"
end
# Class getter method using an existing aug handler
# Emulate define_singleton_method for Ruby 1.8
metaclass = class << self; self; end
metaclass.send(:define_method, "attr_aug_reader_#{name}") do |aug, *args|
case type
when :string
aug.get(rpath)
when :array
aug.match(rpath).map do |p|
if sublabel.nil?
aug.get(p)
else
if sublabel == :seq
sp = "#{p}/*[label()=~regexp('[0-9]+')]"
else
sp = "#{p}/#{sublabel}"
end
aug.match(sp).map { |spp| aug.get(spp) }
end
end.flatten
when :hash
values = {}
aug.match(rpath).each do |p|
sp = "#{p}/#{sublabel}"
values[aug.get(p)] = aug.get(sp) || default
end
values
end
end
# Instance getter method for the instance
define_method("attr_aug_reader_#{name}") do |aug, *args|
self.class.send("attr_aug_reader_#{name}", aug, *args)
end
# We are calling the resource's augopen here, not the class
define_method(name) do |*args|
augopen do |aug|
self.send("attr_aug_reader_#{name}", aug, *args)
end
end
end
# Defines a property setter using #augopen
#
# @param [String] name the name of the property
# @param [Hash] opts the options to create the setter
# @option opts [String] label node label to match beneath resource, default is `name.to_s`. When the value is `:resource`, `$resource` will be used as the path to the node
# @option opts [Symbol] type either :string, :array or :hash
# @option opts [String] default default value for hash values if sublabel doesn't exist
# @option opts [String] sublabel label of next node(s) beneath node label, used in array and hash values, or :seq for array values representing a numbered seq
# @option opts [Boolean] purge_ident whether to purge other matches (keeps the last one only)
# @option opts [Boolean] rm_node whether setting a string value to `nil` removes the node (default is to clear its value)
# @api public
def self.attr_aug_writer(name, opts = {})
label = opts[:label] || name.to_s
default = opts[:default] || nil
type = opts[:type] || :string
sublabel = opts[:sublabel] || nil
purge_ident = opts[:purge_ident] || false
rm_node = opts[:rm_node] || false
rpath = label == :resource ? '$resource' : "$resource/#{label}"
if type == :hash and sublabel.nil?
fail "You must provide a sublabel for type hash"
end
unless [:string, :array, :hash].include? type
fail "Invalid type: #{type}"
end
# Class setter method using an existing aug handler
# Emulate define_singleton_method for Ruby 1.8
metaclass = class << self; self; end
metaclass.send(:define_method, "attr_aug_writer_#{name}") do |aug, *args|
aug.rm("#{rpath}[position() != 1]") if purge_ident
case type
when :string
if args[0]
aug.set(rpath, args[0].to_s)
elsif rm_node
aug.rm(rpath)
else
aug.clear(rpath)
end
when :array
if args[0].nil?
aug.rm(rpath)
else
if sublabel.nil?
aug.rm(rpath)
count = 0
args[0].each do |v|
count += 1
aug.set("#{rpath}[#{count}]", v)
end
elsif sublabel == :seq
# Make sure only our values are used
aug.rm("#{rpath}/*[label()=~regexp('[0-9]+')]")
count = 0
args[0].each do |v|
count += 1
aug.set("#{rpath}/#{count}", v)
end
else
# Make sure only our values are used
aug.rm("#{rpath}/#{sublabel}")
count = 0
args[0].each do |v|
count += 1
aug.set("#{rpath}/#{sublabel}[#{count}]", v)
end
end
end
when :hash
# First get rid of all entries
aug.rm(rpath)
args[0].each do |k, v|
aug.set("#{rpath}[.='#{k}']", k)
unless v == default
aug.set("#{rpath}[.='#{k}']/#{sublabel}", v)
end
end
end
end
# Instance setter method for the instance
define_method("attr_aug_writer_#{name}") do |aug, *args|
self.class.send("attr_aug_writer_#{name}", aug, *args)
end
# We are calling the resource's augopen here, not the class
define_method("#{name}=") do |*args|
augopen! do |aug|
self.send("attr_aug_writer_#{name}", aug, *args)
end
end
end
# Define getter and setter for a property
#
# @param [Symbol] name the name of the property
# @param [Hash] opts the options to create the setter
# @option opts [String] label node label to match beneath resource, default is `name.to_s`. When the value is `:resource`, `$resource` will be used as the path to the node
# @option opts [Symbol] type either :string, :array or :hash
# @option opts [String] default default value for hash values if sublabel doesn't exist
# @option opts [String] sublabel label of next node(s) beneath node label, used in array and hash values, or :seq for array values representing a numbered seq
# @option opts [Boolean] purge_ident whether to purge other matches (keeps the last one only)
# @api public
def self.attr_aug_accessor(name, opts = {})
attr_aug_reader(name, opts)
attr_aug_writer(name, opts)
end
# Setter for the default file path managed by the provider.
#
# Takes a block to store, but doesn't yield. Will be called when it's
# needed.
#
# @yield block that identifies the default file path managed by the provider
# @yieldreturn [String] default file path
# @api public
def self.default_file(&block)
@default_file_block = block
end
# Getter and setter for the Augeas lens used for this provider.
#
# When called with a block, will only store the block - it doesn't yield.
#
# When called without a block, expects `resource` parameter which is
# passed into the block, which returns the lens to be used.
#
# @param resource [Puppet::Resource] required for getter, resource being evaluated
# @yield [resource] block that identifies the lens to use
# @yieldparam [Puppet::Resource] resource resource being evaluted
# @yieldreturn [String] Augeas lens to use, e.g. `'Hosts.lns'`
# @return [String] Augeas lens to use, e.g. `'Hosts.lns'`
# @raise [Puppet::Error] if no block has been set when getting
# @api public
def self.lens(resource = nil, &block)
if block_given?
@lens_block = block
else
fail 'Lens is not provided' unless @lens_block
@lens_block.call(resource)
end
end
# Wrapper around aug.label for older versions of Augeas
# and values not found in the tree.
#
# @param [Augeas] aug Augeas handler
# @param [String] path expression to get the label from
# @return [String] label of the given path
# @api public
def self.path_label(aug, path)
if aug.respond_to? :label
label = aug.label(path)
end
# Fallback
label || path.split("/")[-1].split("[")[0]
end
# Determine which quote is needed
#
# @param [String] value the value to quote
# @param [String] oldvalue the optional old value, used to auto-detect existing quoting
# @return [String] the quoted value
# @api public
def self.whichquote(value, resource = nil, oldvalue = nil)
oldquote = readquote oldvalue
if resource and resource.parameters.include? :quoted
quote = resource[:quoted]
else
quote = :auto
end
if quote == :auto
quote = if oldquote
oldquote
elsif value =~ /[|&;()<>\s]/
:double
else
:none
end
end
case quote
when :double
'"'
when :single
"'"
else
''
end
end
# Automatically quote a value
#
# @param [String] value the value to quote
# @param [String] oldvalue the optional old value, used to auto-detect existing quoting
# @return [String] the quoted value
# @api public
def self.quoteit(value, resource = nil, oldvalue = nil)
quote = whichquote(value, resource, oldvalue)
"#{quote}#{value}#{quote}"
end
# Detect what type of quoting a value uses
#
# @param [String] value the value to be analyzed
# @return [Symbol] the type of quoting used (:double, :single or nil)
# @api public
def self.readquote(value)
if value =~ /^(["'])(.*)(?:\1)$/
case $1
when '"' then :double
when "'" then :single
else nil end
else
nil
end
end
# Getter and setter for the Augeas path expression representing an
# individual resource inside a file, that's managed by this provider.
#
# When called with a block, will only store the block - it doesn't yield.
# The block is later used to generate the path expression.
#
# When called without a block, expects `resource` parameter which is
# passed into the block, which returns the path expression representing
# the supplied resource.
#
# If no block has already been set, it returns the path expression
# representing the top-level of the file.
#
# @param resource [Puppet::Resource] required for getter, resource being evaluated
# @yield [resource] block that identifies the path expression
# @yieldparam [Puppet::Resource] resource resource being evaluted
# @yieldreturn [String] Augeas path expression, e.g. `'/files/etc/hosts/1'`
# @return [String] Augeas path expression to use, e.g. `'/files/etc/hosts/1'`
# @raise [Puppet::Error] if no default file block is set and no resource is passed
# @see AugeasProviders::Provider#resource_path
# @see #target
# @api public
def self.resource_path(resource = nil, &block)
if block_given?
@resource_path_block = block
else
if @resource_path_block
path = "/files#{target(resource)}"
@resource_path_block.call(resource)
else
"#{target(resource)}/#{resource[:name]}"
end
end
end
# Sets useful Augeas variables for the session.
#
# * `$target` points to the root of the target file
# * `$resource` points to path defined by #resource_path
#
# It also sets `/augeas/context` to the target file so
# relative paths can be used, before the variables are set.
#
# If supplied with a resource, it will be used to determine the
# path to the used file.
#
# @param [Augeas] aug Augeas handle
# @param [Puppet::Resource] resource resource being evaluated
# @see #resource_path
# @api public
def self.setvars(aug, resource = nil)
aug.set('/augeas/context', "/files#{target(resource)}")
aug.defnode('target', "/files#{target(resource)}", nil)
aug.defvar('resource', resource_path(resource)) if resource
end
# Gets the path expression representing the file being managed.
#
# If supplied with a resource, this will represent the file identified by
# the resource, else the default file that the provider manages.
#
# @param [Puppet::Resource] resource resource being evaluated
# @return [String] path expression representing the file being managed
# @raise [Puppet::Error] if no default block is set and no resource is passed
# @see AugeasProviders::Provider#target
# @see #resource_path
# @api public
def self.target(resource = nil)
file = @default_file_block.call if @default_file_block
file = resource[:target] if resource and resource[:target]
fail 'No target file given' if file.nil?
file.chomp('/')
end
# Automatically unquote a value
#
# @param [String] value the value to unquote
# @return [String] the unquoted value
# @api public
def self.unquoteit(value)
if value =~ /^(["'])(.*)(?:\1)$/
$2
else
value
end
end
# Returns whether text is parsed as path using lens
#
# @param [String] text the text to test
# @param [String] path the relative path to test
# @param [String] lens the lens to use for parsing
# @return [Boolean] whether the path was found when parsing text with lens
# @api public
def self.parsed_as?(text, path, lens)
Augeas.open(nil, nil, Augeas::NO_MODL_AUTOLOAD) do |aug|
if aug.respond_to? :text_store
aug.set('/input', text)
if aug.text_store(lens, '/input', '/parsed')
return aug.match("/parsed/#{path}").any?
end
else
# ruby-augeas < 0.5 doesn't support text_store
Tempfile.open('aug_text_store') do |tmpfile|
tmpfile.write(text)
tmpfile.flush
aug.transform(
:lens => lens,
:name => 'Text_store',
:incl => tmpfile.path.to_s,
:excl => []
)
aug.load!
return aug.match("/files#{tmpfile.path.to_s}/#{path}").any?
end
end
end
return false
end
# Sets the post_resource_eval class hook for Puppet
# This is only used with Puppet > 3.4.0
# and allows to clean the shared Augeas handler.
def self.post_resource_eval
augclose!(aug_handler)
@aug = nil
end
# Returns a set of load paths to use when initialising Augeas.
#
# @return [String] colon-separated string of module paths, or nil if defaults are to be used
def self.loadpath
loadpath = nil
plugins = File.join(Puppet[:libdir], 'augeas', 'lenses')
if File.exists?(plugins)
loadpath = loadpath.to_s.split(File::PATH_SEPARATOR).push(plugins).join(File::PATH_SEPARATOR)
end
loadpath
end
# Opens Augeas and returns a handle to use. It loads only the file
# identified by {#target} (and the supplied `resource`) using {#lens}.
#
# If called with a block, this will be yielded to and the Augeas handle
# closed after the block has executed (on Puppet < 3.4.0).
# Otherwise, the handle will be returned and not closed automatically.
# On Puppet >= 3.4, the handle will be closed by `post_resource_eval`.
# On older versions, the caller is responsible for closing it to free
# resources.
#
# If `yield_resource` is set to true, the supplied `resource` will be passed
# as a yieldparam to the block, after the `aug` handle. Any arguments passed
# after `yield_resource` will be added as yieldparams to the block.
#
# @param [Puppet::Resource] resource resource being evaluated
# @param [Boolean] autosave whether to call augsave! automatically after the block evaluation
# @param [Boolean] yield_resource whether to send `resource` as a yieldparam
# @param [Splat] yield_params a splat of parameters to pass as yieldparams if `yield_resource` is true
# @return [Augeas] Augeas handle if no block is given
# @yield [aug, resource, *yield_params] block that uses the Augeas handle
# @yieldparam [Augeas] aug open Augeas handle
# @yieldparam [Puppet::Resource] resource the supplied Puppet resource, passed if `yield_resource` is set to true
# @yieldparam [Splat] *yield_params a splat of additional arguments sent to the block, if `yield_resource` is set to true
# @raise [Puppet::Error] if Augeas did not load the file
# @api private
def self.augopen_internal(resource = nil, autosave = false, yield_resource = false, *yield_params, &block)
aug = aug_handler
file = target(resource)
begin
lens_name = lens[/[^\.]+/]
if aug.match("/augeas/load/#{lens_name}").empty?
aug.transform(
:lens => lens,
:name => lens_name,
:incl => file,
:excl => []
)
aug.load!
elsif aug.match("/augeas/load/#{lens_name}/incl[.='#{file}']").empty?
# Only add missing file
aug.set("/augeas/load/#{lens_name}/incl[.='#{file}']", file)
aug.load!
end
if File.exist?(file) && aug.match("/files#{file}").empty?
message = aug.get("/augeas/files#{file}/error/message")
unless aug.match("/augeas/files#{file}/error/pos").empty?
line = aug.get("/augeas/files#{file}/error/line")
char = aug.get("/augeas/files#{file}/error/char")
message += " (line:#{line}, character:#{char})"
end
from = loadpath.nil? ? '' : " from #{loadpath}"
fail("Augeas didn't load #{file} with #{lens}#{from}: #{message}")
end
if block_given?
setvars(aug, resource)
if yield_resource
block.call(aug, resource, *yield_params)
else
block.call(aug)
end
else
aug
end
rescue
autosave = false
raise
ensure
if aug && block_given? && !supported?(:post_resource_eval)
augsave!(aug) if autosave
augclose!(aug)
end
end
end
# Returns the Augeas version used
#
# @return [String] Augeas version in use
# @api public
def aug_version
self.class.aug_version
end
# Returns whether a feature is supported.
#
# The following features are currently supported:
#
# * `:regexpi`: whether Augeas supports an 'i' flag in regexp expressions
# * `:post_resource_eval`: whether Puppet supports `post_resource_eval` hooks
#
# @param [Symbol] feature the feature to check
# @return [Boolean] whether feature is supported
# @api public
def supported?(feature)
self.class.supported?(feature)
end
# Opens Augeas and returns a handle to use. It loads only the file
# for the current Puppet resource using {AugeasProviders::Provider::ClassMethods#lens}.
#
# If called with a block, this will be yielded to and the Augeas handle
# closed after the block has executed (on Puppet < 3.4.0).
# Otherwise, the handle will be returned and not closed automatically.
# On Puppet >= 3.4, the handle will be closed by `post_resource_eval`.
# On older versions, the caller is responsible for closing it to free
# resources.
#
# If `yield_resource` is set to true, the supplied `resource` will be passed
# as a yieldparam to the block, after the `aug` handle. Any arguments passed
# after `yield_resource` will be added as yieldparams to the block.
#
# @return [Augeas] Augeas handle if no block is given
# @yield [aug, resource, *yield_params] block that uses the Augeas handle
# @yieldparam [Augeas] aug open Augeas handle
# @yieldparam [Puppet::Resource] resource the supplied Puppet resource, passed if `yield_resource` is set to true
# @yieldparam [Splat] *yield_params a splat of additional arguments sent to the block, if `yield_resource` is set to true
# @raise [Puppet::Error] if Augeas did not load the file
# @api public
def augopen(yield_resource = false, *yield_params, &block)
self.class.augopen(self.resource, yield_resource, *yield_params, &block)
end
# Opens Augeas and returns a handle to use. It loads only the file
# for the current Puppet resource using {AugeasProviders::Provider::ClassMethods#lens}.
# #augsave! is called after the block is evaluated.
#
# If called with a block, this will be yielded to and the Augeas handle
# closed after the block has executed (on Puppet < 3.4.0).
# Otherwise, the handle will be returned and not closed automatically.
# On Puppet >= 3.4, the handle will be closed by `post_resource_eval`.
# On older versions, the caller is responsible for closing it to free
# resources.
#
# @return [Augeas] Augeas handle if no block is given
# @yield [aug, resource, *yield_params] block that uses the Augeas handle
# @yieldparam [Augeas] aug open Augeas handle
# @yieldparam [Puppet::Resource] resource the supplied Puppet resource, passed if `yield_resource` is set to true
# @yieldparam [Splat] *yield_params a splat of additional arguments sent to the block, if `yield_resource` is set to true
# @raise [Puppet::Error] if Augeas did not load the file
# @api public
def augopen!(yield_resource = false, *yield_params, &block)
self.class.augopen!(self.resource, yield_resource, *yield_params, &block)
end
# Saves all changes made in the current Augeas handle and checks for any
# errors while doing so.
#
# @param [Augeas] aug open Augeas handle
# @param [Boolean] reload whether to reload the tree after saving
# @raise [Augeas::Error] if saving fails
# @api public
def augsave!(aug, reload = false)
self.class.augsave!(aug, reload)
end
# Close the shared Augeas handler.
#
# @param [Augeas] aug open Augeas handle
# @api public
def augclose!(aug)
self.class.augclose!(aug)
end
# Returns an Augeas handler.
#
# On Puppet >= 3.4, stores and returns a shared Augeas handler
# for all instances of the class
#
# @return [Augeas] Augeas shared Augeas handle
# @api private
def aug_handler
self.class.aug_handler
end
# Wrapper around Augeas#label for older versions of Augeas
#
# @param [Augeas] aug Augeas handler
# @param [String] path expression to get the label from
# @return [String] label of the given path
# @api public
def path_label(aug, path)
self.class.path_label(aug, path)
end
# Determine which quote is needed
#
# @param [String] value the value to quote
# @param [String] oldvalue the optional old value, used to auto-detect existing quoting
# @return [String] the quoted value
# @api public
def whichquote(value, oldvalue = nil)
self.class.whichquote(value, self.resource, oldvalue)
end
# Automatically quote a value
#
# @param [String] value the value to quote
# @param [String] oldvalue the optional old value, used to auto-detect existing quoting
# @return [String] the quoted value
# @api public
def quoteit(value, oldvalue = nil)
self.class.quoteit(value, self.resource, oldvalue)
end
# Detect what type of quoting a value uses
#
# @param [String] value the value to be analyzed
# @return [Symbol] the type of quoting used (:double, :single or nil)
# @api public
def readquote(value)
self.class.readquote(value)
end
# Gets the Augeas path expression representing the individual resource inside
# the file, that represents the current Puppet resource.
#
# If no block was set by the provider's class method, it returns the path
# expression representing the top-level of the file.
#
# @return [String] Augeas path expression to use, e.g. `'/files/etc/hosts/1'`
# @see AugeasProviders::Provider::ClassMethods#resource_path
# @see #target
# @api public
def resource_path
self.class.resource_path(self.resource)
end
# Sets useful Augeas variables for the session:
#
# * `$target` points to the root of the target file
# * `$resource` points to path defined by #resource_path
#
# It also sets `/augeas/context` to the target file so
# relative paths can be used, before the variables are set.
#
# If supplied with a resource, it will be used to determine the
# path to the used file.
#
# @param [Augeas] aug Augeas handle
# @see #resource_path
# @api public
def setvars(aug)
self.class.setvars(aug, self.resource)
end
# Gets the path expression representing the file being managed for the
# current Puppet resource.
#
# @return [String] path expression representing the file being managed
# @see AugeasProviders::Provider::ClassMethods#target
# @see #resource_path
# @api public
def target
self.class.target(self.resource)
end
# Automatically unquote a value
#
# @param [String] value the value to unquote
# @return [String] the unquoted value
# @api public
def unquoteit(value)
self.class.unquoteit(value)
end
# Returns whether text is parsed as path using lens
#
# @param [String] text the text to test
# @param [String] path the relative path to test
# @param [String] lens the lens to use for parsing
# @return [Boolean] whether the path was found when parsing text with lens
# @api public
def parsed_as?(text, path, lens = nil)
lens ||= self.class.lens(self.resource)
self.class.parsed_as?(text, path, lens)
end
# Default method to determine the existence of a resource
# can be overridden if necessary
def exists?
augopen do |aug|
not aug.match('$resource').empty?
end
end
# Default method to destroy a resource
# can be overridden if necessary
def destroy
augopen! do |aug|
aug.rm('$resource')
end
end
# Default method to flush a resource
#
# On Puppet >= 3.4, this takes care of
# saving the tree for the shared Augeas handler.
#
# This method can be overridden in your provider
# but you should make sure to call `super`
# to ensure that the tree will be saved in Puppet >= 3.4
def flush
augsave!(aug_handler, true) if supported?(:post_resource_eval)
end
# Returns a node label to use for creating a new entry in an Augeas sequence
# (seq), given the current list, e.g. '1' if it's the first. Supply
# aug.match('$target/*') or similar.
#
# @param [Array<String>] existing paths, from Augeas#match
# @return [String] new node label
def next_seq(matches)
self.class.next_seq(matches)
end
end

View File

@ -0,0 +1,160 @@
# GRUB 2 support for kernel parameters, edits /etc/default/grub
#
# Copyright (c) 2012 Dominic Cleal
# Licensed under the Apache License, Version 2.0
Puppet::Type.type(:kernel_parameter).provide(:grub2, :parent => Puppet::Type.type(:augeasprovider).provider(:default)) do
desc "Uses Augeas API to update kernel parameters in GRUB2's /etc/default/grub"
default_file { '/etc/default/grub' }
lens { 'Shellvars_list.lns' }
resource_path do |resource|
"$target/#{section(resource)}/value[.=~regexp('^#{resource[:name]}(=.*)?$')]"
end
def self.mkconfig_path
which("grub2-mkconfig") or which("grub-mkconfig") or '/usr/sbin/grub-mkconfig'
end
defaultfor :osfamily => 'Redhat', :operatingsystemmajrelease => [ '7' ]
defaultfor :operatingsystem => 'Debian', :operatingsystemmajrelease => [ '8' ]
defaultfor :operatingsystem => 'Ubuntu', :operatingsystemmajrelease => [ '14.04' ]
confine :feature => :augeas
commands :mkconfig => mkconfig_path
def self.instances
augopen do |aug|
resources = []
# Params are nicely separated, but no recovery-only setting (hard-coded)
sections = { 'all' => "GRUB_CMDLINE_LINUX",
'normal' => "GRUB_CMDLINE_LINUX_DEFAULT",
'default' => "GRUB_CMDLINE_LINUX_DEFAULT" }
sections.keys.sort.each do |bootmode|
key = sections[bootmode]
# Get all unique param names
params = aug.match("$target/#{key}/value").map { |pp|
aug.get(pp).split("=")[0]
}.uniq
# Find all values for each param name
params.each do |param|
vals = aug.match("$target/#{key}/value[.=~regexp('^#{param}(=.*)?$')]").map {|vp|
aug.get(vp).split("=", 2)[1]
}
vals = vals[0] if vals.size == 1
param = {:ensure => :present, :name => param, :value => vals, :bootmode => bootmode}
resources << new(param)
end
end
resources
end
end
def self.section(resource)
case resource[:bootmode].to_s
when "default", "normal"
"GRUB_CMDLINE_LINUX_DEFAULT"
when "all"
"GRUB_CMDLINE_LINUX"
else
fail("Unsupported bootmode for #{self.class.to_s} provider")
end
end
def create
self.value=(resource[:value])
end
def value
augopen do |aug|
aug.match('$resource').map {|vp|
aug.get(vp).split("=", 2)[1]
}
end
end
# If GRUB_CMDLINE_LINUX_DEFAULT does not exist, it should be set to the
# present contents of GRUB_CMDLINE_LINUX.
# If this is not done, you may end up with garbage on your next kernel
# upgrade!
def munge_grub_cmdline_linux_default(aug)
src_path = '$target/GRUB_CMDLINE_LINUX/value'
dest_path = '$target/GRUB_CMDLINE_LINUX_DEFAULT'
if aug.match("#{dest_path}/value").empty?
aug.match(src_path).each do |val|
src_val = aug.get(val)
# Need to let the rest of the code work on the actual value properly.
unless src_val.split('=').first.strip == resource[:name]
val_target = val.split('/').last
aug.set("#{dest_path}/#{val_target}", src_val)
end
end
end
end
def value=(newval)
augopen! do |aug|
# If we don't have the section at all, add it. Otherwise, any
# manipulation will result in a parse error.
current_section = self.class.section(resource)
has_section = aug.match("$target/#{current_section}")
if !has_section || has_section.empty?
aug.set("$target/#{current_section}/quote",'"')
end
if current_section == 'GRUB_CMDLINE_LINUX_DEFAULT'
munge_grub_cmdline_linux_default(aug)
end
if newval && !newval.empty?
vals = newval.clone
else
# If no value (e.g. "quiet") then clear the value from the first and
# delete the rest
vals = nil
aug.set("#{resource_path}[1]", resource[:name])
aug.rm("#{resource_path}[position() > 1]")
end
# Set any existing parameters with this name, remove excess ones
if vals
aug.match('$resource').each do |ppath|
val = vals.shift
if val.nil?
aug.rm(ppath)
else
aug.set(ppath, "#{resource[:name]}=#{val}")
end
end
end
# Add new parameters where there are more values than existing params
if vals && !vals.empty?
vals.each do |val|
aug.set("$target/#{current_section}/value[last()+1]", "#{resource[:name]}=#{val}")
end
end
end
end
def flush
cfg = nil
["/boot/grub/grub.cfg", "/boot/grub2/grub.cfg", "/boot/efi/EFI/fedora/grub.cfg"].each {|c|
cfg = c if FileTest.file? c
}
fail("Cannot find grub.cfg location to use with grub-mkconfig") unless cfg
super
mkconfig "-o", cfg
end
end

View File

@ -0,0 +1,5 @@
# Dumb augeasprovider type
Puppet::Type.newtype(:augeasprovider) do
@doc = 'Dumb Augeas provider type'
end

View File

@ -0,0 +1,36 @@
# Manages kernel parameters stored in bootloaders such as GRUB.
#
# Copyright (c) 2012 Dominic Cleal
# Licensed under the Apache License, Version 2.0
Puppet::Type.newtype(:kernel_parameter) do
@doc = "Manages kernel parameters stored in bootloaders."
ensurable
newparam(:name) do
desc "The parameter name, e.g. 'quiet' or 'vga'."
isnamevar
end
newproperty(:value, :array_matching => :all) do
desc "Value of the parameter if applicable. Many parameters are just keywords so this must be left blank, while others (e.g. 'vga') will take a value."
end
newparam(:target) do
desc "The bootloader configuration file, if in a non-default location for the provider."
end
newparam(:bootmode) do
desc "Boot mode(s) to apply the parameter to. Either 'all' (default) to use the parameter on all boots (normal and recovery mode), 'default' for just the default boot entry, 'normal' for just normal boots or 'recovery' for just recovery boots."
newvalues :all, :default, :normal, :recovery
defaultto :all
end
autorequire(:file) do
self[:target]
end
end

View File

@ -0,0 +1,79 @@
# Copyright 2016 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
class contrail::compute::aggregate {
define contrail::provision::aggr_add_host {
exec { "aggr_add_host_${name}":
command => "bash -c \"nova aggregate-add-host hpgs-aggr ${name}\"",
returns => [0,1],
}
}
if $contrail::dpdk_enabled {
$nodes_hash = hiera('nodes')
$dpdk_compute_nodes = nodes_with_roles(['dpdk'], 'fqdn')
$dpdk_hosts = join($dpdk_compute_nodes, ',')
$nova_hash = hiera_hash('nova', {})
$keystone_tenant = pick($nova_hash['tenant'], 'services')
$keystone_user = pick($nova_hash['user'], 'nova')
$service_endpoint = hiera('service_endpoint')
$region = hiera('region', 'RegionOne')
Exec {
provider => 'shell',
path => '/sbin:/usr/sbin:/bin:/usr/bin',
tries => 10,
try_sleep => 2,
environment => [
"OS_TENANT_NAME=${keystone_tenant}",
"OS_USERNAME=${keystone_user}",
"OS_PASSWORD=${nova_hash['user_password']}",
"OS_AUTH_URL=http://${service_endpoint}:5000/v2.0/",
'OS_ENDPOINT_TYPE=internalURL',
"OS_REGION_NAME=${region}",
'NOVA_ENDPOINT_TYPE=internalURL',
],
}
exec {'create-hpgs-aggr':
command => 'bash -c "nova aggregate-create hpgs-aggr hpgs"',
unless => 'bash -c "nova aggregate-list | grep -q hpgs-aggr"',
} ->
exec {'aggr-set-metadata':
command => 'bash -c "nova aggregate-set-metadata hpgs-aggr hpgs=true"',
unless => 'bash -c "nova aggregate-details hpgs-aggr | grep hpgs=true"',
}
if $dpdk_hosts {
contrail::provision::aggr_add_host { $dpdk_hosts:
require => Exec['aggr-set-metadata'],
}
}
# Create flavor for huge pages use
#
exec { 'create-m1.small.hpgs-flavor' :
command => 'bash -c "nova flavor-create --is-public true m1.small.hpgs auto 512 20 2"',
unless => 'bash -c "nova flavor-list | grep -q m1.small.hpgs"',
} ->
exec { 'create-m1.small.hpgs-mempage' :
command => 'bash -c "nova flavor-key m1.small.hpgs set hw:mem_page_size=large"',
} ->
exec { 'create-m1.small.hpgs-aggregate' :
command => 'bash -c "nova flavor-key m1.small.hpgs set aggregate_instance_extra_specs:hpgs=true"',
require => Exec['aggr-set-metadata'],
}
}
}

View File

@ -0,0 +1,92 @@
# Copyright 2016 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
class contrail::compute::hugepages {
if $contrail::dpdk_enabled {
# NOTE: To use hugepages we have to upgrade qemu packages to version 2.4
# The kernel configuration for hugepages
Kernel_parameter {
provider => 'grub2',
}
if $contrail::hugepages_size == 2 {
sysctl::value { 'vm.nr_hugepages':
value => "${contrail::hugepages_number} ",
}
kernel_parameter { 'hugepagesz':
ensure => absent,
}
kernel_parameter { 'hugepages':
ensure => absent,
}
}
elsif $contrail::hugepages_size == 1024 {
kernel_parameter { 'hugepagesz':
ensure => present,
value => "${contrail::hugepages_size}M",
} ->
kernel_parameter { 'hugepages':
ensure => present,
value => $contrail::hugepages_size,
}
#This need for vrouter start when 1Gb hugepages not enabled yet
exec { 'temporary_add_hugepages':
path => ['/sbin', '/usr/bin'],
command => 'sysctl -w vm.nr_hugepages=256',
onlyif => 'test ! -d /sys/kernel/mm/hugepages/hugepages-1048576kB',
}
exec { 'reboot_require':
path => ['/bin', '/usr/bin'],
command => 'touch /tmp/contrail-reboot-require',
onlyif => 'test ! -d /sys/kernel/mm/hugepages/hugepages-1048576kB',
}
}
file { '/hugepages':
ensure => 'directory',
group => 'kvm',
} ->
mount { '/hugepages':
ensure => 'mounted',
fstype => 'hugetlbfs',
device => 'hugetlbfs',
options => 'mode=775,gid=kvm',
atboot => true,
} ->
file_line { 'hugepages_mountpoint':
path => '/etc/libvirt/qemu.conf',
match => '#hugetlbfs_mount',
line => 'hugetlbfs_mount = "/hugepages"',
} ~>
service { 'qemu-kvm':
ensure => running,
enable => true,
} ~>
service { 'libvirtd':
ensure => running,
enable => true,
}
}
}

View File

@ -55,10 +55,14 @@ class contrail {
$admin_tenant = $admin_settings['tenant']
# Contrail settings
$asnum = $settings['contrail_asnum']
$external = $settings['contrail_external']
$route_target = $settings['contrail_route_target']
$gateways = split($settings['contrail_gateways'], ',')
$asnum = $settings['contrail_asnum']
$external = $settings['contrail_external']
$route_target = $settings['contrail_route_target']
$gateways = split($settings['contrail_gateways'], ',')
# Hugepages configuration for DPDK vrouter
$hugepages_size = pick($settings['hugepages_size'],2)
$hugepages_amount = pick($settings['hugepages_amount'],10)
$hugepages_number = floor($::memorysize_mb * $hugepages_amount / '100' / $hugepages_size)
# Custom mount point for contrail-db
$cassandra_path = '/var/lib/contrail_db'
@ -79,6 +83,10 @@ class contrail {
$netmask_short = netmask_to_cidr($netmask)
$phys_dev = get_private_ifname($interface)
# DPDK settings
$dpdk_enabled = 'dpdk' in hiera_array('roles')
$mos_mgmt_vip = $network_metadata['vips']['management']['ipaddr']
$mos_public_vip = $network_metadata['vips']['public']['ipaddr']

View File

View File

@ -9,6 +9,7 @@
parameters:
strategy:
type: one_by_one
- id: contrail-db
type: group
role: [contrail-db]
@ -29,6 +30,7 @@
parameters:
strategy:
type: one_by_one
- id: contrail-config
type: group
role: [contrail-config]
@ -49,6 +51,7 @@
parameters:
strategy:
type: one_by_one
- id: contrail-control
type: group
role: [contrail-control]
@ -83,6 +86,7 @@
parameters:
strategy:
type: parallel
# Tasks
# Install Contrail utils, java
- id: contrail-utils
@ -324,6 +328,17 @@
type: skipped
# Remove Open vSwitch packages, install and configure Contrail vRouter dkms kernel module
# Configures hugepages kernel settings if dpdk is enabled
- id: contrail-compute-hugepages
type: puppet
role: [compute]
required_for: [post_deployment_end, contrail-compute-provision]
requires: [post_deployment_start]
parameters:
puppet_manifest: puppet/manifests/contrail-compute-hugepages.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 720
- id: contrail-compute-provision
type: puppet
role: [compute]
@ -333,6 +348,7 @@
puppet_manifest: puppet/manifests/contrail-compute-provision.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 720
- id: contrail-compute-network
type: puppet
role: [compute]
@ -342,6 +358,7 @@
puppet_manifest: puppet/manifests/contrail-compute-network.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 720
- id: contrail-compute-nova
type: puppet
role: [compute]
@ -351,6 +368,7 @@
puppet_manifest: puppet/manifests/contrail-compute-nova.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 720
- id: contrail-compute-firewall
type: puppet
role: [compute]
@ -360,12 +378,34 @@
puppet_manifest: puppet/manifests/contrail-compute-firewall.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 720
- id: contrail-compute-vrouter
type: puppet
role: [compute]
required_for: [post_deployment_end]
required_for: [post_deployment_end, contrail-compute-aggregate]
requires: [post_deployment_start]
parameters:
puppet_manifest: puppet/manifests/contrail-compute-vrouter.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 720
# Creates aggregate for DPDK
- id: contrail-compute-aggregate
type: puppet
role: [compute]
required_for: [post_deployment_end, compute-reboot]
requires: [post_deployment_start]
parameters:
puppet_manifest: puppet/manifests/contrail-compute-aggregate.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 120
# Reboot compute nodes, if it need.
- id: compute-reboot
type: shell
role: [compute]
required_for: [post_deployment_end]
requires: [configure_default_route]
parameters:
cmd: if [ -f /tmp/contrail-reboot-require ]; then /sbin/reboot; fi
timeout: 720

View File

@ -40,3 +40,23 @@ attributes:
regex:
source: '^(?:(6553[0-5])|(655[0-2]\d)|(65[0-4]\d{2})|(6[0-4]\d{3})|([1-5]\d{4})|([1-9]\d{1,3})|([1-9]))$'
error: "Invalid target"
hugepages_size:
type: 'select'
weight: 120
value: '2'
label: 'Hugepage size'
description: 'Choose the size of hugepages that will be used for dpdk feature. Check if 1GB pages are supported on target compute node. # grep pdpe1gb /proc/cpuinfo | uniq'
values:
- data: '2'
label: '2M'
- data: '1024'
label: "1G"
hugepages_amount:
value: '10'
label: 'Hugepages amount (%)'
description: 'The amount of memory allocated on each compute-node for hugepages in percent'
weight: 130
type: 'text'
regex:
source: '^[1-9][0-9]?$|^100$'
error: "Invalid amount of percent"