Fix prefetching for l2_bond ovs provider
Change-Id: Ied15b1ed0208184b4c540a88a803b551e5fb2005 Closes-bug: #1540907
This commit is contained in:
		@@ -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'},
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -138,4 +138,4 @@ class Puppet::Provider::Ovs_base < Puppet::Provider::L2_base
 | 
			
		||||
  #-----------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
# vim: set ts=2 sw=2 et :
 | 
			
		||||
# vim: set ts=2 sw=2 et :
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -51,4 +51,68 @@ describe Puppet::Type.type(:l2_bond).provider(:ovs) do
 | 
			
		||||
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user