New L23network implementation.
Squized 33 patchsets, all changes detailed described in following blueprint. Can't be merged without corresponded changes in Nailgun part. Fuel-CI: disable Change-Id: I3d7bf070ef6fc42ef82c14f30780672084db5e71 Blueprint: refactor-l23-linux-bridges
This commit is contained in:
parent
879910023c
commit
f83970f017
|
@ -0,0 +1,18 @@
|
|||
# Fact: l23_os
|
||||
#
|
||||
# Purpose: Return return os_name for using inside l23 network module
|
||||
#
|
||||
Facter.add(:l23_os) do
|
||||
setcode do
|
||||
case Facter.value(:osfamily)
|
||||
when /(?i)darwin/
|
||||
'osx'
|
||||
when /(?i)debian/
|
||||
#todo: separate upstart and systemd based
|
||||
'ubuntu'
|
||||
when /(?i)redhat/
|
||||
#todo: separate centos6 and centos7
|
||||
'centos6'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
module Puppet::Parser::Functions
|
||||
newfunction(:default_provider_for, :type => :rvalue, :doc => <<-EOS
|
||||
Get the default provider of a type
|
||||
EOS
|
||||
) do |argv|
|
||||
type_name = argv[0]
|
||||
fail('No type name provided!') if ! type_name
|
||||
Puppet::Type.loadall()
|
||||
type_name = type_name.capitalize.to_sym
|
||||
return 'undef' if ! Puppet::Type.const_defined? type_name
|
||||
type = Puppet::Type.const_get type_name
|
||||
provider = type.defaultprovider
|
||||
return 'undef' if ! provider
|
||||
rv = provider.name.to_s
|
||||
debug("Default provider for type '#{type_name}' is a '#{rv}'.")
|
||||
return rv
|
||||
end
|
||||
end
|
|
@ -1,9 +1,11 @@
|
|||
require 'ipaddr'
|
||||
require 'yaml'
|
||||
require 'forwardable'
|
||||
require 'puppet/parser'
|
||||
require 'puppet/parser/templatewrapper'
|
||||
require 'puppet/resource/type_collection_helper'
|
||||
require 'puppet/util/methodhelper'
|
||||
require 'puppetx/l23_utils'
|
||||
|
||||
begin
|
||||
require 'puppet/parser/functions/lib/l23network_scheme.rb'
|
||||
|
@ -18,79 +20,70 @@ end
|
|||
|
||||
|
||||
module L23network
|
||||
def self.sanitize_transformation(trans)
|
||||
action = trans[:action].downcase()
|
||||
def self.sanitize_transformation(trans, def_provider=nil)
|
||||
action = trans[:action].to_s.downcase()
|
||||
# Setup defaults
|
||||
rv = case action
|
||||
when "noop" then {
|
||||
:name => nil,
|
||||
:name => nil,
|
||||
:provider => nil
|
||||
}
|
||||
when "add-br" then {
|
||||
:name => nil,
|
||||
#:stp_enable => true,
|
||||
:skip_existing => true
|
||||
:name => nil,
|
||||
:stp => nil,
|
||||
:bpdu_forward => nil,
|
||||
# :bridge_id => nil,
|
||||
:external_ids => nil,
|
||||
# :interface_properties => nil,
|
||||
:vendor_specific => nil,
|
||||
:provider => def_provider
|
||||
}
|
||||
when "add-port" then {
|
||||
:name => nil,
|
||||
:bridge => nil,
|
||||
#:type => "internal",
|
||||
:vlan_id => 0,
|
||||
:trunks => [],
|
||||
:port_properties => [],
|
||||
:interface_properties => [],
|
||||
:skip_existing => true
|
||||
:name => nil,
|
||||
:bridge => nil,
|
||||
# :type => "internal",
|
||||
:mtu => nil,
|
||||
:ethtool => nil,
|
||||
:vlan_id => nil,
|
||||
:vlan_dev => nil,
|
||||
# :trunks => [],
|
||||
:vendor_specific => nil,
|
||||
:provider => def_provider
|
||||
}
|
||||
when "add-bond" then {
|
||||
:name => nil,
|
||||
:provider => 'ovs',
|
||||
:bridge => nil,
|
||||
:interfaces => [],
|
||||
:vlan_id => 0,
|
||||
:trunks => [],
|
||||
:properties => [],
|
||||
#:port_properties => [],
|
||||
#:interface_properties => [],
|
||||
:skip_existing => true
|
||||
:name => nil,
|
||||
:bridge => nil,
|
||||
:mtu => nil,
|
||||
:interfaces => [],
|
||||
# :vlan_id => 0,
|
||||
# :trunks => [],
|
||||
:bond_properties => nil,
|
||||
:interface_properties => nil,
|
||||
:vendor_specific => nil,
|
||||
:provider => def_provider
|
||||
}
|
||||
when "add-patch" then {
|
||||
:name => "unnamed", # calculated later
|
||||
:peers => [nil, nil],
|
||||
:bridges => [],
|
||||
:vlan_ids => [0, 0],
|
||||
:trunks => [],
|
||||
:name => "unnamed", # calculated later
|
||||
:bridges => [],
|
||||
:mtu => nil,
|
||||
:vendor_specific => nil,
|
||||
:provider => def_provider
|
||||
}
|
||||
else
|
||||
raise(Puppet::ParseError, "Unknown transformation: '#{action}'.")
|
||||
end
|
||||
# replace defaults to real parameters
|
||||
rv.map{|k,v| rv[k] = trans[k] if trans.has_key? k }
|
||||
# Validate and mahgle highly required properties. Most of properties should be validated in puppet type.
|
||||
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 !["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
|
||||
if !rv[:bridges].is_a? Array or 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) and rv[:interfaces].size() >= 2)
|
||||
raise(Puppet::ParseError, "Transformation bond '#{name}' have wrong 'interfaces' parameter.")
|
||||
end
|
||||
rv[:name] = get_patch_name(rv[:bridges]) # name for patch SHOULD be auto-generated
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
@ -109,80 +102,92 @@ Puppet::Parser::Functions::newfunction(:generate_network_config, :type => :rvalu
|
|||
|
||||
def create_endpoint()
|
||||
{
|
||||
:properties => {},
|
||||
:IP => []
|
||||
:ipaddr => []
|
||||
}
|
||||
end
|
||||
|
||||
def res_factory()
|
||||
# define internal puppet parameters for creating resources
|
||||
{
|
||||
:br => 'l23network::l2::bridge',
|
||||
:port => 'l23network::l2::port',
|
||||
:bond => 'l23network::l2::bond',
|
||||
:patch => 'l23network::l2::patch',
|
||||
:ifconfig => 'l23network::l3::ifconfig'
|
||||
}
|
||||
end
|
||||
|
||||
if argv.size != 0
|
||||
raise(Puppet::ParseError, "generate_network_config(): Wrong number of arguments.")
|
||||
end
|
||||
|
||||
config_hash = L23network::Scheme.get_config(lookupvar('l3_fqdn_hostname'))
|
||||
if config_hash.nil?
|
||||
raise(Puppet::ParseError, "get_network_role_property(...): You must call prepare_network_config(...) first!")
|
||||
raise(Puppet::ParseError, "generate_network_config(...): 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' },
|
||||
:bond_lnx => { :name_of_resource => 'l23network::l3::ifconfig' },
|
||||
: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
|
||||
# we can't imagine, that user can write in this field, but we try to convert to numeric and compare
|
||||
if config_hash[:version].to_s.to_f < 1.1
|
||||
raise(Puppet::ParseError, "generate_network_config(...): You network_scheme hash has wrong format.\nThis parser can work with v1.1 format, please convert you config.")
|
||||
end
|
||||
|
||||
default_provider = config_hash[:provider] || 'lnx'
|
||||
|
||||
# collect interfaces and endpoints
|
||||
endpoints = {}
|
||||
ifconfig_order = []
|
||||
born_ports = []
|
||||
# collect L2::port properties from 'interfaces' section
|
||||
ports_properties = {} # additional parameters from interfaces was stored here
|
||||
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)
|
||||
#endpoints[int_name] = create_endpoint()
|
||||
born_ports << int_name
|
||||
# add some of 1st level interface properties to it's config
|
||||
int_properties.each do |k,v|
|
||||
next if ! ['macaddr', 'mtu', 'ethtool'].index(k.to_s)
|
||||
endpoints[int_name][:properties][k.to_sym] = v
|
||||
ports_properties[int_name] ||= {}
|
||||
if ! int_properties.nil?
|
||||
int_properties.each do |k,v|
|
||||
if v.to_s != ''
|
||||
k = k.to_s.tr('-','_').to_sym
|
||||
ports_properties[int_name][k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
config_hash[:endpoints].each do |e_name, e_properties|
|
||||
e_name = e_name.to_sym()
|
||||
if not endpoints[e_name]
|
||||
# collect L3::ifconfig properties from 'endpoints' section
|
||||
endpoints = {}
|
||||
if config_hash[:endpoints].is_a? Hash and !config_hash[:endpoints].empty?
|
||||
config_hash[:endpoints].each do |e_name, e_properties|
|
||||
e_name = e_name.to_sym()
|
||||
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!.")
|
||||
if ! (e_properties.nil? or e_properties.empty?)
|
||||
e_properties.each do |k,v|
|
||||
k = k.to_s.tr('-','_').to_sym
|
||||
if k == :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',''].include?(v.to_s)
|
||||
# 'none' and 'dhcp' should be passed to resource not as list
|
||||
endpoints[e_name][:ipaddr] = (v.to_s == 'dhcp' ? 'dhcp' : 'none')
|
||||
else
|
||||
v.each do |ip|
|
||||
begin
|
||||
iip = IPAddr.new(ip) # validate IP address
|
||||
endpoints[e_name][:ipaddr] ||= []
|
||||
endpoints[e_name][:ipaddr] << ip
|
||||
rescue
|
||||
raise(Puppet::ParseError, "generate_network_config(): IP address '#{ip}' for endpoint '#{e_name}' wrong!.")
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
endpoints[e_name][k] = v
|
||||
end
|
||||
end
|
||||
else
|
||||
endpoints[e_name][:properties][k.to_sym()] = v
|
||||
endpoints[e_name][:ipaddr] = 'none'
|
||||
end
|
||||
end
|
||||
else
|
||||
config_hash[:endpoints] = {}
|
||||
end
|
||||
|
||||
# execute transformations
|
||||
|
@ -193,157 +198,53 @@ Puppet::Parser::Functions::newfunction(:generate_network_config, :type => :rvalu
|
|||
action = t[:action].strip()
|
||||
if action.start_with?('add-')
|
||||
action = t[:action][4..-1].to_sym()
|
||||
action_ensure = nil
|
||||
elsif action.start_with?('del-')
|
||||
action = t[:action][4..-1].to_sym()
|
||||
action_ensure = 'absent'
|
||||
else
|
||||
action = t[:action].to_sym()
|
||||
end
|
||||
|
||||
# add newly-created interface to ifconfig order
|
||||
if [:noop, :port, :br].index(action)
|
||||
if ! ifconfig_order.index(t[:name].to_sym())
|
||||
ifconfig_order.insert(-1, t[:name].to_sym())
|
||||
end
|
||||
elsif action == :bond
|
||||
t[:provider] ||= 'ovs' # default provider for Bond
|
||||
if ! t[:interfaces].is_a? Array
|
||||
raise(Puppet::ParseError, "generate_network_config(): 'add-bond' resource should has non-empty 'interfaces' list.")
|
||||
end
|
||||
if t[:provider] == 'lnx'
|
||||
if ! t[:properties].is_a? Hash
|
||||
raise(Puppet::ParseError, "generate_network_config(): 'add-bond' resource should has 'properties' hash for '#{t[:provider]}' provider.")
|
||||
else
|
||||
if t[:properties].size < 1
|
||||
raise(Puppet::ParseError, "generate_network_config(): 'add-bond' resource should has non-empty 'properties' hash for '#{t[:provider]}' provider.")
|
||||
end
|
||||
end
|
||||
elsif t[:provider] == 'ovs'
|
||||
if ! t[:properties].is_a? Array
|
||||
raise(Puppet::ParseError, "generate_network_config(): 'add-bond' resource should has 'properties' array for '#{t[:provider]}' provider.")
|
||||
else
|
||||
if t[:properties].size < 1
|
||||
raise(Puppet::ParseError, "generate_network_config(): 'add-bond' resource should has non-empty 'properties' array for '#{t[:provider]}' provider.")
|
||||
end
|
||||
end
|
||||
else
|
||||
raise(Puppet::ParseError, "generate_network_config(): 'add-bond' resource has wrong provider '#{t[:provider]}'.")
|
||||
end
|
||||
if t[:provider] == 'lnx'
|
||||
if ! ifconfig_order.index(t[:name].to_sym())
|
||||
ifconfig_order.insert(-1, t[:name].to_sym())
|
||||
end
|
||||
end
|
||||
t[:interfaces].each do |physint|
|
||||
if ! ifconfig_order.index(physint.to_sym())
|
||||
ifconfig_order.insert(-1, physint.to_sym())
|
||||
end
|
||||
if ! ifconfig_order.include? t[:name].to_sym()
|
||||
ifconfig_order << t[:name].to_sym()
|
||||
end
|
||||
end
|
||||
|
||||
next if action == :noop
|
||||
|
||||
trans = L23network.sanitize_transformation(t)
|
||||
#debug("TXX: '#{t[:name]}' => '#{t.to_yaml.gsub('!ruby/sym ',':')}'.")
|
||||
trans = L23network.sanitize_transformation(t, default_provider)
|
||||
#debug("TTT: '#{trans[:name]}' => '#{trans.to_yaml.gsub('!ruby/sym ',':')}'.")
|
||||
|
||||
# create puppet resources
|
||||
if action == :bond and t[:provider] == 'lnx'
|
||||
# Add Linux_bond-specific parameters to the ifconfig
|
||||
e_name = t[:name].to_sym
|
||||
if ! endpoints[e_name]
|
||||
endpoints[e_name] = create_endpoint()
|
||||
end
|
||||
endpoints[e_name][:properties] ||= { :ipaddr => 'none' }
|
||||
endpoints[e_name][:properties][:bond_properties] = Hash[t[:properties].map{|k,v| [k.to_s,v]}]
|
||||
born_ports.insert(-1, e_name)
|
||||
t[:interfaces].each{ |iface|
|
||||
if ! endpoints[iface.to_sym]
|
||||
endpoints[iface.to_sym] = create_endpoint()
|
||||
end
|
||||
endpoints[iface.to_sym][:properties] ||= { :ipaddr => 'none' }
|
||||
endpoints[iface.to_sym][:properties][:bond_master] = t[:name].to_s
|
||||
}
|
||||
# add port to the ovs bridge as ordinary port
|
||||
tt = Marshal.load(Marshal.dump(t))
|
||||
tt[:action] = 'add-port' # because lnx-bind is a ordinary port in OVS
|
||||
port_trans = L23network.sanitize_transformation(tt)
|
||||
resource = res_factory[:port][:resource]
|
||||
p_resource = Puppet::Parser::Resource.new(
|
||||
res_factory[:port][:name_of_resource],
|
||||
port_trans[:name],
|
||||
:scope => self,
|
||||
:source => resource
|
||||
)
|
||||
trans.select{|k,v| ! [:action, :interfaces, :properties].index(k) }.each do |k,v|
|
||||
p_resource.set_parameter(k,v)
|
||||
end
|
||||
req_list = []
|
||||
req_list.insert(-1, previous) if previous
|
||||
req_list.insert(-1, "L3_if_downup[#{tt[:name]}]")
|
||||
p_resource.set_parameter(:require, req_list)
|
||||
resource.instantiate_resource(self, p_resource)
|
||||
compiler.add_resource(self, p_resource)
|
||||
transformation_success.insert(-1, "bond-lnx_as_port(#{port_trans[:name]})")
|
||||
born_ports.insert(-1, port_trans[:name].to_sym())
|
||||
else
|
||||
# normal OVS transformation
|
||||
resource = res_factory[action][:resource]
|
||||
p_resource = Puppet::Parser::Resource.new(
|
||||
res_factory[action][:name_of_resource],
|
||||
trans[:name],
|
||||
:scope => self,
|
||||
:source => resource
|
||||
)
|
||||
|
||||
# setup trunks and vlan_splinters for phys.NIC
|
||||
if (action == :port) and config_hash[:interfaces][trans[:name].to_sym] and # does adding phys.interface?
|
||||
config_hash[:interfaces][trans[:name].to_sym][:L2] and # does this interface have L2 section
|
||||
config_hash[:interfaces][trans[:name].to_sym][:L2][:trunks] and # does this interface have TRUNKS section
|
||||
config_hash[:interfaces][trans[:name].to_sym][:L2][:trunks].is_a?(Array) and
|
||||
config_hash[:interfaces][trans[:name].to_sym][:L2][:trunks].size() > 0 # does trunks section non empty?
|
||||
Puppet.debug("Configure trunks and vlan_splinters for #{trans[:name]} (value is '#{config_hash[:interfaces][trans[:name].to_sym][:L2][:vlan_splinters]}')")
|
||||
_do_trunks = true
|
||||
if config_hash[:interfaces][trans[:name].to_sym][:L2][:vlan_splinters]
|
||||
if config_hash[:interfaces][trans[:name].to_sym][:L2][:vlan_splinters] == 'on'
|
||||
trans[:vlan_splinters] = true
|
||||
elsif config_hash[:interfaces][trans[:name].to_sym][:L2][:vlan_splinters] == 'auto'
|
||||
sp_nics = lookupvar('l2_ovs_vlan_splinters_need_for')
|
||||
Puppet.debug("l2_ovs_vlan_splinters_need_for: #{sp_nics}")
|
||||
if sp_nics and sp_nics != :undefined and sp_nics.split(',').index(trans[:name].to_s)
|
||||
Puppet.debug("enable vlan_splinters for: #{trans[:name].to_s}")
|
||||
trans[:vlan_splinters] = true
|
||||
else
|
||||
trans[:vlan_splinters] = false
|
||||
if trans[:trunks] and trans[:trunks].size() >0
|
||||
Puppet.debug("disable vlan_splinters for: #{trans[:name].to_s}. Trunks will be set to '#{trans[:trunks].join(',')}'")
|
||||
config_hash[:interfaces][trans[:name].to_sym][:L2][:trunks] = []
|
||||
else
|
||||
Puppet.debug("disable vlan_splinters for: #{trans[:name].to_s}. Trunks for this interface also disabled.")
|
||||
_do_trunks = false
|
||||
end
|
||||
end
|
||||
else
|
||||
trans[:vlan_splinters] = false
|
||||
end
|
||||
else
|
||||
trans[:vlan_splinters] = false
|
||||
end
|
||||
# add trunks list to the interface if it given
|
||||
if _do_trunks
|
||||
_trunks = [0] + trans[:trunks] + config_hash[:interfaces][trans[:name].to_sym][:L2][:trunks] # zero for pass untagged traffic
|
||||
_trunks.sort!().uniq!()
|
||||
trans[:trunks] = _trunks
|
||||
end
|
||||
Puppet.debug("Configure trunks and vlan_splinters for #{trans[:name]} done.")
|
||||
end
|
||||
|
||||
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
|
||||
if !ports_properties[trans[:name].to_sym()].nil?
|
||||
trans.merge! ports_properties[trans[:name].to_sym()]
|
||||
end
|
||||
|
||||
# create puppet resources for transformations
|
||||
resource = res_factory[action]
|
||||
resource_properties = { }
|
||||
debug("generate_network_config(): Transformation '#{trans[:name]}' will be produced as '#{trans.to_yaml.gsub('!ruby/sym ',':')}'.")
|
||||
|
||||
trans.select{|k,v| k != :action}.each do |k,v|
|
||||
if ['Hash', 'Array'].include? v.class.to_s
|
||||
resource_properties[k.to_s] = L23network.reccursive_sanitize_hash(v)
|
||||
elsif ! v.nil?
|
||||
resource_properties[k.to_s] = v
|
||||
else
|
||||
#pass
|
||||
end
|
||||
end
|
||||
|
||||
resource_properties['require'] = [previous] if previous
|
||||
function_create_resources([resource, {
|
||||
"#{trans[:name]}" => resource_properties
|
||||
}])
|
||||
transformation_success.insert(-1, "#{t[:action].strip()}(#{trans[:name]})")
|
||||
born_ports.insert(-1, trans[:name].to_sym()) if action != :patch
|
||||
previous = "#{resource}[#{trans[:name]}]"
|
||||
end
|
||||
|
||||
# check for all in endpoints are in interfaces or born by transformation
|
||||
|
@ -357,48 +258,51 @@ Puppet::Parser::Functions::newfunction(:generate_network_config, :type => :rvalu
|
|||
ifc_delta = endpoints.keys().sort() - ifconfig_order
|
||||
full_ifconfig_order = ifconfig_order + ifc_delta
|
||||
|
||||
# execute interfaces and endpoints
|
||||
# create resources for interfaces and endpoints
|
||||
# in order, defined by transformation
|
||||
full_ifconfig_order.each do |endpoint_name|
|
||||
if endpoints[endpoint_name]
|
||||
endpoint_body = endpoints[endpoint_name]
|
||||
resource_properties = { }
|
||||
|
||||
# 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
|
||||
resource = res_factory[:ifconfig]
|
||||
debug("generate_network_config(): Endpoint '#{endpoint_name}' will be created with additional properties '#{endpoints[endpoint_name].to_yaml.gsub('!ruby/sym ',':')}'.")
|
||||
# collect properties for creating endpoint resource
|
||||
endpoints[endpoint_name].each_pair do |k,v|
|
||||
if ['Hash', 'Array'].include? v.class.to_s
|
||||
resource_properties[k.to_s] = L23network.reccursive_sanitize_hash(v)
|
||||
elsif ! v.nil?
|
||||
resource_properties[k.to_s] = v
|
||||
else
|
||||
#pass
|
||||
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)
|
||||
resource_properties['require'] = [previous] if previous
|
||||
# # set ipaddresses
|
||||
# #if endpoints[endpoint_name][:IP].empty?
|
||||
# # p_resource.set_parameter(:ipaddr, 'none')
|
||||
# #elsif ['none','dhcp'].index(endpoints[endpoint_name][:IP][0])
|
||||
# # p_resource.set_parameter(:ipaddr, endpoints[endpoint_name][:IP][0])
|
||||
# #else
|
||||
# # ipaddrs = []
|
||||
# # endpoints[endpoint_name][: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
|
||||
function_create_resources([resource, {
|
||||
"#{endpoint_name}" => resource_properties
|
||||
}])
|
||||
transformation_success.insert(-1, "endpoint(#{endpoint_name})")
|
||||
previous = p_resource.to_s
|
||||
previous = "#{resource}[#{endpoint_name}]"
|
||||
end
|
||||
end
|
||||
|
||||
return transformation_success.join(" -> ")
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,15 @@
|
|||
require 'puppetx/l23_utils'
|
||||
#
|
||||
module Puppet::Parser::Functions
|
||||
newfunction(:get_pair_of_jack_names, :type => :rvalue) do |arguments|
|
||||
if !arguments.is_a? Array or arguments.size != 1 or arguments[0].size != 2
|
||||
raise(Puppet::ParseError, "get_pair_of_jack_names(): Wrong arguments given. " +
|
||||
"Should be array of two bridge names.")
|
||||
end
|
||||
|
||||
bridges = arguments[0]
|
||||
# name shouldn't depend from bridge order
|
||||
L23network.get_pair_of_jack_names(bridges)
|
||||
end
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,15 @@
|
|||
require 'puppetx/l23_utils'
|
||||
#
|
||||
module Puppet::Parser::Functions
|
||||
newfunction(:get_patch_name, :type => :rvalue) do |arguments|
|
||||
if !arguments.is_a? Array or arguments.size != 1 or arguments[0].size != 2
|
||||
raise(Puppet::ParseError, "get_patch_name(): Wrong arguments given. " +
|
||||
"Should be array of two bridge names.")
|
||||
end
|
||||
|
||||
bridges = arguments[0]
|
||||
# name shouldn't depend from bridge order
|
||||
L23network.get_patch_name(bridges)
|
||||
end
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
module Puppet::Parser::Functions
|
||||
newfunction(:get_provider_for, :type => :rvalue, :doc => <<-EOS
|
||||
Get the default provider of a type
|
||||
EOS
|
||||
) do |argv|
|
||||
type_name = argv[0]
|
||||
res_name = argv[1]
|
||||
fail('No type name provided!') if ! type_name
|
||||
Puppet::Type.loadall()
|
||||
type_name = type_name.capitalize.to_sym
|
||||
return 'undef' if ! Puppet::Type.const_defined? type_name
|
||||
type = Puppet::Type.const_get type_name
|
||||
# require 'pry'
|
||||
# binding.pry
|
||||
type.loadall()
|
||||
rv = type.instances.select{|i| i.name.to_s.downcase == res_name.to_s.downcase}.map{|j| j[:provider].to_s}
|
||||
# require 'pry'
|
||||
# binding.pry
|
||||
rv = rv[0]
|
||||
debug("Provider for '#{type_name}[#{res_name}]' is a '#{rv}'.")
|
||||
return rv
|
||||
end
|
||||
end
|
|
@ -0,0 +1,63 @@
|
|||
require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/lnx_base')
|
||||
|
||||
Puppet::Type.type(:k_mod).provide(:lnx) do
|
||||
defaultfor :osfamily => :linux
|
||||
commands :mod_load => 'modprobe',
|
||||
:ls_mod => 'lsmod',
|
||||
:mod_unload => 'rmmod'
|
||||
|
||||
|
||||
def self.prefetch(resources)
|
||||
interfaces = instances
|
||||
resources.keys.each do |name|
|
||||
if provider = interfaces.find{ |ii| ii.name == name }
|
||||
resources[name].provider = provider
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.instances
|
||||
rv = []
|
||||
ls_mod.split(/\n+/).sort.each do |line|
|
||||
name = line.split(/\s+/)[0]
|
||||
rv << new({
|
||||
:ensure => :present,
|
||||
:name => name,
|
||||
})
|
||||
end
|
||||
rv
|
||||
end
|
||||
|
||||
def exists?
|
||||
@property_hash[:ensure] == :present
|
||||
end
|
||||
|
||||
def create
|
||||
mod_load(@resource[:module])
|
||||
end
|
||||
|
||||
def destroy
|
||||
mod_unload(@resource[:module])
|
||||
end
|
||||
|
||||
def initialize(value={})
|
||||
super(value)
|
||||
@property_flush = {}
|
||||
@old_property_hash = {}
|
||||
@old_property_hash.merge! @property_hash
|
||||
end
|
||||
|
||||
# def flush
|
||||
# if @property_flush
|
||||
# debug("FLUSH properties: #{@property_flush}")
|
||||
# #
|
||||
# # FLUSH changed properties
|
||||
# # if ! @property_flush[:mtu].nil?
|
||||
# # File.open("/sys/class/net/#{@resource[:interface]}/mtu", "w") { |f| f.write(@property_flush[:mtu]) }
|
||||
# # end
|
||||
# @property_hash = resource.to_hash
|
||||
# end
|
||||
# end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,17 @@
|
|||
require 'puppetx/filemapper'
|
||||
require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/l23_stored_config_centos6')
|
||||
|
||||
Puppet::Type.type(:l23_stored_config).provide(:lnx_centos6, :parent => Puppet::Provider::L23_stored_config_centos6) do
|
||||
|
||||
include PuppetX::FileMapper
|
||||
|
||||
confine :l23_os => :centos6
|
||||
defaultfor :l23_os => :centos6
|
||||
|
||||
has_feature :provider_options
|
||||
#has_feature :hotpluggable
|
||||
|
||||
self.unlink_empty_files = true
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,26 @@
|
|||
require 'puppetx/filemapper'
|
||||
require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/l23_stored_config_ubuntu')
|
||||
|
||||
Puppet::Type.type(:l23_stored_config).provide(:lnx_ubuntu, :parent => Puppet::Provider::L23_stored_config_ubuntu) do
|
||||
|
||||
include PuppetX::FileMapper
|
||||
|
||||
defaultfor :l23_os => :ubuntu
|
||||
|
||||
has_feature :provider_options
|
||||
#has_feature :hotpluggable
|
||||
|
||||
self.unlink_empty_files = true
|
||||
|
||||
def self.check_if_provider(if_data)
|
||||
if if_data[:if_provider] == 'auto'
|
||||
if_data[:if_provider] = :lnx
|
||||
true
|
||||
else
|
||||
if_data[:if_provider] = nil
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,15 @@
|
|||
require 'puppetx/filemapper'
|
||||
require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/l23_stored_config_centos6')
|
||||
|
||||
Puppet::Type.type(:l23_stored_config).provide(:ovs_centos6, :parent => Puppet::Provider::L23_stored_config_centos6) do
|
||||
|
||||
include PuppetX::FileMapper
|
||||
|
||||
confine :l23_os => :centos6
|
||||
|
||||
has_feature :provider_options
|
||||
|
||||
self.unlink_empty_files = true
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,39 @@
|
|||
require 'puppetx/filemapper'
|
||||
require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/l23_stored_config_ubuntu')
|
||||
|
||||
Puppet::Type.type(:l23_stored_config).provide(:ovs_ubuntu, :parent => Puppet::Provider::L23_stored_config_ubuntu) do
|
||||
|
||||
include PuppetX::FileMapper
|
||||
|
||||
has_feature :provider_options
|
||||
|
||||
self.unlink_empty_files = true
|
||||
|
||||
def self.property_mappings
|
||||
rv = super
|
||||
rv.merge!({
|
||||
:onboot => 'allow-ovs'
|
||||
})
|
||||
return rv
|
||||
end
|
||||
|
||||
def self.check_if_provider(if_data)
|
||||
#((if_data[:if_provider] == 'allow-ovs') ? true : false)
|
||||
if if_data[:if_provider] == 'allow-ovs'
|
||||
if_data[:if_provider] = :ovs
|
||||
true
|
||||
else
|
||||
if_data[:if_provider] = nil
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def self.mangle__type(val)
|
||||
:ethernet
|
||||
end
|
||||
def self.unmangle__type(val)
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,65 @@
|
|||
# type for managing persistent interface config options
|
||||
# Inspired by puppet-network module. Adrien, thanks.
|
||||
|
||||
require 'puppetx/l23_utils'
|
||||
|
||||
class Puppet::Provider::L23_stored_config_base < Puppet::Provider
|
||||
|
||||
COMMENT_CHAR = '#'
|
||||
|
||||
# The valid vlan ID range is 0-4095; 4096 is out of range
|
||||
VLAN_RANGE_REGEX = %r[\d{1,3}|40[0-9][0-5]]
|
||||
|
||||
# @return [Regexp] The regular expression for interface scripts
|
||||
SCRIPT_REGEX = %r[\Aifcfg-[a-z]+[\w\d-]+(?::\d+|\.#{VLAN_RANGE_REGEX})?\Z]
|
||||
|
||||
def self.script_directory
|
||||
raise "Should be implemented in more specific class."
|
||||
end
|
||||
|
||||
class MalformedInterfacesError < Puppet::Error
|
||||
def initialize(msg = nil)
|
||||
msg = "Malformed config file; cannot instantiate stored_config resources for interface #{name}" if msg.nil?
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def self.raise_malformed
|
||||
@failed = true
|
||||
raise MalformedInterfacesError
|
||||
end
|
||||
|
||||
# Map provider instances to files based on their name
|
||||
#
|
||||
# @return [String] The path of the file for the given interface resource
|
||||
#
|
||||
# @example
|
||||
# prov = RedhatProvider.new(:name => 'eth1')
|
||||
# prov.select_file # => '/etc/sysconfig/network-scripts/ifcfg-eth1'
|
||||
#
|
||||
def select_file
|
||||
"#{self.class.script_directory}/ifcfg-#{name}"
|
||||
end
|
||||
|
||||
# Scan all files in the networking directory for interfaces
|
||||
#
|
||||
# @param script_dir [String] The path to the networking scripts, defaults to
|
||||
# {#SCRIPT_DIRECTORY}
|
||||
#
|
||||
# @return [Array<String>] All network-script config files on this machine.
|
||||
#
|
||||
# @example
|
||||
# RedhatProvider.target_files
|
||||
# # => ['/etc/sysconfig/network-scripts/ifcfg-eth0', '/etc/sysconfig/network-scripts/ifcfg-eth1']
|
||||
def self.target_files(script_dir = nil)
|
||||
script_dir ||= script_directory
|
||||
entries = Dir.entries(script_dir).select {|entry| entry.match SCRIPT_REGEX}
|
||||
entries.map {|entry| File.join(script_directory, entry)}
|
||||
end
|
||||
|
||||
def self.post_flush_hook(filename)
|
||||
File.chmod(0644, filename) if File.exist? filename
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,213 @@
|
|||
require File.join(File.dirname(__FILE__), 'l23_stored_config_base')
|
||||
|
||||
class Puppet::Provider::L23_stored_config_centos6 < Puppet::Provider::L23_stored_config_base
|
||||
|
||||
# @return [String] The path to network-script directory on redhat systems
|
||||
def self.script_directory
|
||||
"/etc/sysconfig/network-scripts"
|
||||
end
|
||||
|
||||
NAME_MAPPINGS = {
|
||||
:method => 'BOOTPROTO',
|
||||
:name => 'DEVICE',
|
||||
:onboot => 'ONBOOT',
|
||||
:mtu => 'MTU',
|
||||
:vlan_id => 'VLAN',
|
||||
:vlan_dev => 'PHYSDEV',
|
||||
:vlan_mode => 'VLAN_NAME_TYPE',
|
||||
:if_type => 'TYPE'
|
||||
}
|
||||
|
||||
# In the interface config files those fields should be written as boolean
|
||||
BOOLEAN_FIELDS = [
|
||||
:vlan_id,
|
||||
:hotplug,
|
||||
:onboot
|
||||
]
|
||||
|
||||
# This is a hook method that will be called by PuppetX::Filemapper
|
||||
#
|
||||
# @param [String] filename The path of the interfaces file being parsed
|
||||
# @param [String] contents The contents of the given file
|
||||
#
|
||||
# @return [Array<Hash<Symbol, String>>] A single element array containing
|
||||
# the key/value pairs of properties parsed from the file.
|
||||
#
|
||||
# @example
|
||||
# RedhatProvider.parse_file('/etc/sysconfig/network-scripts/ifcfg-eth0', #<String:0xdeadbeef>)
|
||||
# # => [
|
||||
# # {
|
||||
# # :name => 'eth0',
|
||||
# # :ipaddress => '169.254.0.1',
|
||||
# # :netmask => '255.255.0.0',
|
||||
# # },
|
||||
# # ]
|
||||
def self.parse_file(filename, contents)
|
||||
# Split up the file into lines
|
||||
lines = contents.split("\n")
|
||||
# Strip out all comments
|
||||
lines.map! { |line| line.sub(/#.*$/, '') }
|
||||
# Remove all blank lines
|
||||
lines.reject! { |line| line.match(/^\s*$/) }
|
||||
|
||||
pair_regex = %r/^\s*(.+?)\s*=\s*(.*)\s*$/
|
||||
|
||||
# Convert the data into key/value pairs
|
||||
pairs = lines.inject({}) do |hash, line|
|
||||
if (m = line.match pair_regex)
|
||||
key = m[1].strip
|
||||
val = m[2].strip
|
||||
hash[key] = val
|
||||
else
|
||||
raise Puppet::Error, %{#{filename} is malformed; "#{line}" did not match "#{pair_regex.to_s}"}
|
||||
end
|
||||
hash
|
||||
end
|
||||
|
||||
props = self.munge(pairs)
|
||||
props.merge!({:family => :inet})
|
||||
|
||||
debug("Resource hash for '#{props[:name]}' is '#{props}'")
|
||||
# The FileMapper mixin expects an array of providers, so we return the
|
||||
# single interface wrapped in an array
|
||||
[props]
|
||||
end
|
||||
|
||||
|
||||
def self.munge(pairs)
|
||||
props = {}
|
||||
|
||||
# Unquote all values
|
||||
pairs.each_pair do |key, val|
|
||||
if (munged = val.to_s.gsub(/['"]/, ''))
|
||||
pairs[key] = munged
|
||||
end
|
||||
end
|
||||
|
||||
# For each interface attribute that we recognize it, add the value to the
|
||||
# hash with our expected label
|
||||
NAME_MAPPINGS.merge({:nnname => 'NAME'}).each_pair do |type_name, redhat_name|
|
||||
if (val = pairs[redhat_name])
|
||||
# We've recognized a value that maps to an actual type property, delete
|
||||
# it from the pairs and copy it as an actual property
|
||||
pairs.delete(redhat_name)
|
||||
case type_name
|
||||
when /if_type/
|
||||
props[type_name] = val.downcase
|
||||
else
|
||||
props[type_name] = val
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# use :name if no :device given
|
||||
if !props[:name] and props[:nnname]
|
||||
props[:name] = props[:nnname]
|
||||
end
|
||||
props.delete(:nnname)
|
||||
|
||||
#!# # For all of the remaining values, blindly toss them into the options hash.
|
||||
#!# props[:options] = pairs if ! pairs.empty?
|
||||
|
||||
BOOLEAN_FIELDS.each do |bool_property|
|
||||
if props[bool_property]
|
||||
props[bool_property] = ! (props[bool_property] =~ /yes/i).nil?
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#todo(sv): Calculate Method
|
||||
# if ! ['bootp', 'dhcp'].include? props[:method]
|
||||
# props[:method] = 'static'
|
||||
# end
|
||||
|
||||
props
|
||||
end
|
||||
|
||||
def self.mangle__vlan_mode(val)
|
||||
if val.to_s.upcase == 'VLAN_PLUS_VID_NO_PAD'
|
||||
'vlan'
|
||||
else
|
||||
'eth'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
# Hash to file
|
||||
|
||||
def self.format_file(filename, providers)
|
||||
if providers.length == 0
|
||||
return ""
|
||||
elsif providers.length > 1
|
||||
raise Puppet::DevError, "Unable to support multiple interfaces [#{providers.map(&:name).join(',')}] in a single file #{filename}"
|
||||
end
|
||||
|
||||
provider = providers[0]
|
||||
props = {}
|
||||
|
||||
# Map everything to a flat hash
|
||||
#props = (provider.options || {})
|
||||
|
||||
NAME_MAPPINGS.keys.each do |type_name|
|
||||
val = provider.send(type_name)
|
||||
if val and val.to_s != 'absent'
|
||||
props[type_name] = val
|
||||
end
|
||||
end
|
||||
|
||||
pairs = self.unmunge(props)
|
||||
|
||||
content = pairs.inject('') do |str, (key, val)|
|
||||
str << %{#{key}=#{val}\n}
|
||||
end
|
||||
|
||||
content
|
||||
end
|
||||
|
||||
|
||||
|
||||
def self.unmunge(props)
|
||||
|
||||
pairs = {}
|
||||
|
||||
BOOLEAN_FIELDS.each do |bool_property|
|
||||
if props[bool_property]
|
||||
props[bool_property] = ((props[bool_property] == true) ? 'yes' : 'no')
|
||||
end
|
||||
end
|
||||
|
||||
NAME_MAPPINGS.each_pair do |type_name, redhat_name|
|
||||
if (val = props[type_name])
|
||||
props.delete(type_name)
|
||||
case type_name
|
||||
when /if_type/
|
||||
pairs[redhat_name] = val.capitalize
|
||||
else
|
||||
pairs[redhat_name] = val
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
pairs.merge! props
|
||||
|
||||
pairs.each_pair do |key, val|
|
||||
if val.is_a? String and val.match(/\s+/)
|
||||
pairs[key] = %{"#{val}"}
|
||||
end
|
||||
end
|
||||
|
||||
pairs
|
||||
end
|
||||
|
||||
def self.unmangle__vlan_mode(val)
|
||||
if val.to_s == 'vlan'
|
||||
'VLAN_PLUS_VID_NO_PAD'
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,334 @@
|
|||
require File.join(File.dirname(__FILE__), 'l23_stored_config_base')
|
||||
|
||||
class Puppet::Provider::L23_stored_config_ubuntu < Puppet::Provider::L23_stored_config_base
|
||||
|
||||
# @return [String] The path to network-script directory on redhat systems
|
||||
def self.script_directory
|
||||
'/etc/network/interfaces.d'
|
||||
end
|
||||
|
||||
def self.property_mappings
|
||||
{
|
||||
:if_type => 'if_type', # pseudo field, not found in config, but calculated
|
||||
:if_provider => 'if_provider', # pseudo field, not found in config, but calculated
|
||||
:method => 'method',
|
||||
:name => 'iface',
|
||||
:onboot => 'auto',
|
||||
:mtu => 'mtu',
|
||||
:bridge_ports => 'bridge_ports', # ports, members of bridge, fake property
|
||||
:bridge_stp => 'bridge_stp',
|
||||
:vlan_dev => 'vlan-raw-device',
|
||||
:ipaddr => 'address',
|
||||
# :netmask => 'netmask',
|
||||
:gateway => 'gateway',
|
||||
:gateway_metric => 'metric', # todo: rename to 'metric'
|
||||
# :dhcp_hostname => 'hostname'
|
||||
:bond_master => 'bond-master',
|
||||
:bond_slaves => 'bond-slaves',
|
||||
:bond_mode => 'bond-mode',
|
||||
:bond_miimon => 'bond-miimon',
|
||||
}
|
||||
end
|
||||
def property_mappings
|
||||
self.class.property_mappings
|
||||
end
|
||||
|
||||
# In the interface config files those fields should be written as boolean
|
||||
def self.boolean_properties
|
||||
[
|
||||
:hotplug,
|
||||
:onboot,
|
||||
:bridge_stp
|
||||
]
|
||||
end
|
||||
def boolean_properties
|
||||
self.class.boolean_properties
|
||||
end
|
||||
|
||||
def self.properties_fake
|
||||
[
|
||||
:onboot,
|
||||
:name,
|
||||
:family,
|
||||
:method,
|
||||
:if_type,
|
||||
:if_provider
|
||||
]
|
||||
end
|
||||
def properties_fake
|
||||
self.class.properties_fake
|
||||
end
|
||||
|
||||
# This is a hook method that will be called by PuppetX::Filemapper
|
||||
#
|
||||
# @param [String] filename The path of the interfaces file being parsed
|
||||
# @param [String] contents The contents of the given file
|
||||
#
|
||||
# @return [Array<Hash<Symbol, String>>] A single element array containing
|
||||
# the key/value pairs of properties parsed from the file.
|
||||
#
|
||||
# @example
|
||||
# RedhatProvider.parse_file('/etc/sysconfig/network-scripts/ifcfg-eth0', #<String:0xdeadbeef>)
|
||||
# # => [
|
||||
# # {
|
||||
# # :name => 'eth0',
|
||||
# # :ipaddress => '169.254.0.1',
|
||||
# # :netmask => '255.255.0.0',
|
||||
# # },
|
||||
# # ]
|
||||
|
||||
def self.parse_file(filename, contents)
|
||||
# WARNING!!!
|
||||
# this implementation can parce only one interface per file file format
|
||||
|
||||
# Split up the file into lines
|
||||
lines = contents.split("\n")
|
||||
# Strip out all comments
|
||||
lines.map! { |line| line.sub(/#.*$/, '') }
|
||||
# Remove all blank lines
|
||||
lines.reject! { |line| line.match(/^\s*$/) }
|
||||
|
||||
# initialize hash as predictible values
|
||||
hash = {}
|
||||
hash['auto'] = false
|
||||
hash['if_provider'] = 'none'
|
||||
hash['if_type'] = :ethernet
|
||||
dirty_iface_name = nil
|
||||
if (m = filename.match(%r/ifcfg-(\S+)$/))
|
||||
# save iface name from file name. One will be used if iface name not defined inside config.
|
||||
dirty_iface_name = m[1].strip
|
||||
end
|
||||
|
||||
# Convert the data into key/value pairs
|
||||
pair_regex = %r/^\s*([\w+\-]+)\s+(.*)\s*$/
|
||||
lines.each do |line|
|
||||
if (m = line.match(pair_regex))
|
||||
key = m[1].strip
|
||||
val = m[2].strip
|
||||
case key
|
||||
# Ubuntu has non-linear config format. Some options should be calculated evristically
|
||||
when /(auto|allow-ovs)/
|
||||
hash[$1] = true
|
||||
hash['if_provider'] = $1 # temporary store additional data for self.check_if_provider
|
||||
if ! hash.has_key?('iface')
|
||||
# setup iface name if it not given in iface directive
|
||||
mm = val.split(/\s+/)
|
||||
hash['iface'] = mm[0]
|
||||
end
|
||||
when /iface/
|
||||
mm = val.split(/\s+/)
|
||||
hash['iface'] = mm[0]
|
||||
hash['method'] = mm[2]
|
||||
# if hash['iface'] =~ /^br.*/i
|
||||
# # todo(sv): Make more powerful methodology for recognizind Bridges.
|
||||
# hash['if_type'] = :bridge
|
||||
# end
|
||||
when /bridge-ports/
|
||||
hash['if_type'] = :bridge
|
||||
hash[key] = val
|
||||
when /bond-(slaves|mode)/
|
||||
hash['if_type'] = :bond
|
||||
hash[key] = val
|
||||
else
|
||||
hash[key] = val
|
||||
end
|
||||
else
|
||||
raise Puppet::Error, %{#{filename} is malformed; "#{line}" did not match "#{pair_regex.to_s}"}
|
||||
end
|
||||
hash
|
||||
end
|
||||
# set mostly low-priority interface name if not given in config file
|
||||
hash['iface'] ||= dirty_iface_name
|
||||
|
||||
props = self.mangle_properties(hash)
|
||||
props.merge!({:family => :inet})
|
||||
|
||||
# The FileMapper mixin expects an array of providers, so we return the
|
||||
# single interface wrapped in an array
|
||||
rv = (self.check_if_provider(props) ? [props] : [])
|
||||
debug("parse_file('#{filename}'): #{props.inspect}")
|
||||
rv
|
||||
end
|
||||
|
||||
def self.check_if_provider(if_data)
|
||||
raise Puppet::Error, "self.check_if_provider(if_data) Should be implemented in more specific class."
|
||||
end
|
||||
|
||||
def self.mangle_properties(pairs)
|
||||
props = {}
|
||||
|
||||
# Unquote all values
|
||||
pairs.each_pair do |key, val|
|
||||
next if ! (val.is_a? String or val.is_a? Symbol)
|
||||
if (munged = val.to_s.gsub(/['"]/, ''))
|
||||
pairs[key] = munged
|
||||
end
|
||||
end
|
||||
|
||||
# For each interface attribute that we recognize it, add the value to the
|
||||
# hash with our expected label
|
||||
property_mappings.each_pair do |type_name, in_config_name|
|
||||
if (val = pairs[in_config_name])
|
||||
# We've recognized a value that maps to an actual type property, delete
|
||||
# it from the pairs and copy it as an actual property
|
||||
pairs.delete(in_config_name)
|
||||
mangle_method_name="mangle__#{type_name}"
|
||||
if self.respond_to?(mangle_method_name)
|
||||
rv = self.send(mangle_method_name, val)
|
||||
else
|
||||
rv = val
|
||||
end
|
||||
props[type_name] = rv if ! [nil, :absent].include? rv
|
||||
end
|
||||
end
|
||||
|
||||
#!# # For all of the remaining values, blindly toss them into the options hash.
|
||||
#!# props[:options] = pairs if ! pairs.empty?
|
||||
|
||||
boolean_properties.each do |bool_property|
|
||||
if props[bool_property]
|
||||
props[bool_property] = ! (props[bool_property] =~ /^\s*(yes|on)\s*$/i).nil?
|
||||
else
|
||||
props[bool_property] = :absent
|
||||
end
|
||||
end
|
||||
|
||||
props
|
||||
end
|
||||
|
||||
def self.mangle__method(val)
|
||||
val.to_sym
|
||||
end
|
||||
|
||||
def self.mangle__if_type(val)
|
||||
val.downcase.to_sym
|
||||
end
|
||||
|
||||
def self.mangle__gateway_metric(val)
|
||||
(val.to_i == 0 ? :absent : val.to_i)
|
||||
end
|
||||
|
||||
def self.mangle__bridge_ports(val)
|
||||
val.split(/[\s,]+/).sort
|
||||
end
|
||||
|
||||
def self.mangle__bond_slaves(val)
|
||||
val.split(/[\s,]+/).sort
|
||||
end
|
||||
|
||||
###
|
||||
# Hash to file
|
||||
|
||||
def self.format_file(filename, providers)
|
||||
if providers.length == 0
|
||||
return ""
|
||||
elsif providers.length > 1
|
||||
raise Puppet::DevError, "Unable to support multiple interfaces [#{providers.map(&:name).join(',')}] in a single file #{filename}"
|
||||
end
|
||||
|
||||
content = []
|
||||
provider = providers[0]
|
||||
|
||||
# Add onboot interfaces
|
||||
if provider.onboot
|
||||
content << "#{property_mappings[:onboot]} #{provider.name}"
|
||||
end
|
||||
|
||||
# Add iface header
|
||||
content << "iface #{provider.name} inet #{provider.method}"
|
||||
|
||||
# Map everything to a flat hash
|
||||
#props = (provider.options || {})
|
||||
props = {}
|
||||
|
||||
property_mappings.keys.select{|v| ! properties_fake.include?(v)}.each do |type_name|
|
||||
#binding.pry
|
||||
#debug("ZZZZZZZ: #{property_mappings}")
|
||||
val = provider.send(type_name)
|
||||
if val and val.to_s != 'absent'
|
||||
props[type_name] = val
|
||||
end
|
||||
end
|
||||
|
||||
debug("format_file('#{filename}')::properties: #{props.inspect}")
|
||||
pairs = self.unmangle_properties(props)
|
||||
|
||||
pairs.each_pair do |key, val|
|
||||
content << "#{key} #{val}" if ! val.nil?
|
||||
end
|
||||
|
||||
debug("format_file('#{filename}')::content: #{content.inspect}")
|
||||
content << ''
|
||||
content.join("\n")
|
||||
end
|
||||
|
||||
|
||||
def self.unmangle_properties(props)
|
||||
pairs = {}
|
||||
|
||||
boolean_properties.each do |bool_property|
|
||||
if ! props[bool_property].nil?
|
||||
props[bool_property] = ((props[bool_property].to_s.to_sym == :true) ? 'yes' : 'no')
|
||||
end
|
||||
end
|
||||
|
||||
property_mappings.each_pair do |type_name, in_config_name|
|
||||
if (val = props[type_name])
|
||||
props.delete(type_name)
|
||||
mangle_method_name="unmangle__#{type_name}"
|
||||
if self.respond_to?(mangle_method_name)
|
||||
rv = self.send(mangle_method_name, val)
|
||||
else
|
||||
rv = val
|
||||
end
|
||||
pairs[in_config_name] = rv if ! [nil, :absent].include? rv
|
||||
end
|
||||
end
|
||||
|
||||
#pairs.merge! props
|
||||
|
||||
# pairs.each_pair do |key, val|
|
||||
# if val.is_a? String and val.match(/\s+/)
|
||||
# debug("==[#{key.to_sym}]==[\"#{val}\"]==")
|
||||
# pairs[key.to_sym] = "\"#{val}\""
|
||||
# end
|
||||
# end
|
||||
|
||||
pairs
|
||||
end
|
||||
|
||||
def self.unmangle__if_type(val)
|
||||
# in Debian family interface config file don't contains declaration of interface type
|
||||
nil
|
||||
end
|
||||
|
||||
def self.unmangle__gateway_metric(val)
|
||||
(val.to_i == 0 ? :absent : val.to_i)
|
||||
end
|
||||
|
||||
def self.unmangle__bridge_ports(val)
|
||||
if val.size < 1 or [:absent, :undef].include? Array(val)[0].to_sym
|
||||
nil
|
||||
else
|
||||
val.sort.join(' ')
|
||||
end
|
||||
end
|
||||
|
||||
def self.unmangle__bond_master(val)
|
||||
if [:none, :absent, :undef].include? val.to_sym
|
||||
nil
|
||||
else
|
||||
val
|
||||
end
|
||||
end
|
||||
|
||||
def self.unmangle__bond_slaves(val)
|
||||
if val.size < 1 or [:absent, :undef].include? Array(val)[0].to_sym
|
||||
nil
|
||||
else
|
||||
val.sort.join(' ')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,621 @@
|
|||
require 'puppetx/l23_utils'
|
||||
require 'puppetx/l23_ethtool_name_commands_mapping'
|
||||
require 'yaml'
|
||||
|
||||
class Puppet::Provider::L2_base < Puppet::Provider
|
||||
|
||||
def self.prefetch(resources)
|
||||
interfaces = instances
|
||||
resources.keys.each do |name|
|
||||
if provider = interfaces.find{ |ii| ii.name == name }
|
||||
resources[name].provider = provider
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def self.iface_exist?(iface)
|
||||
File.exist? "/sys/class/net/#{iface}"
|
||||
end
|
||||
|
||||
def self.get_lnx_vlan_interfaces
|
||||
# returns hash, that contains ports (interfaces) configuration.
|
||||
# i.e {
|
||||
# eth0.101 => { :vlan_dev => 'eth0', :vlan_id => 101, vlan_mode => 'eth' },
|
||||
# vlan102 => { :vlan_dev => 'eth0', :vlan_id => 102, vlan_mode => 'vlan' },
|
||||
# }
|
||||
#
|
||||
vlan_ifaces = {}
|
||||
rc_c = /([\w+\.\-]+)\s*\|\s*(\d+)\s*\|\s*([\w+\-]+)/
|
||||
File.open("/proc/net/vlan/config", "r").each do |line|
|
||||
if (rv=line.match(rc_c))
|
||||
vlan_ifaces[rv[1]] = {
|
||||
:vlan_dev => rv[3],
|
||||
:vlan_id => rv[2],
|
||||
:vlan_mode => (rv[1].match('\.').nil? ? 'vlan' : 'eth' )
|
||||
}
|
||||
end
|
||||
end
|
||||
return vlan_ifaces
|
||||
end
|
||||
|
||||
def self.get_lnx_ports
|
||||
# returns hash, that contains ports (interfaces) configuration.
|
||||
# i.e {
|
||||
# eth0 => { :mtu => 1500, :if_type => :ethernet, port_type => lnx:eth:unremovable },
|
||||
# }
|
||||
#
|
||||
# 'unremovable' flag for port_type means, that this port is a more complicated thing,
|
||||
# than just a port and can't be removed just as port. For example you can't remove bond
|
||||
# as port. You should remove it as bond.
|
||||
#
|
||||
port = {}
|
||||
#
|
||||
# parse 802.1q vlan interfaces from /proc
|
||||
vlan_ifaces = self.get_lnx_vlan_interfaces()
|
||||
# Fetch information about interfaces, visible in network namespace from /sys/class/net
|
||||
interfaces = Dir['/sys/class/net/*'].select{ |f| File.symlink? f}
|
||||
interfaces.each do |if_dir|
|
||||
if_name = if_dir.split('/')[-1]
|
||||
port[if_name] = {
|
||||
:name => if_name,
|
||||
:port_type => [],
|
||||
:onboot => self.get_iface_state(if_name),
|
||||
:ethtool => nil,
|
||||
:mtu => File.open("#{if_dir}/mtu").read.chomp.to_i,
|
||||
:provider => (if_name == 'ovs-system') ? 'ovs' : 'lnx' ,
|
||||
}
|
||||
# determine port_type for this iface
|
||||
if File.directory? "#{if_dir}/bonding"
|
||||
# This interface is a baster of bond, get bonding properties
|
||||
port[if_name][:slaves] = File.open("#{if_dir}/bonding/slaves").read.chomp.strip.split(/\s+/).sort
|
||||
port[if_name][:port_type] << 'bond' << 'unremovable'
|
||||
elsif File.directory? "#{if_dir}/bridge" and File.directory? "#{if_dir}/brif"
|
||||
# this interface is a bridge, get bridge properties
|
||||
port[if_name][:slaves] = Dir["#{if_dir}/brif/*"].map{|f| f.split('/')[-1]}.sort
|
||||
port[if_name][:port_type] << 'bridge' << 'unremovable'
|
||||
else
|
||||
#pass
|
||||
end
|
||||
# Check, whether this interface is a slave of anything
|
||||
if File.symlink?("#{if_dir}/master")
|
||||
port[if_name][:has_master] = File.readlink("#{if_dir}/master").split('/')[-1]
|
||||
end
|
||||
# Check, whether this interface is a subinterface
|
||||
if vlan_ifaces.has_key? if_name
|
||||
# this interface is a 802.1q subinterface
|
||||
port[if_name].merge! vlan_ifaces[if_name]
|
||||
port[if_name][:port_type] << 'vlan'
|
||||
end
|
||||
end
|
||||
# Check, whether port is a slave of anything another
|
||||
port.keys.each do |p_name|
|
||||
if port[p_name].has_key? :has_master
|
||||
master = port[p_name][:has_master]
|
||||
#debug("m='#{master}', name='#{p_name}', props=#{port[p_name]}")
|
||||
master_flags = port[master][:port_type]
|
||||
if master_flags.include? 'bond'
|
||||
# this port is a bond_member
|
||||
port[p_name][:bond_master] = master
|
||||
port[p_name][:port_type] << 'bond-slave'
|
||||
elsif master_flags.include? 'bridge'
|
||||
# this port is a member of bridge
|
||||
port[p_name][:bridge] = master
|
||||
port[p_name][:port_type] << 'bridge-slave'
|
||||
elsif master == 'ovs-system'
|
||||
port[p_name][:port_type] << 'ovs-affected'
|
||||
else
|
||||
#pass
|
||||
end
|
||||
port[p_name].delete(:has_master)
|
||||
end
|
||||
end
|
||||
return port
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
def self.ovs_parse_opthash(hh)
|
||||
#if !(hh=~/^['"]/ and hh=~/['"]$/)
|
||||
rv = {}
|
||||
if hh =~ /^\{(.*)\}$/
|
||||
$1.split(/\s*\,\s*/).each do |pair|
|
||||
k,v = pair.split('=')
|
||||
#debug("===#{k}===#{v}===")
|
||||
rv[k.tr("'\"",'').to_sym] = v.nil? ? nil : v.tr("'\"",'')
|
||||
end
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
def self.get_ovs_bridges
|
||||
# return OVS interfaces hash if it possible
|
||||
begin
|
||||
vsctl_list_bridges = vsctl('list', 'Bridge').split("\n")
|
||||
vsctl_list_bridges << :EOF # last section of output should be processsed anyway.
|
||||
rescue
|
||||
debug("Can't find OVS ports, because error while 'ovs-vsctl list Bridge' execution")
|
||||
return {}
|
||||
end
|
||||
#
|
||||
buff = {}
|
||||
rv = {}
|
||||
# parse ovs-vsctl output and find OVS and OVS-affected interfaces
|
||||
vsctl_list_bridges.each do |line|
|
||||
if line =~ /(\w+)\s*\:\s*(.*)\s*$/
|
||||
key = $1.tr("'\"",'')
|
||||
val = $2.tr("'\"",'')
|
||||
buff[key] = (val == '[]' ? '' : val)
|
||||
elsif line =~ /^\s*$/ or line == :EOF
|
||||
stp_enable = buff['stp_enable'] || ''
|
||||
rv[buff['name']] = {
|
||||
:stp => stp_enable.downcase == 'true',
|
||||
:vendor_specific => {
|
||||
:external_ids => ovs_parse_opthash(buff['external_ids']),
|
||||
:other_config => ovs_parse_opthash(buff['other_config']),
|
||||
:status => ovs_parse_opthash(buff['status']),
|
||||
}
|
||||
}
|
||||
debug("Found OVS br: '#{buff['name']}' with properties: #{rv[buff['name']]}")
|
||||
buff = {}
|
||||
else
|
||||
debug("Output of 'ovs-vsctl list Bridge' contain misformated line: '#{line}'")
|
||||
end
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
def self.get_ovs_ports
|
||||
# return OVS interfaces hash if it possible
|
||||
begin
|
||||
vsctl_list_ports = vsctl('list', 'Port').split("\n")
|
||||
vsctl_list_ports << :EOF # last section of output should be processsed anyway.
|
||||
rescue
|
||||
debug("Can't find OVS ports, because error while 'ovs-vsctl list Port' execution")
|
||||
return {}
|
||||
end
|
||||
#
|
||||
buff = {}
|
||||
rv = {}
|
||||
# parse ovs-vsctl output and find OVS and OVS-affected interfaces
|
||||
vsctl_list_ports.each do |line|
|
||||
if line =~ /(\w+)\s*\:\s*(.*)\s*$/
|
||||
key = $1.tr("'\"",'')
|
||||
val = $2.tr("'\"",'')
|
||||
buff[key] = val == '[]' ? '' : val
|
||||
elsif line =~ /^\s*$/ or line == :EOF
|
||||
rv[buff['name']] = {
|
||||
:vendor_specific => {
|
||||
:other_config => ovs_parse_opthash(buff['other_config']),
|
||||
:status => ovs_parse_opthash(buff['status']),
|
||||
}
|
||||
}
|
||||
rv[buff['name']][:vlan_id] = buff['tag'] if ! (buff['tag'].nil? or buff['tag'].empty?)
|
||||
rv[buff['name']][:trunks] = buff['trunks'].tr("[]",'').split(/[\,\s]+/) if ! (buff['trunks'].nil? or buff['trunks'].empty?)
|
||||
debug("Found OVS port '#{buff['name']}' with properties: #{rv[buff['name']]}")
|
||||
buff = {}
|
||||
else
|
||||
debug("Output of 'ovs-vsctl list Port' contain misformated line: '#{line}'")
|
||||
end
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
def self.get_ovs_interfaces
|
||||
# return OVS interfaces hash if it possible
|
||||
begin
|
||||
vsctl_list_interfaces = vsctl('list', 'Interface').split("\n")
|
||||
vsctl_list_interfaces << :EOF # last section of output should be processsed anyway.
|
||||
rescue
|
||||
debug("Can't find OVS interfaces, because error while 'ovs-vsctl list Interface' execution")
|
||||
return {}
|
||||
end
|
||||
#
|
||||
buff = {}
|
||||
rv = {}
|
||||
# parse ovs-vsctl output and find OVS and OVS-affected interfaces
|
||||
vsctl_list_interfaces.each do |line|
|
||||
if line =~ /(\w+)\s*\:\s*(.*)\s*$/
|
||||
key = $1.tr("'\"",'')
|
||||
val = $2.tr("'\"",'')
|
||||
buff[key] = val == '[]' ? '' : val
|
||||
elsif line =~ /^\s*$/ or line == :EOF
|
||||
rv[buff['name']] = {
|
||||
:mtu => buff['mtu'],
|
||||
:port_type => (buff['type'].nil? or buff['type'].empty?) ? [] : [buff['type']],
|
||||
:vendor_specific => {
|
||||
:status => ovs_parse_opthash(buff['status']),
|
||||
}
|
||||
}
|
||||
driver = rv[buff['name']][:vendor_specific][:status][:driver_name]
|
||||
if driver.nil? or driver.empty? or driver == 'openvswitch'
|
||||
rv[buff['name']][:provider] = 'ovs'
|
||||
else
|
||||
rv[buff['name']][:provider] = nil
|
||||
end
|
||||
debug("Found OVS interface '#{buff['name']}' with properties: #{rv[buff['name']]}")
|
||||
buff = {}
|
||||
else
|
||||
debug("Output of 'ovs-vsctl list Interface' contain misformated line: '#{line}'")
|
||||
end
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
def self.ovs_vsctl_show
|
||||
begin
|
||||
#content = vsctl('show')
|
||||
content = `ovs-vsctl show`
|
||||
rescue
|
||||
debug("Can't get OVS configuration, because error while 'ovs-vsctl show' execution")
|
||||
return {}
|
||||
end
|
||||
bridges = get_ovs_bridges()
|
||||
ports = get_ovs_ports()
|
||||
interfaces = get_ovs_interfaces()
|
||||
ovs_config = {
|
||||
:port => {},
|
||||
:interface => {},
|
||||
#:bond => {}, # bond in ovs is a internal only port !!!
|
||||
:bridge => {},
|
||||
:jack => {} # jack of ovs patchcord (patchcord is a pair of ports with type 'patch')
|
||||
}
|
||||
_br = nil
|
||||
_po = nil
|
||||
_if = nil
|
||||
#_ift = nil
|
||||
content.split("\n").each do |line|
|
||||
line.rstrip!
|
||||
case line
|
||||
when /^\s+Bridge\s+"?([\w\-\.]+)\"?$/
|
||||
_br = $1
|
||||
_po = nil
|
||||
_if = nil
|
||||
ovs_config[:bridge][_br] = {
|
||||
:port_type => ['bridge'],
|
||||
:br_type => 'ovs',
|
||||
:provider => 'ovs'
|
||||
}
|
||||
if bridges.has_key? _br
|
||||
ovs_config[:bridge][_br].merge! bridges[_br]
|
||||
end
|
||||
when /^\s+Port\s+"?([\w\-\.]+)\"?$/
|
||||
next if _br.nil?
|
||||
_po = $1
|
||||
_if = nil
|
||||
ovs_config[:port][_po] = {
|
||||
:bridge => _br,
|
||||
:port_type => [],
|
||||
#:provider => 'ovs'
|
||||
}
|
||||
if ports.has_key? _po
|
||||
ovs_config[:port][_po].merge! ports[_po]
|
||||
end
|
||||
if _po == _br
|
||||
ovs_config[:port][_po][:port_type] << 'bridge'
|
||||
end
|
||||
when /^\s+Interface\s+"?([\w\-\.]+)\"?$/
|
||||
_if = $1
|
||||
ovs_config[:interface][_if] = {
|
||||
:port => _po,
|
||||
}
|
||||
if interfaces.has_key? _if
|
||||
ovs_config[:interface][_if].merge! interfaces[_if]
|
||||
end
|
||||
#todo(sv): Check interface driver from Interfaces table
|
||||
ovs_config[:port][_po][:provider] = ovs_config[:interface][_if][:provider]
|
||||
when /^\s+type:\s+"?([\w\-\.]+)\"?$/
|
||||
ovs_config[:interface][_if].merge!({
|
||||
:type => $1
|
||||
})
|
||||
when /^\s+options:\s+\{(.+)\}\s*$/
|
||||
opts = $1.split(/[\s\,]+/).map{|o| o.split('=')}.reduce({}){|h,p| h.merge(p[0] => p[1].tr('"',''))}
|
||||
ovs_config[:interface][_if].merge!({
|
||||
:options => opts
|
||||
})
|
||||
else
|
||||
#debug("Misformated line for br='#{_br}', po='#{_po}', if='#{_if}' => '#{line}'")
|
||||
end
|
||||
end
|
||||
ovs_config[:port].keys.each do |p_name|
|
||||
# didn't use .select{...} here for backward compatibility with ruby 1.8
|
||||
ifaces = ovs_config[:interface].reject{|k,v| v[:port]!=p_name}
|
||||
iface = ifaces[ifaces.keys[0]]
|
||||
if ifaces.size > 1
|
||||
# Bond found
|
||||
#ovs_config[:bond][p_name] = ovs_config[:port][p_name]
|
||||
#ovs_config[:port].delete(p_name)
|
||||
ovs_config[:port][p_name][:port_type] << 'bond'
|
||||
ovs_config[:port][p_name][:provider] = 'ovs'
|
||||
elsif iface[:type] == 'patch'
|
||||
ovs_config[:port][p_name][:port_type] << 'jack'
|
||||
elsif iface[:type] == 'internal'
|
||||
ovs_config[:port][p_name][:port_type] << 'internal'
|
||||
else
|
||||
# ordinary interface found
|
||||
# pass
|
||||
end
|
||||
# get mtu value (from one of interfaces if bond) and up it to port layer
|
||||
k = ifaces.keys
|
||||
if k.size > 0
|
||||
ovs_config[:port][p_name][:mtu] = ifaces[k[0]][:mtu]
|
||||
end
|
||||
# fix port-type=vlan for tagged ports
|
||||
if !ovs_config[:port][p_name][:vlan_id].nil?
|
||||
ovs_config[:port][p_name][:port_type] << 'vlan'
|
||||
end
|
||||
end
|
||||
debug("VSCTL-SHOW: #{ovs_config.to_yaml.gsub('!ruby/sym ',':')}")
|
||||
return ovs_config
|
||||
end
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def self.get_bridge_list
|
||||
# search all (LXN and OVS) bridges on the host, and return hash with mapping
|
||||
# bridge_name => { bridge options }
|
||||
#
|
||||
bridges = {}
|
||||
# obtain OVS bridges list
|
||||
re_c = /^\s*([\w\-]+)/
|
||||
begin
|
||||
vsctl('list-br').split(/\n+/).select{|l| l.match(re_c)}.collect{|a| $1 if a.match(re_c)}.each do |br_name|
|
||||
br_name.strip!
|
||||
bridges[br_name] = {
|
||||
:br_type => :ovs
|
||||
}
|
||||
end
|
||||
rescue
|
||||
debug("No OVS bridges found, because error while 'ovs-vsctl list-br' execution")
|
||||
end
|
||||
# obtain LNX bridges list
|
||||
re_c = /([\w\-]+)\s+\d+/
|
||||
begin
|
||||
# todo(sv): using port_list instead fork subprocess
|
||||
brctl('show').split(/\n+/).select{|l| l.match(re_c)}.collect{|a| $1 if a.match(re_c)}.each do |br_name|
|
||||
br_name.strip!
|
||||
bridges[br_name] = {
|
||||
:stp => (File.open("/sys/class/net/#{br_name}/bridge/stp_state").read.strip.to_i == 1),
|
||||
:external_ids => :absent,
|
||||
:vendor_specific => {},
|
||||
:br_type => :lnx
|
||||
}
|
||||
end
|
||||
rescue
|
||||
debug("No LNX bridges found, because error while 'brctl show' execution")
|
||||
end
|
||||
return bridges
|
||||
end
|
||||
|
||||
def self.get_ovs_port_bridges_pairs
|
||||
# returns hash, which map ports to it's bridge.
|
||||
# i.e {
|
||||
# qg37f65 => { :bridge => 'br-ex', :br_type => :ovs },
|
||||
# }
|
||||
#
|
||||
port_mappings = {}
|
||||
begin
|
||||
ovs_bridges = vsctl('list-br').split(/\n+/).select{|l| l.match(/^\s*[\w\-]+/)}
|
||||
rescue
|
||||
debug("No OVS bridges found, because error while 'ovs-vsctl list-br' execution")
|
||||
return {}
|
||||
end
|
||||
ovs_bridges.each do |br_name|
|
||||
br_name.strip!
|
||||
ovs_portlist = vsctl('list-ports', br_name).split(/\n+/).select{|l| l.match(/^\s*[\w\-]+\s*/)}
|
||||
#todo: handle error
|
||||
ovs_portlist.each do |port_name|
|
||||
port_name.strip!
|
||||
port_mappings[port_name] = {
|
||||
:bridge => br_name,
|
||||
:br_type => :ovs
|
||||
}
|
||||
end
|
||||
# bridge also a port, but it don't show itself by list-ports, adding it manually
|
||||
port_mappings[br_name] = {
|
||||
:bridge => br_name,
|
||||
:br_type => :ovs
|
||||
}
|
||||
end
|
||||
return port_mappings
|
||||
end
|
||||
|
||||
def self.get_lnx_port_bridges_pairs
|
||||
# returns hash, which map ports to it's bridge.
|
||||
# i.e {
|
||||
# 'eth0' => { :bridge => 'br0', :br_type => :lnx },
|
||||
# }
|
||||
# This function returns all visible in default namespace ports
|
||||
# (lnx and ovs (with type internal)) included to the lnx bridge
|
||||
#
|
||||
begin
|
||||
brctl_show = brctl('show').split(/\n+/).select{|l| l.match(/^[\w\-]+\s+\d+/) or l.match(/^\s+[\w\.\-]+/)}
|
||||
rescue
|
||||
debug("No LNX bridges found, because error while 'brctl show' execution")
|
||||
return {}
|
||||
end
|
||||
port_mappings = {}
|
||||
br_name = nil
|
||||
brctl_show.each do |line|
|
||||
line.rstrip!
|
||||
case line
|
||||
when /^([\w\-]+)\s+[\d\.abcdef]+\s+(yes|no)\s+([\w\-\.]+$)/i
|
||||
br_name = $1
|
||||
port_name = $3
|
||||
when /^\s+([\w\.\-]+)$/
|
||||
#br_name using from previous turn
|
||||
port_name = $1
|
||||
else
|
||||
next
|
||||
end
|
||||
if br_name
|
||||
port_mappings[port_name] = {
|
||||
:bridge => br_name,
|
||||
:br_type => :lnx
|
||||
}
|
||||
end
|
||||
end
|
||||
debug("LNX ports to bridges mapping: #{port_mappings.to_yaml.gsub('!ruby/sym ',':')}")
|
||||
return port_mappings
|
||||
end
|
||||
|
||||
def self.get_port_bridges_pairs
|
||||
# returns hash, which map ports to it's bridge.
|
||||
# i.e {
|
||||
# eth0 => { :bridge => 'br0', :br_type => :lnx },
|
||||
# qg37f65 => { :bridge => 'br-ex', :br_type => :ovs },
|
||||
# }
|
||||
# This function returns all visible in default namespace ports
|
||||
# (lnx and ovs (with type internal)) included to the lnx bridge
|
||||
#
|
||||
# If port included to both bridges (ovs and lnx at one time),
|
||||
# i.e. using as patchcord between bridges -- this port will be
|
||||
# assigned to lnx-type bridge
|
||||
#
|
||||
port_bridges_hash = self.get_ovs_port_bridges_pairs() # LNX bridges should overwrite OVS
|
||||
port_bridges_hash.merge! self.get_lnx_port_bridges_pairs() # because by design!
|
||||
end
|
||||
|
||||
def self.get_bridges_order_for_patch(bridges)
|
||||
# if given two OVS bridges -- we should sort it by name
|
||||
# if given OVS and LNX bridges -- OVS should be first.
|
||||
br_type = []
|
||||
[0,1].each do |i|
|
||||
br_type << (File.directory?("/sys/class/net/#{bridges[i]}/bridge") ? 'lnx' : 'ovs' )
|
||||
end
|
||||
if br_type[0] == br_type[1]
|
||||
rv = bridges.sort()
|
||||
elsif br_type[0] == 'ovs'
|
||||
rv = [bridges[0],bridges[1]]
|
||||
else
|
||||
rv = [bridges[1],bridges[0]]
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def self.get_lnx_bonds
|
||||
# search all LXN bonds on the host, and return hash with
|
||||
# bond_name => { bond options }
|
||||
#
|
||||
bond = {}
|
||||
bondlist = File.open("/sys/class/net/bonding_masters").read.chomp.split(/\s+/).sort
|
||||
bondlist.each do |bond_name|
|
||||
mode = File.open("/sys/class/net/#{bond_name}/bonding/mode").read.split(/\s+/)[0]
|
||||
bond[bond_name] = {
|
||||
:mtu => File.open("/sys/class/net/#{bond_name}/mtu").read.chomp.to_i,
|
||||
:slaves => File.open("/sys/class/net/#{bond_name}/bonding/slaves").read.chomp.split(/\s+/).sort,
|
||||
:bond_properties => {
|
||||
:mode => mode,
|
||||
:miimon => File.open("/sys/class/net/#{bond_name}/bonding/miimon").read.chomp,
|
||||
}
|
||||
}
|
||||
if ['802.3ad', 'balance-xor', 'balance-tlb', 'balance-alb'].include? mode
|
||||
xmit_hash_policy = File.open("/sys/class/net/#{bond_name}/bonding/xmit_hash_policy").read.split(/\s+/)[0]
|
||||
bond[bond_name][:bond_properties][:xmit_hash_policy] = xmit_hash_policy
|
||||
end
|
||||
if mode=='802.3ad'
|
||||
lacp_rate = File.open("/sys/class/net/#{bond_name}/bonding/lacp_rate").read.split(/\s+/)[0]
|
||||
bond[bond_name][:bond_properties][:lacp_rate] = lacp_rate
|
||||
end
|
||||
bond[bond_name][:onboot] = !self.get_iface_state(bond_name).nil?
|
||||
end
|
||||
return bond
|
||||
end
|
||||
|
||||
def self.lnx_bond_allowed_properties
|
||||
{
|
||||
:active_slave => {},
|
||||
:ad_select => {},
|
||||
:all_slaves_active => {},
|
||||
:arp_interval => {},
|
||||
:arp_ip_target => {},
|
||||
:arp_validate => {},
|
||||
:arp_all_targets => {},
|
||||
:downdelay => {},
|
||||
:updelay => {},
|
||||
:fail_over_mac => {},
|
||||
:lacp_rate => {:need_reassemble => true},
|
||||
:miimon => {},
|
||||
:min_links => {},
|
||||
:mode => {:need_reassemble => true},
|
||||
:num_grat_arp => {},
|
||||
:num_unsol_na => {},
|
||||
:packets_per_slave => {},
|
||||
:primary => {},
|
||||
:primary_reselect => {},
|
||||
:tlb_dynamic_lb => {},
|
||||
:use_carrier => {},
|
||||
:xmit_hash_policy => {},
|
||||
:resend_igmp => {},
|
||||
:lp_interval => {}
|
||||
}
|
||||
end
|
||||
def self.lnx_bond_allowed_properties_list
|
||||
self.lnx_bond_allowed_properties.keys.sort
|
||||
end
|
||||
|
||||
def self.ovs_bond_allowed_properties
|
||||
{
|
||||
:downdelay => {:property => 'bond_downdelay'},
|
||||
:updelay => {:property => 'bond_updelay'},
|
||||
:use_carrier => {:property => 'other_config:bond-detect-mode',
|
||||
:override_integer => ['miimon', 'carrier'] },
|
||||
:mode => {:property => 'bond_mode',
|
||||
:allow => ['balance-slb', 'active-backup', 'balance-tcp', 'stable'] },
|
||||
:lacp => {:property => 'lacp',
|
||||
:allow => ['off', 'active', 'passive'] },
|
||||
:lacp_rate => {:property => 'other_config:lacp_time'},
|
||||
:miimon => {:property => 'other_config:bond-miimon-interval'},
|
||||
:slb_rebalance_interval => {:property => 'other_config:bond-rebalance-interval'},
|
||||
}
|
||||
end
|
||||
def self.ovs_bond_allowed_properties_list
|
||||
self.ovs_bond_allowed_properties.keys.sort
|
||||
end
|
||||
|
||||
|
||||
def self.get_iface_state(iface)
|
||||
# returns:
|
||||
# true -- interface in UP state
|
||||
# false -- interface in UP state, but no-carrier
|
||||
# nil -- interface in DOWN state
|
||||
begin
|
||||
1 == File.open("/sys/class/net/#{iface}/carrier").read.chomp.to_i
|
||||
rescue
|
||||
# if interface is down, this file can't be read
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def self.get_ethtool_name_commands_mapping
|
||||
L23network.ethtool_name_commands_mapping
|
||||
end
|
||||
|
||||
def self.get_iface_ethtool_hash(if_name, empty_return = {})
|
||||
tmp = {}
|
||||
#todo(sv): wrap to begin--resque
|
||||
ethtool_k = ethtool_cmd('-k', if_name)
|
||||
ethtool_k.split(/\n+/).select{|l| !l.match(/(^\s+|\[fixed\]|^Features)/)}.map{|x| x.split(/[\s\:]+/)}.each do |p|
|
||||
tmp[p[0]] = (p[1] == 'on')
|
||||
end
|
||||
return {
|
||||
'offload' => tmp || empty_return
|
||||
}
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def self.set_mtu(iface, mtu=1500)
|
||||
if File.symlink?("/sys/class/net/#{iface}")
|
||||
debug("Set MTU to '#{mtu}' for interface '#{iface}'")
|
||||
File.open("/sys/class/net/#{iface}/mtu", "a") { |f| f.write(mtu) }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,199 @@
|
|||
# Native linux bonding implementation
|
||||
# INspired by: https://www.kernel.org/doc/Documentation/networking/bonding.txt
|
||||
#
|
||||
|
||||
require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/lnx_base')
|
||||
|
||||
Puppet::Type.type(:l2_bond).provide(:lnx, :parent => Puppet::Provider::Lnx_base) do
|
||||
defaultfor :osfamily => :linux
|
||||
commands :iproute => 'ip',
|
||||
:ethtool_cmd => 'ethtool',
|
||||
:brctl => 'brctl',
|
||||
:vsctl => 'ovs-vsctl'
|
||||
|
||||
|
||||
def self.prefetch(resources)
|
||||
interfaces = instances
|
||||
resources.keys.each do |name|
|
||||
if provider = interfaces.find{ |ii| ii.name == name }
|
||||
resources[name].provider = provider
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.instances
|
||||
bonds ||= self.get_lnx_bonds()
|
||||
debug("bonds found: #{bonds.keys}")
|
||||
rv = []
|
||||
bonds.each_pair do |bond_name, bond_props|
|
||||
props = {
|
||||
:ensure => :present,
|
||||
:name => bond_name,
|
||||
:vendor_specific => {}
|
||||
}
|
||||
props.merge! bond_props
|
||||
# # get bridge if port included to it
|
||||
# if ! port_bridges_hash[if_name].nil?
|
||||
# props[:bridge] = port_bridges_hash[if_name][:bridge]
|
||||
# end
|
||||
# # calculate port_type field
|
||||
# if !bridges[if_name].nil?
|
||||
# case bridges[if_name][:br_type]
|
||||
# when :ovs
|
||||
# props[:port_type] = 'ovs:br:unremovable'
|
||||
# when :lnx
|
||||
# props[:port_type] = 'lnx:br:unremovable'
|
||||
# else
|
||||
# # pass
|
||||
# end
|
||||
# end
|
||||
debug("PREFETCHED properties for '#{bond_name}': #{props}")
|
||||
rv << new(props)
|
||||
end
|
||||
rv
|
||||
end
|
||||
|
||||
def create
|
||||
debug("CREATE resource: #{@resource}")
|
||||
@old_property_hash = {}
|
||||
@property_flush = {}.merge! @resource
|
||||
open('/sys/class/net/bonding_masters', 'a') do |f|
|
||||
f << "+#{@resource[:name]}"
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
debug("DESTROY resource: #{@resource}")
|
||||
open('/sys/class/net/bonding_masters', 'a') do |f|
|
||||
f << "-#{@resource[:name]}"
|
||||
end
|
||||
end
|
||||
|
||||
def flush
|
||||
if @property_flush
|
||||
debug("FLUSH properties: #{@property_flush}")
|
||||
#
|
||||
# FLUSH changed properties
|
||||
if @property_flush.has_key? :slaves
|
||||
runtime_slave_ports = File.open("/sys/class/net/#{@resource[:bond]}/bonding/slaves", "r").read.split(/\s+/)
|
||||
if @property_flush[:slaves].nil? or @property_flush[:slaves] == :absent
|
||||
debug("Remove all slave ports from bond '#{@resource[:bond]}'")
|
||||
rm_slave_list = runtime_slave_ports
|
||||
else
|
||||
rm_slave_list = runtime_slave_ports - @property_flush[:slaves]
|
||||
debug("Remove '#{rm_slave_list.join(',')}' ports from bond '#{@resource[:bond]}'")
|
||||
rm_slave_list.each do |slave|
|
||||
iproute('link', 'set', 'dev', slave, 'down') # need by kernel requirements by design. undocumented :(
|
||||
File.open("/sys/class/net/#{@resource[:bond]}/bonding/slaves", "a") {|f| f << "-#{slave}"}
|
||||
end
|
||||
end
|
||||
# We shouldn't add ports here, because bond configures early, than ports.
|
||||
# corresponded ports may be unconfigured at this time.
|
||||
# corresponded ports will be add himself to bond while configuration
|
||||
end
|
||||
if @property_flush.has_key? :bond_properties
|
||||
# change bond_properties
|
||||
need_reassemble = [:mode, :lacp_rate]
|
||||
#todo(sv): inplement re-assembling only if it need
|
||||
#todo(sv): re-set only delta between reality and requested
|
||||
runtime_bond_state = !self.class.get_iface_state(@resource[:bond]).nil?
|
||||
runtime_slave_ports = File.open("/sys/class/net/#{@resource[:bond]}/bonding/slaves", "r").read.split(/\s+/)
|
||||
runtime_slave_ports.each do |eth|
|
||||
# for most bond options we should disassemble bond before re-configuration. In the kernel module documentation
|
||||
# says, that bond interface should be downed, but it's not enouth.
|
||||
File.open("/sys/class/net/#{@resource[:bond]}/bonding/slaves", "a") {|f| f << "-#{eth}"}
|
||||
end
|
||||
iproute('link', 'set', 'dev', @resource[:bond], 'down')
|
||||
@property_flush[:bond_properties].each_pair do |prop, val|
|
||||
if self.class.lnx_bond_allowed_properties_list.include? prop.to_sym
|
||||
act_val = val.to_s
|
||||
else
|
||||
debug("Unsupported property '#{prop}' for bond '#{@resource[:bond]}'")
|
||||
act_val = nil
|
||||
end
|
||||
if act_val
|
||||
debug("Set property '#{prop}' to '#{act_val}' for bond '#{@resource[:bond]}'")
|
||||
File.open("/sys/class/net/#{@resource[:bond]}/bonding/#{prop}", 'a') {|f| f << "#{act_val.to_s}"}
|
||||
end
|
||||
end
|
||||
# re-assemble bond after configuration
|
||||
iproute('link', 'set', 'dev', @resource[:bond], 'up') if runtime_bond_state
|
||||
runtime_slave_ports.each do |eth|
|
||||
File.open("/sys/class/net/#{@resource[:bond]}/bonding/slaves", "a") {|f| f << "+#{eth}"}
|
||||
end
|
||||
end
|
||||
if @property_flush.has_key? :bridge
|
||||
# get actual bridge-list. We should do it here,
|
||||
# because bridge may be not existing at prefetch stage.
|
||||
@bridges ||= self.class.get_bridge_list()
|
||||
debug("Actual-bridge-list: #{@bridges}")
|
||||
port_bridges_hash = self.class.get_port_bridges_pairs()
|
||||
debug("Actual-port-bridge-mapping: '#{port_bridges_hash}'") # it should removed from LNX
|
||||
#
|
||||
# remove interface from old bridge
|
||||
runtime_bond_state = !self.class.get_iface_state(@resource[:bond]).nil?
|
||||
iproute('--force', 'link', 'set', 'dev', @resource[:bond], 'down')
|
||||
if ! port_bridges_hash[@resource[:bond]].nil?
|
||||
br_name = port_bridges_hash[@resource[:bond]][:bridge]
|
||||
if br_name != @resource[:bond]
|
||||
# do not remove bridge-based interface from his bridge
|
||||
case port_bridges_hash[@resource[:bond]][:br_type]
|
||||
when :ovs
|
||||
vsctl('del-port', br_name, @resource[:bond])
|
||||
# todo catch exception
|
||||
when :lnx
|
||||
brctl('delif', br_name, @resource[:bond])
|
||||
# todo catch exception
|
||||
else
|
||||
#pass
|
||||
end
|
||||
end
|
||||
end
|
||||
# add port to the new bridge
|
||||
if !@property_flush[:bridge].nil? and @property_flush[:bridge].to_sym != :absent
|
||||
case @bridges[@property_flush[:bridge]][:br_type]
|
||||
when :ovs
|
||||
vsctl('add-port', @property_flush[:bridge], @resource[:bond])
|
||||
when :lnx
|
||||
brctl('addif', @property_flush[:bridge], @resource[:bond])
|
||||
else
|
||||
#pass
|
||||
end
|
||||
end
|
||||
iproute('link', 'set', 'dev', @resource[:bond], 'up') if runtime_bond_state
|
||||
debug("Change bridge")
|
||||
end
|
||||
if @property_flush[:onboot]
|
||||
iproute('link', 'set', 'dev', @resource[:bond], 'up')
|
||||
end
|
||||
if !['', 'absent'].include? @property_flush[:mtu].to_s
|
||||
self.class.set_mtu(@resource[:bond], @property_flush[:mtu])
|
||||
end
|
||||
@property_hash = resource.to_hash
|
||||
end
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
def slaves
|
||||
@property_hash[:slaves] || :absent
|
||||
end
|
||||
def slaves=(val)
|
||||
@property_flush[:slaves] = val
|
||||
end
|
||||
|
||||
def bond_properties
|
||||
@property_hash[:bond_properties] || :absent
|
||||
end
|
||||
def bond_properties=(val)
|
||||
@property_flush[:bond_properties] = val
|
||||
end
|
||||
|
||||
def interface_properties
|
||||
@property_hash[:interface_properties] || :absent
|
||||
end
|
||||
def interface_properties=(val)
|
||||
@property_flush[:interface_properties] = val
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,112 @@
|
|||
require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/ovs_base')
|
||||
|
||||
Puppet::Type.type(:l2_bond).provide(:ovs, :parent => Puppet::Provider::Ovs_base) do
|
||||
commands :vsctl => 'ovs-vsctl',
|
||||
:ethtool_cmd => 'ethtool',
|
||||
:iproute => 'ip'
|
||||
|
||||
|
||||
# def self.add_unremovable_flag(port_props)
|
||||
# # calculate 'unremovable' flag. Should be re-defined in chield providers
|
||||
# if port_props[:port_type].include? 'bridge' or port_props[:port_type].include? 'bond'
|
||||
# port_props[:port_type] << 'unremovable'
|
||||
# end
|
||||
# end
|
||||
|
||||
def self.get_instances(big_hash)
|
||||
# didn't use .select{...} here for backward compatibility with ruby 1.8
|
||||
big_hash[:port].reject{|k,v| !v[:port_type].include?('bond')}
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
|
||||
def create
|
||||
debug("CREATE resource: #{@resource}")
|
||||
@old_property_hash = {}
|
||||
@property_flush = {}.merge! @resource
|
||||
#
|
||||
cmd = ["add-bond", @resource[:bridge], @resource[:bond], @resource[:interface]]
|
||||
begin
|
||||
vsctl(cmd)
|
||||
rescue Puppet::ExecutionFailure => error
|
||||
raise Puppet::ExecutionFailure, "Can't add bond '#{@resource[:bond]}'\n#{error}"
|
||||
end
|
||||
# # set interface properties
|
||||
# if @resource[:interface_properties]
|
||||
# for option in @resource[:interface_properties]
|
||||
# begin
|
||||
# vsctl('--', "set", "Interface", @resource[:interface], option.to_s)
|
||||
# rescue Puppet::ExecutionFailure => error
|
||||
# raise Puppet::ExecutionFailure, "Interface '#{@resource[:interface]}' can't set option '#{option}':\n#{error}"
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
end
|
||||
|
||||
def destroy
|
||||
vsctl("del-port", @resource[:bridge], @resource[:interface])
|
||||
end
|
||||
|
||||
def flush
|
||||
if @property_flush
|
||||
debug("FLUSH properties: #{@property_flush}")
|
||||
if @property_flush.has_key? :slaves
|
||||
warn("Do nothing, OVS don't allow change bond slaves for existing bond ('#{@resource[:bond]}').")
|
||||
# But we can implement this undocumented hack later
|
||||
# ovs-vsctl add-port br3 ee2
|
||||
# ovs-vsctl list interface ee2 # get uuid for port
|
||||
# ovs-vsctl -- set port bond3 'interfaces=[0e6a0107-d0c7-49a6-93c7-41fe23e61c2c, 2c21e847-05ea-4b11-bde2-bb19e2d0ca56]'
|
||||
# ovs-vsctl show
|
||||
# ovs-vsctl del-port ee2 # ignore error
|
||||
# ovs-vsctl show
|
||||
end
|
||||
if @property_flush.has_key? :bond_properties
|
||||
# change bond_properties
|
||||
allowed_properties = self.class.ovs_bond_allowed_properties()
|
||||
@property_flush[:bond_properties].each_pair do |prop, val|
|
||||
if self.class.ovs_bond_allowed_properties_list.include? prop.to_sym
|
||||
act_val = val.to_s
|
||||
else
|
||||
warn("Unsupported property '#{prop}' for bond '#{@resource[:bond]}'")
|
||||
act_val = nil
|
||||
end
|
||||
if act_val
|
||||
debug("Set property '#{prop}' to '#{act_val}' for bond '#{@resource[:bond]}'")
|
||||
if allowed_properties[prop.to_sym][:property]
|
||||
# just setup property in OVSDB
|
||||
if allowed_properties[prop.to_sym][:allow] and ! allowed_properties[prop.to_sym][:allow].include? val
|
||||
warn("Unsupported value '#{val}' for property '#{prop}' for bond '#{@resource[:bond]}'.\nAllowed modes: #{allowed_properties[prop.to_sym][:allow]}")
|
||||
val = nil
|
||||
end
|
||||
if allowed_properties[prop.to_sym][:override_integer]
|
||||
# override property if it should be given as string for ovs and as integer for native linux
|
||||
val = allowed_properties[prop.to_sym][:override_integer][val.to_i] || allowed_properties[prop.to_sym][:override_integer][0]
|
||||
end
|
||||
vsctl('--', "set", "Port", @resource[:bond], "#{allowed_properties[prop.to_sym][:property]}=#{val}") if ! val.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
#
|
||||
if @property_flush.has_key? :mtu
|
||||
debug("Do nothing, because for OVS bonds MTU can be changed only for slave interfaces.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
def bond_properties
|
||||
@property_hash[:bond_properties] || :absent
|
||||
end
|
||||
def bond_properties=(val)
|
||||
@property_flush[:bond_properties] = val
|
||||
end
|
||||
|
||||
def interface_properties
|
||||
@property_hash[:interface_properties] || :absent
|
||||
end
|
||||
def interface_properties=(val)
|
||||
@property_flush[:interface_properties] = val
|
||||
end
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,97 @@
|
|||
# Native linux bridging implementation
|
||||
# Inspired by:
|
||||
# * https://www.kernel.org/doc/Documentation/networking/bridge.txt
|
||||
# * http://www.linuxfoundation.org/collaborate/workgroups/networking/bridge
|
||||
#
|
||||
|
||||
require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/lnx_base')
|
||||
|
||||
Puppet::Type.type(:l2_bridge).provide(:lnx, :parent => Puppet::Provider::Lnx_base) do
|
||||
defaultfor :osfamily => :linux
|
||||
commands :brctl => 'brctl',
|
||||
:ethtool_cmd => 'ethtool',
|
||||
:vsctl => 'ovs-vsctl',
|
||||
:iproute => 'ip'
|
||||
|
||||
def self.instances
|
||||
rv = []
|
||||
get_bridge_list().each_pair do |bridge, props|
|
||||
debug("prefetching '#{bridge}'")
|
||||
br_props = {
|
||||
:ensure => :present,
|
||||
:name => bridge,
|
||||
}
|
||||
br_props.merge! props
|
||||
if props[:br_type] == :lnx
|
||||
#br_props[:provider] = 'lnx'
|
||||
#props[:port_type] = props[:port_type].insert(0, 'ovs').join(':')
|
||||
rv << new(br_props)
|
||||
debug("PREFETCH properties for '#{bridge}': #{br_props}")
|
||||
else
|
||||
debug("SKIP properties for '#{bridge}': #{br_props}")
|
||||
end
|
||||
end
|
||||
rv
|
||||
end
|
||||
|
||||
def create
|
||||
debug("CREATE resource: #{@resource}")
|
||||
@old_property_hash = {}
|
||||
@property_flush = {}.merge! @resource
|
||||
begin
|
||||
brctl('addbr', @resource[:bridge])
|
||||
rescue
|
||||
# Some time interface may be created by OS init scripts. It's a normal for Ubuntu.
|
||||
raise if ! self.class.iface_exist? @resource[:bridge]
|
||||
notice("'#{@resource[:bridge]}' already created by ghost event.")
|
||||
end
|
||||
iproute('link', 'set', 'up', 'dev', @resource[:bridge])
|
||||
end
|
||||
|
||||
def destroy
|
||||
iproute('link', 'set', 'down', 'dev', @resource[:bridge])
|
||||
brctl('delbr', @resource[:bridge])
|
||||
end
|
||||
|
||||
def flush
|
||||
if @property_flush
|
||||
debug("FLUSH properties: #{@property_flush}")
|
||||
#
|
||||
# FLUSH changed properties
|
||||
if @property_flush.has_key? :stp
|
||||
effective_stp = (@property_flush[:stp].to_s == 'true' ? 1 : 0)
|
||||
File.open("/sys/class/net/#{@resource[:bridge]}/bridge/stp_state", "a") {|f| f << effective_stp}
|
||||
end
|
||||
@property_hash = resource.to_hash
|
||||
end
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
def br_type
|
||||
@property_hash[:br_type] || :absent
|
||||
end
|
||||
def br_type=(val)
|
||||
@property_flush[:br_type] = val
|
||||
end
|
||||
|
||||
# external IDs not supported
|
||||
def external_ids
|
||||
:absent
|
||||
end
|
||||
def external_ids=(value)
|
||||
{}
|
||||
end
|
||||
|
||||
def stp
|
||||
# puppet has internal transformation, and we shouldn't use boolean values. Use symbols -- it works stable!!!
|
||||
@property_hash[:stp].to_s.to_sym
|
||||
end
|
||||
def stp=(val)
|
||||
@property_flush[:stp] = (val.to_s.downcase.to_sym==:true)
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,103 @@
|
|||
require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/ovs_base')
|
||||
|
||||
Puppet::Type.type(:l2_bridge).provide(:ovs, :parent => Puppet::Provider::Ovs_base) do
|
||||
commands :vsctl => 'ovs-vsctl',
|
||||
:ethtool_cmd => 'ethtool',
|
||||
:brctl => 'brctl',
|
||||
:iproute => 'ip'
|
||||
|
||||
def self.skip_port_for?(port_props)
|
||||
port_props[:br_type] != 'ovs'
|
||||
end
|
||||
|
||||
def self.get_instances(big_hash)
|
||||
big_hash[:bridge]
|
||||
end
|
||||
|
||||
# def self.instances
|
||||
# rv = super
|
||||
# #debug("#{rv.inspect}")
|
||||
# end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
|
||||
def create
|
||||
debug("CREATE resource: #{@resource}")
|
||||
@old_property_hash = {}
|
||||
@property_flush = {}.merge! @resource
|
||||
#
|
||||
vsctl('add-br', @resource[:bridge])
|
||||
iproute('link', 'set', 'up', 'dev', @resource[:bridge])
|
||||
notice("bridge '#{@resource[:bridge]}' created.")
|
||||
end
|
||||
|
||||
def destroy
|
||||
iproute('link', 'set', 'down', 'dev', @resource[:bridge])
|
||||
vsctl("del-br", @resource[:bridge])
|
||||
end
|
||||
|
||||
def flush
|
||||
if @property_flush
|
||||
debug("FLUSH properties: #{@property_flush}")
|
||||
#
|
||||
# FLUSH changed properties
|
||||
if @property_flush.has_key? :stp
|
||||
vsctl('set', 'Bridge', @resource[:bridge], "stp_enable=#{@property_flush[:stp]}")
|
||||
end
|
||||
if @property_flush.has_key? :external_ids
|
||||
old_ids = (@old_property_hash[:external_ids] || {})
|
||||
new_ids = @property_flush[:external_ids]
|
||||
#todo(sv): calculate deltas and remove unnided.
|
||||
new_ids.each_pair do |k,v|
|
||||
if ! old_ids.has_key?(k)
|
||||
vsctl("br-set-external-id", @resource[:bridge], k, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
#
|
||||
@property_hash = resource.to_hash
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
def br_type
|
||||
@property_hash[:br_type] || :absent
|
||||
end
|
||||
def br_type=(val)
|
||||
@property_flush[:br_type] = val
|
||||
end
|
||||
|
||||
def external_ids
|
||||
# result = vsctl("br-get-external-id", @resource[:bridge])
|
||||
vs = (@property_hash[:vendor_specific] || {})
|
||||
result = (vs[:external_ids] || '')
|
||||
return result #.split("\n").join(",")
|
||||
end
|
||||
def external_ids=(val)
|
||||
@property_flush[:external_ids] = val
|
||||
end
|
||||
|
||||
def vendor_specific
|
||||
@property_hash[:vendor_specific] || :absent
|
||||
end
|
||||
def vendor_specific=(val)
|
||||
@property_flush[:vendor_specific] = val
|
||||
end
|
||||
|
||||
def stp
|
||||
# puppet has internal trancformation, and we shouldn't use boolean values. it works unstable!!!
|
||||
@property_hash[:stp].to_s.to_sym
|
||||
end
|
||||
def stp=(val)
|
||||
@property_flush[:stp] = (val.to_s.downcase.to_sym==:true)
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
|
||||
def _split(string, splitter=",")
|
||||
return Hash[string.split(splitter).map{|i| i.split("=")}]
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -1,57 +0,0 @@
|
|||
Puppet::Type.type(:l2_ovs_bond).provide(:ovs) do
|
||||
optional_commands(
|
||||
:vsctl => "/usr/bin/ovs-vsctl",
|
||||
:appctl => "/usr/bin/ovs-appctl"
|
||||
)
|
||||
|
||||
def _exists?(bond)
|
||||
begin
|
||||
appctl('bond/show', bond)
|
||||
true
|
||||
rescue Puppet::ExecutionFailure
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def exists?
|
||||
_exists?(@resource[:bond])
|
||||
end
|
||||
|
||||
def create
|
||||
if _exists?(@resource[:bond])
|
||||
msg = "Bond '#{@resource[:bond]}' already exists"
|
||||
if @resource[:skip_existing]
|
||||
notice("#{msg}, skip creating.")
|
||||
else
|
||||
fail("#{msg}.")
|
||||
end
|
||||
end
|
||||
|
||||
bond_properties = Array(@resource[:properties])
|
||||
if @resource[:vlan_id] > 0
|
||||
bond_properties.insert(-1, "tag=#{@resource[:vlan_id]}")
|
||||
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
|
||||
fail("Can't create bond '#{@resource[:bond]}' (interfaces: #{@resource[:interfaces].join(',')}) for bridge '#{@resource[:bridge]}'.\n#{error}")
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
begin
|
||||
vsctl("del-port", @resource[:bridge], @resource[:bond])
|
||||
rescue Puppet::ExecutionFailure => error
|
||||
fail("Can't remove bond '#{@resource[:bond]}' from bridge '#{@resource[:bridge]}'.\n#{error}")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -1,55 +0,0 @@
|
|||
Puppet::Type.type(:l2_ovs_bridge).provide(:ovs) do
|
||||
optional_commands :vsctl => "/usr/bin/ovs-vsctl"
|
||||
|
||||
def exists?
|
||||
vsctl("br-exists", @resource[:bridge])
|
||||
rescue Puppet::ExecutionFailure
|
||||
return false
|
||||
end
|
||||
|
||||
def create
|
||||
begin
|
||||
vsctl('br-exists', @resource[:bridge])
|
||||
if @resource[:skip_existing]
|
||||
notice("Bridge '#{@resource[:bridge]}' already exists, skip creating.")
|
||||
#external_ids = @resource[:external_ids] if @resource[:external_ids]
|
||||
return true
|
||||
else
|
||||
raise Puppet::ExecutionFailure, "Bridge '#{@resource[:bridge]}' already exists."
|
||||
end
|
||||
rescue Puppet::ExecutionFailure
|
||||
# pass
|
||||
notice("Bridge '#{@resource[:bridge]}' not exists, creating...")
|
||||
end
|
||||
vsctl('add-br', @resource[:bridge])
|
||||
notice("bridge '#{@resource[:bridge]}' created.")
|
||||
# We do self.attr_setter=(value) instead of attr=value because this doesn't
|
||||
# work in Puppet (our guess).
|
||||
# TODO (adanin): Fix other places like this one. See bug #1366009
|
||||
self.external_ids=(@resource[:external_ids]) if @resource[:external_ids]
|
||||
end
|
||||
|
||||
def destroy
|
||||
vsctl("del-br", @resource[:bridge])
|
||||
end
|
||||
|
||||
def _split(string, splitter=",")
|
||||
return Hash[string.split(splitter).map{|i| i.split("=")}]
|
||||
end
|
||||
|
||||
def external_ids
|
||||
result = vsctl("br-get-external-id", @resource[:bridge])
|
||||
return result.split("\n").join(",")
|
||||
end
|
||||
|
||||
def external_ids=(value)
|
||||
old_ids = _split(external_ids)
|
||||
new_ids = _split(value)
|
||||
|
||||
new_ids.each_pair do |k,v|
|
||||
unless old_ids.has_key?(k)
|
||||
vsctl("br-set-external-id", @resource[:bridge], k, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,90 +0,0 @@
|
|||
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: check 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[:vlan_ids][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
|
|
@ -1,72 +0,0 @@
|
|||
Puppet::Type.type(:l2_ovs_port).provide(:ovs) do
|
||||
optional_commands :vsctl => "/usr/bin/ovs-vsctl"
|
||||
|
||||
def exists?
|
||||
vsctl("list-ports", @resource[:bridge]).split(/\n+/).include? @resource[:interface]
|
||||
end
|
||||
|
||||
def create
|
||||
begin
|
||||
vsctl('port-to-br', @resource[:interface])
|
||||
if @resource[:skip_existing]
|
||||
return true
|
||||
else
|
||||
raise Puppet::ExecutionFailure, "Port '#{@resource[:interface]}' already exists."
|
||||
end
|
||||
rescue Puppet::ExecutionFailure
|
||||
# pass
|
||||
end
|
||||
# tag and trunks for port
|
||||
port_properties = @resource[:port_properties]
|
||||
if @resource[:vlan_id] > 0
|
||||
port_properties.insert(-1, "tag=#{@resource[:vlan_id]}")
|
||||
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 not port_properties.empty?
|
||||
for option in port_properties
|
||||
cmd.insert(-1, option)
|
||||
end
|
||||
end
|
||||
# set interface type
|
||||
if @resource[:type] and @resource[:type].to_s != ''
|
||||
tt = "type=" + @resource[:type].to_s
|
||||
cmd += ['--', "set", "Interface", @resource[:interface], tt]
|
||||
end
|
||||
# executing OVS add-port command
|
||||
cmd = ["add-port"] + cmd
|
||||
begin
|
||||
vsctl(cmd)
|
||||
rescue Puppet::ExecutionFailure => error
|
||||
raise Puppet::ExecutionFailure, "Can't add port '#{@resource[:interface]}'\n#{error}"
|
||||
end
|
||||
# set interface properties
|
||||
if @resource[:interface_properties]
|
||||
for option in @resource[:interface_properties]
|
||||
begin
|
||||
vsctl('--', "set", "Interface", @resource[:interface], option.to_s)
|
||||
rescue Puppet::ExecutionFailure => error
|
||||
raise Puppet::ExecutionFailure, "Interface '#{@resource[:interface]}' can't set option '#{option}':\n#{error}"
|
||||
end
|
||||
end
|
||||
end
|
||||
# enable vlan_splinters if need
|
||||
if @resource[:vlan_splinters].to_s() == 'true' # puppet send non-boolean value instead true/false
|
||||
Puppet.debug("Interface '#{@resource[:interface]}' vlan_splinters is '#{@resource[:vlan_splinters]}' [#{@resource[:vlan_splinters].class}]")
|
||||
begin
|
||||
vsctl('--', "set", "Port", @resource[:interface], "vlan_mode=trunk")
|
||||
vsctl('--', "set", "Interface", @resource[:interface], "other-config:enable-vlan-splinters=true")
|
||||
rescue Puppet::ExecutionFailure => error
|
||||
raise Puppet::ExecutionFailure, "Interface '#{@resource[:interface]}' can't setup vlan_splinters:\n#{error}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
vsctl("del-port", @resource[:bridge], @resource[:interface])
|
||||
end
|
||||
end
|
|
@ -0,0 +1,188 @@
|
|||
require 'puppetx/l23_utils'
|
||||
require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/ovs_base')
|
||||
|
||||
Puppet::Type.type(:l2_patch).provide(:ovs, :parent => Puppet::Provider::Ovs_base) do
|
||||
commands :vsctl => 'ovs-vsctl',
|
||||
:ethtool_cmd => 'ethtool',
|
||||
:brctl => 'brctl',
|
||||
:iproute => 'ip'
|
||||
|
||||
|
||||
def self.instances
|
||||
vsctl_show = ovs_vsctl_show()
|
||||
lnx_port_br_mapping = get_lnx_port_bridges_pairs()
|
||||
jacks = []
|
||||
# didn't use .select{...} here for backward compatibility with ruby 1.8
|
||||
vsctl_show[:port].reject{|k,v| !(v[:port_type] & ['jack','internal']).any?}.each_pair do |p_name, p_props|
|
||||
props = {
|
||||
:name => p_name,
|
||||
}
|
||||
props.merge! p_props
|
||||
if props[:port_type].include? 'jack'
|
||||
debug("found jack '#{p_name}'")
|
||||
# get 'peer' property and copy to jack
|
||||
# didn't use .select{...} here for backward compatibility with ruby 1.8
|
||||
ifaces = vsctl_show[:interface].reject{|k,v| v[:port]!=p_name}
|
||||
iface = ifaces[ifaces.keys[0]]
|
||||
props[:peer] = (iface.has_key?(:options) ? iface[:options]['peer'] : nil)
|
||||
elsif props[:port_type].include? 'internal'
|
||||
debug("found 'internal' ovs port '#{p_name}'")
|
||||
props[:cross] = true
|
||||
else
|
||||
#pass
|
||||
end
|
||||
jacks << props
|
||||
end
|
||||
# search pairs of jacks and make patchcord resources
|
||||
patches = []
|
||||
skip = []
|
||||
mtu = nil
|
||||
jacks.each do |jack|
|
||||
next if skip.include? jack[:name]
|
||||
if jack[:cross]
|
||||
# process 'cross' patch between OVS and LNX bridge
|
||||
peer = lnx_port_br_mapping[jack[:name]]
|
||||
next if peer.nil?
|
||||
_bridges = [jack[:bridge], peer[:bridge]] # no sort here!!! architecture limitation -- ovs brodge always first!
|
||||
_tails = [jack[:name], jack[:name]]
|
||||
mtu = File.open("/sys/class/net/#{jack[:name]}/mtu").read.chomp.to_i
|
||||
else
|
||||
# process patch between two OVS bridges
|
||||
next if jack[:peer].nil?
|
||||
found_peer = jacks.select{|j| j[:name]==jack[:peer]}
|
||||
next if found_peer.empty?
|
||||
peer = found_peer[0]
|
||||
_bridges = [jack[:bridge], peer[:bridge]].sort
|
||||
_tails = ([jack[:bridge], peer[:bridge]] == _bridges ? [jack[:name], peer[:name]] : [peer[:name], jack[:name]])
|
||||
end
|
||||
props = {
|
||||
:ensure => :present,
|
||||
:name => L23network.get_patch_name([jack[:bridge],peer[:bridge]]),
|
||||
:bridges => _bridges,
|
||||
:jacks => _tails,
|
||||
:mtu => mtu,
|
||||
:cross => jack[:cross],
|
||||
:provider => 'ovs'
|
||||
}
|
||||
debug("PREFETCH properties for '#{props[:name]}': #{props}")
|
||||
patches << new(props)
|
||||
skip << peer[:name]
|
||||
end
|
||||
return patches #.map{|x| new(x)}
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
|
||||
def create
|
||||
debug("CREATE resource: #{@resource}")
|
||||
@old_property_hash = {}
|
||||
@property_flush = {}.merge! @resource
|
||||
bridges = self.class.get_bridges_order_for_patch(@resource[:bridges])
|
||||
@property_flush[:bridges] = bridges
|
||||
#
|
||||
debug("Bridges: '#{bridges.join(', ')}.")
|
||||
if File.directory?("/sys/class/net/#{bridges[1]}/bridge")
|
||||
# creating 'cross' OVS-to-lnx patchcord
|
||||
lnx_port_br_mapping = self.class.get_lnx_port_bridges_pairs()
|
||||
jack = L23network.get_lnx_jack_name(bridges[0])
|
||||
vsctl('--may-exist', 'add-port', bridges[0], jack, '--', 'set', 'Interface', jack, 'type=internal')
|
||||
if lnx_port_br_mapping.has_key? jack and lnx_port_br_mapping[jack][:bridge] != bridges[1]
|
||||
# eject lnx-side jack from bridge, if jack aldeady a member
|
||||
brctl('delif', lnx_port_br_mapping[jack][:bridge], jack)
|
||||
lnx_port_br_mapping.delete(jack)
|
||||
end
|
||||
if !lnx_port_br_mapping.has_key? jack
|
||||
begin
|
||||
brctl('addif', bridges[1], jack)
|
||||
rescue Exception => e
|
||||
if e.to_s =~ /device\s+#{jack}\s+is\s+already\s+a\s+member\s+of\s+a\s+bridge/
|
||||
notice("'#{jack}' already addeded to '#{bridges[1]}' by ghost event.")
|
||||
else
|
||||
raise
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
# creating OVS-to-OVS patchcord
|
||||
jacks = []
|
||||
jacks << L23network.get_ovs_jack_name(bridges[1])
|
||||
jacks << L23network.get_ovs_jack_name(bridges[0])
|
||||
#todo(sv): make type and peer change in flush
|
||||
cmds = []
|
||||
cmds << ['--may-exist', 'add-port', bridges[0], jacks[0], '--', 'set', 'Interface', jacks[0], 'type=patch', "option:peer=#{jacks[1]}"]
|
||||
cmds << ['--may-exist', 'add-port', bridges[1], jacks[1], '--', 'set', 'Interface', jacks[1], 'type=patch', "option:peer=#{jacks[0]}"]
|
||||
cmds.each do |cmd|
|
||||
begin
|
||||
vsctl(cmd)
|
||||
rescue Puppet::ExecutionFailure => error
|
||||
raise Puppet::ExecutionFailure, "Can't add jack for patchcord '#{@resource[:name]}'\n#{error}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
if File.directory?("/sys/class/net/#{@resource[:bridges][1]}/bridge")
|
||||
# removing 'cross' OVS-to-lnx patchcord
|
||||
jack = L23network.get_lnx_jack_name(@resource[:bridges][0])
|
||||
if File.symlink?("/sys/class/net/#{@resource[:bridges][1]}/brif/#{jack}")
|
||||
brctl('delif', @resource[:bridges][1], jack)
|
||||
end
|
||||
vsctl('del-port', @resource[:bridges][0], jack)
|
||||
else
|
||||
# removing OVS-to-OVS patchcord
|
||||
bridges = @resource[:bridges].sort
|
||||
jacks = []
|
||||
jacks << L23network.get_ovs_jack_name(bridges[1])
|
||||
jacks << L23network.get_ovs_jack_name(bridges[0])
|
||||
cmds = []
|
||||
cmds << ['del-port', bridges[0], jacks[0]]
|
||||
cmds << ['del-port', bridges[1], jacks[1]]
|
||||
cmds.each do |cmd|
|
||||
begin
|
||||
vsctl(cmd)
|
||||
rescue Puppet::ExecutionFailure => error
|
||||
raise Puppet::ExecutionFailure, "Can't remove jack for patchcord '#{@resource[:name]}'\n#{error}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def flush
|
||||
if !@property_flush.empty?
|
||||
debug("FLUSH properties: #{@property_flush}")
|
||||
if !['', 'absent'].include? @property_flush[:mtu].to_s
|
||||
# 'absent' is a synonym 'do-not-touch' for MTU
|
||||
@property_hash[:jacks].uniq.each do |iface|
|
||||
self.class.set_mtu(iface, @property_flush[:mtu])
|
||||
end
|
||||
end
|
||||
@property_hash = resource.to_hash
|
||||
end
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
|
||||
def bridges
|
||||
self.class.get_bridges_order_for_patch(@property_hash[:bridges])
|
||||
end
|
||||
def bridges=(val)
|
||||
@property_flush[:bridges] = self.class.get_bridges_order_for_patch(val)
|
||||
end
|
||||
|
||||
def jacks
|
||||
@property_hash[:jacks]
|
||||
end
|
||||
def jacks=(val)
|
||||
nil
|
||||
end
|
||||
|
||||
def cross
|
||||
@property_hash[:cross]
|
||||
end
|
||||
def cross=(val)
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,189 @@
|
|||
require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/lnx_base')
|
||||
|
||||
Puppet::Type.type(:l2_port).provide(:lnx, :parent => Puppet::Provider::Lnx_base) do
|
||||
defaultfor :osfamily => :linux
|
||||
commands :iproute => 'ip',
|
||||
:ethtool_cmd => 'ethtool',
|
||||
:brctl => 'brctl',
|
||||
:vsctl => 'ovs-vsctl'
|
||||
|
||||
|
||||
def self.instances
|
||||
rv = []
|
||||
#todo: what do with OVS ports, inserted in LNX bridge? i.e. port located in two bridges.
|
||||
ports = get_lnx_ports()
|
||||
ovs_interfaces = get_ovs_interfaces()
|
||||
ports.each_pair do |if_name, if_props|
|
||||
props = {
|
||||
:ensure => :present,
|
||||
:name => if_name,
|
||||
:vendor_specific => {}
|
||||
}
|
||||
debug("prefetching interface '#{if_name}'")
|
||||
props.merge! if_props
|
||||
props[:ethtool] = get_iface_ethtool_hash(if_name, nil)
|
||||
# add PROVIDER prefix to port type flags and convert port_type to string
|
||||
if ovs_interfaces.has_key? if_name and ovs_interfaces[if_name][:port_type].is_a? Array and ovs_interfaces[if_name][:port_type].include? 'internal'
|
||||
if_provider = ovs_interfaces[if_name][:provider]
|
||||
props[:port_type] = ovs_interfaces[if_name][:port_type]
|
||||
props[:provider] = ovs_interfaces[if_name][:provider]
|
||||
else
|
||||
if_provider = props[:provider]
|
||||
end
|
||||
props[:port_type] = props[:port_type].insert(0, if_provider).join(':')
|
||||
if if_provider == 'lnx'
|
||||
rv << new(props)
|
||||
debug("PREFETCH properties for '#{if_name}': #{props}")
|
||||
else
|
||||
debug("SKIP properties for '#{if_name}': #{props}")
|
||||
end
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
def create
|
||||
debug("CREATE resource: #{@resource}")
|
||||
@old_property_hash = {}
|
||||
@property_flush = {}.merge! @resource
|
||||
# todo: divide simple creating interface and vlan
|
||||
begin
|
||||
iproute('link', 'add', 'link', @resource[:vlan_dev], 'name', @resource[:interface], 'type', 'vlan', 'id', @resource[:vlan_id])
|
||||
rescue
|
||||
# Some time interface may be created by OS init scripts. It's a normal for Ubuntu.
|
||||
raise if ! self.class.iface_exist? @resource[:interface]
|
||||
notice("'#{@resource[:interface]}' already created by ghost event.")
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
debug("DESTROY resource: #{@resource}")
|
||||
# todo: Destroing of L2 resource -- is a putting interface to the DOWN state.
|
||||
# Or remove, if ove a vlan interface
|
||||
#iproute('--force', 'addr', 'flush', 'dev', @resource[:interface])
|
||||
end
|
||||
|
||||
def flush
|
||||
if @property_flush
|
||||
debug("FLUSH properties: #{@property_flush}")
|
||||
#
|
||||
# FLUSH changed properties
|
||||
if @property_flush.has_key? :bond_master
|
||||
bond = @old_property_hash[:bond_master]
|
||||
# putting interface to the down-state, because add/remove upped interface impossible. undocumented kern.behavior.
|
||||
iproute('--force', 'link', 'set', 'dev', @resource[:interface], 'down')
|
||||
if bond and bond != :absent
|
||||
# remove interface from bond, if one included to it
|
||||
debug("Remove interface '#{@resource[:interface]}' from bond '#{bond}'.")
|
||||
File.open("/sys/class/net/#{@resource[:interface]}/master/bonding/slaves", "a") {|f| f << "-#{@resource[:interface]}"}
|
||||
end
|
||||
if ! @property_flush[:bond_master].nil? and @property_flush[:bond_master] != :absent
|
||||
# add interface as slave to bond
|
||||
debug("Add interface '#{@resource[:interface]}' to bond '#{@property_flush[:bond_master]}'.")
|
||||
File.open("/sys/class/net/#{@property_flush[:bond_master]}/bonding/slaves", "a") {|f| f << "+#{@resource[:interface]}"}
|
||||
else
|
||||
# port no more member of any bonds
|
||||
@property_flush[:port_type] = nil
|
||||
end
|
||||
end
|
||||
if @property_flush.has_key? :bridge
|
||||
# get actual bridge-list. We should do it here,
|
||||
# because bridge may be not existing at prefetch stage.
|
||||
@bridges ||= self.class.get_bridge_list # resource port can't change bridge list
|
||||
debug("Actual-bridge-list: #{@bridges}")
|
||||
port_bridges_hash = self.class.get_port_bridges_pairs()
|
||||
debug("Actual-port-bridge-mapping: '#{port_bridges_hash}'") # it should removed from LNX
|
||||
#
|
||||
iproute('--force', 'link', 'set', 'dev', @resource[:interface], 'down')
|
||||
# remove interface from old bridge
|
||||
if ! port_bridges_hash[@resource[:interface]].nil?
|
||||
br_name = port_bridges_hash[@resource[:interface]][:bridge]
|
||||
br_type = port_bridges_hash[@resource[:interface]][:br_type]
|
||||
if br_name != @resource[:interface]
|
||||
# do not remove bridge-based interface from his bridge
|
||||
case br_type
|
||||
when :ovs
|
||||
vsctl('del-port', br_name, @resource[:interface])
|
||||
when :lnx
|
||||
brctl('delif', br_name, @resource[:interface])
|
||||
else
|
||||
#pass
|
||||
end
|
||||
end
|
||||
end
|
||||
# add port to the new bridge
|
||||
if !@property_flush[:bridge].nil? and @property_flush[:bridge].to_sym != :absent
|
||||
case @bridges[@property_flush[:bridge]][:br_type]
|
||||
when :ovs
|
||||
vsctl('add-port', @property_flush[:bridge], @resource[:interface])
|
||||
when :lnx
|
||||
brctl('addif', @property_flush[:bridge], @resource[:interface])
|
||||
else
|
||||
#pass
|
||||
end
|
||||
end
|
||||
iproute('link', 'set', 'dev', @resource[:interface], 'up') if @resource[:onboot]
|
||||
debug("Change bridge")
|
||||
end
|
||||
if @property_flush.has_key? :ethtool and @property_flush[:ethtool].is_a? Hash
|
||||
@property_flush[:ethtool].each_pair do |section, pairs|
|
||||
debug("Setup '#{section}' by ethtool for interface '#{@resource[:interface]}'.")
|
||||
optmaps = self.class.get_ethtool_name_commands_mapping[section]
|
||||
if optmaps
|
||||
pairs.each_pair do |k,v|
|
||||
if optmaps.has_key? k
|
||||
_cmd = [optmaps['__section_key_set__'], @resource[:interface], optmaps[k], v ? 'on':'off']
|
||||
begin
|
||||
ethtool_cmd(_cmd)
|
||||
rescue Exception => e
|
||||
warn("Non-fatal error: #{e.to_s}")
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
warn("No mapping for ethtool section '#{section}' for interface '#{@resource[:interface]}'.")
|
||||
end
|
||||
end
|
||||
end
|
||||
if ! @property_flush[:onboot].nil?
|
||||
# Should be after bond, because interface may auto-upped while added to the bond
|
||||
debug("Setup UP state for interface '#{@resource[:interface]}'.")
|
||||
iproute('link', 'set', 'dev', @resource[:interface], 'up')
|
||||
end
|
||||
if !['', 'absent'].include? @property_flush[:mtu].to_s
|
||||
self.class.set_mtu(@resource[:interface], @property_flush[:mtu])
|
||||
end
|
||||
@property_hash = resource.to_hash
|
||||
end
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
def vlan_dev
|
||||
@property_hash[:vlan_dev] || :absent
|
||||
end
|
||||
def vlan_dev=(val)
|
||||
@property_flush[:vlan_dev] = val
|
||||
end
|
||||
|
||||
def vlan_id
|
||||
@property_hash[:vlan_id] || :absent
|
||||
end
|
||||
def vlan_id=(val)
|
||||
@property_flush[:vlan_id] = val
|
||||
end
|
||||
|
||||
def vlan_mode
|
||||
@property_hash[:vlan_mode] || :absent
|
||||
end
|
||||
def vlan_mode=(val)
|
||||
@property_flush[:vlan_mode] = val
|
||||
end
|
||||
|
||||
def bond_master
|
||||
@property_hash[:bond_master] || :absent
|
||||
end
|
||||
def bond_master=(val)
|
||||
@property_flush[:bond_master] = val
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,100 @@
|
|||
require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/ovs_base')
|
||||
|
||||
Puppet::Type.type(:l2_port).provide(:ovs, :parent => Puppet::Provider::Ovs_base) do
|
||||
commands :vsctl => 'ovs-vsctl',
|
||||
:ethtool_cmd => 'ethtool',
|
||||
:iproute => 'ip'
|
||||
|
||||
|
||||
def self.add_unremovable_flag(port_props)
|
||||
# calculate 'unremovable' flag. Should be re-defined in chield providers
|
||||
if port_props[:port_type].include? 'bridge' or port_props[:port_type].include? 'bond'
|
||||
port_props[:port_type] << 'unremovable'
|
||||
end
|
||||
end
|
||||
|
||||
def self.get_instances(big_hash)
|
||||
big_hash[:port]
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
|
||||
def create
|
||||
debug("CREATE resource: #{@resource}")
|
||||
@old_property_hash = {}
|
||||
@property_flush = {}.merge! @resource
|
||||
#
|
||||
cmd = ["add-port", @resource[:bridge], @resource[:interface]]
|
||||
# # tag and trunks for port
|
||||
# port_properties = @resource[:port_properties]
|
||||
# if ![nil, :absent].include? @resource[:vlan_id] and @resource[:vlan_id] > 0
|
||||
# port_properties << "tag=#{@resource[:vlan_id]}"
|
||||
# end
|
||||
# if ![nil, :absent].include? @resource[:trunks] and !@resource[:trunks].empty?
|
||||
# port_properties.insert(-1, "trunks=[#{@resource[:trunks].join(',')}]")
|
||||
# end
|
||||
# Port create begins from definition brodge and port
|
||||
# # add port properties (k/w) to command line
|
||||
# if not port_properties.empty?
|
||||
# for option in port_properties
|
||||
# cmd.insert(-1, option)
|
||||
# end
|
||||
# end
|
||||
# set interface type
|
||||
if @resource[:type] and (@resource[:type].to_s != '' or @resource[:type].to_s != :absent)
|
||||
tt = "type=" + @resource[:type].to_s
|
||||
else
|
||||
tt = "type=internal"
|
||||
end
|
||||
cmd += ['--', "set", "Interface", @resource[:interface], tt]
|
||||
# executing OVS add-port command
|
||||
begin
|
||||
vsctl(cmd)
|
||||
rescue Puppet::ExecutionFailure => error
|
||||
raise Puppet::ExecutionFailure, "Can't add port '#{@resource[:interface]}'\n#{error}"
|
||||
end
|
||||
# # set interface properties
|
||||
# if @resource[:interface_properties]
|
||||
# for option in @resource[:interface_properties]
|
||||
# begin
|
||||
# vsctl('--', "set", "Interface", @resource[:interface], option.to_s)
|
||||
# rescue Puppet::ExecutionFailure => error
|
||||
# raise Puppet::ExecutionFailure, "Interface '#{@resource[:interface]}' can't set option '#{option}':\n#{error}"
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
end
|
||||
|
||||
def destroy
|
||||
vsctl("del-port", @resource[:bridge], @resource[:interface])
|
||||
end
|
||||
|
||||
def flush
|
||||
if @property_flush
|
||||
debug("FLUSH properties: #{@property_flush}")
|
||||
if !['', 'absent'].include? @property_flush[:mtu].to_s
|
||||
self.class.set_mtu(@resource[:interface], @property_flush[:mtu])
|
||||
end
|
||||
if @property_flush.has_key? :vlan_id
|
||||
if !@property_flush[:vlan_id].nil? and @property_flush[:vlan_id] != :absent
|
||||
vsctl('set', 'Port', @resource[:interface], "tag=#{@property_flush[:vlan_id].to_i}")
|
||||
else
|
||||
# remove 802.1q tag
|
||||
vsctl('set', 'Port', @resource[:interface], "tag='[]'")
|
||||
end
|
||||
end
|
||||
@property_hash = resource.to_hash
|
||||
end
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
|
||||
def ethtool
|
||||
@property_hash[:ethtool] || nil
|
||||
end
|
||||
def ethtool=(val)
|
||||
@property_flush[:ethtool] = val
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -1,226 +0,0 @@
|
|||
require 'timeout'
|
||||
require 'ipaddr'
|
||||
|
||||
begin
|
||||
require 'util/netstat.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__), 'util', 'netstat.rb')
|
||||
load rb_file if File.exists?(rb_file) or raise e
|
||||
end
|
||||
|
||||
def get_gateway()
|
||||
Facter::Util::NetStat.get_route_value('default', 'gw') || Facter::Util::NetStat.get_route_value('0.0.0.0', 'gw')
|
||||
end
|
||||
|
||||
def find_gateway(interface, if_file)
|
||||
rv = nil
|
||||
def_route = get_gateway()
|
||||
if def_route and if_file
|
||||
ifile = /\[(\S+)\]/.match(if_file.to_s())
|
||||
if ifile
|
||||
#notice("RT-def-route: '#{def_route}' int_file: '#{ifile}'") ################
|
||||
ifile = ifile[1]
|
||||
begin
|
||||
File.open(ifile, 'r').each() do |line|
|
||||
gate = /gateway\s+(\d+\.\d+\.\d+\.\d+)/.match(line.to_s()) || /GATEWAY\s*=\s*(\d+\.\d+\.\d+\.\d+)/.match(line.to_s())
|
||||
if gate
|
||||
gate = gate[1]
|
||||
#notice("IN-FILE-GATE: '#{gate}'")
|
||||
if gate == def_route
|
||||
rv = gate
|
||||
#notice("IN-FILE-GATE: '#{gate}' rv = gate")
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue
|
||||
notice("Can't open file '#{ifile}'")
|
||||
end
|
||||
end
|
||||
else
|
||||
notice("Default route: UNKNOWN")
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
Puppet::Type.type(:l3_if_downup).provide(:ruby) do
|
||||
confine :osfamily => [:debian, :redhat]
|
||||
optional_commands(
|
||||
:ifup => 'ifup',
|
||||
:ifdn => 'ifdown',
|
||||
:ip => "ip",
|
||||
:kill => "kill",
|
||||
:ps => "ps",
|
||||
:ping => "ping"
|
||||
)
|
||||
|
||||
def ping_ip(ipaddr,timeout)
|
||||
end_time = Time.now.to_i + timeout
|
||||
rv = false
|
||||
loop do
|
||||
begin
|
||||
ping(['-n', '-c1', ipaddr])
|
||||
rv = true
|
||||
break
|
||||
rescue Puppet::ExecutionFailure => e
|
||||
current_time = Time.now.to_i
|
||||
if current_time > end_time
|
||||
break
|
||||
else
|
||||
wa = end_time - current_time
|
||||
notice("Host #{ipaddr} not answered. Wait up to #{wa} sec.")
|
||||
#notice e.message
|
||||
end
|
||||
sleep(0.5) # do not remove!!! It's a positive brake!
|
||||
end
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
def get_interface_carrier()
|
||||
begin
|
||||
return File.open("/sys/class/net/#{@resource[:interface]}/carrier", 'r'){ |file| file.read().to_i }
|
||||
rescue
|
||||
return -1
|
||||
end
|
||||
end
|
||||
|
||||
def restart()
|
||||
#Check the current state of the interface first
|
||||
if get_interface_carrier != 1
|
||||
notice("Carrier is DOWN, '#{@resource[:interface]}' skipping carrier test")
|
||||
poll_for_carrier = false
|
||||
else
|
||||
poll_for_carrier = true
|
||||
end
|
||||
|
||||
begin # downing inteface
|
||||
# add force for debian-based OS ([PRD-2132])
|
||||
if Facter.value(:osfamily) == 'Debian'
|
||||
ifdn(['--force',@resource[:interface]])
|
||||
else
|
||||
ifdn(@resource[:interface])
|
||||
end
|
||||
notice("Interface '#{@resource[:interface]}' down.")
|
||||
sleep @resource[:sleep_time]
|
||||
rescue Puppet::ExecutionFailure
|
||||
notice("Can't put interface '#{@resource[:interface]}' to DOWN state.")
|
||||
end
|
||||
if @resource[:kill_dhclient] and Facter.value(:osfamily) == 'Debian'
|
||||
# kill forgotten dhclient in Ubuntu
|
||||
dhclient = @resource[:dhclient_name]
|
||||
iface = @resource[:interface]
|
||||
ps('axf').each_line do |line|
|
||||
rg = line.match("^\s*([0-9]+)\s+.*#{dhclient}\s+.*(\s#{iface})")
|
||||
if rg
|
||||
begin
|
||||
kill(['-9',rg[1]])
|
||||
notice("Killed forgotten #{dhclient} with PID=#{rg[1]} succeffuly...")
|
||||
sleep @resource[:sleep_time]
|
||||
rescue Puppet::ExecutionFailure
|
||||
notice("Can't kill #{dhclient} with PID=#{rg[1]}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if @resource[:flush] # Flushing IP addresses from interface
|
||||
begin
|
||||
ip(['addr', 'flush', @resource[:interface]])
|
||||
notice("Interface '#{@resource[:interface]}' flush.")
|
||||
sleep @resource[:sleep_time]
|
||||
rescue Puppet::ExecutionFailure
|
||||
notice("Can't flush interface '#{@resource[:interface]}'.")
|
||||
end
|
||||
end
|
||||
return true if @resource[:onlydown]
|
||||
begin # Put interface to UP state
|
||||
if Facter.value(:osfamily) == 'Debian'
|
||||
# add force for debian-based OS ([PRD-2132])
|
||||
ifup(['--force', @resource[:interface]])
|
||||
else
|
||||
ifup(@resource[:interface])
|
||||
end
|
||||
notice("Interface '#{@resource[:interface]}' up.")
|
||||
# checking and waiting carrier for PHYS. interface
|
||||
if (@resource[:interface] =~ /^eth\d+$/) and @resource[:wait_carrier_after_ifup] and poll_for_carrier
|
||||
begin
|
||||
Timeout::timeout(@resource[:wait_carrier_after_ifup_timeout]) do
|
||||
_w = 10
|
||||
loop do
|
||||
carrier = get_interface_carrier
|
||||
if carrier == 1
|
||||
break
|
||||
elsif carrier == -1
|
||||
notice("Seems that the interface '#{@resource[:interface]}' was brought down administratively. Further deployment actions may fail!")
|
||||
sleep(10)
|
||||
else
|
||||
if _w == 0
|
||||
notice("Interface '#{@resource[:interface]}' waiting for carrier...")
|
||||
_w = 10
|
||||
end
|
||||
sleep(1)
|
||||
_w -= 1
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue Timeout::Error
|
||||
notice("Interface '#{@resource[:interface]}' has no carrier. :(")
|
||||
else
|
||||
notice("Interface '#{@resource[:interface]}' has good carrier.")
|
||||
end
|
||||
end
|
||||
if @resource[:check_by_ping] == 'gateway'
|
||||
# find gateway for interface and ping it
|
||||
ip_to_ping = find_gateway(@resource[:interface], @resource[:subscribe])
|
||||
if ip_to_ping
|
||||
notice("Interface '#{@resource[:interface]}' Gateway #{ip_to_ping} will be pinged. Wait up to #{@resource[:check_by_ping_timeout]} sec.")
|
||||
rv = self.ping_ip(ip_to_ping, @resource[:check_by_ping_timeout].to_i)
|
||||
if rv
|
||||
notice("Interface '#{@resource[:interface]}' #{ip_to_ping} is OK")
|
||||
else
|
||||
notice("Interface '#{@resource[:interface]}' #{ip_to_ping} no answer :(")
|
||||
end
|
||||
end
|
||||
elsif @resource[:check_by_ping] == 'none'
|
||||
#pass
|
||||
notice("Interface '#{@resource[:interface]}' Don't checked.")
|
||||
else
|
||||
# IP address given
|
||||
notice("Interface '#{@resource[:interface]}' IP #{@resource[:check_by_ping]} will be pinged. Wait up to #{@resource[:check_by_ping_timeout]} sec.")
|
||||
rv = self.ping_ip(@resource[:check_by_ping], @resource[:check_by_ping_timeout].to_i)
|
||||
if rv
|
||||
notice("Interface '#{@resource[:interface]}' #{@resource[:check_by_ping]} is OK")
|
||||
else
|
||||
notice("Interface '#{@resource[:interface]}' #{@resource[:check_by_ping]} no answer :(")
|
||||
end
|
||||
end
|
||||
notice("Interface '#{@resource[:interface]}' done.")
|
||||
rescue Puppet::ExecutionFailure
|
||||
notice("Can't put interface '#{@resource[:interface]}' to UP state.")
|
||||
end
|
||||
end
|
||||
|
||||
def create()
|
||||
if ! @resource[:refreshonly]
|
||||
restart()
|
||||
end
|
||||
end
|
||||
|
||||
def destroy()
|
||||
end
|
||||
|
||||
# def self.instances
|
||||
# if_list = []
|
||||
# File.open("/proc/net/dev", "r") do |raw_iflist|
|
||||
# while (line = raw_iflist.gets)
|
||||
# rg = line.match('^\s*([0-9A-Za-z\.\-\_]+):')
|
||||
# if rg
|
||||
# if_list.push(rg[1].to_sym)
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
# return if_list
|
||||
# end
|
||||
end
|
|
@ -1,71 +0,0 @@
|
|||
module Facter::Util::NetStat
|
||||
def self.column_map
|
||||
{
|
||||
:bsd => {
|
||||
:aliases => [:sunos, :freebsd, :netbsd, :darwin],
|
||||
:dest => 0,
|
||||
:gw => 1,
|
||||
:iface => 5
|
||||
},
|
||||
:linux => {
|
||||
:dest => 0,
|
||||
:gw => 1,
|
||||
:iface => 7
|
||||
},
|
||||
:openbsd => {
|
||||
:dest => 0,
|
||||
:gw => 1,
|
||||
:iface => 6
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def self.supported_platforms
|
||||
column_map.inject([]) do |result, tmp|
|
||||
key, map = tmp
|
||||
if map[:aliases]
|
||||
result += map[:aliases]
|
||||
else
|
||||
result << key
|
||||
end
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
def self.get_ipv4_output
|
||||
output = ""
|
||||
case Facter.value(:kernel)
|
||||
when 'SunOS', 'FreeBSD', 'NetBSD', 'OpenBSD'
|
||||
output = %x{/usr/bin/netstat -rn -f inet}
|
||||
when 'Darwin'
|
||||
output = %x{/usr/sbin/netstat -rn -f inet}
|
||||
when 'Linux'
|
||||
output = %x{/bin/netstat -rn -A inet}
|
||||
end
|
||||
output
|
||||
end
|
||||
|
||||
def self.get_route_value(route, label)
|
||||
tmp1 = []
|
||||
|
||||
kernel = Facter.value(:kernel).downcase.to_sym
|
||||
|
||||
# If it's not directly in the map or aliased in the map, then we don't know how to deal with it.
|
||||
unless map = column_map[kernel] || column_map.values.find { |tmp| tmp[:aliases] and tmp[:aliases].include?(kernel) }
|
||||
return nil
|
||||
end
|
||||
|
||||
c1 = map[:dest]
|
||||
c2 = map[label.to_sym]
|
||||
|
||||
get_ipv4_output.split("\n").map { |s| s.split}.each { |a|
|
||||
if a[c1] == route
|
||||
tmp1 << a[c2]
|
||||
end
|
||||
}
|
||||
|
||||
if tmp1
|
||||
return tmp1.shift
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,232 @@
|
|||
Puppet::Type.type(:l3_ifconfig).provide(:lnx) do
|
||||
defaultfor :osfamily => :linux
|
||||
commands :iproute => 'ip'
|
||||
|
||||
|
||||
def self.prefetch(resources)
|
||||
interfaces = instances
|
||||
resources.keys.each do |name|
|
||||
if provider = interfaces.find{ |ii| ii.name == name }
|
||||
resources[name].provider = provider
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.instances
|
||||
insts = []
|
||||
rou_list = self.get_if_defroutes_mappings()
|
||||
# parse all system interfaces
|
||||
self.get_if_addr_mappings().each_pair do |if_name, pro|
|
||||
props = {
|
||||
:ensure => :present,
|
||||
:name => if_name,
|
||||
:ipaddr => pro[:ipaddr],
|
||||
}
|
||||
if !rou_list[if_name].nil?
|
||||
props.merge! rou_list[if_name]
|
||||
else
|
||||
props.merge!({
|
||||
:gateway => :absent,
|
||||
:gateway_metric => :absent
|
||||
})
|
||||
end
|
||||
debug("PREFETCHED properties for '#{if_name}': #{props}")
|
||||
insts << new(props)
|
||||
end
|
||||
return insts
|
||||
end
|
||||
|
||||
def exists?
|
||||
@property_hash[:ensure] == :present
|
||||
end
|
||||
|
||||
def create
|
||||
debug("CREATE resource: #{@resource}") # with hash: '#{m}'")
|
||||
@old_property_hash = {}
|
||||
@property_flush = {}.merge! @resource
|
||||
#p @property_flush
|
||||
#p @property_hash
|
||||
#p @resource.inspect
|
||||
end
|
||||
|
||||
def destroy
|
||||
debug("DESTROY resource: #{@resource}")
|
||||
# todo: Destroing of L3 resource -- is a removing any IP addresses.
|
||||
# DO NOT!!! put intedafce to Down state.
|
||||
iproute('--force', 'addr', 'flush', 'dev', @resource[:interface])
|
||||
@property_hash.clear
|
||||
end
|
||||
|
||||
def initialize(value={})
|
||||
super(value)
|
||||
@property_flush = {}
|
||||
@old_property_hash = {}
|
||||
@old_property_hash.merge! @property_hash
|
||||
end
|
||||
|
||||
def flush
|
||||
if @property_flush
|
||||
debug("FLUSH properties: #{@property_flush}")
|
||||
#
|
||||
# FLUSH changed properties
|
||||
if ! @property_flush[:ipaddr].nil?
|
||||
if @property_flush[:ipaddr].include?(:absent)
|
||||
# flush all ip addresses from interface
|
||||
iproute('--force', 'addr', 'flush', 'dev', @resource[:interface])
|
||||
elsif @property_flush[:ipaddr].include?(:dhcp)
|
||||
# start dhclient on interface
|
||||
iproute('--force', 'addr', 'flush', 'dev', @resource[:interface])
|
||||
#todo: start dhclient
|
||||
else
|
||||
# add-remove static IP addresses
|
||||
if !@old_property_hash.nil? and !@old_property_hash[:ipaddr].nil?
|
||||
(@old_property_hash[:ipaddr] - @property_flush[:ipaddr]).each do |ipaddr|
|
||||
iproute('--force', 'addr', 'del', ipaddr, 'dev', @resource[:interface])
|
||||
end
|
||||
adding_addresses = @property_flush[:ipaddr] - @old_property_hash[:ipaddr]
|
||||
else
|
||||
adding_addresses = @property_flush[:ipaddr]
|
||||
end
|
||||
if adding_addresses.include? :none
|
||||
iproute('--force', 'link', 'set', 'dev', @resource[:interface], 'up')
|
||||
elsif adding_addresses.include? :dhcp
|
||||
debug("!!! DHCP runtime configuration not implemented now !!!")
|
||||
else
|
||||
# add IP addresses
|
||||
adding_addresses.each do |ipaddr|
|
||||
iproute('addr', 'add', ipaddr, 'dev', @resource[:interface])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if !@property_flush[:gateway].nil? or !@property_flush[:gateway_metric].nil?
|
||||
# clean all default gateways for this interface with any metrics
|
||||
cmdline = ['route', 'del', 'default', 'dev', @resource[:interface]]
|
||||
rc = 0
|
||||
while rc == 0
|
||||
# we should remove route repeatedly for prevent situation
|
||||
# when has multiple default routes through the same router,
|
||||
# but with different metrics
|
||||
begin
|
||||
iproute(cmdline)
|
||||
rescue
|
||||
rc = 1
|
||||
end
|
||||
end
|
||||
# add new route
|
||||
if @resource[:gateway] != :absent
|
||||
cmdline = ['route', 'add', 'default', 'via', @resource[:gateway], 'dev', @resource[:interface]]
|
||||
if ![nil, :absent].include?(@property_flush[:gateway_metric]) and @property_flush[:gateway_metric].to_i > 0
|
||||
cmdline << ['metric', @property_flush[:gateway_metric]]
|
||||
end
|
||||
begin
|
||||
rv = iproute(cmdline)
|
||||
rescue
|
||||
warn("!!! Iproute can't setup new gateway.\n!!! May be you already have default gateway with same metric:")
|
||||
rv = iproute('-f', 'inet', 'route', 'show')
|
||||
warn("#{rv}\n\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# if ! @property_flush[:onboot].nil?
|
||||
# iproute('link', 'set', 'dev', @resource[:interface], 'up')
|
||||
# end
|
||||
@property_hash = resource.to_hash
|
||||
end
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
# def bridge
|
||||
# @property_hash[:bridge] || :absent
|
||||
# end
|
||||
# def bridge=(val)
|
||||
# @property_flush[:bridge] = val
|
||||
# end
|
||||
|
||||
# def name
|
||||
# @property_hash[:name]
|
||||
# end
|
||||
|
||||
def port_type
|
||||
@property_hash[:port_type] || :absent
|
||||
end
|
||||
def port_type=(val)
|
||||
@property_flush[:port_type] = val
|
||||
end
|
||||
|
||||
def onboot
|
||||
@property_hash[:onboot] || :absent
|
||||
end
|
||||
def onboot=(val)
|
||||
@property_flush[:onboot] = val
|
||||
end
|
||||
|
||||
def ipaddr
|
||||
@property_hash[:ipaddr] || :absent
|
||||
end
|
||||
def ipaddr=(val)
|
||||
if (@old_property_hash[:ipaddr] - val) != (val - @old_property_hash[:ipaddr])
|
||||
@property_flush[:ipaddr] = val
|
||||
end
|
||||
end
|
||||
|
||||
def gateway
|
||||
@property_hash[:gateway] || :absent
|
||||
end
|
||||
def gateway=(val)
|
||||
@property_flush[:gateway] = val
|
||||
end
|
||||
|
||||
def gateway_metric
|
||||
@property_hash[:gateway_metric] || :absent
|
||||
end
|
||||
def gateway_metric=(val)
|
||||
@property_flush[:gateway_metric] = val
|
||||
end
|
||||
|
||||
def dhcp_hostname
|
||||
@property_hash[:dhcp_hostname] || :absent
|
||||
end
|
||||
def dhcp_hostname=(val)
|
||||
@property_flush[:dhcp_hostname] = val
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
|
||||
def self.get_if_addr_mappings
|
||||
if_list = {}
|
||||
ip_a = iproute('-f', 'inet', 'addr', 'show').split(/\n+/)
|
||||
if_name = nil
|
||||
ip_a.each do |line|
|
||||
line.rstrip!
|
||||
case line
|
||||
when /^\s*\d+\:\s+([\w\-\.]+)[\:\@]/i
|
||||
if_name = $1
|
||||
if_list[if_name] = { :ipaddr => [] }
|
||||
when /^\s+inet\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2})/
|
||||
next if if_name.nil?
|
||||
if_list[if_name][:ipaddr] << $1
|
||||
else
|
||||
next
|
||||
end
|
||||
end
|
||||
return if_list
|
||||
end
|
||||
|
||||
def self.get_if_defroutes_mappings
|
||||
rou_list = {}
|
||||
ip_a = iproute('-f', 'inet', 'route', 'show').split(/\n+/)
|
||||
ip_a.each do |line|
|
||||
line.rstrip!
|
||||
next if !line.match(/^\s*default\s+via\s+([\d\.]+)\s+dev\s+([\w\-\.]+)(\s+metric\s+(\d+))?/)
|
||||
metric = $4.nil? ? :absent : $4.to_i
|
||||
rou_list[$2] = { :gateway => $1, :gateway_metric => metric } if rou_list[$2].nil? # do not replace to gateway with highest metric
|
||||
end
|
||||
return rou_list
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,94 @@
|
|||
require File.join(File.dirname(__FILE__), 'l2_base')
|
||||
|
||||
class Puppet::Provider::Lnx_base < Puppet::Provider::L2_base
|
||||
|
||||
#todo(sv): adapt this to LNX resources
|
||||
# def self.instances
|
||||
# rv = []
|
||||
# get_instances(ovs_vsctl_show()).each_pair do |p_name, p_props|
|
||||
# props = {
|
||||
# :ensure => :present,
|
||||
# :name => p_name,
|
||||
# :vendor_specific => {}
|
||||
# }
|
||||
# debug("prefetching '#{p_name}'")
|
||||
# props.merge! p_props
|
||||
# next if skip_port_for? props
|
||||
# add_unremovable_flag(props)
|
||||
# ##add PROVIDER prefix to port type flags and create puppet resource
|
||||
# if props[:provider] == 'ovs'
|
||||
# props[:port_type] = props[:port_type].insert(0, 'ovs').join(':')
|
||||
# rv << new(props)
|
||||
# debug("PREFETCH properties for '#{p_name}': #{props}")
|
||||
# else
|
||||
# debug("SKIP properties for '#{p_name}': #{props}")
|
||||
# end
|
||||
# end
|
||||
# return rv
|
||||
# end
|
||||
|
||||
|
||||
def initialize(value={})
|
||||
super(value)
|
||||
@property_flush = {}
|
||||
@old_property_hash = {}
|
||||
@old_property_hash.merge! @property_hash
|
||||
end
|
||||
|
||||
def exists?
|
||||
@property_hash[:ensure] == :present
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
def vendor_specific
|
||||
@property_hash[:vendor_specific] || :absent
|
||||
end
|
||||
def vendor_specific=(val)
|
||||
nil
|
||||
end
|
||||
|
||||
def mtu
|
||||
@property_hash[:mtu] || :absent
|
||||
end
|
||||
def mtu=(val)
|
||||
# for MTU :absent is sinonym of 'do not change'
|
||||
@property_flush[:mtu] = val.to_i if !['', 'absent'].include? val.to_s
|
||||
end
|
||||
|
||||
def onboot
|
||||
@property_hash[:onboot] || :absent
|
||||
end
|
||||
def onboot=(val)
|
||||
@property_flush[:onboot] = val
|
||||
end
|
||||
|
||||
def bridge
|
||||
@property_hash[:bridge] || :absent
|
||||
end
|
||||
def bridge=(val)
|
||||
@property_flush[:bridge] = val
|
||||
end
|
||||
|
||||
def ethtool
|
||||
@property_hash[:ethtool] || nil
|
||||
end
|
||||
def ethtool=(val)
|
||||
@property_flush[:ethtool] = val
|
||||
end
|
||||
|
||||
def port_type
|
||||
@property_hash[:port_type] || :absent
|
||||
end
|
||||
def port_type=(val)
|
||||
@property_flush[:port_type] = val
|
||||
end
|
||||
|
||||
def type
|
||||
:absent
|
||||
end
|
||||
def type=(value)
|
||||
debug("Resource '#{@resource[:name]}': Doesn't support interface type change.")
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,141 @@
|
|||
require File.join(File.dirname(__FILE__), 'l2_base')
|
||||
|
||||
class Puppet::Provider::Ovs_base < Puppet::Provider::L2_base
|
||||
|
||||
def self.skip_port_for?(port_props)
|
||||
# calculate whether this port should be skipped.
|
||||
# Should be re-defined in chield providers
|
||||
false
|
||||
end
|
||||
|
||||
def self.add_unremovable_flag(port_props)
|
||||
# calculate 'unremovable' flag. Should be re-defined in chield providers
|
||||
true
|
||||
end
|
||||
|
||||
def self.get_instances(big_hash)
|
||||
# calculate hash of hashes from given big hash
|
||||
# Should be re-defined in chield providers
|
||||
{}
|
||||
end
|
||||
|
||||
def self.instances
|
||||
rv = []
|
||||
get_instances(ovs_vsctl_show()).each_pair do |p_name, p_props|
|
||||
props = {
|
||||
:ensure => :present,
|
||||
:name => p_name,
|
||||
:vendor_specific => {}
|
||||
}
|
||||
debug("prefetching '#{p_name}'")
|
||||
props.merge! p_props
|
||||
next if skip_port_for? props
|
||||
add_unremovable_flag(props)
|
||||
##add PROVIDER prefix to port type flags and create puppet resource
|
||||
if props[:provider] == 'ovs'
|
||||
props[:port_type] = props[:port_type].insert(0, 'ovs').join(':')
|
||||
rv << new(props)
|
||||
debug("PREFETCH properties for '#{p_name}': #{props}")
|
||||
else
|
||||
debug("SKIP properties for '#{p_name}': #{props}")
|
||||
end
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
|
||||
def initialize(value={})
|
||||
super(value)
|
||||
@property_flush = {}
|
||||
@old_property_hash = {}
|
||||
@old_property_hash.merge! @property_hash
|
||||
end
|
||||
|
||||
def exists?
|
||||
@property_hash[:ensure] == :present
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
#-----------------------------------------------------------------
|
||||
def bridge
|
||||
@property_hash[:bridge] || :absent
|
||||
end
|
||||
def bridge=(val)
|
||||
@property_flush[:bridge] = val
|
||||
end
|
||||
|
||||
def vlan_dev
|
||||
:absent
|
||||
end
|
||||
def vlan_dev=(val)
|
||||
nil
|
||||
end
|
||||
|
||||
def vlan_id
|
||||
@property_hash[:vlan_id] || :absent
|
||||
end
|
||||
def vlan_id=(val)
|
||||
@property_flush[:vlan_id] = val
|
||||
end
|
||||
|
||||
def port_type
|
||||
@property_hash[:port_type] || :absent
|
||||
end
|
||||
def port_type=(val)
|
||||
@property_flush[:port_type] = val
|
||||
end
|
||||
|
||||
def vlan_mode
|
||||
'vlan'
|
||||
end
|
||||
def vlan_mode=(val)
|
||||
nil
|
||||
end
|
||||
|
||||
def bond_master
|
||||
:absent
|
||||
end
|
||||
def bond_master=(val)
|
||||
nil
|
||||
end
|
||||
|
||||
def slaves
|
||||
@property_hash[:slaves] || :absent
|
||||
end
|
||||
def slaves=(val)
|
||||
nil
|
||||
end
|
||||
|
||||
def mtu
|
||||
@property_hash[:mtu] || :absent
|
||||
end
|
||||
def mtu=(val)
|
||||
# for MTU :absent is sinonym of 'do not change'
|
||||
@property_flush[:mtu] = val.to_i if !['', 'absent'].include? val.to_s
|
||||
end
|
||||
|
||||
def onboot
|
||||
@property_hash[:onboot] || :absent
|
||||
end
|
||||
def onboot=(val)
|
||||
@property_flush[:onboot] = val
|
||||
end
|
||||
|
||||
def vendor_specific
|
||||
@property_hash[:vendor_specific] || :absent
|
||||
end
|
||||
def vendor_specific=(val)
|
||||
@property_flush[:vendor_specific] = val
|
||||
end
|
||||
|
||||
def type
|
||||
@property_hash[:type] || :absent
|
||||
end
|
||||
def type=(value)
|
||||
@property_flush[:type] = val
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -39,3 +39,4 @@ Puppet::Type.newtype(:cfg) do
|
|||
end
|
||||
end
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,14 @@
|
|||
Puppet::Type.newtype(:k_mod) do
|
||||
@doc = "Check and load kernel module, if need"
|
||||
desc @doc
|
||||
|
||||
ensurable
|
||||
|
||||
MAX_BR_NAME_LENGTH = 15
|
||||
|
||||
newparam(:module) do
|
||||
isnamevar
|
||||
desc "Module name"
|
||||
end
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,268 @@
|
|||
# type for managing persistent interface config options
|
||||
# Inspired by puppet-network module. Adrien, thanks.
|
||||
|
||||
Puppet::Type.newtype(:l23_stored_config) do
|
||||
@doc = "Manage lines in interface config file"
|
||||
desc @doc
|
||||
|
||||
feature :provider_options, <<-EOD
|
||||
The provider can accept a hash of arbitrary options. The semantics of
|
||||
these options will depend on the provider.
|
||||
EOD
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:name) do
|
||||
isnamevar
|
||||
desc "The name of the physical or logical network device"
|
||||
end
|
||||
|
||||
newproperty(:method) do
|
||||
desc "The method for determining an IP address for the interface"
|
||||
# static -- assign IP address in config
|
||||
# manual -- UP interface without IP address
|
||||
newvalues(:static, :absent, :manual, :dhcp, :loopback, :none, :undef, :nil)
|
||||
aliasvalue(:none, :manual)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
defaultto :manual
|
||||
end
|
||||
|
||||
# newproperty(:port_type) do
|
||||
# desc "port_type fake RO property"
|
||||
# end
|
||||
|
||||
newproperty(:if_type) do
|
||||
desc "Device type. Service property, shouldn't be setting by puppet"
|
||||
newvalues(:ethernet, :bridge, :bond)
|
||||
end
|
||||
|
||||
newproperty(:bridge, :array_matching => :all) do
|
||||
# Array_matching for this property required for very complicated cases
|
||||
# ex. patchcord for connectind two bridges or bridge and network namesspace
|
||||
desc "Name of bridge, including this port"
|
||||
newvalues(/^[\w+\-]+$/, :none, :undef, :nil, :absent)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
defaultto :absent
|
||||
end
|
||||
|
||||
newproperty(:jacks, :array_matching => :all) do
|
||||
desc "Name of jacks for patchcord"
|
||||
newvalues(/^[\w+\-]+$/)
|
||||
end
|
||||
|
||||
newproperty(:bridge_ports, :array_matching => :all) do
|
||||
desc "Ports, member of bridge, service property, do not use directly."
|
||||
end
|
||||
|
||||
newproperty(:bridge_stp) do
|
||||
desc "Whether stp enable"
|
||||
newvalues(:true, :absent, :yes, :on, :false, :no, :off)
|
||||
aliasvalue(:yes, :true)
|
||||
aliasvalue(:on, :true)
|
||||
aliasvalue(:no, :false)
|
||||
aliasvalue(:off, :false)
|
||||
defaultto :absent
|
||||
end
|
||||
|
||||
newproperty(:onboot) do
|
||||
desc "Whether to bring the interface up on boot"
|
||||
newvalues(:true, :yes, :on, :false, :no, :off)
|
||||
aliasvalue(:yes, :true)
|
||||
aliasvalue(:on, :true)
|
||||
aliasvalue(:no, :false)
|
||||
aliasvalue(:off, :false)
|
||||
defaultto :true
|
||||
end
|
||||
|
||||
newproperty(:mtu) do
|
||||
desc "The Maximum Transmission Unit size to use for the interface"
|
||||
newvalues(/^\d+$/, :absent, :none, :undef, :nil)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
aliasvalue(0, :absent)
|
||||
defaultto :absent # MTU value should be undefined by default, because some network resources (bridges, subinterfaces)
|
||||
validate do |value| # inherits it from a parent interface
|
||||
# Intel 82598 & 82599 chips support MTUs up to 16110; is there any
|
||||
# hardware in the wild that supports larger frames?
|
||||
#
|
||||
# It appears loopback devices routinely have large MTU values; Eg. 65536
|
||||
#
|
||||
# Frames small than 64bytes are discarded as runts. Smallest valid MTU
|
||||
# is 42 with a 802.1q header and 46 without.
|
||||
min_mtu = 42
|
||||
max_mtu = 65536
|
||||
if ! (value.to_s == 'absent' or (min_mtu .. max_mtu).include?(value.to_i))
|
||||
raise ArgumentError, "'#{value}' is not a valid mtu (must be a positive integer in range (#{min_mtu} .. #{max_mtu})"
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
((val == :absent) ? :absent : val.to_i)
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:vlan_dev) do
|
||||
desc "802.1q vlan base device"
|
||||
end
|
||||
|
||||
newproperty(:vlan_id) do
|
||||
desc "802.1q vlan ID"
|
||||
newvalues(/^\d+$/, :absent, :none, :undef, :nil)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
aliasvalue(0, :absent)
|
||||
defaultto :absent
|
||||
validate do |val|
|
||||
min_vid = 1
|
||||
max_vid = 4094
|
||||
if ! (val.to_s == 'absent' or (min_vid .. max_vid).include?(val.to_i))
|
||||
raise ArgumentError, "'#{val}' is not a valid 802.1q NALN_ID (must be a integer value in range (#{min_vid} .. #{max_vid})"
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
((val == :absent) ? :absent : val.to_i)
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:vlan_mode) do
|
||||
desc "802.1q vlan interface naming model"
|
||||
#newvalues(:ethernet, :bridge, :bond)
|
||||
#defaultto :ethernet
|
||||
end
|
||||
|
||||
|
||||
newproperty(:ipaddr) do
|
||||
desc "Primary IP address for interface"
|
||||
newvalues(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}$/, :absent, :none, :undef, :nil, :dhcp)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
defaultto :absent
|
||||
end
|
||||
|
||||
newproperty(:gateway) do
|
||||
desc "Default gateway"
|
||||
newvalues(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/, :absent, :none, :undef, :nil)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
defaultto :absent
|
||||
end
|
||||
|
||||
newproperty(:gateway_metric) do
|
||||
desc "Default gateway metric"
|
||||
newvalues(/^\d+$/, :absent, :none, :undef, :nil)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
aliasvalue(0, :absent)
|
||||
defaultto :absent
|
||||
validate do |val|
|
||||
min_metric = 0
|
||||
max_metric = 65535
|
||||
if ! (val.to_s == 'absent' or (min_metric .. max_metric).include?(val.to_i))
|
||||
raise ArgumentError, "'#{val}' is not a valid metric (must be a integer value in range (#{min_metric} .. #{max_metric})"
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
((val == :absent) ? :absent : val.to_i)
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:bond_master) do
|
||||
desc "bond name for bonded interface"
|
||||
newvalues(/^[\w+\-]+$/, :none, :undef, :nil, :absent)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
defaultto :absent
|
||||
end
|
||||
|
||||
newproperty(:bond_slaves, :array_matching => :all) do
|
||||
desc "slave ports for bond interface"
|
||||
newvalues(/^[\w+\-]+$/, :false, :none, :undef, :nil, :absent)
|
||||
#aliasvalue(:absent, :none) # none is a valid config value
|
||||
aliasvalue(:false, :none)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
defaultto :absent
|
||||
end
|
||||
|
||||
newproperty(:bond_mode)
|
||||
newproperty(:bond_miimon)
|
||||
newproperty(:bond_lacp_rate)
|
||||
|
||||
# # `:options` provides an arbitrary passthrough for provider properties, so
|
||||
# # that provider specific behavior doesn't clutter up the main type but still
|
||||
# # allows for more powerful actions to be taken.
|
||||
# newproperty(:options, :required_features => :provider_options) do
|
||||
# desc "Provider specific options to be passed to the provider"
|
||||
|
||||
# def is_to_s(hash = @is)
|
||||
# hash.keys.sort.map {|key| "#{key} => #{hash[key]}"}.join(", ")
|
||||
# end
|
||||
|
||||
# def should_to_s(hash = @should)
|
||||
# hash.keys.sort.map {|key| "#{key} => #{hash[key]}"}.join(", ")
|
||||
# end
|
||||
|
||||
# defaultto {}
|
||||
|
||||
# validate do |value|
|
||||
# raise ArgumentError, "#{self.class} requires a hash for the options property" unless value.is_a? Hash
|
||||
# #provider.validate
|
||||
# end
|
||||
# end
|
||||
|
||||
newproperty(:vendor_specific) do
|
||||
desc "Hash of vendor specific properties"
|
||||
#defaultto {} # no default value should be!!!
|
||||
# provider-specific properties, can be validating only by provider.
|
||||
validate do |val|
|
||||
if ! val.is_a? Hash
|
||||
fail("Vendor_specific should be a hash!")
|
||||
end
|
||||
end
|
||||
|
||||
munge do |value|
|
||||
L23network.reccursive_sanitize_hash(value)
|
||||
end
|
||||
|
||||
def should_to_s(value)
|
||||
"\n#{value.to_yaml}\n"
|
||||
end
|
||||
|
||||
def is_to_s(value)
|
||||
"\n#{value.to_yaml}\n"
|
||||
end
|
||||
|
||||
def insync?(value)
|
||||
should_to_s(value) == should_to_s(should)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def generate
|
||||
return if ! (!([:absent, :none, :nil, :undef] & self[:bridge]).any? \
|
||||
and [:ethernet, :bond].include? self[:if_type]
|
||||
)
|
||||
self[:bridge].each do |bridge|
|
||||
br = self.catalog.resource('L23_stored_config', bridge)
|
||||
fail("Stored_config resource for bridge '#{bridge}' not found for port '#{self[:name]}'!") if ! br
|
||||
br[:bridge_ports] ||= []
|
||||
ports = br[:bridge_ports]
|
||||
return if ! ports.is_a? Array
|
||||
if ! ports.include? self[:name]
|
||||
ports << self[:name].to_s
|
||||
br[:bridge_ports] = ports.reject{|a| a=='none'}.sort
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,213 @@
|
|||
# type for managing runtime bond of NICs states.
|
||||
|
||||
Puppet::Type.newtype(:l2_bond) do
|
||||
@doc = "Manage a network port abctraction."
|
||||
desc @doc
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:bond) do
|
||||
isnamevar
|
||||
desc "The bond name"
|
||||
#
|
||||
validate do |val|
|
||||
if not val =~ /^[a-z_][\w\.\-]*[0-9a-z]$/
|
||||
fail("Invalid bond name: '#{val}'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:use_ovs) do
|
||||
desc "Whether using OVS comandline tools"
|
||||
newvalues(:true, :yes, :on, :false, :no, :off)
|
||||
aliasvalue(:yes, :true)
|
||||
aliasvalue(:on, :true)
|
||||
aliasvalue(:no, :false)
|
||||
aliasvalue(:off, :false)
|
||||
defaultto :true
|
||||
end
|
||||
|
||||
newproperty(:port_type) do
|
||||
desc "Internal read-only property"
|
||||
validate do |value|
|
||||
raise ArgumentError, "You shouldn't change port_type -- it's a internal RO property!"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
newproperty(:onboot) do
|
||||
desc "Whether to bring the interface up"
|
||||
newvalues(:true, :yes, :on, :false, :no, :off)
|
||||
aliasvalue(:yes, :true)
|
||||
aliasvalue(:on, :true)
|
||||
aliasvalue(:no, :false)
|
||||
aliasvalue(:off, :false)
|
||||
defaultto :true
|
||||
end
|
||||
|
||||
newproperty(:bridge) do
|
||||
desc "What bridge to use"
|
||||
newvalues(/^[a-z][0-9a-z\-\_]*[0-9a-z]$/, :absent, :none, :undef, :nil)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
defaultto :absent
|
||||
end
|
||||
|
||||
newproperty(:slaves, :array_matching => :all) do
|
||||
desc "What bridge to use"
|
||||
newvalues(/^[a-z][0-9a-z\-\_]*[0-9a-z]$/, :absent, :none, :undef, :nil)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
defaultto :absent
|
||||
# provider-specific list. may be empty.
|
||||
def should_to_s(value)
|
||||
value == :absent ? value : value.sort.join(',')
|
||||
end
|
||||
def is_to_s(value)
|
||||
should_to_s(value)
|
||||
end
|
||||
def insync?(value)
|
||||
should_to_s(value) == should_to_s(should)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
newparam(:trunks, :array_matching => :all) do
|
||||
desc "Array of trunks id, for configure patch's ends as ports in trunk mode"
|
||||
end
|
||||
|
||||
newproperty(:interface_properties) do
|
||||
desc "Hash of bonded interfaces properties"
|
||||
#defaultto {}
|
||||
# provider-specific hash, validating only by type.
|
||||
validate do |val|
|
||||
if ! val.is_a? Hash
|
||||
fail("Interface_properties should be a hash!")
|
||||
end
|
||||
end
|
||||
|
||||
def should_to_s(value)
|
||||
return :absent if value == :absent
|
||||
rv = []
|
||||
value.keys.sort.each do |key|
|
||||
rv << "(#{key.to_s}=#{value[key]})"
|
||||
end
|
||||
rv.join(', ')
|
||||
end
|
||||
|
||||
def is_to_s(value)
|
||||
should_to_s(value)
|
||||
end
|
||||
|
||||
def insync?(value)
|
||||
should_to_s(value) == should_to_s(should)
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:bond_properties) do
|
||||
desc "Hash of bond properties"
|
||||
#defaultto {}
|
||||
# provider-specific hash, validating only by type.
|
||||
validate do |val|
|
||||
#puts "l2_bond validate got '#{val.inspect}'"
|
||||
if ! val.is_a? Hash
|
||||
fail("Interface_properties should be a hash!")
|
||||
end
|
||||
end
|
||||
|
||||
munge do |val|
|
||||
# it's a workaround, because puppet double some values inside his internal logic
|
||||
val.keys.each do |k|
|
||||
if k.is_a? String
|
||||
if ! val.has_key? k.to_sym
|
||||
val[k.to_sym] = val[k]
|
||||
end
|
||||
val.delete(k)
|
||||
end
|
||||
end
|
||||
val
|
||||
end
|
||||
|
||||
def should_to_s(value)
|
||||
return '' if [:absent, 'absent', nil, {}].include? value
|
||||
value.keys.sort.map{|k| "(#{k.to_s}=#{value[k]})"}.join(', ')
|
||||
end
|
||||
|
||||
def is_to_s(value)
|
||||
should_to_s(value)
|
||||
end
|
||||
|
||||
def insync?(value)
|
||||
should_to_s(value) == should_to_s(should)
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:mtu) do
|
||||
desc "The Maximum Transmission Unit size to use for the interface"
|
||||
newvalues(/^\d+$/, :absent, :none, :undef, :nil)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
aliasvalue(0, :absent)
|
||||
defaultto :absent # MTU value should be undefined by default, because some network resources (bridges, subinterfaces)
|
||||
validate do |value| # inherits it from a parent interface
|
||||
# Intel 82598 & 82599 chips support MTUs up to 16110; is there any
|
||||
# hardware in the wild that supports larger frames?
|
||||
#
|
||||
# It appears loopback devices routinely have large MTU values; Eg. 65536
|
||||
#
|
||||
# Frames small than 64bytes are discarded as runts. Smallest valid MTU
|
||||
# is 42 with a 802.1q header and 46 without.
|
||||
min_mtu = 42
|
||||
max_mtu = 65536
|
||||
if ! (value.to_s == 'absent' or (min_mtu .. max_mtu).include?(value.to_i))
|
||||
raise ArgumentError, "'#{value}' is not a valid mtu (must be a positive integer in range (#{min_mtu} .. #{max_mtu})"
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
((val == :absent) ? :absent : val.to_i)
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:vendor_specific) do
|
||||
desc "Hash of vendor specific properties"
|
||||
#defaultto {} # no default value should be!!!
|
||||
# provider-specific properties, can be validating only by provider.
|
||||
validate do |val|
|
||||
if ! val.is_a? Hash
|
||||
fail("Vendor_specific should be a hash!")
|
||||
end
|
||||
end
|
||||
|
||||
munge do |value|
|
||||
L23network.reccursive_sanitize_hash(value)
|
||||
end
|
||||
|
||||
def should_to_s(value)
|
||||
"\n#{value.to_yaml}\n"
|
||||
end
|
||||
|
||||
def is_to_s(value)
|
||||
"\n#{value.to_yaml}\n"
|
||||
end
|
||||
|
||||
def insync?(value)
|
||||
should_to_s(value) == should_to_s(should)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
autorequire(:l2_bridge) do
|
||||
[self[:bridge]]
|
||||
end
|
||||
|
||||
# def validate
|
||||
# if self[:name].to_s == 'bond23'
|
||||
# require 'pry'
|
||||
# binding.pry
|
||||
# end
|
||||
# end
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,115 @@
|
|||
#
|
||||
Puppet::Type.newtype(:l2_bridge) do
|
||||
@doc = "Manage a native linux and open vSwitch bridges (virtual switches)"
|
||||
desc @doc
|
||||
|
||||
ensurable
|
||||
|
||||
MAX_BR_NAME_LENGTH = 15
|
||||
|
||||
newparam(:bridge) do
|
||||
isnamevar
|
||||
desc "The bridge to configure"
|
||||
#
|
||||
validate do |val|
|
||||
if not val =~ /^[a-z][0-9a-z\.\-\_]*[0-9a-z]$/
|
||||
fail("Wrong bridge name: '#{val}'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:use_ovs) do
|
||||
desc "Whether using OVS comandline tools"
|
||||
newvalues(:true, :yes, :on, :false, :no, :off)
|
||||
aliasvalue(:yes, :true)
|
||||
aliasvalue(:on, :true)
|
||||
aliasvalue(:no, :false)
|
||||
aliasvalue(:off, :false)
|
||||
defaultto :true
|
||||
end
|
||||
|
||||
newproperty(:external_ids) do
|
||||
desc "External IDs for the bridge"
|
||||
#defaultto {} # do not use defaultto here!!!
|
||||
|
||||
validate do |val|
|
||||
if ! val.is_a? Hash
|
||||
fail("External_ids should be a hash!")
|
||||
end
|
||||
end
|
||||
def should_to_s(value)
|
||||
return [] if value == :absent
|
||||
rv = []
|
||||
value.keys.sort.each do |key|
|
||||
rv << "(#{key.to_s}=#{value[key]})"
|
||||
end
|
||||
rv.join(', ')
|
||||
end
|
||||
|
||||
def is_to_s(value)
|
||||
should_to_s(value)
|
||||
end
|
||||
|
||||
def insync?(value)
|
||||
should_to_s(value) == should_to_s(should)
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:br_type) do
|
||||
desc "Internal read-only property"
|
||||
validate do |value|
|
||||
raise ArgumentError, "You shouldn't change br_type -- it's a internal RO property!"
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:stp) do
|
||||
desc "Whether stp enable"
|
||||
newvalues(:true, :yes, :on, :false, :no, :off)
|
||||
aliasvalue(:yes, :true)
|
||||
aliasvalue(:on, :true)
|
||||
aliasvalue(:no, :false)
|
||||
aliasvalue(:off, :false)
|
||||
defaultto :false
|
||||
end
|
||||
|
||||
newproperty(:vendor_specific) do
|
||||
desc "Hash of vendor specific properties"
|
||||
#defaultto {} # no default value should be!!!
|
||||
# provider-specific properties, can be validating only by provider.
|
||||
validate do |val|
|
||||
if ! val.is_a? Hash
|
||||
fail("Vendor_specific should be a hash!")
|
||||
end
|
||||
end
|
||||
|
||||
munge do |value|
|
||||
L23network.reccursive_sanitize_hash(value)
|
||||
end
|
||||
|
||||
def should_to_s(value)
|
||||
"\n#{value.to_yaml}\n"
|
||||
end
|
||||
|
||||
def is_to_s(value)
|
||||
"\n#{value.to_yaml}\n"
|
||||
end
|
||||
|
||||
def insync?(value)
|
||||
should_to_s(value) == should_to_s(should)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# global validator
|
||||
def validate
|
||||
# require 'pry'
|
||||
# binding.pry
|
||||
if provider.class.name != :ovs and self[:name].length > MAX_BR_NAME_LENGTH
|
||||
# validate name for differetn providers may only in global validator, because
|
||||
# 'provider' option don't accessible while validating name
|
||||
fail("Wrong bridge name '#{self[:name]}'.\n For provider '#{provider.class.name}' bridge name shouldn't has length more, than #{MAX_BR_NAME_LENGTH}.")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -1,89 +0,0 @@
|
|||
Puppet::Type.newtype(:l2_ovs_bond) do
|
||||
@doc = "Manage a Open vSwitch port"
|
||||
desc @doc
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:bond) do
|
||||
isnamevar
|
||||
desc "The bond name"
|
||||
#
|
||||
validate do |val|
|
||||
if not (val =~ /^[a-zA-Z][0-9a-zA-Z\.\-\_]*[0-9a-zA-Z]$/)
|
||||
fail("Invalid bond name: '#{val}'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:interfaces) do
|
||||
desc "List of interfaces that will be added to the bond"
|
||||
#
|
||||
validate do |val|
|
||||
if not (val.is_a?(Array) and val.size() >= 2)
|
||||
fail("Interfaces parameter must be an array of two or more interface names.")
|
||||
end
|
||||
for ii in val
|
||||
if not (ii =~ /^[a-zA-Z][0-9a-zA-Z\.\-\_]*[0-9a-zA-Z]$/)
|
||||
fail("Invalid port name: '#{ii}'")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:skip_existing) do
|
||||
defaultto(false)
|
||||
desc "Allow to skip existing bond"
|
||||
end
|
||||
|
||||
newparam(:properties) do
|
||||
defaultto([])
|
||||
desc "Array of bond properties"
|
||||
munge do |val|
|
||||
Array(val)
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:bridge) do
|
||||
desc "What bridge to use"
|
||||
#
|
||||
validate do |val|
|
||||
if not (val =~ /^[a-zA-Z][0-9a-zA-Z\.\-\_]*[0-9a-zA-Z]$/)
|
||||
fail("Invalid bridge name: '#{val}'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:vlan_id) do
|
||||
defaultto(0)
|
||||
desc "802.1q tag"
|
||||
validate do |val|
|
||||
if !val.is_a?(Integer) or (val < 0 or val > 4094)
|
||||
fail("Wrong 802.1q tag. Tag must be an integer in 2..4094 interval")
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
val.to_i
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:trunks, :array_matching => :all) do
|
||||
defaultto([])
|
||||
desc "Array of trunks id, for configure patch's ends as ports in trunk mode"
|
||||
#
|
||||
validate do |val|
|
||||
val = Array(val) # prevents puppet conversion array of one Int to Int
|
||||
for i in val
|
||||
if !i.is_a?(Integer) or (i < 0 or i > 4094)
|
||||
fail("Wrong 802.1q tag. Tag must be an integer in 2..4094 interval")
|
||||
end
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
Array(val)
|
||||
end
|
||||
end
|
||||
|
||||
autorequire(:l2_ovs_bridge) do
|
||||
[self[:bridge]]
|
||||
end
|
||||
end
|
|
@ -1,26 +0,0 @@
|
|||
Puppet::Type.newtype(:l2_ovs_bridge) do
|
||||
@doc = "Manage a Open vSwitch bridge (virtual switch)"
|
||||
desc @doc
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:bridge) do
|
||||
isnamevar
|
||||
desc "The bridge to configure"
|
||||
#
|
||||
validate do |val|
|
||||
if not val =~ /^[a-z][0-9a-z\.\-\_]*[0-9a-z]$/
|
||||
fail("Invalid bridge name: '#{val}'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:skip_existing) do
|
||||
defaultto(false)
|
||||
desc "Allow to skip existing bridge"
|
||||
end
|
||||
|
||||
newproperty(:external_ids) do
|
||||
desc "External IDs for the bridge"
|
||||
end
|
||||
end
|
|
@ -1,81 +0,0 @@
|
|||
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, :array_matching => :all) do
|
||||
desc "Array of bridges that will be connected"
|
||||
#
|
||||
validate do |val|
|
||||
if !val.is_a?(Array) or 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, :array_matching => :all) do
|
||||
defaultto([nil,nil])
|
||||
desc "List of names that will be used for naming patches at it's ends."
|
||||
#
|
||||
validate do |val|
|
||||
if !val.is_a?(Array) or 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(:vlan_ids, :array_matching => :all) do
|
||||
defaultto([0,0])
|
||||
desc "Array of 802.1q tag for ends."
|
||||
#
|
||||
validate do |val|
|
||||
if !val.is_a?(Array) or val.size() != 2
|
||||
fail("Must be an array of two integers")
|
||||
end
|
||||
for i in val
|
||||
if !i.is_a?(Integer) or (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, :array_matching => :all) do
|
||||
defaultto([])
|
||||
desc "Array of trunks id, for configure patch's ends as ports in trunk mode"
|
||||
#
|
||||
validate do |val|
|
||||
val = Array(val) # prevents puppet conversion array of one Int to Int
|
||||
for i in val
|
||||
if !i.is_a?(Integer) or (i < 0 or i > 4094)
|
||||
fail("Wrong 802.1q tag. Tag must be an integer in 2..4094 interval")
|
||||
end
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
Array(val)
|
||||
end
|
||||
end
|
||||
|
||||
autorequire(:l2_ovs_bridge) do
|
||||
self[:bridges]
|
||||
end
|
||||
end
|
|
@ -1,94 +0,0 @@
|
|||
Puppet::Type.newtype(:l2_ovs_port) do
|
||||
@doc = "Manage a Open vSwitch port"
|
||||
desc @doc
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:interface) do
|
||||
isnamevar
|
||||
desc "The interface to attach to the bridge"
|
||||
#
|
||||
validate do |val|
|
||||
if not val =~ /^[a-z][0-9a-z\.\-\_]*[0-9a-z]$/
|
||||
fail("Invalid interface name: '#{val}'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:type) do
|
||||
newvalues('', :system, :internal, :tap, :gre, :ipsec_gre, :capwap, :patch, :null)
|
||||
defaultto('')
|
||||
desc "Ovs port type"
|
||||
end
|
||||
|
||||
newparam(:skip_existing) do
|
||||
defaultto(false)
|
||||
desc "Allow to skip existing port"
|
||||
end
|
||||
|
||||
newparam(:bridge) do
|
||||
desc "What bridge to use"
|
||||
#
|
||||
validate do |val|
|
||||
if not val =~ /^[a-z][0-9a-z\.\-\_]*[0-9a-z]$/
|
||||
fail("Invalid bridge name: '#{val}'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:port_properties, :array_matching => :all) do
|
||||
defaultto([])
|
||||
desc "Array of port properties"
|
||||
munge do |val|
|
||||
Array(val)
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:interface_properties) do
|
||||
defaultto([])
|
||||
desc "Array of port interface properties"
|
||||
munge do |val|
|
||||
Array(val)
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:vlan_id) do
|
||||
defaultto(0)
|
||||
desc "802.1q tag"
|
||||
validate do |val|
|
||||
if !val.is_a?(Integer) or (val < 0 or val > 4094)
|
||||
fail("Wrong 802.1q tag. Tag must be an integer in 2..4094 interval")
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
val.to_i
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:trunks, :array_matching => :all) do
|
||||
defaultto([])
|
||||
desc "Array of trunks id, for configure patch's ends as ports in trunk mode"
|
||||
#
|
||||
validate do |val|
|
||||
val = Array(val) # prevents puppet conversion array of one Int to Int
|
||||
for i in val
|
||||
if !i.is_a?(Integer) or (i < 0 or i > 4094)
|
||||
fail("Wrong 802.1q tag. Tag must be an integer in 2..4094 interval")
|
||||
end
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
Array(val)
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:vlan_splinters) do
|
||||
newvalues(true, false)
|
||||
defaultto(false)
|
||||
desc "Enable vlan splinters (if it's a phys. interface)"
|
||||
end
|
||||
|
||||
autorequire(:l2_ovs_bridge) do
|
||||
[self[:bridge]]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,92 @@
|
|||
Puppet::Type.newtype(:l2_patch) do
|
||||
@doc = "Manage a patchcords 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(:use_ovs) do
|
||||
desc "Whether using OVS comandline tools"
|
||||
newvalues(:true, :yes, :on, :false, :no, :off)
|
||||
aliasvalue(:yes, :true)
|
||||
aliasvalue(:on, :true)
|
||||
aliasvalue(:no, :false)
|
||||
aliasvalue(:off, :false)
|
||||
defaultto :true
|
||||
end
|
||||
|
||||
newproperty(:bridges, :array_matching => :all) do
|
||||
desc "Array of bridges that will be connected"
|
||||
newvalues(/^[a-z][0-9a-z\-\_]*[0-9a-z]$/)
|
||||
end
|
||||
|
||||
newproperty(:jacks, :array_matching => :all) do
|
||||
desc "Patchcord jacks. Read-only. for debug purpose."
|
||||
end
|
||||
|
||||
newproperty(:cross) do
|
||||
desc "Cross-system patch. Read-only. for debug purpose."
|
||||
end
|
||||
|
||||
newproperty(:mtu) do
|
||||
desc "The Maximum Transmission Unit size to use for the interface"
|
||||
newvalues(/^\d+$/, :absent, :none, :undef, :nil)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
aliasvalue(0, :absent)
|
||||
defaultto :absent # MTU value should be undefined by default, because some network resources (bridges, subinterfaces)
|
||||
validate do |value| # inherits it from a parent interface
|
||||
# Intel 82598 & 82599 chips support MTUs up to 16110; is there any
|
||||
# hardware in the wild that supports larger frames?
|
||||
#
|
||||
# It appears loopback devices routinely have large MTU values; Eg. 65536
|
||||
#
|
||||
# Frames small than 64bytes are discarded as runts. Smallest valid MTU
|
||||
# is 42 with a 802.1q header and 46 without.
|
||||
min_mtu = 42
|
||||
max_mtu = 65536
|
||||
if ! (value.to_s == 'absent' or (min_mtu .. max_mtu).include?(value.to_i))
|
||||
raise ArgumentError, "'#{value}' is not a valid mtu (must be a positive integer in range (#{min_mtu} .. #{max_mtu})"
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
((val == :absent) ? :absent : val.to_i)
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:vendor_specific) do
|
||||
desc "Hash of vendor specific properties"
|
||||
#defaultto {} # no default value should be!!!
|
||||
# provider-specific properties, can be validating only by provider.
|
||||
validate do |val|
|
||||
if ! val.is_a? Hash
|
||||
fail("Vendor_specific should be a hash!")
|
||||
end
|
||||
end
|
||||
|
||||
munge do |value|
|
||||
L23network.reccursive_sanitize_hash(value)
|
||||
end
|
||||
|
||||
def should_to_s(value)
|
||||
"\n#{value.to_yaml}\n"
|
||||
end
|
||||
|
||||
def is_to_s(value)
|
||||
"\n#{value.to_yaml}\n"
|
||||
end
|
||||
|
||||
def insync?(value)
|
||||
should_to_s(value) == should_to_s(should)
|
||||
end
|
||||
end
|
||||
|
||||
autorequire(:l2_bridge) do
|
||||
self[:bridges]
|
||||
end
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,222 @@
|
|||
# type for managing runtime NIC states.
|
||||
|
||||
require 'yaml'
|
||||
require 'puppetx/l23_utils'
|
||||
|
||||
Puppet::Type.newtype(:l2_port) do
|
||||
@doc = "Manage a network port abctraction."
|
||||
desc @doc
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:interface) do
|
||||
isnamevar
|
||||
desc "The interface name"
|
||||
#
|
||||
validate do |val|
|
||||
if not val =~ /^[a-z_][\w\.\-]*[0-9a-z]$/
|
||||
fail("Invalid interface name: '#{val}'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:use_ovs) do
|
||||
desc "Whether using OVS comandline tools"
|
||||
newvalues(:true, :yes, :on, :false, :no, :off)
|
||||
aliasvalue(:yes, :true)
|
||||
aliasvalue(:on, :true)
|
||||
aliasvalue(:no, :false)
|
||||
aliasvalue(:off, :false)
|
||||
defaultto :true
|
||||
end
|
||||
|
||||
#todo(sv): move to provider_specific hash
|
||||
newproperty(:type) do
|
||||
newvalues(:system, :internal, :tap, :gre, :ipsec_gre, :capwap, :patch, :null, :undef, :nil, :none)
|
||||
aliasvalue(:none, :internal)
|
||||
aliasvalue(:undef, :internal)
|
||||
aliasvalue(:nil, :internal)
|
||||
aliasvalue(:null, :internal)
|
||||
#defaultto :internal
|
||||
desc "Port type (for openvswitch only)"
|
||||
end
|
||||
|
||||
newproperty(:port_type) do
|
||||
desc "Internal read-only property"
|
||||
validate do |value|
|
||||
raise ArgumentError, "You shouldn't change port_type -- it's a internal RO property!"
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:onboot) do
|
||||
desc "Whether to bring the interface up"
|
||||
newvalues(:true, :yes, :on, :false, :no, :off)
|
||||
aliasvalue(:yes, :true)
|
||||
aliasvalue(:on, :true)
|
||||
aliasvalue(:no, :false)
|
||||
aliasvalue(:off, :false)
|
||||
defaultto :true
|
||||
end
|
||||
|
||||
newproperty(:bridge) do
|
||||
desc "What bridge to use"
|
||||
#
|
||||
validate do |val|
|
||||
if not val =~ /^[a-z][0-9a-z\-\_]*[0-9a-z]$/
|
||||
fail("Invalid bridge name: '#{val}'")
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
if ['nil', 'undef', 'none', 'absent', ''].include?(val.to_s)
|
||||
:absent
|
||||
else
|
||||
val
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:port_properties, :array_matching => :all) do
|
||||
desc "Array of port properties"
|
||||
defaultto []
|
||||
end
|
||||
|
||||
newparam(:interface_properties, :array_matching => :all) do
|
||||
desc "Array of port interface properties"
|
||||
defaultto []
|
||||
end
|
||||
|
||||
newproperty(:vlan_dev) do
|
||||
desc "802.1q vlan base device"
|
||||
end
|
||||
|
||||
newproperty(:vlan_id) do
|
||||
desc "802.1q vlan ID"
|
||||
newvalues(/^\d+$/, :absent, :none, :undef, :nil)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
aliasvalue(0, :absent)
|
||||
defaultto :absent
|
||||
validate do |value|
|
||||
min_vid = 1
|
||||
max_vid = 4094
|
||||
if ! (value.to_s == 'absent' or (min_vid .. max_vid).include?(value.to_i))
|
||||
raise ArgumentError, "'#{value}' is not a valid 802.1q NALN_ID (must be a integer value in range (#{min_vid} .. #{max_vid})"
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
((val == :absent) ? :absent : val.to_i)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
newproperty(:vlan_mode) do
|
||||
desc "802.1q vlan interface naming model"
|
||||
end
|
||||
|
||||
newproperty(:bond_master) do
|
||||
desc "Bond name, if interface is a part of bond"
|
||||
newvalues(/^[a-z][\w\-]*$/, :absent, :none, :undef, :nil)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
defaultto :absent
|
||||
end
|
||||
|
||||
newparam(:trunks, :array_matching => :all) do
|
||||
desc "Array of trunks id, for configure patch's ends as ports in trunk mode"
|
||||
end
|
||||
|
||||
newproperty(:mtu) do
|
||||
desc "The Maximum Transmission Unit size to use for the interface"
|
||||
newvalues(/^\d+$/, :absent, :none, :undef, :nil)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
aliasvalue(0, :absent)
|
||||
defaultto :absent # MTU value should be undefined by default, because some network resources (bridges, subinterfaces)
|
||||
validate do |value| # inherits it from a parent interface
|
||||
# Intel 82598 & 82599 chips support MTUs up to 16110; is there any
|
||||
# hardware in the wild that supports larger frames?
|
||||
#
|
||||
# It appears loopback devices routinely have large MTU values; Eg. 65536
|
||||
#
|
||||
# Frames small than 64bytes are discarded as runts. Smallest valid MTU
|
||||
# is 42 with a 802.1q header and 46 without.
|
||||
min_mtu = 42
|
||||
max_mtu = 65536
|
||||
if ! (value.to_s == 'absent' or (min_mtu .. max_mtu).include?(value.to_i))
|
||||
raise ArgumentError, "'#{value}' is not a valid mtu (must be a positive integer in range (#{min_mtu} .. #{max_mtu})"
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
((val == :absent) ? :absent : val.to_i)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
newproperty(:ethtool) do
|
||||
desc "Hash of ethtool properties"
|
||||
#defaultto {}
|
||||
# provider-specific hash, validating only by type.
|
||||
validate do |val|
|
||||
if ! val.is_a? Hash
|
||||
fail("Ethtool should be a hash!")
|
||||
end
|
||||
end
|
||||
munge do |value|
|
||||
L23network.reccursive_sanitize_hash(value)
|
||||
end
|
||||
|
||||
def should_to_s(value)
|
||||
"\n#{value.to_yaml}\n"
|
||||
end
|
||||
|
||||
def is_to_s(value)
|
||||
"\n#{value.to_yaml}\n"
|
||||
end
|
||||
|
||||
def insync?(value)
|
||||
new_should = {}
|
||||
(value.keys + should.keys).uniq.map{|k| new_should[k] = {}}
|
||||
# debug("\nV: #{value.to_yaml}\n")
|
||||
# debug("\nS: #{should.to_yaml}\n")
|
||||
# debug("\nN: #{new_should.to_yaml}\n")
|
||||
new_should.keys.map{|key| new_should[key] = value[key].merge should[key] }
|
||||
#debug("\nZ: #{new_should.to_yaml}\n")
|
||||
(L23network.reccursive_sanitize_hash(value) == L23network.reccursive_sanitize_hash(new_should))
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:vendor_specific) do
|
||||
desc "Hash of vendor specific properties"
|
||||
#defaultto {} # no default value should be!!!
|
||||
# provider-specific properties, can be validating only by provider.
|
||||
validate do |val|
|
||||
if ! val.is_a? Hash
|
||||
fail("Vendor_specific should be a hash!")
|
||||
end
|
||||
end
|
||||
|
||||
munge do |value|
|
||||
L23network.reccursive_sanitize_hash(value)
|
||||
end
|
||||
|
||||
def should_to_s(value)
|
||||
"\n#{value.to_yaml}\n"
|
||||
end
|
||||
|
||||
def is_to_s(value)
|
||||
"\n#{value.to_yaml}\n"
|
||||
end
|
||||
|
||||
def insync?(value)
|
||||
should_to_s(value) == should_to_s(should)
|
||||
end
|
||||
end
|
||||
|
||||
autorequire(:l2_bridge) do
|
||||
[self[:bridge]]
|
||||
end
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -82,7 +82,8 @@ Puppet::Type.newtype(:l3_if_downup) do
|
|||
provider.restart()
|
||||
end
|
||||
|
||||
# autorequire(:l2_ovs_bridge) do
|
||||
# autorequire(:l2_bridge) do
|
||||
# [self[:bridge]]
|
||||
# end
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,148 @@
|
|||
# type for managing runtime IP addresses and another L3 stuff.
|
||||
|
||||
Puppet::Type.newtype(:l3_ifconfig) do
|
||||
@doc = "Manage a network port abctraction."
|
||||
desc @doc
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:interface) do
|
||||
isnamevar
|
||||
desc "The interface name"
|
||||
#
|
||||
validate do |val|
|
||||
if not val =~ /^[a-z_][0-9a-z\.\-\_]*[0-9a-z]$/
|
||||
fail("Invalid interface name: '#{val}'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:use_ovs) do
|
||||
desc "Whether using OVS comandline tools"
|
||||
newvalues(:true, :yes, :on, :false, :no, :off)
|
||||
aliasvalue(:yes, :true)
|
||||
aliasvalue(:on, :true)
|
||||
aliasvalue(:no, :false)
|
||||
aliasvalue(:off, :false)
|
||||
defaultto :true
|
||||
end
|
||||
|
||||
newproperty(:port_type) do
|
||||
desc "Internal read-only property"
|
||||
validate do |value|
|
||||
raise ArgumentError, "You shouldn't change port_type -- it's a internal RO property!"
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:ipaddr, :array_matching => :all) do
|
||||
desc "List of IP address for this interface"
|
||||
newvalues(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(\/(\d{1,2}))?$/, :absent, :none, :undef, :nil)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
validate do |val|
|
||||
return true if [:dhcp, :none, :undef, :nil, :absent].include?(val.downcase.to_sym)
|
||||
val.strip!
|
||||
raise ArgumentError, "Invalid IP address in list: '#{val}'" if \
|
||||
not val.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(\/(\d{1,2}))?$/) \
|
||||
or not ($1.to_i >= 0 and $1.to_i <= 255) \
|
||||
or not ($2.to_i >= 0 and $2.to_i <= 255) \
|
||||
or not ($3.to_i >= 0 and $3.to_i <= 255) \
|
||||
or not ($4.to_i >= 0 and $4.to_i <= 255) \
|
||||
or not ($6.to_i >= 0 and $6.to_i <= 32)
|
||||
end
|
||||
def should_to_s(value)
|
||||
value.inspect
|
||||
end
|
||||
def is_to_s(value)
|
||||
value.inspect
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:gateway) do
|
||||
desc "Default gateway"
|
||||
newvalues(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/, :absent, :none, :undef, :nil)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
defaultto :absent
|
||||
validate do |val|
|
||||
if val != :absent
|
||||
val.strip!
|
||||
raise ArgumentError, "Invalid gateway: '#{val}'" if \
|
||||
not val.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) \
|
||||
or not ($1.to_i >= 0 and $1.to_i <= 255) \
|
||||
or not ($2.to_i >= 0 and $2.to_i <= 255) \
|
||||
or not ($3.to_i >= 0 and $3.to_i <= 255) \
|
||||
or not ($4.to_i >= 0 and $4.to_i <= 255)
|
||||
end
|
||||
end
|
||||
end
|
||||
newproperty(:gateway_metric) do
|
||||
desc "Default gateway metric"
|
||||
newvalues(/^\d+$/, :absent, :none, :undef, :nil)
|
||||
aliasvalue(:none, :absent)
|
||||
aliasvalue(:undef, :absent)
|
||||
aliasvalue(:nil, :absent)
|
||||
defaultto :absent
|
||||
validate do |val|
|
||||
min_metric = 0
|
||||
max_metric = 65535
|
||||
if ! (val.to_s == 'absent' or (min_metric .. max_metric).include?(val.to_i))
|
||||
raise ArgumentError, "'#{val}' is not a valid metric (must be a integer value in range (#{min_metric} .. #{max_metric})"
|
||||
end
|
||||
end
|
||||
munge do |val|
|
||||
if val == :absent
|
||||
:absent
|
||||
else
|
||||
begin
|
||||
val.to_i
|
||||
rescue
|
||||
:absent
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:dhcp_hostname) do
|
||||
desc "DHCP hostname"
|
||||
end
|
||||
|
||||
# newproperty(:onboot, :parent => Puppet::Property::Boolean) do
|
||||
# desc "Whether to bring the interface up"
|
||||
# defaultto :true
|
||||
# end
|
||||
|
||||
newproperty(:vendor_specific) do
|
||||
desc "Hash of vendor specific properties"
|
||||
#defaultto {} # no default value should be!!!
|
||||
# provider-specific properties, can be validating only by provider.
|
||||
validate do |val|
|
||||
if ! val.is_a? Hash
|
||||
fail("Vendor_specific should be a hash!")
|
||||
end
|
||||
end
|
||||
|
||||
munge do |value|
|
||||
L23network.reccursive_sanitize_hash(value)
|
||||
end
|
||||
|
||||
def should_to_s(value)
|
||||
"\n#{value.to_yaml}\n"
|
||||
end
|
||||
|
||||
def is_to_s(value)
|
||||
"\n#{value.to_yaml}\n"
|
||||
end
|
||||
|
||||
def insync?(value)
|
||||
should_to_s(value) == should_to_s(should)
|
||||
end
|
||||
end
|
||||
|
||||
autorequire(:l2_port) do
|
||||
[self[:interface]]
|
||||
end
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -0,0 +1,42 @@
|
|||
module L23network
|
||||
|
||||
def self.ethtool_name_commands_mapping()
|
||||
{
|
||||
'offload' => {
|
||||
'__section_key_set__' => '-K',
|
||||
'__section_key_get__' => '-k',
|
||||
'rx-checksumming' => 'rx',
|
||||
'tx-checksumming' => 'tx',
|
||||
'scatter-gather' => 'sg',
|
||||
'tcp-segmentation-offload' => 'tso',
|
||||
'udp-fragmentation-offload' => 'ufo',
|
||||
'generic-segmentation-offload' => 'gso',
|
||||
'generic-receive-offload' => 'gro',
|
||||
'large-receive-offload' => 'lro',
|
||||
'rx-vlan-offload' => 'rxvlan',
|
||||
'tx-vlan-offload' => 'txvlan',
|
||||
'ntuple-filters' => 'ntuple',
|
||||
'receive-hashing' => 'rxhash',
|
||||
'rx-fcs' => 'rx-fcs',
|
||||
'rx-all' => 'rx-all',
|
||||
'highdma' => 'highdma',
|
||||
'rx-vlan-filter' => 'rx-vlan-filter',
|
||||
'fcoe-mtu' => 'fcoe-mtu',
|
||||
'l2-fwd-offload' => 'l2-fwd-offload',
|
||||
'loopback' => 'loopback',
|
||||
'tx-nocache-copy' => 'tx-nocache-copy',
|
||||
'tx-gso-robust' => 'tx-gso-robust',
|
||||
'tx-fcoe-segmentation' => 'tx-fcoe-segmentation',
|
||||
'tx-gre-segmentation' => 'tx-gre-segmentation',
|
||||
'tx-ipip-segmentation' => 'tx-ipip-segmentation',
|
||||
'tx-sit-segmentation' => 'tx-sit-segmentation',
|
||||
'tx-udp_tnl-segmentation' => 'tx-udp_tnl-segmentation',
|
||||
'tx-mpls-segmentation' => 'tx-mpls-segmentation',
|
||||
'tx-vlan-stag-hw-insert' => 'tx-vlan-stag-hw-insert',
|
||||
'rx-vlan-stag-hw-parse' => 'rx-vlan-stag-hw-parse',
|
||||
'rx-vlan-stag-filter' => 'rx-vlan-stag-filter',
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,101 @@
|
|||
module L23network
|
||||
def self.reccursive_sanitize_hash(data)
|
||||
if data.is_a? Hash
|
||||
new_data = {}
|
||||
data.each do |key, value|
|
||||
new_data.store(reccursive_sanitize_hash(key), reccursive_sanitize_hash(value))
|
||||
end
|
||||
new_data
|
||||
elsif data.is_a? Array
|
||||
data.map do |element|
|
||||
reccursive_sanitize_hash(element)
|
||||
end
|
||||
elsif ['true', 'on', 'yes'].include? data.to_s.downcase
|
||||
true
|
||||
elsif ['false', 'off', 'no'].include? data.to_s.downcase
|
||||
false
|
||||
elsif data.nil?
|
||||
nil
|
||||
else
|
||||
data.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def self.get_patch_name(bridges)
|
||||
# bridges should be an array of two string
|
||||
"patch__#{bridges.map{|s| s.to_s}.sort.join('--')}"
|
||||
end
|
||||
|
||||
def self.ovs_jack_name_len
|
||||
13
|
||||
end
|
||||
|
||||
def self.get_ovs_jack_name(bridge)
|
||||
# bridges should be an array of two string
|
||||
tail = bridge[0..ovs_jack_name_len-1]
|
||||
"p_#{tail}"
|
||||
end
|
||||
|
||||
def self.lnx_jack_name_len
|
||||
11
|
||||
end
|
||||
|
||||
def self.get_lnx_jack_name(bridge, num=0)
|
||||
# bridges should be an array of two string
|
||||
tail = bridge[0..lnx_jack_name_len-1]
|
||||
"p_#{tail}-#{num}"
|
||||
end
|
||||
|
||||
def self.get_pair_of_jack_names(bridges)
|
||||
if bridges.is_a? String
|
||||
j1 = get_lnx_jack_name(bridges,0)
|
||||
j2 = get_lnx_jack_name(bridges,1)
|
||||
elsif bridges.is_a? Array and bridges.length==1
|
||||
j1 = get_lnx_jack_name(bridges[0],0)
|
||||
j2 = get_lnx_jack_name(bridges[0],1)
|
||||
else
|
||||
j1 = get_lnx_jack_name(bridges[0],0)
|
||||
j2 = get_lnx_jack_name(bridges[1],1)
|
||||
end
|
||||
return [j1, j2]
|
||||
end
|
||||
|
||||
# def self.reccursive_merge_hash(a,b)
|
||||
# rv = {}
|
||||
|
||||
# a.keys.each do |key|
|
||||
# if data.is_a? Hash
|
||||
# new_data = {}
|
||||
# data.each do |key, value|
|
||||
# new_data.store(reccursive_sanitize_hash(key), reccursive_sanitize_hash(value))
|
||||
# end
|
||||
# new_data
|
||||
# else
|
||||
# data.to_s
|
||||
# end
|
||||
# end
|
||||
|
||||
# if data.is_a? Hash
|
||||
# new_data = {}
|
||||
# data.each do |key, value|
|
||||
# new_data.store(reccursive_sanitize_hash(key), reccursive_sanitize_hash(value))
|
||||
# end
|
||||
# new_data
|
||||
# elsif data.is_a? Array
|
||||
# data.map do |element|
|
||||
# reccursive_sanitize_hash(element)
|
||||
# end
|
||||
# elsif ['true', 'on', 'yes'].include? data.to_s.downcase
|
||||
# true
|
||||
# elsif ['false', 'off', 'no'].include? data.to_s.downcase
|
||||
# false
|
||||
# elsif data.nil?
|
||||
# nil
|
||||
# else
|
||||
# data.to_s
|
||||
# end
|
||||
|
||||
# return rv
|
||||
# end
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -1,3 +1,4 @@
|
|||
# xxx
|
||||
class l23network::examples::adv_net_config__bond_lnx (
|
||||
$fuel_settings,
|
||||
) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# xxx
|
||||
class l23network::examples::adv_net_config__bond_ovs (
|
||||
$fuel_settings,
|
||||
) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# xxx
|
||||
class l23network::examples::bond_lnx (
|
||||
$bond = $name,
|
||||
$interfaces = ['eth4','eth5'],
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# xxx
|
||||
class l23network::examples::bond_lnx_old_style (
|
||||
$bond = $name,
|
||||
$interfaces = ['eth4','eth5'],
|
||||
|
@ -8,10 +9,10 @@ class l23network::examples::bond_lnx_old_style (
|
|||
$bond_lacp_rate = 1,
|
||||
) {
|
||||
l23network::l3::ifconfig {$bond:
|
||||
ipaddr => $ipaddr,
|
||||
bond_mode => $bond_mode,
|
||||
bond_miimon => $bond_miimon,
|
||||
bond_lacp_rate => $bond_lacp_rate,
|
||||
ipaddr => $ipaddr,
|
||||
bond_mode => $bond_mode,
|
||||
bond_miimon => $bond_miimon,
|
||||
bond_lacp_rate => $bond_lacp_rate,
|
||||
} ->
|
||||
l23network::l3::ifconfig {$interfaces[0]: ipaddr=>'none', bond_master=>$bond} ->
|
||||
l23network::l3::ifconfig {$interfaces[1]: ipaddr=>'none', bond_master=>$bond}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# manage /etc/hosts
|
||||
#
|
||||
class l23network::hosts_file (
|
||||
$nodes,
|
||||
$hosts_file = "/etc/hosts"
|
||||
$hosts_file = '/etc/hosts'
|
||||
) {
|
||||
|
||||
#Move original hosts file
|
||||
|
|
|
@ -4,13 +4,56 @@
|
|||
# Requirements, packages and services.
|
||||
#
|
||||
class l23network (
|
||||
$use_ovs = true,
|
||||
$use_lnxbr = true,
|
||||
$use_ovs = true,
|
||||
$use_lnx = true,
|
||||
$install_ovs = $use_ovs,
|
||||
$install_brtool = $use_lnx,
|
||||
$install_ethtool = $use_lnx,
|
||||
$install_bondtool = $use_lnx,
|
||||
$install_vlantool = $use_lnx,
|
||||
){
|
||||
class {'l23network::l2':
|
||||
use_ovs => $use_ovs,
|
||||
use_lnxbr => $use_lnxbr,
|
||||
|
||||
include ::l23network::params
|
||||
|
||||
class { 'l23network::l2':
|
||||
use_ovs => $use_ovs,
|
||||
use_lnx => $use_lnx,
|
||||
install_ovs => $install_ovs,
|
||||
install_brtool => $install_brtool,
|
||||
install_ethtool => $install_ethtool,
|
||||
install_bondtool => $install_bondtool,
|
||||
install_vlantool => $install_vlantool,
|
||||
}
|
||||
|
||||
if $::l23network::params::interfaces_file {
|
||||
if ! defined(File["${::l23network::params::interfaces_file}"]) {
|
||||
file {"${::l23network::params::interfaces_file}":
|
||||
ensure => present,
|
||||
content => template('l23network/interfaces.erb'),
|
||||
}
|
||||
}
|
||||
File<| title == "${::l23network::params::interfaces_file}" |> -> File<| title == "${::l23network::params::interfaces_dir}" |>
|
||||
}
|
||||
|
||||
if ! defined(File["${::l23network::params::interfaces_dir}"]) {
|
||||
file {"${::l23network::params::interfaces_dir}":
|
||||
ensure => directory,
|
||||
owner => 'root',
|
||||
mode => '0755',
|
||||
} -> Anchor['l23network::init']
|
||||
}
|
||||
Class['l23network::l2'] -> File<| title == "${::l23network::params::interfaces_dir}" |>
|
||||
Class['l23network::l2'] -> File<| title == "${::l23network::params::interfaces_file}" |>
|
||||
|
||||
# Centos interface up-n-down scripts
|
||||
if $::osfamily =~ /(?i)redhat/ {
|
||||
class{'::l23network::l2::centos_upndown_scripts': } -> Anchor['l23network::init']
|
||||
Anchor <| title == 'l23network::l2::centos_upndown_scripts' |> -> Anchor['l23network::init']
|
||||
}
|
||||
|
||||
Anchor['l23network::l2::init'] -> Anchor['l23network::init']
|
||||
anchor { 'l23network::init': }
|
||||
|
||||
}
|
||||
#
|
||||
###
|
||||
|
|
|
@ -4,54 +4,88 @@
|
|||
# Requirements, packages and services.
|
||||
#
|
||||
class l23network::l2 (
|
||||
$use_ovs = true,
|
||||
$use_lnxbr = true,
|
||||
$use_ovs = true,
|
||||
$use_lnx = true,
|
||||
$install_ovs = $use_ovs,
|
||||
$install_brtool = $use_lnx,
|
||||
$install_ethtool = $use_lnx,
|
||||
$install_bondtool = $use_lnx,
|
||||
$install_vlantool = $use_lnx,
|
||||
$ovs_modname = 'openvswitch'
|
||||
){
|
||||
include ::l23network::params
|
||||
|
||||
if $use_ovs {
|
||||
if $::l23network::params::ovs_datapath_package_name {
|
||||
package { 'openvswitch-datapath':
|
||||
name => $::l23network::params::ovs_datapath_package_name
|
||||
$ovs_mod_ensure = present
|
||||
if $install_ovs {
|
||||
if $::l23network::params::ovs_datapath_package_name {
|
||||
package { 'openvswitch-datapath':
|
||||
name => $::l23network::params::ovs_datapath_package_name
|
||||
}
|
||||
}
|
||||
package { 'openvswitch-common':
|
||||
name => $::l23network::params::ovs_common_package_name
|
||||
}
|
||||
}
|
||||
package { 'openvswitch-common':
|
||||
name => $::l23network::params::ovs_common_package_name
|
||||
}
|
||||
|
||||
Package<| title=='openvswitch-datapath' |> -> Package['openvswitch-common']
|
||||
Package['openvswitch-common'] ~> Service['openvswitch-service']
|
||||
service {'openvswitch-service':
|
||||
ensure => running,
|
||||
name => $::l23network::params::ovs_service_name,
|
||||
enable => true,
|
||||
hasstatus => true,
|
||||
status => $::l23network::params::ovs_status_cmd,
|
||||
}
|
||||
Service['openvswitch-service'] -> L23network::L3::Ifconfig<||>
|
||||
if !defined(Service['openvswitch-service']) {
|
||||
notify{ "Module ${module_name} cannot notify service openvswitch-service on packages update": }
|
||||
Package<| title=='openvswitch-datapath' |> -> Package['openvswitch-common']
|
||||
Package['openvswitch-common'] ~> Service['openvswitch-service']
|
||||
}
|
||||
$ovs_service_ensure = 'running'
|
||||
} else {
|
||||
$ovs_mod_ensure = absent
|
||||
$ovs_service_ensure = 'stopped'
|
||||
}
|
||||
service {'openvswitch-service':
|
||||
ensure => $ovs_service_ensure,
|
||||
name => $::l23network::params::ovs_service_name,
|
||||
enable => $ovs_service_ensure == 'running',
|
||||
hasstatus => true,
|
||||
}
|
||||
Service['openvswitch-service'] -> Anchor['l23network::l2::init']
|
||||
|
||||
@k_mod{$ovs_modname:
|
||||
ensure => $ovs_mod_ensure
|
||||
}
|
||||
|
||||
if $::osfamily =~ /(?i)debian/ {
|
||||
if !defined(Package["$l23network::params::lnx_bond_tools"]) {
|
||||
package {"$l23network::params::lnx_bond_tools": }
|
||||
}
|
||||
if $use_lnx {
|
||||
$mod_8021q_ensure = present
|
||||
$mod_bonding_ensure = present
|
||||
$mod_bridge_ensure = present
|
||||
} else {
|
||||
$mod_8021q_ensure = absent
|
||||
$mod_bonding_ensure = absent
|
||||
$mod_bridge_ensure = absent
|
||||
}
|
||||
|
||||
if !defined(Package["$l23network::params::lnx_vlan_tools"]) {
|
||||
package {"$l23network::params::lnx_vlan_tools": }
|
||||
if $install_vlantool and $::l23network::params::lnx_vlan_tools {
|
||||
ensure_packages($::l23network::params::lnx_vlan_tools)
|
||||
Package[$::l23network::params::lnx_vlan_tools] -> Anchor['l23network::l2::init']
|
||||
}
|
||||
@k_mod{'8021q':
|
||||
ensure => $mod_8021q_ensure
|
||||
}
|
||||
|
||||
if !defined(Package["$l23network::params::lnx_ethernet_tools"]) {
|
||||
package {"$l23network::params::lnx_ethernet_tools": }
|
||||
if $install_bondtool and $::l23network::params::lnx_bond_tools {
|
||||
ensure_packages($::l23network::params::lnx_bond_tools)
|
||||
Package[$::l23network::params::lnx_bond_tools] -> Anchor['l23network::l2::init']
|
||||
}
|
||||
@k_mod{'bonding':
|
||||
ensure => $mod_bonding_ensure
|
||||
}
|
||||
|
||||
if $::osfamily =~ /(?i)debian/ {
|
||||
Package["$l23network::params::lnx_bond_tools"] -> L23network::L3::Ifconfig<||>
|
||||
if $install_brtool and $::l23network::params::lnx_bridge_tools {
|
||||
ensure_packages($::l23network::params::lnx_bridge_tools)
|
||||
#Package[$::l23network::params::lnx_bridge_tools] -> Anchor['l23network::l2::init']
|
||||
}
|
||||
Package["$l23network::params::lnx_vlan_tools"] -> L23network::L3::Ifconfig<||>
|
||||
Package["$l23network::params::lnx_ethernet_tools"] -> L23network::L3::Ifconfig<||>
|
||||
@k_mod{'bridge':
|
||||
ensure => $mod_bridge_ensure
|
||||
}
|
||||
|
||||
if $install_ethtool and $::l23network::params::lnx_ethernet_tools {
|
||||
ensure_packages($::l23network::params::lnx_ethernet_tools)
|
||||
Package[$::l23network::params::lnx_ethernet_tools] -> Anchor['l23network::l2::init']
|
||||
}
|
||||
|
||||
anchor { 'l23network::l2::init': }
|
||||
|
||||
}
|
||||
|
|
|
@ -12,52 +12,148 @@
|
|||
#
|
||||
# [*interfaces*]
|
||||
# List of interfaces in this bond.
|
||||
#
|
||||
# [*vlan_id*]
|
||||
# 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.
|
||||
# Must be true or false.
|
||||
#
|
||||
|
||||
define l23network::l2::bond (
|
||||
$bridge,
|
||||
$interfaces = undef,
|
||||
$ports = undef, # deprecated, must be used interfaces
|
||||
$bond = $name,
|
||||
$properties = [],
|
||||
$vlan_id = 0,
|
||||
$trunks = [],
|
||||
$provider = 'ovs',
|
||||
$ensure = present,
|
||||
$skip_existing = false
|
||||
$ensure = present,
|
||||
$bond = $name,
|
||||
$use_ovs = $::l23network::use_ovs,
|
||||
$interfaces = undef,
|
||||
$bridge = undef,
|
||||
$mtu = undef,
|
||||
$onboot = undef,
|
||||
# $ethtool = undef,
|
||||
$bond_properties = undef, # bond configuration options
|
||||
$interface_properties = undef, # configuration options for included interfaces (mtu, ethtool, etc...)
|
||||
$vendor_specific = undef,
|
||||
$monolith_bond_providers = undef,
|
||||
$provider = undef,
|
||||
# deprecated parameters, in the future ones will be moved to the vendor_specific hash
|
||||
# $skip_existing = undef,
|
||||
) {
|
||||
if ! $::l23network::l2::use_ovs {
|
||||
fail('You must enable Open vSwitch by setting the l23network::l2::use_ovs to true.')
|
||||
include ::stdlib
|
||||
include ::l23network::params
|
||||
|
||||
$actual_monolith_bond_providers = $monolith_bond_providers ? {
|
||||
undef => $l23network::params::monolith_bond_providers,
|
||||
default => $monolith_bond_providers,
|
||||
}
|
||||
|
||||
$bond_modes = [
|
||||
'balance-rr',
|
||||
'active-backup',
|
||||
'balance-xor',
|
||||
'broadcast',
|
||||
'802.3ad',
|
||||
'balance-tlb',
|
||||
'balance-alb'
|
||||
]
|
||||
|
||||
$lacp_rates = [
|
||||
'slow',
|
||||
'fast'
|
||||
]
|
||||
|
||||
# calculate string representation for bond_mode
|
||||
if ! $bond_properties[mode] {
|
||||
# default value by design https://www.kernel.org/doc/Documentation/networking/bonding.txt
|
||||
$bond_mode = $bond_modes[0]
|
||||
} elsif is_integer($bond_properties[mode]) and $bond_properties[mode] < size($bond_modes) {
|
||||
$bond_mode = $bond_modes[$bond_properties[mode]]
|
||||
} else {
|
||||
$bond_mode = $bond_properties[mode]
|
||||
}
|
||||
|
||||
# calculate string representation for lacp_rate
|
||||
if ! $bond_properties[lacp_rate] {
|
||||
# default value by design https://www.kernel.org/doc/Documentation/networking/bonding.txt
|
||||
$lacp_rate = $lacp_rates[0]
|
||||
} elsif is_integer($bond_properties[lacp_rate]) and $bond_properties[lacp_rate] < size($lacp_rates) {
|
||||
$lacp_rate = $lacp_rates[$bond_properties[lacp_rate]]
|
||||
} else {
|
||||
$lacp_rate = $bond_properties[lacp_rate]
|
||||
}
|
||||
|
||||
# calculate default miimon
|
||||
if is_integer($bond_properties[miimon]) and $bond_properties[miimon] >= 0 {
|
||||
$miimon = $bond_properties[miimon]
|
||||
} else {
|
||||
# recommended default value https://www.kernel.org/doc/Documentation/networking/bonding.txt
|
||||
$miimon = 100
|
||||
}
|
||||
|
||||
# default bond properties
|
||||
$default_bond_properties = {
|
||||
mode => $bond_mode,
|
||||
miimon => $miimon,
|
||||
lacp_rate => $lacp_rate,
|
||||
}
|
||||
|
||||
$real_bond_properties = merge($bond_properties, $default_bond_properties)
|
||||
|
||||
if $interfaces {
|
||||
$r_interfaces = $interfaces
|
||||
} elsif $ports {
|
||||
$r_interfaces = $ports
|
||||
} else {
|
||||
fail("You must specify 'interfaces' property for this bond.")
|
||||
validate_array($interfaces)
|
||||
}
|
||||
|
||||
if ! defined (L2_ovs_bond["$bond"]) {
|
||||
l2_ovs_bond { "$bond" :
|
||||
ensure => $ensure,
|
||||
interfaces => $r_interfaces,
|
||||
bridge => $bridge,
|
||||
vlan_id => $vlan_id,
|
||||
trunks => $trunks,
|
||||
properties => $properties,
|
||||
skip_existing => $skip_existing,
|
||||
}
|
||||
Service<| title == 'openvswitch-service' |> -> L2_ovs_bond["$bond"]
|
||||
# Use $monolith_bond_providers list for prevent creating ports for monolith bonds
|
||||
$actual_provider_for_bond_interface = $provider ? {
|
||||
undef => default_provider_for('L2_port'),
|
||||
default => $provider
|
||||
}
|
||||
$eee = default_provider_for('L2_port')
|
||||
|
||||
if ! member($actual_monolith_bond_providers, $actual_provider_for_bond_interface) {
|
||||
l23network::l2::bond_interface{ $interfaces:
|
||||
bond => $bond,
|
||||
mtu => $mtu,
|
||||
interface_properties => $interface_properties,
|
||||
ensure => $ensure,
|
||||
provider => $actual_provider_for_bond_interface
|
||||
}
|
||||
}
|
||||
|
||||
if ! defined(L2_bond[$bond]) {
|
||||
if $provider {
|
||||
$config_provider = "${provider}_${::l23_os}"
|
||||
} else {
|
||||
$config_provider = undef
|
||||
}
|
||||
|
||||
if ! defined(L23_stored_config[$bond]) {
|
||||
l23_stored_config { $bond: }
|
||||
}
|
||||
L23_stored_config <| title == $bond |> {
|
||||
ensure => $ensure,
|
||||
if_type => 'bond',
|
||||
bridge => $bridge,
|
||||
mtu => $mtu,
|
||||
onboot => $onboot,
|
||||
bond_mode => $real_bond_properties[mode],
|
||||
bond_master => undef,
|
||||
bond_slaves => $interfaces,
|
||||
bond_miimon => $real_bond_properties[miimon],
|
||||
bond_lacp_rate => $real_bond_properties[lacp_rate],
|
||||
vendor_specific => $vendor_specific,
|
||||
provider => $config_provider
|
||||
}
|
||||
|
||||
l2_bond { $bond :
|
||||
ensure => $ensure,
|
||||
bridge => $bridge,
|
||||
use_ovs => $use_ovs,
|
||||
onboot => $onboot,
|
||||
slaves => $interfaces,
|
||||
mtu => $mtu,
|
||||
interface_properties => $interface_properties,
|
||||
bond_properties => $real_bond_properties,
|
||||
vendor_specific => $vendor_specific,
|
||||
provider => $provider
|
||||
}
|
||||
|
||||
# this need for creating L2_port resource by ifup, if it allowed by OS
|
||||
L23_stored_config[$bond] -> L2_bond[$bond]
|
||||
|
||||
K_mod<||> -> L2_bond<||>
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
#
|
||||
define l23network::l2::bond_interface (
|
||||
$bond,
|
||||
$use_ovs = $::l23network::use_ovs,
|
||||
$ensure = present,
|
||||
$mtu = undef,
|
||||
$interface_properties = {},
|
||||
$provider = undef,
|
||||
) {
|
||||
include ::l23network::params
|
||||
include ::stdlib
|
||||
|
||||
if ! defined(L23network::L2::Port[$name]) {
|
||||
$additional_properties = {
|
||||
use_ovs => $use_ovs,
|
||||
mtu => is_integer($interface_properties[mtu]) ? {false=>$mtu, default=>$interface_properties[mtu]},
|
||||
master => $bond,
|
||||
slave => true,
|
||||
provider => $provider
|
||||
}
|
||||
|
||||
create_resources(l23network::l2::port, {
|
||||
"${name}" => merge($interface_properties, $additional_properties)
|
||||
})
|
||||
} else {
|
||||
L23network::L2::Port<| title == $name |> {
|
||||
use_ovs => $use_ovs,
|
||||
master => $bond,
|
||||
slave => true
|
||||
}
|
||||
}
|
||||
if $provider == 'ovs' {
|
||||
# OVS can't create bond if slave port don't exists.
|
||||
L2_port[$name] -> L2_bond[$bond]
|
||||
} else {
|
||||
L2_bond[$bond] -> L2_port[$name]
|
||||
}
|
||||
}
|
||||
###
|
|
@ -7,30 +7,58 @@
|
|||
# [*name*]
|
||||
# Bridge name.
|
||||
#
|
||||
# [*skip_existing*]
|
||||
# If this bridge already exists it will be ignored without any errors.
|
||||
# Must be true or false.
|
||||
#
|
||||
# [*external_ids*]
|
||||
# See open vSwitch documentation.
|
||||
# http://openvswitch.org/cgi-bin/ovsman.cgi?page=utilities%2Fovs-vsctl.8
|
||||
#
|
||||
define l23network::l2::bridge (
|
||||
$external_ids = "bridge-id=${name}",
|
||||
$provider = 'ovs',
|
||||
$ensure = present,
|
||||
$skip_existing = false
|
||||
$ensure = present,
|
||||
$use_ovs = $::l23network::use_ovs,
|
||||
$mtu = undef,
|
||||
$stp = undef,
|
||||
$bpdu_forward = true,
|
||||
# $bridge_id = undef, # will be implemented later
|
||||
$external_ids = { 'bridge-id' => "${name}" },
|
||||
$vendor_specific = undef,
|
||||
$provider = undef,
|
||||
) {
|
||||
if ! $::l23network::l2::use_ovs {
|
||||
fail('You must enable Open vSwitch by setting the l23network::l2::use_ovs to true.')
|
||||
}
|
||||
if ! defined (L2_ovs_bridge[$name]) {
|
||||
l2_ovs_bridge {$name:
|
||||
ensure => $ensure,
|
||||
external_ids => $external_ids,
|
||||
skip_existing=> $skip_existing,
|
||||
include l23network::params
|
||||
|
||||
if ! defined (L2_bridge[$name]) {
|
||||
if $provider {
|
||||
$config_provider = "${provider}_${::l23_os}"
|
||||
} else {
|
||||
$config_provider = undef
|
||||
}
|
||||
Service<| title == 'openvswitch-service' |> -> L2_ovs_bridge[$name]
|
||||
|
||||
if ! defined (L23_stored_config[$name]) {
|
||||
l23_stored_config { $name: }
|
||||
}
|
||||
|
||||
L23_stored_config <| title == $name |> {
|
||||
ensure => $ensure,
|
||||
#bpdu_forward => $bpdu_forward,
|
||||
if_type => 'bridge',
|
||||
bridge_stp => $stp,
|
||||
bridge_ports => ['none'], # this property will be fulled by l2_port
|
||||
vendor_specific => $vendor_specific,
|
||||
provider => $config_provider
|
||||
}
|
||||
|
||||
l2_bridge {$name:
|
||||
ensure => $ensure,
|
||||
use_ovs => $use_ovs,
|
||||
external_ids => $external_ids,
|
||||
stp => $stp,
|
||||
#bpdu_forward => $bpdu_forward,
|
||||
vendor_specific => $vendor_specific,
|
||||
provider => $provider
|
||||
}
|
||||
|
||||
# this need for creating L2_bridge resource by ifup, if it allowed by OS
|
||||
L23_stored_config[$name] -> L2_bridge[$name]
|
||||
|
||||
K_mod<||> -> L2_bridge<||>
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,15 +4,13 @@ class l23network::l2::centos_upndown_scripts {
|
|||
ensure => present,
|
||||
owner => 'root',
|
||||
mode => '0755',
|
||||
recurse => true,
|
||||
content => template("l23network/centos_ifup-local.erb"),
|
||||
content => template('l23network/centos_ifup-local.erb'),
|
||||
} ->
|
||||
file {'/sbin/ifdown-local':
|
||||
ensure => present,
|
||||
owner => 'root',
|
||||
mode => '0755',
|
||||
recurse => true,
|
||||
content => template("l23network/centos_ifdown-local.erb"),
|
||||
content => template('l23network/centos_ifdown-local.erb'),
|
||||
} ->
|
||||
anchor { 'l23network::l2::centos_upndown_scripts': }
|
||||
}
|
||||
|
|
|
@ -9,45 +9,58 @@
|
|||
# [*peers*]
|
||||
# Patch port names for both bridges. must be array of two strings.
|
||||
#
|
||||
# [*vlan_ids*]
|
||||
# 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],
|
||||
$vlan_ids = [0, 0],
|
||||
$trunks = [],
|
||||
$provider = 'ovs',
|
||||
$ensure = present,
|
||||
$skip_existing = false
|
||||
$use_ovs = $::l23network::use_ovs,
|
||||
$ensure = present,
|
||||
$mtu = undef,
|
||||
$vendor_specific = undef,
|
||||
$provider = undef,
|
||||
) {
|
||||
if ! $::l23network::l2::use_ovs {
|
||||
fail('You must enable Open vSwitch by setting the l23network::l2::use_ovs to true.')
|
||||
}
|
||||
|
||||
#$provider_1 = get_provider_for('L2_bridge', bridges[0]) # this didn't work, because parser functions
|
||||
#$provider_2 = get_provider_for('L2_bridge', bridges[1]) # executed before resources prefetch
|
||||
|
||||
# Architecture limitation.
|
||||
# We can't create more one patch between same bridges.
|
||||
#$patch = "${bridges[0]}_${vlan_ids[0]}--${bridges[1]}_${vlan_ids[1]}"
|
||||
$patch = "${bridges[0]}--${bridges[1]}"
|
||||
$patch_name = get_patch_name($bridges)
|
||||
$patch_jacks_names = get_pair_of_jack_names($bridges)
|
||||
|
||||
if ! defined (L2_ovs_patch["$patch"]) {
|
||||
l2_ovs_patch { "$patch" :
|
||||
bridges => $bridges,
|
||||
peers => $peers,
|
||||
vlan_ids => $vlan_ids,
|
||||
trunks => $trunks,
|
||||
ensure => $ensure
|
||||
if ! defined(L2_patch[$patch_name]) {
|
||||
if $provider {
|
||||
$config_provider = "${provider}_${::l23_os}"
|
||||
} else {
|
||||
$config_provider = undef
|
||||
}
|
||||
Service<| title == 'openvswitch-service' |> -> L2_ovs_patch["$patch"]
|
||||
|
||||
if ! defined(L23_stored_config[$patch_jacks_names[0]]) {
|
||||
# we use only one (last) patch jack name here and later,
|
||||
# because a both jacks for patch
|
||||
# creates by one command. This command stores in one config file.
|
||||
l23_stored_config { $patch_jacks_names[0]: }
|
||||
}
|
||||
L23_stored_config <| title == $patch_jacks_names[0] |> {
|
||||
ensure => $ensure,
|
||||
if_type => 'ethernet',
|
||||
bridge => $bridges,
|
||||
jacks => $patch_jacks_names,
|
||||
mtu => $mtu,
|
||||
onboot => true,
|
||||
vendor_specific => $vendor_specific,
|
||||
provider => $config_provider
|
||||
}
|
||||
L23_stored_config[$patch_jacks_names[0]] -> L2_patch[$patch_name]
|
||||
|
||||
l2_patch{ $patch_name :
|
||||
ensure => $ensure,
|
||||
bridges => $bridges,
|
||||
use_ovs => $use_ovs,
|
||||
mtu => $mtu,
|
||||
vendor_specific => $vendor_specific,
|
||||
provider => $provider
|
||||
}
|
||||
|
||||
K_mod<||> -> L2_patch<||>
|
||||
}
|
||||
}
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -29,34 +29,113 @@
|
|||
# Must be true or false.
|
||||
#
|
||||
define l23network::l2::port (
|
||||
$bridge,
|
||||
$port = $name,
|
||||
$type = '',
|
||||
$port_properties = [],
|
||||
$interface_properties = [],
|
||||
$vlan_id = 0,
|
||||
$trunks = [],
|
||||
$vlan_splinters = false,
|
||||
$provider = 'ovs',
|
||||
$ensure = present,
|
||||
$skip_existing = false
|
||||
$use_ovs = $::l23network::use_ovs,
|
||||
$port = $name,
|
||||
$bridge = undef,
|
||||
$onboot = undef,
|
||||
$vlan_id = undef, # actually only for OVS workflow
|
||||
$vlan_dev = undef,
|
||||
$mtu = undef,
|
||||
$ethtool = undef,
|
||||
$master = undef, # used for bonds automatically
|
||||
$slave = undef, # used for bonds automatically
|
||||
# $type = undef, # was '',
|
||||
$vendor_specific = undef,
|
||||
$provider = undef,
|
||||
# deprecated parameters, in the future ones will be moved to the vendor_specific hash
|
||||
# $skip_existing = undef,
|
||||
# $port_properties = [],
|
||||
# $interface_properties = [],
|
||||
# $trunks = [],
|
||||
) {
|
||||
if ! $::l23network::l2::use_ovs {
|
||||
fail('You must enable Open vSwitch by setting the l23network::l2::use_ovs to true.')
|
||||
# Detect VLAN mode configuration
|
||||
case $port {
|
||||
/^vlan(\d+)/: {
|
||||
$port_name = $port
|
||||
$port_vlan_mode = 'vlan'
|
||||
if $vlan_id {
|
||||
$port_vlan_id = $vlan_id
|
||||
} else {
|
||||
$port_vlan_id = $1
|
||||
}
|
||||
if $vlan_dev {
|
||||
$port_vlan_dev = $vlan_dev
|
||||
} else {
|
||||
if $provider != 'ovs' {
|
||||
fail("Can't configure vlan interface ${port} without definition vlandev=>ethXX.")
|
||||
}
|
||||
}
|
||||
}
|
||||
/^([\w\-]+\d+)\.(\d+)/: {
|
||||
$port_vlan_mode = 'eth'
|
||||
$port_vlan_id = $2
|
||||
$port_vlan_dev = $1
|
||||
$port_name = "${1}.${2}"
|
||||
}
|
||||
default: {
|
||||
$port_vlan_mode = undef
|
||||
$port_vlan_id = undef
|
||||
$port_vlan_dev = undef
|
||||
$port_name = $port
|
||||
}
|
||||
}
|
||||
|
||||
if ! defined (L2_ovs_port[$port]) {
|
||||
l2_ovs_port { $port :
|
||||
ensure => $ensure,
|
||||
bridge => $bridge,
|
||||
type => $type,
|
||||
vlan_id => $vlan_id,
|
||||
trunks => $trunks,
|
||||
vlan_splinters => $vlan_splinters,
|
||||
port_properties => $port_properties,
|
||||
interface_properties => $interface_properties,
|
||||
skip_existing => $skip_existing
|
||||
# # implicitly create bridge, if it given and not exists
|
||||
# if $bridge {
|
||||
# if !defined(L2_bridge[$bridge]) {
|
||||
# l2_bridge { $bridge: }
|
||||
# }
|
||||
# # or do this from autorequire ??????
|
||||
# L2_bridge[$bridge] -> L2_port[$port_name]
|
||||
# }
|
||||
|
||||
if ! defined(L2_port[$port_name]) {
|
||||
if $provider {
|
||||
$config_provider = "${provider}_${::l23_os}"
|
||||
} else {
|
||||
$config_provider = undef
|
||||
}
|
||||
Service<| title == 'openvswitch-service' |> -> L2_ovs_port[$port]
|
||||
|
||||
if ! defined(L23_stored_config[$port_name]) {
|
||||
l23_stored_config { $port_name: }
|
||||
}
|
||||
L23_stored_config <| title == $port_name |> {
|
||||
ensure => $ensure,
|
||||
if_type => 'ethernet',
|
||||
bridge => $bridge,
|
||||
vlan_id => $port_vlan_id,
|
||||
vlan_dev => $port_vlan_dev,
|
||||
vlan_mode => $port_vlan_mode,
|
||||
bond_master => $master,
|
||||
mtu => $mtu,
|
||||
onboot => $onboot,
|
||||
#ethtool => $ethtool,
|
||||
vendor_specific => $vendor_specific,
|
||||
provider => $config_provider
|
||||
}
|
||||
|
||||
l2_port { $port_name :
|
||||
ensure => $ensure,
|
||||
use_ovs => $use_ovs,
|
||||
bridge => $bridge,
|
||||
vlan_id => $port_vlan_id,
|
||||
vlan_dev => $port_vlan_dev,
|
||||
vlan_mode => $port_vlan_mode,
|
||||
bond_master => $master,
|
||||
mtu => $mtu,
|
||||
onboot => $onboot,
|
||||
#type => $type,
|
||||
#trunks => $trunks,
|
||||
ethtool => $ethtool,
|
||||
vendor_specific => $vendor_specific,
|
||||
provider => $provider
|
||||
}
|
||||
|
||||
# this need for creating L2_port resource by ifup, if it allowed by OS
|
||||
L23_stored_config[$port_name] -> L2_port[$port_name]
|
||||
|
||||
K_mod<||> -> L2_port<||>
|
||||
}
|
||||
}
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -1,123 +0,0 @@
|
|||
# == Define: l23network::l3::create_br_iface
|
||||
#
|
||||
# Create L2 ovs bridge, clean IPs from interface and add IP address to this
|
||||
# bridge
|
||||
#
|
||||
# === Parameters
|
||||
#
|
||||
# [*bridge*]
|
||||
# Bridge name
|
||||
#
|
||||
# [*interface*]
|
||||
# Interface that will be added to the bridge.
|
||||
# If you set the interface parameter as an array of interface names
|
||||
# then Open vSwitch will create bond with given interfaces.
|
||||
# In this case you must set ovs_bond_name and ovs_bond_properties parameters.
|
||||
#
|
||||
# [*ipaddr*]
|
||||
# IP address for port in bridge.
|
||||
#
|
||||
# [*netmask*]
|
||||
# Network mask.
|
||||
#
|
||||
# [*gateway*]
|
||||
# You can specify default gateway IP address, or 'save' for save default route
|
||||
# if it lies through this interface now.
|
||||
#
|
||||
# [*dns_nameservers*]
|
||||
# Dns nameservers to use
|
||||
#
|
||||
# [*dns_domain*]
|
||||
# Describe DNS domain
|
||||
#
|
||||
# [*dns_search*]
|
||||
# DNS domain to search for
|
||||
#
|
||||
# [*save_default_gateway*]
|
||||
# If current network configuration contains a gateway parameter
|
||||
# this option will try to save it.
|
||||
# DEPRECATED!!! use gateway=>'save'
|
||||
#
|
||||
define l23network::l3::create_br_iface (
|
||||
$interface,
|
||||
$ipaddr,
|
||||
$bridge = $name,
|
||||
$netmask = '255.255.255.0',
|
||||
$gateway = undef,
|
||||
$se = true,
|
||||
$external_ids = '',
|
||||
$dns_nameservers = undef,
|
||||
$dns_domain = undef,
|
||||
$dns_search = undef,
|
||||
$save_default_gateway = false,
|
||||
$lnx_interface_vlandev = undef,
|
||||
$lnx_interface_bond_mode = undef,
|
||||
$lnx_interface_bond_miimon = 100,
|
||||
$lnx_interface_bond_lacp_rate = 1,
|
||||
$ovs_bond_name = 'bond0',
|
||||
$ovs_bond_properties = [],
|
||||
$interface_order_prefix = false,
|
||||
){
|
||||
if ! $::l23network::l2::use_ovs {
|
||||
fail('You must enable Open vSwitch by setting the l23network::l2::use_ovs to true.')
|
||||
}
|
||||
|
||||
if ! $external_ids {
|
||||
$ext_ids = "bridge-id=${bridge}"
|
||||
}
|
||||
#
|
||||
if $gateway {
|
||||
$gateway_ip_address_for_newly_created_interface = $gateway
|
||||
} elsif ($save_default_gateway or $gateway == 'save') and $::l3_default_route_interface == $interface {
|
||||
$gateway_ip_address_for_newly_created_interface = 'save'
|
||||
} else {
|
||||
$gateway_ip_address_for_newly_created_interface = undef
|
||||
}
|
||||
# Build ovs bridge
|
||||
l23network::l2::bridge {"$bridge":
|
||||
skip_existing => $se,
|
||||
external_ids => $ext_ids,
|
||||
}
|
||||
if is_array($interface) {
|
||||
# Build an ovs bridge containing ovs bond with given interfaces
|
||||
l23network::l2::bond {"$ovs_bond_name":
|
||||
bridge => $bridge,
|
||||
ports => $interface,
|
||||
properties => $ovs_bond_properties,
|
||||
skip_existing => $se,
|
||||
require => L23network::L2::Bridge["$bridge"]
|
||||
} ->
|
||||
l23network::l3::ifconfig {$interface: # no quotes here, $interface _may_be_ array!!!
|
||||
ipaddr => 'none',
|
||||
ifname_order_prefix => '0',
|
||||
require => L23network::L2::Bond["$ovs_bond_name"],
|
||||
before => L23network::L3::Ifconfig["$bridge"]
|
||||
}
|
||||
} else {
|
||||
# Build an ovs bridge containing one interface
|
||||
l23network::l2::port {$interface:
|
||||
bridge => $bridge,
|
||||
skip_existing => $se,
|
||||
require => L23network::L2::Bridge["$bridge"]
|
||||
} ->
|
||||
l23network::l3::ifconfig {"${interface}":
|
||||
ipaddr => 'none',
|
||||
vlandev => $lnx_interface_vlandev,
|
||||
bond_mode => $lnx_interface_bond_mode,
|
||||
bond_miimon => $lnx_interface_bond_miimon,
|
||||
bond_lacp_rate => $lnx_interface_bond_lacp_rate,
|
||||
ifname_order_prefix => $interface_order_prefix,
|
||||
require => L23network::L2::Port["${interface}"],
|
||||
before => L23network::L3::Ifconfig["${bridge}"]
|
||||
}
|
||||
}
|
||||
l23network::l3::ifconfig {"${bridge}":
|
||||
ipaddr => $ipaddr,
|
||||
netmask => $netmask,
|
||||
gateway => $gateway_ip_address_for_newly_created_interface,
|
||||
dns_nameservers => $dns_nameservers,
|
||||
dns_domain => $dns_domain,
|
||||
dns_search => $dns_search,
|
||||
ifname_order_prefix => 'ovs',
|
||||
}
|
||||
}
|
|
@ -16,47 +16,21 @@
|
|||
# [*netmask*]
|
||||
# Specify network mask. Default is '255.255.255.0'.
|
||||
#
|
||||
# [*macaddr*]
|
||||
# Specify macaddr if need change.
|
||||
#
|
||||
# [*vlandev*]
|
||||
# If you configure 802.1q vlan interface with name like 'vlanXXX'
|
||||
# you must specify a parent interface in this option
|
||||
#
|
||||
# [*bond_master*]
|
||||
# This parameter sets the bond_master interface and says that this interface
|
||||
# is a slave for bondX interface.
|
||||
#
|
||||
# [*bond_properties*]
|
||||
# This parameter specifies a bond properties for interfaces like bondNN.
|
||||
# It's a property hash, that should contains native linux bonding options, ex:
|
||||
# bond_properties => {
|
||||
# mode => 1, # mode is a obligatory option
|
||||
# miimon => 100,
|
||||
# ....
|
||||
# }
|
||||
#
|
||||
# bond_properties will be ignored for bond-slave interfaces
|
||||
# Full set of properties we can see here: https://www.kernel.org/doc/Documentation/networking/bonding.txt
|
||||
#
|
||||
# [*ifname_order_prefix*]
|
||||
# Sets the interface startup order
|
||||
#
|
||||
# [*gateway*]
|
||||
# Specify default gateway if need.
|
||||
# You can specify IP address, or 'save' for save default route
|
||||
# if it lies through this interface now.
|
||||
#
|
||||
# [*default_gateway*]
|
||||
# Specify if this nic and gateway should become the default route.
|
||||
# requires that gateway is also set.
|
||||
#
|
||||
# [*other_nets*]
|
||||
# Optional. Defines additional networks that this inteface can reach in CIDR
|
||||
# format.
|
||||
# It will be used to add additional routes to this interface.
|
||||
# other_nets => ['10.10.2.0/24', '10.10.4.0/24']
|
||||
#
|
||||
## [*default_gateway*]
|
||||
## Specify if this nic and gateway should become the default route.
|
||||
## requires that gateway is also set.
|
||||
##
|
||||
## [*other_nets*]
|
||||
## Optional. Defines additional networks that this inteface can reach in CIDR
|
||||
## format.
|
||||
## It will be used to add additional routes to this interface.
|
||||
## other_nets => ['10.10.2.0/24', '10.10.4.0/24']
|
||||
##
|
||||
# [*dns_nameservers*]
|
||||
# Specify a pair of nameservers if need. Must be an array, for example:
|
||||
# nameservers => ['8.8.8.8', '8.8.4.4']
|
||||
|
@ -84,88 +58,35 @@
|
|||
# [*check_by_ping_timeout*]
|
||||
# Timeout for check_by_ping
|
||||
#
|
||||
# [*ethtool*]
|
||||
# You can specify k/w hash with ethtool key/value pairs.
|
||||
# If this hash not empty, this ethtool with this parameters will be executed
|
||||
# at each boot
|
||||
#
|
||||
# If you configure 802.1q vlan interfaces then you must declare relationships
|
||||
# between them in site.pp.
|
||||
# Ex: L23network:L3:Ifconfig['eth2'] -> L23network:L3:Ifconfig['eth2.128']
|
||||
#
|
||||
|
||||
define l23network::l3::ifconfig (
|
||||
$ipaddr,
|
||||
$ensure = present,
|
||||
$interface = $name,
|
||||
$netmask = '255.255.255.0',
|
||||
$ipaddr = undef,
|
||||
# $netmask = '255.255.255.0', # I hardly want deprecate this address notation
|
||||
$gateway = undef,
|
||||
$default_gateway = false,
|
||||
$other_nets = undef,
|
||||
$vlandev = undef,
|
||||
$bond_master = undef,
|
||||
$bond_properties = {},
|
||||
$bond_mode = undef, # deprecated, should be used $bond_properties hash
|
||||
$bond_miimon = undef, # deprecated, should be used $bond_properties hash
|
||||
$bond_lacp_rate = undef, # deprecated, should be used $bond_properties hash
|
||||
$mtu = undef,
|
||||
$macaddr = undef,
|
||||
$ethtool = undef,
|
||||
$gateway_metric = undef,
|
||||
# $default_gateway = false,
|
||||
# $other_nets = undef,
|
||||
$dns_nameservers = undef,
|
||||
$dns_search = undef,
|
||||
$dns_domain = undef,
|
||||
$dhcp_hostname = undef,
|
||||
$dhcp_nowait = false,
|
||||
$ifname_order_prefix = false,
|
||||
# $dhcp_nowait = false,
|
||||
$check_by_ping = 'gateway',
|
||||
$check_by_ping_timeout = 30,
|
||||
#todo: label => "XXX", # -- "ip addr add..... label XXX"
|
||||
){
|
||||
$vendor_specific = undef,
|
||||
$provider = undef
|
||||
) {
|
||||
include ::l23network::params
|
||||
|
||||
$bond_properties_defaults = {
|
||||
mode => 0,
|
||||
miimon => 100,
|
||||
lacp_rate => 1,
|
||||
}
|
||||
|
||||
$bond_modes = [
|
||||
'balance-rr',
|
||||
'active-backup',
|
||||
'balance-xor',
|
||||
'broadcast',
|
||||
'802.3ad',
|
||||
'balance-tlb',
|
||||
'balance-alb'
|
||||
]
|
||||
|
||||
if $bond_properties[mode] or $bond_mode {
|
||||
$actual_bond_properties = get_hash_with_defaults_and_deprecations(
|
||||
$bond_properties,
|
||||
$bond_properties_defaults,
|
||||
{
|
||||
mode => $bond_mode,
|
||||
miimon => $bond_miimon,
|
||||
lacp_rate => $bond_lacp_rate,
|
||||
}
|
||||
)
|
||||
} else {
|
||||
$actual_bond_properties = { mode => undef, }
|
||||
}
|
||||
|
||||
if $macaddr and $macaddr !~ /^([0-9a-fA-F]{2}\:){5}[0-9a-fA-F]{2}$/ {
|
||||
fail("Invalid MAC address '${macaddr}' for interface '${interface}'")
|
||||
}
|
||||
|
||||
if $mtu and !is_integer("${mtu}") { # is_integer() fails if integer given :)
|
||||
fail("Invalid MTU '${mtu}' for interface '${interface}'")
|
||||
}
|
||||
|
||||
# setup configure method for inteface
|
||||
if $bond_master {
|
||||
$method = 'bondslave'
|
||||
} elsif is_array($ipaddr) {
|
||||
if is_array($ipaddr) {
|
||||
# getting array of IP addresses for one interface
|
||||
$method = 'static'
|
||||
check_cidrs($ipaddr)
|
||||
$ipaddr_list = $ipaddr
|
||||
$effective_ipaddr = cidr_to_ipaddr($ipaddr[0])
|
||||
$effective_netmask = cidr_to_netmask($ipaddr[0])
|
||||
$ipaddr_aliases = array_part($ipaddr,1,0)
|
||||
|
@ -177,11 +98,13 @@ define l23network::l3::ifconfig (
|
|||
$method = 'dhcp'
|
||||
$effective_ipaddr = 'dhcp'
|
||||
$effective_netmask = undef
|
||||
$ipaddr_list = ['dhcp']
|
||||
}
|
||||
'none': {
|
||||
$method = 'manual'
|
||||
$effective_ipaddr = 'none'
|
||||
$effective_netmask = undef
|
||||
$ipaddr_list = ['none']
|
||||
}
|
||||
default: {
|
||||
$method = 'static'
|
||||
|
@ -189,39 +112,18 @@ define l23network::l3::ifconfig (
|
|||
# ipaddr can be cidr-notated
|
||||
$effective_ipaddr = cidr_to_ipaddr($ipaddr)
|
||||
$effective_netmask = cidr_to_netmask($ipaddr)
|
||||
$ipaddr_list = [$ipaddr]
|
||||
} else {
|
||||
# or classic pair of ipaddr+netmask
|
||||
$effective_ipaddr = $ipaddr
|
||||
$effective_netmask = $netmask
|
||||
$cidr_notated_effective_netmask = netmask_to_cidr($netmask)
|
||||
$ipaddr_list = ["${ipaddr}/${cidr_notated_effective_netmask}"]
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fail("Ipaddr must be a string or array of strings")
|
||||
}
|
||||
|
||||
# OS dependent constants and packages
|
||||
case $::osfamily {
|
||||
/(?i)debian/: {
|
||||
$if_files_dir = '/etc/network/interfaces.d'
|
||||
$interfaces = '/etc/network/interfaces'
|
||||
}
|
||||
/(?i)redhat/: {
|
||||
$if_files_dir = '/etc/sysconfig/network-scripts'
|
||||
$interfaces = false
|
||||
if ! defined(Class[L23network::L2::Centos_upndown_scripts]) {
|
||||
if defined(Stage[netconfig]) {
|
||||
class{'l23network::l2::centos_upndown_scripts': stage=>'netconfig' }
|
||||
} else {
|
||||
class{'l23network::l2::centos_upndown_scripts': }
|
||||
}
|
||||
}
|
||||
Anchor <| title == 'l23network::l2::centos_upndown_scripts' |>
|
||||
-> L23network::L3::Ifconfig <| interface == "${interface}" |>
|
||||
}
|
||||
default: {
|
||||
fail("Unsupported OS: ${::osfamily}/${::operatingsystem}")
|
||||
}
|
||||
fail('Ipaddr must be a single IPaddr or list of IPaddrs in CIDR notation.')
|
||||
}
|
||||
|
||||
# DNS nameservers, search and domain options
|
||||
|
@ -235,7 +137,7 @@ define l23network::l3::ifconfig (
|
|||
if $dns_search_list {
|
||||
$dns_search_string = join($dns_search_list, ' ')
|
||||
} else {
|
||||
fail("dns_search option must be array or string")
|
||||
fail('dns_search option must be array or string')
|
||||
}
|
||||
}
|
||||
if $dns_domain {
|
||||
|
@ -243,148 +145,96 @@ define l23network::l3::ifconfig (
|
|||
if $dns_domain_list {
|
||||
$dns_domain_string = $dns_domain_list[0]
|
||||
} else {
|
||||
fail("dns_domain option must be array or string")
|
||||
fail('dns_domain option must be array or string')
|
||||
}
|
||||
}
|
||||
|
||||
# Detect VLAN and bond mode configuration
|
||||
case $interface {
|
||||
/^vlan(\d+)/: {
|
||||
$vlan_mode = 'vlan'
|
||||
$vlan_id = $1
|
||||
if $vlandev {
|
||||
$vlan_dev = $vlandev
|
||||
} else {
|
||||
fail("Can't configure vlan interface ${interface} without definition (ex: vlandev=>ethXX).")
|
||||
}
|
||||
}
|
||||
/^(eth\d+)\.(\d+)/: { # TODO: bond0.123 -- also vlan
|
||||
$vlan_mode = 'eth'
|
||||
$vlan_id = $2
|
||||
$vlan_dev = $1
|
||||
}
|
||||
/^(bond\d+)/: {
|
||||
if ! $actual_bond_properties[mode] {
|
||||
fail('To configure the interface bonding you should the mode properties for bond is required and must be between 0..6.')
|
||||
}
|
||||
if $actual_bond_properties[mode] <0 or $actual_bond_properties[mode] >6 {
|
||||
fail("For interface bonding the bond mode should be between 0..6, not '${actual_bond_properties[mode]}'.")
|
||||
}
|
||||
$vlan_mode = undef
|
||||
}
|
||||
default: {
|
||||
$vlan_mode = undef
|
||||
}
|
||||
}
|
||||
|
||||
# Specify interface file name prefix
|
||||
if $ifname_order_prefix {
|
||||
$interface_file= "${if_files_dir}/ifcfg-${ifname_order_prefix}-${interface}"
|
||||
} else {
|
||||
$interface_file= "${if_files_dir}/ifcfg-${interface}"
|
||||
}
|
||||
# # Specify interface file name prefix
|
||||
# if $ifname_order_prefix {
|
||||
# $interface_file= "${::l23network::params::interfaces_dir}/ifcfg-${ifname_order_prefix}-${interface}"
|
||||
# } else {
|
||||
# $interface_file= "${::l23network::params::interfaces_dir}/ifcfg-${interface}"
|
||||
# }
|
||||
# File<| title == "${::l23network::params::interfaces_dir}" |> -> File<| title == "${interface_file}" |>
|
||||
|
||||
if $method == 'static' {
|
||||
if $gateway and $gateway != 'save' and $default_gateway {
|
||||
if $gateway and $gateway != 'save' {
|
||||
$def_gateway = $gateway
|
||||
} elsif $gateway == 'save' and $::l3_default_route and $::l3_default_route_interface == $interface {
|
||||
$def_gateway = $::l3_default_route
|
||||
} else {
|
||||
# recognizing default gateway
|
||||
if $gateway == 'save' and $::l3_default_route and $::l3_default_route_interface == $interface {
|
||||
$def_gateway = $::l3_default_route
|
||||
} else {
|
||||
$def_gateway = undef
|
||||
}
|
||||
}
|
||||
if (($::osfamily == 'RedHat' or $::osfamily == 'Debian') and
|
||||
$def_gateway and
|
||||
!defined(L23network::L3::Defaultroute[$def_gateway])
|
||||
) {
|
||||
L3_if_downup[$interface] ->
|
||||
l23network::l3::defaultroute { $def_gateway: }
|
||||
$def_gateway = undef
|
||||
}
|
||||
# # todo: move routing to separated resource with his own provider
|
||||
# if ($def_gateway and !defined(L23network::L3::Defaultroute[$def_gateway])) {
|
||||
# Anchor['l23network::init'] ->
|
||||
# L3_ifconfig[$interface]
|
||||
# ->
|
||||
# l23network::l3::defaultroute { $def_gateway: }
|
||||
# }
|
||||
} else {
|
||||
$def_gateway = undef
|
||||
}
|
||||
|
||||
if $other_nets {
|
||||
if $::osfamily =~ /(?i)redhat/ and $other_nets {
|
||||
file {"${if_files_dir}/route-${interface}":
|
||||
ensure => present,
|
||||
owner => 'root',
|
||||
mode => '0755',
|
||||
recurse => true,
|
||||
content => template("l23network/route_${::osfamily}.erb"),
|
||||
} ->
|
||||
File <| title == $interface_file |>
|
||||
}
|
||||
}
|
||||
# todo: re-implement later
|
||||
# if $::osfamily =~ /(?i)redhat/ and ($ipaddr_aliases or $ethtool_lines) {
|
||||
# Anchor['l23network::init'] ->
|
||||
# file {"${::l23network::params::interfaces_dir}/interface-up-script-${interface}":
|
||||
# ensure => present,
|
||||
# owner => 'root',
|
||||
# mode => '0755',
|
||||
# recurse => true,
|
||||
# content => template("l23network/ipconfig_${::osfamily}_ifup-script.erb"),
|
||||
# } ->
|
||||
# file {"${::l23network::params::interfaces_dir}/interface-dn-script-${interface}":
|
||||
# ensure => present,
|
||||
# owner => 'root',
|
||||
# mode => '0755',
|
||||
# recurse => true,
|
||||
# content => template("l23network/ipconfig_${::osfamily}_ifdn-script.erb"),
|
||||
# } ->
|
||||
# File <| title == $interface_file |>
|
||||
# }
|
||||
|
||||
if $interfaces {
|
||||
if ! defined(File["${interfaces}"]) {
|
||||
file {"${interfaces}":
|
||||
ensure => present,
|
||||
content => template('l23network/interfaces.erb'),
|
||||
if ! defined (L3_ifconfig[$interface]) {
|
||||
if $provider {
|
||||
$config_provider = "${provider}_${::l23_os}"
|
||||
} else {
|
||||
$config_provider = undef
|
||||
}
|
||||
|
||||
|
||||
if ! defined (L23_stored_config[$interface]) {
|
||||
l23_stored_config { $interface:
|
||||
provider => $config_provider
|
||||
}
|
||||
}
|
||||
File<| title == "${interfaces}" |> -> File<| title == "${if_files_dir}" |>
|
||||
}
|
||||
L23_stored_config <| title == $interface |> {
|
||||
method => $method,
|
||||
ipaddr => $ipaddr_list[0],
|
||||
gateway => $def_gateway,
|
||||
gateway_metric => $gateway_metric,
|
||||
vendor_specific => $vendor_specific,
|
||||
#provider => $config_provider # do not enable, provider should be set while port define
|
||||
}
|
||||
|
||||
if ! defined(File["${if_files_dir}"]) {
|
||||
file {"${if_files_dir}":
|
||||
ensure => directory,
|
||||
owner => 'root',
|
||||
mode => '0755',
|
||||
recurse => true,
|
||||
# configure runtime
|
||||
l3_ifconfig { $interface :
|
||||
ensure => $ensure,
|
||||
ipaddr => $ipaddr_list,
|
||||
gateway => $def_gateway,
|
||||
gateway_metric => $gateway_metric,
|
||||
## $default_gateway = false,
|
||||
## $other_nets = undef,
|
||||
# dns_nameservers => $dns_nameservers,
|
||||
# dns_search => $dns_search_string,
|
||||
# dns_domain => $dns_domain_string,
|
||||
# dhcp_hostname => $dhcp_hostname,
|
||||
# check_by_ping => $check_by_ping,
|
||||
# check_by_ping_timeout => $check_by_ping_timeout,
|
||||
vendor_specific => $vendor_specific,
|
||||
provider => $provider # For L3 features provider independed from OVS
|
||||
}
|
||||
}
|
||||
File<| title == "${if_files_dir}" |> -> File<| title == "${interface_file}" |>
|
||||
|
||||
if $ethtool {
|
||||
$ethtool_lines=ethtool_convert_hash($ethtool)
|
||||
}
|
||||
|
||||
if $::osfamily =~ /(?i)redhat/ and ($ipaddr_aliases or $ethtool_lines) {
|
||||
file {"${if_files_dir}/interface-up-script-${interface}":
|
||||
ensure => present,
|
||||
owner => 'root',
|
||||
mode => '0755',
|
||||
recurse => true,
|
||||
content => template("l23network/ipconfig_${::osfamily}_ifup-script.erb"),
|
||||
} ->
|
||||
file {"${if_files_dir}/interface-dn-script-${interface}":
|
||||
ensure => present,
|
||||
owner => 'root',
|
||||
mode => '0755',
|
||||
recurse => true,
|
||||
content => template("l23network/ipconfig_${::osfamily}_ifdn-script.erb"),
|
||||
} ->
|
||||
File <| title == $interface_file |>
|
||||
}
|
||||
|
||||
file {"${interface_file}":
|
||||
ensure => present,
|
||||
owner => 'root',
|
||||
mode => '0644',
|
||||
content => template("l23network/ipconfig_${::osfamily}_${method}.erb"),
|
||||
}
|
||||
|
||||
# bond master interface should be upped only after including at least one slave interface to one
|
||||
if $interface =~ /^(bond\d+)/ {
|
||||
$l3_if_downup__subscribe = undef
|
||||
File["${interface_file}"] -> L3_if_downup["${interface}"] # do not remove!!! we using L3_if_downup["bondXX"] in advanced_netconfig
|
||||
# todo(sv): filter and notify L3_if_downup["$interface"] if need.
|
||||
# in Centos it works properly without it.
|
||||
# May be because slaves of bond automaticaly ups master-bond
|
||||
# L3_if_downup<| $bond_master == $interface |> ~> L3_if_downup["$interface"]
|
||||
} else {
|
||||
$l3_if_downup__subscribe = File["${interface_file}"]
|
||||
}
|
||||
notify {"ifconfig_${interface}": message=>"Interface:${interface} IP:${effective_ipaddr}/${effective_netmask}", withpath=>false} ->
|
||||
l3_if_downup {"${interface}":
|
||||
check_by_ping => $check_by_ping,
|
||||
check_by_ping_timeout => $check_by_ping_timeout,
|
||||
#require => File["$interface_file"], ## do not enable it!!! It affect requirements interface from interface in some cases.
|
||||
subscribe => $l3_if_downup__subscribe,
|
||||
refreshonly => true,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
# L23network OS-aware constants
|
||||
#
|
||||
class l23network::params {
|
||||
$need_datapath_module = !str2bool($::kern_has_ovs_datapath)
|
||||
$monolith_bond_providers = ['ovs']
|
||||
|
||||
case $::osfamily {
|
||||
/(?i)debian/: {
|
||||
$interfaces_dir = '/etc/network/interfaces.d'
|
||||
$interfaces_file = '/etc/network/interfaces'
|
||||
$ovs_service_name = 'openvswitch-switch'
|
||||
$ovs_status_cmd = '/etc/init.d/openvswitch-switch status'
|
||||
$lnx_vlan_tools = 'vlan'
|
||||
$lnx_bond_tools = 'ifenslave'
|
||||
$lnx_ethernet_tools = 'ethtool'
|
||||
$lnx_bridge_tools = 'bridge-utils'
|
||||
$ovs_datapath_package_name = $need_datapath_module ? {
|
||||
true => 'openvswitch-datapath-lts-saucy-dkms',
|
||||
default => false
|
||||
|
@ -15,14 +21,28 @@ class l23network::params {
|
|||
$ovs_common_package_name = 'openvswitch-switch'
|
||||
}
|
||||
/(?i)redhat/: {
|
||||
$interfaces_dir = '/etc/sysconfig/network-scripts'
|
||||
$interfaces_file = undef
|
||||
$ovs_service_name = 'openvswitch'
|
||||
$ovs_status_cmd = '/etc/init.d/openvswitch status'
|
||||
$lnx_vlan_tools = 'vconfig'
|
||||
$lnx_bond_tools = undef
|
||||
$lnx_ethernet_tools = 'ethtool'
|
||||
$lnx_bridge_tools = 'bridge-utils'
|
||||
$ovs_datapath_package_name = 'kmod-openvswitch'
|
||||
$ovs_common_package_name = 'openvswitch'
|
||||
}
|
||||
/(?i)darwin/: {
|
||||
$interfaces_dir = '/tmp/1'
|
||||
$interfaces_file = undef
|
||||
$ovs_service_name = undef
|
||||
$lnx_vlan_tools = undef
|
||||
$lnx_bond_tools = undef
|
||||
$lnx_ethernet_tools = undef
|
||||
$lnx_bridge_tools = undef
|
||||
$ovs_datapath_package_name = undef
|
||||
$ovs_common_package_name = undef
|
||||
}
|
||||
default: {
|
||||
fail("Unsupported OS: ${::osfamily}/${::operatingsystem}")
|
||||
}
|
||||
|
|
|
@ -1,191 +0,0 @@
|
|||
require 'rspec-puppet'
|
||||
require 'spec_helper'
|
||||
require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals'
|
||||
require 'yaml'
|
||||
|
||||
#fuel_settings = YAML::load(<<-EOM)
|
||||
c_ipaddr = '10.0.0.1'
|
||||
c_masklen = '24'
|
||||
c_mode = 2
|
||||
c_bondname = 'bond0'
|
||||
c_interfaces = ['eth1','eth2']
|
||||
c_lacp_rate = 2
|
||||
c_miimon = 150
|
||||
bond_modes = [
|
||||
'balance-rr',
|
||||
'active-backup',
|
||||
'balance-xor',
|
||||
'broadcast',
|
||||
'802.3ad',
|
||||
'balance-tlb',
|
||||
'balance-alb'
|
||||
]
|
||||
fuel_settings = YAML::load(<<-EOM)
|
||||
network_scheme:
|
||||
version: '1.0'
|
||||
provider: ovs
|
||||
interfaces:
|
||||
eth2:
|
||||
L2:
|
||||
vlan_splinters: 'off'
|
||||
eth1:
|
||||
L2:
|
||||
vlan_splinters: 'off'
|
||||
transformations:
|
||||
- action: add-br
|
||||
name: br-#{c_bondname}
|
||||
- action: add-bond
|
||||
bridge: br-#{c_bondname}
|
||||
name: #{c_bondname}
|
||||
provider: lnx
|
||||
interfaces:
|
||||
- eth1
|
||||
- eth2
|
||||
properties:
|
||||
mode: #{c_mode}
|
||||
miimon: #{c_miimon}
|
||||
lacp_rate: #{c_lacp_rate}
|
||||
endpoints:
|
||||
#{c_bondname}:
|
||||
IP:
|
||||
- #{c_ipaddr}/#{c_masklen}
|
||||
# eth1:
|
||||
# IP: none
|
||||
# eth2:
|
||||
# IP: none
|
||||
EOM
|
||||
|
||||
#p fuel_settings
|
||||
|
||||
# Ubintu, static
|
||||
describe 'l23network::examples::adv_net_config__bond_lnx', :type => :class do
|
||||
let(:module_path) { '../' }
|
||||
#let(:title) { 'bond0' }
|
||||
let(:params) { {
|
||||
:fuel_settings => fuel_settings
|
||||
} }
|
||||
let(:facts) { {
|
||||
:l3_fqdn_hostname => 'qweqweqwe',
|
||||
:osfamily => 'Debian',
|
||||
:operatingsystem => 'Ubuntu',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' }
|
||||
|
||||
it "Should contains interface_file" do
|
||||
should contain_file('/etc/network/interfaces').with_content(/\*/)
|
||||
end
|
||||
|
||||
it 'Should contains interface_file with IP-addr' do
|
||||
rv = contain_file("#{interface_file_start}#{c_bondname}")
|
||||
should rv.with_content(/auto\s+#{c_bondname}/)
|
||||
should rv.with_content(/iface\s+#{c_bondname}/)
|
||||
should rv.with_content(/address\s+#{c_ipaddr}/)
|
||||
should rv.with_content(/netmask\s+255.255.255.0/)
|
||||
end
|
||||
|
||||
it 'Should contains bond-specific parameters' do
|
||||
rv = contain_file("#{interface_file_start}#{c_bondname}")
|
||||
should rv.with_content(/slaves\s+none/)
|
||||
should rv.with_content(/bond-mode\s+#{c_mode}/)
|
||||
should rv.with_content(/bond-miimon\s+#{c_miimon}/)
|
||||
should rv.with_content(/bond-lacp-rate\s+#{c_lacp_rate}/)
|
||||
end
|
||||
|
||||
it 'Should contains interface files for bond-slave interfaces' do
|
||||
c_interfaces.each do |iface|
|
||||
rv = contain_file("#{interface_file_start}#{iface}")
|
||||
should rv.with_content(/auto\s+#{iface}/)
|
||||
should rv.with_content(/iface\s+#{iface}/)
|
||||
should rv.with_content(/bond-master\s+#{c_bondname}/)
|
||||
end
|
||||
end
|
||||
|
||||
it 'ALL: Should contains l23network::l2::bridge resource' do
|
||||
rv = contain_l23network__l2__bridge("br-#{c_bondname}")
|
||||
should rv.with(
|
||||
'ensure' => 'present'
|
||||
)
|
||||
end
|
||||
|
||||
it 'ALL: Should contains l23network::l2::port resource' do
|
||||
rv = contain_l23network__l2__port("#{c_bondname}")
|
||||
should rv.with(
|
||||
'bridge' => "br-#{c_bondname}",
|
||||
'ensure' => 'present'
|
||||
)
|
||||
end
|
||||
|
||||
it 'ALL: Should contains relationship beetwen l23network::l2::bridge and l23network::l2::port' do
|
||||
bridge = contain_l23network__l2__bridge("br-#{c_bondname}")
|
||||
should bridge.that_comes_before("L23network::L2::Port[#{c_bondname}]")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Centos, static
|
||||
describe 'l23network::examples::adv_net_config__bond_lnx', :type => :class do
|
||||
let(:module_path) { '../' }
|
||||
#let(:title) { 'bond0' }
|
||||
let(:params) { {
|
||||
:fuel_settings => fuel_settings
|
||||
} }
|
||||
let(:facts) { {
|
||||
:l3_fqdn_hostname => 'qweqweqwe',
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystem => 'Centos',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' }
|
||||
let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' }
|
||||
let(:bond_modes) { [
|
||||
'balance-rr',
|
||||
'active-backup',
|
||||
'balance-xor',
|
||||
'broadcast',
|
||||
'802.3ad',
|
||||
'balance-tlb',
|
||||
'balance-alb'
|
||||
] }
|
||||
|
||||
it 'Should contains interface_file with IP-addr' do
|
||||
rv = contain_file("#{interface_file_start}#{c_bondname}")
|
||||
should rv.with_content(/DEVICE=#{c_bondname}/)
|
||||
should rv.with_content(/BOOTPROTO=none/)
|
||||
should rv.with_content(/ONBOOT=yes/)
|
||||
should rv.with_content(/IPADDR=#{c_ipaddr}/)
|
||||
should rv.with_content(/NETMASK=255.255.255.0/)
|
||||
end
|
||||
|
||||
it 'Should contains interface files for bond-slave interfaces' do
|
||||
c_interfaces.each do |iface|
|
||||
rv = contain_file("#{interface_file_start}#{iface}")
|
||||
should rv.with_content(/DEVICE=#{iface}/)
|
||||
should rv.with_content(/BOOTPROTO=none/)
|
||||
should rv.with_content(/ONBOOT=yes/)
|
||||
should rv.with_content(/MASTER=#{c_bondname}/)
|
||||
should rv.with_content(/SLAVE=yes/)
|
||||
end
|
||||
end
|
||||
|
||||
it 'Should contains Bonding-opts line' do
|
||||
rv = contain_file("#{interface_file_start}#{c_bondname}")
|
||||
should rv.with_content(/DEVICE=#{c_bondname}/)
|
||||
should rv.with_content(/BONDING_OPTS="mode=/)
|
||||
end
|
||||
|
||||
it 'Should contains Bond mode' do
|
||||
rv = contain_file("#{interface_file_start}#{c_bondname}")
|
||||
should rv.with_content(/BONDING_OPTS.*mode=#{bond_modes[c_mode]}/)
|
||||
end
|
||||
|
||||
it 'Should contains miimon' do
|
||||
rv = contain_file("#{interface_file_start}#{c_bondname}")
|
||||
should rv.with_content(/BONDING_OPTS.*miimon=#{c_miimon}/)
|
||||
end
|
||||
|
||||
it 'Should contains lacp_rate' do
|
||||
rv = contain_file("#{interface_file_start}#{c_bondname}")
|
||||
should rv.with_content(/BONDING_OPTS.*lacp_rate=#{c_lacp_rate}/)
|
||||
end
|
||||
end
|
|
@ -1,117 +0,0 @@
|
|||
require 'rspec-puppet'
|
||||
require 'spec_helper'
|
||||
require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals'
|
||||
require 'yaml'
|
||||
|
||||
#fuel_settings = YAML::load(<<-EOM)
|
||||
c_bondname = 'bond0'
|
||||
c_interfaces = ['eth1','eth2']
|
||||
c_lacp_rate = 2
|
||||
c_miimon = 150
|
||||
fuel_settings = YAML::load(<<-EOM)
|
||||
network_scheme:
|
||||
version: '1.0'
|
||||
provider: ovs
|
||||
interfaces:
|
||||
eth2:
|
||||
L2:
|
||||
vlan_splinters: 'off'
|
||||
eth1:
|
||||
L2:
|
||||
vlan_splinters: 'off'
|
||||
eth5:
|
||||
fake:
|
||||
interface: eth5
|
||||
transformations:
|
||||
- action: add-br
|
||||
name: br-#{c_bondname}
|
||||
- action: add-bond
|
||||
bridge: br-#{c_bondname}
|
||||
name: #{c_bondname}
|
||||
interfaces:
|
||||
- eth1
|
||||
- eth2
|
||||
properties:
|
||||
- bond_mode=active-backup
|
||||
endpoints:
|
||||
eth5:
|
||||
IP: none
|
||||
EOM
|
||||
|
||||
# Ubintu
|
||||
describe 'l23network::examples::adv_net_config__bond_ovs', :type => :class do
|
||||
let(:module_path) { '../' }
|
||||
#let(:title) { 'bond0' }
|
||||
let(:params) { {
|
||||
:fuel_settings => fuel_settings
|
||||
} }
|
||||
let(:facts) { {
|
||||
:l3_fqdn_hostname => 'qweqweqwe',
|
||||
:osfamily => 'Debian',
|
||||
:operatingsystem => 'Ubuntu',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' }
|
||||
|
||||
it "UBUNTU: Should contains interface_file" do
|
||||
should contain_file('/etc/network/interfaces').with_content(/\*/)
|
||||
end
|
||||
|
||||
it 'UBUNTU: Should contains interface files for bond-slave interfaces' do
|
||||
c_interfaces.each do |iface|
|
||||
rv = contain_file("#{interface_file_start}#{iface}")
|
||||
should rv.with_content(/auto\s+#{iface}/)
|
||||
should rv.with_content(/iface\s+#{iface}/)
|
||||
should rv.with_content(/up\s+ip\s+l\s+set\s+#{iface}\s+up/)
|
||||
should rv.with_content(/down\s+ip\s+l\s+set\s+#{iface}\s+down/)
|
||||
end
|
||||
end
|
||||
|
||||
it 'ALL: Should contains l23network::l2::bridge resource' do
|
||||
rv = contain_l23network__l2__bridge("br-#{c_bondname}")
|
||||
should rv.with(
|
||||
'ensure' => 'present'
|
||||
)
|
||||
end
|
||||
|
||||
it 'ALL: Should contains l23network::l2::bond resource' do
|
||||
rv = contain_l23network__l2__bond("#{c_bondname}")
|
||||
should rv.with(
|
||||
'bridge' => "br-#{c_bondname}",
|
||||
'interfaces' => c_interfaces,
|
||||
'ensure' => 'present'
|
||||
)
|
||||
end
|
||||
|
||||
it 'ALL: Should contains relationship beetwen l23network::l2::bridge and l23network::l2::bond' do
|
||||
bridge = contain_l23network__l2__bridge("br-#{c_bondname}")
|
||||
should bridge.that_comes_before("L23network::L2::Bond[#{c_bondname}]")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Centos
|
||||
describe 'l23network::examples::adv_net_config__bond_ovs', :type => :class do
|
||||
let(:module_path) { '../' }
|
||||
#let(:title) { 'bond0' }
|
||||
let(:params) { {
|
||||
:fuel_settings => fuel_settings
|
||||
} }
|
||||
let(:facts) { {
|
||||
:l3_fqdn_hostname => 'qweqweqwe',
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystem => 'Centos',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' }
|
||||
|
||||
it 'CENTOS: Should contains interface files for bond-slave interfaces' do
|
||||
c_interfaces.each do |iface|
|
||||
rv = contain_file("#{interface_file_start}#{iface}")
|
||||
should rv.with_content(/DEVICE=#{iface}/)
|
||||
should rv.with_content(/BOOTPROTO=none/)
|
||||
should rv.with_content(/ONBOOT=yes/)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -1,130 +0,0 @@
|
|||
# require 'puppet'
|
||||
# require 'rspec'
|
||||
require 'rspec-puppet'
|
||||
require 'spec_helper'
|
||||
require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals'
|
||||
|
||||
# Ubintu, static
|
||||
describe 'l23network::examples::bond_lnx', :type => :class do
|
||||
let(:module_path) { '../' }
|
||||
#let(:title) { 'bond0' }
|
||||
let(:params) { {
|
||||
:bond => 'bond0',
|
||||
:ipaddr => '1.1.1.1/27',
|
||||
:interfaces => ['eth4','eth5'],
|
||||
:bond_properties => {
|
||||
'mode' => 2,
|
||||
'miimon' => 150,
|
||||
'lacp_rate' => 0,
|
||||
},
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'Debian',
|
||||
:operatingsystem => 'Ubuntu',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' }
|
||||
|
||||
it "Should contains interface_file" do
|
||||
should contain_file('/etc/network/interfaces').with_content(/\*/)
|
||||
end
|
||||
|
||||
it 'Should contains interface_file with IP-addr' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:bond]}")
|
||||
should rv.with_content(/auto\s+#{params[:bond]}/)
|
||||
should rv.with_content(/iface\s+#{params[:bond]}/)
|
||||
should rv.with_content(/address\s+1.1.1.1/)
|
||||
should rv.with_content(/netmask\s+255.255.255.224/)
|
||||
end
|
||||
|
||||
it 'Should contains bond-specific parameters' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:bond]}")
|
||||
should rv.with_content(/slaves\s+none/)
|
||||
should rv.with_content(/bond-mode\s+#{params[:bond_properties]['mode']}/)
|
||||
should rv.with_content(/bond-miimon\s+#{params[:bond_properties]['miimon']}/)
|
||||
should rv.with_content(/bond-lacp-rate\s+#{params[:bond_properties]['lacp_rate']}/)
|
||||
end
|
||||
|
||||
it 'Should contains interface files for bond-slave interfaces' do
|
||||
params[:interfaces].each do |iface|
|
||||
rv = contain_file("#{interface_file_start}#{iface}")
|
||||
should rv.with_content(/auto\s+#{iface}/)
|
||||
should rv.with_content(/iface\s+#{iface}/)
|
||||
should rv.with_content(/bond-master\s+#{params[:bond]}/)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Centos, static
|
||||
describe 'l23network::examples::bond_lnx', :type => :class do
|
||||
let(:module_path) { '../' }
|
||||
#let(:title) { 'bond0' }
|
||||
let(:params) { {
|
||||
:bond => 'bond0',
|
||||
:ipaddr => '1.1.1.1/27',
|
||||
:interfaces => ['eth4','eth5'],
|
||||
:bond_properties => {
|
||||
'mode' => 2,
|
||||
'miimon' => 150,
|
||||
'lacp_rate' => 0,
|
||||
},
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystem => 'Centos',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' }
|
||||
let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' }
|
||||
let(:bond_modes) { [
|
||||
'balance-rr',
|
||||
'active-backup',
|
||||
'balance-xor',
|
||||
'broadcast',
|
||||
'802.3ad',
|
||||
'balance-tlb',
|
||||
'balance-alb'
|
||||
] }
|
||||
|
||||
it 'Should contains interface_file with IP-addr' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:bond]}")
|
||||
should rv.with_content(/DEVICE=#{params[:bond]}/)
|
||||
should rv.with_content(/BOOTPROTO=none/)
|
||||
should rv.with_content(/ONBOOT=yes/)
|
||||
should rv.with_content(/IPADDR=1.1.1.1/)
|
||||
should rv.with_content(/NETMASK=255.255.255.224/)
|
||||
end
|
||||
|
||||
it 'Should contains interface files for bond-slave interfaces' do
|
||||
params[:interfaces].each do |iface|
|
||||
rv = contain_file("#{interface_file_start}#{iface}")
|
||||
should rv.with_content(/DEVICE=#{iface}/)
|
||||
should rv.with_content(/BOOTPROTO=none/)
|
||||
should rv.with_content(/ONBOOT=yes/)
|
||||
should rv.with_content(/MASTER=#{params[:bond]}/)
|
||||
should rv.with_content(/SLAVE=yes/)
|
||||
end
|
||||
end
|
||||
|
||||
it 'Should contains Bonding-opts line' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:bond]}")
|
||||
should rv.with_content(/DEVICE=#{params[:bond]}/)
|
||||
should rv.with_content(/BONDING_OPTS="mode=/)
|
||||
end
|
||||
|
||||
it 'Should contains Bond mode' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:bond]}")
|
||||
should rv.with_content(/BONDING_OPTS.*mode=#{bond_modes[params[:bond_properties]['mode']]}/)
|
||||
end
|
||||
|
||||
it 'Should contains miimon' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:bond]}")
|
||||
should rv.with_content(/BONDING_OPTS.*miimon=#{params[:bond_properties]['miimon']}/)
|
||||
end
|
||||
|
||||
it 'Should contains lacp_rate' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:bond]}")
|
||||
should rv.with_content(/BONDING_OPTS.*lacp_rate=#{params[:bond_properties]['lacp_rate']}/)
|
||||
end
|
||||
end
|
|
@ -1,126 +0,0 @@
|
|||
# require 'puppet'
|
||||
# require 'rspec'
|
||||
require 'rspec-puppet'
|
||||
require 'spec_helper'
|
||||
require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals'
|
||||
|
||||
# Ubintu, static
|
||||
describe 'l23network::examples::bond_lnx_old_style', :type => :class do
|
||||
let(:module_path) { '../' }
|
||||
#let(:title) { 'bond0' }
|
||||
let(:params) { {
|
||||
:bond => 'bond0',
|
||||
:ipaddr => '1.1.1.1/27',
|
||||
:interfaces => ['eth4','eth5'],
|
||||
:bond_mode => 2,
|
||||
:bond_miimon => 200,
|
||||
:bond_lacp_rate => 2,
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'Debian',
|
||||
:operatingsystem => 'Ubuntu',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' }
|
||||
|
||||
it "Should contains interface_file" do
|
||||
should contain_file('/etc/network/interfaces').with_content(/\*/)
|
||||
end
|
||||
|
||||
it 'Should contains interface_file with IP-addr' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:bond]}")
|
||||
should rv.with_content(/auto\s+#{params[:bond]}/)
|
||||
should rv.with_content(/iface\s+#{params[:bond]}/)
|
||||
should rv.with_content(/address\s+1.1.1.1/)
|
||||
should rv.with_content(/netmask\s+255.255.255.224/)
|
||||
end
|
||||
|
||||
it 'Should contains bond-specific parameters' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:bond]}")
|
||||
should rv.with_content(/slaves\s+none/)
|
||||
should rv.with_content(/bond-mode\s+#{params[:bond_mode]}/)
|
||||
should rv.with_content(/bond-miimon\s+#{params[:bond_miimon]}/)
|
||||
should rv.with_content(/bond-lacp-rate\s+#{params[:bond_lacp_rate]}/)
|
||||
end
|
||||
|
||||
it 'Should contains interface files for bond-slave interfaces' do
|
||||
params[:interfaces].each do |iface|
|
||||
rv = contain_file("#{interface_file_start}#{iface}")
|
||||
should rv.with_content(/auto\s+#{iface}/)
|
||||
should rv.with_content(/iface\s+#{iface}/)
|
||||
should rv.with_content(/bond-master\s+#{params[:bond]}/)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Centos, static
|
||||
describe 'l23network::examples::bond_lnx_old_style', :type => :class do
|
||||
let(:module_path) { '../' }
|
||||
#let(:title) { 'bond0' }
|
||||
let(:params) { {
|
||||
:bond => 'bond0',
|
||||
:ipaddr => '1.1.1.1/27',
|
||||
:interfaces => ['eth4','eth5'],
|
||||
:bond_mode => 2,
|
||||
:bond_miimon => 200,
|
||||
:bond_lacp_rate => 0,
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystem => 'Centos',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' }
|
||||
let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' }
|
||||
let(:bond_modes) { [
|
||||
'balance-rr',
|
||||
'active-backup',
|
||||
'balance-xor',
|
||||
'broadcast',
|
||||
'802.3ad',
|
||||
'balance-tlb',
|
||||
'balance-alb'
|
||||
] }
|
||||
|
||||
it 'Should contains interface_file with IP-addr' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:bond]}")
|
||||
should rv.with_content(/DEVICE=#{params[:bond]}/)
|
||||
should rv.with_content(/BOOTPROTO=none/)
|
||||
should rv.with_content(/ONBOOT=yes/)
|
||||
should rv.with_content(/IPADDR=1.1.1.1/)
|
||||
should rv.with_content(/NETMASK=255.255.255.224/)
|
||||
end
|
||||
|
||||
it 'Should contains interface files for bond-slave interfaces' do
|
||||
params[:interfaces].each do |iface|
|
||||
rv = contain_file("#{interface_file_start}#{iface}")
|
||||
should rv.with_content(/DEVICE=#{iface}/)
|
||||
should rv.with_content(/BOOTPROTO=none/)
|
||||
should rv.with_content(/ONBOOT=yes/)
|
||||
should rv.with_content(/MASTER=#{params[:bond]}/)
|
||||
should rv.with_content(/SLAVE=yes/)
|
||||
end
|
||||
end
|
||||
|
||||
it 'Should contains Bonding-opts line' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:bond]}")
|
||||
should rv.with_content(/DEVICE=#{params[:bond]}/)
|
||||
should rv.with_content(/BONDING_OPTS="mode=/)
|
||||
end
|
||||
|
||||
it 'Should contains Bond mode' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:bond]}")
|
||||
should rv.with_content(/BONDING_OPTS.*mode=#{bond_modes[params[:bond_mode]]}/)
|
||||
end
|
||||
|
||||
it 'Should contains miimon' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:bond]}")
|
||||
should rv.with_content(/BONDING_OPTS.*miimon=#{params[:miimon]}/)
|
||||
end
|
||||
|
||||
it 'Should contains lacp_rate' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:bond]}")
|
||||
should rv.with_content(/BONDING_OPTS.*lacp_rate=#{params[:lacp_rate]}/)
|
||||
end
|
||||
end
|
|
@ -1,145 +0,0 @@
|
|||
# require 'puppet'
|
||||
# require 'rspec'
|
||||
require 'rspec-puppet'
|
||||
require 'spec_helper'
|
||||
require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals'
|
||||
|
||||
# Ubintu, dhcp
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'ifconfig simple test' }
|
||||
let(:params) { {
|
||||
:interface => 'eth4',
|
||||
:ipaddr => 'dhcp'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'Debian',
|
||||
:operatingsystem => 'Ubuntu',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' }
|
||||
|
||||
it "Ubintu/dhcp: Should contain interface_file" do
|
||||
should contain_file('/etc/network/interfaces').with_content(/\*/)
|
||||
end
|
||||
|
||||
it 'Ubintu/dhcp: interface file should contain DHCP ipaddr and netmask' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.with_content(/auto\s+#{params[:interface]}/)
|
||||
should rv.with_content(/iface\s+#{params[:interface]}\s+inet\s+dhcp/)
|
||||
end
|
||||
|
||||
it "Ubintu/dhcp: interface file shouldn't contain ipaddr and netmask" do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.without_content(/address/)
|
||||
should rv.without_content(/netmask/)
|
||||
end
|
||||
|
||||
it "Ubintu/dhcp: interface file shouldn't contains bond-master options" do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.without_content(/bond-mode/)
|
||||
should rv.without_content(/slaves/)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Ubintu, dhcp, ordered iface
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'ifconfig simple test' }
|
||||
let(:params) { {
|
||||
:interface => 'eth4',
|
||||
:ipaddr => 'dhcp',
|
||||
:ifname_order_prefix => 'zzz'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'Debian',
|
||||
:operatingsystem => 'Ubuntu',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' }
|
||||
|
||||
it "Ubintu/dhcp: ordered.ifaces: Should contain interface_file" do
|
||||
should contain_file('/etc/network/interfaces').with_content(/\*/)
|
||||
end
|
||||
|
||||
it "Ubintu/dhcp: ordered.ifaces: interface file shouldn't contain ipaddr and netmask" do
|
||||
rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}")
|
||||
should rv.without_content(/address/)
|
||||
should rv.without_content(/netmask/)
|
||||
end
|
||||
|
||||
it "Ubintu/dhcp: ordered.ifaces: interface file should contain ifup/ifdn commands" do
|
||||
rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}")
|
||||
should rv.without_content(/address/)
|
||||
should rv.without_content(/netmask/)
|
||||
end
|
||||
|
||||
it "Ubintu/dhcp: ordered.ifaces: interface file shouldn't contains bond-master options" do
|
||||
rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}")
|
||||
should rv.without_content(/bond-mode/)
|
||||
should rv.without_content(/slaves/)
|
||||
end
|
||||
end
|
||||
|
||||
# Centos, dhcp
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'ifconfig simple test' }
|
||||
let(:params) { {
|
||||
:interface => 'eth4',
|
||||
:ipaddr => 'dhcp'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystem => 'Centos',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' }
|
||||
let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' }
|
||||
|
||||
it 'Centos/dhcp: interface file should contains true header' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.with_content(/DEVICE=#{params[:interface]}/)
|
||||
should rv.with_content(/BOOTPROTO=dhcp/)
|
||||
should rv.with_content(/ONBOOT=yes/)
|
||||
end
|
||||
|
||||
it "Centos/dhcp: Shouldn't contains interface_file with IP-addr" do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.without_content(/IPADDR=/)
|
||||
should rv.without_content(/NETMASK=/)
|
||||
end
|
||||
end
|
||||
|
||||
# Centos, dhcp, ordered iface
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'ifconfig simple test' }
|
||||
let(:params) { {
|
||||
:interface => 'eth4',
|
||||
:ipaddr => 'dhcp',
|
||||
:ifname_order_prefix => 'zzz'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystem => 'Centos',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' }
|
||||
let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' }
|
||||
|
||||
it 'Centos/dhcp: ordered.ifaces: interface file should contains true header' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}")
|
||||
should rv.with_content(/DEVICE=#{params[:interface]}/)
|
||||
should rv.with_content(/BOOTPROTO=dhcp/)
|
||||
should rv.with_content(/ONBOOT=yes/)
|
||||
end
|
||||
|
||||
it 'Centos/dhcp: ordered.ifaces: Should contains interface_file with IP-addr' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}")
|
||||
should rv.without_content(/IPADDR=/)
|
||||
should rv.without_content(/NETMASK=/)
|
||||
end
|
||||
end
|
||||
###
|
|
@ -1,154 +0,0 @@
|
|||
# require 'puppet'
|
||||
# require 'rspec'
|
||||
require 'rspec-puppet'
|
||||
require 'spec_helper'
|
||||
require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals'
|
||||
|
||||
# Ubintu, manual -- no IP addresses, but interface in UP state
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'ifconfig simple test' }
|
||||
let(:params) { {
|
||||
:interface => 'eth4',
|
||||
:ipaddr => 'none'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'Debian',
|
||||
:operatingsystem => 'Ubuntu',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' }
|
||||
|
||||
it "Ubintu/manual: Should contain interface_file" do
|
||||
should contain_file('/etc/network/interfaces').with_content(/\*/)
|
||||
end
|
||||
|
||||
it 'Ubintu/manual: interface file should contain DHCP ipaddr and netmask' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.with_content(/auto\s+#{params[:interface]}/)
|
||||
should rv.with_content(/iface\s+#{params[:interface]}\s+inet\s+manual/)
|
||||
end
|
||||
|
||||
it "Ubintu/manual: interface file shouldn't contain ipaddr and netmask" do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.without_content(/address/)
|
||||
should rv.without_content(/netmask/)
|
||||
end
|
||||
|
||||
it "Ubintu/manual: interface file should contain ifup/ifdn commands" do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.with_content(/up\s+ip\s+l\s+set\s+#{params[:interface]}\s+up/)
|
||||
should rv.with_content(/down\s+ip\s+l\s+set\s+#{params[:interface]}\s+down/)
|
||||
end
|
||||
|
||||
it "Ubintu/manual: interface file shouldn't contains bond-master options" do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.without_content(/bond-mode/)
|
||||
should rv.without_content(/slaves/)
|
||||
end
|
||||
end
|
||||
|
||||
# Ubintu, manual, ordered iface
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'ifconfig simple test' }
|
||||
let(:params) { {
|
||||
:interface => 'eth4',
|
||||
:ipaddr => 'none',
|
||||
:ifname_order_prefix => 'zzz'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'Debian',
|
||||
:operatingsystem => 'Ubuntu',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' }
|
||||
|
||||
it "Ubintu/manual: ordered.ifaces:Should contain interface_file" do
|
||||
should contain_file('/etc/network/interfaces').with_content(/\*/)
|
||||
end
|
||||
|
||||
it "Ubintu/manual: interface file shouldn't contain ipaddr and netmask" do
|
||||
rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}")
|
||||
should rv.without_content(/address/)
|
||||
should rv.without_content(/netmask/)
|
||||
end
|
||||
|
||||
it "Ubintu/manual: ordered.ifaces:interface file should contain ifup/ifdn commands" do
|
||||
rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}")
|
||||
should rv.with_content(/up\s+ip\s+l\s+set\s+#{params[:interface]}\s+up/)
|
||||
should rv.with_content(/down\s+ip\s+l\s+set\s+#{params[:interface]}\s+down/)
|
||||
end
|
||||
|
||||
it "Ubintu/manual: ordered.ifaces:interface file shouldn't contains bond-master options" do
|
||||
rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}")
|
||||
should rv.without_content(/bond-mode/)
|
||||
should rv.without_content(/slaves/)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
# Centos, manual -- no IP addresses, but interface in UP state
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'ifconfig simple test' }
|
||||
let(:params) { {
|
||||
:interface => 'eth4',
|
||||
:ipaddr => 'none'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystem => 'Centos',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' }
|
||||
let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' }
|
||||
|
||||
it 'Centos/manual: interface file should contains true header' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.with_content(/DEVICE=#{params[:interface]}/)
|
||||
should rv.with_content(/BOOTPROTO=none/)
|
||||
should rv.with_content(/ONBOOT=yes/)
|
||||
end
|
||||
|
||||
it "Centos/manual: Shouldn't contains interface_file with IP-addr" do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.without_content(/IPADDR=/)
|
||||
should rv.without_content(/NETMASK=/)
|
||||
end
|
||||
end
|
||||
|
||||
# Centos, manual, ordered iface
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'ifconfig simple test' }
|
||||
let(:params) { {
|
||||
:interface => 'eth4',
|
||||
:ipaddr => 'none',
|
||||
:ifname_order_prefix => 'zzz'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystem => 'Centos',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' }
|
||||
let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' }
|
||||
|
||||
it 'Centos/manual: ordered.ifaces: interface file should contains true header' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}")
|
||||
should rv.with_content(/DEVICE=#{params[:interface]}/)
|
||||
should rv.with_content(/BOOTPROTO=none/)
|
||||
should rv.with_content(/ONBOOT=yes/)
|
||||
end
|
||||
|
||||
it 'Centos/manual: ordered.ifaces: Should contains interface_file with IP-addr' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}")
|
||||
should rv.without_content(/IPADDR=/)
|
||||
should rv.without_content(/NETMASK=/)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
###
|
|
@ -1,211 +0,0 @@
|
|||
# require 'puppet'
|
||||
# require 'rspec'
|
||||
require 'rspec-puppet'
|
||||
require 'spec_helper'
|
||||
require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals'
|
||||
|
||||
# Ubintu, static
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'ifconfig simple test' }
|
||||
let(:params) { {
|
||||
:interface => 'eth4',
|
||||
:ipaddr => '1.2.3.4/16'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'Debian',
|
||||
:operatingsystem => 'Ubuntu',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' }
|
||||
|
||||
it "Ubintu/static: Should contain interface_file" do
|
||||
should contain_file('/etc/network/interfaces').with_content(/\*/)
|
||||
end
|
||||
|
||||
it 'Ubintu/static: interface file should contain ipaddr and netmask' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.with_content(/auto\s+#{params[:interface]}/)
|
||||
should rv.with_content(/iface\s+#{params[:interface]}\s+inet\s+static/)
|
||||
end
|
||||
|
||||
it 'Ubintu/static: interface file should contain ipaddr and netmask' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.with_content(/address\s+1.2.3.4/)
|
||||
should rv.with_content(/netmask\s+255.255.0.0/)
|
||||
end
|
||||
|
||||
it "Ubintu/static: interface file shouldn't contain bond-master options" do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.without_content(/bond-mode/)
|
||||
should rv.without_content(/slaves/)
|
||||
end
|
||||
end
|
||||
|
||||
# Ubintu, static, netmask as additional parameter
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'ifconfig simple test' }
|
||||
let(:params) { {
|
||||
:interface => 'eth4',
|
||||
:ipaddr => '1.2.3.4',
|
||||
:netmask => '255.255.0.0'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'Debian',
|
||||
:operatingsystem => 'Ubuntu',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' }
|
||||
|
||||
it "Ubintu/static: old.netmask: Should contains interface_file" do
|
||||
should contain_file('/etc/network/interfaces').with_content(/\*/)
|
||||
end
|
||||
|
||||
it 'Ubintu/static: old.netmask: interface file should contains true header' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.with_content(/auto\s+#{params[:interface]}/)
|
||||
should rv.with_content(/iface\s+#{params[:interface]}\s+inet\s+static/)
|
||||
end
|
||||
|
||||
it 'Ubintu/static: old.netmask: interface file should contains ipaddr and netmask' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.with_content(/address\s+#{params[:ipaddr]}/)
|
||||
should rv.with_content(/netmask\s+#{params[:netmask]}/)
|
||||
end
|
||||
|
||||
it "Ubintu/static: old.netmask: interface file shouldn't contains bond-master options" do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.without_content(/bond-mode/)
|
||||
should rv.without_content(/slaves/)
|
||||
end
|
||||
end
|
||||
|
||||
# Ubintu, static, ordered iface
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'ifconfig simple test' }
|
||||
let(:params) { {
|
||||
:interface => 'eth4',
|
||||
:ipaddr => '1.2.3.4/16',
|
||||
:ifname_order_prefix => 'zzz'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'Debian',
|
||||
:operatingsystem => 'Ubuntu',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' }
|
||||
|
||||
it "Ubintu/static: ordered.ifaces: Should contain interface_file" do
|
||||
should contain_file('/etc/network/interfaces').with_content(/\*/)
|
||||
end
|
||||
|
||||
it 'Ubintu/static: ordered.ifaces: interface file should contain ipaddr and netmask' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}")
|
||||
should rv.with_content(/auto\s+#{params[:interface]}/)
|
||||
should rv.with_content(/iface\s+#{params[:interface]}\s+inet\s+static/)
|
||||
end
|
||||
|
||||
it 'Ubintu/static: ordered.ifaces: interface file should contain ipaddr and netmask' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}")
|
||||
should rv.with_content(/address\s+1.2.3.4/)
|
||||
should rv.with_content(/netmask\s+255.255.0.0/)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
# Centos, static
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'ifconfig simple test' }
|
||||
let(:params) { {
|
||||
:interface => 'eth4',
|
||||
:ipaddr => '1.2.3.4/16'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystem => 'Centos',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' }
|
||||
let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' }
|
||||
|
||||
it 'Centos/static: interface file should contains true header' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.with_content(/DEVICE=#{params[:interface]}/)
|
||||
should rv.with_content(/BOOTPROTO=none/)
|
||||
should rv.with_content(/ONBOOT=yes/)
|
||||
end
|
||||
|
||||
it 'Centos/static: Should contains interface_file with IP-addr' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.with_content(/IPADDR=1.2.3.4/)
|
||||
should rv.with_content(/NETMASK=255.255.0.0/)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Centos, static, netmask as additional parameter
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'ifconfig simple test' }
|
||||
let(:params) { {
|
||||
:interface => 'eth4',
|
||||
:ipaddr => '1.2.3.4',
|
||||
:netmask => '255.255.0.0'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystem => 'Centos',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' }
|
||||
let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' }
|
||||
|
||||
it 'Centos/static: old.netmask: interface file should contains true header' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.with_content(/DEVICE=#{params[:interface]}/)
|
||||
should rv.with_content(/BOOTPROTO=none/)
|
||||
should rv.with_content(/ONBOOT=yes/)
|
||||
end
|
||||
|
||||
it 'Centos/static: old.netmask: Should contains interface_file with IP-addr' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:interface]}")
|
||||
should rv.with_content(/IPADDR=#{params[:ipaddr]}/)
|
||||
should rv.with_content(/NETMASK=#{params[:netmask]}/)
|
||||
end
|
||||
end
|
||||
|
||||
# Centos, static, ordered iface
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'ifconfig simple test' }
|
||||
let(:params) { {
|
||||
:interface => 'eth4',
|
||||
:ipaddr => '1.2.3.4/16',
|
||||
:ifname_order_prefix => 'zzz'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystem => 'Centos',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' }
|
||||
let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' }
|
||||
|
||||
it 'Centos/static: ordered.ifaces: interface file should contains true header' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}")
|
||||
should rv.with_content(/DEVICE=#{params[:interface]}/)
|
||||
should rv.with_content(/BOOTPROTO=none/)
|
||||
should rv.with_content(/ONBOOT=yes/)
|
||||
end
|
||||
|
||||
it 'Centos/static: ordered.ifaces: Should contains interface_file with IP-addr' do
|
||||
rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}")
|
||||
should rv.with_content(/IPADDR=1.2.3.4/)
|
||||
should rv.with_content(/NETMASK=255.255.0.0/)
|
||||
end
|
||||
|
||||
end
|
|
@ -1,86 +0,0 @@
|
|||
# require 'puppet'
|
||||
# require 'rspec'
|
||||
require 'rspec-puppet'
|
||||
require 'spec_helper'
|
||||
require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals'
|
||||
|
||||
# Ubintu, static
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'eth4' }
|
||||
let(:params) { {
|
||||
:ipaddr => ['1.1.1.1/16','2.2.2.2/25','3.3.3.3/26']
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'Debian',
|
||||
:operatingsystem => 'Ubuntu',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file) { '/etc/network/interfaces.d/ifcfg-eth4' }
|
||||
|
||||
it "Should contain interface_file" do
|
||||
should contain_file('/etc/network/interfaces').with_content(/\*/)
|
||||
end
|
||||
|
||||
it 'Should contain interface_file /etc/network/interfaces.d/ifcfg-eth4' do
|
||||
rv = contain_file("#{interface_file}")
|
||||
should rv.with_content(/auto\s+#{title}/)
|
||||
should rv.with_content(/iface\s+#{title}\s+inet\s+static/)
|
||||
should rv.with_content(/address\s+1.1.1.1/)
|
||||
end
|
||||
|
||||
it 'Should contain main ipaddr' do
|
||||
rv = contain_file("#{interface_file}")
|
||||
should rv.with_content(/address\s+1.1.1.1/)
|
||||
should rv.with_content(/netmask\s+255.255.0.0/)
|
||||
end
|
||||
|
||||
it 'Should contains post-up directives for apply IP aliases' do
|
||||
rv = contain_file("#{interface_file}")
|
||||
params[:ipaddr][1..-1].each do |addr|
|
||||
should rv.with_content(/post-up\s+ip\s+addr\s+add\s+#{addr}\s+dev\s+#{title}/)
|
||||
should rv.with_content(/pre-down\s+ip\s+addr\s+del\s+#{addr}\s+dev\s+#{title}/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Centos, static
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'eth4' }
|
||||
let(:params) { {
|
||||
:ipaddr => ['1.1.1.1/16','2.2.2.2/25','3.3.3.3/26']
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystem => 'Centos',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file) { '/etc/sysconfig/network-scripts/ifcfg-eth4' }
|
||||
let(:interface_up_file) { '/etc/sysconfig/network-scripts/interface-up-script-eth4' }
|
||||
|
||||
it 'Should contain interface_file /etc/sysconfig/network-scripts/ifcfg-eth4' do
|
||||
rv = contain_file("#{interface_file}")
|
||||
should rv.with_content(/DEVICE=#{title}/)
|
||||
should rv.with_content(/BOOTPROTO=none/)
|
||||
should rv.with_content(/ONBOOT=yes/)
|
||||
end
|
||||
|
||||
it 'Should contains common ifup script file /sbin/ifup-local' do
|
||||
should contain_file("/sbin/ifup-local")
|
||||
end
|
||||
|
||||
it 'Should contain main ipaddr' do
|
||||
rv = contain_file("#{interface_file}")
|
||||
should rv.with_content(/IPADDR=1.1.1.1/)
|
||||
should rv.with_content(/NETMASK=255.255.0.0/)
|
||||
end
|
||||
|
||||
it 'Should contains post-up directives for apply IP aliases' do
|
||||
rv = contain_file("#{interface_up_file}")
|
||||
params[:ipaddr][1..-1].each do |addr|
|
||||
should rv.with_content(/ip\s+addr\s+add\s+#{addr}\s+dev\s+#{title}/)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -1,69 +0,0 @@
|
|||
# require 'puppet'
|
||||
# require 'rspec'
|
||||
require 'rspec-puppet'
|
||||
require 'spec_helper'
|
||||
require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals'
|
||||
|
||||
# Ubintu, static
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'eth4' }
|
||||
let(:params) { {
|
||||
:ipaddr => '1.2.3.4/24',
|
||||
:ethtool => {
|
||||
'-K' => 'gso off gro off',
|
||||
'--set-channels' => 'rx 1 tx 2 other 3'
|
||||
}
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'Debian',
|
||||
:operatingsystem => 'Ubuntu',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file) { '/etc/network/interfaces.d/ifcfg-eth4' }
|
||||
|
||||
it "Should contains interface_file" do
|
||||
should contain_file('/etc/network/interfaces').with_content(/\*/)
|
||||
end
|
||||
|
||||
it 'Should contains post-up directives' do
|
||||
rv = contain_file("#{interface_file}")
|
||||
params[:ethtool].each do |k, v|
|
||||
# "--#{k}"" -- workaround for rspec-pupppet bug.
|
||||
should rv.with_content(/post-up\s+ethtool\s+--#{k}\s+#{title}\s+#{v}/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Centos, static
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'eth4' }
|
||||
let(:params) { {
|
||||
:ipaddr => '1.2.3.4/24',
|
||||
:ethtool => {
|
||||
'-K' => 'gso off gro off',
|
||||
'--set-channels' => 'rx 1 tx 2 other 3'
|
||||
}
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystem => 'Centos',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file) { '/etc/sysconfig/network-scripts/ifcfg-eth4' }
|
||||
let(:interface_up_file) { '/etc/sysconfig/network-scripts/interface-up-script-eth4' }
|
||||
|
||||
it 'Should contains common ifup script file /sbin/ifup-local' do
|
||||
should contain_file("/sbin/ifup-local")
|
||||
end
|
||||
|
||||
it 'Should contain interface post-up script' do
|
||||
rv = contain_file("#{interface_up_file}")
|
||||
params[:ethtool].each do |k, v|
|
||||
# "--#{k}"" -- workaround for rspec-pupppet bug.
|
||||
should rv.with_content(/ethtool\s+--#{k}\s+#{title}\s+#{v}/)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -1,58 +0,0 @@
|
|||
# require 'puppet'
|
||||
# require 'rspec'
|
||||
require 'rspec-puppet'
|
||||
require 'spec_helper'
|
||||
require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals'
|
||||
|
||||
# Ubintu, static
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'eth4' }
|
||||
let(:params) { {
|
||||
:ipaddr => '1.2.3.4/24',
|
||||
:macaddr => 'AA:BB:CC:33:22:11'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'Debian',
|
||||
:operatingsystem => 'Ubuntu',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file) { '/etc/network/interfaces.d/ifcfg-eth4' }
|
||||
|
||||
it "Should contain interface_file" do
|
||||
should contain_file('/etc/network/interfaces').with_content(/\*/)
|
||||
end
|
||||
|
||||
it 'Should contain interface_file /etc/network/interfaces.d/ifcfg-eth4' do
|
||||
rv = contain_file("#{interface_file}")
|
||||
should rv.with_content(/hwaddress\s+ether\s+#{params[:macaddr].downcase()}/)
|
||||
should rv.with_content(/address\s+1.2.3.4/)
|
||||
should rv.with_content(/auto\s+#{title}/)
|
||||
should rv.with_content(/iface\s+#{title}/)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Centos, static
|
||||
describe 'l23network::l3::ifconfig', :type => :define do
|
||||
let(:module_path) { '../' }
|
||||
let(:title) { 'eth4' }
|
||||
let(:params) { {
|
||||
:ipaddr => '1.2.3.4/24',
|
||||
:macaddr => 'AA:BB:CC:33:22:11'
|
||||
} }
|
||||
let(:facts) { {
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystem => 'Centos',
|
||||
:kernel => 'Linux'
|
||||
} }
|
||||
let(:interface_file) { '/etc/sysconfig/network-scripts/ifcfg-eth4' }
|
||||
|
||||
it 'Should contain interface_file /etc/sysconfig/network-scripts/ifcfg-eth4' do
|
||||
rv = contain_file("#{interface_file}")
|
||||
should rv.with_content(/MACADDR=#{params[:macaddr].upcase()}/)
|
||||
should rv.with_content(/IPADDR=1.2.3.4/)
|
||||
should rv.with_content(/DEVICE=#{title}/)
|
||||
end
|
||||
|
||||
end
|
|
@ -1,73 +0,0 @@
|
|||
# require 'puppet'
|
||||
# require 'rspec'
|
||||
# require 'rspec-puppet'
|
||||
require 'spec_helper'
|
||||
require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals'
|
||||
|
||||
describe 'ethtool_convert_hash' do
|
||||
let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
|
||||
|
||||
it 'should exist' do
|
||||
expect(Puppet::Parser::Functions.function('ethtool_convert_hash')).to eq 'function_ethtool_convert_hash'
|
||||
end
|
||||
|
||||
it 'should throw an error on invalid arguments number #1' do
|
||||
expect {
|
||||
scope.function_ethtool_convert_hash([])
|
||||
}.to raise_error(Puppet::ParseError)
|
||||
end
|
||||
|
||||
it 'should throw an error on invalid arguments number #2' do
|
||||
expect {
|
||||
scope.function_ethtool_convert_hash([{},{},{}])
|
||||
}.to raise_error(Puppet::ParseError)
|
||||
end
|
||||
|
||||
it 'should throw an error on invalid argument type' do
|
||||
expect {
|
||||
scope.function_ethtool_convert_hash(['qweqwe'])
|
||||
}.to raise_error(Puppet::ParseError)
|
||||
end
|
||||
|
||||
it 'should return hash with two sort of options' do
|
||||
rv = scope.function_ethtool_convert_hash([{
|
||||
:K => [
|
||||
'gso off',
|
||||
'gro off'
|
||||
],
|
||||
:"set-channels" => [
|
||||
'rx 1',
|
||||
'tx 2',
|
||||
'other 3',
|
||||
]
|
||||
}])
|
||||
expect(rv).to eq({
|
||||
'-K' => 'gso off gro off',
|
||||
'--set-channels' => 'rx 1 tx 2 other 3'
|
||||
})
|
||||
end
|
||||
|
||||
it 'should return hash with three sort of options with different case' do
|
||||
rv = scope.function_ethtool_convert_hash([{
|
||||
:s => [
|
||||
'xxx off',
|
||||
'yyy off'
|
||||
],
|
||||
:K => [
|
||||
'gso off',
|
||||
'gro off'
|
||||
],
|
||||
:"set-channels" => [
|
||||
'rx 1',
|
||||
'tx 2',
|
||||
'other 3',
|
||||
]
|
||||
}])
|
||||
expect(rv).to eq({
|
||||
'-s' => 'xxx off yyy off',
|
||||
'-K' => 'gso off gro off',
|
||||
'--set-channels' => 'rx 1 tx 2 other 3'
|
||||
})
|
||||
|
||||
end
|
||||
end
|
|
@ -1,189 +0,0 @@
|
|||
# require 'puppet'
|
||||
# require 'rspec'
|
||||
# require 'rspec-puppet'
|
||||
require 'spec_helper'
|
||||
require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals'
|
||||
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_concat(['xxx'])
|
||||
# }.should(raise_error(Puppet::ParseError))
|
||||
# end
|
||||
|
||||
end
|
||||
|
||||
# vim: set ts=2 sw=2 et :
|
|
@ -1,115 +0,0 @@
|
|||
# require 'puppet'
|
||||
# require 'rspec'
|
||||
# require 'rspec-puppet'
|
||||
require 'spec_helper'
|
||||
require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals'
|
||||
|
||||
describe 'get_hash_with_defaults_and_deprecations' do
|
||||
let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
|
||||
|
||||
it 'should exist' do
|
||||
expect(Puppet::Parser::Functions.function('get_hash_with_defaults_and_deprecations')).to eq 'function_get_hash_with_defaults_and_deprecations'
|
||||
end
|
||||
|
||||
it 'should throw an error on invalid arguments number #1' do
|
||||
expect {
|
||||
scope.function_get_hash_with_defaults_and_deprecations([])
|
||||
}.to raise_error(Puppet::ParseError)
|
||||
end
|
||||
|
||||
it 'should throw an error on invalid arguments number #2' do
|
||||
expect {
|
||||
scope.function_get_hash_with_defaults_and_deprecations([{},{}])
|
||||
}.to raise_error(Puppet::ParseError)
|
||||
end
|
||||
|
||||
it 'should throw an error on invalid arguments number #3' do
|
||||
expect {
|
||||
scope.function_get_hash_with_defaults_and_deprecations([{},{},{},{}])
|
||||
}.to raise_error(Puppet::ParseError)
|
||||
end
|
||||
|
||||
it 'should throw an error on invalid argument type' do
|
||||
expect {
|
||||
scope.function_get_hash_with_defaults_and_deprecations(['qweqwe'])
|
||||
}.to raise_error(Puppet::ParseError)
|
||||
end
|
||||
|
||||
it 'should return hash with sum of two hashes' do
|
||||
rv = scope.function_get_hash_with_defaults_and_deprecations([{
|
||||
'aaa' => 1,
|
||||
'bbb' => 2,
|
||||
}, {
|
||||
'ccc' => 3,
|
||||
'ddd' => 4,
|
||||
}, {}])
|
||||
expect(rv).to eq({
|
||||
'aaa' => 1,
|
||||
'bbb' => 2,
|
||||
'ccc' => 3,
|
||||
'ddd' => 4,
|
||||
})
|
||||
end
|
||||
|
||||
it 'should return hash with sum of two hashes, add defaults if need' do
|
||||
rv = scope.function_get_hash_with_defaults_and_deprecations([{
|
||||
'aaa' => 1,
|
||||
'bbb' => 2,
|
||||
}, {
|
||||
'bbb' => -1,
|
||||
'ccc' => 3,
|
||||
'ddd' => 4,
|
||||
}, {}])
|
||||
expect(rv).to eq({
|
||||
'aaa' => 1,
|
||||
'bbb' => 2,
|
||||
'ccc' => 3,
|
||||
'ddd' => 4,
|
||||
})
|
||||
end
|
||||
|
||||
it 'should return hash with sum of three hashes' do
|
||||
rv = scope.function_get_hash_with_defaults_and_deprecations([{
|
||||
'aaa' => 1,
|
||||
'bbb' => 2,
|
||||
}, {
|
||||
'bbb' => -1,
|
||||
'ccc' => 3,
|
||||
'ddd' => 4,
|
||||
}, {
|
||||
'eee' => 5,
|
||||
}])
|
||||
expect(rv).to eq({
|
||||
'aaa' => 1,
|
||||
'bbb' => 2,
|
||||
'ccc' => 3,
|
||||
'ddd' => 4,
|
||||
'eee' => 5,
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
# it 'should return hash with three sort of options with different case' do
|
||||
# rv = scope.function_get_hash_with_defaults_and_deprecations([{
|
||||
# :s => [
|
||||
# 'xxx off',
|
||||
# 'yyy off'
|
||||
# ],
|
||||
# :K => [
|
||||
# 'gso off',
|
||||
# 'gro off'
|
||||
# ],
|
||||
# :"set-channels" => [
|
||||
# 'rx 1',
|
||||
# 'tx 2',
|
||||
# 'other 3',
|
||||
# ]
|
||||
# }])
|
||||
# expect(rv).to eq({
|
||||
# '-s' => 'xxx off yyy off',
|
||||
# '-K' => 'gso off gro off',
|
||||
# '--set-channels' => 'rx 1 tx 2 other 3'
|
||||
# })
|
||||
|
||||
# end
|
||||
end
|
|
@ -1,6 +0,0 @@
|
|||
<%- if @actual_bond_properties['mode'].to_s != 'undef' -%>
|
||||
slaves none
|
||||
<%- @actual_bond_properties.each do |key, val| -%>
|
||||
bond-<%= key.tr('_','-') %> <%= val %>
|
||||
<%- end -%>
|
||||
<%- end -%>
|
|
@ -1,4 +0,0 @@
|
|||
<%- if @actual_bond_properties['mode'].to_s != 'undef' -%>
|
||||
BONDING_OPTS="mode=<%= @bond_modes[@actual_bond_properties['mode'].to_i] -%>
|
||||
<%- @actual_bond_properties.select{|k,v| k!='mode'}.each do |key, val| -%> <%= key %>=<%= val %><%- end -%>"
|
||||
<% end %>
|
|
@ -1,10 +0,0 @@
|
|||
auto <%= @interface %>
|
||||
iface <%= @interface %> inet manual
|
||||
bond-master <%= @bond_master %>
|
||||
<% if @macaddr -%>
|
||||
hwaddress ether <%= @macaddr.downcase %>
|
||||
<% end -%>
|
||||
<% if @mtu -%>
|
||||
mtu <%= @mtu %>
|
||||
<% end -%>
|
||||
<%= scope.function_template(['l23network/ethtool_Debian.erb']) %>
|
|
@ -1,12 +0,0 @@
|
|||
auto <%= @interface %>
|
||||
iface <%= @interface %> inet dhcp
|
||||
<% if @macaddr -%>
|
||||
hwaddress ether <%= @macaddr.downcase %>
|
||||
<% end -%>
|
||||
<% if @dhcp_hostname %>hostname <%= @dhcp_hostname %><% end %>
|
||||
<% if @vlan_mode %>vlan_raw_device <%= @vlan_dev %><% end %>
|
||||
<% if @mtu -%>
|
||||
mtu <%= @mtu %>
|
||||
<% end -%>
|
||||
<%= scope.function_template(['l23network/bonding_Debian.erb']) %>
|
||||
<%= scope.function_template(['l23network/ethtool_Debian.erb']) %>
|
|
@ -1,13 +0,0 @@
|
|||
auto <%= @interface %>
|
||||
iface <%= @interface %> inet manual
|
||||
<% if @macaddr -%>
|
||||
hwaddress ether <%= @macaddr.downcase %>
|
||||
<% end -%>
|
||||
<% if @mtu -%>
|
||||
mtu <%= @mtu %>
|
||||
<% end -%>
|
||||
<% if @vlan_mode %>vlan_raw_device <%= @vlan_dev %><% end %>
|
||||
up ip l set <%= @interface %> up
|
||||
down ip l set <%= @interface %> down
|
||||
<%= scope.function_template(['l23network/bonding_Debian.erb']) %>
|
||||
<%= scope.function_template(['l23network/ethtool_Debian.erb']) %>
|
|
@ -1,24 +0,0 @@
|
|||
auto <%= @interface %>
|
||||
iface <%= @interface %> inet static
|
||||
<% if @macaddr -%>
|
||||
hwaddress ether <%= @macaddr.downcase %>
|
||||
<% end -%>
|
||||
<% if @mtu -%>
|
||||
mtu <%= @mtu %>
|
||||
<% end -%>
|
||||
<% if @vlan_mode %>vlan_raw_device <%= @vlan_dev %><% end %>
|
||||
address <%= @effective_ipaddr %>
|
||||
netmask <%= @effective_netmask %>
|
||||
<% if @def_gateway %>gateway <%= @def_gateway %><% end %>
|
||||
<% if @dns_nameservers_1 or @dns_nameservers_2 %>dns-nameservers <% if @dns_nameservers_1 %><%= @dns_nameservers_1 %><% end %> <% if @dns_nameservers_2 %><%= @dns_nameservers_2 %><% end %><% end %>
|
||||
<% if @dns_search_string %>dns-search <%= @dns_search_string %><% end %>
|
||||
<% if @dns_domain_string %>dns-domain <%= @dns_domain_string %><% end %>
|
||||
<%- if @other_nets -%>
|
||||
<%= scope.function_template(['l23network/ip_route_Debian.erb']) %>
|
||||
<%- end -%>
|
||||
<%- if @ipaddr_aliases -%><%- @ipaddr_aliases.each do |addr| -%>
|
||||
post-up ip addr add <%= addr %> dev <%= @interface %>
|
||||
pre-down ip addr del <%= addr %> dev <%= @interface %>
|
||||
<%- end -%><%- end -%>
|
||||
<%= scope.function_template(['l23network/bonding_Debian.erb']) %>
|
||||
<%= scope.function_template(['l23network/ethtool_Debian.erb']) %>
|
|
@ -1,12 +0,0 @@
|
|||
DEVICE=<%= @interface %>
|
||||
BOOTPROTO=none
|
||||
ONBOOT=yes
|
||||
USERCTL=no
|
||||
MASTER=<%= @bond_master %>
|
||||
SLAVE=yes
|
||||
<% if @macaddr -%>
|
||||
MACADDR=<%= @macaddr.upcase %>
|
||||
<% end -%>
|
||||
<% if @mtu -%>
|
||||
MTU=<%= @mtu %>
|
||||
<% end -%>
|
|
@ -1,24 +0,0 @@
|
|||
DEVICE=<%= @interface %>
|
||||
BOOTPROTO=dhcp
|
||||
ONBOOT=yes
|
||||
USERCTL=no
|
||||
<% if @dhcp_hostname -%>
|
||||
DHCP_HOSTNAME=<%= @dhcp_hostname %>
|
||||
<% end -%>
|
||||
<% if @vlan_mode -%>
|
||||
VLAN=yes
|
||||
<% end -%>
|
||||
<% if @vlan_mode == 'vlan' -%>
|
||||
VLAN_NAME_TYPE=VLAN_PLUS_VID_NO_PAD
|
||||
PHYSDEV=<%= @vlan_dev %>
|
||||
<% end -%>
|
||||
<% if @mtu -%>
|
||||
MTU=<%= @mtu %>
|
||||
<% end -%>
|
||||
<% if @macaddr -%>
|
||||
MACADDR=<%= @macaddr.upcase %>
|
||||
<% end -%>
|
||||
<% if @mtu -%>
|
||||
MTU=<%= @mtu %>
|
||||
<% end -%>
|
||||
<%= scope.function_template(['l23network/bonding_RedHat.erb']) %>
|
|
@ -1,18 +0,0 @@
|
|||
DEVICE=<%= @interface %>
|
||||
BOOTPROTO=none
|
||||
ONBOOT=yes
|
||||
USERCTL=no
|
||||
<% if @vlan_mode -%>
|
||||
VLAN=yes
|
||||
<% end -%>
|
||||
<% if @vlan_mode == 'vlan' -%>
|
||||
VLAN_NAME_TYPE=VLAN_PLUS_VID_NO_PAD
|
||||
PHYSDEV=<%= @vlan_dev %>
|
||||
<% end -%>
|
||||
<% if @mtu -%>
|
||||
MTU=<%= @mtu %>
|
||||
<% end -%>
|
||||
<% if @macaddr -%>
|
||||
MACADDR=<%= @macaddr.upcase %>
|
||||
<% end -%>
|
||||
<%= scope.function_template(['l23network/bonding_RedHat.erb']) %>
|
|
@ -1,32 +0,0 @@
|
|||
DEVICE=<%= @interface %>
|
||||
IPADDR=<%= @effective_ipaddr %>
|
||||
NETMASK=<%= @effective_netmask %>
|
||||
BOOTPROTO=none
|
||||
ONBOOT=yes
|
||||
USERCTL=no
|
||||
<% if @macaddr -%>
|
||||
MACADDR=<%= @macaddr.upcase %>
|
||||
<% end -%>
|
||||
<% if @vlan_mode -%>
|
||||
VLAN=yes
|
||||
<% end -%>
|
||||
<% if @vlan_mode == 'vlan' -%>
|
||||
VLAN_NAME_TYPE=VLAN_PLUS_VID_NO_PAD
|
||||
PHYSDEV=<%= @vlan_dev %>
|
||||
<% end -%>
|
||||
<% if @def_gateway -%>
|
||||
GATEWAY=<%= @def_gateway %>
|
||||
<% end -%>
|
||||
<% if @dns_nameservers_1 -%>
|
||||
DNS1=<%= @dns_nameservers_1 %>
|
||||
<% end -%>
|
||||
<% if @dns_nameservers_2 -%>
|
||||
DNS2=<%= @dns_nameservers_2 %>
|
||||
<% end -%>
|
||||
<% if @dns_search_string -%>
|
||||
SEARCH=<%= @dns_search_string %>
|
||||
<% end -%>
|
||||
<% if @mtu -%>
|
||||
MTU=<%= @mtu %>
|
||||
<% end -%>
|
||||
<%= scope.function_template(['l23network/bonding_RedHat.erb']) %>
|
|
@ -1,6 +1,6 @@
|
|||
Puppet::Type.type(:l2_nsx_bridge).provide(
|
||||
:ovs,
|
||||
:parent => Puppet::Type.type(:l2_ovs_bridge).provider(:ovs)
|
||||
:parent => Puppet::Type.type(:l2_bridge).provider(:ovs)
|
||||
) do
|
||||
optional_commands :vsctl => "/usr/bin/ovs-vsctl"
|
||||
|
||||
|
|
Loading…
Reference in New Issue