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.
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