Fix prefetching for l2_bond ovs provider

Change-Id: Ied15b1ed0208184b4c540a88a803b551e5fb2005
Closes-bug: #1540907
This commit is contained in:
Stanislav Makar
2016-02-02 12:51:28 +00:00
parent dfad93c217
commit ee1c027abe
5 changed files with 139 additions and 28 deletions

View File

@@ -1,4 +1,5 @@
require 'puppetx/l23_ethtool_name_commands_mapping'
require 'json'
require File.join(File.dirname(__FILE__), 'interface_toolset')
class Puppet::Provider::L2_base < Puppet::Provider::InterfaceToolset
@@ -523,6 +524,7 @@ class Puppet::Provider::L2_base < Puppet::Provider::InterfaceToolset
end
bond[bond_name][:onboot] = !self.get_iface_state(bond_name).nil?
end
debug("get_lnx_bonds: LNX bond list #{bond}")
return bond
end
@@ -558,16 +560,61 @@ class Puppet::Provider::L2_base < Puppet::Provider::InterfaceToolset
self.lnx_bond_allowed_properties.keys.sort
end
def self.get_ovs_bonds
# search all OVS bonds on the host, and return hash with
# bond_name => { bond options }
all_ports_json = JSON.parse(ovs_vsctl(['-f json', 'list', 'port'])[0])
all_ports_headings_to_data_hash = []
all_ports_json['data'].each do | port |
all_ports_headings_to_data_hash << Hash[all_ports_json['headings'].zip(port)]
end
bond_list = {}
all_ports_headings_to_data_hash.each do | each_port |
unless each_port['bond_active_slave'].is_a?(Array)
bond_properties = {}
bond_name = each_port['name']
bond_list[bond_name] = {}
self.ovs_bond_allowed_properties.each do | p_name, prop |
transf_prop = prop[:property]
get_value = ''
get_value = prop[:default] if prop[:default]
if transf_prop.match(%{config:})
transf_prop = "#{transf_prop.split(':')[1]}"
each_port['other_config'][1].each do |each_config|
get_value = each_config[1] unless each_config.select{ |get_property| get_property == transf_prop }.empty?
end
else
get_value = each_port[transf_prop] unless each_port[transf_prop].is_a?(Array)
end
get_value = prop[:override_integer].index(get_value) if prop[:override_integer]
bond_properties[p_name] = get_value.to_s.gsub('"', '') unless get_value.to_s.empty?
end
slaves = []
each_port['interfaces'][1].collect{ |int| int[1] }.each do | sl |
slaves << ovs_vsctl(['get', 'interface', sl, 'name' ]).join().gsub('"', '')
end
bond_list[bond_name][:slaves] = slaves
bond_list[bond_name][:bridge] = ovs_vsctl(['port-to-br', bond_name])[0]
bond_list[bond_name][:bond_properties] = bond_properties
end
end
debug("get_ovs_bonds: OVS bond list #{bond_list}")
return bond_list
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'] },
:default => 'carrier',
:override_integer => ['miimon', 'carrier'], },
:mode => {:property => 'bond_mode',
:allow => ['balance-slb', 'active-backup', 'balance-tcp', 'stable'] },
:allow => ['balance-slb', 'active-backup', 'balance-tcp', 'stable'],
:default => 'active-backup' },
:lacp => {:property => 'lacp',
:allow => ['off', 'active', 'passive'] },
: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'},

View File

@@ -4,17 +4,21 @@ Puppet::Type.type(:l2_bond).provide(:ovs, :parent => Puppet::Provider::Ovs_base)
commands :vsctl => 'ovs-vsctl',
:ethtool_cmd => 'ethtool'
# 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.fetch(:port, {}).reject{|k,v| !v[:port_type].include?('bond')}
def self.instances
bonds ||= self.get_ovs_bonds()
debug("found bonds: #{bonds.keys}")
rv = []
bonds.each_pair do |bond_name, bond_props|
props = {
:ensure => :present,
:name => bond_name,
:vendor_specific => {}
}
props.merge! bond_props
debug("PREFETCHED properties for '#{bond_name}': #{props}")
rv << new(props)
end
rv
end
#-----------------------------------------------------------------
@@ -33,16 +37,6 @@ Puppet::Type.type(:l2_bond).provide(:ovs, :parent => Puppet::Provider::Ovs_base)
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
@@ -63,9 +57,15 @@ Puppet::Type.type(:l2_bond).provide(:ovs, :parent => Puppet::Provider::Ovs_base)
# ovs-vsctl show
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?
bond_properties_to_change = @property_flush[:bond_properties].to_a - @old_property_hash[:bond_properties].to_a
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
allowed_properties = self.class.ovs_bond_allowed_properties()
@property_flush[:bond_properties].each_pair do |prop, val|
bond_properties_to_change.each_pair do |prop, val|
if self.class.ovs_bond_allowed_properties_list.include? prop.to_sym
act_val = val.to_s
else

View File

@@ -140,7 +140,7 @@ Puppet::Type.newtype(:l2_bond) do
val.keys.each do |k|
if k.is_a? String
unless val.has_key? k.to_sym
val[k.to_sym] = val[k] unless [:undef, :absent, ''].include?(val[k])
val[k.to_sym] = val[k].to_s unless [:undef, :absent, ''].include?(val[k])
end
val.delete(k)
end

View File

@@ -52,3 +52,67 @@ describe Puppet::Type.type(:l2_bond).provider(:ovs) do
end
end
describe Puppet::Type.type(:l2_bond).provider(:ovs) do
let(:resource) {
Puppet::Type.type(:l2_bond).new(
:provider => :ovs,
:name => 'bond1',
:bridge => 'br1',
:slaves => ['eth1', 'eth2'],
:bond_properties => {
'mode' => 'balance-slb',
'lacp_rate' => 'fast',
'updelay' => 0,
'downdelay' => 0,
},
)
}
let(:provider_class) {
Puppet::Type.type(:l2_bond).provider(:ovs)
}
let(:provider) {
prefetched_provider = provider_class.instances.first
resource.provider = prefetched_provider if prefetched_provider
resource.provider
}
before(:each) do
puppet_debug_override()
end
it "Just change needed bond properties ( bond_mode and lscp_rate )" do
provider_class.stubs(:ovs_vsctl).with(['-f json', 'list', 'port']).returns(['{"data":[[["uuid","fd022078-c30c-4e1c-8ff1-e12e36a7d4fc"],["set",[]],0,false,["set",[]],0,["map",[]],false,["uuid","8f347007-d5f2-4b34-bfd9-785cc359659d"],["set",[]],["set",[]],"patch-tun",["map",[]],["set",[]],["map",[]],["map",[]],["set",[]],["set",[]],["set",[]]],[["uuid","114b5b6c-ff22-42c4-bdb3-bbba31b763ee"],"64:6a:0e:e3:9f:42",0,false,["set",[]],0,["map",[]],false,["set",[["uuid","4acb3e5e-d144-4121-93ee-f28e57705a61"],["uuid","f207bef7-9597-46cf-a75a-e032e1c397c4"]]],["set",[]],["set",[]],"bond1",["map",[]],["set",[]],["map",[]],["map",[]],["set",[]],["set",[]],["set",[]]],[["uuid","17ae81dc-8575-4fb0-972e-ad3680fa6078"],["set",[]],0,false,["set",[]],0,["map",[]],false,["uuid","ee0ba3c8-cd19-47af-8af0-0a184928a746"],["set",[]],["set",[]],"br-bond",["map",[]],["set",[]],["map",[]],["map",[]],["set",[]],["set",[]],["set",[]]],[["uuid","ebd27817-a1d9-486f-b158-f296d1caf456"],["set",[]],0,false,["set",[]],0,["map",[]],false,["uuid","0a16958b-b3d2-4da5-aa85-9bc80cf26d2d"],["set",[]],["set",[]],"br-int",["map",[]],["set",[]],["map",[]],["map",[]],["set",[]],["set",[]],["set",[]]]],"headings":["_uuid","bond_active_slave","bond_downdelay","bond_fake_iface","bond_mode","bond_updelay","external_ids","fake_bridge","interfaces","lacp","mac","name","other_config","qos","statistics","status","tag","trunks","vlan_mode"]}'])
provider_class.stubs(:ovs_vsctl).with(['get', 'interface', '4acb3e5e-d144-4121-93ee-f28e57705a61', 'name']).returns(['eth1'])
provider_class.stubs(:ovs_vsctl).with(['get', 'interface', 'f207bef7-9597-46cf-a75a-e032e1c397c4', 'name']).returns(['eth2'])
provider_class.stubs(:ovs_vsctl).with(['port-to-br', 'bond1']).returns(['br1'])
provider.bond_properties = provider.resource[:bond_properties] # emulate puppet works
provider.class.expects(:vsctl).with('--', 'set', 'Port', 'bond1', 'bond_mode=balance-slb').returns(true)
provider.class.expects(:vsctl).with('--', 'set', 'Port', 'bond1', 'other_config:lacp_time=fast').returns(true)
provider.class.expects(:vsctl).with('--', 'set', 'Port', 'bond1', 'bond_updelay=0').never
provider.class.expects(:vsctl).with('--', 'set', 'Port', 'bond1', 'bond_downdelay=0').never
provider.flush
end
it "Change nothing" do
provider_class.stubs(:ovs_vsctl).with(['-f json', 'list', 'port']).returns(['{"data":[[["uuid","fd022078-c30c-4e1c-8ff1-e12e36a7d4fc"],["set",[]],0,false,["set",[]],0,["map",[]],false,["uuid","8f347007-d5f2-4b34-bfd9-785cc359659d"],["set",[]],["set",[]],"patch-tun",["map",[]],["set",[]],["map",[]],["map",[]],["set",[]],["set",[]],["set",[]]],[["uuid","114b5b6c-ff22-42c4-bdb3-bbba31b763ee"],"64:6a:0e:e3:9f:42",0,false,"balance-slb",0,["map",[]],false,["set",[["uuid","4acb3e5e-d144-4121-93ee-f28e57705a61"],["uuid","f207bef7-9597-46cf-a75a-e032e1c397c4"]]],["set",[]],["set",[]],"bond1",["map",[["lacp_time","fast"]]],["set",[]],["map",[]],["map",[]],["set",[]],["set",[]],["set",[]]],[["uuid","17ae81dc-8575-4fb0-972e-ad3680fa6078"],["set",[]],0,false,["set",[]],0,["map",[]],false,["uuid","ee0ba3c8-cd19-47af-8af0-0a184928a746"],["set",[]],["set",[]],"br-bond",["map",[]],["set",[]],["map",[]],["map",[]],["set",[]],["set",[]],["set",[]]],[["uuid","ebd27817-a1d9-486f-b158-f296d1caf456"],["set",[]],0,false,["set",[]],0,["map",[]],false,["uuid","0a16958b-b3d2-4da5-aa85-9bc80cf26d2d"],["set",[]],["set",[]],"br-int",["map",[]],["set",[]],["map",[]],["map",[]],["set",[]],["set",[]],["set",[]]]],"headings":["_uuid","bond_active_slave","bond_downdelay","bond_fake_iface","bond_mode","bond_updelay","external_ids","fake_bridge","interfaces","lacp","mac","name","other_config","qos","statistics","status","tag","trunks","vlan_mode"]}'])
provider_class.stubs(:ovs_vsctl).with(['get', 'interface', '4acb3e5e-d144-4121-93ee-f28e57705a61', 'name']).returns(['eth1'])
provider_class.stubs(:ovs_vsctl).with(['get', 'interface', 'f207bef7-9597-46cf-a75a-e032e1c397c4', 'name']).returns(['eth2'])
provider_class.stubs(:ovs_vsctl).with(['port-to-br', 'bond1']).returns(['br1'])
provider.bond_properties = provider.resource[:bond_properties] # emulate puppet works
provider.class.expects(:vsctl).with('--', 'set', 'Port', 'bond1', 'bond_mode=balance-slb').never
provider.class.expects(:vsctl).with('--', 'set', 'Port', 'bond1', 'other_config:lacp_time=fast').never
provider.class.expects(:vsctl).with('--', 'set', 'Port', 'bond1', 'bond_updelay=0').never
provider.class.expects(:vsctl).with('--', 'set', 'Port', 'bond1', 'bond_downdelay=0').never
provider.flush
end
end