cisco_node_utils 1.2.0 → 1.3.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 +2 -0
- data/.rspec +2 -0
- data/.rubocop.yml +13 -0
- data/.travis.yml +4 -1
- data/CHANGELOG.md +81 -2
- data/CONTRIBUTING.md +2 -17
- data/Gemfile +5 -0
- data/README.md +92 -47
- data/Rakefile +23 -1
- data/bin/git/hooks/hook_lib +7 -0
- data/bin/git/hooks/pre-commit/check_unstaged_changes +18 -0
- data/bin/git/hooks/pre-commit/rubocop +7 -2
- data/bin/git/hooks/pre-commit/validate-diffs +18 -4
- data/bin/git/hooks/pre-commit/validate-yaml +18 -0
- data/bin/git/update-hooks +64 -6
- data/cisco_node_utils.gemspec +9 -6
- data/docs/README-develop-best-practices.md +149 -50
- data/docs/README-develop-node-utils-APIs.md +92 -42
- data/docs/README-maintainers.md +7 -4
- data/docs/README-test-execution.md +57 -0
- data/docs/cisco_node_utils.yaml.example +30 -0
- data/docs/template-router.rb +4 -0
- data/ext/mkrf_conf.rb +63 -0
- data/lib/.rubocop.yml +2 -2
- data/lib/cisco_node_utils.rb +5 -0
- data/lib/cisco_node_utils/aaa_authentication_login.rb +5 -6
- data/lib/cisco_node_utils/aaa_authorization_service.rb +1 -1
- data/lib/cisco_node_utils/ace.rb +165 -12
- data/lib/cisco_node_utils/acl.rb +2 -1
- data/lib/cisco_node_utils/bgp.rb +184 -21
- data/lib/cisco_node_utils/bgp_af.rb +94 -249
- data/lib/cisco_node_utils/bgp_neighbor.rb +94 -14
- data/lib/cisco_node_utils/bgp_neighbor_af.rb +75 -8
- data/lib/cisco_node_utils/bridge_domain.rb +183 -0
- data/lib/cisco_node_utils/bridge_domain_vni.rb +206 -0
- data/lib/cisco_node_utils/cisco_cmn_utils.rb +85 -2
- data/lib/cisco_node_utils/client.rb +35 -0
- data/lib/cisco_node_utils/client/client.rb +234 -0
- data/lib/cisco_node_utils/client/grpc.rb +33 -0
- data/lib/cisco_node_utils/client/grpc/client.rb +311 -0
- data/lib/cisco_node_utils/client/grpc/ems.proto +148 -0
- data/lib/cisco_node_utils/client/grpc/ems.rb +111 -0
- data/lib/cisco_node_utils/client/grpc/ems_services.rb +49 -0
- data/lib/cisco_node_utils/client/nxapi.rb +31 -0
- data/lib/cisco_node_utils/client/nxapi/client.rb +305 -0
- data/lib/cisco_node_utils/client/utils.rb +164 -0
- data/lib/cisco_node_utils/cmd_ref/README_YAML.md +222 -254
- data/lib/cisco_node_utils/cmd_ref/aaa_auth_login_service.yaml +11 -8
- data/lib/cisco_node_utils/cmd_ref/aaa_authentication_login.yaml +22 -15
- data/lib/cisco_node_utils/cmd_ref/aaa_authorization_service.yaml +11 -8
- data/lib/cisco_node_utils/cmd_ref/acl.yaml +21 -16
- data/lib/cisco_node_utils/cmd_ref/bgp.yaml +239 -109
- data/lib/cisco_node_utils/cmd_ref/bgp_af.yaml +114 -55
- data/lib/cisco_node_utils/cmd_ref/bgp_neighbor.yaml +76 -52
- data/lib/cisco_node_utils/cmd_ref/bgp_neighbor_af.yaml +106 -62
- data/lib/cisco_node_utils/cmd_ref/bridge_domain.yaml +71 -0
- data/lib/cisco_node_utils/cmd_ref/bridge_domain_vni.yaml +33 -0
- data/lib/cisco_node_utils/cmd_ref/dnsclient.yaml +35 -14
- data/lib/cisco_node_utils/cmd_ref/encapsulation.yaml +25 -0
- data/lib/cisco_node_utils/cmd_ref/evpn_vni.yaml +23 -17
- data/lib/cisco_node_utils/cmd_ref/fabricpath.yaml +94 -83
- data/lib/cisco_node_utils/cmd_ref/fabricpath_topology.yaml +22 -17
- data/lib/cisco_node_utils/cmd_ref/feature.yaml +76 -26
- data/lib/cisco_node_utils/cmd_ref/images.yaml +3 -2
- data/lib/cisco_node_utils/cmd_ref/interface.yaml +381 -153
- data/lib/cisco_node_utils/cmd_ref/interface_channel_group.yaml +21 -11
- data/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +21 -21
- data/lib/cisco_node_utils/cmd_ref/interface_portchannel.yaml +30 -21
- data/lib/cisco_node_utils/cmd_ref/interface_service_vni.yaml +18 -13
- data/lib/cisco_node_utils/cmd_ref/inventory.yaml +26 -31
- data/lib/cisco_node_utils/cmd_ref/itd_device_group.yaml +83 -0
- data/lib/cisco_node_utils/cmd_ref/itd_service.yaml +119 -0
- data/lib/cisco_node_utils/cmd_ref/memory.yaml +17 -6
- data/lib/cisco_node_utils/cmd_ref/ntp_config.yaml +10 -3
- data/lib/cisco_node_utils/cmd_ref/ntp_server.yaml +17 -5
- data/lib/cisco_node_utils/cmd_ref/ospf.yaml +33 -29
- data/lib/cisco_node_utils/cmd_ref/overlay_global.yaml +12 -10
- data/lib/cisco_node_utils/cmd_ref/pim.yaml +16 -19
- data/lib/cisco_node_utils/cmd_ref/portchannel_global.yaml +40 -25
- data/lib/cisco_node_utils/cmd_ref/radius_global.yaml +17 -12
- data/lib/cisco_node_utils/cmd_ref/radius_server.yaml +71 -35
- data/lib/cisco_node_utils/cmd_ref/radius_server_group.yaml +10 -5
- data/lib/cisco_node_utils/cmd_ref/show_system.yaml +6 -2
- data/lib/cisco_node_utils/cmd_ref/show_version.yaml +47 -43
- data/lib/cisco_node_utils/cmd_ref/snmp_community.yaml +13 -11
- data/lib/cisco_node_utils/cmd_ref/snmp_group.yaml +4 -2
- data/lib/cisco_node_utils/cmd_ref/snmp_notification_receiver.yaml +23 -21
- data/lib/cisco_node_utils/cmd_ref/snmp_server.yaml +26 -22
- data/lib/cisco_node_utils/cmd_ref/snmp_user.yaml +19 -17
- data/lib/cisco_node_utils/cmd_ref/snmpnotification.yaml +18 -6
- data/lib/cisco_node_utils/cmd_ref/stp_global.yaml +234 -0
- data/lib/cisco_node_utils/cmd_ref/syslog_server.yaml +24 -9
- data/lib/cisco_node_utils/cmd_ref/syslog_settings.yaml +5 -3
- data/lib/cisco_node_utils/cmd_ref/system.yaml +4 -3
- data/lib/cisco_node_utils/cmd_ref/tacacs_server.yaml +22 -20
- data/lib/cisco_node_utils/cmd_ref/tacacs_server_group.yaml +27 -15
- data/lib/cisco_node_utils/cmd_ref/tacacs_server_host.yaml +45 -16
- data/lib/cisco_node_utils/cmd_ref/vdc.yaml +21 -11
- data/lib/cisco_node_utils/cmd_ref/virtual_service.yaml +3 -2
- data/lib/cisco_node_utils/cmd_ref/vlan.yaml +60 -32
- data/lib/cisco_node_utils/cmd_ref/vpc.yaml +118 -101
- data/lib/cisco_node_utils/cmd_ref/vrf.yaml +54 -58
- data/lib/cisco_node_utils/cmd_ref/vrf_af.yaml +118 -0
- data/lib/cisco_node_utils/cmd_ref/vtp.yaml +19 -25
- data/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml +28 -18
- data/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml +34 -17
- data/lib/cisco_node_utils/cmd_ref/yum.yaml +6 -4
- data/lib/cisco_node_utils/command_reference.rb +261 -142
- data/lib/cisco_node_utils/constants.rb +33 -0
- data/lib/cisco_node_utils/encapsulation.rb +112 -0
- data/lib/cisco_node_utils/environment.rb +102 -0
- data/lib/cisco_node_utils/evpn_vni.rb +5 -3
- data/lib/cisco_node_utils/exceptions.rb +111 -0
- data/lib/cisco_node_utils/fabricpath_global.rb +52 -35
- data/lib/cisco_node_utils/fabricpath_topology.rb +44 -57
- data/lib/cisco_node_utils/feature.rb +165 -3
- data/lib/cisco_node_utils/interface.rb +1051 -260
- data/lib/cisco_node_utils/interface_channel_group.rb +11 -10
- data/lib/cisco_node_utils/interface_ospf.rb +1 -2
- data/lib/cisco_node_utils/interface_portchannel.rb +4 -12
- data/lib/cisco_node_utils/interface_service_vni.rb +7 -7
- data/lib/cisco_node_utils/itd_device_group.rb +248 -0
- data/lib/cisco_node_utils/itd_device_group_node.rb +144 -0
- data/lib/cisco_node_utils/itd_service.rb +523 -0
- data/lib/cisco_node_utils/logger.rb +75 -0
- data/lib/cisco_node_utils/node.rb +62 -192
- data/lib/cisco_node_utils/node_util.rb +56 -10
- data/lib/cisco_node_utils/overlay_global.rb +2 -2
- data/lib/cisco_node_utils/pim.rb +2 -13
- data/lib/cisco_node_utils/pim_group_list.rb +1 -1
- data/lib/cisco_node_utils/pim_rp_address.rb +1 -1
- data/lib/cisco_node_utils/platform.rb +52 -21
- data/lib/cisco_node_utils/portchannel_global.rb +89 -19
- data/lib/cisco_node_utils/radius_server.rb +168 -37
- data/lib/cisco_node_utils/router_ospf.rb +20 -35
- data/lib/cisco_node_utils/router_ospf_vrf.rb +4 -4
- data/lib/cisco_node_utils/snmpserver.rb +1 -6
- data/lib/cisco_node_utils/snmpuser.rb +6 -4
- data/lib/cisco_node_utils/stp_global.rb +676 -0
- data/lib/cisco_node_utils/syslog_server.rb +77 -18
- data/lib/cisco_node_utils/syslog_settings.rb +1 -1
- data/lib/cisco_node_utils/tacacs_server_group.rb +8 -4
- data/lib/cisco_node_utils/tacacs_server_host.rb +115 -25
- data/lib/cisco_node_utils/vdc.rb +12 -0
- data/lib/cisco_node_utils/version.rb +1 -1
- data/lib/cisco_node_utils/vlan.rb +147 -29
- data/lib/cisco_node_utils/vpc.rb +55 -3
- data/lib/cisco_node_utils/vrf.rb +72 -11
- data/lib/cisco_node_utils/vrf_af.rb +114 -29
- data/lib/cisco_node_utils/vtp.rb +34 -52
- data/lib/cisco_node_utils/vxlan_vtep.rb +34 -8
- data/lib/cisco_node_utils/vxlan_vtep_vni.rb +36 -4
- data/lib/minitest/environment_plugin.rb +31 -0
- data/lib/minitest/log_level_plugin.rb +41 -0
- data/spec/client_spec.rb +7 -0
- data/spec/environment_spec.rb +263 -0
- data/spec/grpc_client_spec.rb +23 -0
- data/spec/isolate/all_clients_spec.rb +9 -0
- data/spec/isolate/grpc_only_spec.rb +16 -0
- data/spec/isolate/no_clients_spec.rb +26 -0
- data/spec/isolate/nxapi_only_spec.rb +16 -0
- data/spec/nxapi_client_spec.rb +42 -0
- data/spec/schema.yaml +75 -0
- data/spec/shared_examples_for_clients.rb +14 -0
- data/spec/spec_helper.rb +91 -0
- data/spec/whitespace_spec.rb +10 -0
- data/spec/yaml_spec.rb +42 -0
- data/tests/.rubocop.yml +2 -2
- data/tests/CSCuxdublin-1.0.0-7.0.3.I3.1.lib32_n9000.rpm +0 -0
- data/tests/basetest.rb +96 -36
- data/tests/ciscotest.rb +220 -12
- data/tests/cmd_config.yaml +71 -49
- data/tests/cmd_config_invalid.yaml +1 -1
- data/tests/test_aaa_authentication_login.rb +1 -0
- data/tests/test_aaa_authentication_login_service.rb +9 -0
- data/tests/test_aaa_authorization_service.rb +173 -367
- data/tests/test_ace.rb +171 -100
- data/tests/test_acl.rb +10 -1
- data/tests/test_bgp_af.rb +395 -728
- data/tests/test_bgp_neighbor.rb +274 -115
- data/tests/test_bgp_neighbor_af.rb +178 -77
- data/tests/test_bridge_domain.rb +191 -0
- data/tests/test_bridge_domain_vni.rb +116 -0
- data/tests/test_client_utils.rb +111 -0
- data/tests/test_command_config.rb +9 -5
- data/tests/test_command_reference.rb +380 -102
- data/tests/test_dns_domain.rb +13 -3
- data/tests/test_domain_name.rb +13 -3
- data/tests/test_encapsulation.rb +77 -0
- data/tests/test_evpn_vni.rb +25 -7
- data/tests/test_fabricpath_global.rb +167 -163
- data/tests/test_fabricpath_topology.rb +12 -33
- data/tests/test_feature.rb +215 -0
- data/tests/test_grpc.rb +166 -0
- data/tests/test_interface.rb +585 -344
- data/tests/test_interface_bdi.rb +80 -0
- data/tests/test_interface_channel_group.rb +6 -3
- data/tests/test_interface_ospf.rb +26 -24
- data/tests/test_interface_portchannel.rb +1 -0
- data/tests/test_interface_private_vlan.rb +724 -0
- data/tests/test_interface_service_vni.rb +37 -66
- data/tests/test_interface_svi.rb +98 -101
- data/tests/test_interface_switchport.rb +419 -549
- data/tests/test_itd_device_group.rb +145 -0
- data/tests/test_itd_device_group_node.rb +199 -0
- data/tests/test_itd_service.rb +298 -0
- data/tests/test_logger.rb +43 -0
- data/tests/test_name_server.rb +11 -2
- data/tests/test_node.rb +16 -75
- data/tests/test_node_ext.rb +174 -163
- data/tests/test_node_util.rb +119 -0
- data/tests/test_ntp_config.rb +5 -1
- data/tests/test_ntp_server.rb +2 -2
- data/tests/test_nxapi.rb +221 -0
- data/tests/test_overlay_global.rb +47 -38
- data/tests/test_pim.rb +2 -0
- data/tests/test_pim_group_list.rb +2 -0
- data/tests/test_pim_rp_address.rb +2 -0
- data/tests/test_platform.rb +86 -39
- data/tests/test_portchannel_global.rb +211 -135
- data/tests/test_radius_global.rb +13 -5
- data/tests/test_radius_server.rb +256 -104
- data/tests/test_radius_server_group.rb +2 -0
- data/tests/test_router_bgp.rb +781 -485
- data/tests/test_router_ospf.rb +26 -103
- data/tests/test_router_ospf_vrf.rb +52 -57
- data/tests/test_snmp_notification_receiver.rb +2 -0
- data/tests/test_snmpcommunity.rb +2 -0
- data/tests/test_snmpgroup.rb +2 -0
- data/tests/test_snmpnotification.rb +40 -21
- data/tests/test_snmpserver.rb +2 -0
- data/tests/test_snmpuser.rb +2 -0
- data/tests/test_stp_global.rb +563 -0
- data/tests/test_syslog_server.rb +32 -8
- data/tests/test_syslog_settings.rb +22 -9
- data/tests/test_tacacs_server.rb +32 -27
- data/tests/test_tacacs_server_group.rb +100 -45
- data/tests/test_tacacs_server_host.rb +135 -43
- data/tests/test_vdc.rb +2 -16
- data/tests/test_vlan.rb +106 -54
- data/tests/test_vlan_mt_full.rb +11 -21
- data/tests/test_vlan_private.rb +669 -0
- data/tests/test_vpc.rb +312 -159
- data/tests/test_vrf.rb +122 -113
- data/tests/test_vrf_af.rb +238 -0
- data/tests/test_vtp.rb +58 -102
- data/tests/test_vxlan_vtep.rb +38 -17
- data/tests/test_vxlan_vtep_vni.rb +61 -9
- data/tests/test_yum.rb +49 -25
- metadata +122 -36
- data/lib/cisco_node_utils/cmd_ref/fex.yaml +0 -9
- data/lib/cisco_node_utils/cmd_ref/vni.yaml +0 -76
- data/lib/cisco_node_utils/vni.rb +0 -227
- data/tests/test_vni.rb +0 -106
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# January 2016, Glenn F. Matthews
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2014-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
|
+
# Shared constants for the Cisco module
|
|
18
|
+
module Cisco
|
|
19
|
+
PLATFORMS = [
|
|
20
|
+
# Cisco IOS XR
|
|
21
|
+
:ios_xr,
|
|
22
|
+
# Cisco NX-OS (Nexus switches)
|
|
23
|
+
:nexus,
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
DATA_FORMATS = [
|
|
27
|
+
# Cisco CLI. Indentation is significant.
|
|
28
|
+
:cli,
|
|
29
|
+
# Structured data format specific to NX-API
|
|
30
|
+
:nxapi_structured,
|
|
31
|
+
# TODO: :yang,
|
|
32
|
+
]
|
|
33
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# NXAPI implementation of encapsulation profile class
|
|
2
|
+
#
|
|
3
|
+
# March 2016, Rohan Gandhi Korlepara
|
|
4
|
+
#
|
|
5
|
+
# Copyright (c) 2014-2016 Cisco and/or its affiliates.
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
|
|
19
|
+
require_relative 'node_util'
|
|
20
|
+
require_relative 'feature'
|
|
21
|
+
|
|
22
|
+
module Cisco
|
|
23
|
+
# Encapsulation - node utility class for Encapsulation config mgmt.
|
|
24
|
+
class Encapsulation < NodeUtil
|
|
25
|
+
attr_reader :encap_name
|
|
26
|
+
|
|
27
|
+
# name: name of the encap instance
|
|
28
|
+
# instantiate: true = create encap instance
|
|
29
|
+
def initialize(name, instantiate=true)
|
|
30
|
+
fail ArgumentError unless name.length > 0
|
|
31
|
+
@encap_name = name
|
|
32
|
+
create if instantiate
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def to_s
|
|
36
|
+
"Encapsulation #{encap_name}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Create a hash of all current encap instances.
|
|
40
|
+
def self.encaps
|
|
41
|
+
return {} unless Feature.vni_enabled?
|
|
42
|
+
instances = config_get('encapsulation', 'all_encaps')
|
|
43
|
+
return {} if instances.nil?
|
|
44
|
+
hash = {}
|
|
45
|
+
instances.each do |name|
|
|
46
|
+
hash[name] = Encapsulation.new(name, false)
|
|
47
|
+
end
|
|
48
|
+
hash
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# This will expand the string to a list of bds as integers
|
|
52
|
+
def self.string_to_array(string)
|
|
53
|
+
list = []
|
|
54
|
+
narray = string.split(',')
|
|
55
|
+
narray.each do |elem|
|
|
56
|
+
if elem.include?('-')
|
|
57
|
+
es = elem.gsub('-', '..')
|
|
58
|
+
ea = es.split('..').map { |d| Integer(d) }
|
|
59
|
+
er = ea[0]..ea[1]
|
|
60
|
+
list << er.to_a
|
|
61
|
+
else
|
|
62
|
+
list << elem.to_i
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
list.flatten
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Enable feature and create encap instance
|
|
69
|
+
def create
|
|
70
|
+
Feature.vni_enable
|
|
71
|
+
config_set('encapsulation', 'create', profile: @encap_name)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Destroy an encap instance
|
|
75
|
+
def destroy
|
|
76
|
+
config_set('encapsulation', 'destroy', profile: @encap_name)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# ----------
|
|
80
|
+
# PROPERTIES
|
|
81
|
+
# ----------
|
|
82
|
+
|
|
83
|
+
def range_summarize(string)
|
|
84
|
+
Utils.array_to_str(Encapsulation.string_to_array(string.to_s), false)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def dot1q_map
|
|
88
|
+
result = config_get('encapsulation', 'dot1q_map', profile: @encap_name)
|
|
89
|
+
return default_dot1q_map if result.empty?
|
|
90
|
+
|
|
91
|
+
result[0] = range_summarize(result[0])
|
|
92
|
+
result[1] = range_summarize(result[1])
|
|
93
|
+
result
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def dot1q_map=(map)
|
|
97
|
+
state = ''
|
|
98
|
+
if map.empty?
|
|
99
|
+
state = 'no'
|
|
100
|
+
map = dot1q_map
|
|
101
|
+
return if map.empty?
|
|
102
|
+
end
|
|
103
|
+
vlans, vnis = map
|
|
104
|
+
config_set('encapsulation', 'dot1q_map', profile: @encap_name,
|
|
105
|
+
state: state, vlans: vlans, vnis: vnis)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def default_dot1q_map
|
|
109
|
+
config_get_default('encapsulation', 'dot1q_map')
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# March 2016, Glenn F. Matthews
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 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 'yaml'
|
|
18
|
+
require_relative 'logger'
|
|
19
|
+
|
|
20
|
+
module Cisco
|
|
21
|
+
# Class representing the configuration environment
|
|
22
|
+
class Environment
|
|
23
|
+
@environments = {}
|
|
24
|
+
@default_environment_name = 'default'
|
|
25
|
+
|
|
26
|
+
# Autogenerate Cisco::Environment.default_environment_name and
|
|
27
|
+
# Cisco::Environment.default_environment_name= class methods.
|
|
28
|
+
class << self
|
|
29
|
+
attr_accessor :default_environment_name
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# We have three tiers of configuration:
|
|
33
|
+
# 1) default (defined in this file)
|
|
34
|
+
# 2) System-wide gem configuration in /etc/cisco_node_utils.yaml
|
|
35
|
+
# 3) User configuration in ~/cisco_node_utils.yaml
|
|
36
|
+
|
|
37
|
+
DEFAULT_ENVIRONMENT = {
|
|
38
|
+
host: nil, # localhost by default
|
|
39
|
+
port: nil, # only applicable to gRPC
|
|
40
|
+
username: nil,
|
|
41
|
+
password: nil,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
def self.environments
|
|
45
|
+
if @environments.empty?
|
|
46
|
+
@environments = merge_config('/etc/cisco_node_utils.yaml',
|
|
47
|
+
@environments)
|
|
48
|
+
@environments = merge_config('~/cisco_node_utils.yaml',
|
|
49
|
+
@environments)
|
|
50
|
+
@environments.each do |name, config|
|
|
51
|
+
Cisco::Logger.debug("Environment '#{name}': #{config}")
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
@environments
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def self.merge_config(path, current_config)
|
|
58
|
+
data = data_from_file(path)
|
|
59
|
+
data.each do |name, config|
|
|
60
|
+
# in case config is nil:
|
|
61
|
+
config ||= {}
|
|
62
|
+
# in case current_config has no entry for this name:
|
|
63
|
+
current_config[name] ||= DEFAULT_ENVIRONMENT.clone
|
|
64
|
+
# merge it on in!
|
|
65
|
+
current_config[name].merge!(strings_to_symbols(config))
|
|
66
|
+
end
|
|
67
|
+
current_config
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def self.data_from_file(path)
|
|
71
|
+
begin
|
|
72
|
+
path = File.expand_path(path)
|
|
73
|
+
rescue ArgumentError => e
|
|
74
|
+
# Can happen if path includes '~' but $HOME is not defined
|
|
75
|
+
Cisco::Logger.debug "Failed to load #{path}: #{e}"
|
|
76
|
+
return {}
|
|
77
|
+
end
|
|
78
|
+
unless File.file?(path)
|
|
79
|
+
Cisco::Logger.debug "No file found at #{path}"
|
|
80
|
+
return {}
|
|
81
|
+
end
|
|
82
|
+
unless File.readable?(path)
|
|
83
|
+
Cisco::Logger.debug "No permissions to read #{path}"
|
|
84
|
+
return {}
|
|
85
|
+
end
|
|
86
|
+
YAML.load_file(path)
|
|
87
|
+
rescue Psych::SyntaxError => e
|
|
88
|
+
Cisco::Logger.error("Error loading #{path}: #{e}")
|
|
89
|
+
{}
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def self.strings_to_symbols(hash)
|
|
93
|
+
Hash[hash.map { |k, v| [k.to_sym, v] }]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def self.environment(name=nil)
|
|
97
|
+
name ||= @default_environment_name
|
|
98
|
+
Cisco::Logger.debug("Getting environment '#{name}'")
|
|
99
|
+
environments.fetch(name, DEFAULT_ENVIRONMENT)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -84,11 +84,13 @@ module Cisco
|
|
|
84
84
|
def route_distinguisher=(rd)
|
|
85
85
|
if rd == default_route_distinguisher
|
|
86
86
|
@set_args[:state] = 'no'
|
|
87
|
-
|
|
87
|
+
# I2 images require an rd for removal
|
|
88
|
+
rd = route_distinguisher
|
|
89
|
+
return if rd.to_s.empty?
|
|
88
90
|
else
|
|
89
91
|
@set_args[:state] = ''
|
|
90
|
-
@set_args[:rd] = rd
|
|
91
92
|
end
|
|
93
|
+
@set_args[:rd] = rd
|
|
92
94
|
config_set('evpn_vni', 'route_distinguisher', @set_args)
|
|
93
95
|
set_args_keys_default
|
|
94
96
|
end
|
|
@@ -143,7 +145,7 @@ module Cisco
|
|
|
143
145
|
delta_hash = Utils.delta_add_remove(should, is)
|
|
144
146
|
return if delta_hash.values.flatten.empty?
|
|
145
147
|
[:add, :remove].each do |action|
|
|
146
|
-
|
|
148
|
+
Cisco::Logger.debug("#{prop}" \
|
|
147
149
|
"#{@get_args}\n #{action}: #{delta_hash[action]}")
|
|
148
150
|
delta_hash[action].each do |community|
|
|
149
151
|
state = (action == :add) ? '' : 'no'
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# March 2016, Glenn F. Matthews
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2014-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
|
+
# Add generic exception classes to the Cisco module
|
|
18
|
+
# The hierarchy is:
|
|
19
|
+
# RuntimeError
|
|
20
|
+
# Cisco::CiscoError
|
|
21
|
+
# Cisco::ClientError
|
|
22
|
+
# Cisco::ConnectionRefused
|
|
23
|
+
# Cisco::AuthenticationFailed
|
|
24
|
+
# Cisco::RequestFailed
|
|
25
|
+
# Cisco::CliError
|
|
26
|
+
# Cisco::RequestNotSupported
|
|
27
|
+
# Cisco::UnsupportedError
|
|
28
|
+
module Cisco
|
|
29
|
+
# Generic class for exceptions raised by this module
|
|
30
|
+
class CiscoError < RuntimeError
|
|
31
|
+
attr_reader :kwargs
|
|
32
|
+
|
|
33
|
+
def initialize(message=nil, **kwargs)
|
|
34
|
+
@kwargs = kwargs
|
|
35
|
+
super(message)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def respond_to?(method_sym, include_private=false)
|
|
39
|
+
@kwargs.key?(method_sym) ? true : super
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def method_missing(method_sym, *args, **kwargs, &block)
|
|
43
|
+
@kwargs.key?(method_sym) ? @kwargs[method_sym] : super
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Exception class for fundamental client failures
|
|
48
|
+
class ClientError < CiscoError
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# ConnectionRefused means the server isn't listening
|
|
52
|
+
class ConnectionRefused < ClientError
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# AuthenticationFailed means we were able to connect but not login
|
|
56
|
+
class AuthenticationFailed < ClientError
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Exception class for failures of a specific request to the client
|
|
60
|
+
class RequestFailed < CiscoError
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Extension of RequestFailed class specifically for CLI errors
|
|
64
|
+
class CliError < RequestFailed
|
|
65
|
+
def initialize(message=nil,
|
|
66
|
+
clierror: nil,
|
|
67
|
+
rejected_input: nil,
|
|
68
|
+
successful_input: [],
|
|
69
|
+
**kwargs)
|
|
70
|
+
unless message
|
|
71
|
+
if rejected_input.is_a?(Array)
|
|
72
|
+
if rejected_input.length > 1
|
|
73
|
+
message = "The following commands were rejected:\n"
|
|
74
|
+
message += " #{rejected_input.join("\n ")}\n"
|
|
75
|
+
else
|
|
76
|
+
message = "The command '#{rejected_input.first}' was rejected "
|
|
77
|
+
end
|
|
78
|
+
else
|
|
79
|
+
message = "The command '#{rejected_input}' was rejected "
|
|
80
|
+
end
|
|
81
|
+
message += "with error:\n#{clierror}"
|
|
82
|
+
end
|
|
83
|
+
super(message,
|
|
84
|
+
:clierror => clierror,
|
|
85
|
+
:rejected_input => rejected_input,
|
|
86
|
+
:successful_input => successful_input,
|
|
87
|
+
**kwargs)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# RequestNotSupported means we made a request that was validly
|
|
92
|
+
# constructed but includes options that are unsupported.
|
|
93
|
+
#
|
|
94
|
+
# An example would be requesting structured output on a CLI command
|
|
95
|
+
# that only supports ASCII output.
|
|
96
|
+
class RequestNotSupported < RequestFailed
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Exception class raised by CommandReference to indicate that
|
|
100
|
+
# a particular feature/attribute is explicitly excluded on the given node.
|
|
101
|
+
class UnsupportedError < CiscoError
|
|
102
|
+
def initialize(feature, name, oper=nil, msg=nil)
|
|
103
|
+
message = "Feature '#{feature}'"
|
|
104
|
+
message += ", attribute '#{name}'" unless name.nil?
|
|
105
|
+
message += ", operation '#{oper}'" unless oper.nil?
|
|
106
|
+
message += ' is unsupported on this node'
|
|
107
|
+
message += ": #{msg}" unless msg.nil?
|
|
108
|
+
super(message, feature: feature, name: name, oper: oper)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
# limitations under the License.
|
|
19
19
|
|
|
20
20
|
require_relative 'node_util'
|
|
21
|
+
require_relative 'vdc'
|
|
21
22
|
|
|
22
23
|
module Cisco
|
|
23
24
|
# node_utils class for fabricpath_global
|
|
@@ -33,23 +34,49 @@ module Cisco
|
|
|
33
34
|
|
|
34
35
|
def self.globals
|
|
35
36
|
hash = {}
|
|
36
|
-
|
|
37
|
-
return hash if
|
|
37
|
+
feature = config_get('fabricpath', 'feature')
|
|
38
|
+
return hash if feature.nil? || feature.to_sym != :enabled
|
|
38
39
|
hash['default'] = FabricpathGlobal.new('default', false)
|
|
39
40
|
hash
|
|
41
|
+
rescue Cisco::CliError => e
|
|
42
|
+
# cmd will syntax reject when feature is not enabled
|
|
43
|
+
raise unless e.clierror =~ /Syntax error/
|
|
44
|
+
return {}
|
|
40
45
|
end
|
|
41
46
|
|
|
42
47
|
def self.fabricpath_feature
|
|
43
48
|
fabricpath = config_get('fabricpath', 'feature')
|
|
44
|
-
fail 'fabricpath_feature not found' if fabricpath.nil?
|
|
45
49
|
return :disabled if fabricpath.nil?
|
|
46
50
|
fabricpath.to_sym
|
|
51
|
+
rescue Cisco::CliError => e
|
|
52
|
+
# cmd will syntax reject when feature is not enabled
|
|
53
|
+
raise unless e.clierror =~ /Syntax error/
|
|
54
|
+
return :disabled
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def self.fabricpath_enable
|
|
58
|
+
# TBD: Move to Feature provider
|
|
59
|
+
FabricpathGlobal.fabricpath_feature_set(:enabled) unless
|
|
60
|
+
FabricpathGlobal.fabricpath_feature == :enabled
|
|
47
61
|
end
|
|
48
62
|
|
|
49
63
|
def self.fabricpath_feature_set(fabricpath_set)
|
|
50
64
|
curr = FabricpathGlobal.fabricpath_feature
|
|
51
65
|
return if curr == fabricpath_set
|
|
52
66
|
|
|
67
|
+
# NOTE: Add this in future if we want to automatically move only supported
|
|
68
|
+
# interfaces into the VDC
|
|
69
|
+
# if Vdc.vdc_support
|
|
70
|
+
# # For modular platforms, make sure to limit the feature to
|
|
71
|
+
# # modules which support this feature
|
|
72
|
+
# if fabricpath_set == :installed || fabricpath_set == :enabled
|
|
73
|
+
# v = Vdc.new('default')
|
|
74
|
+
# v.limit_resource_module_type =
|
|
75
|
+
# config_get('fabricpath', 'supported_modules')
|
|
76
|
+
# # exception will be raised for un-supported platforms/modules
|
|
77
|
+
# end
|
|
78
|
+
# end
|
|
79
|
+
|
|
53
80
|
case fabricpath_set
|
|
54
81
|
when :enabled
|
|
55
82
|
config_set('fabricpath', 'feature_install',
|
|
@@ -68,8 +95,7 @@ module Cisco
|
|
|
68
95
|
end
|
|
69
96
|
|
|
70
97
|
def create
|
|
71
|
-
FabricpathGlobal.
|
|
72
|
-
:enabled == FabricpathGlobal.fabricpath_feature
|
|
98
|
+
FabricpathGlobal.fabricpath_enable
|
|
73
99
|
end
|
|
74
100
|
|
|
75
101
|
def destroy
|
|
@@ -77,22 +103,15 @@ module Cisco
|
|
|
77
103
|
FabricpathGlobal.fabricpath_feature_set(:disabled)
|
|
78
104
|
end
|
|
79
105
|
|
|
80
|
-
def
|
|
81
|
-
val = config_get_default('fabricpath', property)
|
|
106
|
+
def loadbalance_munge(property, set_val)
|
|
82
107
|
case property
|
|
83
108
|
when /loadbalance_algorithm/
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
else
|
|
88
|
-
set_val
|
|
89
|
-
end
|
|
109
|
+
val = config_get_default('fabricpath', property)
|
|
110
|
+
return val if (val == 'source-destination') && set_val[/symmetric|xor/]
|
|
111
|
+
set_val
|
|
90
112
|
when /loadbalance_.*_rotate/
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
else
|
|
94
|
-
"rotate-amount 0x#{set_val.to_s(16)}"
|
|
95
|
-
end
|
|
113
|
+
return '' if set_val == ''
|
|
114
|
+
"rotate-amount 0x#{set_val.to_i.to_s(16)}"
|
|
96
115
|
else
|
|
97
116
|
set_val
|
|
98
117
|
end
|
|
@@ -200,13 +219,18 @@ module Cisco
|
|
|
200
219
|
config_get_default('fabricpath', 'linkup_delay_enable')
|
|
201
220
|
end
|
|
202
221
|
|
|
222
|
+
def loadbalance_algorithm_symmetric_support
|
|
223
|
+
config_get_default('fabricpath',
|
|
224
|
+
'loadbalance_algorithm_symmetric_support')
|
|
225
|
+
end
|
|
226
|
+
|
|
203
227
|
def loadbalance_algorithm
|
|
204
228
|
algo = config_get('fabricpath', 'loadbalance_algorithm')
|
|
205
229
|
algo.downcase
|
|
206
230
|
end
|
|
207
231
|
|
|
208
232
|
def loadbalance_algorithm=(val)
|
|
209
|
-
val =
|
|
233
|
+
val = loadbalance_munge('loadbalance_algorithm', val)
|
|
210
234
|
state = val ? '' : 'no'
|
|
211
235
|
algo = val ? val : ''
|
|
212
236
|
config_set('fabricpath', 'loadbalance_algorithm', state: state,
|
|
@@ -230,16 +254,14 @@ module Cisco
|
|
|
230
254
|
if rotate == '' && (has_vlan == '' || has_vlan == false)
|
|
231
255
|
config_set('fabricpath', 'loadbalance_multicast_reset')
|
|
232
256
|
else
|
|
233
|
-
rotate =
|
|
257
|
+
rotate = loadbalance_munge('loadbalance_multicast_rotate', rotate)
|
|
234
258
|
has_vlan = (has_vlan == true) ? 'include-vlan' : ''
|
|
235
259
|
config_set('fabricpath', 'loadbalance_multicast_set',
|
|
236
|
-
|
|
260
|
+
rotate: rotate, has_vlan: has_vlan)
|
|
237
261
|
end
|
|
238
262
|
end
|
|
239
263
|
|
|
240
|
-
|
|
241
|
-
config_get_default('fabricpath', 'loadbalance_multicast_rotate')
|
|
242
|
-
end
|
|
264
|
+
# default_loadbalance_multicast_rotate: n/a
|
|
243
265
|
|
|
244
266
|
def default_loadbalance_multicast_has_vlan
|
|
245
267
|
config_get_default('fabricpath', 'loadbalance_multicast_has_vlan')
|
|
@@ -269,9 +291,9 @@ module Cisco
|
|
|
269
291
|
|
|
270
292
|
def split_loadbalance_unicast_layer=(val)
|
|
271
293
|
state = val ? '' : 'no'
|
|
272
|
-
|
|
273
|
-
config_set('fabricpath', 'loadbalance_unicast_layer',
|
|
274
|
-
|
|
294
|
+
layer = val ? val : ''
|
|
295
|
+
config_set('fabricpath', 'loadbalance_unicast_layer',
|
|
296
|
+
state: state, layer: layer)
|
|
275
297
|
end
|
|
276
298
|
|
|
277
299
|
def split_loadbalance_unicast_has_vlan=(val)
|
|
@@ -289,10 +311,10 @@ module Cisco
|
|
|
289
311
|
if layer == '' && rotate == '' && (has_vlan == '' || has_vlan == false)
|
|
290
312
|
config_set('fabricpath', 'loadbalance_unicast_reset')
|
|
291
313
|
else
|
|
292
|
-
rotate =
|
|
314
|
+
rotate = loadbalance_munge('loadbalance_unicast_rotate', rotate)
|
|
293
315
|
has_vlan = (has_vlan == true) ? 'include-vlan' : ''
|
|
294
316
|
config_set('fabricpath', 'loadbalance_unicast_set',
|
|
295
|
-
|
|
317
|
+
layer: layer, rotate: rotate, has_vlan: has_vlan)
|
|
296
318
|
end
|
|
297
319
|
else
|
|
298
320
|
self.split_loadbalance_unicast_layer = layer
|
|
@@ -304,9 +326,7 @@ module Cisco
|
|
|
304
326
|
config_get_default('fabricpath', 'loadbalance_unicast_layer')
|
|
305
327
|
end
|
|
306
328
|
|
|
307
|
-
|
|
308
|
-
config_get_default('fabricpath', 'loadbalance_unicast_rotate')
|
|
309
|
-
end
|
|
329
|
+
# default_loadbalance_unicast_rotate: n/a
|
|
310
330
|
|
|
311
331
|
def default_loadbalance_unicast_has_vlan
|
|
312
332
|
config_get_default('fabricpath', 'loadbalance_unicast_has_vlan')
|
|
@@ -321,9 +341,6 @@ module Cisco
|
|
|
321
341
|
state = 'no'
|
|
322
342
|
else
|
|
323
343
|
state = ''
|
|
324
|
-
vdc = config_get('limit_resource', 'vdc')
|
|
325
|
-
# for vdc unsupported platforms, this will be nil
|
|
326
|
-
config_set('limit_resource', 'fabricpath_transit', vdc) unless vdc.nil?
|
|
327
344
|
end
|
|
328
345
|
config_set('fabricpath', 'mode', state: state)
|
|
329
346
|
end
|