cisco_node_utils 1.3.0 → 1.4.0
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 +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +66 -0
- data/Gemfile +1 -0
- data/README.md +44 -43
- data/bin/.rubocop.yml +18 -0
- data/bin/show_running_yang.rb +233 -0
- data/cisco_node_utils.gemspec +1 -1
- data/docs/README-maintainers.md +1 -0
- data/docs/README-utilities.md +14 -0
- data/lib/.rubocop.yml +1 -1
- data/lib/cisco_node_utils/aaa_authentication_login_service.rb +8 -3
- data/lib/cisco_node_utils/aaa_authorization_service.rb +6 -0
- data/lib/cisco_node_utils/bfd_global.rb +300 -0
- data/lib/cisco_node_utils/bgp.rb +6 -4
- data/lib/cisco_node_utils/bgp_af.rb +2 -0
- data/lib/cisco_node_utils/bgp_neighbor.rb +14 -0
- data/lib/cisco_node_utils/bgp_neighbor_af.rb +4 -1
- data/lib/cisco_node_utils/cisco_cmn_utils.rb +126 -0
- data/lib/cisco_node_utils/client/client.rb +6 -2
- data/lib/cisco_node_utils/client/grpc/client.rb +120 -36
- data/lib/cisco_node_utils/client/nxapi/client.rb +6 -2
- data/lib/cisco_node_utils/cmd_ref/DEPRECATED.yaml +118 -0
- data/lib/cisco_node_utils/cmd_ref/aaa_authorization_service.yaml +14 -0
- data/lib/cisco_node_utils/cmd_ref/bfd_global.yaml +117 -0
- data/lib/cisco_node_utils/cmd_ref/bgp.yaml +7 -7
- data/lib/cisco_node_utils/cmd_ref/bgp_neighbor.yaml +7 -0
- data/lib/cisco_node_utils/cmd_ref/dhcp_relay_global.yaml +125 -0
- data/lib/cisco_node_utils/cmd_ref/feature.yaml +10 -0
- data/lib/cisco_node_utils/cmd_ref/interface.yaml +141 -49
- data/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +44 -0
- data/lib/cisco_node_utils/cmd_ref/interface_portchannel.yaml +6 -0
- data/lib/cisco_node_utils/cmd_ref/ospf.yaml +6 -0
- data/lib/cisco_node_utils/cmd_ref/ospf_area.yaml +91 -0
- data/lib/cisco_node_utils/cmd_ref/ospf_area_vlink.yaml +88 -0
- data/lib/cisco_node_utils/cmd_ref/overlay_global.yaml +0 -3
- data/lib/cisco_node_utils/cmd_ref/show_version.yaml +3 -3
- data/lib/cisco_node_utils/cmd_ref/snmp_community.yaml +39 -15
- data/lib/cisco_node_utils/cmd_ref/snmp_notification_receiver.yaml +43 -21
- data/lib/cisco_node_utils/cmd_ref/snmp_server.yaml +48 -19
- data/lib/cisco_node_utils/cmd_ref/snmp_user.yaml +0 -0
- data/lib/cisco_node_utils/cmd_ref/tacacs_global.yaml +30 -0
- data/lib/cisco_node_utils/cmd_ref/tacacs_server.yaml +18 -6
- data/lib/cisco_node_utils/cmd_ref/vdc.yaml +4 -0
- data/lib/cisco_node_utils/cmd_ref/virtual_service.yaml +1 -0
- data/lib/cisco_node_utils/cmd_ref/vlan.yaml +23 -10
- data/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml +8 -2
- data/lib/cisco_node_utils/cmd_ref/yang.yaml +7 -0
- data/lib/cisco_node_utils/cmd_ref/yum.yaml +10 -1
- data/lib/cisco_node_utils/constants.rb +8 -1
- data/lib/cisco_node_utils/dhcp_relay_global.rb +302 -0
- data/lib/cisco_node_utils/exceptions.rb +29 -0
- data/lib/cisco_node_utils/feature.rb +28 -0
- data/lib/cisco_node_utils/interface.rb +493 -402
- data/lib/cisco_node_utils/interface_DEPRECATED.rb +513 -0
- data/lib/cisco_node_utils/interface_ospf.rb +126 -0
- data/lib/cisco_node_utils/interface_portchannel.rb +16 -0
- data/lib/cisco_node_utils/logger.rb +3 -0
- data/lib/cisco_node_utils/node.rb +29 -1
- data/lib/cisco_node_utils/overlay_global.rb +1 -12
- data/lib/cisco_node_utils/pim.rb +1 -0
- data/lib/cisco_node_utils/pim_group_list.rb +1 -0
- data/lib/cisco_node_utils/pim_rp_address.rb +1 -0
- data/lib/cisco_node_utils/platform.rb +9 -2
- data/lib/cisco_node_utils/router_ospf.rb +1 -1
- data/lib/cisco_node_utils/router_ospf_area.rb +416 -0
- data/lib/cisco_node_utils/router_ospf_area_vlink.rb +313 -0
- data/lib/cisco_node_utils/router_ospf_vrf.rb +17 -0
- data/lib/cisco_node_utils/snmp_notification_receiver.rb +27 -9
- data/lib/cisco_node_utils/snmpcommunity.rb +34 -8
- data/lib/cisco_node_utils/snmpserver.rb +4 -4
- data/lib/cisco_node_utils/snmpuser.rb +0 -0
- data/lib/cisco_node_utils/tacacs_global.rb +102 -0
- data/lib/cisco_node_utils/tacacs_server.rb +8 -7
- data/lib/cisco_node_utils/vdc.rb +25 -7
- data/lib/cisco_node_utils/version.rb +1 -1
- data/lib/cisco_node_utils/vlan.rb +30 -56
- data/lib/cisco_node_utils/vlan_DEPRECATED.rb +108 -0
- data/lib/cisco_node_utils/yang.rb +160 -0
- data/lib/cisco_node_utils/yum.rb +25 -32
- data/tests/.rubocop.yml +3 -0
- data/tests/ciscotest.rb +136 -19
- data/tests/cmd_config_invalid.yaml +1 -1
- data/tests/noop.rb +7 -0
- data/tests/tacacs_server.yaml.example +6 -0
- data/tests/test_aaa_authentication_login.rb +24 -1
- data/tests/test_aaa_authentication_login_service.rb +9 -16
- data/tests/test_aaa_authorization_service.rb +111 -84
- data/tests/test_bfd_global.rb +278 -0
- data/tests/test_bgp_neighbor.rb +20 -0
- data/tests/test_bridge_domain_vni.rb +2 -9
- data/tests/test_cmn_utils.rb +76 -0
- data/tests/test_dhcp_relay_global.rb +284 -0
- data/tests/test_dns_domain.rb +4 -4
- data/tests/test_domain_name.rb +2 -2
- data/tests/test_encapsulation.rb +2 -4
- data/tests/test_evpn_vni.rb +14 -7
- data/tests/test_fabricpath_global.rb +12 -13
- data/tests/test_feature.rb +35 -17
- data/tests/test_interface.rb +352 -127
- data/tests/test_interface_bdi.rb +2 -2
- data/tests/test_interface_channel_group.rb +1 -1
- data/tests/test_interface_ospf.rb +153 -23
- data/tests/test_interface_portchannel.rb +15 -6
- data/tests/test_interface_private_vlan.rb +200 -576
- data/tests/test_interface_svi.rb +5 -52
- data/tests/test_interface_switchport.rb +80 -240
- data/tests/test_itd_device_group.rb +2 -2
- data/tests/test_itd_device_group_node.rb +2 -2
- data/tests/test_itd_service.rb +1 -1
- data/tests/test_name_server.rb +3 -3
- data/tests/test_node_ext.rb +15 -17
- data/tests/test_ntp_config.rb +1 -1
- data/tests/test_ntp_server.rb +3 -3
- data/tests/test_nxapi.rb +1 -0
- data/tests/test_overlay_global.rb +15 -19
- data/tests/test_pim.rb +5 -5
- data/tests/test_pim_group_list.rb +1 -37
- data/tests/test_pim_rp_address.rb +1 -1
- data/tests/test_platform.rb +9 -11
- data/tests/test_portchannel_global.rb +43 -3
- data/tests/test_radius_server.rb +1 -1
- data/tests/test_radius_server_group.rb +1 -1
- data/tests/test_router_bgp.rb +17 -30
- data/tests/test_router_ospf_area.rb +433 -0
- data/tests/test_router_ospf_area_vlink.rb +298 -0
- data/tests/test_router_ospf_vrf.rb +17 -0
- data/tests/test_snmp_notification_receiver.rb +11 -11
- data/tests/test_snmpcommunity.rb +177 -69
- data/tests/test_snmpgroup.rb +7 -7
- data/tests/test_snmpserver.rb +164 -253
- data/tests/test_snmpuser.rb +73 -69
- data/tests/test_stp_global.rb +15 -15
- data/tests/test_syslog_settings.rb +1 -1
- data/tests/test_tacacs_global.rb +80 -0
- data/tests/test_tacacs_server.rb +129 -51
- data/tests/test_tacacs_server_group.rb +3 -29
- data/tests/test_tacacs_server_host.rb +24 -27
- data/tests/test_vlan.rb +57 -59
- data/tests/test_vlan_private.rb +271 -284
- data/tests/test_vpc.rb +10 -4
- data/tests/test_vrf.rb +2 -0
- data/tests/test_vrf_af.rb +2 -5
- data/tests/test_vtp.rb +5 -2
- data/tests/test_vxlan_vtep.rb +20 -44
- data/tests/test_vxlan_vtep_vni.rb +23 -16
- data/tests/test_yang.rb +369 -0
- data/tests/test_yum.rb +34 -42
- data/tests/yum_package.yaml +35 -0
- metadata +31 -4
- data/tests/test_vlan_mt_full.rb +0 -85
|
@@ -92,7 +92,13 @@ module Cisco
|
|
|
92
92
|
self.hello_interval = default_hello_interval
|
|
93
93
|
config_set('interface_ospf', 'dead_interval',
|
|
94
94
|
@interface.name, 'no', '')
|
|
95
|
+
self.bfd = default_bfd
|
|
96
|
+
self.mtu_ignore = default_mtu_ignore
|
|
97
|
+
self.priority = default_priority
|
|
98
|
+
self.network_type = default_network_type
|
|
95
99
|
self.passive_interface = default_passive_interface if passive_interface
|
|
100
|
+
self.shutdown = default_shutdown
|
|
101
|
+
self.transmit_delay = default_transmit_delay
|
|
96
102
|
end
|
|
97
103
|
|
|
98
104
|
def default_message_digest
|
|
@@ -106,6 +112,7 @@ module Cisco
|
|
|
106
112
|
# interface %s
|
|
107
113
|
# %s ip ospf authentication message-digest
|
|
108
114
|
def message_digest=(enable)
|
|
115
|
+
return if enable == message_digest
|
|
109
116
|
config_set('interface_ospf', 'message_digest', @interface.name,
|
|
110
117
|
enable ? '' : 'no')
|
|
111
118
|
end
|
|
@@ -144,6 +151,10 @@ module Cisco
|
|
|
144
151
|
config_get('interface_ospf', 'message_digest_password', @interface.name)
|
|
145
152
|
end
|
|
146
153
|
|
|
154
|
+
def default_message_digest_password
|
|
155
|
+
config_get_default('interface_ospf', 'message_digest_password')
|
|
156
|
+
end
|
|
157
|
+
|
|
147
158
|
# interface %s
|
|
148
159
|
# %s ip ospf message-digest-key %d %s %d %s
|
|
149
160
|
def message_digest_key_set(keyid, algtype, enctype, enc)
|
|
@@ -209,6 +220,72 @@ module Cisco
|
|
|
209
220
|
@interface.name, '', interval.to_i)
|
|
210
221
|
end
|
|
211
222
|
|
|
223
|
+
# CLI can be either of the following or none
|
|
224
|
+
# ip ospf bfd
|
|
225
|
+
# ip ospf bfd disable
|
|
226
|
+
def bfd
|
|
227
|
+
val = config_get('interface_ospf', 'bfd', @interface.name)
|
|
228
|
+
return if val.nil?
|
|
229
|
+
val.include?('disable') ? false : true
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# interface %s
|
|
233
|
+
# %s ip ospf bfd %s
|
|
234
|
+
def bfd=(val)
|
|
235
|
+
return if val == bfd
|
|
236
|
+
Feature.bfd_enable
|
|
237
|
+
state = (val == default_bfd) ? 'no' : ''
|
|
238
|
+
disable = val ? '' : 'disable'
|
|
239
|
+
config_set('interface_ospf', 'bfd', @interface.name,
|
|
240
|
+
state, disable)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def default_bfd
|
|
244
|
+
config_get_default('interface_ospf', 'bfd')
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def default_network_type
|
|
248
|
+
case @interface.name
|
|
249
|
+
when /loopback/i
|
|
250
|
+
lookup = 'network_type_loopback_default'
|
|
251
|
+
else
|
|
252
|
+
lookup = 'network_type_default'
|
|
253
|
+
end
|
|
254
|
+
config_get_default('interface_ospf', lookup)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def mtu_ignore
|
|
258
|
+
config_get('interface_ospf', 'mtu_ignore', @interface.name)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# interface %s
|
|
262
|
+
# %s ip ospf mtu-ignore
|
|
263
|
+
def mtu_ignore=(enable)
|
|
264
|
+
config_set('interface_ospf', 'mtu_ignore', @interface.name,
|
|
265
|
+
enable ? '' : 'no')
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def default_mtu_ignore
|
|
269
|
+
config_get_default('interface_ospf', 'mtu_ignore')
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def network_type
|
|
273
|
+
type = config_get('interface_ospf', 'network_type', @interface.name)
|
|
274
|
+
return 'p2p' if type == 'point-to-point'
|
|
275
|
+
return default_network_type if type.nil?
|
|
276
|
+
type
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# interface %s
|
|
280
|
+
# %s ip ospf network %s
|
|
281
|
+
def network_type=(type)
|
|
282
|
+
no_cmd = (type == default_network_type) ? 'no' : ''
|
|
283
|
+
network = (type == default_network_type) ? '' : type
|
|
284
|
+
network = 'point-to-point' if type.to_s == 'p2p'
|
|
285
|
+
config_set('interface_ospf', 'network_type', @interface.name,
|
|
286
|
+
no_cmd, network)
|
|
287
|
+
end
|
|
288
|
+
|
|
212
289
|
def default_passive_interface
|
|
213
290
|
config_get_default('interface_ospf', 'passive_interface')
|
|
214
291
|
end
|
|
@@ -224,5 +301,54 @@ module Cisco
|
|
|
224
301
|
config_set('interface_ospf', 'passive_interface', @interface.name,
|
|
225
302
|
enable ? '' : 'no')
|
|
226
303
|
end
|
|
304
|
+
|
|
305
|
+
def priority
|
|
306
|
+
config_get('interface_ospf', 'priority', @interface.name)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
# interface %s
|
|
310
|
+
# ip ospf priority %d
|
|
311
|
+
def priority=(val)
|
|
312
|
+
no_cmd = (val == default_priority) ? 'no' : ''
|
|
313
|
+
pri = (val == default_priority) ? '' : val
|
|
314
|
+
config_set('interface_ospf', 'priority',
|
|
315
|
+
@interface.name, no_cmd, pri)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def default_priority
|
|
319
|
+
config_get_default('interface_ospf', 'priority')
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def shutdown
|
|
323
|
+
config_get('interface_ospf', 'shutdown', @interface.name)
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
# interface %s
|
|
327
|
+
# %s ip ospf shutdown
|
|
328
|
+
def shutdown=(state)
|
|
329
|
+
config_set('interface_ospf', 'shutdown', @interface.name,
|
|
330
|
+
state ? '' : 'no')
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def default_shutdown
|
|
334
|
+
config_get_default('interface_ospf', 'shutdown')
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def transmit_delay
|
|
338
|
+
config_get('interface_ospf', 'transmit_delay', @interface.name)
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# interface %s
|
|
342
|
+
# ip ospf transmit-delay %d
|
|
343
|
+
def transmit_delay=(val)
|
|
344
|
+
no_cmd = (val == default_transmit_delay) ? 'no' : ''
|
|
345
|
+
delay = (val == default_transmit_delay) ? '' : val
|
|
346
|
+
config_set('interface_ospf', 'transmit_delay',
|
|
347
|
+
@interface.name, no_cmd, delay)
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
def default_transmit_delay
|
|
351
|
+
config_get_default('interface_ospf', 'transmit_delay')
|
|
352
|
+
end
|
|
227
353
|
end
|
|
228
354
|
end
|
|
@@ -61,6 +61,22 @@ module Cisco
|
|
|
61
61
|
# PROPERTIES #
|
|
62
62
|
########################################################
|
|
63
63
|
|
|
64
|
+
def bfd_per_link
|
|
65
|
+
config_get('interface_portchannel', 'bfd_per_link', @name)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def bfd_per_link=(state)
|
|
69
|
+
return if state == bfd_per_link
|
|
70
|
+
no_cmd = (state ? '' : 'no')
|
|
71
|
+
Feature.bfd_enable
|
|
72
|
+
config_set('interface_portchannel',
|
|
73
|
+
'bfd_per_link', @name, no_cmd)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def default_bfd_per_link
|
|
77
|
+
config_get_default('interface_portchannel', 'bfd_per_link')
|
|
78
|
+
end
|
|
79
|
+
|
|
64
80
|
def lacp_graceful_convergence
|
|
65
81
|
config_get('interface_portchannel', 'lacp_graceful_convergence', @name)
|
|
66
82
|
end
|
|
@@ -45,6 +45,9 @@ module Cisco::Logger
|
|
|
45
45
|
@@logger = Chef::Log # rubocop:disable Style/ClassVars
|
|
46
46
|
else
|
|
47
47
|
@@logger = Logger.new(STDOUT) # rubocop:disable Style/ClassVars
|
|
48
|
+
@@logger.formatter = proc do |severity, _datetime, _progname, msg|
|
|
49
|
+
"#{severity} -- : #{msg}\n"
|
|
50
|
+
end
|
|
48
51
|
@@logger.level = Logger::INFO
|
|
49
52
|
|
|
50
53
|
def level
|
|
@@ -206,6 +206,34 @@ module Cisco
|
|
|
206
206
|
@client.get(**kwargs)
|
|
207
207
|
end
|
|
208
208
|
|
|
209
|
+
# Merge the specified JSON YANG config with the running config on
|
|
210
|
+
# the device.
|
|
211
|
+
def merge_yang(yang)
|
|
212
|
+
@client.set(data_format: :yang_json, values: [yang], mode: :merge_config)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Replace the running config on the device with the specified
|
|
216
|
+
# JSON YANG config.
|
|
217
|
+
def replace_yang(yang)
|
|
218
|
+
@client.set(data_format: :yang_json, values: [yang],
|
|
219
|
+
mode: :replace_config)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Delete the specified JSON YANG config from the device.
|
|
223
|
+
def delete_yang(yang)
|
|
224
|
+
@client.set(data_format: :yang_json, values: [yang], mode: :delete_config)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# Retrieve JSON YANG config from the device for the specified path.
|
|
228
|
+
def get_yang(yang_path)
|
|
229
|
+
@client.get(data_format: :yang_json, command: yang_path)
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Retrieve JSON YANG operational data for the specified path.
|
|
233
|
+
def get_yang_oper(yang_path)
|
|
234
|
+
@client.get(data_format: :yang_json, command: yang_path, mode: :get_oper)
|
|
235
|
+
end
|
|
236
|
+
|
|
209
237
|
# @return [String] such as "Cisco Nexus Operating System (NX-OS) Software"
|
|
210
238
|
def os
|
|
211
239
|
o = config_get('show_version', 'header')
|
|
@@ -237,7 +265,7 @@ module Cisco
|
|
|
237
265
|
# No support for structured output for this command yet
|
|
238
266
|
output = get(command: 'show inventory',
|
|
239
267
|
data_format: :cli)
|
|
240
|
-
return /NAME:
|
|
268
|
+
return /NAME: .*\nPID: (\S+)/.match(output)[1]
|
|
241
269
|
end
|
|
242
270
|
end
|
|
243
271
|
end
|
|
@@ -31,7 +31,6 @@ module Cisco
|
|
|
31
31
|
|
|
32
32
|
# dup-host-ip-addr-detection
|
|
33
33
|
def dup_host_ip_addr_detection
|
|
34
|
-
return nil unless Feature.nv_overlay_evpn_enabled?
|
|
35
34
|
match = config_get('overlay_global', 'dup_host_ip_addr_detection')
|
|
36
35
|
if match.nil?
|
|
37
36
|
default_dup_host_ip_addr_detection
|
|
@@ -99,16 +98,7 @@ module Cisco
|
|
|
99
98
|
|
|
100
99
|
def dup_host_mac_detection_set(host_moves, timeout)
|
|
101
100
|
set_args = { host_moves: host_moves, timeout: timeout }
|
|
102
|
-
|
|
103
|
-
timeout == default_dup_host_mac_detection_timeout
|
|
104
|
-
dup_host_mac_detection_default
|
|
105
|
-
else
|
|
106
|
-
config_set('overlay_global', 'dup_host_mac_detection', set_args)
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def dup_host_mac_detection_default
|
|
111
|
-
config_set('overlay_global', 'dup_host_mac_detection_default')
|
|
101
|
+
config_set('overlay_global', 'dup_host_mac_detection', set_args)
|
|
112
102
|
end
|
|
113
103
|
|
|
114
104
|
def default_dup_host_mac_detection
|
|
@@ -126,7 +116,6 @@ module Cisco
|
|
|
126
116
|
|
|
127
117
|
# anycast-gateway-mac
|
|
128
118
|
def anycast_gateway_mac
|
|
129
|
-
return nil unless Feature.nv_overlay_evpn_enabled?
|
|
130
119
|
mac = config_get('overlay_global', 'anycast_gateway_mac')
|
|
131
120
|
mac.nil? || mac.empty? ? default_anycast_gateway_mac : mac.downcase
|
|
132
121
|
end
|
data/lib/cisco_node_utils/pim.rb
CHANGED
|
@@ -28,7 +28,7 @@ module Cisco
|
|
|
28
28
|
|
|
29
29
|
# ex: 'n3500-uk9.6.0.2.A3.0.40.bin'
|
|
30
30
|
def self.system_image
|
|
31
|
-
config_get('show_version', '
|
|
31
|
+
config_get('show_version', 'system_image')
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
# Returns package hash with state values
|
|
@@ -188,7 +188,14 @@ module Cisco
|
|
|
188
188
|
# 'cpu' => '0% system CPU' }},
|
|
189
189
|
# { ... }}
|
|
190
190
|
def self.virtual_services
|
|
191
|
-
|
|
191
|
+
# If no virtual-services are installed, this will result
|
|
192
|
+
# in a RuntimeError. We need to rescue this specific case.
|
|
193
|
+
begin
|
|
194
|
+
virts = config_get('virtual_service', 'services')
|
|
195
|
+
rescue RuntimeError => e
|
|
196
|
+
return {} if e.message[/No key \"TABLE_detail\"/]
|
|
197
|
+
raise
|
|
198
|
+
end
|
|
192
199
|
return {} if virts.nil?
|
|
193
200
|
# NXAPI returns hash instead of array if there's only 1
|
|
194
201
|
virts = [virts] if virts.is_a? Hash
|
|
@@ -61,7 +61,7 @@ module Cisco
|
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
def wait_for_process_initialized
|
|
64
|
-
return unless node.product_id[/N(5|6)/]
|
|
64
|
+
return unless node.product_id[/N(5|6|8)/]
|
|
65
65
|
|
|
66
66
|
# Hack for slow-start platforms which will have setter failures if the
|
|
67
67
|
# ospf instance is still initializing. To see this problem in a sandbox
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
#
|
|
2
|
+
# NXAPI implementation of Router OSPF Area class
|
|
3
|
+
#
|
|
4
|
+
# June 2016, Sai Chintalapudi
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2016 Cisco and/or its affiliates.
|
|
7
|
+
#
|
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
# you may not use this file except in compliance with the License.
|
|
10
|
+
# You may obtain a copy of the License at
|
|
11
|
+
#
|
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
#
|
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
# See the License for the specific language governing permissions and
|
|
18
|
+
# limitations under the License.
|
|
19
|
+
|
|
20
|
+
require 'ipaddr'
|
|
21
|
+
require_relative 'node_util'
|
|
22
|
+
require_relative 'router_ospf'
|
|
23
|
+
require_relative 'router_ospf_vrf'
|
|
24
|
+
|
|
25
|
+
module Cisco
|
|
26
|
+
# node_utils class for ospf_area
|
|
27
|
+
class RouterOspfArea < NodeUtil
|
|
28
|
+
attr_reader :router, :vrf, :area_id
|
|
29
|
+
|
|
30
|
+
def initialize(ospf_router, vrf_name, area_id, instantiate=true)
|
|
31
|
+
fail TypeError unless ospf_router.is_a?(String)
|
|
32
|
+
fail TypeError unless vrf_name.is_a?(String)
|
|
33
|
+
fail ArgumentError unless ospf_router.length > 0
|
|
34
|
+
fail ArgumentError unless vrf_name.length > 0
|
|
35
|
+
@area_id = area_id.to_s
|
|
36
|
+
fail ArgumentError if @area_id.empty?
|
|
37
|
+
|
|
38
|
+
Feature.ospf_enable if instantiate
|
|
39
|
+
# Convert to dot-notation
|
|
40
|
+
|
|
41
|
+
@router = ospf_router
|
|
42
|
+
@vrf = vrf_name
|
|
43
|
+
@area_id = IPAddr.new(area_id.to_i, Socket::AF_INET) unless @area_id[/\./]
|
|
44
|
+
|
|
45
|
+
set_args_keys_default
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.areas
|
|
49
|
+
hash = {}
|
|
50
|
+
RouterOspf.routers.each do |name, _obj|
|
|
51
|
+
# get all area ids under default vrf
|
|
52
|
+
area_ids = config_get('ospf_area', 'areas', name: name)
|
|
53
|
+
if area_ids
|
|
54
|
+
hash[name] = {}
|
|
55
|
+
hash[name]['default'] = {}
|
|
56
|
+
area_ids.uniq.each do |area|
|
|
57
|
+
hash[name]['default'][area] =
|
|
58
|
+
RouterOspfArea.new(name, 'default', area, false)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
vrf_ids = config_get('ospf', 'vrf', name: name)
|
|
62
|
+
next if vrf_ids.nil?
|
|
63
|
+
vrf_ids.each do |vrf|
|
|
64
|
+
# get all area ids under each vrf
|
|
65
|
+
area_ids = config_get('ospf_area', 'areas', name: name, vrf: vrf)
|
|
66
|
+
next if area_ids.nil?
|
|
67
|
+
hash[name] ||= {}
|
|
68
|
+
hash[name][vrf] = {}
|
|
69
|
+
area_ids.uniq.each do |area|
|
|
70
|
+
hash[name][vrf][area] =
|
|
71
|
+
RouterOspfArea.new(name, vrf, area, false)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
hash
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Helper method to delete @set_args hash keys
|
|
79
|
+
def set_args_keys_default
|
|
80
|
+
@set_args = { name: @router, area: @area_id }
|
|
81
|
+
@set_args[:vrf] = @vrf unless @vrf == 'default'
|
|
82
|
+
@get_args = @set_args
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# rubocop:disable Style/AccessorMethodName
|
|
86
|
+
def set_args_keys(hash={})
|
|
87
|
+
set_args_keys_default
|
|
88
|
+
@set_args = @get_args.merge!(hash) unless hash.empty?
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def destroy
|
|
92
|
+
return unless Feature.ospf_enabled?
|
|
93
|
+
[:authentication,
|
|
94
|
+
:default_cost,
|
|
95
|
+
:filter_list_in,
|
|
96
|
+
:filter_list_out,
|
|
97
|
+
:nssa,
|
|
98
|
+
:nssa_translate_type7,
|
|
99
|
+
:range,
|
|
100
|
+
:stub,
|
|
101
|
+
].each do |prop|
|
|
102
|
+
send("#{prop}=", send("default_#{prop}")) unless
|
|
103
|
+
send("#{prop}") == send("default_#{prop}")
|
|
104
|
+
end
|
|
105
|
+
set_args_keys_default
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def ==(other)
|
|
109
|
+
(ospf_router == other.ospf_router) &&
|
|
110
|
+
(vrf_name == other.vrf_name) && (area_id == other.area_id)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
########################################################
|
|
114
|
+
# PROPERTIES #
|
|
115
|
+
########################################################
|
|
116
|
+
|
|
117
|
+
# CLI can be either of the following or none
|
|
118
|
+
# area 1.1.1.1 authentication
|
|
119
|
+
# area 1.1.1.1 authentication message-digest
|
|
120
|
+
def authentication
|
|
121
|
+
auth = config_get('ospf_area', 'authentication', @get_args)
|
|
122
|
+
return default_authentication unless auth
|
|
123
|
+
auth.include?('message-digest') ? 'md5' : 'cleartext'
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def authentication=(val)
|
|
127
|
+
state = val ? '' : 'no'
|
|
128
|
+
auth = (val.to_s == 'md5') ? 'message-digest' : ''
|
|
129
|
+
set_args_keys(state: state, auth: auth)
|
|
130
|
+
config_set('ospf_area', 'authentication', @set_args)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def default_authentication
|
|
134
|
+
config_get_default('ospf_area', 'authentication')
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# CLI can be the following or none
|
|
138
|
+
# area 1.1.1.1 default-cost 1000
|
|
139
|
+
def default_cost
|
|
140
|
+
config_get('ospf_area', 'default_cost', @get_args)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def default_cost=(val)
|
|
144
|
+
state = val == default_default_cost ? 'no' : ''
|
|
145
|
+
cost = val == default_default_cost ? '' : val
|
|
146
|
+
set_args_keys(state: state, cost: cost)
|
|
147
|
+
config_set('ospf_area', 'default_cost', @set_args)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def default_default_cost
|
|
151
|
+
config_get_default('ospf_area', 'default_cost')
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# CLI can be the following or none
|
|
155
|
+
# area 1.1.1.1 filter-list route-map aaa in
|
|
156
|
+
def filter_list_in
|
|
157
|
+
config_get('ospf_area', 'filter_list_in', @get_args)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def filter_list_in=(val)
|
|
161
|
+
return if filter_list_in == false && val == false
|
|
162
|
+
state = val ? '' : 'no'
|
|
163
|
+
rm = val ? val : filter_list_in
|
|
164
|
+
set_args_keys(state: state, route_map: rm)
|
|
165
|
+
config_set('ospf_area', 'filter_list_in', @set_args)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def default_filter_list_in
|
|
169
|
+
config_get_default('ospf_area', 'filter_list_in')
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# CLI can be the following or none
|
|
173
|
+
# area 1.1.1.1 filter-list route-map bbb out
|
|
174
|
+
def filter_list_out
|
|
175
|
+
config_get('ospf_area', 'filter_list_out', @get_args)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def filter_list_out=(val)
|
|
179
|
+
return if filter_list_out == false && val == false
|
|
180
|
+
state = val ? '' : 'no'
|
|
181
|
+
rm = val ? val : filter_list_out
|
|
182
|
+
set_args_keys(state: state, route_map: rm)
|
|
183
|
+
config_set('ospf_area', 'filter_list_out', @set_args)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def default_filter_list_out
|
|
187
|
+
config_get_default('ospf_area', 'filter_list_out')
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# CLI can be the following or none
|
|
191
|
+
# area 1.1.1.1 nssa
|
|
192
|
+
# the above command can be appended with no-summary and/or
|
|
193
|
+
# no-redistribution and/or default-information-originate.
|
|
194
|
+
# route-map <map> can be appended with default-information-originate
|
|
195
|
+
# Basically, every property this CLI configures is optional
|
|
196
|
+
# example manifest:
|
|
197
|
+
# nssa => true,
|
|
198
|
+
# nssa_default_originate => true,
|
|
199
|
+
# nssa_no_redistribution => false,
|
|
200
|
+
# nssa_no_summary => false,
|
|
201
|
+
# nssa_route_map => 'aaa',
|
|
202
|
+
def nssa_get
|
|
203
|
+
hash = {}
|
|
204
|
+
output = config_get('ospf_area', 'nssa_get', @get_args)
|
|
205
|
+
return hash if output.nil?
|
|
206
|
+
output.each do |line|
|
|
207
|
+
next if line.include?('translate')
|
|
208
|
+
hash[:nssa] = true
|
|
209
|
+
hash[:no_summary] = true if line.include?('no-summary')
|
|
210
|
+
hash[:no_redistribution] = true if line.include?('no-redistribution')
|
|
211
|
+
hash[:def_info_origin] = true if
|
|
212
|
+
line.include?('default-information-originate')
|
|
213
|
+
if line.include?('route-map')
|
|
214
|
+
params = line.split
|
|
215
|
+
hash[:route_map] = params[params.index('route-map') + 1]
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
hash
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def nssa
|
|
222
|
+
nssa_get[:nssa].nil? ? false : true
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def default_nssa
|
|
226
|
+
config_get_default('ospf_area', 'nssa')
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def nssa_default_originate
|
|
230
|
+
nssa_get[:def_info_origin].nil? ? false : true
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def default_nssa_default_originate
|
|
234
|
+
config_get_default('ospf_area', 'nssa_default_originate')
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def nssa_no_redistribution
|
|
238
|
+
nssa_get[:no_redistribution].nil? ? false : true
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def default_nssa_no_redistribution
|
|
242
|
+
config_get_default('ospf_area', 'nssa_no_redistribution')
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def nssa_no_summary
|
|
246
|
+
nssa_get[:no_summary].nil? ? false : true
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def default_nssa_no_summary
|
|
250
|
+
config_get_default('ospf_area', 'nssa_no_summary')
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def nssa_route_map
|
|
254
|
+
nssa_get[:route_map].nil? ? '' : nssa_get[:route_map]
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def default_nssa_route_map
|
|
258
|
+
config_get_default('ospf_area', 'nssa_route_map')
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def nssa_set(hash)
|
|
262
|
+
# The nssa cli is additive so it must be removed altogether
|
|
263
|
+
# when making changes.
|
|
264
|
+
config_set('ospf_area', 'nssa_destroy', @set_args) if nssa
|
|
265
|
+
return if hash.empty?
|
|
266
|
+
|
|
267
|
+
@set_args[:state] = ''
|
|
268
|
+
@set_args[:nssa_no_summary] = ''
|
|
269
|
+
@set_args[:nssa_no_redistribution] = ''
|
|
270
|
+
@set_args[:nssa_default_originate] = ''
|
|
271
|
+
@set_args[:nssa_route_map] = ''
|
|
272
|
+
# Process each nssa property
|
|
273
|
+
hash.keys.each do |k|
|
|
274
|
+
hash[k] = 'default-information-originate' if
|
|
275
|
+
k == :nssa_default_originate
|
|
276
|
+
hash[k] = 'no-summary' if k == :nssa_no_summary
|
|
277
|
+
hash[k] = 'no-redistribution' if k == :nssa_no_redistribution
|
|
278
|
+
hash[k] = "route-map #{hash[:nssa_route_map]}" if
|
|
279
|
+
k == :nssa_route_map
|
|
280
|
+
@set_args[k] = hash[k]
|
|
281
|
+
end
|
|
282
|
+
config_set('ospf_area', 'nssa_set', @set_args)
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
# CLI can be the following or none
|
|
286
|
+
# area 1.1.1.1 nssa translate type7 always
|
|
287
|
+
# area 1.1.1.1 nssa translate type7 always supress-fa
|
|
288
|
+
# area 1.1.1.1 nssa translate type7 never
|
|
289
|
+
# area 1.1.1.1 nssa translate type7 supress-fa
|
|
290
|
+
def nssa_translate_type7
|
|
291
|
+
str = config_get('ospf_area', 'nssa_translate_type7', @get_args)
|
|
292
|
+
str = 'always_supress_fa' if str == 'always supress-fa'
|
|
293
|
+
str = 'supress_fa' if str == 'supress-fa'
|
|
294
|
+
str
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def nssa_translate_type7=(val)
|
|
298
|
+
state = val ? '' : 'no'
|
|
299
|
+
value = val ? val : ''
|
|
300
|
+
value = 'always supress-fa' if val.to_s == 'always_supress_fa'
|
|
301
|
+
value = 'supress-fa' if val.to_s == 'supress_fa'
|
|
302
|
+
set_args_keys(state: state, value: value)
|
|
303
|
+
config_set('ospf_area', 'nssa_translate_type7', @set_args)
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def default_nssa_translate_type7
|
|
307
|
+
config_get_default('ospf_area', 'nssa_translate_type7')
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# range can take multiple values for the same vrf
|
|
311
|
+
# area 1.1.1.1 range 10.3.0.0/32
|
|
312
|
+
# area 1.1.1.1 range 10.3.0.1/32
|
|
313
|
+
# area 1.1.1.1 range 10.3.3.0/24
|
|
314
|
+
# area 1.1.1.1 range 10.3.0.0/16 not-advertise cost 23
|
|
315
|
+
# sometimes the not-advertise and cost are reversed in the
|
|
316
|
+
# show command for reasons unknown!
|
|
317
|
+
# area 1.1.1.1 range 10.3.0.0/16 cost 23 not-advertise
|
|
318
|
+
# use positional way of getting the values as it is
|
|
319
|
+
# simple and there are only two properties which are
|
|
320
|
+
# optional. ip is mandatory
|
|
321
|
+
# the return list is of the form [ip, not-advertise, cost]
|
|
322
|
+
# ex: [['10.3.0.0/16', 'not-advertise', '23'],
|
|
323
|
+
# ['10.3.0.0/32', 'not-advertise'],
|
|
324
|
+
# ['10.3.0.1/32'],
|
|
325
|
+
# ['10.3.3.0/24', '450']]
|
|
326
|
+
def range
|
|
327
|
+
list = []
|
|
328
|
+
ranges = config_get('ospf_area', 'range', @get_args)
|
|
329
|
+
ranges.each do |line|
|
|
330
|
+
llist = []
|
|
331
|
+
params = line.split
|
|
332
|
+
llist[0] = params[0]
|
|
333
|
+
llist[1] = 'not_advertise' if line.include?('not-advertise')
|
|
334
|
+
if line.include?('cost')
|
|
335
|
+
arr_index = llist[1].nil? ? 1 : 2
|
|
336
|
+
llist[arr_index] = params[params.index('cost') + 1]
|
|
337
|
+
end
|
|
338
|
+
list << llist
|
|
339
|
+
end
|
|
340
|
+
list
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def range=(set_list)
|
|
344
|
+
# fail if set_list contains duplicate ip values
|
|
345
|
+
ip_list = []
|
|
346
|
+
set_list.each do |ip, _not_advertise, _cval|
|
|
347
|
+
ip_list << ip
|
|
348
|
+
end
|
|
349
|
+
fail ArgumentError, 'Duplicate ip values for range' unless
|
|
350
|
+
ip_list.size == ip_list.uniq.size
|
|
351
|
+
# reset the current ranges first due to bug CSCuz98937
|
|
352
|
+
cur_list = range
|
|
353
|
+
cur_list.each do |ip, _not_advertise, _cval|
|
|
354
|
+
set_args_keys(state: 'no', ip: ip, not_advertise: '',
|
|
355
|
+
cost: '', value: '')
|
|
356
|
+
config_set('ospf_area', 'range', @set_args)
|
|
357
|
+
end
|
|
358
|
+
# now set the range from the set_list
|
|
359
|
+
set_list.each do |ip, noadv, cval|
|
|
360
|
+
na = noadv == 'not_advertise' ? 'not-advertise' : ''
|
|
361
|
+
cost = cval ? 'cost' : ''
|
|
362
|
+
value = cval ? cval : ''
|
|
363
|
+
# in case of 2 variables, ip and cost
|
|
364
|
+
if noadv && noadv != 'not_advertise'
|
|
365
|
+
cost = 'cost'
|
|
366
|
+
value = noadv
|
|
367
|
+
end
|
|
368
|
+
set_args_keys(state: '', ip: ip, not_advertise: na,
|
|
369
|
+
cost: cost, value: value)
|
|
370
|
+
config_set('ospf_area', 'range', @set_args)
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
def default_range
|
|
375
|
+
config_get_default('ospf_area', 'range')
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
def stub
|
|
379
|
+
config_get('ospf_area', 'stub', @get_args)
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
def stub=(val)
|
|
383
|
+
state = val ? '' : 'no'
|
|
384
|
+
set_args_keys(state: state)
|
|
385
|
+
config_set('ospf_area', 'stub', @set_args)
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def default_stub
|
|
389
|
+
config_get_default('ospf_area', 'stub')
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def stub_no_summary
|
|
393
|
+
config_get('ospf_area', 'stub_no_summary', @get_args)
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def stub_no_summary=(val)
|
|
397
|
+
if val
|
|
398
|
+
state = ''
|
|
399
|
+
set_args_keys(state: state)
|
|
400
|
+
config_set('ospf_area', 'stub_no_summary', @set_args)
|
|
401
|
+
else
|
|
402
|
+
if stub
|
|
403
|
+
# reset and set stub
|
|
404
|
+
set_args_keys(state: 'no')
|
|
405
|
+
config_set('ospf_area', 'stub', @set_args)
|
|
406
|
+
set_args_keys(state: '')
|
|
407
|
+
config_set('ospf_area', 'stub', @set_args)
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
def default_stub_no_summary
|
|
413
|
+
config_get_default('ospf_area', 'stub_no_summary')
|
|
414
|
+
end
|
|
415
|
+
end # class
|
|
416
|
+
end # module
|