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
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# June 2016, Charles Burkett
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2015-2016 Cisco and/or its affiliates.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
require 'json'
|
|
18
|
+
|
|
19
|
+
module Cisco
|
|
20
|
+
# class Cisco::Yang
|
|
21
|
+
# Utility class mainly containing methods to compare YANG configurations
|
|
22
|
+
# in order to determine if the running config is in-sync with the
|
|
23
|
+
# desired config.
|
|
24
|
+
class Yang
|
|
25
|
+
# Is the specified yang string empty?
|
|
26
|
+
def self.empty?(yang)
|
|
27
|
+
!yang || yang.empty?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Given target and current YANG configurations, returns true if
|
|
31
|
+
# the configurations are in-sync, relative to a "merge_config" action
|
|
32
|
+
# @param should [String] the should configuration in YANG JASON format
|
|
33
|
+
# @param is [String] the is configuration in YANG JASON format
|
|
34
|
+
def self.insync_for_merge?(should, is)
|
|
35
|
+
should_hash = self.empty?(should) ? {} : JSON.parse(should)
|
|
36
|
+
is_hash = self.empty?(is) ? {} : JSON.parse(is)
|
|
37
|
+
|
|
38
|
+
!needs_something?(:merge, should_hash, is_hash)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Given a is and should YANG configuration, returns true if
|
|
42
|
+
# the configuration are in-sync, relative to a "replace_config" action
|
|
43
|
+
# @param should [String] the should configuration in YANG JASON format
|
|
44
|
+
# @param is [String] the is configuration in YANG JASON format
|
|
45
|
+
def self.insync_for_replace?(should, is)
|
|
46
|
+
should_hash = self.empty?(should) ? {} : JSON.parse(should)
|
|
47
|
+
is_hash = self.empty?(is) ? {} : JSON.parse(is)
|
|
48
|
+
|
|
49
|
+
!needs_something?(:replace, should_hash, is_hash)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# usage:
|
|
53
|
+
# needs_something?(op, should, run)
|
|
54
|
+
#
|
|
55
|
+
# op - symbol - If value is not :replace, it's assumed to be :merge.
|
|
56
|
+
# Indicates to the function whether to check for a
|
|
57
|
+
# possible merge vs. replace
|
|
58
|
+
#
|
|
59
|
+
# should - JSON - JSON tree representing target configuration
|
|
60
|
+
#
|
|
61
|
+
# is - JSON - JSON tree representing current configuration
|
|
62
|
+
#
|
|
63
|
+
#
|
|
64
|
+
# Needs merge will determine if should and is differ
|
|
65
|
+
# sufficiently to necessitate running the merge command.
|
|
66
|
+
#
|
|
67
|
+
# The logic here amounts to determining if should is a subtree
|
|
68
|
+
# of is, with a tiny bit of domain trickiness surrounding
|
|
69
|
+
# elements that are arrays that contain a single nil element
|
|
70
|
+
# that is required for "creating" certain configuration elements.
|
|
71
|
+
#
|
|
72
|
+
# There are ultimately 3 different types of elements in a json
|
|
73
|
+
# tree. Hashes, Arrays, and leaves. While hashes and array values
|
|
74
|
+
# are organized with an order, the logic here ignores the order.
|
|
75
|
+
# In fact, it specifically attempts to match assuming order
|
|
76
|
+
# doesn't matter. This is largely to allow users some freedom
|
|
77
|
+
# in specifying the target configuration. The gRPC interface
|
|
78
|
+
# doesn't seem to care about order. If that changes, then so
|
|
79
|
+
# should this code.
|
|
80
|
+
#
|
|
81
|
+
# Arrays and Hashes are compared by iterating over every element
|
|
82
|
+
# in should, and ensuring it is within is.
|
|
83
|
+
#
|
|
84
|
+
# Leaves are directly compared for equality, excepting the
|
|
85
|
+
# condition that the should leaf is in fact an array with one
|
|
86
|
+
# element that is nil.
|
|
87
|
+
#
|
|
88
|
+
# Needs replace will determine if should and is differ
|
|
89
|
+
# sufficiently to necessitate running the replace command.
|
|
90
|
+
#
|
|
91
|
+
# The logic is the same as merge, except when comparing
|
|
92
|
+
# hashes, if the is hash table has elements that are not
|
|
93
|
+
# in should, we ultimately indicate that replace is needed
|
|
94
|
+
def self.needs_something?(op, should, is)
|
|
95
|
+
!hash_equiv?(op, should, is)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def self.nil_array(elt)
|
|
99
|
+
elt.nil? || (elt.is_a?(Array) && elt.length == 1 && elt[0].nil?)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def self.sub_elt(op, should, is)
|
|
103
|
+
if should.is_a?(Hash) && is.is_a?(Hash)
|
|
104
|
+
return self.hash_equiv?(op, should, is)
|
|
105
|
+
elsif should.is_a?(Array) && is.is_a?(Array)
|
|
106
|
+
return self.array_equiv?(op, should, is)
|
|
107
|
+
else
|
|
108
|
+
return !(should != is && !nil_array(should))
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def self.array_equiv?(op, should, is)
|
|
113
|
+
n = should.length
|
|
114
|
+
loop = lambda do|i|
|
|
115
|
+
if i == n
|
|
116
|
+
if op == :replace
|
|
117
|
+
is.length == should.length
|
|
118
|
+
else
|
|
119
|
+
true
|
|
120
|
+
end
|
|
121
|
+
else
|
|
122
|
+
should_elt = should[i]
|
|
123
|
+
is_elt = is.find do |elt|
|
|
124
|
+
sub_elt(op, should_elt, elt)
|
|
125
|
+
end
|
|
126
|
+
if is_elt.nil? && !nil_array(should_elt)
|
|
127
|
+
should_elt.nil?
|
|
128
|
+
else
|
|
129
|
+
loop.call(i + 1)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
loop.call(0)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def self.hash_equiv?(op, should, is)
|
|
137
|
+
keys = should.keys
|
|
138
|
+
n = keys.length
|
|
139
|
+
loop = lambda do|i|
|
|
140
|
+
if i == n
|
|
141
|
+
if op == :replace
|
|
142
|
+
is.keys.length == should.keys.length
|
|
143
|
+
else
|
|
144
|
+
true
|
|
145
|
+
end
|
|
146
|
+
else
|
|
147
|
+
k = keys[i]
|
|
148
|
+
is_v = is[k]
|
|
149
|
+
should_v = should[k]
|
|
150
|
+
if is_v.nil? && !nil_array(should_v)
|
|
151
|
+
false
|
|
152
|
+
else
|
|
153
|
+
sub_elt(op, should_v, is_v) && loop.call(i + 1)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
loop.call(0)
|
|
158
|
+
end
|
|
159
|
+
end # Yang
|
|
160
|
+
end # Cisco
|
data/lib/cisco_node_utils/yum.rb
CHANGED
|
@@ -22,38 +22,22 @@ require_relative 'node_util'
|
|
|
22
22
|
module Cisco
|
|
23
23
|
# This Yum class provides cisco package management functions through nxapi.
|
|
24
24
|
class Yum < NodeUtil
|
|
25
|
-
def self.
|
|
26
|
-
#
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def self.validate(pkg)
|
|
41
|
-
file_name = pkg.strip.tr(':', '/').split('/').last
|
|
42
|
-
pkg_info = Yum.decompose_name(file_name)
|
|
43
|
-
if pkg_info.nil?
|
|
44
|
-
query_name = file_name
|
|
45
|
-
else
|
|
46
|
-
if pkg_info[3].nil?
|
|
47
|
-
query_name = pkg_info[1]
|
|
48
|
-
else
|
|
49
|
-
query_name = "#{pkg_info[1]}.#{pkg_info[3]}"
|
|
25
|
+
def self.validate_installed(pkg)
|
|
26
|
+
# Sample data returned from config_get('yum', 'query_all')
|
|
27
|
+
# ["nxos.sample-n8k_EOR.lib32_nxos", "1.0.0-7.0.3.F1.1", "@patching"],
|
|
28
|
+
patch_data = config_get('yum', 'query_all')
|
|
29
|
+
patch_data.each do |name_arch, version, _state|
|
|
30
|
+
# Separate name and architecture
|
|
31
|
+
next if name_arch.rindex('.').nil?
|
|
32
|
+
arch = name_arch.slice!(name_arch.rindex('.')..-1).delete('.')
|
|
33
|
+
# Version/Architecture info not available when only pkg name specified.
|
|
34
|
+
version = arch = '' if name_arch == pkg
|
|
35
|
+
# Check for match
|
|
36
|
+
if pkg.match(name_arch) && pkg.match(version) && pkg.match(arch)
|
|
37
|
+
return true
|
|
50
38
|
end
|
|
51
39
|
end
|
|
52
|
-
|
|
53
|
-
ver = query(query_name)
|
|
54
|
-
if ver.nil? || (!should_ver.nil? && should_ver != ver)
|
|
55
|
-
fail 'Failed to install the requested rpm'
|
|
56
|
-
end
|
|
40
|
+
fail 'Failed to install the requested rpm'
|
|
57
41
|
end
|
|
58
42
|
|
|
59
43
|
def self.detect_vrf
|
|
@@ -61,6 +45,7 @@ module Cisco
|
|
|
61
45
|
inode = File::Stat.new('/proc/self/ns/net').ino
|
|
62
46
|
# -L reqd for guestshell's find command
|
|
63
47
|
vrfname = File.basename(`find -L /var/run/netns/ -inum #{inode}`.chop)
|
|
48
|
+
|
|
64
49
|
vrf = 'vrf ' + vrfname unless vrfname.empty?
|
|
65
50
|
vrf
|
|
66
51
|
end
|
|
@@ -73,7 +58,7 @@ module Cisco
|
|
|
73
58
|
# which may fail at a later stage yet return a false positive;
|
|
74
59
|
# therefore a post-validation check is needed here to verify the
|
|
75
60
|
# actual outcome.
|
|
76
|
-
|
|
61
|
+
validate_installed(pkg)
|
|
77
62
|
end
|
|
78
63
|
|
|
79
64
|
# returns version of package, or false if package doesn't exist
|
|
@@ -86,7 +71,15 @@ module Cisco
|
|
|
86
71
|
end
|
|
87
72
|
|
|
88
73
|
def self.remove(pkg)
|
|
89
|
-
config_set('yum', '
|
|
74
|
+
config_set('yum', 'deactivate', pkg)
|
|
75
|
+
# May not be able to remove the package immediately after
|
|
76
|
+
# deactivation.
|
|
77
|
+
while (try ||= 1) < 20
|
|
78
|
+
o = config_set('yum', 'remove', pkg)
|
|
79
|
+
break unless o[/operation is in progress, please try again later/]
|
|
80
|
+
sleep 1
|
|
81
|
+
try += 1
|
|
82
|
+
end
|
|
90
83
|
end
|
|
91
84
|
end
|
|
92
85
|
end
|
data/tests/.rubocop.yml
CHANGED
data/tests/ciscotest.rb
CHANGED
|
@@ -16,10 +16,11 @@ require 'ipaddr'
|
|
|
16
16
|
require 'resolv'
|
|
17
17
|
require_relative 'basetest'
|
|
18
18
|
require_relative 'platform_info'
|
|
19
|
+
require_relative '../lib/cisco_node_utils/bridge_domain'
|
|
19
20
|
require_relative '../lib/cisco_node_utils/interface'
|
|
20
21
|
require_relative '../lib/cisco_node_utils/node'
|
|
22
|
+
require_relative '../lib/cisco_node_utils/platform'
|
|
21
23
|
require_relative '../lib/cisco_node_utils/vlan'
|
|
22
|
-
require_relative '../lib/cisco_node_utils/bridge_domain'
|
|
23
24
|
|
|
24
25
|
include Cisco
|
|
25
26
|
|
|
@@ -29,7 +30,8 @@ class CiscoTestCase < TestCase
|
|
|
29
30
|
@@node = nil
|
|
30
31
|
@@interfaces = nil
|
|
31
32
|
@@interfaces_id = nil
|
|
32
|
-
|
|
33
|
+
@@testcases = []
|
|
34
|
+
@@testcase_teardowns = 0
|
|
33
35
|
|
|
34
36
|
# The feature (lib/cisco_node_utils/cmd_ref/<feature>.yaml) that this
|
|
35
37
|
# test case is associated with, if applicable.
|
|
@@ -43,6 +45,7 @@ class CiscoTestCase < TestCase
|
|
|
43
45
|
end
|
|
44
46
|
|
|
45
47
|
def self.runnable_methods
|
|
48
|
+
@@testcases = super
|
|
46
49
|
return super if skip_unless_supported.nil?
|
|
47
50
|
return super if node.cmd_ref.supports?(skip_unless_supported)
|
|
48
51
|
# If the entire feature under test is unsupported,
|
|
@@ -52,6 +55,20 @@ class CiscoTestCase < TestCase
|
|
|
52
55
|
[:all_skipped]
|
|
53
56
|
end
|
|
54
57
|
|
|
58
|
+
def first_or_last_teardown
|
|
59
|
+
# Return true if this is the first or last teardown call.
|
|
60
|
+
# This hack is needed to prevent excessive post-test cleanups from
|
|
61
|
+
# occurring: e.g. a non-F3 N7k test class may require an expensive setup
|
|
62
|
+
# and teardown to enable/disable vdc settings; ideally this vdc setup
|
|
63
|
+
# would occur prior to the first test and vdc teardown only after the
|
|
64
|
+
# final test. Checks for first test case because we have to handle the
|
|
65
|
+
# -n option, which filters the list of runnable testcases.
|
|
66
|
+
# Note that Minitest.after_run is not a solution for this problem.
|
|
67
|
+
@@testcase_teardowns += 1
|
|
68
|
+
(@@testcase_teardowns == 1) || (@@testcase_teardowns == @@testcases.size)
|
|
69
|
+
end
|
|
70
|
+
# rubocop:enable Style/ClassVars
|
|
71
|
+
|
|
55
72
|
def all_skipped
|
|
56
73
|
skip("Skipping #{self.class}; feature " \
|
|
57
74
|
"'#{self.class.skip_unless_supported}' is unsupported on this node")
|
|
@@ -100,7 +117,7 @@ class CiscoTestCase < TestCase
|
|
|
100
117
|
|
|
101
118
|
def config_and_warn_on_match(warn_match, *args)
|
|
102
119
|
if node.client.platform == :ios_xr
|
|
103
|
-
result = super(warn_match, *args, 'commit
|
|
120
|
+
result = super(warn_match, *args, 'commit')
|
|
104
121
|
else
|
|
105
122
|
result = super
|
|
106
123
|
end
|
|
@@ -108,6 +125,11 @@ class CiscoTestCase < TestCase
|
|
|
108
125
|
result
|
|
109
126
|
end
|
|
110
127
|
|
|
128
|
+
# Check exception and only fail if it does not contain message
|
|
129
|
+
def check_and_raise_error(exception, message)
|
|
130
|
+
fail exception unless exception.message.include?(message)
|
|
131
|
+
end
|
|
132
|
+
|
|
111
133
|
def ip_address?(ip)
|
|
112
134
|
return IPAddr.new(ip).ipv4?
|
|
113
135
|
rescue IPAddr::InvalidAddressError
|
|
@@ -139,6 +161,13 @@ class CiscoTestCase < TestCase
|
|
|
139
161
|
flunk(message)
|
|
140
162
|
end
|
|
141
163
|
|
|
164
|
+
def incompatible_interface?(msg)
|
|
165
|
+
patterns = ['switchport_mode is not supported on this interface',
|
|
166
|
+
'Configuration does not match the port capability']
|
|
167
|
+
assert_match(Regexp.union(patterns), msg,
|
|
168
|
+
'Msg does not match known incompatibility messages')
|
|
169
|
+
end
|
|
170
|
+
|
|
142
171
|
def validate_property_excluded?(feature, property)
|
|
143
172
|
!node.cmd_ref.supports?(feature, property)
|
|
144
173
|
end
|
|
@@ -148,13 +177,22 @@ class CiscoTestCase < TestCase
|
|
|
148
177
|
Utils.nexus_i2_image
|
|
149
178
|
end
|
|
150
179
|
|
|
180
|
+
def system_image
|
|
181
|
+
@image ||= Platform.system_image
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def skip_legacy_defect?(pattern, msg)
|
|
185
|
+
msg = "Defect in legacy image: [#{msg}]"
|
|
186
|
+
skip(msg) if system_image.match(Regexp.new(pattern))
|
|
187
|
+
end
|
|
188
|
+
|
|
151
189
|
def interfaces
|
|
152
190
|
unless @@interfaces
|
|
153
191
|
# Build the platform_info, used for interface lookup
|
|
154
192
|
# rubocop:disable Style/ClassVars
|
|
155
193
|
@@interfaces = []
|
|
156
194
|
Interface.interfaces.each do |int, obj|
|
|
157
|
-
next unless /
|
|
195
|
+
next unless int[%r{ethernet[\d/]+$}] # exclude dot1q & non-eth
|
|
158
196
|
next if address_match?(obj.ipv4_address)
|
|
159
197
|
@@interfaces << int
|
|
160
198
|
end
|
|
@@ -165,19 +203,6 @@ class CiscoTestCase < TestCase
|
|
|
165
203
|
@@interfaces
|
|
166
204
|
end
|
|
167
205
|
|
|
168
|
-
def interfaces_id
|
|
169
|
-
unless @@interfaces_id
|
|
170
|
-
# rubocop:disable Style/ClassVars
|
|
171
|
-
@@interfaces_id = []
|
|
172
|
-
interfaces.each do |interface|
|
|
173
|
-
id = interface.split('ethernet')[1]
|
|
174
|
-
@@interfaces_id << id
|
|
175
|
-
end
|
|
176
|
-
# rubocop:enable Style/ClassVars
|
|
177
|
-
end
|
|
178
|
-
@@interfaces_id
|
|
179
|
-
end
|
|
180
|
-
|
|
181
206
|
# Remove all router bgps.
|
|
182
207
|
def remove_all_bgps
|
|
183
208
|
require_relative '../lib/cisco_node_utils/bgp'
|
|
@@ -202,16 +227,25 @@ class CiscoTestCase < TestCase
|
|
|
202
227
|
# This testcase will remove all the bds existing in the system
|
|
203
228
|
# specifically in cleanup for minitests
|
|
204
229
|
def remove_all_bridge_domains
|
|
205
|
-
|
|
230
|
+
return unless /N7/ =~ node.product_id
|
|
206
231
|
BridgeDomain.bds.each do |_bd, obj|
|
|
207
232
|
obj.destroy
|
|
208
233
|
end
|
|
234
|
+
config 'system bridge-domain none'
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def remove_all_svis
|
|
238
|
+
Interface.interfaces(:vlan).each do |svi, obj|
|
|
239
|
+
next if svi == 'vlan1'
|
|
240
|
+
obj.destroy
|
|
241
|
+
end
|
|
209
242
|
end
|
|
210
243
|
|
|
211
244
|
# This testcase will remove all the vlans existing in the system
|
|
212
245
|
# specifically in cleanup for minitests
|
|
213
246
|
def remove_all_vlans
|
|
214
247
|
remove_all_bridge_domains
|
|
248
|
+
remove_all_svis
|
|
215
249
|
Vlan.vlans.each do |vlan, obj|
|
|
216
250
|
# skip reserved vlan
|
|
217
251
|
next if vlan == '1'
|
|
@@ -225,6 +259,8 @@ class CiscoTestCase < TestCase
|
|
|
225
259
|
require_relative '../lib/cisco_node_utils/vrf'
|
|
226
260
|
Vrf.vrfs.each do |vrf, obj|
|
|
227
261
|
next if vrf[/management/]
|
|
262
|
+
# TBD: Remove vrf workaround below after CSCuz56697 is resolved
|
|
263
|
+
config 'vrf context ' + vrf if node.product_id[/N8/]
|
|
228
264
|
obj.destroy
|
|
229
265
|
end
|
|
230
266
|
end
|
|
@@ -235,6 +271,86 @@ class CiscoTestCase < TestCase
|
|
|
235
271
|
config(*cfg)
|
|
236
272
|
end
|
|
237
273
|
|
|
274
|
+
# TBD: -- The following methods are a WIP --
|
|
275
|
+
#
|
|
276
|
+
# def find_compatible_intf(feature, opt=:raise_skip)
|
|
277
|
+
# # Some platforms require specific linecards before allowing a feature to
|
|
278
|
+
# # be enabled. This method will find a compatible interface or optionally
|
|
279
|
+
# # raise a skip.
|
|
280
|
+
# # TBD: This wants to become a common "compatible interface" checker to
|
|
281
|
+
# # eventually replace all of the single-use methods.
|
|
282
|
+
# intf = compatible_intf(feature)
|
|
283
|
+
# if intf.nil? && opt[/raise_skip/]
|
|
284
|
+
# skip("Unable to find compatible interface for 'feature #{feature}'")
|
|
285
|
+
# end
|
|
286
|
+
# intf
|
|
287
|
+
# end
|
|
288
|
+
|
|
289
|
+
# def compatible_intf(feature)
|
|
290
|
+
# # The feat hash contains module restrictions for a given feature.
|
|
291
|
+
# # :mods - (optional) The module ids used in the 'limit-resource' config
|
|
292
|
+
# # :pids - A regex pattern for the line module product IDs (ref: 'sh mod')
|
|
293
|
+
# feat = {}
|
|
294
|
+
# if node.product_id[/N7K/]
|
|
295
|
+
# feat = {
|
|
296
|
+
# # nv overlay raises error unless solely F3
|
|
297
|
+
# 'nv overlay' => { mods: 'f3', pids: 'N7[K7]-F3' }
|
|
298
|
+
# }
|
|
299
|
+
# end
|
|
300
|
+
# patterns = feat[feature]
|
|
301
|
+
# return interfaces[0] if patterns.nil? # No restrictions for this platform
|
|
302
|
+
|
|
303
|
+
# # Check if module is present and usable; i.e. 'ok'
|
|
304
|
+
# pids = patterns[:pids]
|
|
305
|
+
# sh_mod_string = @device.cmd("show mod | i '^[0-9]+.*#{pids}.*ok'")
|
|
306
|
+
# sh_mod = sh_mod_string[/^(\d+)\s.*#{pids}/]
|
|
307
|
+
# slot = sh_mod.nil? ? nil : Regexp.last_match[1]
|
|
308
|
+
# return nil if slot.nil?
|
|
309
|
+
# intf = "ethernet#{slot}/1"
|
|
310
|
+
|
|
311
|
+
# # Check/Set VDC config. VDC platforms restrict module usage per vdc.
|
|
312
|
+
# mods = patterns[:mods]
|
|
313
|
+
# return intf if mods.nil? || !node.product_id[/N7K/]
|
|
314
|
+
# vdc = Vdc.new(Vdc.default_vdc_name)
|
|
315
|
+
# unless mods == vdc.limit_resource_module_type
|
|
316
|
+
# # Update the allowed module types in this vdc
|
|
317
|
+
# vdc.limit_resource_module_type = mods
|
|
318
|
+
# end
|
|
319
|
+
|
|
320
|
+
# # Return the first interface found in 'allocate interface' config, or nil
|
|
321
|
+
# vdc.allocate_interface[%r{Ethernet#{slot}\/(\d+)}]
|
|
322
|
+
# end
|
|
323
|
+
|
|
324
|
+
def vdc_limit_f3_no_intf_needed(action=:set)
|
|
325
|
+
# This is a special-use method for N7Ks that don't have a physical F3.
|
|
326
|
+
# 1) There are some features that refuse to load unless the VDC is
|
|
327
|
+
# limited to F3 only, but they will actually load if the config is
|
|
328
|
+
# present, despite the fact that there are no physical F3s.
|
|
329
|
+
# 2) We have some tests that need these features but don't need interfaces.
|
|
330
|
+
#
|
|
331
|
+
# action = :set (enable limit F3 config), :clear (default limit config)
|
|
332
|
+
#
|
|
333
|
+
# The limit config should be removed after testing if the device does not
|
|
334
|
+
# have an actual F3.
|
|
335
|
+
return unless node.product_id[/N7K/]
|
|
336
|
+
vdc = Vdc.new(Vdc.default_vdc_name)
|
|
337
|
+
case action
|
|
338
|
+
when :set
|
|
339
|
+
return if vdc.limit_resource_module_type == 'f3'
|
|
340
|
+
vdc.limit_resource_module_type = 'f3'
|
|
341
|
+
|
|
342
|
+
when :clear
|
|
343
|
+
# Remove the config if there are no physical F3 cards
|
|
344
|
+
pids = 'N7[K7]-F3'
|
|
345
|
+
sh_mod_string = @device.cmd("show mod | i '^[0-9]+.*#{pids}'")
|
|
346
|
+
sh_mod = sh_mod_string[/^(\d+)\s.*#{pids}/]
|
|
347
|
+
if sh_mod.nil?
|
|
348
|
+
# It's safe to remove the config
|
|
349
|
+
vdc.limit_resource_module_type = ''
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
|
|
238
354
|
# setup fabricpath env if possible and populate the interfaces array
|
|
239
355
|
# otherwise cause a global skip
|
|
240
356
|
def fabricpath_testenv_setup
|
|
@@ -291,9 +407,10 @@ class CiscoTestCase < TestCase
|
|
|
291
407
|
# '9 12 10/40 Gbps Ethernet Module N77-F312FQ-25 ok'
|
|
292
408
|
# '2 6 Nexus 6xQSFP Ethernet Module N5K-C5672UP-M6Q ok'
|
|
293
409
|
# '2 6 Nexus xxQSFP Ethernet Module N6K-C6004-96Q/EF ok'
|
|
410
|
+
# '2 4 Nexus 4xQSFP Ethernet Module N6K-C6001-M4Q ok'
|
|
294
411
|
if node.product_id[/N(5|6)K/]
|
|
295
412
|
sh_mod_string = @device.cmd("sh mod | i '^[0-9]+.*N[56]K-C[56]'")
|
|
296
|
-
sh_mod = sh_mod_string[/^(\d+)\s.*N[56]K-C(56|
|
|
413
|
+
sh_mod = sh_mod_string[/^(\d+)\s.*N[56]K-C(56|600[14])/]
|
|
297
414
|
skip('Unable to find compatible interface in chassis') if sh_mod.nil?
|
|
298
415
|
elsif node.product_id[/N7K/]
|
|
299
416
|
mt_full_interface?
|