netutils 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/README.md +36 -0
- data/Rakefile +6 -0
- data/bin/acl +109 -0
- data/bin/alaxala-deploy +271 -0
- data/bin/config-diff-check +111 -0
- data/bin/config-gets +64 -0
- data/bin/console +14 -0
- data/bin/host-locate-on-demand +102 -0
- data/bin/ipaddr-resolv +74 -0
- data/bin/ipaddr-resolv.sh +97 -0
- data/bin/mac-drop +84 -0
- data/bin/mac-nodrop +45 -0
- data/bin/port-shutdown +78 -0
- data/bin/setup +8 -0
- data/lib/netutils.rb +118 -0
- data/lib/netutils/arp.rb +28 -0
- data/lib/netutils/cli.rb +702 -0
- data/lib/netutils/cli/alaxala.rb +121 -0
- data/lib/netutils/cli/alaxala/interface.rb +137 -0
- data/lib/netutils/cli/alaxala/lldp.rb +166 -0
- data/lib/netutils/cli/alaxala/macfib.rb +62 -0
- data/lib/netutils/cli/alaxala/showarp.rb +51 -0
- data/lib/netutils/cli/alaxala/showroute.rb +86 -0
- data/lib/netutils/cli/alaxala/showvrf.rb +46 -0
- data/lib/netutils/cli/aruba.rb +15 -0
- data/lib/netutils/cli/cisco.rb +45 -0
- data/lib/netutils/cli/cisco/cdp.rb +117 -0
- data/lib/netutils/cli/cisco/ifsummary.rb +32 -0
- data/lib/netutils/cli/cisco/interface.rb +67 -0
- data/lib/netutils/cli/cisco/macfib.rb +38 -0
- data/lib/netutils/cli/cisco/showarp.rb +27 -0
- data/lib/netutils/cli/cisco/showinterface.rb +27 -0
- data/lib/netutils/cli/cisco/showroute.rb +73 -0
- data/lib/netutils/cli/cisco/showvrf.rb +45 -0
- data/lib/netutils/cli/nec.rb +20 -0
- data/lib/netutils/cli/nec/lldp.rb +16 -0
- data/lib/netutils/cli/paloalto.rb +21 -0
- data/lib/netutils/fsm.rb +43 -0
- data/lib/netutils/macaddr.rb +51 -0
- data/lib/netutils/oncequeue.rb +78 -0
- data/lib/netutils/parser.rb +30 -0
- data/lib/netutils/rib.rb +80 -0
- data/lib/netutils/switch.rb +402 -0
- data/lib/netutils/tunnel.rb +8 -0
- data/lib/netutils/version.rb +3 -0
- data/lib/netutils/vrf.rb +42 -0
- data/log/.gitignore +1 -0
- data/netutils.gemspec +33 -0
- metadata +195 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'netutils/parser'
|
2
|
+
require 'netutils/macaddr'
|
3
|
+
|
4
|
+
module Cisco
|
5
|
+
|
6
|
+
class MACFIB < Parser
|
7
|
+
attr_reader :ports
|
8
|
+
|
9
|
+
# XXX
|
10
|
+
# * 2005 082e.5f24.56a9 dynamic Yes 0 Po19
|
11
|
+
CISCO6500_RE = /^\* +[0-9]+ +[^ ]+ +dynamic +Yes +[0-9]+ +([^ ]+)$/
|
12
|
+
# 3188 f80f.41d2.e746 dynamic ip,(cut),other TenGigabitEthernet1/1
|
13
|
+
CISCO4500_RE = /^ *[0-9]+ +[^ ]+ +dynamic +ip[^ ]+ +([^ ]+) +$/
|
14
|
+
# 100 0016.c8c5.35a2 DYNAMIC Po1
|
15
|
+
CISCO2500_RE = /^ *[0-9]+ +[^ ]+ +(?:STATIC|DYNAMIC) +([^ ]+).*$/
|
16
|
+
|
17
|
+
def cmd(ma, vlan)
|
18
|
+
return "show mac address-table address #{ma.to_s} vlan #{vlan}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(sw)
|
22
|
+
@ports = {}
|
23
|
+
super()
|
24
|
+
add('Init', :init)
|
25
|
+
@sw = sw
|
26
|
+
end
|
27
|
+
|
28
|
+
def init(l, m)
|
29
|
+
case l
|
30
|
+
# XXX: other switches...
|
31
|
+
when CISCO6500_RE, CISCO4500_RE, CISCO2500_RE
|
32
|
+
name = @sw.ports.key($1)
|
33
|
+
@ports[name] = name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'netutils/parser'
|
2
|
+
require 'netutils/arp'
|
3
|
+
|
4
|
+
module Cisco
|
5
|
+
|
6
|
+
class ShowARP < Parser
|
7
|
+
attr_reader :arps
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@arps = ARPTable.new
|
11
|
+
super()
|
12
|
+
add('Init', :init)
|
13
|
+
# Protocol Address Age (min) Hardware Addr Type Interface
|
14
|
+
# Internet 192.168.0.1 3 dead.beef.dead ARPA Vlan9999
|
15
|
+
add('Entry', :entry, /^Internet +([^ ]+) +([0-9]+|-) +([^ ]+) +ARPA+ +([^ ]+)$/)
|
16
|
+
end
|
17
|
+
|
18
|
+
def init(l, m)
|
19
|
+
changeto('Entry') if l =~ /^Protocol/
|
20
|
+
end
|
21
|
+
|
22
|
+
def entry(l, m)
|
23
|
+
@arps.add(m[1], m[3], m[4], m[2] === '-')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'netutils/parser'
|
2
|
+
require 'netutils/tunnel'
|
3
|
+
|
4
|
+
module Cisco
|
5
|
+
|
6
|
+
class ShowInterface < Parser
|
7
|
+
attr_reader :tunnel
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
super()
|
11
|
+
add('Init', :init)
|
12
|
+
add('Done', :done)
|
13
|
+
end
|
14
|
+
|
15
|
+
def init(l, m)
|
16
|
+
# Tunnel source 192.168.0.1 (Dialer1), destination 192.168.0.2
|
17
|
+
if l =~ /^ Tunnel source ([^ ]+) [^,]+, destination ([^ ]+)/
|
18
|
+
@tunnel = Tunnel.new($1, $2)
|
19
|
+
changeto('Done')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def done(l, m)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'netutils/parser'
|
2
|
+
require 'netutils/rib'
|
3
|
+
|
4
|
+
module Cisco
|
5
|
+
|
6
|
+
class ShowRoute < Parser
|
7
|
+
attr_reader :rib
|
8
|
+
|
9
|
+
def cmd(ia)
|
10
|
+
"show ip route vrf \* #{ia}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@rib = RIB.new
|
15
|
+
super
|
16
|
+
# % Network not in table
|
17
|
+
# Routing entry for 192.168.0.0/24
|
18
|
+
add('Init', :init)
|
19
|
+
# Known via "connected", distance 0, metric 0 (connected, via interface)
|
20
|
+
add('Protocol', :protocol, / Known via "([^"]+)",.*$/)
|
21
|
+
add('Descriptor', :descriptor)
|
22
|
+
# * 192.168.0.200
|
23
|
+
# * directly connected, via Vlan4000
|
24
|
+
# * 192.168.0.1, from 192.168.0.1, 00:00:19 ago, via Vlan9999
|
25
|
+
add('Nexthop', :nexthop, /^ \* ([^ ,]+)(?:,? .*, via ([^ ]+)|)$/)
|
26
|
+
# Route metric is 0, traffic share count is 1
|
27
|
+
add('Metric', :metric, /^ Route metric is .*$/)
|
28
|
+
end
|
29
|
+
|
30
|
+
def init(l, m)
|
31
|
+
return if l =~ /^% .* not in table/
|
32
|
+
return if l =~ /^$/
|
33
|
+
if l !~ /^Routing entry for ([0-9\.\/]+)(?:, supernet)?$/
|
34
|
+
raise "Invalid format: #{l}"
|
35
|
+
end
|
36
|
+
@dst = $1
|
37
|
+
changeto('Protocol')
|
38
|
+
end
|
39
|
+
|
40
|
+
def protocol(l, m)
|
41
|
+
@protocol = m[1]
|
42
|
+
changeto('Descriptor')
|
43
|
+
end
|
44
|
+
|
45
|
+
def descriptor(l, m)
|
46
|
+
# Routing Descriptor Blocks:
|
47
|
+
case l
|
48
|
+
when /^ Routing Descriptor Blocks:$/
|
49
|
+
changeto('Nexthop')
|
50
|
+
when /^ Redistributing via /, /^ Advertised by /
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def nexthop(l, m)
|
55
|
+
case m[1]
|
56
|
+
when 'directly'
|
57
|
+
@nh = nil
|
58
|
+
when /[0-9\.\/]+/
|
59
|
+
@nh = m[1]
|
60
|
+
else
|
61
|
+
raise "Invalid format: #{l}"
|
62
|
+
end
|
63
|
+
@interface = m[2]
|
64
|
+
changeto('Metric')
|
65
|
+
end
|
66
|
+
|
67
|
+
def metric(l, m)
|
68
|
+
@rib.add(@protocol, @dst, @nh, @interface)
|
69
|
+
changeto('Init')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'netutils/parser'
|
2
|
+
require 'netutils/vrf'
|
3
|
+
|
4
|
+
module Cisco
|
5
|
+
|
6
|
+
class ShowVRF < Parser
|
7
|
+
attr_reader :vrfs
|
8
|
+
|
9
|
+
def cmd
|
10
|
+
return 'show vrf'
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
super()
|
15
|
+
@vrfs = VRFTable.new
|
16
|
+
add('Init', :init)
|
17
|
+
add('VRF', :vrf)
|
18
|
+
add('Interface', :interface)
|
19
|
+
end
|
20
|
+
|
21
|
+
def init(l, m)
|
22
|
+
return if l !~ /^ +Name +Default RD +Protocols +Interfaces$/
|
23
|
+
changeto('VRF')
|
24
|
+
end
|
25
|
+
|
26
|
+
def vrf(l, m)
|
27
|
+
if l !~ /^ *([^ ]+) +([^ ]+|<not set>) +[^ ]+ +([^ ]+) *$/ &&
|
28
|
+
l !~ /^ *([^ ]+) +([^ ]+|<not set>) +[^ ]+ *$/
|
29
|
+
raise(ArgumentError, "Invalid line: \"#{l}\"")
|
30
|
+
end
|
31
|
+
@vrf = vrfs.add($1, $2)
|
32
|
+
@vrf.interface_add($3) if $3
|
33
|
+
changeto('Interface')
|
34
|
+
end
|
35
|
+
|
36
|
+
def interface(l, m)
|
37
|
+
if l =~ /^ +([^ ]+) *$/
|
38
|
+
@vrf.interface_add(m[1])
|
39
|
+
else
|
40
|
+
vrf(l, nil)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'netutils/cli/nec/lldp'
|
2
|
+
|
3
|
+
module NEC
|
4
|
+
CONFIG_RE = /^(.*\n)$/m
|
5
|
+
|
6
|
+
def disable_logging_console
|
7
|
+
# XXX
|
8
|
+
end
|
9
|
+
|
10
|
+
def enable
|
11
|
+
end
|
12
|
+
|
13
|
+
def show_running_config
|
14
|
+
return cmd('show running-config')
|
15
|
+
end
|
16
|
+
|
17
|
+
def interface_gets(sw)
|
18
|
+
# XXX
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Paloalto
|
2
|
+
CONFIG_RE = /^(config {\n(?:[^\n]+\n){1,}}\n)\n\Z/
|
3
|
+
|
4
|
+
def disable_logging_console
|
5
|
+
# XXX
|
6
|
+
end
|
7
|
+
|
8
|
+
def enable
|
9
|
+
end
|
10
|
+
|
11
|
+
def disable
|
12
|
+
end
|
13
|
+
|
14
|
+
def show_running_config
|
15
|
+
return cmd('show config running')
|
16
|
+
end
|
17
|
+
|
18
|
+
def interface_gets(sw)
|
19
|
+
# XXX
|
20
|
+
end
|
21
|
+
end
|
data/lib/netutils/fsm.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
class FSM
|
2
|
+
class State
|
3
|
+
attr_reader :cb
|
4
|
+
|
5
|
+
def initialize(cb)
|
6
|
+
@cb = cb
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
FSM_S_INIT = 0
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@state = FSM_S_INIT
|
14
|
+
@fsm = Array.new
|
15
|
+
@name2index = Hash.new
|
16
|
+
@index2name = Array.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def add(name, cb)
|
20
|
+
if @name2index.key?(name)
|
21
|
+
raise(ArgumentError, "duplicated key \"#{name}\"")
|
22
|
+
end
|
23
|
+
@fsm.push(State.new(cb))
|
24
|
+
idx = @fsm.length - 1
|
25
|
+
@name2index[name] = idx
|
26
|
+
@index2name[idx] = name
|
27
|
+
end
|
28
|
+
|
29
|
+
def cb
|
30
|
+
return @fsm[@state].cb
|
31
|
+
end
|
32
|
+
|
33
|
+
def changeto(name)
|
34
|
+
if ! @name2index.key?(name)
|
35
|
+
raise(ArgumentError, "unnown state: \"#{name}\"")
|
36
|
+
end
|
37
|
+
@state = @name2index[name]
|
38
|
+
end
|
39
|
+
|
40
|
+
def state_name
|
41
|
+
return @index2name[@state]
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class MACAddr
|
2
|
+
NBBY = 8
|
3
|
+
Length = 6
|
4
|
+
|
5
|
+
def initialize(s)
|
6
|
+
s = s.delete('-.:')
|
7
|
+
raise if s =~ /[^0-9a-z]/i # XXX EINVAL
|
8
|
+
v = s.hex
|
9
|
+
raise if v > 0xffffffffffff # XXX ERANGE
|
10
|
+
@addr = v
|
11
|
+
end
|
12
|
+
|
13
|
+
def [](n, len)
|
14
|
+
raise if len > Length
|
15
|
+
raise if Length % len != 0
|
16
|
+
n *= len
|
17
|
+
v = 0
|
18
|
+
off = 0
|
19
|
+
while off < len do
|
20
|
+
v <<= NBBY
|
21
|
+
v |= (@addr >> (NBBY * ((Length - 1) - n - off))) & 0xff
|
22
|
+
off += 1
|
23
|
+
end
|
24
|
+
return v
|
25
|
+
end
|
26
|
+
private :[]
|
27
|
+
|
28
|
+
def to_a(len = 1)
|
29
|
+
a = Array.new
|
30
|
+
max = Length / len
|
31
|
+
for n in 0 .. max - 1 do
|
32
|
+
a.push(self[n, len])
|
33
|
+
end
|
34
|
+
return a
|
35
|
+
end
|
36
|
+
private :to_a
|
37
|
+
|
38
|
+
def to_s(sep = '.', step = 2)
|
39
|
+
to_a(step).map { |v| sprintf('%0*x', step * 2, v) }.join(sep)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# XXX: test
|
44
|
+
#x = MACAddr.new('aabb.ccdd.eeff')
|
45
|
+
#x.to_s == 'aa:bb:cc:dd:ee:ff'
|
46
|
+
#x.to_s('.') == 'aa.bb.cc.dd.ee.ff'
|
47
|
+
#x.to_s('.', 2) == 'aabb.ccdd.eeff'
|
48
|
+
#x.to_s('.', 3) == 'aabbcc.ddeeff'
|
49
|
+
#x.to_s('.', 6) == 'aabbccddeeff'
|
50
|
+
#x.to_s('.', 4) != 'aabbccddeeff'
|
51
|
+
#x.to_s('.', 7) != 'aabbccddeeff'
|
@@ -0,0 +1,78 @@
|
|
1
|
+
class OnceQueue
|
2
|
+
def initialize
|
3
|
+
@element = []
|
4
|
+
@queue = []
|
5
|
+
@mutex = Thread::Mutex.new
|
6
|
+
@cond = Thread::ConditionVariable.new
|
7
|
+
@empty = Thread::ConditionVariable.new
|
8
|
+
@processing = 0
|
9
|
+
@total = 0
|
10
|
+
@errors = 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def __count
|
14
|
+
@queue.size + @processing
|
15
|
+
end
|
16
|
+
private :__count
|
17
|
+
|
18
|
+
def count
|
19
|
+
@mutex.synchronize do
|
20
|
+
__count
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def total
|
25
|
+
@mutex.synchronize do
|
26
|
+
@total
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def errors
|
31
|
+
@mutex.synchronize do
|
32
|
+
@errors
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def enqueue(v)
|
37
|
+
@mutex.synchronize do
|
38
|
+
break if @element.include?(v)
|
39
|
+
@element.push(v)
|
40
|
+
@queue.push(v)
|
41
|
+
@cond.signal
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def dequeue
|
46
|
+
@mutex.synchronize do
|
47
|
+
@cond.wait(@mutex) while @queue.empty?
|
48
|
+
@processing += 1
|
49
|
+
@queue.shift
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def done(v)
|
54
|
+
@mutex.synchronize do
|
55
|
+
@processing -= 1
|
56
|
+
@empty.signal if __count === 0
|
57
|
+
@total += 1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def error
|
62
|
+
@mutex.synchronize do
|
63
|
+
@errors += 1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def synchronize
|
68
|
+
@mutex.synchronize do
|
69
|
+
yield
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def wait_all
|
74
|
+
@mutex.synchronize do
|
75
|
+
@empty.wait(@mutex) if __count > 0
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|