Advanced network configuration
This commit is contained in:
parent
2fde90dd4f
commit
6ae4854eb4
|
@ -1,4 +1,3 @@
|
|||
|
||||
#
|
||||
# cidr_to_netmask.rb
|
||||
#
|
||||
|
@ -20,7 +19,7 @@ EOS
|
|||
) do |arguments|
|
||||
if arguments.size != 1
|
||||
raise(Puppet::ParseError, "cidr_to_netmask(): Wrong number of arguments " +
|
||||
"given (#{arguments.size} for 1)")
|
||||
"given (#{arguments.size} for 1)")
|
||||
end
|
||||
|
||||
masklen = prepare_cidr(arguments[0])[1]
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
require 'yaml'
|
||||
require 'json'
|
||||
|
||||
Puppet::Parser::Functions::newfunction(:debug__dump_to_file, :doc => <<-EOS
|
||||
debug output to file
|
||||
|
||||
EOS
|
||||
) do |argv|
|
||||
File.open(argv[0], 'w'){ |file| file.write argv[1].to_yaml() }
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,258 @@
|
|||
require 'ipaddr'
|
||||
require 'forwardable'
|
||||
require 'puppet/parser'
|
||||
require 'puppet/parser/templatewrapper'
|
||||
require 'puppet/resource/type_collection_helper'
|
||||
require 'puppet/util/methodhelper'
|
||||
|
||||
begin
|
||||
require 'puppet/parser/functions/lib/l23network_scheme.rb'
|
||||
rescue LoadError => e
|
||||
# puppet apply does not add module lib directories to the $LOAD_PATH (See
|
||||
# #4248). It should (in the future) but for the time being we need to be
|
||||
# defensive which is what this rescue block is doing.
|
||||
rb_file = File.join(File.dirname(__FILE__),'lib','l23network_scheme.rb')
|
||||
load rb_file if File.exists?(rb_file) or raise e
|
||||
end
|
||||
|
||||
|
||||
|
||||
module L23network
|
||||
def self.sanitize_transformation(trans)
|
||||
action = trans[:action].downcase()
|
||||
# Setup defaults
|
||||
rv = case action
|
||||
when "add-br" then {
|
||||
:name => nil,
|
||||
#:stp_enable => true,
|
||||
:skip_existing => true
|
||||
}
|
||||
when "add-port" then {
|
||||
:name => nil,
|
||||
:bridge => nil,
|
||||
#:type => "internal",
|
||||
:tag => 0,
|
||||
:trunks => [],
|
||||
:port_properties => [],
|
||||
:interface_properties => [],
|
||||
:skip_existing => true
|
||||
}
|
||||
when "add-bond" then {
|
||||
:name => nil,
|
||||
:bridge => nil,
|
||||
:interfaces => [],
|
||||
:tag => 0,
|
||||
:trunks => [],
|
||||
:properties => [],
|
||||
#:port_properties => [],
|
||||
#:interface_properties => [],
|
||||
:skip_existing => true
|
||||
}
|
||||
when "add-patch" then {
|
||||
:name => "unnamed", # calculated later
|
||||
:peers => [nil, nil],
|
||||
:bridges => [],
|
||||
:tags => [0, 0],
|
||||
:trunks => [],
|
||||
}
|
||||
else
|
||||
raise(Puppet::ParseError, "Unknown transformation: '#{action}'.")
|
||||
end
|
||||
# replace defaults to real parameters
|
||||
rv[:action] = action
|
||||
rv.each do |k,v|
|
||||
if trans[k]
|
||||
rv[k] = trans[k]
|
||||
end
|
||||
end
|
||||
# Check for incorrect parameters
|
||||
if not rv[:name].is_a? String
|
||||
raise(Puppet::ParseError, "Unnamed transformation: '#{action}'.")
|
||||
end
|
||||
name = rv[:name]
|
||||
if not rv[:bridge].is_a? String and not ["add-patch", "add-br"].index(action)
|
||||
raise(Puppet::ParseError, "Undefined bridge for transformation '#{action}' with name '#{name}'.")
|
||||
end
|
||||
if action == "add-patch"
|
||||
if not rv[:bridges].is_a? Array and rv[:bridges].size() != 2
|
||||
raise(Puppet::ParseError, "Transformation patch have wrong 'bridges' parameter.")
|
||||
end
|
||||
name = "patch__#{rv[:bridges][0]}__#{rv[:bridges][1]}"
|
||||
if not rv[:peers].is_a? Array and rv[:peers].size() != 2
|
||||
raise(Puppet::ParseError, "Transformation patch '#{name}' have wrong 'peers' parameter.")
|
||||
end
|
||||
rv[:name] = name
|
||||
end
|
||||
if action == "add-bond"
|
||||
if not rv[:interfaces].is_a? Array or rv[:interfaces].size() != 2
|
||||
raise(Puppet::ParseError, "Transformation bond '#{name}' have wrong 'interfaces' parameter.")
|
||||
end
|
||||
# rv[:interfaces].each do |i|
|
||||
# if
|
||||
# end
|
||||
end
|
||||
return rv
|
||||
end
|
||||
end
|
||||
|
||||
Puppet::Parser::Functions::newfunction(:generate_network_config, :type => :rvalue, :doc => <<-EOS
|
||||
This function get Hash of network interfaces and endpoints configuration
|
||||
and realized it.
|
||||
|
||||
EOS
|
||||
) do |argv|
|
||||
|
||||
def default_netmask()
|
||||
"/24"
|
||||
end
|
||||
|
||||
def create_endpoint()
|
||||
{
|
||||
:properties => {},
|
||||
:IP => []
|
||||
}
|
||||
end
|
||||
|
||||
if argv.size != 0
|
||||
raise(Puppet::ParseError, "generate_network_config(): Wrong number of arguments.")
|
||||
end
|
||||
|
||||
config_hash = L23network::Scheme.get()
|
||||
if config_hash.nil?
|
||||
raise(Puppet::ParseError, "get_network_role_property(...): You must call prepare_network_config(...) first!")
|
||||
end
|
||||
|
||||
# define internal puppet parameters for creating resources
|
||||
res_factory = {
|
||||
:br => { :name_of_resource => 'l23network::l2::bridge' },
|
||||
:port => { :name_of_resource => 'l23network::l2::port' },
|
||||
:bond => { :name_of_resource => 'l23network::l2::bond' },
|
||||
:patch => { :name_of_resource => 'l23network::l2::patch' },
|
||||
:ifconfig=> { :name_of_resource => 'l23network::l3::ifconfig' }
|
||||
}
|
||||
res_factory.each do |k, v|
|
||||
if v[:name_of_resource].index('::')
|
||||
# operate by Define
|
||||
res_factory[k][:resource] = lookuptype(v[:name_of_resource].downcase()) # may be find_definition(k.downcase())
|
||||
res_factory[k][:type_of_resource] = :define
|
||||
else
|
||||
# operate by custom Type
|
||||
res_factory[k][:resource] = Puppet::Type.type(v[:name_of_resource].to_sym())
|
||||
res_factory[k][:type_of_resource] = :type
|
||||
end
|
||||
end
|
||||
|
||||
# collect interfaces and endpoints
|
||||
endpoints = {}
|
||||
born_ports = []
|
||||
config_hash[:interfaces].each do |int_name, int_properties|
|
||||
int_name = int_name.to_sym()
|
||||
endpoints[int_name] = create_endpoint()
|
||||
born_ports.insert(-1, int_name)
|
||||
end
|
||||
config_hash[:endpoints].each do |e_name, e_properties|
|
||||
e_name = e_name.to_sym()
|
||||
if not endpoints[e_name]
|
||||
endpoints[e_name] = create_endpoint()
|
||||
end
|
||||
e_properties.each do |k,v|
|
||||
if k.to_sym() == :IP
|
||||
if !(v.is_a?(Array) || ['none','dhcp',nil].include?(v))
|
||||
raise(Puppet::ParseError, "generate_network_config(): IP field for endpoint '#{e_name}' must be array of IP addresses, 'dhcp' or 'none'.")
|
||||
elsif ['none','dhcp',nil].include?(v)
|
||||
endpoints[e_name][:IP].insert(-1, v ? v : 'none')
|
||||
else
|
||||
v.each do |ip|
|
||||
begin
|
||||
iip = IPAddr.new(ip)
|
||||
endpoints[e_name][:IP].insert(-1, ip)
|
||||
rescue
|
||||
raise(Puppet::ParseError, "generate_network_config(): IP address '#{ip}' for endpoint '#{e_name}' wrong!.")
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
endpoints[e_name][:properties][k.to_sym()] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# execute transformations
|
||||
# todo: if provider="lnx" execute transformations for LNX bridges
|
||||
transformation_success = []
|
||||
previous = nil
|
||||
config_hash[:transformations].each do |t|
|
||||
action = t[:action].strip()
|
||||
if action.start_with?('add-')
|
||||
action = t[:action][4..-1].to_sym()
|
||||
else
|
||||
action = t[:action].to_sym()
|
||||
end
|
||||
|
||||
trans = L23network.sanitize_transformation(t)
|
||||
resource = res_factory[action][:resource]
|
||||
p_resource = Puppet::Parser::Resource.new(
|
||||
res_factory[action][:name_of_resource],
|
||||
trans[:name],
|
||||
:scope => self,
|
||||
:source => resource
|
||||
)
|
||||
trans.select{|k,v| k != :action}.each do |k,v|
|
||||
p_resource.set_parameter(k,v)
|
||||
end
|
||||
p_resource.set_parameter(:require, [previous]) if previous
|
||||
resource.instantiate_resource(self, p_resource)
|
||||
compiler.add_resource(self, p_resource)
|
||||
transformation_success.insert(-1, "#{t[:action].strip()}(#{trans[:name]})")
|
||||
born_ports.insert(-1, trans[:name].to_sym()) if action != :patch
|
||||
previous = p_resource.to_s
|
||||
end
|
||||
|
||||
# check for all in endpoints are in interfaces or born by transformation
|
||||
config_hash[:endpoints].each do |e_name, e_properties|
|
||||
if not born_ports.index(e_name.to_sym())
|
||||
raise(Puppet::ParseError, "generate_network_config(): Endpoint '#{e_name}' not found in interfaces or transformations result.")
|
||||
end
|
||||
end
|
||||
# execute interfaces and endpoints
|
||||
# may be in future we will move interfaces before transformations
|
||||
endpoints.each do |endpoint_name, endpoint_body|
|
||||
# create resource
|
||||
resource = res_factory[:ifconfig][:resource]
|
||||
p_resource = Puppet::Parser::Resource.new(
|
||||
res_factory[:ifconfig][:name_of_resource],
|
||||
endpoint_name,
|
||||
:scope => self,
|
||||
:source => resource
|
||||
)
|
||||
p_resource.set_parameter(:interface, endpoint_name)
|
||||
# set ipaddresses
|
||||
if endpoint_body[:IP].empty?
|
||||
p_resource.set_parameter(:ipaddr, 'none')
|
||||
elsif ['none','dhcp'].index(endpoint_body[:IP][0])
|
||||
p_resource.set_parameter(:ipaddr, endpoint_body[:IP][0])
|
||||
else
|
||||
ipaddrs = []
|
||||
endpoint_body[:IP].each do |i|
|
||||
if i =~ /\/\d+$/
|
||||
ipaddrs.insert(-1, i)
|
||||
else
|
||||
ipaddrs.insert(-1, "#{i}#{default_netmask()}")
|
||||
end
|
||||
end
|
||||
p_resource.set_parameter(:ipaddr, ipaddrs)
|
||||
end
|
||||
#set another (see L23network::l3::ifconfig DOC) parametres
|
||||
endpoint_body[:properties].each do |k,v|
|
||||
p_resource.set_parameter(k,v)
|
||||
end
|
||||
p_resource.set_parameter(:require, [previous]) if previous
|
||||
resource.instantiate_resource(self, p_resource)
|
||||
compiler.add_resource(self, p_resource)
|
||||
transformation_success.insert(-1, "endpoint(#{endpoint_name})")
|
||||
previous = p_resource.to_s
|
||||
end
|
||||
|
||||
return transformation_success.join(" -> ")
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,99 @@
|
|||
require 'ipaddr'
|
||||
begin
|
||||
require 'puppet/parser/functions/lib/prepare_cidr.rb'
|
||||
rescue LoadError => e
|
||||
# puppet apply does not add module lib directories to the $LOAD_PATH (See
|
||||
# #4248). It should (in the future) but for the time being we need to be
|
||||
# defensive which is what this rescue block is doing.
|
||||
rb_file = File.join(File.dirname(__FILE__),'lib','prepare_cidr.rb')
|
||||
load rb_file if File.exists?(rb_file) or raise e
|
||||
end
|
||||
begin
|
||||
require 'puppet/parser/functions/lib/l23network_scheme.rb'
|
||||
rescue LoadError => e
|
||||
# puppet apply does not add module lib directories to the $LOAD_PATH (See
|
||||
# #4248). It should (in the future) but for the time being we need to be
|
||||
# defensive which is what this rescue block is doing.
|
||||
rb_file = File.join(File.dirname(__FILE__),'lib','l23network_scheme.rb')
|
||||
load rb_file if File.exists?(rb_file) or raise e
|
||||
end
|
||||
|
||||
Puppet::Parser::Functions::newfunction(:get_network_role_property, :type => :rvalue, :doc => <<-EOS
|
||||
This function get get network the network_role name and mode --
|
||||
and return information about network role.
|
||||
|
||||
ex: get_network_role_property('admin', 'interface')
|
||||
|
||||
You can use following modes:
|
||||
interface -- network interface for the network_role
|
||||
ipaddr -- IP address for the network_role
|
||||
cidr -- CIDR-notated IP addr and mask for the network_role
|
||||
netmask -- string, contains dotted nemmask
|
||||
ipaddr_netmask_pair -- list of ipaddr and netmask
|
||||
|
||||
EOS
|
||||
) do |argv|
|
||||
if argv.size == 2
|
||||
mode = argv[1].to_s().upcase()
|
||||
else
|
||||
raise(Puppet::ParseError, "get_network_role_property(...): Wrong number of arguments.")
|
||||
end
|
||||
|
||||
cfg = L23network::Scheme.get()
|
||||
File.open("/tmp/L23network_scheme.yaml", 'w'){ |file| file.write cfg.to_yaml() }
|
||||
if cfg.nil?
|
||||
raise(Puppet::ParseError, "get_network_role_property(...): You must call prepare_network_config(...) first!")
|
||||
end
|
||||
|
||||
network_role = argv[0].to_sym()
|
||||
|
||||
if !cfg[:roles] || !cfg[:endpoints] || cfg[:roles].class.to_s() != "Hash" || cfg[:endpoints].class.to_s() != "Hash"
|
||||
raise(Puppet::ParseError, "get_network_role_property(...): Invalid cfg_hash format.")
|
||||
end
|
||||
|
||||
# search interface for role
|
||||
interface = cfg[:roles][network_role]
|
||||
if !interface
|
||||
raise(Puppet::ParseError, "get_network_role_property(...): Undefined network_role '#{network_role}'.")
|
||||
end
|
||||
|
||||
# get endpoint configuration hash for interface
|
||||
ep = cfg[:endpoints][interface.to_sym()]
|
||||
if !ep
|
||||
raise(Puppet::ParseError, "get_network_role_property(...): Can't find interface '#{interface}' in endpoints for network_role '#{network_role}'.")
|
||||
end
|
||||
|
||||
if mode == 'INTERFACE'
|
||||
return interface.to_s
|
||||
end
|
||||
|
||||
case ep[:IP].class().to_s()
|
||||
when "Array"
|
||||
ipaddr_cidr = ep[:IP][0] ? ep[:IP][0] : nil
|
||||
when "String"
|
||||
#raise(Puppet::ParseError, "get_network_role_property(cfg_hash, role_name): Can't determine dynamic or empty IP address for endpoint '#{interface}' (#{ep[:IP]}).")
|
||||
ipaddr_cidr = nil
|
||||
else
|
||||
raise(Puppet::ParseError, "get_network_role_property(...): invalid IP address for endpoint '#{interface}'.")
|
||||
end
|
||||
|
||||
if ipaddr_cidr == nil
|
||||
return nil
|
||||
end
|
||||
|
||||
case mode
|
||||
when 'CIDR'
|
||||
return ipaddr_cidr
|
||||
when 'NETMASK'
|
||||
return IPAddr.new('255.255.255.255').mask(prepare_cidr(ipaddr_cidr)[1]).to_s()
|
||||
when 'IPADDR'
|
||||
return prepare_cidr(ipaddr_cidr)[0].to_s()
|
||||
when 'IPADDR_NETMASK_PAIR'
|
||||
return prepare_cidr(ipaddr_cidr)[0].to_s(), IPAddr.new('255.255.255.255').mask(prepare_cidr(ipaddr_cidr)[1]).to_s()
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,67 @@
|
|||
module L23network
|
||||
|
||||
def self.process_array4keys(aa)
|
||||
rv = []
|
||||
aa.each do |v|
|
||||
if v.is_a? Hash
|
||||
rv.insert(-1, self.sanitize_keys_in_hash(v))
|
||||
elsif v.is_a? Array
|
||||
rv.insert(-1, self.process_array4keys(v))
|
||||
else
|
||||
rv.insert(-1, v)
|
||||
end
|
||||
end
|
||||
return rv
|
||||
end
|
||||
def self.sanitize_keys_in_hash(hh)
|
||||
rv = {}
|
||||
hh.each do |k, v|
|
||||
#info("xx>>#{k}--#{k.to_sym}<<")
|
||||
if v.is_a? Hash
|
||||
rv[k.to_sym] = self.sanitize_keys_in_hash(v)
|
||||
elsif v.is_a? Array
|
||||
rv[k.to_sym] = self.process_array4keys(v)
|
||||
else
|
||||
rv[k.to_sym] = v
|
||||
end
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
|
||||
def self.process_array4bool(aa)
|
||||
rv = []
|
||||
aa.each do |v|
|
||||
if v.is_a? Hash
|
||||
rv.insert(-1, self.sanitize_bool_in_hash(v))
|
||||
elsif v.is_a? Array
|
||||
rv.insert(-1, self.process_array4bool(v))
|
||||
else
|
||||
rv.insert(-1, v)
|
||||
end
|
||||
end
|
||||
return rv
|
||||
end
|
||||
def self.sanitize_bool_in_hash(hh)
|
||||
rv = {}
|
||||
hh.each do |k, v|
|
||||
if v.is_a? String or v.is_a? Symbol
|
||||
rv[k] = case v.upcase()
|
||||
when 'TRUE', :TRUE then true
|
||||
when 'FALSE', :FALSE then false
|
||||
when 'NONE', :NONE, 'NULL', :NULL, 'NIL', :NIL, 'NILL', :NILL then nil
|
||||
else v
|
||||
end
|
||||
elsif v.is_a? Hash
|
||||
rv[k] = self.sanitize_bool_in_hash(v)
|
||||
elsif v.is_a? Array
|
||||
rv[k] = self.process_array4bool(v)
|
||||
else
|
||||
rv[k] = v
|
||||
end
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,11 @@
|
|||
module L23network
|
||||
class Scheme
|
||||
def self.set=(v)
|
||||
@network_scheme_hash = v
|
||||
end
|
||||
def self.get
|
||||
@network_scheme_hash
|
||||
end
|
||||
end
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -1,16 +1,17 @@
|
|||
def prepare_cidr(cidr)
|
||||
if ! cidr.is_a?(String)
|
||||
if !cidr.is_a?(String)
|
||||
raise(Puppet::ParseError, "Can't recognize IP address in non-string data.")
|
||||
end
|
||||
|
||||
re_groups = /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/(\d{1,2})$/.match(cidr)
|
||||
if ! re_groups or re_groups[2].to_i > 32
|
||||
if !re_groups or re_groups[2].to_i > 32
|
||||
raise(Puppet::ParseError, "cidr_to_ipaddr(): Wrong CIDR: '#{cidr}'.")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
for octet in re_groups[1].split('.')
|
||||
raise(Puppet::ParseError, "cidr_to_ipaddr(): Wrong CIDR: '#{cidr}'.") if octet.to_i > 255
|
||||
end
|
||||
|
||||
|
||||
return re_groups[1], re_groups[2].to_i
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,38 @@
|
|||
begin
|
||||
require 'puppet/parser/functions/lib/l23network_scheme.rb'
|
||||
rescue LoadError => e
|
||||
# puppet apply does not add module lib directories to the $LOAD_PATH (See
|
||||
# #4248). It should (in the future) but for the time being we need to be
|
||||
# defensive which is what this rescue block is doing.
|
||||
rb_file = File.join(File.dirname(__FILE__),'lib','l23network_scheme.rb')
|
||||
load rb_file if File.exists?(rb_file) or raise e
|
||||
end
|
||||
begin
|
||||
require 'puppet/parser/functions/lib/hash_tools.rb'
|
||||
rescue LoadError => e
|
||||
# puppet apply does not add module lib directories to the $LOAD_PATH (See
|
||||
# #4248). It should (in the future) but for the time being we need to be
|
||||
# defensive which is what this rescue block is doing.
|
||||
rb_file = File.join(File.dirname(__FILE__),'lib','hash_tools.rb')
|
||||
load rb_file if File.exists?(rb_file) or raise e
|
||||
end
|
||||
|
||||
module Puppet::Parser::Functions
|
||||
newfunction(:prepare_network_config, :doc => <<-EOS
|
||||
This function get Hash, and prepare it for using for network configuration.
|
||||
|
||||
You must call this function as early as possible. It do nothing, only stored protected
|
||||
sanitized network config for usind later.
|
||||
EOS
|
||||
) do |argv|
|
||||
if argv.size != 1
|
||||
raise(Puppet::ParseError, "prepare_network_config(hash): Wrong number of arguments.")
|
||||
end
|
||||
cfg_hash = argv[0]
|
||||
Puppet::Parser::Functions.autoloader.loadall
|
||||
rv = L23network.sanitize_bool_in_hash(L23network.sanitize_keys_in_hash(cfg_hash))
|
||||
L23network::Scheme.set=rv
|
||||
return true
|
||||
end
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,27 @@
|
|||
begin
|
||||
require 'puppet/parser/functions/lib/hash_tools.rb'
|
||||
rescue LoadError => e
|
||||
# puppet apply does not add module lib directories to the $LOAD_PATH (See
|
||||
# #4248). It should (in the future) but for the time being we need to be
|
||||
# defensive which is what this rescue block is doing.
|
||||
rb_file = File.join(File.dirname(__FILE__),'lib','hash_tools.rb')
|
||||
load rb_file if File.exists?(rb_file) or raise e
|
||||
end
|
||||
|
||||
module Puppet::Parser::Functions
|
||||
newfunction(:sanitize_bool_in_hash, :type => :rvalue, :doc => <<-EOS
|
||||
This function get Hash, recursive convert string implementation
|
||||
of true, false, none, null, nil to Puppet/Ruby-specific
|
||||
types.
|
||||
|
||||
EOS
|
||||
) do |argv|
|
||||
if argv.size != 1
|
||||
raise(Puppet::ParseError, "sanitize_bool_in_hash(hash): Wrong number of arguments.")
|
||||
end
|
||||
|
||||
return L23network.sanitize_bool_in_hash(argv[0])
|
||||
end
|
||||
end
|
||||
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -4,21 +4,21 @@ Puppet::Type.type(:l2_ovs_bond).provide(:ovs) do
|
|||
:appctl => "/usr/bin/ovs-appctl"
|
||||
)
|
||||
|
||||
def _exists(bond)
|
||||
def _exists?(bond)
|
||||
begin
|
||||
appctl('bond/show', bond)
|
||||
return true
|
||||
true
|
||||
rescue Puppet::ExecutionFailure
|
||||
return false
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def exists?
|
||||
_exists(@resource[:bond])
|
||||
_exists?(@resource[:bond])
|
||||
end
|
||||
|
||||
def create
|
||||
if _exists(@resource[:bond])
|
||||
if _exists?(@resource[:bond])
|
||||
msg = "Bond '#{@resource[:bond]}' already exists"
|
||||
if @resource[:skip_existing]
|
||||
notice("#{msg}, skip creating.")
|
||||
|
@ -27,15 +27,23 @@ Puppet::Type.type(:l2_ovs_bond).provide(:ovs) do
|
|||
end
|
||||
end
|
||||
|
||||
bond_create_cmd = ['add-bond', @resource[:bridge], @resource[:bond]] + @resource[:ports]
|
||||
if ! @resource[:properties].empty?
|
||||
bond_create_cmd += @resource[:properties]
|
||||
bond_properties = @resource[:properties]
|
||||
if @resource[:tag] > 0
|
||||
bond_properties.insert(-1, "tag=#{@resource[:tag]}")
|
||||
end
|
||||
if not @resource[:trunks].empty?
|
||||
bond_properties.insert(-1, "trunks=[#{@resource[:trunks].join(',')}]")
|
||||
end
|
||||
|
||||
bond_create_cmd = ['add-bond', @resource[:bridge], @resource[:bond]] + @resource[:interfaces]
|
||||
if ! bond_properties.empty?
|
||||
bond_create_cmd += bond_properties
|
||||
end
|
||||
begin
|
||||
vsctl(bond_create_cmd)
|
||||
rescue Puppet::ExecutionFailure => error
|
||||
notice(">>>#{bond_create_cmd.join(',')}<<<")
|
||||
fail("Can't create bond '#{@resource[:bond]}' (ports: #{@resource[:ports].join(',')}) for bridge '#{@resource[:bridge]}'.\n#{error}")
|
||||
fail("Can't create bond '#{@resource[:bond]}' (interfaces: #{@resource[:interfaces].join(',')}) for bridge '#{@resource[:bridge]}'.\n#{error}")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
Puppet::Type.type(:l2_ovs_patch).provide(:ovs) do
|
||||
optional_commands(
|
||||
:vsctl => "/usr/bin/ovs-vsctl",
|
||||
:appctl => "/usr/bin/ovs-appctl"
|
||||
)
|
||||
|
||||
def get_names()
|
||||
# result always contains array of two elements
|
||||
# get_names()[i-1] always returns neighbor's name
|
||||
#
|
||||
rv = []
|
||||
i = 0
|
||||
for peer in @resource[:peers]
|
||||
if peer == nil
|
||||
rv.insert(-1, "#{@resource[:bridges][i]}--#{@resource[:bridges][i-1]}")
|
||||
else
|
||||
rv.insert(-1, peer)
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
#todo: chect tags, trunks and bridge names
|
||||
return rv
|
||||
end
|
||||
|
||||
def _exists?(interface)
|
||||
rv = true
|
||||
begin
|
||||
result = vsctl('get', 'interface', "#{interface}", 'type')
|
||||
rv = false if result.strip() != 'patch'
|
||||
rescue Puppet::ExecutionFailure
|
||||
rv = false
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
def exists?
|
||||
for name in get_names()
|
||||
return false if not _exists?(name)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
def create()
|
||||
names = get_names()
|
||||
i = 0
|
||||
for name in names
|
||||
# tag and trunks for port
|
||||
port_properties = [] #@resource[:port_properties]
|
||||
tag = @resource[:tags][i]
|
||||
if tag > 0
|
||||
port_properties.insert(-1, "tag=#{tag}")
|
||||
end
|
||||
if not @resource[:trunks].empty?
|
||||
port_properties.insert(-1, "trunks=[#{@resource[:trunks].join(',')}]")
|
||||
end
|
||||
#todo: kill before create if need
|
||||
cmd = ['add-port', @resource[:bridges][i], name]
|
||||
cmd.concat(port_properties)
|
||||
cmd.concat(['--', 'set', 'interface', name, 'type=patch'])
|
||||
begin
|
||||
vsctl(cmd)
|
||||
rescue Puppet::ExecutionFailure => errmsg
|
||||
raise Puppet::ExecutionFailure, "Can't create patch '#{name}':\n#{errmsg}"
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
i = 0
|
||||
for name in names
|
||||
begin
|
||||
vsctl('set', 'interface', name, "options:peer=#{names[i-1]}")
|
||||
rescue Puppet::ExecutionFailure => errmsg
|
||||
raise Puppet::ExecutionFailure, "Can't connect patch '#{name}' to '#{names[i-1]}':\n#{errmsg}"
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
def destroy()
|
||||
names = get_names()
|
||||
i = 0
|
||||
for name in names
|
||||
begin
|
||||
vsctl('del-port', @resource[:bridges][i], name)
|
||||
rescue Puppet::ExecutionFailure => error
|
||||
raise Puppet::ExecutionFailure, "Can't remove patch '#{name}' from bridge '#{@resource[:bridges][i]}':\n#{error}"
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
end
|
|
@ -16,16 +16,23 @@ Puppet::Type.type(:l2_ovs_port).provide(:ovs) do
|
|||
rescue Puppet::ExecutionFailure
|
||||
# pass
|
||||
end
|
||||
# tag and trunks for port
|
||||
port_properties = @resource[:port_properties]
|
||||
if @resource[:tag] > 0
|
||||
port_properties.insert(-1, "tag=#{@resource[:tag]}")
|
||||
end
|
||||
if not @resource[:trunks].empty?
|
||||
port_properties.insert(-1, "trunks=[#{@resource[:trunks].join(',')}]")
|
||||
end
|
||||
# Port create begins from definition brodge and port
|
||||
cmd = [@resource[:bridge], @resource[:interface]]
|
||||
# add port properties (k/w) to command line
|
||||
if @resource[:port_properties]
|
||||
for option in @resource[:port_properties]
|
||||
cmd += [option]
|
||||
if not port_properties.empty?
|
||||
for option in port_properties
|
||||
cmd.insert(-1, option)
|
||||
end
|
||||
end
|
||||
# set interface type
|
||||
#TODO: implement type=>patch sintax as type=>'patch:peer-name'
|
||||
if @resource[:type] and @resource[:type].to_s != ''
|
||||
tt = "type=" + @resource[:type].to_s
|
||||
cmd += ['--', "set", "Interface", @resource[:interface], tt]
|
||||
|
|
|
@ -15,16 +15,16 @@ Puppet::Type.newtype(:l2_ovs_bond) do
|
|||
end
|
||||
end
|
||||
|
||||
newparam(:ports) do
|
||||
desc "List of ports that will be added to the bond"
|
||||
newparam(:interfaces) do
|
||||
desc "List of interfaces that will be added to the bond"
|
||||
#
|
||||
validate do |val|
|
||||
if not val.is_a?(Array)
|
||||
fail("Ports parameter must be an array (not #{val.class}).")
|
||||
fail("Interfaces parameter must be an array (not #{val.class}).")
|
||||
end
|
||||
for port in val
|
||||
if not port =~ /^[a-z][0-9a-z\.\-\_]*[0-9a-z]$/
|
||||
fail("Invalid port name: '#{port}'")
|
||||
for ii in val
|
||||
if not ii =~ /^[a-z][0-9a-z\.\-\_]*[0-9a-z]$/
|
||||
fail("Invalid port name: '#{ii}'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -50,6 +50,47 @@ Puppet::Type.newtype(:l2_ovs_bond) do
|
|||
end
|
||||
end
|
||||
|
||||
newparam(:tag) do
|
||||
defaultto(0)
|
||||
desc "802.1q tag"
|
||||
validate do |val|
|
||||
if not (val.is_a?(Integer) or val.is_a?(String))
|
||||
fail("tag must be an integer (not #{val.class}).")
|
||||
end
|
||||
v = val.to_i
|
||||
if v < 0 or v > 4094
|
||||
fail("tag must be an integer in 2..4094 interval")
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
val.to_i
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:trunks) do
|
||||
defaultto([])
|
||||
desc "Array of trunks id, for configure port in trunk mode"
|
||||
validate do |val|
|
||||
if not (val.is_a?(Array) or val.is_a?(String) or val.is_a?(Integer)) # String need for array with one element. it's a puppet's feature
|
||||
fail("trunks must be an array (not #{val.class}).")
|
||||
end
|
||||
end
|
||||
|
||||
munge do |val|
|
||||
if val.is_a?(String)
|
||||
[val.to_i]
|
||||
elsif val.is_a?(Integer)
|
||||
if val >= 0 and val < 4095
|
||||
[val]
|
||||
else
|
||||
[]
|
||||
end
|
||||
else
|
||||
val
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
autorequire(:l2_ovs_bridge) do
|
||||
[self[:bridge]]
|
||||
end
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
Puppet::Type.newtype(:l2_ovs_patch) do
|
||||
@doc = "Manage a Open vSwitch patch between two bridges"
|
||||
desc @doc
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:name) # workarround for following error:
|
||||
# Error 400 on SERVER: Could not render to pson: undefined method `merge' for []:Array
|
||||
# http://projects.puppetlabs.com/issues/5220
|
||||
|
||||
newparam(:bridges) do
|
||||
desc "Array of bridges that will be connected"
|
||||
#
|
||||
validate do |val|
|
||||
if not (val.is_a?(Array) and val.size() == 2)
|
||||
fail("Must be an array of two bridge names")
|
||||
end
|
||||
if not (val[0].is_a?(String) and val[1].is_a?(String))
|
||||
fail("Bridge names must have be a string.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:peers) do
|
||||
defaultto([nil,nil])
|
||||
desc "List of names that will be used for naming patches at it's ends."
|
||||
#
|
||||
validate do |val|
|
||||
if not (val.is_a?(Array) and val.size() == 2)
|
||||
fail("Must be an array of two bridge names")
|
||||
end
|
||||
for i in val
|
||||
if not (i.is_a?(String) or i == nil)
|
||||
fail("Peer names must have be a string.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# newparam(:skip_existing) do
|
||||
# defaultto(false)
|
||||
# desc "Allow to skip existing bond"
|
||||
# end
|
||||
|
||||
newparam(:tags) do
|
||||
defaultto([0,0])
|
||||
desc "Array of 802.1q tag for ends."
|
||||
#
|
||||
validate do |val|
|
||||
if not (val.is_a?(Array) and val.size() == 2)
|
||||
fail("Must be an array of integers")
|
||||
end
|
||||
for i in val
|
||||
if not i.is_a?(Integer)
|
||||
fail("802.1q tags must have be a integer.")
|
||||
end
|
||||
if i < 0 or i > 4094
|
||||
fail("Wrong 802.1q tag. Tag must be an integer in 2..4094 interval")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:trunks) do
|
||||
defaultto([])
|
||||
desc "Array of trunks id, for configure patch's ends as ports in trunk mode"
|
||||
#
|
||||
validate do |val|
|
||||
if not (val.is_a?(Array) or val.is_a?(Integer)) # Integer need for array with one element. it's a puppet's feature
|
||||
fail("Must be an array (not #{val.class}).")
|
||||
end
|
||||
if val.is_a?(Array)
|
||||
for i in val
|
||||
if not (i.to_i >= 0 and i.to_i <= 4094)
|
||||
fail("Wrong trunk. Tag must be an integer in 2..4094 interval")
|
||||
end
|
||||
end
|
||||
else
|
||||
if not (val >= 0 and val <= 4094)
|
||||
fail("Wrong trunk. Tag must be an integer in 2..4094 interval")
|
||||
end
|
||||
end
|
||||
end
|
||||
#
|
||||
munge do |val|
|
||||
if val.is_a?(Integer)
|
||||
[val]
|
||||
else
|
||||
val
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
autorequire(:l2_ovs_bridge) do
|
||||
self[:bridges]
|
||||
end
|
||||
end
|
|
@ -44,6 +44,13 @@ Puppet::Type.newtype(:l2_ovs_port) do
|
|||
fail("port_properties must be an array (not #{val.class}).")
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
if val.is_a?(String)
|
||||
[val]
|
||||
else
|
||||
val
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:interface_properties) do
|
||||
|
@ -54,6 +61,54 @@ Puppet::Type.newtype(:l2_ovs_port) do
|
|||
fail("interface_properties must be an array (not #{val.class}).")
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
if val.is_a?(String)
|
||||
[val]
|
||||
else
|
||||
val
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:tag) do
|
||||
defaultto(0)
|
||||
desc "802.1q tag"
|
||||
validate do |val|
|
||||
if not (val.is_a?(Integer) or val.is_a?(String))
|
||||
fail("tag must be an integer (not #{val.class}).")
|
||||
end
|
||||
v = val.to_i
|
||||
if v < 0 or v > 4094
|
||||
fail("tag must be an integer in 2..4094 interval")
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
val.to_i
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:trunks) do
|
||||
defaultto([])
|
||||
desc "Array of trunks id, for configure port in trunk mode"
|
||||
validate do |val|
|
||||
if not (val.is_a?(Array) or val.is_a?(String) or val.is_a?(Integer)) # String need for array with one element. it's a puppet's feature
|
||||
fail("trunks must be an array (not #{val.class}).")
|
||||
end
|
||||
end
|
||||
|
||||
munge do |val|
|
||||
if val.is_a?(String)
|
||||
[val.to_i]
|
||||
elsif val.is_a?(Integer)
|
||||
if val >= 0 and val < 4095
|
||||
[val]
|
||||
else
|
||||
[]
|
||||
end
|
||||
else
|
||||
val
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
autorequire(:l2_ovs_bridge) do
|
||||
|
|
|
@ -10,8 +10,15 @@
|
|||
# [*bridge*]
|
||||
# Bridge that will contain this bond.
|
||||
#
|
||||
# [*ports*]
|
||||
# List of ports in this bond.
|
||||
# [*interfaces*]
|
||||
# List of interfaces in this bond.
|
||||
#
|
||||
# [*tag*]
|
||||
# Specify 802.1q tag for result bond. If need.
|
||||
#
|
||||
# [*trunks*]
|
||||
# Specify array of 802.1q tags if need configure bond in trunk mode.
|
||||
# Define trunks => [0] if you need pass only untagged traffic.
|
||||
#
|
||||
# [*skip_existing*]
|
||||
# If this bond already exists it will be ignored without any errors.
|
||||
|
@ -19,21 +26,34 @@
|
|||
#
|
||||
define l23network::l2::bond (
|
||||
$bridge,
|
||||
$ports,
|
||||
$interfaces = undef,
|
||||
$ports = undef, # deprecated, must be used interfaces
|
||||
$bond = $name,
|
||||
$properties = [],
|
||||
$tag = 0,
|
||||
$trunks = [],
|
||||
$ensure = present,
|
||||
$skip_existing = false,
|
||||
$skip_existing = false
|
||||
) {
|
||||
if ! $::l23network::l2::use_ovs {
|
||||
fail('You must enable Open vSwitch by setting the l23network::l2::use_ovs to true.')
|
||||
}
|
||||
|
||||
|
||||
if $interfaces {
|
||||
$r_interfaces = $interfaces
|
||||
} elsif $ports {
|
||||
$r_interfaces = $ports
|
||||
} else {
|
||||
fail("You must specify 'interfaces' property for this bond.")
|
||||
}
|
||||
|
||||
if ! defined (L2_ovs_bond["$bond"]) {
|
||||
l2_ovs_bond { "$bond" :
|
||||
ports => $ports,
|
||||
interfaces => $r_interfaces,
|
||||
ensure => $ensure,
|
||||
bridge => $bridge,
|
||||
tag => $tag,
|
||||
trunks => $trunks,
|
||||
properties => $properties,
|
||||
skip_existing => $skip_existing,
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
# == Define: l23network::l2::patch
|
||||
#
|
||||
# Connect two open vSwitch bridges by virtual patch-cord.
|
||||
#
|
||||
# === Parameters
|
||||
# [*bridges*]
|
||||
# Bridges that will be connected.
|
||||
#
|
||||
# [*peers*]
|
||||
# Patch port names for both bridges. must be array of two strings.
|
||||
#
|
||||
# [*tags*]
|
||||
# Specify 802.1q tag for each end of patchcord. Must be array of 2 integers.
|
||||
# Default [0,0] -- untagged
|
||||
#
|
||||
# [*trunks*]
|
||||
# Specify array of 802.1q tags (identical for both ends) if need configure patch in trunk mode.
|
||||
# Define trunks => [0] if you need pass only untagged traffic.
|
||||
# by default -- undefined.
|
||||
#
|
||||
# [*skip_existing*]
|
||||
# If this patch already exists it will be ignored without any errors.
|
||||
# Must be true or false.
|
||||
#
|
||||
define l23network::l2::patch (
|
||||
$bridges,
|
||||
$peers = [undef,undef],
|
||||
$tags = [0, 0],
|
||||
$trunks = [],
|
||||
$ensure = present,
|
||||
) {
|
||||
if ! $::l23network::l2::use_ovs {
|
||||
fail('You must enable Open vSwitch by setting the l23network::l2::use_ovs to true.')
|
||||
}
|
||||
|
||||
# Architecture limitation.
|
||||
# We can't create more one patch between same bridges.
|
||||
#$patch = "${bridges[0]}_${tags[0]}--${bridges[1]}_${tags[1]}"
|
||||
$patch = "${bridges[0]}--${bridges[1]}"
|
||||
|
||||
if ! defined (L2_ovs_patch["$patch"]) {
|
||||
l2_ovs_patch { "$patch" :
|
||||
bridges => $bridges,
|
||||
peers => $peers,
|
||||
tags => $tags,
|
||||
trunks => $trunks,
|
||||
ensure => $ensure
|
||||
}
|
||||
Service<| title == 'openvswitch-service' |> -> L2_ovs_patch["$patch"]
|
||||
}
|
||||
}
|
|
@ -17,6 +17,13 @@
|
|||
# the port with default behavior.
|
||||
# (see http://openvswitch.org/cgi-bin/ovsman.cgi?page=utilities%2Fovs-vsctl.8)
|
||||
#
|
||||
# [*tag*]
|
||||
# Specify 802.1q tag for result bond. If need.
|
||||
#
|
||||
# [*trunks*]
|
||||
# Specify array of 802.1q tags if need configure bond in trunk mode.
|
||||
# Define trunks => [0] if you need pass only untagged traffic.
|
||||
#
|
||||
# [*skip_existing*]
|
||||
# If this port already exists it will be ignored without any errors.
|
||||
# Must be true or false.
|
||||
|
@ -29,19 +36,23 @@ define l23network::l2::port (
|
|||
$interface_properties = [],
|
||||
$ensure = present,
|
||||
$skip_existing = false,
|
||||
$tag = 0,
|
||||
$trunks = [],
|
||||
) {
|
||||
if ! $::l23network::l2::use_ovs {
|
||||
fail('You must enable Open vSwitch by setting the l23network::l2::use_ovs to true.')
|
||||
}
|
||||
|
||||
|
||||
if ! defined (L2_ovs_port[$port]) {
|
||||
l2_ovs_port { $port :
|
||||
ensure => $ensure,
|
||||
bridge => $bridge,
|
||||
type => $type,
|
||||
port_properties => $port_properties,
|
||||
interface_properties => $interface_properties,
|
||||
skip_existing => $skip_existing,
|
||||
tag => $tag,
|
||||
trunks => $trunks,
|
||||
port_properties => $port_properties,
|
||||
interface_properties => $interface_properties,
|
||||
skip_existing => $skip_existing
|
||||
}
|
||||
Service<| title == 'openvswitch-service' |> -> L2_ovs_port[$port]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
require 'spec_helper'
|
||||
begin
|
||||
require 'puppet/parser/functions/lib/l23network_scheme.rb'
|
||||
rescue LoadError => e
|
||||
# puppet apply does not add module lib directories to the $LOAD_PATH (See
|
||||
# #4248). It should (in the future) but for the time being we need to be
|
||||
# defensive which is what this rescue block is doing.
|
||||
rb_file = File.join(File.dirname(__FILE__),'lib','l23network_scheme.rb')
|
||||
load rb_file if File.exists?(rb_file) or raise e
|
||||
end
|
||||
|
||||
|
||||
describe 'generate_network_config' do
|
||||
let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
|
||||
# before(:each) do
|
||||
# L23network::Scheme.set = {
|
||||
# :endpoints => {
|
||||
# :eth0 => {:IP => 'dhcp'},
|
||||
# :"br-ex" => {
|
||||
# :gateway => '10.1.3.1',
|
||||
# :IP => ['10.1.3.11/24'],
|
||||
# },
|
||||
# :"br-mgmt" => { :IP => ['10.20.1.11/25'] },
|
||||
# :"br-storage" => { :IP => ['192.168.1.2/24'] },
|
||||
# :"br-prv" => { :IP => 'none' },
|
||||
# },
|
||||
# :roles => {
|
||||
# :management => 'br-mgmt',
|
||||
# :private => 'br-prv',
|
||||
# :ex => 'br-ex',
|
||||
# :storage => 'br-storage',
|
||||
# :admin => 'eth0',
|
||||
# },
|
||||
# }
|
||||
# end
|
||||
|
||||
it 'should exist' do
|
||||
Puppet::Parser::Functions.function('generate_network_config').should == 'function_generate_network_config'
|
||||
end
|
||||
|
||||
# it 'should convert string-boolean values to boolean' do
|
||||
# should run.with_params({
|
||||
# :s_true => 'true',
|
||||
# :s_false => 'false',
|
||||
# :s_none => 'none',
|
||||
# :s_null => 'null',
|
||||
# :s_nil => 'nil',
|
||||
# :s_nill => 'nill',
|
||||
# }).and_return({
|
||||
# :s_true => true,
|
||||
# :s_false => false,
|
||||
# :s_none => nil,
|
||||
# :s_null => nil,
|
||||
# :s_nil => nil,
|
||||
# :s_nill => nil,
|
||||
# })
|
||||
# end
|
||||
|
||||
# it 'should convert UP-sace string-boolean values to boolean' do
|
||||
# should run.with_params({
|
||||
# :s_true => 'TRUE',
|
||||
# :s_false => 'FALSE',
|
||||
# :s_none => 'NONE',
|
||||
# :s_null => 'NULL',
|
||||
# :s_nil => 'NIL',
|
||||
# :s_nill => 'NILL',
|
||||
# }).and_return({
|
||||
# :s_true => true,
|
||||
# :s_false => false,
|
||||
# :s_none => nil,
|
||||
# :s_null => nil,
|
||||
# :s_nil => nil,
|
||||
# :s_nill => nil,
|
||||
# })
|
||||
# end
|
||||
|
||||
# it 'should convert reccursive hashes' do
|
||||
# should run.with_params({
|
||||
# :bool_hash => {
|
||||
# :str => 'aaa',
|
||||
# :int => 123,
|
||||
# :array => [111,222,333],
|
||||
# :hash => {
|
||||
# :str => 'aaa',
|
||||
# :int => 123,
|
||||
# :array => [111,222,333],
|
||||
# :a_sbool => ['true', 'nil', 'false'],
|
||||
# :a_bool => [true, nil, false],
|
||||
# :hash => {
|
||||
# :str => 'aaa',
|
||||
# :int => 123,
|
||||
# :array => [111,222,333],
|
||||
# :a_sbool => ['true', 'nil', 'false'],
|
||||
# :a_bool => [true, nil, false],
|
||||
# },
|
||||
# },
|
||||
# :a_sbool => ['true', 'nil', 'false'],
|
||||
# :a_bool => [true, nil, false],
|
||||
# },
|
||||
# :bool_hash => {
|
||||
# :t => true,
|
||||
# :f => false,
|
||||
# :n => nil
|
||||
# },
|
||||
# }).and_return({
|
||||
# :bool_hash => {
|
||||
# :str => 'aaa',
|
||||
# :int => 123,
|
||||
# :array => [111,222,333],
|
||||
# :hash => {
|
||||
# :str => 'aaa',
|
||||
# :int => 123,
|
||||
# :array => [111,222,333],
|
||||
# :a_sbool => [true, nil, false],
|
||||
# :a_bool => [true, nil, false],
|
||||
# :hash => {
|
||||
# :str => 'aaa',
|
||||
# :int => 123,
|
||||
# :array => [111,222,333],
|
||||
# :a_sbool => [true, nil, false],
|
||||
# :a_bool => [true, nil, false],
|
||||
# },
|
||||
# },
|
||||
# :a_sbool => [true, nil, false],
|
||||
# :a_bool => [true, nil, false],
|
||||
# },
|
||||
# :bool_hash => {
|
||||
# :t => true,
|
||||
# :f => false,
|
||||
# :n => nil
|
||||
# },
|
||||
# })
|
||||
# end
|
||||
|
||||
# it 'should convert array of hashes' do
|
||||
# should run.with_params({ :array => [
|
||||
# {:aaa=>1,"aaa"=>11, :bbb=>2,'bbb'=>12, :ccc=>3,'ccc'=>3},
|
||||
# {:t=>'true','tt'=>'true', :f=>'false','ff'=>'false', :n=>'nil','nn'=>'nil'},
|
||||
# {
|
||||
# :s_true => 'true',
|
||||
# :s_false => 'false',
|
||||
# :s_none => 'none',
|
||||
# :s_null => 'null',
|
||||
# :s_nil => 'nil',
|
||||
# :s_nill => 'nill',
|
||||
# },
|
||||
# {
|
||||
# :s_true => 'TRUE',
|
||||
# :s_false => 'FALSE',
|
||||
# :s_none => 'NONE',
|
||||
# :s_null => 'NULL',
|
||||
# :s_nil => 'NIL',
|
||||
# :s_nill => 'NILL',
|
||||
# },
|
||||
# ]}).and_return({ :array => [
|
||||
# {:aaa=>1,"aaa"=>11, :bbb=>2,'bbb'=>12, :ccc=>3,'ccc'=>3},
|
||||
# {:t=>true,'tt'=>true, :f=>false,'ff'=>false, :n=>nil,'nn'=>nil},
|
||||
# {
|
||||
# :s_true => true,
|
||||
# :s_false => false,
|
||||
# :s_none => nil,
|
||||
# :s_null => nil,
|
||||
# :s_nil => nil,
|
||||
# :s_nill => nil,
|
||||
# },
|
||||
# {
|
||||
# :s_true => true,
|
||||
# :s_false => false,
|
||||
# :s_none => nil,
|
||||
# :s_null => nil,
|
||||
# :s_nil => nil,
|
||||
# :s_nill => nil,
|
||||
# },
|
||||
# ]})
|
||||
# end
|
||||
|
||||
# it 'should throw an error' do
|
||||
# lambda {
|
||||
# scope.function_merge_arrays(['xxx'])
|
||||
# }.should(raise_error(Puppet::ParseError))
|
||||
# end
|
||||
|
||||
end
|
||||
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,78 @@
|
|||
require 'spec_helper'
|
||||
begin
|
||||
require 'puppet/parser/functions/lib/l23network_scheme.rb'
|
||||
rescue LoadError => e
|
||||
# puppet apply does not add module lib directories to the $LOAD_PATH (See
|
||||
# #4248). It should (in the future) but for the time being we need to be
|
||||
# defensive which is what this rescue block is doing.
|
||||
rb_file = File.join(File.dirname(__FILE__),'lib','l23network_scheme.rb')
|
||||
load rb_file if File.exists?(rb_file) or raise e
|
||||
end
|
||||
|
||||
|
||||
describe 'get_network_role_property' do
|
||||
let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
|
||||
before(:each) do
|
||||
L23network::Scheme.set = {
|
||||
:endpoints => {
|
||||
:eth0 => {:IP => 'dhcp'},
|
||||
:"br-ex" => {
|
||||
:gateway => '10.1.3.1',
|
||||
:IP => ['10.1.3.11/24'],
|
||||
},
|
||||
:"br-mgmt" => { :IP => ['10.20.1.11/25'] },
|
||||
:"br-storage" => { :IP => ['192.168.1.2/24'] },
|
||||
:"br-prv" => { :IP => 'none' },
|
||||
},
|
||||
:roles => {
|
||||
:management => 'br-mgmt',
|
||||
:private => 'br-prv',
|
||||
:ex => 'br-ex',
|
||||
:storage => 'br-storage',
|
||||
:admin => 'eth0',
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
it 'should exist' do
|
||||
Puppet::Parser::Functions.function('get_network_role_property').should == 'function_get_network_role_property'
|
||||
end
|
||||
|
||||
it 'should return interface name for "private" network role' do
|
||||
should run.with_params('private', 'interface').and_return('br-prv')
|
||||
end
|
||||
|
||||
it 'should raise for non-existing role name' do
|
||||
should run.with_params('not_exist', 'interface').and_raise_error(Puppet::ParseError)
|
||||
end
|
||||
|
||||
it 'should return ip address for "management" network role' do
|
||||
should run.with_params('management', 'ipaddr').and_return('10.20.1.11')
|
||||
end
|
||||
|
||||
it 'should return cidr-notated ip address for "management" network role' do
|
||||
should run.with_params('management', 'cidr').and_return('10.20.1.11/25')
|
||||
end
|
||||
|
||||
it 'should return netmask for "management" network role' do
|
||||
should run.with_params('management', 'netmask').and_return('255.255.255.128')
|
||||
end
|
||||
|
||||
it 'should return ip address and netmask for "management" network role' do
|
||||
should run.with_params('management', 'ipaddr_netmask_pair').and_return(['10.20.1.11','255.255.255.128'])
|
||||
end
|
||||
|
||||
it 'should return NIL for "admin" network role' do
|
||||
should run.with_params('admin', 'netmask').and_return(nil)
|
||||
end
|
||||
it 'should return NIL for "admin" network role' do
|
||||
should run.with_params('admin', 'ipaddr').and_return(nil)
|
||||
end
|
||||
it 'should return NIL for "admin" network role' do
|
||||
should run.with_params('admin', 'cidr').and_return(nil)
|
||||
end
|
||||
it 'should return NIL for "admin" network role' do
|
||||
should run.with_params('admin', 'ipaddr_netmask_pair').and_return(nil)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,154 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'sanitize_bool_in_hash' do
|
||||
let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
|
||||
|
||||
it 'should exist' do
|
||||
Puppet::Parser::Functions.function('sanitize_bool_in_hash').should == 'function_sanitize_bool_in_hash'
|
||||
end
|
||||
|
||||
it 'should convert string-boolean values to boolean' do
|
||||
should run.with_params({
|
||||
:s_true => 'true',
|
||||
:s_false => 'false',
|
||||
:s_none => 'none',
|
||||
:s_null => 'null',
|
||||
:s_nil => 'nil',
|
||||
:s_nill => 'nill',
|
||||
}).and_return({
|
||||
:s_true => true,
|
||||
:s_false => false,
|
||||
:s_none => nil,
|
||||
:s_null => nil,
|
||||
:s_nil => nil,
|
||||
:s_nill => nil,
|
||||
})
|
||||
end
|
||||
|
||||
it 'should convert UP-sace string-boolean values to boolean' do
|
||||
should run.with_params({
|
||||
:s_true => 'TRUE',
|
||||
:s_false => 'FALSE',
|
||||
:s_none => 'NONE',
|
||||
:s_null => 'NULL',
|
||||
:s_nil => 'NIL',
|
||||
:s_nill => 'NILL',
|
||||
}).and_return({
|
||||
:s_true => true,
|
||||
:s_false => false,
|
||||
:s_none => nil,
|
||||
:s_null => nil,
|
||||
:s_nil => nil,
|
||||
:s_nill => nil,
|
||||
})
|
||||
end
|
||||
|
||||
it 'should convert reccursive hashes' do
|
||||
should run.with_params({
|
||||
:bool_hash => {
|
||||
:str => 'aaa',
|
||||
:int => 123,
|
||||
:array => [111,222,333],
|
||||
:hash => {
|
||||
:str => 'aaa',
|
||||
:int => 123,
|
||||
:array => [111,222,333],
|
||||
:a_sbool => ['true', 'nil', 'false'],
|
||||
:a_bool => [true, nil, false],
|
||||
:hash => {
|
||||
:str => 'aaa',
|
||||
:int => 123,
|
||||
:array => [111,222,333],
|
||||
:a_sbool => ['true', 'nil', 'false'],
|
||||
:a_bool => [true, nil, false],
|
||||
},
|
||||
},
|
||||
:a_sbool => ['true', 'nil', 'false'],
|
||||
:a_bool => [true, nil, false],
|
||||
},
|
||||
:bool_hash => {
|
||||
:t => true,
|
||||
:f => false,
|
||||
:n => nil
|
||||
},
|
||||
}).and_return({
|
||||
:bool_hash => {
|
||||
:str => 'aaa',
|
||||
:int => 123,
|
||||
:array => [111,222,333],
|
||||
:hash => {
|
||||
:str => 'aaa',
|
||||
:int => 123,
|
||||
:array => [111,222,333],
|
||||
:a_sbool => [true, nil, false],
|
||||
:a_bool => [true, nil, false],
|
||||
:hash => {
|
||||
:str => 'aaa',
|
||||
:int => 123,
|
||||
:array => [111,222,333],
|
||||
:a_sbool => [true, nil, false],
|
||||
:a_bool => [true, nil, false],
|
||||
},
|
||||
},
|
||||
:a_sbool => [true, nil, false],
|
||||
:a_bool => [true, nil, false],
|
||||
},
|
||||
:bool_hash => {
|
||||
:t => true,
|
||||
:f => false,
|
||||
:n => nil
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
it 'should convert array of hashes' do
|
||||
should run.with_params({ :array => [
|
||||
{:aaa=>1,"aaa"=>11, :bbb=>2,'bbb'=>12, :ccc=>3,'ccc'=>3},
|
||||
{:t=>'true','tt'=>'true', :f=>'false','ff'=>'false', :n=>'nil','nn'=>'nil'},
|
||||
{
|
||||
:s_true => 'true',
|
||||
:s_false => 'false',
|
||||
:s_none => 'none',
|
||||
:s_null => 'null',
|
||||
:s_nil => 'nil',
|
||||
:s_nill => 'nill',
|
||||
},
|
||||
{
|
||||
:s_true => 'TRUE',
|
||||
:s_false => 'FALSE',
|
||||
:s_none => 'NONE',
|
||||
:s_null => 'NULL',
|
||||
:s_nil => 'NIL',
|
||||
:s_nill => 'NILL',
|
||||
},
|
||||
]}).and_return({ :array => [
|
||||
{:aaa=>1,"aaa"=>11, :bbb=>2,'bbb'=>12, :ccc=>3,'ccc'=>3},
|
||||
{:t=>true,'tt'=>true, :f=>false,'ff'=>false, :n=>nil,'nn'=>nil},
|
||||
{
|
||||
:s_true => true,
|
||||
:s_false => false,
|
||||
:s_none => nil,
|
||||
:s_null => nil,
|
||||
:s_nil => nil,
|
||||
:s_nill => nil,
|
||||
},
|
||||
{
|
||||
:s_true => true,
|
||||
:s_false => false,
|
||||
:s_none => nil,
|
||||
:s_null => nil,
|
||||
:s_nil => nil,
|
||||
:s_nill => nil,
|
||||
},
|
||||
]})
|
||||
end
|
||||
|
||||
it 'should throw an error' do
|
||||
lambda {
|
||||
scope.function_merge_arrays(['xxx'])
|
||||
}.should(raise_error(Puppet::ParseError))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -21,7 +21,8 @@ stage {'glance-image':
|
|||
require => Stage['main'],
|
||||
}
|
||||
|
||||
|
||||
# ANC: Advanced network configuration. Discovering.
|
||||
#prepare_network_config(parsejson($::network_scheme))
|
||||
|
||||
if $nodes != undef {
|
||||
$nodes_hash = parsejson($nodes)
|
||||
|
@ -135,6 +136,17 @@ class node_netconfig (
|
|||
l23network::l3::ifconfig {$fixed_interface: ipaddr=>'none' }
|
||||
}
|
||||
|
||||
# ANC: Advanced network configuration. Creating resources.
|
||||
#class advanced_node_netconfig {
|
||||
# $sdn = generate_network_config()
|
||||
# notify {"SDN: ${sdn}": }
|
||||
#}
|
||||
#
|
||||
#class {'advanced_node_netconfig':
|
||||
# stage => 'netconfig'
|
||||
#}
|
||||
|
||||
|
||||
case $::operatingsystem {
|
||||
'redhat' : {
|
||||
$queue_provider = 'qpid'
|
||||
|
|
Loading…
Reference in New Issue