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
|
@@ -23,6 +23,16 @@ module Cisco
|
|
|
23
23
|
class SyslogServer < NodeUtil
|
|
24
24
|
attr_reader :name, :level, :vrf
|
|
25
25
|
|
|
26
|
+
LEVEL_TO_NUM = { 'emergencies' => 0,
|
|
27
|
+
'alerts' => 1,
|
|
28
|
+
'critical' => 2,
|
|
29
|
+
'error' => 3,
|
|
30
|
+
'warning' => 4,
|
|
31
|
+
'notifications' => 5,
|
|
32
|
+
'info' => 6,
|
|
33
|
+
'debugging' => 7 }.freeze
|
|
34
|
+
NUM_TO_LEVEL = LEVEL_TO_NUM.invert.freeze
|
|
35
|
+
|
|
26
36
|
def initialize(name,
|
|
27
37
|
level=nil,
|
|
28
38
|
vrf=nil,
|
|
@@ -42,14 +52,24 @@ module Cisco
|
|
|
42
52
|
|
|
43
53
|
def self.syslogservers
|
|
44
54
|
hash = {}
|
|
45
|
-
|
|
46
55
|
syslogservers_list = config_get('syslog_server', 'server')
|
|
47
56
|
return hash if syslogservers_list.nil?
|
|
48
57
|
|
|
49
58
|
syslogservers_list.each do |id|
|
|
59
|
+
# The YAML regex isn't specific enough for some platforms,
|
|
60
|
+
# so we have to do further checking.
|
|
61
|
+
begin
|
|
62
|
+
IPAddr.new(id)
|
|
63
|
+
rescue
|
|
64
|
+
next
|
|
65
|
+
end
|
|
66
|
+
|
|
50
67
|
level = config_get('syslog_server', 'level', id)
|
|
68
|
+
level = level[0] if level.is_a?(Array)
|
|
69
|
+
level = LEVEL_TO_NUM[level] if platform == :ios_xr
|
|
51
70
|
|
|
52
71
|
vrf = config_get('syslog_server', 'vrf', id)
|
|
72
|
+
vrf = vrf[0] if vrf.is_a?(Array)
|
|
53
73
|
|
|
54
74
|
hash[id] = SyslogServer.new(id, level, vrf, false)
|
|
55
75
|
end
|
|
@@ -62,25 +82,64 @@ module Cisco
|
|
|
62
82
|
end
|
|
63
83
|
|
|
64
84
|
def create
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
85
|
+
if platform == :ios_xr
|
|
86
|
+
|
|
87
|
+
# This provider only support a 1-1 mapping between host and VRF.
|
|
88
|
+
# Thus, we must remove the other entries on different VRFs.
|
|
89
|
+
all_vrfs = config_get('syslog_server', 'vrf', name)
|
|
90
|
+
destroy(all_vrfs) if all_vrfs.is_a?(Array) && all_vrfs.count > 1
|
|
91
|
+
|
|
92
|
+
config_set('syslog_server',
|
|
93
|
+
'server',
|
|
94
|
+
state: '',
|
|
95
|
+
ip: "#{name}",
|
|
96
|
+
level: level.nil? ? '' : "severity #{NUM_TO_LEVEL[level]}",
|
|
97
|
+
vrf: vrf.nil? ? '' : "vrf #{vrf}",
|
|
98
|
+
)
|
|
99
|
+
else
|
|
100
|
+
config_set('syslog_server',
|
|
101
|
+
'server',
|
|
102
|
+
state: '',
|
|
103
|
+
ip: "#{name}",
|
|
104
|
+
level: level.nil? ? '' : "#{level}",
|
|
105
|
+
vrf: vrf.nil? ? '' : "use-vrf #{vrf}",
|
|
106
|
+
)
|
|
107
|
+
end
|
|
73
108
|
end
|
|
74
109
|
|
|
75
|
-
def destroy
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
110
|
+
def destroy(duplicate_vrfs=[])
|
|
111
|
+
if platform == :ios_xr
|
|
112
|
+
if duplicate_vrfs.empty?
|
|
113
|
+
config_set('syslog_server',
|
|
114
|
+
'server',
|
|
115
|
+
state: 'no',
|
|
116
|
+
ip: "#{name}",
|
|
117
|
+
level: '',
|
|
118
|
+
vrf: vrf.nil? ? '' : "vrf #{vrf}",
|
|
119
|
+
)
|
|
120
|
+
else
|
|
121
|
+
warn("#{name} is configured multiple times on the device" \
|
|
122
|
+
' (possibly in different VRFs). This is unsupported by this' \
|
|
123
|
+
' API and the duplicate entries are being deleted.')
|
|
124
|
+
duplicate_vrfs.each do |dup|
|
|
125
|
+
config_set('syslog_server',
|
|
126
|
+
'server',
|
|
127
|
+
state: 'no',
|
|
128
|
+
ip: "#{name}",
|
|
129
|
+
level: '',
|
|
130
|
+
vrf: "vrf #{dup}",
|
|
131
|
+
)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
else
|
|
135
|
+
config_set('syslog_server',
|
|
136
|
+
'server',
|
|
137
|
+
state: 'no',
|
|
138
|
+
ip: "#{name}",
|
|
139
|
+
level: '',
|
|
140
|
+
vrf: '',
|
|
141
|
+
)
|
|
142
|
+
end
|
|
84
143
|
end
|
|
85
144
|
end # class
|
|
86
145
|
end # module
|
|
@@ -49,7 +49,7 @@ module Cisco
|
|
|
49
49
|
def timestamp=(val)
|
|
50
50
|
fail TypeError unless val.is_a?(String)
|
|
51
51
|
fail TypeError \
|
|
52
|
-
unless %w(seconds milliseconds).include?(
|
|
52
|
+
unless %w(seconds milliseconds).include?(val)
|
|
53
53
|
|
|
54
54
|
# There is no unset version as timestamp has a default value
|
|
55
55
|
config_set('syslog_settings',
|
|
@@ -31,7 +31,7 @@ module Cisco
|
|
|
31
31
|
|
|
32
32
|
return unless create
|
|
33
33
|
|
|
34
|
-
TacacsServer.new.enable
|
|
34
|
+
TacacsServer.new.enable if platform != :ios_xr && !TacacsServer.enabled
|
|
35
35
|
config_set('tacacs_server_group', 'group', state: '', name: name)
|
|
36
36
|
end
|
|
37
37
|
|
|
@@ -81,8 +81,12 @@ module Cisco
|
|
|
81
81
|
|
|
82
82
|
def self.groups
|
|
83
83
|
grps = {}
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
if platform == :ios_xr
|
|
85
|
+
tacgroups = config_get('tacacs_server_group', 'group')
|
|
86
|
+
else
|
|
87
|
+
tacgroups = config_get('tacacs_server_group', 'group') if
|
|
88
|
+
TacacsServer.enabled
|
|
89
|
+
end
|
|
86
90
|
unless tacgroups.nil?
|
|
87
91
|
tacgroups.each { |s| grps[s] = TacacsServerGroup.new(s, false) }
|
|
88
92
|
end
|
|
@@ -125,7 +129,7 @@ module Cisco
|
|
|
125
129
|
|
|
126
130
|
def source_interface
|
|
127
131
|
i = config_get('tacacs_server_group', 'source_interface', @name)
|
|
128
|
-
i.nil? ? default_source_interface : i
|
|
132
|
+
i.nil? ? default_source_interface : i.downcase
|
|
129
133
|
end
|
|
130
134
|
|
|
131
135
|
def source_interface=(s)
|
|
@@ -23,41 +23,104 @@ module Cisco
|
|
|
23
23
|
attr_reader :name
|
|
24
24
|
@hosts = {}
|
|
25
25
|
|
|
26
|
-
def initialize(name,
|
|
26
|
+
def initialize(name, instantiate=true, host_port=nil)
|
|
27
27
|
fail TypeError unless name.is_a? String
|
|
28
28
|
fail ArgumentError if name.empty?
|
|
29
29
|
@name = name
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
|
|
31
|
+
if platform == :ios_xr
|
|
32
|
+
if host_port.nil?
|
|
33
|
+
@port = config_get_default('tacacs_server_host', 'port')
|
|
34
|
+
else
|
|
35
|
+
fail ArgumentError, 'host_port must be an Integer' \
|
|
36
|
+
unless host_port.is_a?(Integer)
|
|
37
|
+
@port = host_port
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
create if instantiate
|
|
42
|
+
|
|
43
|
+
return if platform == :ios_xr
|
|
44
|
+
|
|
45
|
+
return if host_port.nil?
|
|
46
|
+
fail ArgumentError, 'host_port must be an Integer' \
|
|
47
|
+
unless host_port.is_a?(Integer)
|
|
48
|
+
self.port = host_port
|
|
34
49
|
end
|
|
35
50
|
|
|
36
51
|
def self.hosts
|
|
37
|
-
|
|
52
|
+
hosts = {}
|
|
53
|
+
return hosts unless Feature.tacacs_enabled?
|
|
38
54
|
|
|
39
|
-
|
|
55
|
+
hosts_list = config_get('tacacs_server_host', 'hosts')
|
|
56
|
+
return hosts if hosts_list.nil? || hosts_list.empty?
|
|
40
57
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
58
|
+
hosts_list.each do |name|
|
|
59
|
+
if platform == :ios_xr
|
|
60
|
+
host_port = config_get('tacacs_server_host', 'port', ip: name)
|
|
61
|
+
host_port = host_port[0] if host_port.is_a?(Array)
|
|
62
|
+
host_port = host_port.to_i
|
|
63
|
+
|
|
64
|
+
hosts[name] = TacacsServerHost.new(name, false, host_port)
|
|
65
|
+
else
|
|
66
|
+
hosts[name] = TacacsServerHost.new(name, false) if @hosts[name].nil?
|
|
46
67
|
end
|
|
47
68
|
end
|
|
48
|
-
|
|
69
|
+
hosts
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def create
|
|
73
|
+
destroy if platform == :ios_xr
|
|
74
|
+
Feature.tacacs_enable
|
|
75
|
+
config_set('tacacs_server_host',
|
|
76
|
+
'host',
|
|
77
|
+
state: '',
|
|
78
|
+
ip: name,
|
|
79
|
+
port: @port)
|
|
49
80
|
end
|
|
50
81
|
|
|
51
82
|
def destroy
|
|
52
|
-
|
|
83
|
+
if platform == :ios_xr
|
|
84
|
+
# This provider only support a 1-1 mapping between host and ports.
|
|
85
|
+
# Thus, we must remove the other entries on different ports.
|
|
86
|
+
all_hosts = config_get('tacacs_server_host',
|
|
87
|
+
'host_port_pairs',
|
|
88
|
+
ip: @name)
|
|
89
|
+
return unless all_hosts.is_a?(Array)
|
|
90
|
+
|
|
91
|
+
warn("#{name} is configured multiple times on the device" \
|
|
92
|
+
' (possibly using different ports). This is unsupported by this' \
|
|
93
|
+
' API and the duplicate entries are being deleted.') \
|
|
94
|
+
if all_hosts.count > 1
|
|
95
|
+
|
|
96
|
+
all_hosts.each do |host_port|
|
|
97
|
+
config_set('tacacs_server_host',
|
|
98
|
+
'host',
|
|
99
|
+
state: 'no',
|
|
100
|
+
ip: @name,
|
|
101
|
+
port: host_port)
|
|
102
|
+
end
|
|
103
|
+
else
|
|
104
|
+
config_set('tacacs_server_host',
|
|
105
|
+
'host',
|
|
106
|
+
state: 'no',
|
|
107
|
+
ip: @name,
|
|
108
|
+
port: @port)
|
|
109
|
+
end
|
|
53
110
|
end
|
|
54
111
|
|
|
55
112
|
def port
|
|
56
|
-
config_get('tacacs_server_host',
|
|
113
|
+
platform == :ios_xr ? @port : config_get('tacacs_server_host',
|
|
114
|
+
'port',
|
|
115
|
+
ip: @name)
|
|
57
116
|
end
|
|
58
117
|
|
|
59
118
|
def port=(n)
|
|
60
|
-
|
|
119
|
+
fail("'port' setter method not applicable for this platform." \
|
|
120
|
+
'port must be passed in to the constructor.') \
|
|
121
|
+
if platform == :ios_xr
|
|
122
|
+
|
|
123
|
+
config_set('tacacs_server_host', 'port', ip: @name, port: n.to_i)
|
|
61
124
|
end
|
|
62
125
|
|
|
63
126
|
def self.default_port
|
|
@@ -65,7 +128,10 @@ module Cisco
|
|
|
65
128
|
end
|
|
66
129
|
|
|
67
130
|
def encryption_type
|
|
68
|
-
type = config_get('tacacs_server_host',
|
|
131
|
+
type = config_get('tacacs_server_host',
|
|
132
|
+
'encryption_type',
|
|
133
|
+
ip: @name,
|
|
134
|
+
port: @port)
|
|
69
135
|
type.nil? ? TACACS_SERVER_ENC_UNKNOWN : type.to_i
|
|
70
136
|
end
|
|
71
137
|
|
|
@@ -74,7 +140,10 @@ module Cisco
|
|
|
74
140
|
end
|
|
75
141
|
|
|
76
142
|
def encryption_password
|
|
77
|
-
config_get('tacacs_server_host',
|
|
143
|
+
config_get('tacacs_server_host',
|
|
144
|
+
'encryption_password',
|
|
145
|
+
ip: @name,
|
|
146
|
+
port: @port)
|
|
78
147
|
end
|
|
79
148
|
|
|
80
149
|
def self.default_encryption_password
|
|
@@ -93,29 +162,50 @@ module Cisco
|
|
|
93
162
|
# to unset the key value. Otherwise, the box is not configured with key,
|
|
94
163
|
# thus we don't need to do anything
|
|
95
164
|
if encryption_type != TACACS_SERVER_ENC_UNKNOWN
|
|
96
|
-
config_set('tacacs_server_host',
|
|
97
|
-
|
|
98
|
-
|
|
165
|
+
config_set('tacacs_server_host',
|
|
166
|
+
'encryption',
|
|
167
|
+
state: 'no',
|
|
168
|
+
ip: @name,
|
|
169
|
+
port: @port,
|
|
170
|
+
enc_type: encryption_type,
|
|
171
|
+
password: encryption_password)
|
|
99
172
|
end
|
|
100
173
|
else
|
|
101
|
-
config_set('tacacs_server_host',
|
|
102
|
-
'',
|
|
174
|
+
config_set('tacacs_server_host',
|
|
175
|
+
'encryption',
|
|
176
|
+
state: '',
|
|
177
|
+
ip: @name,
|
|
178
|
+
port: @port,
|
|
179
|
+
enc_type: enctype,
|
|
180
|
+
password: password)
|
|
103
181
|
end
|
|
104
182
|
end
|
|
105
183
|
|
|
106
184
|
def timeout
|
|
107
|
-
config_get('tacacs_server_host',
|
|
185
|
+
config_get('tacacs_server_host',
|
|
186
|
+
'timeout',
|
|
187
|
+
ip: @name,
|
|
188
|
+
port: @port)
|
|
108
189
|
end
|
|
109
190
|
|
|
110
191
|
def timeout=(t)
|
|
111
192
|
fail TypeError unless t.is_a? Fixnum
|
|
112
193
|
return if t == timeout
|
|
113
194
|
|
|
114
|
-
config_set('tacacs_server_host',
|
|
195
|
+
config_set('tacacs_server_host',
|
|
196
|
+
'timeout',
|
|
197
|
+
state: '',
|
|
198
|
+
ip: @name,
|
|
199
|
+
port: @port,
|
|
200
|
+
timeout: t)
|
|
115
201
|
end
|
|
116
202
|
|
|
117
203
|
def self.default_timeout
|
|
118
204
|
config_get_default('tacacs_server_host', 'timeout')
|
|
119
205
|
end
|
|
206
|
+
|
|
207
|
+
def ==(other)
|
|
208
|
+
name == other.name
|
|
209
|
+
end
|
|
120
210
|
end
|
|
121
211
|
end
|
data/lib/cisco_node_utils/vdc.rb
CHANGED
|
@@ -84,5 +84,17 @@ module Cisco
|
|
|
84
84
|
def default_limit_resource_module_type
|
|
85
85
|
config_get_default('vdc', 'limit_resource_module_type')
|
|
86
86
|
end
|
|
87
|
+
|
|
88
|
+
def interface_membership
|
|
89
|
+
config_get('vdc', 'membership', vdc: @vdc)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def interface_membership=(intf)
|
|
93
|
+
config_set('vdc', 'membership', vdc: @vdc, intf: intf)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def default_interface_membership
|
|
97
|
+
config_get_default('vdc', 'membership')
|
|
98
|
+
end
|
|
87
99
|
end # Class
|
|
88
100
|
end # Module
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
# Container module for version number only.
|
|
16
16
|
module CiscoNodeUtils
|
|
17
|
-
VERSION = '1.
|
|
17
|
+
VERSION = '1.3.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
|
|
@@ -14,9 +14,11 @@
|
|
|
14
14
|
# See the License for the specific language governing permissions and
|
|
15
15
|
# limitations under the License.
|
|
16
16
|
|
|
17
|
+
require_relative 'cisco_cmn_utils'
|
|
17
18
|
require_relative 'node_util'
|
|
18
19
|
require_relative 'interface'
|
|
19
20
|
require_relative 'fabricpath_global'
|
|
21
|
+
require_relative 'feature'
|
|
20
22
|
|
|
21
23
|
# Add some Vlan-specific constants to the Cisco namespace
|
|
22
24
|
module Cisco
|
|
@@ -24,7 +26,7 @@ module Cisco
|
|
|
24
26
|
|
|
25
27
|
# Vlan - node utility class for VLAN configuration management
|
|
26
28
|
class Vlan < NodeUtil
|
|
27
|
-
attr_reader :
|
|
29
|
+
attr_reader :vlan_id
|
|
28
30
|
|
|
29
31
|
def initialize(vlan_id, instantiate=true)
|
|
30
32
|
@vlan_id = vlan_id.to_s
|
|
@@ -34,6 +36,10 @@ module Cisco
|
|
|
34
36
|
create if instantiate
|
|
35
37
|
end
|
|
36
38
|
|
|
39
|
+
def to_s
|
|
40
|
+
"VLAN #{vlan_id}"
|
|
41
|
+
end
|
|
42
|
+
|
|
37
43
|
def self.vlans
|
|
38
44
|
hash = {}
|
|
39
45
|
vlan_list = config_get('vlan', 'all_vlans')
|
|
@@ -53,19 +59,49 @@ module Cisco
|
|
|
53
59
|
config_set('vlan', 'destroy', @vlan_id)
|
|
54
60
|
end
|
|
55
61
|
|
|
56
|
-
def cli_error_check(result)
|
|
62
|
+
def cli_error_check(result, ignore_message=nil)
|
|
57
63
|
# The NXOS vlan cli does not raise an exception in some conditions and
|
|
58
64
|
# instead just displays a STDOUT error message; thus NXAPI does not detect
|
|
59
65
|
# the failure and we must catch it by inspecting the "body" hash entry
|
|
60
66
|
# returned by NXAPI. This vlan cli behavior is unlikely to change.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
# Check for messages that can be safely ignored.
|
|
68
|
+
|
|
69
|
+
errors = /(ERROR:|VLAN:|Warning:)/
|
|
70
|
+
|
|
71
|
+
return unless
|
|
72
|
+
result[2].is_a?(Hash) && errors.match(result[2]['body'].to_s)
|
|
73
|
+
# Split errors into a list, but keep the delimiter as part of the message.
|
|
74
|
+
error_list =
|
|
75
|
+
(result[2]['body'].split(errors) - ['']).each_slice(2).map(&:join)
|
|
76
|
+
error_list.each do |msg|
|
|
77
|
+
next if ignore_message && msg.to_s.include?(ignore_message)
|
|
78
|
+
fail result[2]['body']
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def set_args_keys_default
|
|
83
|
+
keys = { vlan: @vlan_id }
|
|
84
|
+
@set_args = keys
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def set_args_keys(hash={}) # rubocop:disable Style/AccessorMethodName
|
|
88
|
+
set_args_keys_default
|
|
89
|
+
@set_args = @set_args.merge!(hash) unless hash.empty?
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def fabric_control
|
|
93
|
+
config_get('vlan', 'fabric_control', vlan: @vlan_id)
|
|
94
|
+
end
|
|
64
95
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
96
|
+
def fabric_control=(val)
|
|
97
|
+
no_cmd = (val) ? '' : 'no'
|
|
98
|
+
result = config_set('vlan', 'fabric_control', vlan: @vlan_id,
|
|
99
|
+
state: no_cmd)
|
|
100
|
+
cli_error_check(result)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def default_fabric_control
|
|
104
|
+
config_get_default('vlan', 'fabric_control')
|
|
69
105
|
end
|
|
70
106
|
|
|
71
107
|
def fabricpath_feature
|
|
@@ -79,28 +115,24 @@ module Cisco
|
|
|
79
115
|
def mode
|
|
80
116
|
result = config_get('vlan', 'mode', @vlan_id)
|
|
81
117
|
return default_mode if result.nil?
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
118
|
+
# Note: The yaml definition for this property
|
|
119
|
+
# uses 'multiple' as a workaround for a bug
|
|
120
|
+
# in the N7k nxapi code which displays
|
|
121
|
+
# the 'show vlan' output twice.
|
|
122
|
+
result[0].downcase! if result[0][/FABRICPATH/]
|
|
123
|
+
result[0]
|
|
88
124
|
end
|
|
89
125
|
|
|
90
126
|
def mode=(str)
|
|
91
|
-
str
|
|
92
|
-
|
|
93
|
-
result = config_set('vlan', 'mode', @vlan_id, 'no', '')
|
|
127
|
+
if str == default_mode
|
|
128
|
+
config_set('vlan', 'mode', @vlan_id, 'no', '')
|
|
94
129
|
else
|
|
95
130
|
if 'fabricpath' == str
|
|
96
131
|
fabricpath_feature_set(:enabled) unless
|
|
97
132
|
:enabled == fabricpath_feature
|
|
98
133
|
end
|
|
99
|
-
|
|
134
|
+
config_set('vlan', 'mode', @vlan_id, '', str)
|
|
100
135
|
end
|
|
101
|
-
cli_error_check(result)
|
|
102
|
-
rescue CliError => e
|
|
103
|
-
raise "[vlan #{@vlan_id}] '#{e.command}' : #{e.clierror}"
|
|
104
136
|
end
|
|
105
137
|
|
|
106
138
|
def default_mode
|
|
@@ -120,8 +152,6 @@ module Cisco
|
|
|
120
152
|
result = config_set('vlan', 'name', @vlan_id, '', str)
|
|
121
153
|
end
|
|
122
154
|
cli_error_check(result)
|
|
123
|
-
rescue CliError => e
|
|
124
|
-
raise "[vlan #{@vlan_id}] '#{e.command}' : #{e.clierror}"
|
|
125
155
|
end
|
|
126
156
|
|
|
127
157
|
def default_vlan_name
|
|
@@ -146,8 +176,6 @@ module Cisco
|
|
|
146
176
|
result = config_set('vlan', 'state', @vlan_id, '', str)
|
|
147
177
|
end
|
|
148
178
|
cli_error_check(result)
|
|
149
|
-
rescue CliError => e
|
|
150
|
-
raise "[vlan #{@vlan_id}] '#{e.command}' : #{e.clierror}"
|
|
151
179
|
end
|
|
152
180
|
|
|
153
181
|
def default_state
|
|
@@ -164,8 +192,6 @@ module Cisco
|
|
|
164
192
|
no_cmd = (val) ? '' : 'no'
|
|
165
193
|
result = config_set('vlan', 'shutdown', @vlan_id, no_cmd)
|
|
166
194
|
cli_error_check(result)
|
|
167
|
-
rescue CliError => e
|
|
168
|
-
raise "[vlan #{@vlan_id}] '#{e.command}' : #{e.clierror}"
|
|
169
195
|
end
|
|
170
196
|
|
|
171
197
|
def default_shutdown
|
|
@@ -185,7 +211,7 @@ module Cisco
|
|
|
185
211
|
interfaces = {}
|
|
186
212
|
all_interfaces.each do |name, i|
|
|
187
213
|
next unless i.switchport_mode == :access
|
|
188
|
-
next unless i.access_vlan == @vlan_id
|
|
214
|
+
next unless i.access_vlan.to_i == @vlan_id.to_i
|
|
189
215
|
interfaces[name] = i
|
|
190
216
|
end
|
|
191
217
|
interfaces
|
|
@@ -209,5 +235,97 @@ module Cisco
|
|
|
209
235
|
def default_mapped_vni
|
|
210
236
|
config_get_default('vlan', 'mapped_vni')
|
|
211
237
|
end
|
|
238
|
+
|
|
239
|
+
def private_vlan_type
|
|
240
|
+
return nil unless Feature.private_vlan_enabled?
|
|
241
|
+
config_get('vlan', 'private_vlan_type', id: @vlan_id)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def private_vlan_type=(type)
|
|
245
|
+
Feature.private_vlan_enable
|
|
246
|
+
fail TypeError unless type && type.is_a?(String)
|
|
247
|
+
|
|
248
|
+
if type == default_private_vlan_type
|
|
249
|
+
return if private_vlan_type.empty?
|
|
250
|
+
set_args_keys(state: 'no', type: private_vlan_type)
|
|
251
|
+
ignore_msg = 'Warning: Private-VLAN CLI removed'
|
|
252
|
+
else
|
|
253
|
+
set_args_keys(state: '', type: type)
|
|
254
|
+
ignore_msg = 'Warning: Private-VLAN CLI entered'
|
|
255
|
+
end
|
|
256
|
+
result = config_set('vlan', 'private_vlan_type', @set_args)
|
|
257
|
+
cli_error_check(result, ignore_msg)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def default_private_vlan_type
|
|
261
|
+
config_get_default('vlan', 'private_vlan_type')
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def private_vlan_association
|
|
265
|
+
return nil unless Feature.private_vlan_enabled?
|
|
266
|
+
config_get('vlan', 'private_vlan_association', id: @vlan_id)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def private_vlan_association=(vlan_list)
|
|
270
|
+
Feature.private_vlan_enable
|
|
271
|
+
vlan_list_delta(private_vlan_association, vlan_list)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def default_private_vlan_association
|
|
275
|
+
config_get_default('vlan', 'private_vlan_association')
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# --------------------------
|
|
279
|
+
# vlan_list_delta is a helper function for the private_vlan_association
|
|
280
|
+
# property. It walks the delta hash and adds/removes each target private
|
|
281
|
+
# vlan.
|
|
282
|
+
# This api is used by private vlan to prepare the input to the setter
|
|
283
|
+
# method. The input can be in the following formats for vlans:
|
|
284
|
+
# 10-12,14. Prepare_array api is transforming this input into a flat array.
|
|
285
|
+
# In the example above the returned array will be 10, 11, 12, 14. Prepare
|
|
286
|
+
# array is first splitting the input on ',' and the than expanding the vlan
|
|
287
|
+
# range element like 10-12 into a flat array. The final result will
|
|
288
|
+
# be a flat array.
|
|
289
|
+
# This way we can later used the lib utility to check the delta from
|
|
290
|
+
# the input vlan value and the vlan configured to apply the right config.
|
|
291
|
+
|
|
292
|
+
def vlan_list_delta(is_list, should_list)
|
|
293
|
+
new_list = []
|
|
294
|
+
should_list.each do |item|
|
|
295
|
+
if item.include?(',')
|
|
296
|
+
new_list.push(item.split(','))
|
|
297
|
+
else
|
|
298
|
+
new_list.push(item)
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
new_list.flatten!
|
|
302
|
+
new_list.sort!
|
|
303
|
+
|
|
304
|
+
new_list.each { |item| item.gsub!('-', '..') }
|
|
305
|
+
|
|
306
|
+
should_list_new = []
|
|
307
|
+
new_list.each do |elem|
|
|
308
|
+
if elem.include?('..')
|
|
309
|
+
elema = elem.split('..').map { |d| Integer(d) }
|
|
310
|
+
elema.sort!
|
|
311
|
+
tr = elema[0]..elema[1]
|
|
312
|
+
tr.to_a.each do |item|
|
|
313
|
+
should_list_new.push(item.to_s)
|
|
314
|
+
end
|
|
315
|
+
else
|
|
316
|
+
should_list_new.push(elem)
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
delta_hash = Utils.delta_add_remove(should_list_new, is_list)
|
|
321
|
+
[:add, :remove].each do |action|
|
|
322
|
+
delta_hash[action].each do |vlans|
|
|
323
|
+
state = (action == :add) ? '' : 'no'
|
|
324
|
+
set_args_keys(state: state, vlans: vlans)
|
|
325
|
+
result = config_set('vlan', 'private_vlan_association', @set_args)
|
|
326
|
+
cli_error_check(result)
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
end
|
|
212
330
|
end # class
|
|
213
331
|
end # module
|