Merge "Lnx2Lnx patchcord implementation for ubuntu"
This commit is contained in:
commit
b9f8c28f0e
@ -5,6 +5,7 @@ class Puppet::Provider::InterfaceToolset < Puppet::Provider
|
||||
|
||||
def self.iproute(*cmd)
|
||||
actual_cmd = ['ip'] + Array(*cmd)
|
||||
debug("iproute: run the command #{actual_cmd.join(' ')}")
|
||||
rv = []
|
||||
IO.popen(actual_cmd.join(' ') + ' 2>&1') do |ff|
|
||||
rv = ff.readlines().map{|l| l.chomp()}
|
||||
@ -29,6 +30,33 @@ class Puppet::Provider::InterfaceToolset < Puppet::Provider
|
||||
return rv
|
||||
end
|
||||
|
||||
def self.brctl(*cmd)
|
||||
actual_cmd = ['brctl'] + Array(*cmd)
|
||||
rv = []
|
||||
IO.popen(actual_cmd.join(' ') + ' 2>&1') do |ff|
|
||||
rv = ff.readlines().map{|l| l.chomp()}
|
||||
ff.close
|
||||
if 0 != $?.exitstatus
|
||||
rv = nil
|
||||
end
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
def self.ethtool(*cmd)
|
||||
actual_cmd = ['ethtool'] + Array(*cmd)
|
||||
rv = []
|
||||
debug(actual_cmd.join(' ') + ' 2>&1')
|
||||
IO.popen(actual_cmd.join(' ') + ' 2>&1') do |ff|
|
||||
rv = ff.readlines().map{|l| l.chomp()}
|
||||
ff.close
|
||||
if 0 != $?.exitstatus and 94 != $?.exitstatus # 94 is a 'no stats available'. it's a not error.
|
||||
rv = nil
|
||||
end
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def self.iface_exist?(iface)
|
||||
@ -71,6 +99,21 @@ class Puppet::Provider::InterfaceToolset < Puppet::Provider
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
def self.get_iface_peer_index(iface)
|
||||
# returns:
|
||||
# N -- ifindex of peer interface
|
||||
# nil -- interface in not an veth pair jack
|
||||
cmd = ['-S', iface]
|
||||
begin
|
||||
rv = ethtool(cmd)
|
||||
rescue Exception => e
|
||||
debug("Non-fatal-Error: Can't run ethtool for interface '#{iface}': #{e.message}")
|
||||
return nil
|
||||
end
|
||||
rv = rv.select{|l| l =~ /\s*peer_ifindex\:\s+\d+/}[0]
|
||||
(rv.nil? ? nil : rv.split(':')[-1].strip.to_i)
|
||||
end
|
||||
|
||||
def self.get_iface_state(iface)
|
||||
# returns:
|
||||
# true -- interface in UP state
|
||||
|
@ -78,6 +78,11 @@ class Puppet::Provider::L23_stored_config_ubuntu < Puppet::Provider::L23_stored_
|
||||
:detect_re => /(post-)?up\s+sleep\s+(\d+)/,
|
||||
:detect_shift => 2,
|
||||
},
|
||||
:jacks => {
|
||||
# pre-up ip link add p_33470efd-0 type veth peer name p_33470efd-1
|
||||
:detect_re => /pre-up\s+ip\s+link\s+add\s+([\w\-]+)\s+type\s+veth\s+peer\s+name\s+([\w\-]+)/,
|
||||
:detect_shift => 1,
|
||||
},
|
||||
}
|
||||
end
|
||||
def collected_properties
|
||||
@ -200,15 +205,18 @@ class Puppet::Provider::L23_stored_config_ubuntu < Puppet::Provider::L23_stored_
|
||||
# # todo(sv): Make more powerful methodology for recognizind Bridges.
|
||||
# hash['if_type'] = :bridge
|
||||
# end
|
||||
when /bridge-ports/
|
||||
when /bridge[-_]ports/
|
||||
hash['if_type'] = :bridge
|
||||
hash[key] = val
|
||||
when /bond-(slaves|mode)/
|
||||
when /bond[-_](slaves|mode)/
|
||||
hash['if_type'] = :bond
|
||||
hash[key] = val
|
||||
else
|
||||
hash[key] = val
|
||||
end
|
||||
if val =~ /\s+type\s+veth\s+/
|
||||
hash['if_type'] = :patch
|
||||
end
|
||||
else
|
||||
raise Puppet::Error, %{#{filename} is malformed; "#{line}" did not match "#{pair_regex.to_s}"}
|
||||
end
|
||||
@ -382,6 +390,10 @@ class Puppet::Provider::L23_stored_config_ubuntu < Puppet::Provider::L23_stored_
|
||||
return rv
|
||||
end
|
||||
|
||||
def self.mangle__jacks(data)
|
||||
[data[0][0], data[0][1]]
|
||||
end
|
||||
|
||||
###
|
||||
# Hash to file
|
||||
|
||||
@ -420,7 +432,7 @@ class Puppet::Provider::L23_stored_config_ubuntu < Puppet::Provider::L23_stored_
|
||||
#add to content unmangled collected-properties
|
||||
collected_properties.keys.each do |type_name|
|
||||
data = provider.send(type_name)
|
||||
if ((!data.nil? or !data.empty?) and data.to_s != 'absent')
|
||||
if ! ['', 'absent'].include? data.to_s
|
||||
mangle_method_name="unmangle__#{type_name}"
|
||||
if self.respond_to?(mangle_method_name)
|
||||
rv = self.send(mangle_method_name, provider, data)
|
||||
@ -556,5 +568,12 @@ class Puppet::Provider::L23_stored_config_ubuntu < Puppet::Provider::L23_stored_
|
||||
return rv
|
||||
end
|
||||
|
||||
def self.unmangle__jacks(provider, data)
|
||||
rv = []
|
||||
rv << "pre-up ip link add #{data[0]} type veth peer name #{data[1]}"
|
||||
rv << "post-up ip link set up dev #{data[1]}"
|
||||
rv << "post-down ip link del #{data[0]}"
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
||||
|
@ -60,11 +60,17 @@ class Puppet::Provider::L2_base < Puppet::Provider::InterfaceToolset
|
||||
:port_type => [],
|
||||
:onboot => self.get_iface_state(if_name),
|
||||
:ethtool => nil,
|
||||
:peer_ifindex => nil,
|
||||
:ifindex => File.open("#{if_dir}/ifindex").read.chomp.to_i,
|
||||
: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"
|
||||
peer_ifindex = self.get_iface_peer_index(if_name)
|
||||
if !peer_ifindex.nil?
|
||||
port[if_name][:port_type] << 'jack' << 'unremovable'
|
||||
port[if_name][:peer_ifindex] = peer_ifindex
|
||||
elsif 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'
|
||||
@ -365,7 +371,7 @@ class Puppet::Provider::L2_base < Puppet::Provider::InterfaceToolset
|
||||
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|
|
||||
self.brctl(['show']).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),
|
||||
@ -421,7 +427,7 @@ class Puppet::Provider::L2_base < Puppet::Provider::InterfaceToolset
|
||||
# (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\.\-]+/)}
|
||||
brctl_show = self.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 {}
|
||||
|
@ -6,8 +6,7 @@ require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/lnx_ba
|
||||
|
||||
Puppet::Type.type(:l2_bond).provide(:lnx, :parent => Puppet::Provider::Lnx_base) do
|
||||
defaultfor :osfamily => :linux
|
||||
commands :ethtool_cmd => 'ethtool',
|
||||
:brctl => 'brctl'
|
||||
commands :ethtool_cmd => 'ethtool'
|
||||
|
||||
|
||||
def self.prefetch(resources)
|
||||
@ -192,7 +191,7 @@ Puppet::Type.type(:l2_bond).provide(:lnx, :parent => Puppet::Provider::Lnx_base)
|
||||
ovs_vsctl(['del-port', br_name, @resource[:bond]])
|
||||
# todo catch exception
|
||||
when :lnx
|
||||
brctl('delif', br_name, @resource[:bond])
|
||||
self.class.brctl(['delif', br_name, @resource[:bond]])
|
||||
# todo catch exception
|
||||
else
|
||||
#pass
|
||||
@ -205,7 +204,7 @@ Puppet::Type.type(:l2_bond).provide(:lnx, :parent => Puppet::Provider::Lnx_base)
|
||||
when :ovs
|
||||
ovs_vsctl(['add-port', @property_flush[:bridge], @resource[:bond]])
|
||||
when :lnx
|
||||
brctl('addif', @property_flush[:bridge], @resource[:bond])
|
||||
self.class.brctl(['addif', @property_flush[:bridge], @resource[:bond]])
|
||||
else
|
||||
#pass
|
||||
end
|
||||
|
@ -8,8 +8,7 @@ require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/lnx_ba
|
||||
|
||||
Puppet::Type.type(:l2_bridge).provide(:lnx, :parent => Puppet::Provider::Lnx_base) do
|
||||
defaultfor :osfamily => :linux
|
||||
commands :brctl => 'brctl',
|
||||
:ethtool_cmd => 'ethtool'
|
||||
commands :ethtool_cmd => 'ethtool'
|
||||
|
||||
def self.instances
|
||||
rv = []
|
||||
@ -37,7 +36,7 @@ Puppet::Type.type(:l2_bridge).provide(:lnx, :parent => Puppet::Provider::Lnx_bas
|
||||
@old_property_hash = {}
|
||||
@property_flush = {}.merge! @resource
|
||||
begin
|
||||
brctl('addbr', @resource[:bridge])
|
||||
self.class.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]
|
||||
@ -48,7 +47,7 @@ Puppet::Type.type(:l2_bridge).provide(:lnx, :parent => Puppet::Provider::Lnx_bas
|
||||
|
||||
def destroy
|
||||
self.class.interface_down(@resource[:bridge])
|
||||
brctl('delbr', @resource[:bridge])
|
||||
self.class.brctl(['delbr', @resource[:bridge]])
|
||||
end
|
||||
|
||||
def flush
|
||||
|
@ -2,8 +2,7 @@ require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/ovs_ba
|
||||
|
||||
Puppet::Type.type(:l2_bridge).provide(:ovs, :parent => Puppet::Provider::Ovs_base) do
|
||||
commands :vsctl => 'ovs-vsctl',
|
||||
:ethtool_cmd => 'ethtool',
|
||||
:brctl => 'brctl'
|
||||
:ethtool_cmd => 'ethtool'
|
||||
|
||||
def self.skip_port_for?(port_props)
|
||||
port_props[:br_type] != 'ovs'
|
||||
|
141
deployment/puppet/l23network/lib/puppet/provider/l2_patch/lnx.rb
Normal file
141
deployment/puppet/l23network/lib/puppet/provider/l2_patch/lnx.rb
Normal file
@ -0,0 +1,141 @@
|
||||
require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/lnx_base')
|
||||
|
||||
Puppet::Type.type(:l2_patch).provide(:lnx, :parent => Puppet::Provider::Lnx_base) do
|
||||
defaultfor :osfamily => :linux
|
||||
|
||||
|
||||
def self.instances
|
||||
ports = get_lnx_ports()
|
||||
jacks = []
|
||||
ports.each_pair do |if_name, if_props|
|
||||
next unless if_props[:port_type].include? 'jack'
|
||||
jacks << {
|
||||
:name => if_name,
|
||||
:bridge => if_props[:bridge],
|
||||
:ifindex => if_props[:ifindex],
|
||||
:peer_ifindex => if_props[:peer_ifindex],
|
||||
:mtu => if_props[:mtu],
|
||||
:provider => 'lnx'
|
||||
}
|
||||
end
|
||||
|
||||
# search pairs of jacks and make patchcord resources
|
||||
patches = []
|
||||
skip = []
|
||||
mtu = nil
|
||||
jacks.each do |jack|
|
||||
next if skip.include? jack[:name]
|
||||
# process patch between two bridges
|
||||
found_peer = jacks.select{|j| j[:ifindex]==jack[:peer_ifindex]}
|
||||
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]])
|
||||
if _bridges.include? nil
|
||||
_name = "patch__raw__#{_tails[0]}--#{_tails[1]}"
|
||||
else
|
||||
_name = L23network.get_patch_name([jack[:bridge],peer[:bridge]])
|
||||
end
|
||||
props = {
|
||||
:ensure => :present,
|
||||
:name => _name,
|
||||
:bridges => _bridges,
|
||||
:jacks => _tails,
|
||||
:mtu => mtu.to_s,
|
||||
:vlan_ids => ['0','0'], # because veth pairs can't be tagged
|
||||
:provider => 'ovs'
|
||||
}
|
||||
debug("PREFETCH properties for '#{props[:name]}': #{props}")
|
||||
patches << new(props)
|
||||
skip << peer[:name]
|
||||
end
|
||||
return patches
|
||||
end
|
||||
|
||||
def create
|
||||
debug("CREATE resource: #{@resource}")
|
||||
@old_property_hash = {}
|
||||
@property_flush = {}.merge! @resource
|
||||
patch_name = L23network.get_patch_name(@resource[:jacks])
|
||||
begin
|
||||
self.class.iproute(['link', 'add', 'dev', @resource[:jacks][0], 'type', 'veth', 'peer', 'name', @resource[:jacks][1]])
|
||||
rescue
|
||||
# Some time interface may be created by OS init scripts.
|
||||
raise unless self.class.iface_exist?(@resource[:jacks][0]) & self.class.iface_exist?(@resource[:jacks][1])
|
||||
notice("'#{patch_name}' is already created by ghost event.")
|
||||
end
|
||||
# plug-in jacks to bridges
|
||||
_bridges = self.class.get_bridge_list()
|
||||
self.class.get_bridges_order_for_patch(@resource[:bridges]).each_with_index do |br_name, i|
|
||||
_br = _bridges.fetch(br_name, {})
|
||||
#todo: sv: re-design for call method from bridge provider
|
||||
if _br[:br_type].to_s == 'lnx'
|
||||
self.class.iproute(['link', 'set', 'dev', @resource[:jacks][i], 'master', br_name ])
|
||||
elsif _br[:br_type].to_s == 'ovs'
|
||||
fail("lnx2ovs patchcord '#{patch_name}' is not implemented yet, use ovs2lnx for this purpose!")
|
||||
#self.class.ovs_vsctl(['--may-exist', 'add-port', br_name, @resource[:jacks][i]])
|
||||
end
|
||||
end
|
||||
# UP jacks
|
||||
@resource[:jacks].each do |jack_name|
|
||||
self.class.interface_up(jack_name, true)
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
debug("DESTROY resource: #{@resource}")
|
||||
self.class.iproute(['link', 'del', 'dev', @resource[:jacks][0]])
|
||||
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
|
||||
#todo: /sv: make ability of change bridges for RAW patchcords
|
||||
@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 vlan_ids
|
||||
['0', '0']
|
||||
end
|
||||
def vlan_ids=(val)
|
||||
warn("There are no ability for setup VLAN IDs for LNX-patchcords")
|
||||
end
|
||||
|
||||
def mtu
|
||||
'absent'
|
||||
end
|
||||
def mtu=(val)
|
||||
@property_flush[:mtu] = val
|
||||
end
|
||||
|
||||
def jacks
|
||||
@property_hash[:jacks]
|
||||
end
|
||||
def jacks=(val)
|
||||
nil
|
||||
end
|
||||
|
||||
def cross
|
||||
nil
|
||||
end
|
||||
def cross=(val)
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
# vim: set ts=2 sw=2 et :
|
@ -3,8 +3,7 @@ require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/ovs_ba
|
||||
|
||||
Puppet::Type.type(:l2_patch).provide(:ovs, :parent => Puppet::Provider::Ovs_base) do
|
||||
commands :vsctl => 'ovs-vsctl',
|
||||
:ethtool_cmd => 'ethtool',
|
||||
:brctl => 'brctl'
|
||||
:ethtool_cmd => 'ethtool'
|
||||
|
||||
def self.get_instances(big_hash)
|
||||
big_hash.fetch(:port, {})
|
||||
@ -57,7 +56,7 @@ Puppet::Type.type(:l2_patch).provide(:ovs, :parent => Puppet::Provider::Ovs_base
|
||||
peer = found_peer[0]
|
||||
_bridges = [jack[:bridge], peer[:bridge]].sort
|
||||
_tails = ([jack[:bridge], peer[:bridge]] == _bridges ? [jack[:name], peer[:name]] : [peer[:name], jack[:name]])
|
||||
_vlan_ids = [(jack[:vlan_id].to_i or 0), (peer[:vlan_id].to_i or 0)]
|
||||
_vlan_ids = [jack[:vlan_id].to_i, peer[:vlan_id].to_i]
|
||||
end
|
||||
props = {
|
||||
:ensure => :present,
|
||||
@ -95,12 +94,12 @@ Puppet::Type.type(:l2_patch).provide(:ovs, :parent => Puppet::Provider::Ovs_base
|
||||
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)
|
||||
self.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)
|
||||
self.class.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.")
|
||||
@ -138,7 +137,7 @@ debug(cmds)
|
||||
jack = L23network.get_jack_name(@resource[:bridges], 0)
|
||||
# we don't normalize bridge ordering, because OVS bridge always first. by design.
|
||||
if File.symlink?("/sys/class/net/#{@resource[:bridges][1]}/brif/#{jack}")
|
||||
brctl('delif', @resource[:bridges][1], jack)
|
||||
self.class.brctl(['delif', @resource[:bridges][1], jack])
|
||||
end
|
||||
vsctl('del-port', @resource[:bridges][0], jack)
|
||||
else
|
||||
@ -207,6 +206,13 @@ debug(cmds)
|
||||
@property_flush[:vlan_ids] = val
|
||||
end
|
||||
|
||||
def mtu
|
||||
'absent'
|
||||
end
|
||||
def mtu=(val)
|
||||
@property_flush[:mtu] = val
|
||||
end
|
||||
|
||||
def jacks
|
||||
@property_hash[:jacks]
|
||||
end
|
||||
|
@ -3,7 +3,6 @@ require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/lnx_ba
|
||||
Puppet::Type.type(:l2_port).provide(:lnx, :parent => Puppet::Provider::Lnx_base) do
|
||||
defaultfor :osfamily => :linux
|
||||
commands :ethtool_cmd => 'ethtool',
|
||||
:brctl => 'brctl',
|
||||
:pkill => 'pkill'
|
||||
|
||||
|
||||
@ -124,7 +123,7 @@ Puppet::Type.type(:l2_port).provide(:lnx, :parent => Puppet::Provider::Lnx_base)
|
||||
when :ovs
|
||||
self.class.ovs_vsctl(['del-port', br_name, @resource[:interface]])
|
||||
when :lnx
|
||||
brctl('delif', br_name, @resource[:interface])
|
||||
self.class.brctl(['delif', br_name, @resource[:interface]])
|
||||
else
|
||||
#pass
|
||||
end
|
||||
@ -137,7 +136,7 @@ Puppet::Type.type(:l2_port).provide(:lnx, :parent => Puppet::Provider::Lnx_base)
|
||||
self.class.ovs_vsctl(['add-port', @property_flush[:bridge], @resource[:interface]])
|
||||
when :lnx
|
||||
begin
|
||||
brctl('addif', @property_flush[:bridge], @resource[:interface])
|
||||
self.class.brctl(['addif', @property_flush[:bridge], @resource[:interface]])
|
||||
rescue
|
||||
# Sometimes interface may be automatically added to bridge if config file exists before interface creation,
|
||||
# especially vlan interfaces. It appears on CentOS.
|
||||
|
@ -48,6 +48,7 @@ define l23network::l2::patch (
|
||||
$act_bridges = [$bridges[1], $bridges[0]]
|
||||
$act_vlan_ids = undef
|
||||
} else {
|
||||
$lnx2lnx = true
|
||||
$act_bridges = $bridges
|
||||
}
|
||||
|
||||
@ -91,7 +92,36 @@ define l23network::l2::patch (
|
||||
provider => $config_provider
|
||||
}
|
||||
L23_stored_config[$patch_jacks_names[1]] -> L2_patch[$patch_name]
|
||||
} elsif $lnx2lnx {
|
||||
if ! defined(L23_stored_config[$patch_jacks_names[0]]) {
|
||||
l23_stored_config { $patch_jacks_names[0]: }
|
||||
}
|
||||
L23_stored_config <| title == $patch_jacks_names[0] |> {
|
||||
ensure => $ensure,
|
||||
if_type => 'patch',
|
||||
bridge => $act_bridges[0],
|
||||
jacks => $patch_jacks_names,
|
||||
onboot => true,
|
||||
vendor_specific => $vendor_specific,
|
||||
provider => $config_provider
|
||||
}
|
||||
L23_stored_config[$patch_jacks_names[0]] -> L2_patch[$patch_name]
|
||||
|
||||
if ! defined(L23_stored_config[$patch_jacks_names[1]]) {
|
||||
l23_stored_config { $patch_jacks_names[1]: }
|
||||
}
|
||||
L23_stored_config <| title == $patch_jacks_names[1] |> {
|
||||
ensure => $ensure,
|
||||
if_type => 'patch',
|
||||
bridge => $act_bridges[1],
|
||||
jacks => $patch_jacks_names,
|
||||
onboot => true,
|
||||
vendor_specific => $vendor_specific,
|
||||
provider => $config_provider
|
||||
}
|
||||
L23_stored_config[$patch_jacks_names[1]] -> L2_patch[$patch_name]
|
||||
} else {
|
||||
# ovs2lnx patch
|
||||
if ! defined(L23_stored_config[$patch_jacks_names[0]]) {
|
||||
# we use only one (first) patch jack name here and later,
|
||||
# because a both jacks for patch are created by
|
||||
|
@ -0,0 +1,4 @@
|
||||
auto br1
|
||||
iface br1 inet static
|
||||
bridge_ports p_33470efd-0
|
||||
address 192.168.88.2/24
|
@ -0,0 +1,4 @@
|
||||
auto br2
|
||||
iface br2 inet static
|
||||
bridge_ports p_33470efd-1
|
||||
address 192.168.99.2/24
|
@ -0,0 +1,5 @@
|
||||
auto p_33470efd-0
|
||||
iface p_33470efd-0 inet manual
|
||||
pre-up ip link add p_33470efd-0 type veth peer name p_33470efd-1
|
||||
post-up ip link set up dev p_33470efd-1
|
||||
post-down ip link del p_33470efd-0
|
@ -0,0 +1,5 @@
|
||||
auto p_33470efd-1
|
||||
iface p_33470efd-1 inet manual
|
||||
pre-up ip link add p_33470efd-0 type veth peer name p_33470efd-1
|
||||
post-up ip link set up dev p_33470efd-1
|
||||
post-down ip link del p_33470efd-0
|
@ -0,0 +1,173 @@
|
||||
require 'spec_helper'
|
||||
|
||||
resources_map = {
|
||||
:'br1' => {
|
||||
:name => "br1",
|
||||
:onboot => "yes",
|
||||
:method => "static",
|
||||
:if_type => "bridge",
|
||||
:ipaddr => "192.168.88.2/24",
|
||||
:bridge_ports => ['p_33470efd-0'], # in real cases this value doesn't pass directly to stored_config,
|
||||
:provider => "lnx_ubuntu", # but filled in generate() method of type
|
||||
},
|
||||
:'br2' => {
|
||||
:name => "br2",
|
||||
:onboot => "yes",
|
||||
:method => "static",
|
||||
:if_type => "bridge",
|
||||
:ipaddr => "192.168.99.2/24",
|
||||
:bridge_ports => ['p_33470efd-1'], # in real cases this value doesn't pass directly to stored_config,
|
||||
:provider => "lnx_ubuntu", # but filled in generate() method of type
|
||||
},
|
||||
:'p_33470efd-0' => {
|
||||
:name => 'p_33470efd-0',
|
||||
:if_type => 'patch',
|
||||
:bridge => ["br1"],
|
||||
:jacks => ['p_33470efd-0', 'p_33470efd-1'],
|
||||
:provider => "lnx_ubuntu",
|
||||
},
|
||||
:'p_33470efd-1' => {
|
||||
:name => "p_33470efd-1",
|
||||
:if_type => 'patch',
|
||||
:bridge => ["br2"],
|
||||
:jacks => ['p_33470efd-0', 'p_33470efd-1'],
|
||||
:provider => "lnx_ubuntu",
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
# This test is functional continue of .spec/classes/ovs2lnx_patch__spec.rb
|
||||
describe Puppet::Type.type(:l23_stored_config).provider(:lnx_ubuntu) do
|
||||
|
||||
let(:input_data) { resources_map}
|
||||
|
||||
let(:resources) do
|
||||
resources = {}
|
||||
input_data.each do |name, res|
|
||||
resources.store name, Puppet::Type.type(:l23_stored_config).new(res)
|
||||
end
|
||||
return resources
|
||||
end
|
||||
|
||||
let(:providers) do
|
||||
providers = {}
|
||||
resources.each do |name, resource|
|
||||
provider = resource.provider
|
||||
if ENV['SPEC_PUPPET_DEBUG']
|
||||
class << provider
|
||||
def debug(msg)
|
||||
puts msg
|
||||
end
|
||||
end
|
||||
end
|
||||
provider.create
|
||||
providers.store name, provider
|
||||
end
|
||||
return providers
|
||||
end
|
||||
|
||||
before(:each) do
|
||||
puppet_debug_override()
|
||||
end
|
||||
|
||||
def fixture_path
|
||||
File.join(PROJECT_ROOT, 'spec', 'fixtures', 'provider', 'l23_stored_config', 'lnx_ubuntu__lnx2lnx_patch__spec')
|
||||
end
|
||||
|
||||
def fixture_file(file)
|
||||
File.join(fixture_path, file)
|
||||
end
|
||||
|
||||
def fixture_data(file)
|
||||
File.read(fixture_file(file))
|
||||
end
|
||||
|
||||
context "when formating config files" do
|
||||
|
||||
context 'for LNX bridge br1' do
|
||||
subject { providers[:'br1'] }
|
||||
let(:cfg_file) { subject.class.format_file('filepath', [subject]) }
|
||||
it { expect(cfg_file).to match(/auto\s+br1/) }
|
||||
it { expect(cfg_file).to match(/iface\s+br1\s+inet\s+static/) }
|
||||
it { expect(cfg_file).to match(/bridge_ports\s+p_33470efd-0/) }
|
||||
it { expect(cfg_file).to match(/address\s+192.168.88.2\/24/) }
|
||||
it { expect(cfg_file.split(/\n/).reject{|x| x=~/^\s*$/}.length). to eq(4) }
|
||||
end
|
||||
|
||||
context 'for LNX bridge br2' do
|
||||
subject { providers[:'br2'] }
|
||||
let(:cfg_file) { subject.class.format_file('filepath', [subject]) }
|
||||
it { expect(cfg_file).to match(/auto\s+br2/) }
|
||||
it { expect(cfg_file).to match(/iface\s+br2\s+inet\s+static/) }
|
||||
it { expect(cfg_file).to match(/bridge_ports\s+p_33470efd-1/) }
|
||||
it { expect(cfg_file).to match(/address\s+192.168.99.2\/24/) }
|
||||
it { expect(cfg_file.split(/\n/).reject{|x| x=~/^\s*$/}.length). to eq(4) }
|
||||
end
|
||||
|
||||
context 'for lnx2lnx patchcord p_33470efd-0' do
|
||||
subject { providers[:'p_33470efd-0'] }
|
||||
let(:cfg_file) { subject.class.format_file('filepath', [subject]) }
|
||||
it { expect(cfg_file).to match(/auto\s+p_33470efd-0/) }
|
||||
it { expect(cfg_file).to match(/iface\s+p_33470efd-0\s+inet\s+manual/) }
|
||||
it { expect(cfg_file).to match(/pre-up\s+ip\s+link\s+add\s+p_33470efd-0\s+type\s+veth\s+peer\s+name\s+p_33470efd-1/) }
|
||||
it { expect(cfg_file).to match(/post-up\s+ip\s+link\s+set\s+up\s+dev\s+p_33470efd-1/) }
|
||||
it { expect(cfg_file).to match(/post-down\s+ip\s+link\s+del\s+p_33470efd-0/) }
|
||||
it { expect(cfg_file.split(/\n/).reject{|x| x=~/^\s*$/}.length). to eq(5) }
|
||||
end
|
||||
|
||||
context 'for lnx2lnx patchcord p_33470efd-1' do
|
||||
subject { providers[:'p_33470efd-1'] }
|
||||
let(:cfg_file) { subject.class.format_file('filepath', [subject]) }
|
||||
it { expect(cfg_file).to match(/auto\s+p_33470efd-1/) }
|
||||
it { expect(cfg_file).to match(/iface\s+p_33470efd-1\s+inet\s+manual/) }
|
||||
it { expect(cfg_file).to match(/pre-up\s+ip\s+link\s+add\s+p_33470efd-0\s+type\s+veth\s+peer\s+name\s+p_33470efd-1/) }
|
||||
it { expect(cfg_file).to match(/post-up\s+ip\s+link\s+set\s+up\s+dev\s+p_33470efd-1/) }
|
||||
it { expect(cfg_file).to match(/post-down\s+ip\s+link\s+del\s+p_33470efd-0/) }
|
||||
it { expect(cfg_file.split(/\n/).reject{|x| x=~/^\s*$/}.length). to eq(5) }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "when parsing config files" do
|
||||
|
||||
context 'for LNX bridge br1' do
|
||||
let(:res) { subject.class.parse_file('br1', fixture_data('ifcfg-br1'))[0] }
|
||||
it { expect(res[:method]).to eq :static }
|
||||
it { expect(res[:onboot]).to eq true }
|
||||
it { expect(res[:name]).to eq 'br1' }
|
||||
it { expect(res[:bridge_ports]).to eq ['p_33470efd-0'] }
|
||||
it { expect(res[:if_type].to_s).to eq 'bridge' }
|
||||
it { expect(res[:if_provider].to_s).to eq 'lnx' }
|
||||
end
|
||||
|
||||
context 'for LNX bridge br2' do
|
||||
let(:res) { subject.class.parse_file('br2', fixture_data('ifcfg-br2'))[0] }
|
||||
it { expect(res[:method]).to eq :static }
|
||||
it { expect(res[:onboot]).to eq true }
|
||||
it { expect(res[:name]).to eq 'br2' }
|
||||
it { expect(res[:bridge_ports]).to eq ['p_33470efd-1'] }
|
||||
it { expect(res[:if_type].to_s).to eq 'bridge' }
|
||||
it { expect(res[:if_provider].to_s).to eq 'lnx' }
|
||||
end
|
||||
|
||||
context 'for lnx2lnx patchcord p_33470efd-0' do
|
||||
let(:res) { subject.class.parse_file('p_33470efd-0', fixture_data('ifcfg-p_33470efd-0'))[0] }
|
||||
it { expect(res[:method]).to eq :manual }
|
||||
it { expect(res[:onboot]).to eq true }
|
||||
it { expect(res[:name]).to eq 'p_33470efd-0' }
|
||||
it { expect(res[:if_type].to_s).to eq 'patch' }
|
||||
it { expect(res[:if_provider].to_s).to eq 'lnx' }
|
||||
end
|
||||
|
||||
context 'for lnx2lnx patchcord p_33470efd-1' do
|
||||
let(:res) { subject.class.parse_file('p_33470efd-1', fixture_data('ifcfg-p_33470efd-1'))[0] }
|
||||
it { expect(res[:method]).to eq :manual }
|
||||
it { expect(res[:onboot]).to eq true }
|
||||
it { expect(res[:name]).to eq 'p_33470efd-1' }
|
||||
it { expect(res[:if_type].to_s).to eq 'patch' }
|
||||
it { expect(res[:if_provider].to_s).to eq 'lnx' }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
@ -0,0 +1,69 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Puppet::Type.type(:l2_patch).provider(:ovs) do
|
||||
# NOTE! for bridges ['br1', 'br2'] jack names will be ['p_39a440c1-0', 'p_39a440c1-1']
|
||||
|
||||
|
||||
let(:resource_br1) {
|
||||
Puppet::Type.type(:l2_bridge).new(
|
||||
:provider => 'lnx',
|
||||
:name => 'br1',
|
||||
:bridge => 'br1',
|
||||
)
|
||||
}
|
||||
let(:provider_br1) { resource_br1.provider }
|
||||
#let(:instance_br1_ovs) { provider_br1.class.instances }
|
||||
|
||||
let(:resource_patch) {
|
||||
Puppet::Type.type(:l2_patch).new(
|
||||
:provider => 'lnx',
|
||||
:name => 'patch__br1--br2',
|
||||
:bridges => ['br1', 'br2'],
|
||||
:jacks => ['p_39a440c1-0', 'p_39a440c1-1'],
|
||||
:mtu => '9000'
|
||||
)
|
||||
}
|
||||
let(:provider_patch) { resource_patch.provider }
|
||||
#let(:instance_patch_ovs) { provider_patch.class.instances }
|
||||
|
||||
describe "lnx-to-lnx patchcord" do
|
||||
|
||||
let(:resource_br2) {
|
||||
Puppet::Type.type(:l2_bridge).new(
|
||||
:provider => 'lnx',
|
||||
:name => 'br2',
|
||||
:bridge => 'br2',
|
||||
)
|
||||
}
|
||||
let(:provider_br2) { resource_br2.provider }
|
||||
#let(:instance_br2_ovs) { provider_br2.class.instances }
|
||||
|
||||
|
||||
before(:each) do
|
||||
puppet_debug_override()
|
||||
provider_br1.class.stubs(:iproute)
|
||||
provider_br2.class.stubs(:iproute)
|
||||
provider_br1.class.stubs(:brctl).with(['addbr', 'br1']).returns(true)
|
||||
provider_br2.class.stubs(:brctl).with(['addbr', 'br2']).returns(true)
|
||||
provider_patch.class.stubs(:iproute).with([
|
||||
'link', 'add', 'dev', 'p_39a440c1-0', 'type', 'veth', 'peer', 'name', 'p_39a440c1-1'
|
||||
]).returns(true)
|
||||
provider_patch.class.stubs(:get_bridge_list).returns({
|
||||
'br1' => {:br_type => :lnx},
|
||||
'br2' => {:br_type => :lnx},
|
||||
})
|
||||
provider_patch.class.stubs(:iproute).with(['link', 'set', 'dev', 'p_39a440c1-0', 'master', 'br1']).returns(true)
|
||||
provider_patch.class.stubs(:iproute).with(['link', 'set', 'dev', 'p_39a440c1-1', 'master', 'br2']).returns(true)
|
||||
provider_patch.class.stubs(:interface_up).with('p_39a440c1-0', true).returns(true)
|
||||
provider_patch.class.stubs(:interface_up).with('p_39a440c1-1', true).returns(true)
|
||||
end
|
||||
|
||||
it "Just create two bridges and connect it by patchcord" do
|
||||
provider_br1.create
|
||||
provider_br2.create
|
||||
provider_patch.create
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
@ -83,15 +83,16 @@ describe Puppet::Type.type(:l2_patch).provider(:ovs) do
|
||||
provider_br1.class.stubs(:vsctl).with('add-br', 'br1').returns(true)
|
||||
provider_br2.class.stubs(:iproute).with().returns(true)
|
||||
provider_br2.class.stubs(:iproute).with('link', 'set', 'up', 'dev', 'br2').returns(true)
|
||||
provider_br2.class.stubs(:brctl).with('addbr', 'br2').returns(true)
|
||||
provider_patch.class.stubs(:brctl).with('addif', 'br2', 'p_39a440c1-0').returns(true)
|
||||
provider_br2.stubs(:brctl).with(['addbr', 'br2']).returns(true)
|
||||
provider_patch.class.stubs(:get_bridges_order_for_patch).with(['br1','br2']).returns(['br1','br2'])
|
||||
File.stubs(:directory?).with('/sys/class/net/br2/bridge').returns(true)
|
||||
provider_patch.class.stubs(:vsctl).with(
|
||||
'--may-exist', 'add-port', 'br1', 'p_39a440c1-0', '--', 'set', 'Interface', 'p_39a440c1-0', 'type=internal'
|
||||
).returns(true)
|
||||
File.stubs(:directory?).with('/sys/class/net/br2/bridge').returns(true)
|
||||
provider_patch.class.stubs(:get_lnx_port_bridges_pairs).with().returns({})
|
||||
provider_patch.class.stubs(:get_bridges_order_for_patch).with(['br1','br2']).returns(['br1','br2'])
|
||||
provider_patch.stubs(:brctl).with(['addif', 'br2', 'p_39a440c1-0']).returns(true)
|
||||
provider_patch.class.stubs(:iproute).with('link', 'set', 'up', 'dev', 'p_39a440c1-0').returns(true)
|
||||
|
||||
end
|
||||
|
||||
it "Just create two bridges and connect it by patchcord" do
|
||||
@ -100,6 +101,15 @@ describe Puppet::Type.type(:l2_patch).provider(:ovs) do
|
||||
provider_patch.create
|
||||
end
|
||||
|
||||
it "Patch was connected to another bridge" do
|
||||
provider_br1.create
|
||||
provider_br2.create
|
||||
provider_patch.class.stubs(:get_lnx_port_bridges_pairs).with().returns({'p_39a440c1-0'=>{:bridge=>'br-lnx1', :br_type=>:lnx},})
|
||||
provider_patch.stubs(:brctl).with(['delif', 'br-lnx1', 'p_39a440c1-0']).returns(true)
|
||||
provider_patch.stubs(:brctl).with(['addif', 'br2', 'p_39a440c1-0']).returns(true)
|
||||
provider_patch.create
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue
Block a user