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