netutils 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +4 -0
  7. data/README.md +36 -0
  8. data/Rakefile +6 -0
  9. data/bin/acl +109 -0
  10. data/bin/alaxala-deploy +271 -0
  11. data/bin/config-diff-check +111 -0
  12. data/bin/config-gets +64 -0
  13. data/bin/console +14 -0
  14. data/bin/host-locate-on-demand +102 -0
  15. data/bin/ipaddr-resolv +74 -0
  16. data/bin/ipaddr-resolv.sh +97 -0
  17. data/bin/mac-drop +84 -0
  18. data/bin/mac-nodrop +45 -0
  19. data/bin/port-shutdown +78 -0
  20. data/bin/setup +8 -0
  21. data/lib/netutils.rb +118 -0
  22. data/lib/netutils/arp.rb +28 -0
  23. data/lib/netutils/cli.rb +702 -0
  24. data/lib/netutils/cli/alaxala.rb +121 -0
  25. data/lib/netutils/cli/alaxala/interface.rb +137 -0
  26. data/lib/netutils/cli/alaxala/lldp.rb +166 -0
  27. data/lib/netutils/cli/alaxala/macfib.rb +62 -0
  28. data/lib/netutils/cli/alaxala/showarp.rb +51 -0
  29. data/lib/netutils/cli/alaxala/showroute.rb +86 -0
  30. data/lib/netutils/cli/alaxala/showvrf.rb +46 -0
  31. data/lib/netutils/cli/aruba.rb +15 -0
  32. data/lib/netutils/cli/cisco.rb +45 -0
  33. data/lib/netutils/cli/cisco/cdp.rb +117 -0
  34. data/lib/netutils/cli/cisco/ifsummary.rb +32 -0
  35. data/lib/netutils/cli/cisco/interface.rb +67 -0
  36. data/lib/netutils/cli/cisco/macfib.rb +38 -0
  37. data/lib/netutils/cli/cisco/showarp.rb +27 -0
  38. data/lib/netutils/cli/cisco/showinterface.rb +27 -0
  39. data/lib/netutils/cli/cisco/showroute.rb +73 -0
  40. data/lib/netutils/cli/cisco/showvrf.rb +45 -0
  41. data/lib/netutils/cli/nec.rb +20 -0
  42. data/lib/netutils/cli/nec/lldp.rb +16 -0
  43. data/lib/netutils/cli/paloalto.rb +21 -0
  44. data/lib/netutils/fsm.rb +43 -0
  45. data/lib/netutils/macaddr.rb +51 -0
  46. data/lib/netutils/oncequeue.rb +78 -0
  47. data/lib/netutils/parser.rb +30 -0
  48. data/lib/netutils/rib.rb +80 -0
  49. data/lib/netutils/switch.rb +402 -0
  50. data/lib/netutils/tunnel.rb +8 -0
  51. data/lib/netutils/version.rb +3 -0
  52. data/lib/netutils/vrf.rb +42 -0
  53. data/log/.gitignore +1 -0
  54. data/netutils.gemspec +33 -0
  55. 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,16 @@
1
+ module NEC
2
+
3
+ # IX series does not have LLDP and this is dummy class.
4
+ class LLDP
5
+ def cmd(port)
6
+ ''
7
+ end
8
+
9
+ def initialize(sw)
10
+ end
11
+
12
+ def parse(l)
13
+ end
14
+ end
15
+
16
+ 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
@@ -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