cisco_node_utils 2.0.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +37 -0
- data/lib/cisco_node_utils/bfd_global.rb +4 -0
- data/lib/cisco_node_utils/cisco_cmn_utils.rb +25 -0
- data/lib/cisco_node_utils/cmd_ref/interface.yaml +18 -18
- data/lib/cisco_node_utils/cmd_ref/interface_channel_group.yaml +4 -1
- data/lib/cisco_node_utils/cmd_ref/interface_evpn_multisite.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +17 -15
- data/lib/cisco_node_utils/interface.rb +117 -118
- data/lib/cisco_node_utils/interface_channel_group.rb +17 -8
- data/lib/cisco_node_utils/interface_evpn_multisite.rb +15 -6
- data/lib/cisco_node_utils/interface_ospf.rb +126 -102
- data/lib/cisco_node_utils/itd_service.rb +8 -0
- data/lib/cisco_node_utils/node.rb +0 -1
- data/lib/cisco_node_utils/platform.rb +16 -32
- data/lib/cisco_node_utils/version.rb +1 -1
- data/lib/cisco_node_utils/vlan.rb +1 -2
- data/lib/cisco_node_utils/vxlan_vtep.rb +1 -1
- data/tests/test_interface.rb +74 -13
- data/tests/test_interface_bdi.rb +2 -2
- data/tests/test_interface_channel_group.rb +24 -17
- data/tests/test_interface_evpn_multisite.rb +35 -0
- data/tests/test_interface_ospf.rb +71 -3
- data/tests/test_itd_service.rb +16 -4
- data/tests/test_node_ext.rb +4 -1
- data/tests/test_portchannel_global.rb +3 -0
- data/tests/test_router_ospf_vrf.rb +2 -34
- data/tests/test_stp_global.rb +4 -0
- metadata +3 -6
- data/lib/cisco_node_utils/cmd_ref/DEPRECATED.yaml +0 -118
- data/lib/cisco_node_utils/interface_DEPRECATED.rb +0 -518
- data/lib/cisco_node_utils/vlan_DEPRECATED.rb +0 -108
@@ -376,6 +376,14 @@ module Cisco
|
|
376
376
|
end
|
377
377
|
# for boolean we need to do this
|
378
378
|
send('load_bal_enable=', false) if attrs[:load_bal_enable] == ''
|
379
|
+
if Platform.image_version[/9.3\(1\)/] && @set_args[:state] == 'no'
|
380
|
+
# In the 9.3(1) release image, the load_balance config cannot
|
381
|
+
# be removed using 'no load-balance'. It requires a valid
|
382
|
+
# parameter but it can be any parameter, even if not configured.
|
383
|
+
# For this version only we send the following command to
|
384
|
+
# remove load-balance config: 'no load-balance mask-position 0'
|
385
|
+
@set_args[:mask] = 'mask-position 0'
|
386
|
+
end
|
379
387
|
@get_args = @set_args
|
380
388
|
config_set('itd_service', 'load_balance', @set_args)
|
381
389
|
set_args_keys_default
|
@@ -35,13 +35,15 @@ module Cisco
|
|
35
35
|
# Ex: { 'n3000-uk9.6.0.2.U1.1.CSCaa12345.bin' => 'inactive committed',
|
36
36
|
# 'n3000-uk9.6.0.2.U1.1.CSCaa12346.bin' => 'active', }
|
37
37
|
def self.packages
|
38
|
+
pkgs = []
|
38
39
|
pkg_hsh = {}
|
39
|
-
|
40
|
+
begin
|
41
|
+
pkgs = config_get('images', 'packages')
|
42
|
+
rescue RuntimeError => e
|
43
|
+
raise unless e.message[/Invalid command/]
|
44
|
+
end
|
40
45
|
return {} if pkgs.nil?
|
41
46
|
pkgs.each { |p| pkg_hsh[p[0]] = p[1].downcase }
|
42
|
-
rescue RuntimeError => e
|
43
|
-
raise unless e.message[/Invalid command/]
|
44
|
-
ensure
|
45
47
|
pkg_hsh
|
46
48
|
end
|
47
49
|
|
@@ -103,7 +105,7 @@ module Cisco
|
|
103
105
|
# 'vid' => 'V02',
|
104
106
|
# 'sn' => 'SAL1812NTBP' }
|
105
107
|
def self.chassis
|
106
|
-
node.cache_flush # TODO: investigate why this is needed
|
108
|
+
# node.cache_flush # TODO: investigate why this is needed
|
107
109
|
all = config_get('inventory', 'chassis')
|
108
110
|
return nil if all.nil?
|
109
111
|
|
@@ -126,36 +128,18 @@ module Cisco
|
|
126
128
|
# 'sn' => 'SAL1812NTBP' },
|
127
129
|
# 'Slot 2' => { ... }}
|
128
130
|
def self.inventory_of(type)
|
129
|
-
node.cache_flush # TODO: investigate why this is needed
|
130
131
|
inv = config_get('inventory', 'all')
|
131
132
|
inv_hsh = {}
|
132
133
|
return inv_hsh if inv.nil?
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
inv_arr.each do |entry|
|
143
|
-
inv_hsh[entry[0]] = { 'descr' => entry[1],
|
144
|
-
'pid' => entry[2],
|
145
|
-
'vid' => entry[3],
|
146
|
-
'sn' => entry[4] }
|
147
|
-
end
|
148
|
-
else
|
149
|
-
# Nexus gets structured output
|
150
|
-
inv.select! { |x| x['name'].include? type }
|
151
|
-
return inv_hsh if inv.empty?
|
152
|
-
# match desired output format
|
153
|
-
inv.each do |s|
|
154
|
-
inv_hsh[s['name'].tr('"', '')] = { 'descr' => s['desc'].tr('"', ''),
|
155
|
-
'pid' => s['productid'],
|
156
|
-
'vid' => s['vendorid'],
|
157
|
-
'sn' => s['serialnum'] }
|
158
|
-
end
|
134
|
+
# Nexus gets structured output
|
135
|
+
inv_copy = inv.select { |x| x['name'].include? type }
|
136
|
+
return inv_hsh if inv_copy.empty?
|
137
|
+
# match desired output format
|
138
|
+
inv_copy.each do |s|
|
139
|
+
inv_hsh[s['name'].tr('"', '')] = { 'descr' => s['desc'].tr('"', ''),
|
140
|
+
'pid' => s['productid'],
|
141
|
+
'vid' => s['vendorid'],
|
142
|
+
'sn' => s['serialnum'] }
|
159
143
|
end
|
160
144
|
inv_hsh
|
161
145
|
end
|
@@ -14,7 +14,7 @@
|
|
14
14
|
|
15
15
|
# Container module for version number only.
|
16
16
|
module CiscoNodeUtils
|
17
|
-
VERSION = '2.0
|
17
|
+
VERSION = '2.1.0'
|
18
18
|
gem_version = Gem::Version.new(Gem::VERSION)
|
19
19
|
min_gem_version = Gem::Version.new('2.1.0')
|
20
20
|
fail 'Required rubygems version >= 2.1.0' if gem_version < min_gem_version
|
@@ -19,14 +19,13 @@ require_relative 'node_util'
|
|
19
19
|
require_relative 'interface'
|
20
20
|
require_relative 'fabricpath_global'
|
21
21
|
require_relative 'feature'
|
22
|
-
require_relative 'vlan_DEPRECATED'
|
23
22
|
|
24
23
|
# Add some Vlan-specific constants to the Cisco namespace
|
25
24
|
module Cisco
|
26
25
|
VLAN_NAME_SIZE = 33
|
27
26
|
|
28
27
|
# Vlan - node utility class for VLAN configuration management
|
29
|
-
class Vlan <
|
28
|
+
class Vlan < NodeUtil
|
30
29
|
attr_reader :vlan_id
|
31
30
|
|
32
31
|
def initialize(vlan_id, instantiate=true)
|
data/tests/test_interface.rb
CHANGED
@@ -161,6 +161,80 @@ class TestInterface < CiscoTestCase
|
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
164
|
+
def test_non_existent_intf
|
165
|
+
# pre-clean: remove intf if it exists
|
166
|
+
Interface.new('loopback100').destroy
|
167
|
+
|
168
|
+
# Create from non-exist
|
169
|
+
interface = Interface.new('loopback100')
|
170
|
+
refute_nil(interface.name)
|
171
|
+
interface.destroy
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_interface_apis
|
175
|
+
# N7K: verify show_name pattern
|
176
|
+
{
|
177
|
+
'etherNET1/1.42' => 'Ethernet1/1.42$',
|
178
|
+
'LOOPback23' => 'loopback23$',
|
179
|
+
'Port-Channel19' => 'port-channel19$',
|
180
|
+
'MONGOsonet12' => '.ongosonet12$',
|
181
|
+
}.each do |k, v|
|
182
|
+
assert_equal(v, Utils.normalize_intf_pattern(k),
|
183
|
+
"pattern should be #{v}")
|
184
|
+
end if node.product_id[/N7/]
|
185
|
+
|
186
|
+
# Verify intf counter
|
187
|
+
assert_equal(Interface.interface_count, interface_count,
|
188
|
+
'Interface.interface_count did not return the expected count')
|
189
|
+
|
190
|
+
# Verify raise rescued when loopback does not exist ('Invalid range' rescued)
|
191
|
+
Interface.new('loopback100').destroy
|
192
|
+
no_loopback = Interface.interfaces(nil, 'loopback100')
|
193
|
+
assert_empty(no_loopback,
|
194
|
+
'Return value should be empty hash when non existent loopback')
|
195
|
+
|
196
|
+
# Verify show_name usage
|
197
|
+
intf = interfaces[0]
|
198
|
+
one = Interface.interfaces(nil, intf)
|
199
|
+
assert_equal(1, one.length,
|
200
|
+
'Invalid number of keys returned, should be 1')
|
201
|
+
assert_equal(Utils.normalize_intf_pattern(intf), one[intf].show_name,
|
202
|
+
':show_name should be intf name when intf specified')
|
203
|
+
|
204
|
+
# Verify 'all' interfaces returned
|
205
|
+
all = Interface.interfaces
|
206
|
+
assert_operator(all.length, :>, 1,
|
207
|
+
'Invalid number of keys returned, should exceed 1')
|
208
|
+
assert_empty(all[intf].show_name,
|
209
|
+
':show_name should be empty string when intf is nil')
|
210
|
+
|
211
|
+
# Verify filter operations
|
212
|
+
eth_count = all.keys.join.scan(/ethernet/).count
|
213
|
+
filtered = Interface.interfaces(:ethernet)
|
214
|
+
assert_equal(eth_count, filtered.length,
|
215
|
+
'filter returned invalid number of ethernet interfaces')
|
216
|
+
|
217
|
+
filtered = Interface.interfaces(:mgmt)
|
218
|
+
assert_equal(1, filtered.length,
|
219
|
+
'filter returned invalid number of mgmt interfaces')
|
220
|
+
assert_equal('mgmt0', filtered.keys[0],
|
221
|
+
'filter returned incorrect interface name')
|
222
|
+
|
223
|
+
filtered = Interface.interfaces(:mgmt, intf)
|
224
|
+
assert_empty(filtered,
|
225
|
+
'mgmt filter returned interface when it should be an empty hash')
|
226
|
+
|
227
|
+
filtered = Interface.interfaces(:invalid_intf_pattern)
|
228
|
+
assert_empty(filtered,
|
229
|
+
'invalid filter returned interface when it should be an empty hash')
|
230
|
+
|
231
|
+
filtered = Interface.interfaces(:ethernet, intf)
|
232
|
+
assert_equal(1, filtered.length,
|
233
|
+
'Invalid number of keys returned by ethernet filter with intf specified')
|
234
|
+
assert_equal(intf, filtered.keys[0],
|
235
|
+
'filter returned incorrect interface name')
|
236
|
+
end
|
237
|
+
|
164
238
|
# Helper to get valid speeds for port
|
165
239
|
def capable_speed_values(interface)
|
166
240
|
speed_capa = Interface.capabilities(interface.name)['Speed']
|
@@ -1881,17 +1955,4 @@ class TestInterface < CiscoTestCase
|
|
1881
1955
|
int.destroy
|
1882
1956
|
assert(int.default?)
|
1883
1957
|
end
|
1884
|
-
|
1885
|
-
def test_purge_config
|
1886
|
-
name = interfaces[0]
|
1887
|
-
int = Interface.new(name)
|
1888
|
-
int.switchport_mode = :disabled
|
1889
|
-
|
1890
|
-
int.description = 'destroy_pysical'
|
1891
|
-
int.ipv4_addr_mask_set('192.168.0.1', '24')
|
1892
|
-
refute(int.purge_config)
|
1893
|
-
|
1894
|
-
int.purge_config = true
|
1895
|
-
assert(int.purge_config)
|
1896
|
-
end
|
1897
1958
|
end
|
data/tests/test_interface_bdi.rb
CHANGED
@@ -26,8 +26,8 @@ class TestInterfaceBdi < CiscoTestCase
|
|
26
26
|
def self.runnable_methods
|
27
27
|
# We don't have a separate YAML file to key off, so we check platform
|
28
28
|
return super if node.product_id[/N7/]
|
29
|
-
remove_method :setup
|
30
|
-
remove_method :teardown
|
29
|
+
remove_method :setup if instance_methods(false).include?(:setup)
|
30
|
+
remove_method :teardown if instance_methods(false).include?(:teardown)
|
31
31
|
[:unsupported]
|
32
32
|
end
|
33
33
|
|
@@ -31,23 +31,30 @@ class TestInterfaceChanGrp < CiscoTestCase
|
|
31
31
|
interface_cleanup(@intf.name)
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
assert_equal(
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
34
|
+
# Test InterfaceChannelGroup.interfaces class method api
|
35
|
+
def test_interface_apis
|
36
|
+
intf = interfaces[0]
|
37
|
+
intf2 = interfaces[1]
|
38
|
+
|
39
|
+
# Verify show_name usage
|
40
|
+
one = InterfaceChannelGroup.interfaces(intf)
|
41
|
+
assert_equal(1, one.length,
|
42
|
+
'Invalid number of keys returned, should be 1')
|
43
|
+
assert_equal(Utils.normalize_intf_pattern(intf), one[intf].show_name,
|
44
|
+
':show_name should be intf name when show_name param specified')
|
45
|
+
|
46
|
+
# Verify 'all' interfaces
|
47
|
+
all = InterfaceChannelGroup.interfaces
|
48
|
+
assert_operator(all.length, :>, 1,
|
49
|
+
'Invalid number of keys returned, should exceed 1')
|
50
|
+
assert_empty(all[intf2].show_name,
|
51
|
+
':show_name should be empty string when show_name param is nil')
|
52
|
+
|
53
|
+
# Test non-existent loopback does NOT raise when calling interfaces
|
54
|
+
Interface.new('loopback543', false).destroy if
|
55
|
+
Interface.interfaces(nil, 'loopback543').any?
|
56
|
+
one = InterfaceChannelGroup.interfaces('loopback543')
|
57
|
+
assert_empty(one, 'InterfaceChannelGroup.interfaces hash should be empty')
|
51
58
|
end
|
52
59
|
|
53
60
|
def test_channel_group_mode
|
@@ -36,6 +36,41 @@ class TestInterfaceEvpnMultisite < CiscoTestCase
|
|
36
36
|
config("default interface #{intf}")
|
37
37
|
end
|
38
38
|
|
39
|
+
# Test InterfaceEvpnMultisite.interfaces class method api
|
40
|
+
def test_interface_apis
|
41
|
+
# setup
|
42
|
+
ms = EvpnMultisite.new(100)
|
43
|
+
intf = interfaces[0]
|
44
|
+
intf2 = interfaces[1]
|
45
|
+
interface_ethernet_default(intf2)
|
46
|
+
[intf, intf2].each do |i|
|
47
|
+
InterfaceEvpnMultisite.new(i).enable('dci-tracking')
|
48
|
+
end
|
49
|
+
|
50
|
+
# Verify show_name usage
|
51
|
+
one = InterfaceEvpnMultisite.interfaces(intf)
|
52
|
+
assert_equal(1, one.length,
|
53
|
+
'Invalid number of keys returned, should be 1')
|
54
|
+
assert_equal(Utils.normalize_intf_pattern(intf), one[intf].show_name,
|
55
|
+
':show_name should be intf name when show_name param specified')
|
56
|
+
|
57
|
+
# Verify 'all' interfaces
|
58
|
+
all = InterfaceEvpnMultisite.interfaces
|
59
|
+
assert_operator(all.length, :>, 1,
|
60
|
+
'Invalid number of keys returned, should exceed 1')
|
61
|
+
assert_empty(all[intf2].show_name,
|
62
|
+
':show_name should be empty string when show_name param is nil')
|
63
|
+
|
64
|
+
# Test non-existent interface does NOT raise when calling interfaces
|
65
|
+
Interface.new('loopback543', false).destroy if
|
66
|
+
Interface.interfaces(nil, 'loopback543').any?
|
67
|
+
no_intf = InterfaceEvpnMultisite.interfaces('loopback543')
|
68
|
+
assert_empty(no_intf,
|
69
|
+
'InterfaceEvpnMultisite.interfaces hash should be empty')
|
70
|
+
|
71
|
+
ms.destroy
|
72
|
+
end
|
73
|
+
|
39
74
|
def test_enable_disable
|
40
75
|
interface = interfaces[0]
|
41
76
|
intf_ms = InterfaceEvpnMultisite.new(interface)
|
@@ -61,6 +61,58 @@ class TestInterfaceOspf < CiscoTestCase
|
|
61
61
|
InterfaceOspf.new(ifname, routerospf.name, area)
|
62
62
|
end
|
63
63
|
|
64
|
+
# Test InterfaceOspf.interfaces class method api
|
65
|
+
def test_interface_apis
|
66
|
+
intf = interfaces[0]
|
67
|
+
intf2 = interfaces[1]
|
68
|
+
|
69
|
+
# Verify show_name usage when no ospf config on intf
|
70
|
+
none = InterfaceOspf.interfaces(nil, intf)
|
71
|
+
assert_equal(0, none.length,
|
72
|
+
'Invalid number of keys returned, should be 0')
|
73
|
+
|
74
|
+
# Verify show_name usage when ospf config present on intf
|
75
|
+
InterfaceOspf.new(intf, 'ospf_test', '0')
|
76
|
+
one = InterfaceOspf.interfaces(nil, intf)
|
77
|
+
assert_equal(1, one.length,
|
78
|
+
'Invalid number of keys returned, should be 1')
|
79
|
+
assert_equal(Utils.normalize_intf_pattern(intf), one[intf].show_name,
|
80
|
+
':show_name should be intf name when show_name param specified')
|
81
|
+
|
82
|
+
# Verify 'all' interfaces returned
|
83
|
+
Interface.new(intf2)
|
84
|
+
InterfaceOspf.new(intf2, 'ospf_test', '0')
|
85
|
+
all = InterfaceOspf.interfaces
|
86
|
+
assert_operator(all.length, :>, 1,
|
87
|
+
'Invalid number of keys returned, should exceed 1')
|
88
|
+
assert_empty(all[intf2].show_name,
|
89
|
+
':show_name should be empty string when show_name param is nil')
|
90
|
+
|
91
|
+
# Test with ospf_name parameter specified
|
92
|
+
all = InterfaceOspf.interfaces('ospf_test')
|
93
|
+
assert_operator(all.length, :>, 1,
|
94
|
+
'Invalid number of keys returned, should exceed 1')
|
95
|
+
assert_empty(all[intf2].show_name,
|
96
|
+
':show_name should be empty string when show_name param is nil')
|
97
|
+
|
98
|
+
one = InterfaceOspf.interfaces('ospf_test', intf2)
|
99
|
+
assert_equal(one.length, 1,
|
100
|
+
'Invalid number of keys returned, should be 1')
|
101
|
+
assert_equal(Utils.normalize_intf_pattern(intf2), one[intf2].show_name,
|
102
|
+
':show_name should be intf2 name when show_name param specified')
|
103
|
+
|
104
|
+
# Test non-existent loopback raises fail when calling initialize
|
105
|
+
Interface.new('loopback543', false).destroy if
|
106
|
+
Interface.interfaces(nil, 'loopback543').any?
|
107
|
+
assert_raises(RuntimeError) do
|
108
|
+
InterfaceOspf.new('loopback543', 'ospf_test', '0', false)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Test non-existent loopback does NOT raise when calling interfaces
|
112
|
+
one = InterfaceOspf.interfaces('ospf_test', 'loopback543')
|
113
|
+
assert_empty(one, 'InterfaceOspf.interfaces hash should be empty')
|
114
|
+
end
|
115
|
+
|
64
116
|
def test_get_set_area
|
65
117
|
# setup a loopback to use
|
66
118
|
config('interface loopback12')
|
@@ -209,7 +261,7 @@ class TestInterfaceOspf < CiscoTestCase
|
|
209
261
|
pattern = (/\s+ip router ospf #{ospf.name} area #{area}/)
|
210
262
|
assert_show_match(command: show_cmd(ifname),
|
211
263
|
pattern: pattern)
|
212
|
-
assert_equal(ifname.downcase, interface.
|
264
|
+
assert_equal(ifname.downcase, interface.intf_name,
|
213
265
|
'Error: interface name get value mismatch ')
|
214
266
|
assert_equal(area, interface.area,
|
215
267
|
'Error: area get value mismatch ')
|
@@ -320,6 +372,14 @@ class TestInterfaceOspf < CiscoTestCase
|
|
320
372
|
interface.hello_interval = interface.default_hello_interval
|
321
373
|
refute_show_match(pattern: /\s+ip ospf hello-interval(.*)/,
|
322
374
|
msg: 'Error: default hello-interval set failed')
|
375
|
+
|
376
|
+
# Test destroy_interval helper method
|
377
|
+
interface.hello_interval = interval
|
378
|
+
interface.destroy_interval('hello_interval')
|
379
|
+
refute_show_match(
|
380
|
+
command: show_cmd(interface.intf_name),
|
381
|
+
pattern: /\s+ip ospf hello-interval/,
|
382
|
+
msg: 'ip ospf hello-interval not removed')
|
323
383
|
end
|
324
384
|
|
325
385
|
def test_dead_inv
|
@@ -354,6 +414,14 @@ class TestInterfaceOspf < CiscoTestCase
|
|
354
414
|
assert_show_match(
|
355
415
|
pattern: /^\s+ip ospf dead-interval #{interface.default_dead_interval}/,
|
356
416
|
msg: 'Error: default dead-interval set failed')
|
417
|
+
|
418
|
+
# Test destroy_interval helper method
|
419
|
+
interface.dead_interval = interval
|
420
|
+
interface.destroy_interval('dead_interval')
|
421
|
+
refute_show_match(
|
422
|
+
command: show_cmd(interface.intf_name),
|
423
|
+
pattern: /\s+ip ospf dead-interval/,
|
424
|
+
msg: 'ip ospf dead-interval not removed')
|
357
425
|
end
|
358
426
|
|
359
427
|
def test_bfd
|
@@ -471,7 +539,7 @@ class TestInterfaceOspf < CiscoTestCase
|
|
471
539
|
ifname = interfaces[2]
|
472
540
|
area = '1.1.1.1'
|
473
541
|
interface1 = create_interfaceospf(ospf, ifname, area)
|
474
|
-
assert_equal(ifname.downcase, interface1.
|
542
|
+
assert_equal(ifname.downcase, interface1.intf_name,
|
475
543
|
"Error: 'ip router ospf #{ospf.name} area #{area}' " \
|
476
544
|
'not configured')
|
477
545
|
|
@@ -483,7 +551,7 @@ class TestInterfaceOspf < CiscoTestCase
|
|
483
551
|
|
484
552
|
# check other interface association still exist.
|
485
553
|
assert_show_match(
|
486
|
-
command: show_cmd(interface.
|
554
|
+
command: show_cmd(interface.intf_name),
|
487
555
|
pattern: /\s+ip router ospf #{ospf.name} area #{interface.area}/,
|
488
556
|
msg: "'ip router ospf #{ospf.name} default area' not configured")
|
489
557
|
end
|