Add ip address duplication check

* Add ip address duplication check for l3_ifconfig puppet resource
before ip address set. Sometimes when there is ip address duplication
it leads to wierd problems and long-time investigation of root cause.
* Add sending Gratuitous ARP to update all neighbours.

Closes-bug: #1457416
Change-Id: I047458dff0fbbb6fbd2a8143c641f834ecc9a100
This commit is contained in:
Stanislav Makar 2015-06-22 15:37:40 +00:00 committed by Sergey Vasilenko
parent b82855db50
commit f1e949592e
5 changed files with 86 additions and 6 deletions

View File

@ -2,7 +2,8 @@ Puppet::Type.type(:l3_ifconfig).provide(:lnx) do
defaultfor :osfamily => :linux
commands :iproute => 'ip',
:ifup => 'ifup',
:ifdown => 'ifdown'
:ifdown => 'ifdown',
:arping => 'arping'
def self.prefetch(resources)
@ -98,12 +99,30 @@ Puppet::Type.type(:l3_ifconfig).provide(:lnx) do
else
# add IP addresses
adding_addresses.each do |ipaddr|
# Check whether IP address is already used
begin
arping('-D', '-c 32', '-w 5', '-I', @resource[:interface], ipaddr.split('/')[0])
rescue Exception => e
_errmsg = nil
e.message.split(/\n/).each do |line|
line =~ /reply\s+from\s+(\d+\.\d+\.\d+\.\d+)/i
if $1
_errmsg = line
break
end
end
raise if _errmsg.nil?
warn("There is IP duplication for IP address #{ipaddr} on interface #{@resource[:interface]}!!!\n#{_errmsg}")
end
# Set IP address
begin
iproute('addr', 'add', ipaddr, 'dev', @resource[:interface])
rescue
rv = iproute('-o', 'addr', 'show', 'dev', @resource[:interface], 'to', "#{ipaddr.split('/')[0]}/32")
raise if ! rv.include? "inet #{ipaddr}"
end
# Send Gratuitous ARP to update all neighbours
arping('-U', '-c 32', '-w 5', '-I', @resource[:interface], ipaddr.split('/')[0])
end
end
end
@ -112,15 +131,15 @@ Puppet::Type.type(:l3_ifconfig).provide(:lnx) do
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
while true
# 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
break
end
end

View File

@ -58,10 +58,10 @@ class l23network (
Anchor <| title == 'l23network::l2::centos_upndown_scripts' |> -> Anchor['l23network::init']
}
#install extra tools
ensure_packages($::l23network::params::extra_tools)
Anchor['l23network::l2::init'] -> Anchor['l23network::init']
anchor { 'l23network::init': }
}
#
###

View File

@ -16,6 +16,7 @@ class l23network::params {
$ovs_datapath_package_name = 'openvswitch-datapath-dkms'
$ovs_common_package_name = 'openvswitch-switch'
$ovs_kern_module_name = 'openvswitch'
$extra_tools = 'iputils-arping'
}
/(?i)redhat/: {
$interfaces_dir = '/etc/sysconfig/network-scripts'
@ -32,6 +33,7 @@ class l23network::params {
}
$ovs_common_package_name = 'openvswitch'
$ovs_kern_module_name = 'openvswitch'
$extra_tools = 'iputils'
}
/(?i)darwin/: {
$interfaces_dir = '/tmp/1'

View File

@ -13,7 +13,13 @@ if Puppet.version < '4.0.0'
end
end
Puppet::Util::Log.level = :debug
Puppet::Util::Log.newdestination(:console)
RSpec.configure do |c|
c.module_path = File.join(fixture_path, 'modules')
c.manifest_dir = File.join(fixture_path, 'manifests')
c.mock_with(:mocha)
end
###

View File

@ -0,0 +1,53 @@
require 'spec_helper'
describe Puppet::Type.type(:l3_ifconfig).provider(:lnx) do
let(:resource) {
Puppet::Type.type(:l3_ifconfig).new(
:name => 'eth1',
:interface => 'eth1',
:ensure => :present,
:ipaddr => ["10.99.1.4/24"],
:gateway => :absent,
:provider => :lnx
)
}
let(:provider) { resource.provider }
let(:instance) { provider.class.instances }
describe "l3_ifconfig " do
before(:each) do
provider.class.stubs(:arping).with('-U', '-c 32', '-w 5', '-I', 'eth1', '10.99.1.4').returns(true)
provider.class.stubs(:iproute)
provider.class.stubs(:iproute).with(['route', 'del', 'default', 'dev', 'eth1']).raises(Puppet::ExecutionFailure)
end
it "Assign IP address to the NIC" do
provider.class.stubs(:arping).with('-D', '-c 32', '-w 5', '-I', 'eth1', '10.99.1.4').returns(true)
provider.expects(:warn).with { |arg| arg =~ /IP\s+duplication/ }.never
provider.create
provider.flush
end
it "Assign duplication IP address to the NIC" do
provider.class.stubs(:arping).with('-D', '-c 32', '-w 5', '-I', 'eth1', '10.99.1.4').raises(Exception, """
ARPING 10.99.1.4 from 0.0.0.0 eth1
Unicast reply from 10.99.1.4 [00:1C:42:99:06:98] 1.292ms
Sent 1 probes (1 broadcast(s))
Received 1 response(s)
""")
provider.expects(:warn).with { |arg| arg =~ /IP\s+duplication/ }
provider.create
provider.flush
end
it "Arping execution error while assigning IP address to the NIC" do
provider.class.stubs(:arping).with('-D', '-c 32', '-w 5', '-I', 'eth1', '10.99.1.4').raises(Puppet::ExecutionFailure, '')
provider.create
expect{provider.flush}.to raise_error(Puppet::ExecutionFailure)
end
end
end