The route provider
always runs route command regardless of the current state of route´s
table.
I have looked
closely at the source code and it seems that the implementation contains
several errors
a) in line
100 : "is_running" is actually a local variable not the attribute
"is_running" of the object so it will get lost not being
used in method action_add
this is
fundamental error of programming, inside the instance method we must use
@is_running to set the value of the attribute of the
object
b) the method
load_current_resource has wrong logic, checking destination/target of the
current and new route , because while destination/target can
be
the same, the
gateway can be changed and the route should be considered as changed and
must be updated
c) the method
load_current_resource when pulling data from /proc/net/route shall take into
consideration the header of the file and ignore it
chef-test]$ cat /proc/net/route
Iface
Destination
Gateway Flags
RefCnt Use Metric
Mask
MTU Window
IRTT
eth0 0064A8C0
00000000 0001
0 0
0
00FFFFFF
0 0
0
eth1 000A10AC
00000000 0001
0 0
0
00FEFFFF
0 0
0
eth1 0000FEA9
00000000 0001
0 0
0
0000FFFF
0 0
0
eth1 00000000
030A10AC 0003
0 0
0
00000000
0 0 0
65 def
load_current_resource
66
is_running =
nil
67
68
Chef::Log.debug("Configuring Route
">
}")
69
70
# cidr or quad dot
mask
71 if
@new_resource.netmask
72
new_ip = IPAddr.new("
/
">
/
}")
73
else
74
new_ip =
IPAddr.new(@new_resource.target)
75
end
76
77 #
pull routes from
proc
78 if node[:os]
==
"linux"
79
route_file = ::File.open("/proc/net/route",
"r")
80
while (line =
route_file.gets)
81
# proc
layout
82
iface,destination,gateway,flags,refcnt,use,metric,mask,mtu,window,irtt =
line.split
83
84
# need to convert packed adresses int quad
dot
85
# the addrs are reversed hex packed decimal addrs. so this unwraps them.
tho you
could
86
# do this without ipaddr using unpack. ipaddr has no htoa
method.
87
#
88
destination = IPAddr.new(destination.scan(/../).reverse.to_s.hex,
Socket::AF_INET).to_s
89
gateway = IPAddr.new(gateway.scan(/../).reverse.to_s.hex,
Socket::AF_INET).to_s
90
mask = IPAddr.new(mask.scan(/../).reverse.to_s.hex,
Socket::AF_INET).to_s
91
Chef::Log.debug( "System has route: dest=#{destination} mask=#{mask}
gw=#{gateway}")
92
93
# check if what were trying to configure is already
there
94
# use an ipaddr object with ip/mask this way we can
have
95
# a new resource be in cidr format (i don't feel
like
96
# expanding bitmask by
hand.
97
#
98
running_ip =
IPAddr.new("#{destination}/#{mask}")
99
Chef::Log.debug( "new ip: #{new_ip.inspect} running ip: #{running_ip.inspect}
")
100
is_running = true if running_ip ==
new_ip
101
end
102
route_file.close
103
end
104 end
106 def action_add
107 # check to see if
load_current_resource found the route
108 if
is_running
109
Chef::Log.debug("Route
">
} already active
")
110
else
111
command = "ip route replace
">
}"
112
command << "/
" if
@new_resource.netmask
113
command << " via
">
}
"
114
command << " dev
">
} " if
@new_resource.device
115
116
Chef::Log.info("Adding route: #{command}
")
117
run_command( :command => command )
118
@new_resource.updated = true
119 end
120
121
#for now we always write the file (ugly but its what it
is)
122
generate_config
123
124 end
-----------------------------------------------------------------
ATTENTION:
The
information in this electronic mail message is private and
confidential,
and only intended for the addressee. Should you
receive this message by
mistake, you are hereby notified that
any disclosure, reproduction,
distribution or use of this
message is strictly prohibited. Please inform
the sender by
reply transmission and delete the message without copying
or
opening it.
Messages and attachments are scanned for all viruses known.
If this
message contains password-protected attachments, the
files have NOT been
scanned for viruses by the ING mail domain.
Always scan attachments before
opening
them.
-----------------------------------------------------------------