cisco_node_utils 1.4.1 → 1.5.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 +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
|