Prevent a bond for unrequired re-assembles
* Assemble bond members under bond in UP state
* FIX lost bridge parameter
* FIX lost 'use_carrier' bond property
* waiting for bond UP after slaves added
* additional flush IP addresses from slave while bond assemble
Change-Id: I568d852e65dc5d5c246e11deb0740f4a608f5ecc
Closes-bug: #1658981
Related-bug: #1657750
(cherry picked from commit 6fde41c44a
)
This commit is contained in:
parent
af4d0aa90f
commit
a848384706
|
@ -520,6 +520,11 @@ class Puppet::Provider::L2_base < Puppet::Provider::InterfaceToolset
|
|||
bond[bond_name][:bond_properties][:ad_select] = ad_select
|
||||
end
|
||||
bond[bond_name][:onboot] = !self.get_iface_state(bond_name).nil?
|
||||
bond[bond_name][:bond_properties][:use_carrier] = self.get_sys_class("/sys/class/net/#{bond_name}/bonding/use_carrier")
|
||||
# get bridge, if bond a member an one
|
||||
if self.get_port_bridges_pairs[bond_name]
|
||||
bond[bond_name][:bridge] = self.get_port_bridges_pairs[bond_name][:bridge]
|
||||
end
|
||||
end
|
||||
debug("get_lnx_bonds: LNX bond list #{bond}")
|
||||
return bond
|
||||
|
|
|
@ -29,21 +29,6 @@ Puppet::Type.type(:l2_bond).provide(:lnx, :parent => Puppet::Provider::Lnx_base)
|
|||
: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
|
||||
|
@ -66,34 +51,9 @@ Puppet::Type.type(:l2_bond).provide(:lnx, :parent => Puppet::Provider::Lnx_base)
|
|||
if ! @property_flush.empty?
|
||||
debug("FLUSH properties: #{@property_flush}")
|
||||
bond_prop_dir = "/sys/class/net/#{@resource[:bond]}"
|
||||
runtime_slave_ports = self.class.get_sys_class("#{bond_prop_dir}/bonding/slaves", true)
|
||||
bond_is_up = !self.class.get_iface_state(@resource[:bond]).nil?
|
||||
# FLUSH changed properties
|
||||
if @property_flush.has_key? :slaves
|
||||
runtime_slave_ports = self.class.get_sys_class("/sys/class/net/#{@resource[:bond]}/bonding/slaves", true)
|
||||
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]
|
||||
if !rm_slave_list.empty?
|
||||
debug("Remove '#{rm_slave_list.join(',')}' ports from bond '#{@resource[:bond]}'")
|
||||
rm_slave_list.each do |slave|
|
||||
self.class.interface_down(slave) # need by kernel requirements by design. undocumented :(
|
||||
self.class.set_sys_class("#{bond_prop_dir}/bonding/slaves", "-#{slave}")
|
||||
end
|
||||
end
|
||||
# add interfaces to bond
|
||||
add_slave_list = @property_flush[:slaves] - runtime_slave_ports
|
||||
if !add_slave_list.empty?
|
||||
debug("Add '#{add_slave_list.join(',')}' ports to bond '#{@resource[:bond]}'")
|
||||
add_slave_list.each do |slave|
|
||||
debug("Add interface '#{slave}' to bond '#{@resource[:bond]}'")
|
||||
self.class.interface_down(slave) # need by kernel requirements by design. undocumented :(
|
||||
self.class.set_sys_class("#{bond_prop_dir}/bonding/slaves", "+#{slave}")
|
||||
self.class.interface_up(slave)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if @property_flush.has_key? :bond_properties
|
||||
bond_properties_to_change = @property_flush[:bond_properties]
|
||||
if @old_property_hash[:bond_properties] and !@old_property_hash[:bond_properties].empty?
|
||||
|
@ -101,14 +61,11 @@ Puppet::Type.type(:l2_bond).provide(:lnx, :parent => Puppet::Provider::Lnx_base)
|
|||
bond_properties_to_change = Hash[*bond_properties_to_change.flatten]
|
||||
end
|
||||
debug("Bond properties which are going to be changed #{bond_properties_to_change}")
|
||||
# change bond_properties
|
||||
bond_is_up = !self.class.get_iface_state(@resource[:bond]).nil?
|
||||
# Reassemble bond if we change bond mode
|
||||
need_reassembling = true if bond_properties_to_change[:mode] and self.class.get_sys_class("#{bond_prop_dir}/bonding/#{'mode'}") != bond_properties_to_change[:mode]
|
||||
if need_reassembling
|
||||
if need_reassembling and !runtime_slave_ports.empty?
|
||||
self.class.interface_down(@resource[:bond])
|
||||
bond_is_up = false
|
||||
runtime_slave_ports = self.class.get_sys_class("#{bond_prop_dir}/bonding/slaves", true)
|
||||
debug("Disassemble bond '#{@resource[:bond]}'")
|
||||
runtime_slave_ports.each do |eth|
|
||||
debug("Remove interface '#{eth}' from bond '#{@resource[:bond]}'")
|
||||
|
@ -163,16 +120,63 @@ Puppet::Type.type(:l2_bond).provide(:lnx, :parent => Puppet::Provider::Lnx_base)
|
|||
debug("Unsupported property '#{prop}' for bond '#{@resource[:bond]}'")
|
||||
end
|
||||
end
|
||||
if need_reassembling
|
||||
if need_reassembling and !runtime_slave_ports.empty?
|
||||
# re-assemble bond after configuration
|
||||
debug("Re-assemble bond '#{@resource[:bond]}'")
|
||||
self.class.interface_up(@resource[:bond])
|
||||
runtime_slave_ports.each do |eth|
|
||||
debug("Add interface '#{eth}' to bond '#{@resource[:bond]}'")
|
||||
self.class.set_sys_class("#{bond_prop_dir}/bonding/slaves", "+#{eth}")
|
||||
end
|
||||
end
|
||||
self.class.interface_up(@resource[:bond]) if !bond_is_up
|
||||
end
|
||||
|
||||
# set interface state to UP
|
||||
if !bond_is_up
|
||||
self.class.interface_up(@resource[:bond])
|
||||
bond_is_up = true
|
||||
end
|
||||
|
||||
# Change list of slaves
|
||||
if @property_flush.has_key? :slaves
|
||||
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]
|
||||
if !rm_slave_list.empty?
|
||||
debug("Remove '#{rm_slave_list.join(',')}' ports from bond '#{@resource[:bond]}'")
|
||||
rm_slave_list.each do |slave|
|
||||
self.class.interface_down(slave) # need by kernel requirements by design. undocumented :(
|
||||
self.class.set_sys_class("#{bond_prop_dir}/bonding/slaves", "-#{slave}")
|
||||
end
|
||||
end
|
||||
# add interfaces to bond
|
||||
add_slave_list = @property_flush[:slaves] - runtime_slave_ports
|
||||
if !add_slave_list.empty?
|
||||
debug("Add '#{add_slave_list.join(',')}' ports to bond '#{@resource[:bond]}'")
|
||||
add_slave_list.each do |slave|
|
||||
debug("Add interface '#{slave}' to bond '#{@resource[:bond]}'")
|
||||
self.class.interface_down(slave) # need by kernel requirements by design. undocumented :(
|
||||
self.class.iproute("addr flush dev #{slave}")
|
||||
self.class.set_sys_class("#{bond_prop_dir}/bonding/slaves", "+#{slave}")
|
||||
self.class.interface_up(slave)
|
||||
end
|
||||
end
|
||||
end
|
||||
if bond_is_up
|
||||
# waiting for bond became UP
|
||||
wait_time = @resource[:bond_properties][:updelay].to_i/1000 || 60.0
|
||||
wait_step = 0.5
|
||||
while !self.class.get_iface_state(@resource[:bond]) and wait_time>0 do
|
||||
debug("Waiting for bond '#{@resource[:bond]}' interface UP (#{wait_time})")
|
||||
sleep(wait_step)
|
||||
wait_time -= wait_step
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Make bond a member of bridge
|
||||
if @property_flush.has_key? :bridge
|
||||
# get actual bridge-list. We should do it here,
|
||||
# because bridge may be not existing at prefetch stage.
|
||||
|
@ -182,14 +186,9 @@ Puppet::Type.type(:l2_bond).provide(:lnx, :parent => Puppet::Provider::Lnx_base)
|
|||
debug("Actual-port-bridge-mapping: '#{port_bridges_hash}'") # it should removed from LNX
|
||||
#
|
||||
# remove interface from old bridge
|
||||
bond_is_up = !self.class.get_iface_state(@resource[:bond]).nil?
|
||||
if ! port_bridges_hash[@resource[:bond]].nil?
|
||||
br_name = port_bridges_hash[@resource[:bond]][:bridge]
|
||||
if br_name != @resource[:bond]
|
||||
if bond_is_up
|
||||
self.class.interface_down(@resource[:bond], true)
|
||||
bond_is_up = false
|
||||
end
|
||||
# do not remove bridge-based interface from his bridge
|
||||
case port_bridges_hash[@resource[:bond]][:br_type]
|
||||
when :ovs
|
||||
|
@ -214,7 +213,6 @@ Puppet::Type.type(:l2_bond).provide(:lnx, :parent => Puppet::Provider::Lnx_base)
|
|||
#pass
|
||||
end
|
||||
end
|
||||
self.class.interface_up(@resource[:bond]) if !bond_is_up
|
||||
debug("Change bridge")
|
||||
end
|
||||
if @property_flush[:onboot]
|
||||
|
|
|
@ -71,36 +71,6 @@ Puppet::Type.type(:l2_port).provide(:lnx, :parent => Puppet::Provider::Lnx_base)
|
|||
end
|
||||
#
|
||||
# FLUSH changed properties
|
||||
if @property_flush.has_key? :bond_master and @property_flush[:bond_master] != :absent
|
||||
bond = @old_property_hash[:bond_master]
|
||||
if self.class.ipaddr_exist? @resource[:interface]
|
||||
# remove all IP addresses from member of bond. This should be done on device in UP state
|
||||
self.class.addr_flush(@resource[:interface])
|
||||
end
|
||||
# putting interface to the down-state, because add/remove upped interface impossible. undocumented kern.behavior.
|
||||
self.class.interface_down(@resource[:interface], true)
|
||||
if bond and bond != :absent and File.exist?("/sys/class/net/#{@resource[:interface]}/master/bonding/slaves")
|
||||
# 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
|
||||
if File.exist? "/sys/class/net/#{@property_flush[:bond_master]}/bonding/slaves"
|
||||
# If port is bond member and bond still doesn't exist we skip the adding to bond action
|
||||
# Bond will do it by itself during bond creation
|
||||
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]}"}
|
||||
end
|
||||
else
|
||||
# port no more member of any bonds
|
||||
@property_flush[:port_type] = nil
|
||||
end
|
||||
# Up parent interface if this is vlan port
|
||||
self.class.interface_up(@resource[:vlan_dev]) if @resource[:vlan_dev]
|
||||
# Up port
|
||||
self.class.interface_up(@resource[:interface])
|
||||
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.
|
||||
|
|
|
@ -267,7 +267,8 @@ type : patch
|
|||
:mode=>"balance-rr",
|
||||
:miimon=>"0",
|
||||
:updelay=>"0",
|
||||
:downdelay=>"0"
|
||||
:downdelay=>"0",
|
||||
:use_carrier=>"1"
|
||||
},
|
||||
:onboot=>false
|
||||
}
|
||||
|
@ -296,6 +297,7 @@ type : patch
|
|||
end
|
||||
|
||||
it 'parses the sysfs to get_lnx_bonds' do
|
||||
subject.stubs(:ovs_vsctl).with('list-br').returns({})
|
||||
subject.stubs(:get_sys_class).with('/sys/class/net/bonding_masters', true).returns(['bond0'])
|
||||
subject.stubs(:get_sys_class).with('/sys/class/net/bond0/bonding/mode').returns('balance-rr')
|
||||
subject.stubs(:get_sys_class).with('/sys/class/net/bond0/mtu').returns('1500')
|
||||
|
@ -304,7 +306,7 @@ type : patch
|
|||
subject.stubs(:get_sys_class).with('/sys/class/net/bond0/bonding/updelay').returns('0')
|
||||
subject.stubs(:get_sys_class).with('/sys/class/net/bond0/bonding/downdelay').returns('0')
|
||||
subject.stubs(:get_sys_class).with('/sys/class/net/bond0/bonding/mode').returns('balance-rr')
|
||||
subject.stubs(:get_sys_class).with('/sys/class/net/bond0/bonding/mode').returns('balance-rr')
|
||||
subject.stubs(:get_sys_class).with('/sys/class/net/bond0/bonding/use_carrier').returns('1')
|
||||
|
||||
expect(subject.get_lnx_bonds).to eq get_lnx_bonds_result
|
||||
end
|
||||
|
|
|
@ -55,6 +55,8 @@ describe Puppet::Type.type(:l2_bond).provider(:lnx) do
|
|||
provider.class.stubs(:set_sys_class).with('/sys/class/net/bond1/bonding/updelay', '111').returns(true)
|
||||
provider.class.stubs(:get_sys_class).with('/sys/class/net/bond1/bonding/downdelay').returns('0')
|
||||
provider.class.stubs(:set_sys_class).with('/sys/class/net/bond1/bonding/downdelay', '222').returns(true)
|
||||
provider.class.stubs(:iproute).with('addr flush dev eth1').returns(true)
|
||||
provider.class.stubs(:iproute).with('addr flush dev eth2').returns(true)
|
||||
provider.class.stubs(:interface_up).with('bond1').returns(true)
|
||||
provider.class.stubs(:interface_up).with('eth1').returns(true)
|
||||
provider.class.stubs(:interface_up).with('eth2').returns(true)
|
||||
|
@ -239,6 +241,8 @@ describe Puppet::Type.type(:l2_bond).provider(:lnx) do
|
|||
provider.class.stubs(:get_bridge_list).returns({'br-ovs'=>{:br_type=>:ovs},})
|
||||
provider.class.stubs(:get_port_bridges_pairs).returns({"br-storage"=>{:bridge=>"br-storage", :br_type=>:ovs}})
|
||||
provider.class.stubs(:ovs_vsctl).with(['add-port', 'br-ovs', 'bond12']).once
|
||||
provider.class.stubs(:iproute).with('addr flush dev eth1').returns(true)
|
||||
provider.class.stubs(:iproute).with('addr flush dev eth2').returns(true)
|
||||
provider.class.stubs(:interface_up).with('bond12').returns(true)
|
||||
provider.class.stubs(:interface_up).with('eth1').returns(true)
|
||||
provider.class.stubs(:interface_up).with('eth2').returns(true)
|
||||
|
|
Loading…
Reference in New Issue