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,121 @@
|
|
1
|
+
require 'netutils/cli/alaxala/interface'
|
2
|
+
require 'netutils/cli/alaxala/lldp'
|
3
|
+
require 'netutils/cli/alaxala/macfib'
|
4
|
+
require 'netutils/cli/alaxala/showarp'
|
5
|
+
require 'netutils/cli/alaxala/showroute'
|
6
|
+
require 'netutils/cli/alaxala/showvrf'
|
7
|
+
|
8
|
+
module Alaxala
|
9
|
+
CONFIG_RE = /\A((?:#configuration list for [^\n]+|#Last modified [^\n]+)\n.*)\n\Z/m
|
10
|
+
|
11
|
+
def disable_logging_console
|
12
|
+
case @product
|
13
|
+
when /^AX86[0-9]{2}/
|
14
|
+
# AX8600
|
15
|
+
configure
|
16
|
+
cmd('username default_user logging-console event-level 0')
|
17
|
+
unconfigure
|
18
|
+
when /^AX22[0-9]{2}/
|
19
|
+
# XXX: AX2230 seems not to have set logging commands...
|
20
|
+
when /^AX[23][0-9]{2,3}/
|
21
|
+
# AX3800, AX3600, AX2500, AX260
|
22
|
+
for level in 3..9
|
23
|
+
cmd("set logging console disable E#{level}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def interface_name(sw, name)
|
29
|
+
if name =~ /^Port\s+(.*)$/i
|
30
|
+
name = $1
|
31
|
+
elsif name =~ /^[^\s0-9]/
|
32
|
+
return name
|
33
|
+
end
|
34
|
+
numbers = name.delete(' ').split('/')
|
35
|
+
sw.ports.each do |port|
|
36
|
+
return port.name.to_s if port.name.numbers == numbers
|
37
|
+
if sw.product =~ /^AX3[0-9]{3}/ &&
|
38
|
+
port.name.numbers.size === 3 &&
|
39
|
+
numbers.size === 2 &&
|
40
|
+
port.name.numbers.drop(1) == numbers
|
41
|
+
return port.name.to_s
|
42
|
+
end
|
43
|
+
end
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def interface_name_cli(name)
|
48
|
+
name.split(' ')[1]
|
49
|
+
end
|
50
|
+
|
51
|
+
def unconfigure
|
52
|
+
cmd('save')
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# XXX: forcely override method because Alaxala
|
58
|
+
# interface command accept lower case characters only...
|
59
|
+
# e.g., GigabitEthernet should be gigabitethernet...
|
60
|
+
#
|
61
|
+
def interface_name_interface_command(port)
|
62
|
+
port.downcase
|
63
|
+
end
|
64
|
+
private :interface_name_interface_command
|
65
|
+
|
66
|
+
def interface_shutdown(port)
|
67
|
+
super(interface_name_interface_command(port))
|
68
|
+
end
|
69
|
+
|
70
|
+
def interface_noshutdown(port)
|
71
|
+
super(interface_name_interface_command(port))
|
72
|
+
end
|
73
|
+
|
74
|
+
def acl_definition(type, name)
|
75
|
+
case type
|
76
|
+
when 'ip'
|
77
|
+
when 'mac'
|
78
|
+
"#{type} access-list extended #{name}"
|
79
|
+
when 'advance' # XXX: AX8600 only
|
80
|
+
"#{type} access-list #{name}"
|
81
|
+
else
|
82
|
+
raise(ArgumentError, "Unsupported ACL type: #{type}")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def acl_type_to_cmd(type)
|
87
|
+
case type
|
88
|
+
when 'ip'
|
89
|
+
when 'mac'
|
90
|
+
when 'advance' # XXX: AX8600 only
|
91
|
+
#
|
92
|
+
# we here use only ``mac'' even though mac-ip and
|
93
|
+
# mac-ipv6 are available.
|
94
|
+
#
|
95
|
+
type = 'mac'
|
96
|
+
else
|
97
|
+
raise(ArgumentError, "Unsupported ACL type: #{type}")
|
98
|
+
end
|
99
|
+
type
|
100
|
+
end
|
101
|
+
|
102
|
+
def show_running_config
|
103
|
+
return cmd('show running-config')
|
104
|
+
end
|
105
|
+
|
106
|
+
def syslog(host, vrf = 1)
|
107
|
+
configure
|
108
|
+
case @product
|
109
|
+
when /^AX86[0-9]{2}/
|
110
|
+
# AX8600
|
111
|
+
cmd("logging syslog-host #{host} vrf #{vrf} no-date-info")
|
112
|
+
when /^AX(?:25[0-9]{2}|3[0-9]{3})/
|
113
|
+
# AX2500, AX3000
|
114
|
+
cmd("logging host #{host} no-date-info")
|
115
|
+
when /^AX22[0-9]{2}/
|
116
|
+
# AX2230
|
117
|
+
cmd("logging host #{host}")
|
118
|
+
end
|
119
|
+
unconfigure
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'netutils/parser'
|
2
|
+
|
3
|
+
module Alaxala
|
4
|
+
|
5
|
+
class Interface < Parser
|
6
|
+
def cmd
|
7
|
+
return 'show port'
|
8
|
+
end
|
9
|
+
|
10
|
+
# AX2500
|
11
|
+
# Date 2017/10/14 21:00:10 JST
|
12
|
+
# Port Counts: 52
|
13
|
+
# Port Name Status Speed Duplex FCtl FrLen ChGr/Status
|
14
|
+
# 0/1 geth0/1 down - - - - -/-
|
15
|
+
# 0/2 geth0/2 down - - - - -/-
|
16
|
+
|
17
|
+
# AX2200
|
18
|
+
# Date 2017/10/14 20:47:34 JST
|
19
|
+
# Port Counts: 28
|
20
|
+
# Port Name Status Speed Duplex FCtl FrLen ChGr/Status
|
21
|
+
# 0/1 gigaether0/1 up 1000BASE-T full(auto) off 1518 -/-
|
22
|
+
# 0/2 gigaether0/2 up 1000BASE-T full(auto) off 1518 -/-
|
23
|
+
|
24
|
+
# AX3800 (stack)
|
25
|
+
# Switch 1 (Master)
|
26
|
+
# -----------------
|
27
|
+
# Date 2017/10/15 23:10:44 JST
|
28
|
+
# Port Counts: 48
|
29
|
+
# Port Name Status Speed Duplex FCtl FrLen ChGr/Status
|
30
|
+
# 0/ 1 tengeth1/0/1 up 10GBASE-SR full off 1518 1/up
|
31
|
+
# 0/ 2 tengeth1/0/2 up 10GBASE-SR full off 1518 2/up
|
32
|
+
#
|
33
|
+
#
|
34
|
+
# Switch 2 (Backup)
|
35
|
+
# -----------------
|
36
|
+
# Date 2017/10/15 23:10:44 JST
|
37
|
+
# Port Counts: 48
|
38
|
+
# Port Name Status Speed Duplex FCtl FrLen ChGr/Status
|
39
|
+
# 0/ 1 tengeth2/0/1 up 10GBASE-SR full off 1518 1/-
|
40
|
+
# 0/ 2 tengeth2/0/2 up 10GBASE-SR full off 1518 2/-
|
41
|
+
|
42
|
+
# AX8600
|
43
|
+
# Date 2017/10/14 20:16:41 JST
|
44
|
+
# Port Counts: 54
|
45
|
+
# Port Status Speed Duplex FCtl FrLen Description
|
46
|
+
# 1/1 up 10GBASE-SR full off 1518 hogehoge
|
47
|
+
# 1/2 up 10GBASE-SR full off 1518 fugafuga
|
48
|
+
PORT_RE = /^\s*([0-9\/\s]+)\s+([^\s]*)\s*(up|down|dis|inact|init)\s+([^\s]+)\s+(full|half|-)(?:\(auto\))?\s+(on|off|-)\s+(?:[0-9]+|-)\s+.*$/
|
49
|
+
|
50
|
+
def initialize(sw)
|
51
|
+
super()
|
52
|
+
add('Init', :init)
|
53
|
+
add('Date', :date, /^Port Counts:.*$/)
|
54
|
+
add('Count', :count, /^Port\s+(?:Name|Status).*$/)
|
55
|
+
add('Port', :port)
|
56
|
+
@sw = sw
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def init(l, m)
|
62
|
+
case l
|
63
|
+
when /^Date/
|
64
|
+
changeto('Date')
|
65
|
+
when /^Switch/
|
66
|
+
when /^-------/
|
67
|
+
when /^$/
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def date(l, m)
|
72
|
+
changeto('Count')
|
73
|
+
end
|
74
|
+
|
75
|
+
def count(l, m)
|
76
|
+
changeto('Port')
|
77
|
+
end
|
78
|
+
|
79
|
+
def port_name_normalize(port0, name, speed)
|
80
|
+
port0.delete!(' ')
|
81
|
+
# XXX: should check actual port capability...
|
82
|
+
if ! name || name.empty?
|
83
|
+
case speed
|
84
|
+
when /^(10|100|1000)BASE/
|
85
|
+
name = 'Gigabit'
|
86
|
+
when /^10GBASE/
|
87
|
+
name = 'TenG'
|
88
|
+
when /^40GBASE/
|
89
|
+
name = 'FortyG'
|
90
|
+
when /^100GBASE/
|
91
|
+
name = 'HundredG'
|
92
|
+
when '-'
|
93
|
+
else
|
94
|
+
raise "Unknown Speed: #{speed}"
|
95
|
+
end
|
96
|
+
elsif @sw.product =~ /^AX3[0-9]{3}/
|
97
|
+
#
|
98
|
+
# AX3000 series uses 3 numbers for port numbers
|
99
|
+
# in many commands of CLI but ``show port''
|
100
|
+
# command returns 2 numbers only like below.
|
101
|
+
#
|
102
|
+
# 0/23 tengeth1/0/23 up 1000BASE-SX...
|
103
|
+
#
|
104
|
+
if name !~ /^[a-z]+([0-9\/]+)$/
|
105
|
+
raise "Invalid port format: \"#{name}\""
|
106
|
+
end
|
107
|
+
port0 = $1
|
108
|
+
end
|
109
|
+
case name
|
110
|
+
when /^TenG/i
|
111
|
+
prefix = 'Ten'
|
112
|
+
when /^FourtyG/i
|
113
|
+
prefix = 'Fourty'
|
114
|
+
when /^HundredG/i
|
115
|
+
prefix = 'Hundred'
|
116
|
+
else
|
117
|
+
prefix = ''
|
118
|
+
end
|
119
|
+
return "#{prefix}GigabitEthernet #{port0}"
|
120
|
+
end
|
121
|
+
|
122
|
+
def port(l, m)
|
123
|
+
if l =~ /^Switch/
|
124
|
+
changeto('Init')
|
125
|
+
return
|
126
|
+
end
|
127
|
+
return if l =~ /^$/ # AX2500, or others...
|
128
|
+
if l !~ PORT_RE
|
129
|
+
raise "CLI invalid format of port: #{l}"
|
130
|
+
end
|
131
|
+
name = port_name_normalize($1, $2, $4)
|
132
|
+
@sw.ports.add(name, nil, $4, $4, $5)
|
133
|
+
@sw.ports[name].up = $3 == 'up'
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'netutils/parser'
|
2
|
+
require 'netutils/switch'
|
3
|
+
|
4
|
+
module Alaxala
|
5
|
+
|
6
|
+
class LLDP < Parser
|
7
|
+
def cmd(port)
|
8
|
+
if port
|
9
|
+
port = @sw.interface_name_cli(port)
|
10
|
+
# XXX: how about stack configuration...
|
11
|
+
if @sw.product =~ /^AX3[0-9]{3}/
|
12
|
+
numbers = port.split('/')
|
13
|
+
if numbers.size != 3
|
14
|
+
raise "Invalid port format: #{numbers}"
|
15
|
+
end
|
16
|
+
port = "#{numbers[1]}/#{numbers[2]}"
|
17
|
+
end
|
18
|
+
port = "port #{port} "
|
19
|
+
end
|
20
|
+
return "show lldp #{port}detail"
|
21
|
+
end
|
22
|
+
|
23
|
+
# Date 2017/10/15 00:06:36 JST
|
24
|
+
# Status: Enabled Chassis ID: Type=MAC Info=beef.dad.beef
|
25
|
+
# Interval Time: 30 Hold Count: 4 TTL: 121 Draft TTL: 120
|
26
|
+
# System Name: hogehoge
|
27
|
+
# System Description: ALAXALA AX8600S AX-8600-S16 [AX8616S] Switching software (including encryption) Ver. 12.7.B [OS-SE]
|
28
|
+
# Neighbor Counts=1
|
29
|
+
# Draft Neighbor Counts=0
|
30
|
+
# Port Counts=1
|
31
|
+
# Port 1/ 1(CH: 1)
|
32
|
+
# Link: Up PortEnabled: TRUE AdminStatus: enabledRxTx
|
33
|
+
# Neighbor Counts: 1 Draft Neighbor Counts: 0
|
34
|
+
# Port ID: Type=MAC Info=beef.dead.beef
|
35
|
+
# Port Description: hogehoge
|
36
|
+
# Neighbor 1 TTL: 95
|
37
|
+
# Chassis ID: Type=MAC Info=dead.beef.dead
|
38
|
+
# System Name: fugafuga
|
39
|
+
# System Description: ALAXALA AX2530 AX-2530-48T2X-B [AX2530S-48T2X] Switching software Ver. 4.6.A [OS-L2B]
|
40
|
+
# Port ID: Type=MAC Info=dead.beef.dead
|
41
|
+
# Port Description: hogehoge
|
42
|
+
|
43
|
+
attr_reader :rsw
|
44
|
+
def initialize(sw)
|
45
|
+
super()
|
46
|
+
add('Init', :init)
|
47
|
+
add('Port', :port)
|
48
|
+
add('PortInfo', :port_info)
|
49
|
+
add('ChassisID', :chassis_id, /^ Chassis ID: Type=[^\s]+ \s+Info=[0-9a-z.]+$/)
|
50
|
+
add('SystemName', :system_name, /^\s{4,6}System Name: ([^\s]+)$/)
|
51
|
+
add('SystemDescription',:system_description, /^\s{4,6}System Description: (.*)$/)
|
52
|
+
add('PortID', :port_id)
|
53
|
+
add('PortDescription', :port_description, /^\s{4,6}Port Description: .*$/)
|
54
|
+
add('TagID', :tag_id)
|
55
|
+
@sw = sw
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def init(l, m)
|
61
|
+
changeto('Port') if l =~ /^Port Counts.*$/
|
62
|
+
end
|
63
|
+
|
64
|
+
def port(l, m)
|
65
|
+
raise 'Invalid format' if l !~ /^Port\s+([0-9\s\/]+).*$/
|
66
|
+
@lport = @sw.interface_name($1)
|
67
|
+
changeto('PortInfo')
|
68
|
+
end
|
69
|
+
|
70
|
+
def port_info(l, m)
|
71
|
+
if l =~ /^ (?:Draft Neighbor|Neighbor)\s+[0-9]+\s+TTL: [0-9]+\s*.*$/
|
72
|
+
neighbor(l, m)
|
73
|
+
elsif l =~ /^ [0-9]+\s+TTL:\s*[0-9]+\s+Chassis ID: Type=[^\s]+\s+Info=[0-9a-z.]+$/
|
74
|
+
neighbor_ax3000(l, m)
|
75
|
+
elsif l =~ /^Port/
|
76
|
+
port(l, m)
|
77
|
+
else
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def neighbor(l, m)
|
82
|
+
@rname = nil
|
83
|
+
changeto('ChassisID')
|
84
|
+
end
|
85
|
+
|
86
|
+
def neighbor_ax3000(l, m)
|
87
|
+
@rname = nil
|
88
|
+
changeto('SystemName')
|
89
|
+
end
|
90
|
+
|
91
|
+
def chassis_id(l, m)
|
92
|
+
changeto('SystemName')
|
93
|
+
end
|
94
|
+
|
95
|
+
def system_name(l, m)
|
96
|
+
@rname = m[1]
|
97
|
+
changeto('SystemDescription')
|
98
|
+
end
|
99
|
+
|
100
|
+
def system_description(l, m)
|
101
|
+
desc = m[1]
|
102
|
+
case desc
|
103
|
+
when /^(ALAXALA.*) Switching software Ver. (.*)$/
|
104
|
+
platform = $1
|
105
|
+
firmware = $2
|
106
|
+
else
|
107
|
+
platform = desc
|
108
|
+
firmware = nil
|
109
|
+
end
|
110
|
+
case platform
|
111
|
+
when /Cisco*/,
|
112
|
+
/^ALAXALA AX[87643]/, /ALAXALA AX2[0-9]{2}[^0-9]/
|
113
|
+
type = Switch::Type::ROUTER
|
114
|
+
when /^ALAXALA AX[12][0-9]{3}[^0-9]/
|
115
|
+
type = Switch::Type::SWITCH
|
116
|
+
# elsif /XXX/
|
117
|
+
# type = Switch::Type::BRIDGE
|
118
|
+
else
|
119
|
+
type = Switch::Type::HOST
|
120
|
+
end
|
121
|
+
neighbor_add(@lport, @rname, type, platform, firmware)
|
122
|
+
changeto('PortID')
|
123
|
+
end
|
124
|
+
|
125
|
+
def port_id(l, m)
|
126
|
+
# XXX: this may be left system description.
|
127
|
+
return if l !~ /^\s{4,6}Port ID: Type=[^\s]+ \s+Info=.*+$/
|
128
|
+
changeto('PortDescription')
|
129
|
+
end
|
130
|
+
|
131
|
+
def port_description(l, m)
|
132
|
+
changeto('TagID')
|
133
|
+
end
|
134
|
+
|
135
|
+
def tag_id(l, m)
|
136
|
+
case l
|
137
|
+
when /^Port+/
|
138
|
+
if ! @rsw.ia
|
139
|
+
raise "no IP address found for #{@rsw.name} "
|
140
|
+
"on #{@sw.name} #{@lport}"
|
141
|
+
end
|
142
|
+
port(l, m)
|
143
|
+
when /^ [^\s]+/
|
144
|
+
port_info(l, m)
|
145
|
+
when /^\s{4,6}Tag ID: .*$/
|
146
|
+
return
|
147
|
+
when /^\s{4,6}IPv4 Address: (?:Untagged|Tagged:\s+[0-9]+)\s+([0-9.]+)$/,
|
148
|
+
/^\s{4,6}Management Address:\s+([0-9.]+)$/
|
149
|
+
@rsw.ip_address_set($1)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def neighbor_add(lport, rname, type, platform, firmware)
|
154
|
+
# XXX: this is valid for cisco only...
|
155
|
+
if firmware =~ /^.*Copyright \(c\) .*([0-9]{4}) .*$/
|
156
|
+
time = $1
|
157
|
+
else
|
158
|
+
time = 'unknown'
|
159
|
+
end
|
160
|
+
static_neighbor_resolve(@sw.name, lport)
|
161
|
+
@rsw = Switch.get(rname, type, platform, firmware, time)
|
162
|
+
@sw.ports[lport].peers.add(@rsw, nil) # XXX: no way to know remote port...
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'netutils/parser'
|
2
|
+
require 'netutils/macaddr'
|
3
|
+
|
4
|
+
module Alaxala
|
5
|
+
|
6
|
+
class MACFIB < Parser
|
7
|
+
attr_reader :ports
|
8
|
+
|
9
|
+
#
|
10
|
+
# Date 2017/10/15 08:24:22 JST
|
11
|
+
# Aging time : 300
|
12
|
+
# MAC address VLAN Type Port-list
|
13
|
+
# dead.beef.dead 9999 Dynamic 0/26-27
|
14
|
+
#
|
15
|
+
AX2000_RE = /^[0-9a-z.]+\s+[0-9]+\s+[^\s]+\s+([0-9\/,\-]+)$/
|
16
|
+
|
17
|
+
# Date 2017/10/14 19:39:20 JST
|
18
|
+
# MAC address VLAN C-Tag Aging-Time Type Port-list
|
19
|
+
# dead.beef.dead 9999 - 479 Dynamic 7/5,11/5
|
20
|
+
AX8600_RE = /^[0-9a-z.]+\s+[0-9]+\s+[^\s]+\s+[0-9]+\s+[^\s]+\s+([0-9\/,\-]+)$/
|
21
|
+
|
22
|
+
def cmd(ma, vlan)
|
23
|
+
mac = "mac " if @sw.product =~ /^AX2[0-9]{3}/
|
24
|
+
return "show mac-address-table #{mac}#{ma.to_s} vlan #{vlan}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(sw)
|
28
|
+
@ports = {}
|
29
|
+
super()
|
30
|
+
add('Init', :init)
|
31
|
+
@sw = sw
|
32
|
+
end
|
33
|
+
|
34
|
+
def init(l, m)
|
35
|
+
case l
|
36
|
+
# XXX: other switches...
|
37
|
+
when AX2000_RE, AX8600_RE
|
38
|
+
$1.split(',').each do |port|
|
39
|
+
port, last = port.split('-')
|
40
|
+
if port =~ /^(.*\/)([0-9]+)$/
|
41
|
+
prefix = $1
|
42
|
+
first = $2.to_i
|
43
|
+
else
|
44
|
+
raise(ArgumentError,
|
45
|
+
"Unknown port name format: #{port}")
|
46
|
+
end
|
47
|
+
if last
|
48
|
+
last = last.to_i
|
49
|
+
else
|
50
|
+
last = first
|
51
|
+
end
|
52
|
+
for i in first .. last do
|
53
|
+
name = prefix + i.to_s
|
54
|
+
name = @sw.interface_name(name)
|
55
|
+
@ports[name] = name
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|