cisco_node_utils 1.4.1 → 1.5.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/CHANGELOG.md +30 -0
- data/README.md +8 -7
- data/docs/README-maintainers.md +0 -1
- data/lib/cisco_node_utils/aaa_authentication_login_service.rb +2 -2
- data/lib/cisco_node_utils/bgp.rb +2 -2
- data/lib/cisco_node_utils/cisco_cmn_utils.rb +16 -0
- data/lib/cisco_node_utils/client/utils.rb +7 -1
- data/lib/cisco_node_utils/cmd_ref/DEPRECATED.yaml +12 -12
- data/lib/cisco_node_utils/cmd_ref/README_YAML.md +35 -7
- data/lib/cisco_node_utils/cmd_ref/aaa_authorization_service.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/bfd_global.yaml +4 -4
- data/lib/cisco_node_utils/cmd_ref/bgp_af.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/bgp_neighbor_af.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/bridge_domain.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/bridge_domain_vni.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/dhcp_relay_global.yaml +5 -5
- data/lib/cisco_node_utils/cmd_ref/encapsulation.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/fabricpath.yaml +5 -5
- data/lib/cisco_node_utils/cmd_ref/fabricpath_topology.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/feature.yaml +8 -3
- data/lib/cisco_node_utils/cmd_ref/hsrp_global.yaml +25 -0
- data/lib/cisco_node_utils/cmd_ref/interface.yaml +65 -14
- data/lib/cisco_node_utils/cmd_ref/interface_hsrp_group.yaml +117 -0
- data/lib/cisco_node_utils/cmd_ref/interface_portchannel.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/interface_service_vni.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/inventory.yaml +4 -8
- data/lib/cisco_node_utils/cmd_ref/itd_device_group.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/itd_service.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/ospf.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/pim.yaml +6 -0
- data/lib/cisco_node_utils/cmd_ref/portchannel_global.yaml +9 -9
- data/lib/cisco_node_utils/cmd_ref/snmp_server.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/stp_global.yaml +8 -8
- data/lib/cisco_node_utils/cmd_ref/vdc.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/vlan.yaml +16 -8
- data/lib/cisco_node_utils/cmd_ref/vpc.yaml +11 -11
- data/lib/cisco_node_utils/cmd_ref/vrf.yaml +2 -1
- data/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml +1 -1
- data/lib/cisco_node_utils/command_reference.rb +8 -1
- data/lib/cisco_node_utils/domain_name.rb +17 -2
- data/lib/cisco_node_utils/feature.rb +14 -0
- data/lib/cisco_node_utils/hsrp_global.rb +97 -0
- data/lib/cisco_node_utils/interface.rb +146 -0
- data/lib/cisco_node_utils/interface_hsrp_group.rb +544 -0
- data/lib/cisco_node_utils/node.rb +93 -4
- data/lib/cisco_node_utils/pim.rb +17 -0
- data/lib/cisco_node_utils/portchannel_global.rb +2 -2
- data/lib/cisco_node_utils/version.rb +1 -1
- data/lib/cisco_node_utils/vlan.rb +2 -5
- data/lib/cisco_node_utils/yum.rb +11 -6
- data/spec/schema.yaml +3 -3
- data/tests/ciscotest.rb +25 -4
- data/tests/cmd_config.yaml +0 -2
- data/tests/test_bgp_af.rb +13 -2
- data/tests/test_feature.rb +5 -0
- data/tests/test_hsrp_global.rb +79 -0
- data/tests/test_interface.rb +23 -0
- data/tests/test_interface_hsrp.rb +134 -0
- data/tests/test_interface_hsrp_group.rb +582 -0
- data/tests/test_node_ext.rb +7 -1
- data/tests/test_pim.rb +27 -3
- data/tests/test_platform.rb +1 -1
- data/tests/test_radius_global.rb +4 -5
- data/tests/test_radius_server.rb +16 -11
- data/tests/test_router_bgp.rb +11 -6
- data/tests/test_router_ospf_area.rb +6 -6
- data/tests/test_tacacs_server.rb +2 -2
- data/tests/test_tacacs_server_host.rb +2 -2
- data/tests/test_vlan.rb +14 -0
- data/tests/test_yum.rb +2 -2
- data/tests/yum_package.yaml +4 -0
- metadata +10 -3
@@ -56,7 +56,7 @@ module Cisco
|
|
56
56
|
# If we have a default value but no getter, just return the default
|
57
57
|
return ref.default_value if ref.default_value? && !ref.getter?
|
58
58
|
|
59
|
-
get_args = ref.getter(*args)
|
59
|
+
get_args, ref = massage_structured(ref.getter(*args).clone, ref)
|
60
60
|
massage(get(command: ref.get_command,
|
61
61
|
data_format: get_args[:data_format],
|
62
62
|
context: get_args[:context],
|
@@ -64,18 +64,80 @@ module Cisco
|
|
64
64
|
ref)
|
65
65
|
end
|
66
66
|
|
67
|
+
# The yaml file may specifiy an Array as the get_value to drill down into
|
68
|
+
# nxapi_structured table output. The table may contain multiple rows but
|
69
|
+
# only one of the rows has the interesting data.
|
70
|
+
def massage_structured(get_args, ref)
|
71
|
+
# Nothing to do unless nxapi_structured.
|
72
|
+
return [get_args, ref] unless
|
73
|
+
ref.hash['get_data_format'] == :nxapi_structured
|
74
|
+
|
75
|
+
# The CmdRef object will contain a get_value Array with 2 values.
|
76
|
+
# The first value is the key to identify the correct row in the table
|
77
|
+
# of structured output and the second is the key to identify the data
|
78
|
+
# to retrieve.
|
79
|
+
#
|
80
|
+
# Example: Get vlanshowbr-vlanname in the row that contains a specific
|
81
|
+
# vlan_id.
|
82
|
+
# "get_value"=>["vlanshowbr-vlanid-utf <vlan_id>", "vlanshowbr-vlanname"]
|
83
|
+
if ref.hash['get_value'].is_a?(Array) && ref.hash['get_value'].size >= 2
|
84
|
+
# Replace the get_value hash entry with the value after any tokens
|
85
|
+
# specified in the yaml file have been replaced and set get_args[:value]
|
86
|
+
# to nil so that the structured table data can be retrieved properly.
|
87
|
+
ref.hash['get_value'] = get_args[:value]
|
88
|
+
ref.hash['drill_down'] = true
|
89
|
+
get_args[:value] = nil
|
90
|
+
end
|
91
|
+
cache_flush
|
92
|
+
[get_args, ref]
|
93
|
+
end
|
94
|
+
|
95
|
+
# Drill down into structured nxapi table data and return value from the
|
96
|
+
# row specified by a two part key.
|
97
|
+
#
|
98
|
+
# Example: Get vlanshowbr-vlanname in the row that contains vlan id 1000
|
99
|
+
# "get_value"=>["vlanshowbr-vlanid-utf 1000", "vlanshowbr-vlanname"]
|
100
|
+
# Example with optional regexp match
|
101
|
+
# "get_value"=>["vlanshowbr-vlanid-utf 1000", "vlanshowbr-vlanname",
|
102
|
+
# '/^shutdown$/']
|
103
|
+
def drill_down_structured(value, ref)
|
104
|
+
# Nothing to do unless nxapi_structured
|
105
|
+
return value unless ref.hash['drill_down']
|
106
|
+
|
107
|
+
row_key = ref.hash['get_value'][0][/^\S+/]
|
108
|
+
row_index = ref.hash['get_value'][0][/\S+$/]
|
109
|
+
data_key = ref.hash['get_value'][1]
|
110
|
+
regexp_filter = nil
|
111
|
+
regexp_filter = ref.hash['get_value'][2] if ref.hash['get_value'][2]
|
112
|
+
|
113
|
+
# Get the value using the row_key, row_index and data_key
|
114
|
+
value = value.is_a?(Hash) ? [value] : value
|
115
|
+
data = value.find { |item| item[row_key].to_s[/#{row_index}/] }
|
116
|
+
return value if data.nil?
|
117
|
+
if regexp_filter
|
118
|
+
filtered = regexp_filter.match(data[data_key])
|
119
|
+
return filtered.nil? ? filtered : filtered[0]
|
120
|
+
end
|
121
|
+
data[data_key]
|
122
|
+
end
|
123
|
+
|
67
124
|
# Attempt to massage the given value into the format specified by the
|
68
125
|
# given CmdRef object.
|
69
126
|
def massage(value, ref)
|
70
127
|
Cisco::Logger.debug "Massaging '#{value}' (#{value.inspect})"
|
128
|
+
value = drill_down_structured(value, ref)
|
71
129
|
if value.is_a?(Array) && !ref.multiple
|
72
130
|
fail "Expected zero/one value but got '#{value}'" if value.length > 1
|
73
131
|
value = value[0]
|
74
132
|
end
|
75
|
-
if (value.nil? || value.empty?) &&
|
133
|
+
if (value.nil? || value.to_s.empty?) &&
|
134
|
+
ref.default_value? && ref.auto_default
|
76
135
|
Cisco::Logger.debug "Default: #{ref.default_value}"
|
77
136
|
return ref.default_value
|
78
137
|
end
|
138
|
+
if ref.multiple && ref.hash['get_data_format'] == :nxapi_structured
|
139
|
+
value = [value.to_s] if value.size == 1
|
140
|
+
end
|
79
141
|
return value unless ref.kind
|
80
142
|
case ref.kind
|
81
143
|
when :boolean
|
@@ -254,13 +316,16 @@ module Cisco
|
|
254
316
|
# @return [String] such as "N3K-C3048TP-1GE"
|
255
317
|
def product_id
|
256
318
|
if @cmd_ref
|
257
|
-
|
319
|
+
prod = config_get('inventory', 'productid')
|
320
|
+
all = config_get('inventory', 'all')
|
321
|
+
prod_qualifier(prod, all)
|
258
322
|
else
|
259
323
|
# We use this function to *find* the appropriate CommandReference
|
260
324
|
if @client.platform == :nexus
|
261
325
|
entries = get(command: 'show inventory',
|
262
326
|
data_format: :nxapi_structured)
|
263
|
-
|
327
|
+
prod = entries['TABLE_inv']['ROW_inv'][0]['productid']
|
328
|
+
prod_qualifier(prod, entries['TABLE_inv']['ROW_inv'])
|
264
329
|
elsif @client.platform == :ios_xr
|
265
330
|
# No support for structured output for this command yet
|
266
331
|
output = get(command: 'show inventory',
|
@@ -270,6 +335,30 @@ module Cisco
|
|
270
335
|
end
|
271
336
|
end
|
272
337
|
|
338
|
+
def prod_qualifier(prod, inventory)
|
339
|
+
case prod
|
340
|
+
when /N9K/
|
341
|
+
# Two datapoints are used to determine if the current n9k
|
342
|
+
# platform is a fretta based n9k or non-fretta.
|
343
|
+
#
|
344
|
+
# 1) Image Version == 7.0(3)F*
|
345
|
+
# 2) Fabric Module == N9K-C9*-FM-R
|
346
|
+
if @cmd_ref
|
347
|
+
ver = os_version
|
348
|
+
else
|
349
|
+
ver = get(command: 'show version',
|
350
|
+
data_format: :nxapi_structured)['kickstart_ver_str']
|
351
|
+
end
|
352
|
+
# Append -F for fretta platform.
|
353
|
+
inventory.each do |row|
|
354
|
+
if row['productid'][/N9K-C9...-FM-R/] && ver[/7.0\(3\)F/]
|
355
|
+
return prod.concat('-F') unless prod[/-F/]
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
prod
|
360
|
+
end
|
361
|
+
|
273
362
|
# @return [String] such as "V01"
|
274
363
|
def product_version_id
|
275
364
|
config_get('inventory', 'versionid')
|
data/lib/cisco_node_utils/pim.rb
CHANGED
@@ -90,6 +90,7 @@ module Cisco
|
|
90
90
|
def destroy
|
91
91
|
return unless Feature.pim_enabled?
|
92
92
|
self.ssm_range = ''
|
93
|
+
self.bfd = false
|
93
94
|
end
|
94
95
|
|
95
96
|
#-----------
|
@@ -110,5 +111,21 @@ module Cisco
|
|
110
111
|
set_args_keys(state: state, ssm_range: range)
|
111
112
|
config_set('pim', 'ssm_range', @set_args)
|
112
113
|
end
|
114
|
+
|
115
|
+
def bfd
|
116
|
+
config_get('pim', 'bfd', @get_args)
|
117
|
+
end
|
118
|
+
|
119
|
+
def bfd=(val)
|
120
|
+
return if val == bfd
|
121
|
+
state = val ? '' : 'no'
|
122
|
+
set_args_keys(state: state)
|
123
|
+
Feature.bfd_enable if val
|
124
|
+
config_set('pim', 'bfd', @set_args)
|
125
|
+
end
|
126
|
+
|
127
|
+
def default_bfd
|
128
|
+
config_get_default('pim', 'bfd')
|
129
|
+
end
|
113
130
|
end # Class
|
114
131
|
end # Module
|
@@ -113,7 +113,7 @@ module Cisco
|
|
113
113
|
_parse_ethernet_params(hash, params)
|
114
114
|
when :asymmetric # n7k
|
115
115
|
_parse_asymmetric_params(hash, params, line)
|
116
|
-
when :no_hash #
|
116
|
+
when :no_hash # n9k-f
|
117
117
|
_parse_no_hash_params(hash, params)
|
118
118
|
when :symmetry # n9k
|
119
119
|
_parse_symmetry_params(hash, params, line)
|
@@ -213,7 +213,7 @@ module Cisco
|
|
213
213
|
# port-channel load-balance dst ip-l4port rotate 4 asymmetric
|
214
214
|
config_set('portchannel_global', 'port_channel_load_balance',
|
215
215
|
bselect, bhash, 'rotate', rot.to_s, asym, '')
|
216
|
-
when :no_hash #
|
216
|
+
when :no_hash # n9k-f
|
217
217
|
# port-channel load-balance dst ip-l4port rotate 4
|
218
218
|
rot_str = rot.zero? ? '' : 'rotate'
|
219
219
|
rot_val = rot.zero? ? '' : rot.to_s
|
@@ -14,7 +14,7 @@
|
|
14
14
|
|
15
15
|
# Container module for version number only.
|
16
16
|
module CiscoNodeUtils
|
17
|
-
VERSION = '1.
|
17
|
+
VERSION = '1.5.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
|
@@ -141,8 +141,7 @@ module Cisco
|
|
141
141
|
end
|
142
142
|
|
143
143
|
def vlan_name
|
144
|
-
|
145
|
-
result.nil? ? default_vlan_name : result
|
144
|
+
config_get('vlan', 'name', vlanid: @vlan_id)
|
146
145
|
end
|
147
146
|
|
148
147
|
def vlan_name=(str)
|
@@ -184,9 +183,7 @@ module Cisco
|
|
184
183
|
end
|
185
184
|
|
186
185
|
def shutdown
|
187
|
-
|
188
|
-
# Valid result is either: "active"(aka no shutdown) or "shutdown"
|
189
|
-
result[/shut/] ? true : false
|
186
|
+
config_get('vlan', 'shutdown', vlanid: @vlan_id)
|
190
187
|
end
|
191
188
|
|
192
189
|
def shutdown=(val)
|
data/lib/cisco_node_utils/yum.rb
CHANGED
@@ -52,13 +52,18 @@ module Cisco
|
|
52
52
|
|
53
53
|
def self.install(pkg, vrf=nil)
|
54
54
|
vrf = vrf.nil? ? detect_vrf : "vrf #{vrf}"
|
55
|
-
config_set('yum', 'install', pkg, vrf)
|
56
55
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
56
|
+
begin
|
57
|
+
config_set('yum', 'install', pkg, vrf)
|
58
|
+
|
59
|
+
# HACK: The current nxos host installer is a multi-part command
|
60
|
+
# which may fail at a later stage yet return a false positive;
|
61
|
+
# therefore a post-validation check is needed here to verify the
|
62
|
+
# actual outcome.
|
63
|
+
validate_installed(pkg)
|
64
|
+
rescue Cisco::CliError, RuntimeError => e
|
65
|
+
raise Cisco::CliError, "#{e.class}, #{e.message}"
|
66
|
+
end
|
62
67
|
end
|
63
68
|
|
64
69
|
# returns version of package, or false if package doesn't exist
|
data/spec/schema.yaml
CHANGED
@@ -19,8 +19,8 @@ mapping:
|
|
19
19
|
- 'N5k'
|
20
20
|
- 'N6k'
|
21
21
|
- 'N7k'
|
22
|
-
- 'N8k'
|
23
22
|
- 'N9k'
|
23
|
+
- 'N9k-F'
|
24
24
|
|
25
25
|
=: &base # default rule - apply to all properties
|
26
26
|
type: map
|
@@ -36,8 +36,8 @@ mapping:
|
|
36
36
|
N5k: *base
|
37
37
|
N6k: *base
|
38
38
|
N7k: *base
|
39
|
-
N8k: *base
|
40
39
|
N9k: *base
|
40
|
+
N9k-F: *base
|
41
41
|
# 'else' case if not matching any filter above
|
42
42
|
else: *base
|
43
43
|
# Generally applicable attributes
|
@@ -62,7 +62,7 @@ mapping:
|
|
62
62
|
get_data_format: *data_format
|
63
63
|
get_context: *context
|
64
64
|
get_value:
|
65
|
-
type:
|
65
|
+
type: any
|
66
66
|
kind:
|
67
67
|
type: str
|
68
68
|
enum: [boolean, int, string, symbol]
|
data/tests/ciscotest.rb
CHANGED
@@ -260,7 +260,7 @@ class CiscoTestCase < TestCase
|
|
260
260
|
Vrf.vrfs.each do |vrf, obj|
|
261
261
|
next if vrf[/management/]
|
262
262
|
# TBD: Remove vrf workaround below after CSCuz56697 is resolved
|
263
|
-
config 'vrf context ' + vrf if node.product_id[/
|
263
|
+
config 'vrf context ' + vrf if node.product_id[/N9K.*-F/]
|
264
264
|
obj.destroy
|
265
265
|
end
|
266
266
|
end
|
@@ -424,7 +424,7 @@ class CiscoTestCase < TestCase
|
|
424
424
|
# Returns the output of the command.
|
425
425
|
def shell_command(command, context='bash')
|
426
426
|
fail "shell_command api not supported on #{node.product_id}" unless
|
427
|
-
node.product_id[/N3K|
|
427
|
+
node.product_id[/N3K|N9K.*-F|N9K/]
|
428
428
|
unless context == 'bash' || context == 'guestshell'
|
429
429
|
fail "Context must be either 'bash' or 'guestshell'"
|
430
430
|
end
|
@@ -434,7 +434,7 @@ class CiscoTestCase < TestCase
|
|
434
434
|
def backup_resolv_file(context='bash')
|
435
435
|
# Configuration bleeding is only a problem on some platforms, so
|
436
436
|
# only backup the resolv.conf file on required plaforms.
|
437
|
-
return unless node.product_id[/N3K|
|
437
|
+
return unless node.product_id[/N3K|N9K.*-F|N9K/]
|
438
438
|
time_stamp = Time.now.strftime('%Y-%m-%d_%H-%M-%S')
|
439
439
|
backup_filename = "/tmp/resolv.conf.#{time_stamp}"
|
440
440
|
shell_command("cp /etc/resolv.conf #{backup_filename}", context)
|
@@ -442,7 +442,7 @@ class CiscoTestCase < TestCase
|
|
442
442
|
end
|
443
443
|
|
444
444
|
def restore_resolv_file(filename, context='bash')
|
445
|
-
return unless node.product_id[/N3K|
|
445
|
+
return unless node.product_id[/N3K|N9K.*-F|N9K/]
|
446
446
|
shell_command("sudo cp #{filename} /etc/resolv.conf", context)
|
447
447
|
shell_command("rm #{filename}", context)
|
448
448
|
end
|
@@ -460,4 +460,25 @@ class CiscoTestCase < TestCase
|
|
460
460
|
v.limit_resource_module_type
|
461
461
|
end
|
462
462
|
end
|
463
|
+
|
464
|
+
# Helper method to massage node.product_id into a short but
|
465
|
+
# meaningful tag to represent the product_type.
|
466
|
+
def product_tag
|
467
|
+
@product_id ||= node.product_id
|
468
|
+
case @product_id
|
469
|
+
when /N3/
|
470
|
+
tag = 'n3k'
|
471
|
+
when /N5/
|
472
|
+
tag = 'n5k'
|
473
|
+
when /N6/
|
474
|
+
tag = 'n6k'
|
475
|
+
when /N7/
|
476
|
+
tag = 'n7k'
|
477
|
+
when /N9/
|
478
|
+
tag = Utils.image_version?(/7.0.3.F/) ? 'n9k-f' : 'n9k'
|
479
|
+
else
|
480
|
+
fail "Unrecognized product_id: #{@product_id}"
|
481
|
+
end
|
482
|
+
tag
|
483
|
+
end
|
463
484
|
end
|
data/tests/cmd_config.yaml
CHANGED
@@ -8,7 +8,6 @@ nexus:
|
|
8
8
|
feature bgp
|
9
9
|
feature pim
|
10
10
|
feature msdp
|
11
|
-
feature udld
|
12
11
|
feature interface-vlan
|
13
12
|
feature hsrp
|
14
13
|
feature lacp
|
@@ -22,7 +21,6 @@ nexus:
|
|
22
21
|
no feature bgp
|
23
22
|
no feature pim
|
24
23
|
no feature msdp
|
25
|
-
no feature udld
|
26
24
|
no feature interface-vlan
|
27
25
|
no feature hsrp
|
28
26
|
no feature lacp
|
data/tests/test_bgp_af.rb
CHANGED
@@ -46,7 +46,6 @@ class TestBgpAF < CiscoTestCase
|
|
46
46
|
|
47
47
|
# Disabling line length to support wide-format test matrix definition
|
48
48
|
# rubocop:disable Metrics/LineLength
|
49
|
-
|
50
49
|
# Address Families to test:
|
51
50
|
T_AFS = [
|
52
51
|
# afi safi
|
@@ -124,6 +123,10 @@ class TestBgpAF < CiscoTestCase
|
|
124
123
|
|
125
124
|
# Tests that are successful even though a rule below says otherwise
|
126
125
|
[:next_hop_route_map, :nexus, 'default', %w(l2vpn evpn), :success],
|
126
|
+
[:additional_paths_send, :nexus, 'default', %w(l2vpn evpn), :runtime],
|
127
|
+
[:additional_paths_selection, :nexus, 'default', %w(l2vpn evpn), :runtime],
|
128
|
+
[:maximum_paths, :nexus, 'default', %w(l2vpn evpn), :runtime],
|
129
|
+
[:maximum_paths_ibgp, :nexus, 'default', %w(l2vpn evpn), :runtime],
|
127
130
|
|
128
131
|
# XR CLI Errors
|
129
132
|
[:additional_paths_send, :ios_xr, :any, :multicast, :CliError],
|
@@ -158,6 +161,15 @@ class TestBgpAF < CiscoTestCase
|
|
158
161
|
(af == :multicast && (af_.include? 'multicast')) ||
|
159
162
|
(af == :ipv4 && (af_.include? 'ipv4')) ||
|
160
163
|
(af == :ipv6 && (af_.include? 'ipv6')))
|
164
|
+
|
165
|
+
# We need a connection to the device under test so that we can
|
166
|
+
# query the image version to determine if some properties are
|
167
|
+
# supported. When TEST_EXCEPTIONS is defined, no connection
|
168
|
+
# to the device is available. If the entry is :runtime this
|
169
|
+
# triggers a version check below.
|
170
|
+
if expect == :runtime
|
171
|
+
expect = Utils.image_version?(/8.0/) ? :success : :CliError
|
172
|
+
end
|
161
173
|
return expect if expect == :success || expect == :skip
|
162
174
|
|
163
175
|
# Otherwise, make sure there's no ambiguity/overlap in the exceptions.
|
@@ -196,7 +208,6 @@ class TestBgpAF < CiscoTestCase
|
|
196
208
|
|
197
209
|
# What result do we expect from this test?
|
198
210
|
expect = check_test_exceptions(test, platform, vrf, af)
|
199
|
-
|
200
211
|
# Gather initial value, default value, and the first test value..
|
201
212
|
initial = bgp_af.send(test)
|
202
213
|
|
data/tests/test_feature.rb
CHANGED
@@ -32,6 +32,7 @@ class TestFeature < CiscoTestCase
|
|
32
32
|
'no feature dhcp',
|
33
33
|
'no feature fabric forwarding',
|
34
34
|
'no feature-set fex',
|
35
|
+
'no feature hsrp',
|
35
36
|
'no feature itd',
|
36
37
|
'no feature nv overlay',
|
37
38
|
'no feature ospf',
|
@@ -97,6 +98,10 @@ class TestFeature < CiscoTestCase
|
|
97
98
|
feature('dhcp')
|
98
99
|
end
|
99
100
|
|
101
|
+
def test_hsrp
|
102
|
+
feature('hsrp')
|
103
|
+
end
|
104
|
+
|
100
105
|
def test_fabric_forwarding
|
101
106
|
if node.product_id[/N(3)/]
|
102
107
|
assert_nil(Feature.fabric_forwarding_enabled?)
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# Copyright (c) 2016 Cisco and/or its affiliates.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require_relative 'ciscotest'
|
16
|
+
require_relative '../lib/cisco_node_utils/hsrp_global'
|
17
|
+
|
18
|
+
include Cisco
|
19
|
+
# TestHsrpGlobal - Minitest for general functionality
|
20
|
+
# of the HsrpGlobal class.
|
21
|
+
class TestHsrpGlobal < CiscoTestCase
|
22
|
+
@skip_unless_supported = 'hsrp_global'
|
23
|
+
|
24
|
+
# Tests
|
25
|
+
def setup
|
26
|
+
super
|
27
|
+
config_no_warn('no feature hsrp')
|
28
|
+
end
|
29
|
+
|
30
|
+
def teardown
|
31
|
+
config_no_warn('no feature hsrp') if first_or_last_teardown
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_collection_empty
|
36
|
+
hg = HsrpGlobal.globals
|
37
|
+
assert_empty(hg)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_destroy
|
41
|
+
hg = HsrpGlobal.new
|
42
|
+
assert_equal(true, Feature.hsrp_enabled?)
|
43
|
+
|
44
|
+
hg.destroy
|
45
|
+
[:bfd_all_intf,
|
46
|
+
:extended_hold,
|
47
|
+
].each do |prop|
|
48
|
+
assert_equal(hg.send("default_#{prop}"), hg.send("#{prop}")) if
|
49
|
+
hg.send("#{prop}")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_bfd_all_intf
|
54
|
+
hg = HsrpGlobal.new
|
55
|
+
if validate_property_excluded?('hsrp_global', 'bfd_all_intf')
|
56
|
+
assert_nil(hg.bfd_all_intf)
|
57
|
+
assert_raises(Cisco::UnsupportedError) do
|
58
|
+
hg.bfd_all_intf = true
|
59
|
+
end
|
60
|
+
return
|
61
|
+
end
|
62
|
+
assert_equal(hg.default_bfd_all_intf, hg.bfd_all_intf)
|
63
|
+
hg.bfd_all_intf = true
|
64
|
+
assert_equal(true, hg.bfd_all_intf)
|
65
|
+
hg.bfd_all_intf = hg.default_bfd_all_intf
|
66
|
+
assert_equal(hg.default_bfd_all_intf, hg.bfd_all_intf)
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_extended_hold
|
70
|
+
hg = HsrpGlobal.new
|
71
|
+
assert_equal(hg.default_extended_hold, hg.extended_hold)
|
72
|
+
hg.extended_hold = '100'
|
73
|
+
assert_equal('100', hg.extended_hold)
|
74
|
+
hg.extended_hold = '10'
|
75
|
+
assert_equal('10', hg.extended_hold)
|
76
|
+
hg.extended_hold = hg.default_extended_hold
|
77
|
+
assert_equal(hg.default_extended_hold, hg.extended_hold)
|
78
|
+
end
|
79
|
+
end
|