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:
Sergey Vasilenko 2014-12-17 19:22:24 +03:00
parent 879910023c
commit f83970f017
86 changed files with 4949 additions and 3486 deletions

View File

@ -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

View File

@ -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

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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

View File

@ -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

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -39,3 +39,4 @@ Puppet::Type.newtype(:cfg) do
end
end
end
# vim: set ts=2 sw=2 et :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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

View File

@ -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 :

View File

@ -1,3 +1,4 @@
# xxx
class l23network::examples::adv_net_config__bond_lnx (
$fuel_settings,
) {

View File

@ -1,3 +1,4 @@
# xxx
class l23network::examples::adv_net_config__bond_ovs (
$fuel_settings,
) {

View File

@ -1,3 +1,4 @@
# xxx
class l23network::examples::bond_lnx (
$bond = $name,
$interfaces = ['eth4','eth5'],

View File

@ -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}

View File

@ -1,6 +1,8 @@
# manage /etc/hosts
#
class l23network::hosts_file (
$nodes,
$hosts_file = "/etc/hosts"
$hosts_file = '/etc/hosts'
) {
#Move original hosts file

View 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': }
}
#
###

View File

@ -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': }
}

View File

@ -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<||>
}
}

View File

@ -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]
}
}
###

View File

@ -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<||>
}
}

View File

@ -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': }
}

View File

@ -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 :

View File

@ -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 :

View File

@ -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',
}
}

View File

@ -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,
}
}

View File

@ -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}")
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
###

View File

@ -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
###

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 :

View File

@ -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

View File

@ -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 -%>

View File

@ -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 %>

View File

@ -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']) %>

View File

@ -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']) %>

View File

@ -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']) %>

View File

@ -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']) %>

View File

@ -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 -%>

View File

@ -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']) %>

View File

@ -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']) %>

View File

@ -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']) %>

View File

@ -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"