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,51 @@
1
+ require 'netutils/parser'
2
+ require 'netutils/arp'
3
+
4
+ module Alaxala
5
+
6
+ class ShowARP < Parser
7
+ attr_reader :arps
8
+
9
+ def initialize
10
+ @arps = ARPTable.new
11
+ super
12
+ # Date 2017/10/05 21:30:53 JST
13
+ add('Init', :init, /^Date/)
14
+ # VRF: 1 Total: 946 entries
15
+ add('VRF', :vrf, /^VRF/)
16
+ # IP Address Linklayer Address Netif Expire Type
17
+ add('Title', :title, /^(?: IP Address Linklayer Address Netif Expire Type|There is no ARP entry.)/)
18
+ # 192.168.0.1 dead.beaf.dead VLAN9999 4m58s arpa
19
+ add('Entry', :entry, /^\s+([0-9\.]+)\s+([0-9a-f\.]+|\(incomplete\))\s+([^\s]+)\s+([^\s]+).*$/)
20
+ end
21
+
22
+ def init(l, m)
23
+ # XXX: VRF appears if and only if an IP address is given.
24
+ #changeto('VRF')
25
+ changeto('Title')
26
+ end
27
+
28
+ def vrf(l, m)
29
+ changeto('Title')
30
+ end
31
+
32
+ def title(l, m)
33
+ changeto('Entry')
34
+ end
35
+
36
+ def entry(l, m)
37
+ #
38
+ # remove mediate ``0''s because Alaxala CLI may to accept such
39
+ # interface name like ``VLAN0620.''
40
+ #
41
+ if m[3] =~ /^([^0-9]+)0+([0-9]+)$/
42
+ interface = "#{$1}#{$2}"
43
+ else
44
+ interface = m[3]
45
+ end
46
+ return if m[2] === '(incomplete)'
47
+ @arps.add(m[1], m[2].downcase, interface, m[4] === 'Static')
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1,86 @@
1
+ require 'netutils/parser'
2
+ require 'netutils/rib'
3
+
4
+ module Alaxala
5
+
6
+ class ShowRoute < Parser
7
+ attr_reader :rib
8
+
9
+ def cmd(ia)
10
+ "show ip route vrf all #{ia}"
11
+ end
12
+
13
+ def initialize
14
+ @rib = RIB.new
15
+ super
16
+ # Route 10/8 , VRF 2
17
+ add('Init', :init)
18
+ # AX8600
19
+ # Entries 1
20
+ # AX3600
21
+ # Entries 1 Announced 1 Depth 0 <>
22
+ add('Entries', :entries, /^Entries [0-9]+.*$/)
23
+ # empty line
24
+ add('Empty', :empty, /^$/)
25
+ # * NextHop 192.168.0.1 , Interface : VLAN9999
26
+ add('Nexthop', :nexthop, /^..NextHop ([^\s]+)\s*, Interface\s*: ([^\s]+)\s*$/)
27
+ # Protocol <OSPF inter>
28
+ add('Protocol', :protocol, /^ Protocol <([^>]+)>/)
29
+ #
30
+ add('Skip', :skip)
31
+ end
32
+
33
+ def init(l, m)
34
+ return if l =~ /^$/
35
+ return if l !~ /^Route ([0-9\.\/]+)\s*, VRF ([0-9]+|global)$/
36
+ @dst = $1
37
+ @vrf = $1
38
+ changeto('Entries')
39
+ end
40
+
41
+ def entries(l, m)
42
+ changeto('Empty')
43
+ end
44
+
45
+ def empty(l, m)
46
+ changeto('Nexthop')
47
+ end
48
+
49
+ def nexthop(l, m)
50
+ @nh = m[1]
51
+ @interface = m[2]
52
+ #
53
+ # remove mediate ``0''s because Alaxala CLI may to accept such
54
+ # interface name like ``VLAN0999.''
55
+ #
56
+ @interface = "#{$1}#{$2}" if @interface =~ /^([^0-9]+)0+([0-9]+)$/
57
+ changeto('Protocol')
58
+ end
59
+
60
+ def protocol(l, m)
61
+ case m[1]
62
+ when /^Static/
63
+ @protocol = 'static'
64
+ when /^Connected/
65
+ @protocol = 'connected'
66
+ when /^RIP/
67
+ @protocol = 'rip'
68
+ when /^OSPF/
69
+ @protocol = 'ospf'
70
+ when /^BGP/
71
+ @protocol = 'bgp'
72
+ when /^Extra-VRF/
73
+ @protocol = 'extranet'
74
+ else
75
+ raise(ArgumentError, "Invalid routing protocol: #{m[1]}")
76
+ end
77
+ @rib.add(@protocol, @dst, @nh, @interface)
78
+ changeto('Skip')
79
+ end
80
+
81
+ def skip(l, m)
82
+ changeto('Init') if l =~ /^$/
83
+ end
84
+ end
85
+
86
+ end
@@ -0,0 +1,46 @@
1
+ require 'netutils/parser'
2
+ require 'netutils/vrf'
3
+
4
+ module Alaxala
5
+
6
+ class ShowVRF < Parser
7
+ attr_reader :vrfs
8
+
9
+ DUMMY_RD = '0:0' # XXX: Alaxala do not have RD...
10
+
11
+ def cmd
12
+ # XXX: we do not use interfaces for now...
13
+ return 'show ip vrf all'
14
+ end
15
+
16
+ def initialize
17
+ super
18
+ @vrfs = VRFTable.new
19
+ # Date 2017/10/05 21:11:51 JST
20
+ add('Init', :init, /^Date/)
21
+ # VRF Routes ARP
22
+ add('Title', :title, /^VRF/)
23
+ # global 7/- 0/-
24
+ # 1 235/- 949/-
25
+ add('VRF', :vrf)
26
+ end
27
+
28
+ def init(l, m)
29
+ changeto('Title')
30
+ end
31
+
32
+ def title(l, m)
33
+ changeto('VRF')
34
+ end
35
+
36
+ def vrf(l, m)
37
+ if l !~ /^(global|[0-9]+)\s+.*$/
38
+ raise(ArgumentError, "Invalid line: \"#{l}\"")
39
+ end
40
+ name = $1
41
+ name = 'default' if name === 'global'
42
+ @vrf = vrfs.add(name, DUMMY_RD)
43
+ end
44
+ end
45
+
46
+ end
@@ -0,0 +1,15 @@
1
+ module Aruba
2
+ CONFIG_RE = /^Building Configuration...[^a-zA-Z]+(.*end\n)$/m
3
+
4
+ def disable_logging_console
5
+ # XXX
6
+ end
7
+
8
+ def show_running_config
9
+ return cmd('show running-config')
10
+ end
11
+
12
+ def interface_gets(sw)
13
+ # XXX
14
+ end
15
+ end
@@ -0,0 +1,45 @@
1
+ require 'netutils/cli/cisco/interface'
2
+ require 'netutils/cli/cisco/cdp'
3
+ require 'netutils/cli/cisco/macfib'
4
+ require 'netutils/cli/cisco/showarp'
5
+ require 'netutils/cli/cisco/showroute'
6
+ require 'netutils/cli/cisco/showvrf'
7
+
8
+ module Cisco
9
+ CONFIG_RE = /^.*Current configuration[^\n]+\n(.*)\n.*$/m
10
+
11
+ def disable_logging_console
12
+ configure
13
+ cmd('no loggin console')
14
+ unconfigure
15
+ end
16
+
17
+ def acl_definition(type, name)
18
+ case type
19
+ when 'ip'
20
+ when 'mac'
21
+ "#{type} access-list extended #{name}"
22
+ else
23
+ raise(ArgumentError, "Unsupported ACL type: #{type}")
24
+ end
25
+ end
26
+
27
+ def acl_type_to_cmd(type)
28
+ case type
29
+ when 'ip'
30
+ when 'mac'
31
+ #
32
+ # we here use only ``mac'' even though mac-ip and
33
+ # mac-ipv6 are available.
34
+ #
35
+ type = 'mac'
36
+ else
37
+ raise(ArgumentError, "Unsupported ACL type: #{type}")
38
+ end
39
+ type
40
+ end
41
+
42
+ def show_running_config
43
+ return cmd('show running-config')
44
+ end
45
+ end
@@ -0,0 +1,117 @@
1
+ require 'netutils/parser'
2
+
3
+ module Cisco
4
+
5
+ class CDP < Parser
6
+ def cmd(port = nil)
7
+ port = "#{port} " if port
8
+ return "show cdp neighbors #{port}detail"
9
+ end
10
+
11
+ attr_reader :rsw, :ias # XXX
12
+ def initialize(sw)
13
+ super()
14
+ add('Init', :init)
15
+ add('DeviceID', :device_id, /^Device ID: (.*)$/)
16
+ add('EntryAddrs', :entry_addrs,
17
+ /^Entry address\(es\): $/)
18
+ add('EntryAddr', :entry_addr)
19
+ add('Interface', :interface,
20
+ /^Interface: (.*), Port ID \(outgoing port\): (.*)$/)
21
+ add('Ignore', :ignore)
22
+ add('Firmware', :firmware)
23
+ add('MngAddr', :mng_addr)
24
+
25
+ @sw = sw
26
+ end
27
+
28
+ private
29
+
30
+ def init(l, m)
31
+ return unless l =~ /^-{25}$/
32
+ @rdevid = nil
33
+ @ias = Array.new
34
+ @platform = nil
35
+ @lport = nil
36
+ @rport = nil
37
+ @firmware = ''
38
+ @mngias = Array.new
39
+ @type = Switch::Type::UNKNOWN
40
+ changeto('DeviceID')
41
+ end
42
+
43
+ def device_id(l, m)
44
+ @rdevid = m[1]
45
+ changeto('EntryAddrs')
46
+ end
47
+
48
+ def entry_addrs(l, m)
49
+ changeto('EntryAddr')
50
+ end
51
+
52
+ def entry_addr(l, m)
53
+ unless l =~ /^ +[^:]+: (.*)$/
54
+ platform(l)
55
+ else
56
+ @ias.push($1)
57
+ end
58
+ end
59
+
60
+ def platform(l)
61
+ unless l =~ /^Platform: ([^,]+), Capabilities: (.*)$/
62
+ raise(ArgumentError)
63
+ end
64
+ @platform = $1.strip
65
+ cap = $2
66
+ if cap =~ /Router/
67
+ @type = Switch::Type::ROUTER
68
+ elsif cap =~ /Switch/
69
+ @type = Switch::Type::SWITCH
70
+ elsif cap =~ /Trans-Bridge/
71
+ @type = Switch::Type::BRIDGE
72
+ elsif cap =~ /Host/
73
+ @type = Switch::Type::HOST
74
+ end
75
+ changeto('Interface')
76
+ end
77
+
78
+ def interface(l, m)
79
+ @lport = m[1]
80
+ @rport = m[2]
81
+ changeto('Ignore')
82
+ end
83
+
84
+ def ignore(l, m)
85
+ changeto('Firmware') if l =~ /^Version :$/
86
+ changeto('MngAddr') if l =~ /^Management address\(es\): $/
87
+ end
88
+
89
+ def firmware(l, m)
90
+ if l =~ /^advertisement version: .*$/
91
+ @firmware.strip!
92
+ changeto('Ignore')
93
+ else
94
+ @firmware += l
95
+ end
96
+ end
97
+
98
+ def mng_addr(l, m)
99
+ if l=~ /^ [^:]+: (.*)$/
100
+ @mngias.push($1)
101
+ else
102
+ ia = @mngias[0]
103
+ ia = @ias[0] if ia == nil
104
+ if @firmware =~ /^.*Copyright \(c\) .*([0-9]{4}) .*$/
105
+ time = $1
106
+ else
107
+ time = 'unknown'
108
+ end
109
+ @rsw = Switch.get(@rdevid, @type, @platform, @firmware,
110
+ time, ia)
111
+ @sw.ports[@lport].peers.add(@rsw, @rport)
112
+ changeto('Init')
113
+ end
114
+ end
115
+ end
116
+
117
+ end
@@ -0,0 +1,32 @@
1
+ require 'netutils/parser'
2
+
3
+ module Cisco
4
+
5
+ class IfSummary < Parser
6
+ def cmd
7
+ 'show interfaces summary'
8
+ end
9
+
10
+ def initialize(sw)
11
+ super()
12
+ add('Init', :init)
13
+ add('Interface', :interface)
14
+ @sw = sw
15
+ end
16
+
17
+ def init(l, m)
18
+ changeto('Interface') if l =~ /^-+$/
19
+ end
20
+
21
+ def interface(l, m)
22
+ return unless l =~ /^(.) ([^ ]+) +.*$/
23
+ up = $1
24
+ name = $2
25
+ return if name =~ /Port-channel/
26
+ return if name =~ /Vlan/
27
+ return if ! @sw.ports.exists?(name)
28
+ @sw.ports[name].up = up == '*' ? true : false
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,67 @@
1
+ require 'netutils/parser'
2
+
3
+ module Cisco
4
+
5
+ class Interface < Parser
6
+ def cmd
7
+ return 'show interfaces capabilities'
8
+ end
9
+
10
+ def initialize(sw)
11
+ super()
12
+ add('Init', :init)
13
+ add('Name', :name, /^ +Model: +(.+)$/)
14
+ add('Model', :model, /^ +Type: +(.+)$/)
15
+ add('Type', :type)
16
+ add('Speed', :speed, /^ +Duplex: +(.+)$/)
17
+ @sw = sw
18
+ end
19
+
20
+ private
21
+
22
+ def init(l, m)
23
+ return unless l =~ /^([^ ]+)$/
24
+ @name = $1
25
+ @model = nil
26
+ @type = nil
27
+ @speed = nil
28
+ @duplex = nil
29
+ changeto('Name')
30
+ end
31
+
32
+ def name(l, m)
33
+ @model = m[1]
34
+ changeto('Model')
35
+ end
36
+
37
+ def model(l, m)
38
+ @type = m[1]
39
+ changeto('Type')
40
+ end
41
+
42
+ def type(l, m)
43
+ if l =~ /^ +Speed: +(.+)$/
44
+ @speed = m[1]
45
+ changeto('Speed')
46
+ else
47
+ @speed = 'unknown'
48
+ done
49
+ end
50
+ end
51
+
52
+ def speed(l, m)
53
+ @duplex = m[1]
54
+ done
55
+ end
56
+
57
+ def done
58
+ changeto('Init')
59
+ return if @model === 'not applicable' # port-channel
60
+ return if @model === 'N/A' # port-channel
61
+ return if @type === 'WiSM'
62
+ return if @type === 'unknown' # port-channel
63
+ @sw.ports.add(@name, @model, @type, @speed, @duplex)
64
+ end
65
+ end
66
+
67
+ end