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
|
@@ -26,7 +26,6 @@ module Cisco
|
|
|
26
26
|
|
|
27
27
|
def initialize(topo_id, instantiate=true)
|
|
28
28
|
@topo_id = topo_id.to_s
|
|
29
|
-
@set_params = {}
|
|
30
29
|
fail ArgumentError, "Invalid value(non-numeric
|
|
31
30
|
Topo id #{@topo_id})" unless @topo_id[/^\d+$/]
|
|
32
31
|
|
|
@@ -35,8 +34,8 @@ module Cisco
|
|
|
35
34
|
|
|
36
35
|
def self.topos
|
|
37
36
|
hash = {}
|
|
38
|
-
|
|
39
|
-
return hash if
|
|
37
|
+
feature = config_get('fabricpath', 'feature')
|
|
38
|
+
return hash if feature.nil? || feature.to_sym != :enabled
|
|
40
39
|
topo_list = config_get('fabricpath_topology', 'all_topos')
|
|
41
40
|
return hash if topo_list.nil?
|
|
42
41
|
|
|
@@ -44,24 +43,20 @@ module Cisco
|
|
|
44
43
|
hash[id] = FabricpathTopo.new(id, false)
|
|
45
44
|
end
|
|
46
45
|
hash
|
|
46
|
+
rescue Cisco::CliError => e
|
|
47
|
+
# cmd will syntax reject when feature is not enabled
|
|
48
|
+
raise unless e.clierror =~ /Syntax error/
|
|
49
|
+
return {}
|
|
47
50
|
end
|
|
48
51
|
|
|
49
52
|
def create
|
|
50
53
|
fabricpath_feature_set(:enabled) unless :enabled == fabricpath_feature
|
|
51
54
|
config_set('fabricpath_topology', 'create',
|
|
52
|
-
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def cli_error_check(result)
|
|
56
|
-
# The NXOS vlan cli does not raise an exception in some conditions and
|
|
57
|
-
# instead just displays a STDOUT error message; thus NXAPI does not detect
|
|
58
|
-
# the failure and we must catch it by inspecting the "body" hash entry
|
|
59
|
-
# returned by NXAPI. This vlan cli behavior is unlikely to change.
|
|
60
|
-
fail result[2]['body'] unless result[2]['body'].empty?
|
|
55
|
+
topo_id: @topo_id) unless @topo_id == '0'
|
|
61
56
|
end
|
|
62
57
|
|
|
63
58
|
def destroy
|
|
64
|
-
config_set('fabricpath_topology', 'destroy',
|
|
59
|
+
config_set('fabricpath_topology', 'destroy', topo_id: @topo_id)
|
|
65
60
|
end
|
|
66
61
|
|
|
67
62
|
def fabricpath_feature
|
|
@@ -72,54 +67,50 @@ module Cisco
|
|
|
72
67
|
FabricpathGlobal.fabricpath_feature_set(fabricpath_set)
|
|
73
68
|
end
|
|
74
69
|
|
|
75
|
-
def
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
70
|
+
def member_vlans
|
|
71
|
+
config_get('fabricpath_topology', 'member_vlans',
|
|
72
|
+
@topo_id).gsub(/\s+/, '')
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def member_vlans=(str)
|
|
76
|
+
if str.empty?
|
|
77
|
+
state = 'no'
|
|
78
|
+
range = ''
|
|
79
|
+
else
|
|
80
|
+
state = ''
|
|
81
|
+
range = str
|
|
82
|
+
# reset existing range since we don't want incremental sets
|
|
83
|
+
config_set('fabricpath_topology', 'member_vlans', topo_id: @topo_id,
|
|
84
|
+
state: 'no', vlan_range: '') if member_vlans != ''
|
|
83
85
|
end
|
|
86
|
+
config_set('fabricpath_topology', 'member_vlans', topo_id: @topo_id,
|
|
87
|
+
state: state, vlan_range: range)
|
|
84
88
|
end
|
|
85
89
|
|
|
86
|
-
def
|
|
87
|
-
config_get_default('fabricpath_topology', '
|
|
90
|
+
def default_member_vlans
|
|
91
|
+
config_get_default('fabricpath_topology', 'member_vlans')
|
|
88
92
|
end
|
|
89
93
|
|
|
90
|
-
def
|
|
91
|
-
|
|
92
|
-
return [] if str == '--'
|
|
93
|
-
str.gsub!('-', '..')
|
|
94
|
-
if /,/.match(str)
|
|
95
|
-
str.split(/\s*,\s*/)
|
|
96
|
-
else
|
|
97
|
-
str.lines.to_a
|
|
98
|
-
end
|
|
94
|
+
def member_vnis
|
|
95
|
+
config_get('fabricpath_topology', 'member_vnis', @topo_id).gsub(/\s+/, '')
|
|
99
96
|
end
|
|
100
97
|
|
|
101
|
-
def
|
|
98
|
+
def member_vnis=(str)
|
|
102
99
|
debug "str is #{str} whose class is #{str.class}"
|
|
103
|
-
@set_params = {}
|
|
104
100
|
str = str.join(',') unless str.empty?
|
|
105
101
|
if str.empty?
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
@set_params[:vlan_range] = ''
|
|
102
|
+
state = 'no'
|
|
103
|
+
range = ''
|
|
109
104
|
else
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
@set_params[:state] = ''
|
|
113
|
-
@set_params[:vlan_range] = str
|
|
105
|
+
state = ''
|
|
106
|
+
range = str
|
|
114
107
|
end
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
rescue CliError => e
|
|
118
|
-
raise "[topo #{@topo_id}] '#{e.command}' : #{e.clierror}"
|
|
108
|
+
config_set('fabricpath_topology', 'member_vnis', topo_id: @topo_id,
|
|
109
|
+
state: state, vni_range: range)
|
|
119
110
|
end
|
|
120
111
|
|
|
121
|
-
def
|
|
122
|
-
|
|
112
|
+
def default_member_vnis
|
|
113
|
+
config_get_default('fabricpath_topology', 'member_vlans')
|
|
123
114
|
end
|
|
124
115
|
|
|
125
116
|
def topo_name
|
|
@@ -128,19 +119,15 @@ module Cisco
|
|
|
128
119
|
|
|
129
120
|
def topo_name=(desc)
|
|
130
121
|
fail TypeError unless desc.is_a?(String)
|
|
131
|
-
@set_params = {}
|
|
132
122
|
if desc.empty?
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
@set_params[:name] = ''
|
|
123
|
+
state = 'no'
|
|
124
|
+
name = ''
|
|
136
125
|
else
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
@set_params[:name] = desc
|
|
126
|
+
state = ''
|
|
127
|
+
name = desc
|
|
140
128
|
end
|
|
141
|
-
config_set('fabricpath_topology', 'description', @
|
|
142
|
-
|
|
143
|
-
raise "[#{@name}] '#{e.command}' : #{e.clierror}"
|
|
129
|
+
config_set('fabricpath_topology', 'description', topo_id: @topo_id,
|
|
130
|
+
state: state, name: name)
|
|
144
131
|
end
|
|
145
132
|
|
|
146
133
|
def default_topo_name
|
|
@@ -63,7 +63,7 @@ module Cisco
|
|
|
63
63
|
begin
|
|
64
64
|
config_set('feature', 'fabric_forwarding')
|
|
65
65
|
rescue Cisco::CliError
|
|
66
|
-
|
|
66
|
+
Cisco::Logger.debug '"feature fabric forwarding" CLI was rejected'
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
|
|
@@ -71,11 +71,54 @@ module Cisco
|
|
|
71
71
|
config_get('feature', 'fabric_forwarding')
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
+
# ---------------------------
|
|
75
|
+
def self.fex_enable
|
|
76
|
+
# install feature-set and enable it
|
|
77
|
+
return if fex_enabled?
|
|
78
|
+
config_set('feature', 'fex', state: 'install') unless fex_installed?
|
|
79
|
+
config_set('feature', 'fex', state: '')
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def self.fex_enabled?
|
|
83
|
+
config_get('feature', 'fex') =~ /^enabled/
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def self.fex_installed?
|
|
87
|
+
config_get('feature', 'fex') !~ /^uninstalled/
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def self.fex_supported?
|
|
91
|
+
config_get('feature', 'fex')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# ---------------------------
|
|
95
|
+
def self.itd_enable
|
|
96
|
+
return if itd_enabled?
|
|
97
|
+
config_set('feature', 'itd')
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def self.itd_enabled?
|
|
101
|
+
config_get('feature', 'itd')
|
|
102
|
+
rescue Cisco::CliError => e
|
|
103
|
+
# cmd will syntax reject when feature is not enabled.
|
|
104
|
+
raise unless e.clierror =~ /Syntax error/
|
|
105
|
+
return false
|
|
106
|
+
end
|
|
107
|
+
|
|
74
108
|
# ---------------------------
|
|
75
109
|
def self.nv_overlay_enable
|
|
76
110
|
# Note: vdc platforms restrict this feature to F3 or newer linecards
|
|
77
111
|
return if nv_overlay_enabled?
|
|
78
|
-
config_set('feature', 'nv_overlay')
|
|
112
|
+
config_set('feature', 'nv_overlay', state: '')
|
|
113
|
+
sleep 1
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def self.nv_overlay_disable
|
|
117
|
+
# Note: vdc platforms restrict this feature to F3 or newer linecards
|
|
118
|
+
# Note: this is for test purposes only
|
|
119
|
+
return unless nv_overlay_enabled?
|
|
120
|
+
config_set('feature', 'nv_overlay', state: 'no')
|
|
121
|
+
sleep 1
|
|
79
122
|
end
|
|
80
123
|
|
|
81
124
|
def self.nv_overlay_enabled?
|
|
@@ -86,6 +129,10 @@ module Cisco
|
|
|
86
129
|
return false
|
|
87
130
|
end
|
|
88
131
|
|
|
132
|
+
def self.nv_overlay_supported?
|
|
133
|
+
node.cmd_ref.supports?('feature', 'nv_overlay')
|
|
134
|
+
end
|
|
135
|
+
|
|
89
136
|
# ---------------------------
|
|
90
137
|
def self.nv_overlay_evpn_enable
|
|
91
138
|
return if nv_overlay_evpn_enabled?
|
|
@@ -96,10 +143,55 @@ module Cisco
|
|
|
96
143
|
config_get('feature', 'nv_overlay_evpn')
|
|
97
144
|
end
|
|
98
145
|
|
|
146
|
+
def self.nv_overlay_evpn_supported?
|
|
147
|
+
node.cmd_ref.supports?('feature', 'nv_overlay_evpn')
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# ---------------------------
|
|
151
|
+
def self.ospf_enable
|
|
152
|
+
return if ospf_enabled?
|
|
153
|
+
config_set('feature', 'ospf')
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def self.ospf_enabled?
|
|
157
|
+
config_get('feature', 'ospf')
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# ---------------------------
|
|
161
|
+
def self.pim_enable
|
|
162
|
+
return if pim_enabled?
|
|
163
|
+
config_set('feature', 'pim')
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def self.pim_enabled?
|
|
167
|
+
config_get('feature', 'pim')
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# ---------------------------
|
|
171
|
+
def self.private_vlan_enable
|
|
172
|
+
return if private_vlan_enabled?
|
|
173
|
+
config_set('feature', 'private_vlan')
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def self.private_vlan_enabled?
|
|
177
|
+
config_get('feature', 'private_vlan')
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# ---------------------------
|
|
181
|
+
def self.tacacs_enable
|
|
182
|
+
return if tacacs_enabled? || platform == :ios_xr
|
|
183
|
+
config_set('feature', 'tacacs')
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def self.tacacs_enabled?
|
|
187
|
+
config_get('feature', 'tacacs')
|
|
188
|
+
end
|
|
189
|
+
|
|
99
190
|
# ---------------------------
|
|
100
191
|
def self.vn_segment_vlan_based_enable
|
|
101
192
|
return if vn_segment_vlan_based_enabled?
|
|
102
|
-
config_set('feature', 'vn_segment_vlan_based')
|
|
193
|
+
result = config_set('feature', 'vn_segment_vlan_based')
|
|
194
|
+
cli_error_check(result)
|
|
103
195
|
end
|
|
104
196
|
|
|
105
197
|
def self.vn_segment_vlan_based_enabled?
|
|
@@ -107,5 +199,75 @@ module Cisco
|
|
|
107
199
|
end
|
|
108
200
|
|
|
109
201
|
# ---------------------------
|
|
202
|
+
def self.vni_enable
|
|
203
|
+
return if vni_enabled?
|
|
204
|
+
result = config_set('feature', 'vni')
|
|
205
|
+
cli_error_check(result)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def self.vni_enabled?
|
|
209
|
+
config_get('feature', 'vni')
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# ---------------------------
|
|
213
|
+
def self.vtp_enable
|
|
214
|
+
return if vtp_enabled?
|
|
215
|
+
result = config_set('feature', 'vtp', state: '')
|
|
216
|
+
cli_error_check(result)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Special Case: The only way to remove a vtp instance
|
|
220
|
+
# is by disabling the feature.
|
|
221
|
+
def self.vtp_disable
|
|
222
|
+
return unless vtp_enabled?
|
|
223
|
+
config_set('feature', 'vtp', state: 'no')
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def self.vtp_enabled?
|
|
227
|
+
config_get('feature', 'vtp')
|
|
228
|
+
rescue Cisco::CliError => e
|
|
229
|
+
# cmd will syntax reject when feature is not enabled.
|
|
230
|
+
raise unless e.clierror =~ /Syntax error/
|
|
231
|
+
return false
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# ---------------------------
|
|
235
|
+
def self.cli_error_check(result)
|
|
236
|
+
# The NXOS feature cli may not raise an exception in some conditions and
|
|
237
|
+
# instead just displays a STDOUT error message; thus NXAPI does not detect
|
|
238
|
+
# the failure and we must catch it by inspecting the "body" hash entry
|
|
239
|
+
# returned by NXAPI. This cli behavior is unlikely to change soon.
|
|
240
|
+
fail result[2]['body'] if
|
|
241
|
+
result[2].is_a?(Hash) &&
|
|
242
|
+
/Hardware is not capable of supporting/.match(result[2]['body'].to_s)
|
|
243
|
+
|
|
244
|
+
# Some test environments get result as a string instead of a hash
|
|
245
|
+
fail result if
|
|
246
|
+
result.is_a?(String) &&
|
|
247
|
+
/Hardware is not capable of supporting/.match(result)
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# ---------------------------
|
|
251
|
+
def self.compatible_interfaces(feature, property='supported_module_pids')
|
|
252
|
+
# Figure out the interfaces in a modular switch that are
|
|
253
|
+
# compatible with the given feature (or property within a feature)
|
|
254
|
+
# and return an array of such interfaces
|
|
255
|
+
module_pids = config_get(feature, property)
|
|
256
|
+
return [] if module_pids.nil?
|
|
257
|
+
module_regex = Regexp.new module_pids
|
|
258
|
+
# first get the compatible modules present in the switch
|
|
259
|
+
slots = Platform.slots.select do |_slot, filt_mod|
|
|
260
|
+
filt_mod['pid'] =~ module_regex
|
|
261
|
+
end
|
|
262
|
+
return [] if slots.empty?
|
|
263
|
+
# get the slot numbers only into filtered slots array
|
|
264
|
+
filt_slots = slots.keys.map { |key| key[/\d+/] }
|
|
265
|
+
# now filter interfaces in the vdc based on compatible slots
|
|
266
|
+
vdc = Vdc.new(Vdc.default_vdc_name)
|
|
267
|
+
filt_intfs = vdc.interface_membership.select do |intf|
|
|
268
|
+
filt_slots.include? intf[/\d+/]
|
|
269
|
+
end
|
|
270
|
+
filt_intfs
|
|
271
|
+
end
|
|
110
272
|
end
|
|
111
273
|
end
|
|
@@ -16,145 +16,151 @@
|
|
|
16
16
|
|
|
17
17
|
require_relative 'cisco_cmn_utils'
|
|
18
18
|
require_relative 'node_util'
|
|
19
|
-
require_relative 'pim'
|
|
20
19
|
require_relative 'vrf'
|
|
21
|
-
require_relative 'vni'
|
|
22
20
|
require_relative 'overlay_global'
|
|
23
21
|
|
|
24
22
|
# Add some interface-specific constants to the Cisco namespace
|
|
25
23
|
module Cisco
|
|
26
24
|
IF_SWITCHPORT_MODE = {
|
|
27
|
-
disabled:
|
|
28
|
-
access:
|
|
29
|
-
trunk:
|
|
30
|
-
fex_fabric:
|
|
31
|
-
tunnel:
|
|
32
|
-
fabricpath:
|
|
25
|
+
disabled: '',
|
|
26
|
+
access: 'access',
|
|
27
|
+
trunk: 'trunk',
|
|
28
|
+
fex_fabric: 'fex-fabric',
|
|
29
|
+
tunnel: 'dot1q-tunnel',
|
|
30
|
+
fabricpath: 'fabricpath',
|
|
31
|
+
host: 'host',
|
|
32
|
+
promiscuous: 'promiscuous',
|
|
33
|
+
secondary: 'secondary',
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
PVLAN_PROPERTY = {
|
|
37
|
+
host_promisc: 'switchport_mode_private_vlan_host_promiscous',
|
|
38
|
+
allow_vlan: 'switchport_private_vlan_trunk_allowed_vlan',
|
|
39
|
+
trunk_assoc: 'switchport_private_vlan_association_trunk',
|
|
40
|
+
mapping_trunk: 'switchport_private_vlan_mapping_trunk',
|
|
41
|
+
vlan_mapping: 'private_vlan_mapping',
|
|
33
42
|
}
|
|
34
43
|
|
|
35
44
|
# Interface - node utility class for general interface config management
|
|
36
45
|
class Interface < NodeUtil
|
|
46
|
+
# Regexp to match various Ethernet interface variants:
|
|
47
|
+
# Ethernet
|
|
48
|
+
# GigabitEthernet
|
|
49
|
+
# TenGigE
|
|
50
|
+
# HundredGigE
|
|
51
|
+
# MgmtEth
|
|
52
|
+
ETHERNET = Regexp.new('(Ethernet|GigE|MgmtEth)', Regexp::IGNORECASE)
|
|
53
|
+
# Regexp to match various link bundle interface variants
|
|
54
|
+
PORTCHANNEL = Regexp.new('(port-channel|Bundle-Ether)', Regexp::IGNORECASE)
|
|
55
|
+
|
|
37
56
|
attr_reader :name
|
|
38
57
|
|
|
39
58
|
def initialize(name, instantiate=true)
|
|
40
59
|
fail TypeError unless name.is_a?(String)
|
|
41
60
|
fail ArgumentError unless name.length > 0
|
|
42
61
|
@name = name.downcase
|
|
43
|
-
|
|
62
|
+
@smr = config_get('interface', 'stp_mst_range')
|
|
63
|
+
@svr = config_get('interface', 'stp_vlan_range')
|
|
64
|
+
@match_found = false
|
|
44
65
|
create if instantiate
|
|
45
66
|
end
|
|
46
67
|
|
|
47
|
-
def
|
|
68
|
+
def to_s
|
|
69
|
+
"interface #{name}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.interfaces(opt=nil)
|
|
48
73
|
hash = {}
|
|
49
74
|
intf_list = config_get('interface', 'all_interfaces')
|
|
50
75
|
return hash if intf_list.nil?
|
|
51
76
|
|
|
52
77
|
intf_list.each do |id|
|
|
53
78
|
id = id.downcase
|
|
79
|
+
next if opt && filter(opt, id)
|
|
54
80
|
hash[id] = Interface.new(id, false)
|
|
55
81
|
end
|
|
56
82
|
hash
|
|
57
83
|
end
|
|
58
84
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
########################################################
|
|
69
|
-
# PROPERTIES #
|
|
70
|
-
########################################################
|
|
71
|
-
|
|
72
|
-
def access_vlan
|
|
73
|
-
config_get('interface', 'access_vlan', @name)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def access_vlan=(vlan)
|
|
77
|
-
config_set('interface', 'access_vlan', @name, vlan)
|
|
78
|
-
rescue Cisco::CliError => e
|
|
79
|
-
raise "[#{@name}] '#{e.command}' : #{e.clierror}"
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def ipv4_acl_in
|
|
83
|
-
config_get('interface', 'ipv4_acl_in', @name)
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def ipv4_acl_in=(val)
|
|
87
|
-
if val != ''
|
|
88
|
-
state = ''
|
|
89
|
-
else
|
|
90
|
-
state = 'no'
|
|
91
|
-
val = ipv4_acl_in
|
|
85
|
+
# General-purpose filter for Interface.interfaces().
|
|
86
|
+
# opt: Identifies the filter. This may be overloaded in the future to
|
|
87
|
+
# allow a hash of filter conditions.
|
|
88
|
+
# id: The interface name
|
|
89
|
+
# Return: true if the interface should be filtered out, false to keep it.
|
|
90
|
+
def self.filter(opt, id)
|
|
91
|
+
case opt
|
|
92
|
+
when :private_vlan_any
|
|
93
|
+
return false if config_get('interface', 'private_vlan_any', name: id)
|
|
92
94
|
end
|
|
93
|
-
|
|
94
|
-
return unless val && val != ''
|
|
95
|
-
config_set('interface', 'ipv4_acl_in', @name, state, val)
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def default_ipv4_acl_in
|
|
99
|
-
config_get_default('interface', 'ipv4_acl_in')
|
|
95
|
+
true
|
|
100
96
|
end
|
|
101
97
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
98
|
+
# 'capabilities' is a getter-only helper for minitest and beaker.
|
|
99
|
+
# mode values:
|
|
100
|
+
# :hash = Transform the output into a hash
|
|
101
|
+
# :raw = The raw output from 'show int capabilities'. Some multi-line
|
|
102
|
+
# values do not translate easily so this option allows the
|
|
103
|
+
# caller to extract the data it needs.
|
|
104
|
+
#
|
|
105
|
+
# Sample cli output:
|
|
106
|
+
# Model: N7K-M132XP-12L
|
|
107
|
+
# Type (SFP capable): 10Gbase-SR
|
|
108
|
+
# Speed: 10,100,1000
|
|
109
|
+
#
|
|
110
|
+
# Sample hash output:
|
|
111
|
+
# {"Model"=>"N7K-M132XP-12L", "Type"=>"10Gbase-SR", "Speed"=>"10,100,1000"}
|
|
112
|
+
#
|
|
113
|
+
def self.capabilities(intf, mode=:hash)
|
|
114
|
+
array = config_get('interface', 'capabilities', name: intf)
|
|
115
|
+
return array if mode == :raw
|
|
116
|
+
hash = {}
|
|
117
|
+
if array
|
|
118
|
+
array.delete('')
|
|
119
|
+
array.each do |line|
|
|
120
|
+
k, v = line.split(':')
|
|
121
|
+
next if k.nil? || v.nil?
|
|
122
|
+
k.gsub!(/ \(.*\)/, '') # Remove any parenthetical text from key
|
|
123
|
+
v.strip!
|
|
124
|
+
hash[k] = v
|
|
125
|
+
end
|
|
112
126
|
end
|
|
113
|
-
|
|
114
|
-
return unless val && val != ''
|
|
115
|
-
config_set('interface', 'ipv4_acl_out', @name, state, val)
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def default_ipv4_acl_out
|
|
119
|
-
config_get_default('interface', 'ipv4_acl_out')
|
|
127
|
+
hash
|
|
120
128
|
end
|
|
121
129
|
|
|
122
|
-
def
|
|
123
|
-
|
|
130
|
+
def create
|
|
131
|
+
feature_vlan_set(true) if @name[/(vlan|bdi)/i]
|
|
132
|
+
config_set('interface', 'create', name: @name)
|
|
133
|
+
rescue Cisco::CliError
|
|
134
|
+
# Some XR platforms do not support channel-group configuration
|
|
135
|
+
# on some OS versions. Since this is an OS version difference and not
|
|
136
|
+
# a platform difference, we can't handle this in the YAML.
|
|
137
|
+
raise unless PORTCHANNEL =~ @name && platform == :ios_xr
|
|
138
|
+
raise Cisco::UnsupportedError.new('interface', @name, 'create')
|
|
124
139
|
end
|
|
125
140
|
|
|
126
|
-
def
|
|
127
|
-
|
|
128
|
-
state = ''
|
|
129
|
-
else
|
|
130
|
-
state = 'no'
|
|
131
|
-
val = ipv6_acl_in
|
|
132
|
-
end
|
|
133
|
-
return unless val && val != ''
|
|
134
|
-
config_set('interface', 'ipv6_acl_in', @name, state, val)
|
|
141
|
+
def destroy
|
|
142
|
+
config_set('interface', 'destroy', name: @name)
|
|
135
143
|
end
|
|
136
144
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
145
|
+
########################################################
|
|
146
|
+
# PROPERTIES #
|
|
147
|
+
########################################################
|
|
140
148
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
149
|
+
# For range based attributes, a new attribute purge will
|
|
150
|
+
# be added in future. When purge is set to true, all the
|
|
151
|
+
# ranges which are specified in the manifest will be set
|
|
152
|
+
# to the desired values and those which are not specified
|
|
153
|
+
# in the manifest will be set to default. When purge is
|
|
154
|
+
# false, only the ranges specified in the manifest will
|
|
155
|
+
# be set to the values given in the manifest and others
|
|
156
|
+
# are left untouched.
|
|
144
157
|
|
|
145
|
-
def
|
|
146
|
-
|
|
147
|
-
state = ''
|
|
148
|
-
else
|
|
149
|
-
state = 'no'
|
|
150
|
-
val = ipv6_acl_out
|
|
151
|
-
end
|
|
152
|
-
return unless val && val != ''
|
|
153
|
-
config_set('interface', 'ipv6_acl_out', @name, state, val)
|
|
158
|
+
def access_vlan
|
|
159
|
+
config_get('interface', 'access_vlan', name: @name)
|
|
154
160
|
end
|
|
155
161
|
|
|
156
|
-
def
|
|
157
|
-
|
|
162
|
+
def access_vlan=(vlan)
|
|
163
|
+
config_set('interface', 'access_vlan', name: @name, vlan: vlan)
|
|
158
164
|
end
|
|
159
165
|
|
|
160
166
|
def default_access_vlan
|
|
@@ -162,18 +168,18 @@ module Cisco
|
|
|
162
168
|
end
|
|
163
169
|
|
|
164
170
|
def description
|
|
165
|
-
config_get('interface', 'description', @name)
|
|
171
|
+
config_get('interface', 'description', name: @name)
|
|
166
172
|
end
|
|
167
173
|
|
|
168
174
|
def description=(desc)
|
|
169
175
|
fail TypeError unless desc.is_a?(String)
|
|
170
176
|
if desc.strip.empty?
|
|
171
|
-
config_set('interface', 'description',
|
|
177
|
+
config_set('interface', 'description',
|
|
178
|
+
name: @name, state: 'no', desc: '')
|
|
172
179
|
else
|
|
173
|
-
config_set('interface', 'description',
|
|
180
|
+
config_set('interface', 'description',
|
|
181
|
+
name: @name, state: '', desc: desc)
|
|
174
182
|
end
|
|
175
|
-
rescue Cisco::CliError => e
|
|
176
|
-
raise "[#{@name}] '#{e.command}' : #{e.clierror}"
|
|
177
183
|
end
|
|
178
184
|
|
|
179
185
|
def default_description
|
|
@@ -181,17 +187,17 @@ module Cisco
|
|
|
181
187
|
end
|
|
182
188
|
|
|
183
189
|
def encapsulation_dot1q
|
|
184
|
-
config_get('interface', 'encapsulation_dot1q', @name)
|
|
190
|
+
config_get('interface', 'encapsulation_dot1q', name: @name)
|
|
185
191
|
end
|
|
186
192
|
|
|
187
193
|
def encapsulation_dot1q=(val)
|
|
188
194
|
if val.to_s.empty?
|
|
189
|
-
config_set('interface', 'encapsulation_dot1q',
|
|
195
|
+
config_set('interface', 'encapsulation_dot1q',
|
|
196
|
+
name: @name, state: 'no', vlan: '')
|
|
190
197
|
else
|
|
191
|
-
config_set('interface', 'encapsulation_dot1q',
|
|
198
|
+
config_set('interface', 'encapsulation_dot1q',
|
|
199
|
+
name: @name, state: '', vlan: val)
|
|
192
200
|
end
|
|
193
|
-
rescue Cisco::CliError => e
|
|
194
|
-
raise "[#{@name}] '#{e.command}' : #{e.clierror}"
|
|
195
201
|
end
|
|
196
202
|
|
|
197
203
|
def default_encapsulation_dot1q
|
|
@@ -207,59 +213,74 @@ module Cisco
|
|
|
207
213
|
end
|
|
208
214
|
|
|
209
215
|
def fabric_forwarding_anycast_gateway
|
|
210
|
-
config_get('interface', 'fabric_forwarding_anycast_gateway', @name)
|
|
216
|
+
config_get('interface', 'fabric_forwarding_anycast_gateway', name: @name)
|
|
211
217
|
end
|
|
212
218
|
|
|
213
219
|
def fabric_forwarding_anycast_gateway=(state)
|
|
214
220
|
no_cmd = (state ? '' : 'no')
|
|
215
221
|
config_set('interface',
|
|
216
|
-
'fabric_forwarding_anycast_gateway',
|
|
222
|
+
'fabric_forwarding_anycast_gateway',
|
|
223
|
+
name: @name, state: no_cmd)
|
|
217
224
|
fail if fabric_forwarding_anycast_gateway.to_s != state.to_s
|
|
218
225
|
rescue Cisco::CliError => e
|
|
219
|
-
|
|
220
|
-
raise "#{info} 'fabric_forwarding_anycast_gateway' can only be " \
|
|
226
|
+
raise "#{e} 'fabric_forwarding_anycast_gateway' can only be " \
|
|
221
227
|
'configured on a vlan interface' unless /vlan/.match(@name)
|
|
222
228
|
anycast_gateway_mac = OverlayGlobal.new.anycast_gateway_mac
|
|
223
229
|
if anycast_gateway_mac.nil? || anycast_gateway_mac.empty?
|
|
224
|
-
raise "#{
|
|
230
|
+
raise "#{e} Anycast gateway mac must be configured " \
|
|
225
231
|
'before configuring forwarding mode under interface'
|
|
226
232
|
end
|
|
227
|
-
raise
|
|
233
|
+
raise
|
|
228
234
|
end
|
|
229
235
|
|
|
230
236
|
def default_fabric_forwarding_anycast_gateway
|
|
231
237
|
config_get_default('interface', 'fabric_forwarding_anycast_gateway')
|
|
232
238
|
end
|
|
233
239
|
|
|
234
|
-
def
|
|
235
|
-
|
|
236
|
-
fail 'fex_feature not found' if fex.nil?
|
|
237
|
-
fex.to_sym
|
|
240
|
+
def ipv4_acl_in
|
|
241
|
+
config_get('interface', 'ipv4_acl_in', name: @name)
|
|
238
242
|
end
|
|
239
243
|
|
|
240
|
-
def
|
|
241
|
-
|
|
242
|
-
|
|
244
|
+
def ipv4_acl_in=(val)
|
|
245
|
+
if val != ''
|
|
246
|
+
state = ''
|
|
247
|
+
else
|
|
248
|
+
state = 'no'
|
|
249
|
+
val = ipv4_acl_in
|
|
250
|
+
end
|
|
243
251
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
252
|
+
return unless val && val != ''
|
|
253
|
+
config_set('interface', 'ipv4_acl_in',
|
|
254
|
+
name: @name, state: state, acl: val)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def default_ipv4_acl_in
|
|
258
|
+
config_get_default('interface', 'ipv4_acl_in')
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def ipv4_acl_out
|
|
262
|
+
config_get('interface', 'ipv4_acl_out', name: @name)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def ipv4_acl_out=(val)
|
|
266
|
+
if val != ''
|
|
267
|
+
state = ''
|
|
268
|
+
else
|
|
269
|
+
state = 'no'
|
|
270
|
+
val = ipv4_acl_out
|
|
256
271
|
end
|
|
257
|
-
|
|
258
|
-
|
|
272
|
+
|
|
273
|
+
return unless val && val != ''
|
|
274
|
+
config_set('interface', 'ipv4_acl_out',
|
|
275
|
+
name: @name, state: state, acl: val)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def default_ipv4_acl_out
|
|
279
|
+
config_get_default('interface', 'ipv4_acl_out')
|
|
259
280
|
end
|
|
260
281
|
|
|
261
282
|
def ipv4_addr_mask_set(addr, mask, secondary=false)
|
|
262
|
-
|
|
283
|
+
check_switchport(:disabled)
|
|
263
284
|
sec = secondary ? 'secondary' : ''
|
|
264
285
|
if addr.nil? || addr == default_ipv4_address
|
|
265
286
|
state = 'no'
|
|
@@ -275,13 +296,22 @@ module Cisco
|
|
|
275
296
|
state = ''
|
|
276
297
|
am = "#{addr}/#{mask}"
|
|
277
298
|
end
|
|
278
|
-
config_set('interface', 'ipv4_addr_mask',
|
|
279
|
-
|
|
280
|
-
raise "[#{@name}] '#{e.command}' : #{e.clierror}"
|
|
299
|
+
config_set('interface', 'ipv4_addr_mask',
|
|
300
|
+
name: @name, state: state, addr: am, secondary: sec)
|
|
281
301
|
end
|
|
282
302
|
|
|
283
303
|
def ipv4_addr_mask
|
|
284
|
-
config_get('interface', 'ipv4_addr_mask', @name)
|
|
304
|
+
val = config_get('interface', 'ipv4_addr_mask', name: @name)
|
|
305
|
+
if val && platform == :ios_xr
|
|
306
|
+
# IOS XR reports address as <address> <bitmask> [secondary] but we
|
|
307
|
+
# want <address>/<length> [secondary]
|
|
308
|
+
val.each_with_index do |entry, i|
|
|
309
|
+
mask = entry[1].split(' ')
|
|
310
|
+
mask[0] = Utils.bitmask_to_length(mask[0])
|
|
311
|
+
val[i][1] = mask.join(' ')
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
val
|
|
285
315
|
end
|
|
286
316
|
|
|
287
317
|
def select_ipv4_attribute(attribute)
|
|
@@ -346,31 +376,43 @@ module Cisco
|
|
|
346
376
|
end
|
|
347
377
|
|
|
348
378
|
def ipv4_arp_timeout
|
|
349
|
-
config_get('interface', ipv4_arp_timeout_lookup_string, @name)
|
|
379
|
+
config_get('interface', ipv4_arp_timeout_lookup_string, name: @name)
|
|
350
380
|
end
|
|
351
381
|
|
|
352
382
|
def ipv4_arp_timeout=(timeout)
|
|
353
383
|
fail "'ipv4 arp timeout' can ony be configured on a vlan interface" unless
|
|
354
384
|
/vlan/.match(@name)
|
|
355
385
|
state = (timeout == default_ipv4_arp_timeout) ? 'no' : ''
|
|
356
|
-
config_set('interface', 'ipv4_arp_timeout',
|
|
386
|
+
config_set('interface', 'ipv4_arp_timeout',
|
|
387
|
+
name: @name, state: state, timeout: timeout)
|
|
357
388
|
end
|
|
358
389
|
|
|
359
390
|
def default_ipv4_arp_timeout
|
|
360
391
|
config_get_default('interface', ipv4_arp_timeout_lookup_string)
|
|
361
392
|
end
|
|
362
393
|
|
|
394
|
+
def ipv4_forwarding
|
|
395
|
+
config_get('interface', 'ipv4_forwarding', name: @name)
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
def ipv4_forwarding=(state)
|
|
399
|
+
config_set('interface', 'ipv4_forwarding',
|
|
400
|
+
name: @name, state: state ? '' : 'no')
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
def default_ipv4_forwarding
|
|
404
|
+
config_get_default('interface', 'ipv4_forwarding')
|
|
405
|
+
end
|
|
406
|
+
|
|
363
407
|
def ipv4_pim_sparse_mode
|
|
364
|
-
config_get('interface', 'ipv4_pim_sparse_mode', @name)
|
|
408
|
+
config_get('interface', 'ipv4_pim_sparse_mode', name: @name)
|
|
365
409
|
end
|
|
366
410
|
|
|
367
411
|
def ipv4_pim_sparse_mode=(state)
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
config_set('interface', 'ipv4_pim_sparse_mode',
|
|
371
|
-
state ? '' : 'no')
|
|
372
|
-
rescue Cisco::CliError => e
|
|
373
|
-
raise "[#{@name}] '#{e.command}' : #{e.clierror}"
|
|
412
|
+
check_switchport(:disabled)
|
|
413
|
+
Feature.pim_enable unless platform == :ios_xr
|
|
414
|
+
config_set('interface', 'ipv4_pim_sparse_mode',
|
|
415
|
+
name: @name, state: state ? '' : 'no')
|
|
374
416
|
end
|
|
375
417
|
|
|
376
418
|
def default_ipv4_pim_sparse_mode
|
|
@@ -378,13 +420,13 @@ module Cisco
|
|
|
378
420
|
end
|
|
379
421
|
|
|
380
422
|
def ipv4_proxy_arp
|
|
381
|
-
config_get('interface', 'ipv4_proxy_arp', @name)
|
|
423
|
+
config_get('interface', 'ipv4_proxy_arp', name: @name)
|
|
382
424
|
end
|
|
383
425
|
|
|
384
426
|
def ipv4_proxy_arp=(proxy_arp)
|
|
385
|
-
|
|
427
|
+
check_switchport(:disabled)
|
|
386
428
|
no_cmd = (proxy_arp ? '' : 'no')
|
|
387
|
-
config_set('interface', 'ipv4_proxy_arp', @name, no_cmd)
|
|
429
|
+
config_set('interface', 'ipv4_proxy_arp', name: @name, state: no_cmd)
|
|
388
430
|
end
|
|
389
431
|
|
|
390
432
|
def default_ipv4_proxy_arp
|
|
@@ -401,54 +443,98 @@ module Cisco
|
|
|
401
443
|
end
|
|
402
444
|
|
|
403
445
|
def ipv4_redirects
|
|
404
|
-
config_get('interface', ipv4_redirects_lookup_string, @name)
|
|
446
|
+
config_get('interface', ipv4_redirects_lookup_string, name: @name)
|
|
405
447
|
end
|
|
406
448
|
|
|
407
449
|
def ipv4_redirects=(redirects)
|
|
408
|
-
|
|
450
|
+
check_switchport(:disabled)
|
|
409
451
|
no_cmd = (redirects ? '' : 'no')
|
|
410
|
-
config_set('interface', ipv4_redirects_lookup_string,
|
|
452
|
+
config_set('interface', ipv4_redirects_lookup_string,
|
|
453
|
+
name: @name, state: no_cmd)
|
|
411
454
|
end
|
|
412
455
|
|
|
413
456
|
def default_ipv4_redirects
|
|
414
457
|
config_get_default('interface', ipv4_redirects_lookup_string)
|
|
415
458
|
end
|
|
416
459
|
|
|
460
|
+
def ipv6_acl_in
|
|
461
|
+
config_get('interface', 'ipv6_acl_in', name: @name)
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
def ipv6_acl_in=(val)
|
|
465
|
+
if val != ''
|
|
466
|
+
state = ''
|
|
467
|
+
else
|
|
468
|
+
state = 'no'
|
|
469
|
+
val = ipv6_acl_in
|
|
470
|
+
end
|
|
471
|
+
return unless val && val != ''
|
|
472
|
+
config_set('interface', 'ipv6_acl_in',
|
|
473
|
+
name: @name, state: state, acl: val)
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
def default_ipv6_acl_in
|
|
477
|
+
config_get_default('interface', 'ipv6_acl_in')
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
def ipv6_acl_out
|
|
481
|
+
config_get('interface', 'ipv6_acl_out', name: @name)
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
def ipv6_acl_out=(val)
|
|
485
|
+
if val != ''
|
|
486
|
+
state = ''
|
|
487
|
+
else
|
|
488
|
+
state = 'no'
|
|
489
|
+
val = ipv6_acl_out
|
|
490
|
+
end
|
|
491
|
+
return unless val && val != ''
|
|
492
|
+
config_set('interface', 'ipv6_acl_out',
|
|
493
|
+
name: @name, state: state, acl: val)
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
def default_ipv6_acl_out
|
|
497
|
+
config_get_default('interface', 'ipv6_acl_out')
|
|
498
|
+
end
|
|
499
|
+
|
|
417
500
|
def feature_lacp?
|
|
418
501
|
config_get('interface', 'feature_lacp')
|
|
419
502
|
end
|
|
420
503
|
|
|
421
504
|
def feature_lacp_set(val)
|
|
422
505
|
return if feature_lacp? == val
|
|
423
|
-
config_set('interface', 'feature_lacp', val ? '' : 'no')
|
|
506
|
+
config_set('interface', 'feature_lacp', state: val ? '' : 'no')
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
def mtu_lookup_string
|
|
510
|
+
case @name
|
|
511
|
+
when /loopback/i
|
|
512
|
+
return 'mtu_loopback'
|
|
513
|
+
else
|
|
514
|
+
return 'mtu_other_interfaces'
|
|
515
|
+
end
|
|
424
516
|
end
|
|
425
517
|
|
|
426
518
|
def mtu
|
|
427
|
-
config_get('interface',
|
|
519
|
+
config_get('interface', mtu_lookup_string, name: @name)
|
|
428
520
|
end
|
|
429
521
|
|
|
430
522
|
def mtu=(val)
|
|
431
|
-
|
|
432
|
-
config_set('interface',
|
|
433
|
-
|
|
434
|
-
raise "[#{@name}] '#{e.command}' : #{e.clierror}"
|
|
523
|
+
check_switchport(:disabled)
|
|
524
|
+
config_set('interface', mtu_lookup_string,
|
|
525
|
+
name: @name, state: '', mtu: val)
|
|
435
526
|
end
|
|
436
527
|
|
|
437
528
|
def default_mtu
|
|
438
|
-
config_get_default('interface',
|
|
529
|
+
config_get_default('interface', mtu_lookup_string)
|
|
439
530
|
end
|
|
440
531
|
|
|
441
532
|
def speed
|
|
442
|
-
config_get('interface', 'speed', @name)
|
|
533
|
+
config_get('interface', 'speed', name: @name)
|
|
443
534
|
end
|
|
444
535
|
|
|
445
536
|
def speed=(val)
|
|
446
|
-
|
|
447
|
-
fail 'Changing interface speed is not permitted on this platform'
|
|
448
|
-
end
|
|
449
|
-
config_set('interface', 'speed', @name, val)
|
|
450
|
-
rescue Cisco::CliError => e
|
|
451
|
-
raise "[#{@name}] '#{e.command}' : #{e.clierror}"
|
|
537
|
+
config_set('interface', 'speed', name: @name, speed: val)
|
|
452
538
|
end
|
|
453
539
|
|
|
454
540
|
def default_speed
|
|
@@ -456,16 +542,11 @@ module Cisco
|
|
|
456
542
|
end
|
|
457
543
|
|
|
458
544
|
def duplex
|
|
459
|
-
config_get('interface', 'duplex', @name)
|
|
545
|
+
config_get('interface', 'duplex', name: @name)
|
|
460
546
|
end
|
|
461
547
|
|
|
462
548
|
def duplex=(val)
|
|
463
|
-
|
|
464
|
-
fail 'Changing interface duplex is not permitted on this platform'
|
|
465
|
-
end
|
|
466
|
-
config_set('interface', 'duplex', @name, val)
|
|
467
|
-
rescue Cisco::CliError => e
|
|
468
|
-
raise "[#{@name}] '#{e.command}' : #{e.clierror}"
|
|
549
|
+
config_set('interface', 'duplex', name: @name, duplex: val)
|
|
469
550
|
end
|
|
470
551
|
|
|
471
552
|
def default_duplex
|
|
@@ -474,9 +555,9 @@ module Cisco
|
|
|
474
555
|
|
|
475
556
|
def negotiate_auto_lookup_string
|
|
476
557
|
case @name
|
|
477
|
-
when
|
|
558
|
+
when ETHERNET
|
|
478
559
|
return 'negotiate_auto_ethernet'
|
|
479
|
-
when
|
|
560
|
+
when PORTCHANNEL
|
|
480
561
|
return 'negotiate_auto_portchannel'
|
|
481
562
|
else
|
|
482
563
|
return 'negotiate_auto_other_interfaces'
|
|
@@ -484,13 +565,13 @@ module Cisco
|
|
|
484
565
|
end
|
|
485
566
|
|
|
486
567
|
def negotiate_auto
|
|
487
|
-
config_get('interface', negotiate_auto_lookup_string, @name)
|
|
568
|
+
config_get('interface', negotiate_auto_lookup_string, name: @name)
|
|
488
569
|
end
|
|
489
570
|
|
|
490
571
|
def negotiate_auto=(negotiate_auto)
|
|
491
572
|
lookup = negotiate_auto_lookup_string
|
|
492
573
|
no_cmd = (negotiate_auto ? '' : 'no')
|
|
493
|
-
config_set('interface', lookup, @name, no_cmd)
|
|
574
|
+
config_set('interface', lookup, name: @name, state: no_cmd)
|
|
494
575
|
end
|
|
495
576
|
|
|
496
577
|
def default_negotiate_auto
|
|
@@ -498,19 +579,17 @@ module Cisco
|
|
|
498
579
|
end
|
|
499
580
|
|
|
500
581
|
def shutdown
|
|
501
|
-
config_get('interface', 'shutdown', @name)
|
|
582
|
+
config_get('interface', 'shutdown', name: @name)
|
|
502
583
|
end
|
|
503
584
|
|
|
504
585
|
def shutdown=(state)
|
|
505
586
|
no_cmd = (state ? '' : 'no')
|
|
506
|
-
config_set('interface', 'shutdown', @name, no_cmd)
|
|
507
|
-
rescue Cisco::CliError => e
|
|
508
|
-
raise "[#{@name}] '#{e.command}' : #{e.clierror}"
|
|
587
|
+
config_set('interface', 'shutdown', name: @name, state: no_cmd)
|
|
509
588
|
end
|
|
510
589
|
|
|
511
590
|
def default_shutdown
|
|
512
591
|
case @name
|
|
513
|
-
when
|
|
592
|
+
when ETHERNET
|
|
514
593
|
def_sw = system_default_switchport
|
|
515
594
|
def_shut = system_default_switchport_shutdown
|
|
516
595
|
|
|
@@ -529,7 +608,7 @@ module Cisco
|
|
|
529
608
|
when /loopback/i
|
|
530
609
|
lookup = 'shutdown_loopback'
|
|
531
610
|
|
|
532
|
-
when
|
|
611
|
+
when PORTCHANNEL
|
|
533
612
|
lookup = 'shutdown_ether_channel'
|
|
534
613
|
|
|
535
614
|
when /Vlan/i
|
|
@@ -541,28 +620,236 @@ module Cisco
|
|
|
541
620
|
config_get_default('interface', lookup)
|
|
542
621
|
end
|
|
543
622
|
|
|
623
|
+
def stp_bpdufilter
|
|
624
|
+
config_get('interface', 'stp_bpdufilter', name: @name)
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
def stp_bpdufilter=(val)
|
|
628
|
+
check_switchport([:access, :trunk])
|
|
629
|
+
if val
|
|
630
|
+
state = ''
|
|
631
|
+
else
|
|
632
|
+
state = 'no'
|
|
633
|
+
val = ''
|
|
634
|
+
end
|
|
635
|
+
config_set('interface',
|
|
636
|
+
'stp_bpdufilter', name: @name, state: state, filter: val)
|
|
637
|
+
end
|
|
638
|
+
|
|
639
|
+
def default_stp_bpdufilter
|
|
640
|
+
config_get_default('interface', 'stp_bpdufilter')
|
|
641
|
+
end
|
|
642
|
+
|
|
643
|
+
def stp_bpduguard
|
|
644
|
+
config_get('interface', 'stp_bpduguard', name: @name)
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
def stp_bpduguard=(val)
|
|
648
|
+
if val
|
|
649
|
+
state = ''
|
|
650
|
+
else
|
|
651
|
+
state = 'no'
|
|
652
|
+
val = ''
|
|
653
|
+
end
|
|
654
|
+
config_set('interface',
|
|
655
|
+
'stp_bpduguard', name: @name, state: state, guard: val)
|
|
656
|
+
end
|
|
657
|
+
|
|
658
|
+
def default_stp_bpduguard
|
|
659
|
+
config_get_default('interface', 'stp_bpduguard')
|
|
660
|
+
end
|
|
661
|
+
|
|
662
|
+
def stp_cost
|
|
663
|
+
cost = config_get('interface', 'stp_cost', name: @name)
|
|
664
|
+
cost == 'auto' ? cost : cost.to_i
|
|
665
|
+
end
|
|
666
|
+
|
|
667
|
+
def stp_cost=(val)
|
|
668
|
+
check_switchport([:access, :trunk])
|
|
669
|
+
config_set('interface', 'stp_cost', name: @name, cost: val)
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
def default_stp_cost
|
|
673
|
+
config_get_default('interface', 'stp_cost')
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
def stp_guard
|
|
677
|
+
config_get('interface', 'stp_guard', name: @name)
|
|
678
|
+
end
|
|
679
|
+
|
|
680
|
+
def stp_guard=(val)
|
|
681
|
+
check_switchport([:access, :trunk])
|
|
682
|
+
if val
|
|
683
|
+
state = ''
|
|
684
|
+
else
|
|
685
|
+
state = 'no'
|
|
686
|
+
val = ''
|
|
687
|
+
end
|
|
688
|
+
config_set('interface', 'stp_guard', name: @name, state: state,
|
|
689
|
+
guard: val)
|
|
690
|
+
end
|
|
691
|
+
|
|
692
|
+
def default_stp_guard
|
|
693
|
+
config_get_default('interface', 'stp_guard')
|
|
694
|
+
end
|
|
695
|
+
|
|
696
|
+
def stp_link_type
|
|
697
|
+
config_get('interface', 'stp_link_type', name: @name)
|
|
698
|
+
end
|
|
699
|
+
|
|
700
|
+
def stp_link_type=(val)
|
|
701
|
+
check_switchport([:access, :trunk])
|
|
702
|
+
config_set('interface', 'stp_link_type', name: @name, type: val)
|
|
703
|
+
end
|
|
704
|
+
|
|
705
|
+
def default_stp_link_type
|
|
706
|
+
config_get_default('interface', 'stp_link_type')
|
|
707
|
+
end
|
|
708
|
+
|
|
709
|
+
def stp_port_priority
|
|
710
|
+
config_get('interface', 'stp_port_priority', name: @name)
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
def stp_port_priority=(val)
|
|
714
|
+
check_switchport([:access, :trunk])
|
|
715
|
+
config_set('interface', 'stp_port_priority', name: @name, pp: val)
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
def default_stp_port_priority
|
|
719
|
+
config_get_default('interface', 'stp_port_priority')
|
|
720
|
+
end
|
|
721
|
+
|
|
722
|
+
# Getter: Builds an array of mst cost commands currently
|
|
723
|
+
# on the device.
|
|
724
|
+
# cli: spanning-tree mst 0,2-4,6,8-12 cost 1000
|
|
725
|
+
# spanning-tree mst 4000-4020 cost 2568
|
|
726
|
+
# array: [['0,2-4,6,8-12', '1000'], ['4000-4020', '2568']]
|
|
727
|
+
#
|
|
728
|
+
def stp_mst_cost
|
|
729
|
+
config_get('interface', 'stp_mst_cost', name: @name)
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
def stp_mst_cost=(list)
|
|
733
|
+
check_switchport([:access, :trunk])
|
|
734
|
+
config_set('interface', 'stp_mst_cost',
|
|
735
|
+
name: @name, state: 'no', range: @smr,
|
|
736
|
+
val: '') if list.empty?
|
|
737
|
+
set_range_based_params(list, 'stp_mst_cost')
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
def default_stp_mst_cost
|
|
741
|
+
config_get_default('interface', 'stp_mst_cost')
|
|
742
|
+
end
|
|
743
|
+
|
|
744
|
+
# Getter: Builds an array of mst port-priority commands
|
|
745
|
+
# currently on the device.
|
|
746
|
+
# cli: spanning-tree mst 0,2-4,6,8-12 port-priority 64
|
|
747
|
+
# spanning-tree mst 4000-4020 port-priority 160
|
|
748
|
+
# array: [['0,2-4,6,8-12', '64'], ['4000-4020', '160']]
|
|
749
|
+
#
|
|
750
|
+
def stp_mst_port_priority
|
|
751
|
+
config_get('interface', 'stp_mst_port_priority', name: @name)
|
|
752
|
+
end
|
|
753
|
+
|
|
754
|
+
def stp_mst_port_priority=(list)
|
|
755
|
+
check_switchport([:access, :trunk])
|
|
756
|
+
config_set('interface', 'stp_mst_port_priority',
|
|
757
|
+
name: @name, state: 'no', range: @smr,
|
|
758
|
+
val: '') if list.empty?
|
|
759
|
+
set_range_based_params(list, 'stp_mst_port_priority')
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
def default_stp_mst_port_priority
|
|
763
|
+
config_get_default('interface', 'stp_mst_port_priority')
|
|
764
|
+
end
|
|
765
|
+
|
|
766
|
+
def stp_port_type
|
|
767
|
+
config_get('interface', 'stp_port_type', name: @name)
|
|
768
|
+
end
|
|
769
|
+
|
|
770
|
+
def stp_port_type=(val)
|
|
771
|
+
if val
|
|
772
|
+
state = ''
|
|
773
|
+
else
|
|
774
|
+
state = 'no'
|
|
775
|
+
val = ''
|
|
776
|
+
end
|
|
777
|
+
config_set('interface', 'stp_port_type', name: @name,
|
|
778
|
+
state: state, type: val)
|
|
779
|
+
end
|
|
780
|
+
|
|
781
|
+
def default_stp_port_type
|
|
782
|
+
config_get_default('interface', 'stp_port_type')
|
|
783
|
+
end
|
|
784
|
+
|
|
785
|
+
# Getter: Builds an array of vlan cost commands currently
|
|
786
|
+
# on the device.
|
|
787
|
+
# cli: spanning-tree vlan 1-4,6,8-12 cost 1000
|
|
788
|
+
# spanning-tree vlan 3000-3960 cost 2568
|
|
789
|
+
# array: [['1-4,6,8-12', '1000'], ['3000-3960', '2568']]
|
|
790
|
+
#
|
|
791
|
+
def stp_vlan_cost
|
|
792
|
+
config_get('interface', 'stp_vlan_cost', name: @name)
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
def stp_vlan_cost=(list)
|
|
796
|
+
check_switchport([:access, :trunk])
|
|
797
|
+
config_set('interface', 'stp_vlan_cost',
|
|
798
|
+
name: @name, state: 'no',
|
|
799
|
+
range: @svr, val: '') if list.empty?
|
|
800
|
+
set_range_based_params(list, 'stp_vlan_cost')
|
|
801
|
+
end
|
|
802
|
+
|
|
803
|
+
def default_stp_vlan_cost
|
|
804
|
+
config_get_default('interface', 'stp_vlan_cost')
|
|
805
|
+
end
|
|
806
|
+
|
|
807
|
+
# Getter: Builds an array of vlan port-priority commands
|
|
808
|
+
# currently on the device.
|
|
809
|
+
# cli: spanning-tree vlan 1-4,6,8-12 port-priority 64
|
|
810
|
+
# spanning-tree vlan 3000-3960 port-priority 160
|
|
811
|
+
# array: [['1-4,6,8-12', '64'], ['3000-3960', '160']]
|
|
812
|
+
#
|
|
813
|
+
def stp_vlan_port_priority
|
|
814
|
+
config_get('interface', 'stp_vlan_port_priority', name: @name)
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
def stp_vlan_port_priority=(list)
|
|
818
|
+
check_switchport([:access, :trunk])
|
|
819
|
+
config_set('interface', 'stp_vlan_port_priority',
|
|
820
|
+
name: @name, state: 'no',
|
|
821
|
+
range: @svr, val: '') if list.empty?
|
|
822
|
+
set_range_based_params(list, 'stp_vlan_port_priority')
|
|
823
|
+
end
|
|
824
|
+
|
|
825
|
+
def default_stp_vlan_port_priority
|
|
826
|
+
config_get_default('interface', 'stp_vlan_port_priority')
|
|
827
|
+
end
|
|
828
|
+
|
|
544
829
|
def switchport
|
|
545
830
|
# This is "switchport", not "switchport mode"
|
|
546
|
-
config_get('interface', 'switchport', @name)
|
|
831
|
+
config_get('interface', 'switchport', name: @name)
|
|
547
832
|
end
|
|
548
833
|
|
|
549
834
|
def switchport_enable(val=true)
|
|
550
|
-
config_set('interface', 'switchport', @name, val ? '' : 'no')
|
|
835
|
+
config_set('interface', 'switchport', name: @name, state: val ? '' : 'no')
|
|
551
836
|
end
|
|
552
837
|
|
|
553
838
|
# switchport_autostate_exclude is exclusive to switchport interfaces
|
|
554
839
|
def switchport_autostate_exclude
|
|
555
840
|
config_get('interface',
|
|
556
|
-
'switchport_autostate_exclude', @name)
|
|
841
|
+
'switchport_autostate_exclude', name: @name)
|
|
557
842
|
end
|
|
558
843
|
|
|
559
844
|
def switchport_autostate_exclude=(val)
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
845
|
+
if platform == :nexus
|
|
846
|
+
# cannot configure autostate unless feature vlan is enabled
|
|
847
|
+
fail('switchport mode must be configured before ' \
|
|
848
|
+
'switchport autostate') unless switchport
|
|
849
|
+
feature_vlan_set(true)
|
|
850
|
+
end
|
|
564
851
|
config_set('interface', 'switchport_autostate_exclude',
|
|
565
|
-
@name, val ? '' : 'no')
|
|
852
|
+
name: @name, state: val ? '' : 'no')
|
|
566
853
|
end
|
|
567
854
|
|
|
568
855
|
def default_switchport_autostate_exclude
|
|
@@ -571,9 +858,9 @@ module Cisco
|
|
|
571
858
|
|
|
572
859
|
def switchport_mode_lookup_string
|
|
573
860
|
case @name
|
|
574
|
-
when
|
|
861
|
+
when ETHERNET
|
|
575
862
|
return 'switchport_mode_ethernet'
|
|
576
|
-
when
|
|
863
|
+
when PORTCHANNEL
|
|
577
864
|
return 'switchport_mode_port_channel'
|
|
578
865
|
else
|
|
579
866
|
return 'switchport_mode_other_interfaces'
|
|
@@ -581,7 +868,8 @@ module Cisco
|
|
|
581
868
|
end
|
|
582
869
|
|
|
583
870
|
def switchport_mode
|
|
584
|
-
|
|
871
|
+
return nil if platform == :ios_xr
|
|
872
|
+
mode = config_get('interface', switchport_mode_lookup_string, name: @name)
|
|
585
873
|
|
|
586
874
|
return mode.nil? ? :disabled : IF_SWITCHPORT_MODE.key(mode)
|
|
587
875
|
|
|
@@ -589,6 +877,7 @@ module Cisco
|
|
|
589
877
|
# Assume this is an interface that doesn't support switchport.
|
|
590
878
|
# Do not raise exception since the providers will prefetch this property
|
|
591
879
|
# regardless of interface type.
|
|
880
|
+
# TODO: this should probably be nil instead
|
|
592
881
|
return :disabled
|
|
593
882
|
end
|
|
594
883
|
|
|
@@ -598,13 +887,10 @@ module Cisco
|
|
|
598
887
|
if :fabricpath == mode_set
|
|
599
888
|
fabricpath_feature_set(:enabled) unless :enabled == fabricpath_feature
|
|
600
889
|
elsif :fex_fabric == mode_set
|
|
601
|
-
|
|
890
|
+
Feature.fex_enable
|
|
602
891
|
end
|
|
603
|
-
config_set('interface', switchport_mode_lookup_string,
|
|
604
|
-
IF_SWITCHPORT_MODE[mode_set])
|
|
605
|
-
|
|
606
|
-
rescue RuntimeError
|
|
607
|
-
raise "[#{@name}] switchport_mode is not supported on this interface"
|
|
892
|
+
config_set('interface', switchport_mode_lookup_string,
|
|
893
|
+
name: @name, state: '', mode: IF_SWITCHPORT_MODE[mode_set])
|
|
608
894
|
end
|
|
609
895
|
|
|
610
896
|
def switchport_mode=(mode_set)
|
|
@@ -617,13 +903,13 @@ module Cisco
|
|
|
617
903
|
when :disabled
|
|
618
904
|
if switchport
|
|
619
905
|
# Note: turn off switchport command, not switchport mode
|
|
620
|
-
config_set('interface', 'switchport', @name, 'no')
|
|
906
|
+
config_set('interface', 'switchport', name: @name, state: 'no')
|
|
621
907
|
end
|
|
622
908
|
|
|
623
909
|
when :default
|
|
624
910
|
if :disabled == default_switchport_mode
|
|
625
911
|
config_set('interface', switchport_mode_lookup_string,
|
|
626
|
-
@name, 'no', '')
|
|
912
|
+
name: @name, state: 'no', mode: '')
|
|
627
913
|
else
|
|
628
914
|
switchport_enable_and_mode(mode_set)
|
|
629
915
|
end
|
|
@@ -631,31 +917,27 @@ module Cisco
|
|
|
631
917
|
else
|
|
632
918
|
switchport_enable_and_mode(mode_set)
|
|
633
919
|
end # case
|
|
634
|
-
|
|
635
|
-
rescue Cisco::CliError => e
|
|
636
|
-
raise "[#{@name}] '#{e.command}' : #{e.clierror}"
|
|
637
920
|
end
|
|
638
921
|
|
|
639
922
|
def default_switchport_mode
|
|
923
|
+
return nil if platform == :ios_xr
|
|
640
924
|
return :disabled unless system_default_switchport
|
|
641
925
|
IF_SWITCHPORT_MODE.key(
|
|
642
926
|
config_get_default('interface', switchport_mode_lookup_string))
|
|
643
927
|
end
|
|
644
928
|
|
|
645
929
|
def switchport_trunk_allowed_vlan
|
|
646
|
-
config_get('interface', 'switchport_trunk_allowed_vlan', @name)
|
|
930
|
+
config_get('interface', 'switchport_trunk_allowed_vlan', name: @name)
|
|
647
931
|
end
|
|
648
932
|
|
|
649
933
|
def switchport_trunk_allowed_vlan=(val)
|
|
650
934
|
if val.nil?
|
|
651
|
-
config_set(
|
|
652
|
-
|
|
935
|
+
config_set('interface', 'switchport_trunk_allowed_vlan',
|
|
936
|
+
name: @name, state: 'no', vlan: '')
|
|
653
937
|
else
|
|
654
|
-
config_set(
|
|
655
|
-
|
|
938
|
+
config_set('interface', 'switchport_trunk_allowed_vlan',
|
|
939
|
+
name: @name, state: '', vlan: val)
|
|
656
940
|
end
|
|
657
|
-
rescue Cisco::CliError => e
|
|
658
|
-
raise "[#{@name}] '#{e.command}' : #{e.clierror}"
|
|
659
941
|
end
|
|
660
942
|
|
|
661
943
|
def default_switchport_trunk_allowed_vlan
|
|
@@ -663,19 +945,488 @@ module Cisco
|
|
|
663
945
|
end
|
|
664
946
|
|
|
665
947
|
def switchport_trunk_native_vlan
|
|
666
|
-
config_get('interface', 'switchport_trunk_native_vlan', @name)
|
|
948
|
+
config_get('interface', 'switchport_trunk_native_vlan', name: @name)
|
|
667
949
|
end
|
|
668
950
|
|
|
669
951
|
def switchport_trunk_native_vlan=(val)
|
|
670
952
|
if val.nil?
|
|
671
|
-
config_set(
|
|
672
|
-
|
|
953
|
+
config_set('interface', 'switchport_trunk_native_vlan',
|
|
954
|
+
name: @name, state: 'no', vlan: '')
|
|
673
955
|
else
|
|
674
|
-
config_set(
|
|
675
|
-
|
|
956
|
+
config_set('interface', 'switchport_trunk_native_vlan',
|
|
957
|
+
name: @name, state: '', vlan: val)
|
|
676
958
|
end
|
|
677
|
-
|
|
678
|
-
|
|
959
|
+
end
|
|
960
|
+
|
|
961
|
+
# Interface private vlan configuration properties
|
|
962
|
+
# private vlan mode (host, promisc, trunk promisc , trunk sec)
|
|
963
|
+
# private vlan mapping
|
|
964
|
+
# private vlan native vlan
|
|
965
|
+
# private vlan allow vlan
|
|
966
|
+
|
|
967
|
+
def cli_error_check(result)
|
|
968
|
+
# The NXOS interface private vlan cli does not raise an exception
|
|
969
|
+
# in some conditions and instead just displays a STDOUT error message
|
|
970
|
+
# thus NXAPI does not detect the failure.
|
|
971
|
+
# We must catch it by inspecting the "body" hash entry
|
|
972
|
+
# returned by NXAPI. This vlan cli behavior is unlikely to change.
|
|
973
|
+
# Check for messages that can be safely ignored.
|
|
974
|
+
|
|
975
|
+
errors = /(ERROR:|VLAN:|Eth)/
|
|
976
|
+
return unless
|
|
977
|
+
result[1].is_a?(Hash) && errors.match(result[1]['body'].to_s)
|
|
978
|
+
# Split errors into a list, but keep the delimiter as part of the message.
|
|
979
|
+
error_list =
|
|
980
|
+
(result[1]['body'].split(errors) - ['']).each_slice(2).map(&:join)
|
|
981
|
+
error_list.each do |_msg|
|
|
982
|
+
fail result[1]['body']
|
|
983
|
+
end
|
|
984
|
+
end
|
|
985
|
+
|
|
986
|
+
def switchport_enable_and_mode_private_vlan_host(mode_set)
|
|
987
|
+
switchport_enable unless switchport
|
|
988
|
+
if mode_set[/(host|promiscuous)/]
|
|
989
|
+
config_set('interface', 'switchport_mode_private_vlan_host',
|
|
990
|
+
name: @name, state: '', mode: IF_SWITCHPORT_MODE[mode_set])
|
|
991
|
+
else
|
|
992
|
+
config_set('interface', 'switchport_mode_private_vlan_host',
|
|
993
|
+
name: @name, state: 'no', mode: IF_SWITCHPORT_MODE[mode_set])
|
|
994
|
+
end
|
|
995
|
+
end
|
|
996
|
+
|
|
997
|
+
def switchport_mode_private_vlan_host
|
|
998
|
+
mode = config_get('interface',
|
|
999
|
+
'switchport_mode_private_vlan_host',
|
|
1000
|
+
name: @name)
|
|
1001
|
+
unless mode == default_switchport_mode_private_vlan_host
|
|
1002
|
+
mode = IF_SWITCHPORT_MODE.key(mode)
|
|
1003
|
+
end
|
|
1004
|
+
mode
|
|
1005
|
+
rescue IndexError
|
|
1006
|
+
# Assume this is an interface that doesn't support switchport.
|
|
1007
|
+
# Do not raise exception since the providers will prefetch this property
|
|
1008
|
+
# regardless of interface type.
|
|
1009
|
+
# TODO: this should probably be nil instead
|
|
1010
|
+
return default_switchport_mode_private_vlan_host
|
|
1011
|
+
end
|
|
1012
|
+
|
|
1013
|
+
def switchport_mode_private_vlan_host=(mode_set)
|
|
1014
|
+
fail ArgumentError unless IF_SWITCHPORT_MODE.keys.include? mode_set
|
|
1015
|
+
Feature.private_vlan_enable
|
|
1016
|
+
switchport_enable_and_mode_private_vlan_host(mode_set)
|
|
1017
|
+
end
|
|
1018
|
+
|
|
1019
|
+
def default_switchport_mode_private_vlan_host
|
|
1020
|
+
config_get_default('interface',
|
|
1021
|
+
'switchport_mode_private_vlan_host')
|
|
1022
|
+
end
|
|
1023
|
+
|
|
1024
|
+
def switchport_mode_private_vlan_host_association
|
|
1025
|
+
result = config_get('interface',
|
|
1026
|
+
'switchport_mode_private_vlan_host_association',
|
|
1027
|
+
name: @name)
|
|
1028
|
+
unless result == default_switchport_mode_private_vlan_host_association
|
|
1029
|
+
result = result[0].split(' ')
|
|
1030
|
+
end
|
|
1031
|
+
result
|
|
1032
|
+
end
|
|
1033
|
+
|
|
1034
|
+
def switchport_mode_private_vlan_host_association=(vlans)
|
|
1035
|
+
fail TypeError unless vlans.is_a?(Array) || vlans.empty?
|
|
1036
|
+
switchport_enable unless switchport
|
|
1037
|
+
Feature.private_vlan_enable
|
|
1038
|
+
if vlans == default_switchport_mode_private_vlan_host_association
|
|
1039
|
+
result = config_set('interface',
|
|
1040
|
+
'switchport_mode_private_vlan_host_association',
|
|
1041
|
+
name: @name, state: 'no', vlan_pr: '', vlan_sec: '')
|
|
1042
|
+
|
|
1043
|
+
else
|
|
1044
|
+
result = config_set('interface',
|
|
1045
|
+
'switchport_mode_private_vlan_host_association',
|
|
1046
|
+
name: @name, state: '',
|
|
1047
|
+
vlan_pr: vlans[0], vlan_sec: vlans[1])
|
|
1048
|
+
|
|
1049
|
+
end
|
|
1050
|
+
cli_error_check(result)
|
|
1051
|
+
end
|
|
1052
|
+
|
|
1053
|
+
def default_switchport_mode_private_vlan_host_association
|
|
1054
|
+
config_get_default('interface',
|
|
1055
|
+
'switchport_mode_private_vlan_host_association')
|
|
1056
|
+
end
|
|
1057
|
+
|
|
1058
|
+
# This api is used by private vlan to prepare the input to the setter
|
|
1059
|
+
# method. The input can be in the following formats for vlans:
|
|
1060
|
+
# 10-12,14. Prepare_array api is transforming this input into a flat array.
|
|
1061
|
+
# In the example above the returned array will be 10, 11, 12, 13. Prepare
|
|
1062
|
+
# array is first splitting the input on ',' and the than expanding the vlan
|
|
1063
|
+
# range element like 10-12 into a flat array. The final result will
|
|
1064
|
+
# be a flat array.
|
|
1065
|
+
# This way we can later used the lib utility to check the delta from
|
|
1066
|
+
# the input vlan value and the vlan configured to apply the right config.
|
|
1067
|
+
def prepare_array(is_list)
|
|
1068
|
+
new_list = []
|
|
1069
|
+
is_list.each do |item|
|
|
1070
|
+
if item.include?(',')
|
|
1071
|
+
new_list.push(item.split(','))
|
|
1072
|
+
else
|
|
1073
|
+
new_list.push(item)
|
|
1074
|
+
end
|
|
1075
|
+
end
|
|
1076
|
+
new_list.flatten!
|
|
1077
|
+
new_list.sort!
|
|
1078
|
+
new_list.each { |item| item.gsub!('-', '..') }
|
|
1079
|
+
is_list_new = []
|
|
1080
|
+
new_list.each do |elem|
|
|
1081
|
+
if elem.include?('..')
|
|
1082
|
+
elema = elem.split('..').map { |d| Integer(d) }
|
|
1083
|
+
elema.sort!
|
|
1084
|
+
tr = elema[0]..elema[1]
|
|
1085
|
+
tr.to_a.each do |item|
|
|
1086
|
+
is_list_new.push(item.to_s)
|
|
1087
|
+
end
|
|
1088
|
+
else
|
|
1089
|
+
is_list_new.push(elem)
|
|
1090
|
+
end
|
|
1091
|
+
end
|
|
1092
|
+
is_list_new
|
|
1093
|
+
end
|
|
1094
|
+
|
|
1095
|
+
def configure_private_vlan_host_property(property, should_list_new,
|
|
1096
|
+
is_list_new, pr_vlan)
|
|
1097
|
+
delta_hash = Utils.delta_add_remove(should_list_new, is_list_new)
|
|
1098
|
+
[:add, :remove].each do |action|
|
|
1099
|
+
delta_hash[action].each do |vlans|
|
|
1100
|
+
state = (action == :add) ? '' : 'no'
|
|
1101
|
+
oper = (action == :add) ? 'add' : 'remove'
|
|
1102
|
+
if property[/(host_promisc|mapping_trunk)/]
|
|
1103
|
+
|
|
1104
|
+
result = config_set('interface', PVLAN_PROPERTY[property],
|
|
1105
|
+
name: @name, state: state,
|
|
1106
|
+
vlan_pr: pr_vlan, vlans: vlans)
|
|
1107
|
+
@match_found = true
|
|
1108
|
+
end
|
|
1109
|
+
if property[/allow_vlan/]
|
|
1110
|
+
result = config_set('interface',
|
|
1111
|
+
PVLAN_PROPERTY[property],
|
|
1112
|
+
name: @name, state: '',
|
|
1113
|
+
oper: oper, vlans: vlans)
|
|
1114
|
+
end
|
|
1115
|
+
if property[/vlan_mapping/]
|
|
1116
|
+
result = config_set('interface',
|
|
1117
|
+
PVLAN_PROPERTY[property],
|
|
1118
|
+
name: @name, state: state,
|
|
1119
|
+
vlans: vlans)
|
|
1120
|
+
end
|
|
1121
|
+
cli_error_check(result)
|
|
1122
|
+
end
|
|
1123
|
+
end
|
|
1124
|
+
end
|
|
1125
|
+
|
|
1126
|
+
def configure_private_vlan_trunk_property(property, should_list_new,
|
|
1127
|
+
is_list, pr_vlan)
|
|
1128
|
+
case property
|
|
1129
|
+
when :trunk_assoc
|
|
1130
|
+
is_list.each do |vlans|
|
|
1131
|
+
vlans = vlans.split(' ')
|
|
1132
|
+
if vlans[0].eql? should_list_new[0]
|
|
1133
|
+
config_set('interface',
|
|
1134
|
+
'switchport_private_vlan_association_trunk',
|
|
1135
|
+
name: @name, state: 'no',
|
|
1136
|
+
vlan_pr: pr_vlan, vlan: vlans[1])
|
|
1137
|
+
break
|
|
1138
|
+
else
|
|
1139
|
+
next
|
|
1140
|
+
end
|
|
1141
|
+
end
|
|
1142
|
+
result = config_set('interface', PVLAN_PROPERTY[property], name: @name,
|
|
1143
|
+
state: '', vlan_pr: should_list_new[0],
|
|
1144
|
+
vlan: should_list_new[1])
|
|
1145
|
+
when :mapping_trunk
|
|
1146
|
+
@match_found = false
|
|
1147
|
+
is_list.each do |vlans|
|
|
1148
|
+
vlans = vlans.split(' ')
|
|
1149
|
+
interf_vlan_list_delta(:mapping_trunk, vlans,
|
|
1150
|
+
should_list_new)
|
|
1151
|
+
if @match_found
|
|
1152
|
+
break
|
|
1153
|
+
else
|
|
1154
|
+
next
|
|
1155
|
+
end
|
|
1156
|
+
end
|
|
1157
|
+
result = config_set('interface', PVLAN_PROPERTY[property], name: @name,
|
|
1158
|
+
state: '', vlan_pr: should_list_new[0],
|
|
1159
|
+
vlans: should_list_new[1])
|
|
1160
|
+
end
|
|
1161
|
+
cli_error_check(result)
|
|
1162
|
+
end
|
|
1163
|
+
|
|
1164
|
+
# --------------------------
|
|
1165
|
+
# interf_vlan_list_delta is a helper function for the private_vlan_mapping
|
|
1166
|
+
# property. It walks the delta hash and adds/removes each target private
|
|
1167
|
+
# vlan.
|
|
1168
|
+
|
|
1169
|
+
def interf_vlan_list_delta(property, is_list, should_list)
|
|
1170
|
+
pr_vlan = should_list[0]
|
|
1171
|
+
if is_list[0].eql? should_list[0]
|
|
1172
|
+
should_list = should_list[1].split(',')
|
|
1173
|
+
is_list = is_list[1].split(',')
|
|
1174
|
+
|
|
1175
|
+
should_list_new = prepare_array(should_list)
|
|
1176
|
+
is_list_new = prepare_array(is_list)
|
|
1177
|
+
configure_private_vlan_host_property(property, should_list_new,
|
|
1178
|
+
is_list_new, pr_vlan)
|
|
1179
|
+
else
|
|
1180
|
+
case property
|
|
1181
|
+
when :mapping_trunk
|
|
1182
|
+
return
|
|
1183
|
+
end
|
|
1184
|
+
# If primary vlan are different we can simply replacing the all
|
|
1185
|
+
# config
|
|
1186
|
+
if should_list == default_switchport_mode_private_vlan_host_promisc
|
|
1187
|
+
result = config_set('interface',
|
|
1188
|
+
'switchport_mode_private_vlan_host_promiscous',
|
|
1189
|
+
name: @name, state: 'no',
|
|
1190
|
+
vlan_pr: '', vlans: '')
|
|
1191
|
+
|
|
1192
|
+
else
|
|
1193
|
+
result = config_set('interface',
|
|
1194
|
+
'switchport_mode_private_vlan_host_promiscous',
|
|
1195
|
+
name: @name, state: '',
|
|
1196
|
+
vlan_pr: pr_vlan, vlans: should_list[1])
|
|
1197
|
+
|
|
1198
|
+
end
|
|
1199
|
+
cli_error_check(result)
|
|
1200
|
+
end
|
|
1201
|
+
end
|
|
1202
|
+
|
|
1203
|
+
def switchport_mode_private_vlan_host_promisc
|
|
1204
|
+
result = config_get('interface',
|
|
1205
|
+
'switchport_mode_private_vlan_host_promiscous',
|
|
1206
|
+
name: @name)
|
|
1207
|
+
unless result == default_switchport_mode_private_vlan_host_promisc
|
|
1208
|
+
result = result[0].split(' ')
|
|
1209
|
+
end
|
|
1210
|
+
result
|
|
1211
|
+
end
|
|
1212
|
+
|
|
1213
|
+
def switchport_mode_private_vlan_host_promisc=(vlans)
|
|
1214
|
+
fail TypeError unless vlans.is_a?(Array)
|
|
1215
|
+
fail TypeError unless vlans.empty? || vlans.length == 2
|
|
1216
|
+
switchport_enable unless switchport
|
|
1217
|
+
Feature.private_vlan_enable
|
|
1218
|
+
is_list = switchport_mode_private_vlan_host_promisc
|
|
1219
|
+
interf_vlan_list_delta(:host_promisc, is_list, vlans)
|
|
1220
|
+
end
|
|
1221
|
+
|
|
1222
|
+
def default_switchport_mode_private_vlan_host_promisc
|
|
1223
|
+
config_get_default('interface',
|
|
1224
|
+
'switchport_mode_private_vlan_host_promiscous')
|
|
1225
|
+
end
|
|
1226
|
+
|
|
1227
|
+
def switchport_mode_private_vlan_trunk_promiscuous
|
|
1228
|
+
config_get('interface',
|
|
1229
|
+
'switchport_mode_private_vlan_trunk_promiscuous',
|
|
1230
|
+
name: @name)
|
|
1231
|
+
rescue IndexError
|
|
1232
|
+
# Assume this is an interface that doesn't support switchport.
|
|
1233
|
+
# Do not raise exception since the providers will prefetch this property
|
|
1234
|
+
# regardless of interface type.
|
|
1235
|
+
# TODO: this should probably be nil instead
|
|
1236
|
+
return default_switchport_mode_private_vlan_trunk_promiscuous
|
|
1237
|
+
end
|
|
1238
|
+
|
|
1239
|
+
def switchport_mode_private_vlan_trunk_promiscuous=(state)
|
|
1240
|
+
Feature.private_vlan_enable
|
|
1241
|
+
switchport_enable unless switchport
|
|
1242
|
+
if state == default_switchport_mode_private_vlan_trunk_promiscuous
|
|
1243
|
+
config_set('interface',
|
|
1244
|
+
'switchport_mode_private_vlan_trunk_promiscuous',
|
|
1245
|
+
name: @name, state: 'no')
|
|
1246
|
+
else
|
|
1247
|
+
config_set('interface',
|
|
1248
|
+
'switchport_mode_private_vlan_trunk_promiscuous',
|
|
1249
|
+
name: @name, state: '')
|
|
1250
|
+
end
|
|
1251
|
+
end
|
|
1252
|
+
|
|
1253
|
+
def default_switchport_mode_private_vlan_trunk_promiscuous
|
|
1254
|
+
config_get_default('interface',
|
|
1255
|
+
'switchport_mode_private_vlan_trunk_promiscuous')
|
|
1256
|
+
end
|
|
1257
|
+
|
|
1258
|
+
def switchport_mode_private_vlan_trunk_secondary
|
|
1259
|
+
config_get('interface',
|
|
1260
|
+
'switchport_mode_private_vlan_trunk_secondary',
|
|
1261
|
+
name: @name)
|
|
1262
|
+
rescue IndexError
|
|
1263
|
+
# Assume this is an interface that doesn't support switchport.
|
|
1264
|
+
# Do not raise exception since the providers will prefetch this property
|
|
1265
|
+
# regardless of interface type.
|
|
1266
|
+
# TODO: this should probably be nil instead
|
|
1267
|
+
return default_switchport_mode_private_vlan_trunk_secondary
|
|
1268
|
+
end
|
|
1269
|
+
|
|
1270
|
+
def switchport_mode_private_vlan_trunk_secondary=(state)
|
|
1271
|
+
Feature.private_vlan_enable
|
|
1272
|
+
switchport_enable unless switchport
|
|
1273
|
+
if state == default_switchport_mode_private_vlan_trunk_secondary
|
|
1274
|
+
config_set('interface', 'switchport_mode_private_vlan_trunk_secondary',
|
|
1275
|
+
name: @name, state: 'no')
|
|
1276
|
+
else
|
|
1277
|
+
config_set('interface', 'switchport_mode_private_vlan_trunk_secondary',
|
|
1278
|
+
name: @name, state: '')
|
|
1279
|
+
end
|
|
1280
|
+
end
|
|
1281
|
+
|
|
1282
|
+
def default_switchport_mode_private_vlan_trunk_secondary
|
|
1283
|
+
config_get_default('interface',
|
|
1284
|
+
'switchport_mode_private_vlan_trunk_secondary')
|
|
1285
|
+
end
|
|
1286
|
+
|
|
1287
|
+
def switchport_private_vlan_trunk_allowed_vlan
|
|
1288
|
+
result = config_get('interface',
|
|
1289
|
+
'switchport_private_vlan_trunk_allowed_vlan',
|
|
1290
|
+
name: @name)
|
|
1291
|
+
|
|
1292
|
+
unless result == default_switchport_private_vlan_trunk_allowed_vlan
|
|
1293
|
+
if result[0].eql? 'none'
|
|
1294
|
+
result = default_switchport_private_vlan_trunk_allowed_vlan
|
|
1295
|
+
else
|
|
1296
|
+
result = result[0].split(',')
|
|
1297
|
+
end
|
|
1298
|
+
end
|
|
1299
|
+
result
|
|
1300
|
+
end
|
|
1301
|
+
|
|
1302
|
+
def switchport_private_vlan_trunk_allowed_vlan=(vlans)
|
|
1303
|
+
fail TypeError unless vlans.is_a?(Array)
|
|
1304
|
+
Feature.private_vlan_enable
|
|
1305
|
+
switchport_enable unless switchport
|
|
1306
|
+
if vlans == default_switchport_private_vlan_trunk_allowed_vlan
|
|
1307
|
+
vlans = prepare_array(switchport_private_vlan_trunk_allowed_vlan)
|
|
1308
|
+
# If there are no vlan presently configured, we can simply return
|
|
1309
|
+
return if vlans == default_switchport_private_vlan_trunk_allowed_vlan
|
|
1310
|
+
configure_private_vlan_host_property(:allow_vlan, [],
|
|
1311
|
+
vlans, '')
|
|
1312
|
+
else
|
|
1313
|
+
vlans = prepare_array(vlans)
|
|
1314
|
+
is_list = prepare_array(switchport_private_vlan_trunk_allowed_vlan)
|
|
1315
|
+
configure_private_vlan_host_property(:allow_vlan, vlans,
|
|
1316
|
+
is_list, '')
|
|
1317
|
+
end
|
|
1318
|
+
end
|
|
1319
|
+
|
|
1320
|
+
def default_switchport_private_vlan_trunk_allowed_vlan
|
|
1321
|
+
config_get_default('interface',
|
|
1322
|
+
'switchport_private_vlan_trunk_allowed_vlan')
|
|
1323
|
+
end
|
|
1324
|
+
|
|
1325
|
+
def switchport_private_vlan_trunk_native_vlan
|
|
1326
|
+
config_get('interface',
|
|
1327
|
+
'switchport_private_vlan_trunk_native_vlan',
|
|
1328
|
+
name: @name)
|
|
1329
|
+
end
|
|
1330
|
+
|
|
1331
|
+
def switchport_private_vlan_trunk_native_vlan=(vlan)
|
|
1332
|
+
Feature.private_vlan_enable
|
|
1333
|
+
switchport_enable unless switchport
|
|
1334
|
+
if vlan == default_switchport_private_vlan_trunk_native_vlan
|
|
1335
|
+
config_set('interface',
|
|
1336
|
+
'switchport_private_vlan_trunk_native_vlan',
|
|
1337
|
+
name: @name, state: 'no', vlan: '')
|
|
1338
|
+
|
|
1339
|
+
else
|
|
1340
|
+
config_set('interface',
|
|
1341
|
+
'switchport_private_vlan_trunk_native_vlan',
|
|
1342
|
+
name: @name, state: '', vlan: vlan)
|
|
1343
|
+
end
|
|
1344
|
+
end
|
|
1345
|
+
|
|
1346
|
+
def default_switchport_private_vlan_trunk_native_vlan
|
|
1347
|
+
config_get_default('interface',
|
|
1348
|
+
'switchport_private_vlan_trunk_native_vlan')
|
|
1349
|
+
end
|
|
1350
|
+
|
|
1351
|
+
def switchport_private_vlan_association_trunk
|
|
1352
|
+
config_get('interface',
|
|
1353
|
+
'switchport_private_vlan_association_trunk',
|
|
1354
|
+
name: @name)
|
|
1355
|
+
end
|
|
1356
|
+
|
|
1357
|
+
def switchport_private_vlan_association_trunk=(vlans)
|
|
1358
|
+
fail TypeError unless vlans.is_a?(Array) || vlans.empty?
|
|
1359
|
+
Feature.private_vlan_enable
|
|
1360
|
+
switchport_enable unless switchport
|
|
1361
|
+
if vlans == default_switchport_private_vlan_association_trunk
|
|
1362
|
+
config_set('interface', 'switchport_private_vlan_association_trunk',
|
|
1363
|
+
name: @name, state: 'no',
|
|
1364
|
+
vlan_pr: '', vlan: '')
|
|
1365
|
+
else
|
|
1366
|
+
is_list = switchport_private_vlan_association_trunk
|
|
1367
|
+
configure_private_vlan_trunk_property(:trunk_assoc, vlans,
|
|
1368
|
+
is_list, vlans[0])
|
|
1369
|
+
end
|
|
1370
|
+
end
|
|
1371
|
+
|
|
1372
|
+
def default_switchport_private_vlan_association_trunk
|
|
1373
|
+
config_get_default('interface',
|
|
1374
|
+
'switchport_private_vlan_association_trunk')
|
|
1375
|
+
end
|
|
1376
|
+
|
|
1377
|
+
def switchport_private_vlan_mapping_trunk
|
|
1378
|
+
config_get('interface',
|
|
1379
|
+
'switchport_private_vlan_mapping_trunk',
|
|
1380
|
+
name: @name)
|
|
1381
|
+
end
|
|
1382
|
+
|
|
1383
|
+
def switchport_private_vlan_mapping_trunk=(vlans)
|
|
1384
|
+
fail TypeError unless vlans.is_a?(Array) || vlans.empty?
|
|
1385
|
+
Feature.private_vlan_enable
|
|
1386
|
+
switchport_enable unless switchport
|
|
1387
|
+
if vlans == default_switchport_private_vlan_mapping_trunk
|
|
1388
|
+
config_set('interface', 'switchport_private_vlan_mapping_trunk',
|
|
1389
|
+
name: @name, state: 'no',
|
|
1390
|
+
vlan_pr: '', vlans: '')
|
|
1391
|
+
else
|
|
1392
|
+
is_list = switchport_private_vlan_mapping_trunk
|
|
1393
|
+
configure_private_vlan_trunk_property(:mapping_trunk, vlans,
|
|
1394
|
+
is_list, vlans[0])
|
|
1395
|
+
end
|
|
1396
|
+
end
|
|
1397
|
+
|
|
1398
|
+
def default_switchport_private_vlan_mapping_trunk
|
|
1399
|
+
config_get_default('interface',
|
|
1400
|
+
'switchport_private_vlan_mapping_trunk')
|
|
1401
|
+
end
|
|
1402
|
+
|
|
1403
|
+
def private_vlan_mapping
|
|
1404
|
+
match = config_get('interface',
|
|
1405
|
+
'private_vlan_mapping',
|
|
1406
|
+
name: @name)
|
|
1407
|
+
match[0].delete!(' ') unless match == default_private_vlan_mapping
|
|
1408
|
+
match
|
|
1409
|
+
end
|
|
1410
|
+
|
|
1411
|
+
def private_vlan_mapping=(vlans)
|
|
1412
|
+
fail TypeError unless vlans.is_a?(Array) || vlans.empty?
|
|
1413
|
+
Feature.private_vlan_enable
|
|
1414
|
+
feature_vlan_set(true)
|
|
1415
|
+
if vlans == default_private_vlan_mapping
|
|
1416
|
+
config_set('interface', 'private_vlan_mapping',
|
|
1417
|
+
name: @name, state: 'no', vlans: '')
|
|
1418
|
+
else
|
|
1419
|
+
is_list = private_vlan_mapping
|
|
1420
|
+
new_is_list = prepare_array(is_list)
|
|
1421
|
+
new_vlans = prepare_array(vlans)
|
|
1422
|
+
configure_private_vlan_host_property(:vlan_mapping, new_vlans,
|
|
1423
|
+
new_is_list, '')
|
|
1424
|
+
end
|
|
1425
|
+
end
|
|
1426
|
+
|
|
1427
|
+
def default_private_vlan_mapping
|
|
1428
|
+
config_get_default('interface',
|
|
1429
|
+
'private_vlan_mapping')
|
|
679
1430
|
end
|
|
680
1431
|
|
|
681
1432
|
# vlan_mapping & vlan_mapping_enable
|
|
@@ -698,13 +1449,13 @@ module Cisco
|
|
|
698
1449
|
end
|
|
699
1450
|
|
|
700
1451
|
def vlan_mapping
|
|
701
|
-
match = config_get('interface', 'vlan_mapping', @name)
|
|
1452
|
+
match = config_get('interface', 'vlan_mapping', name: @name)
|
|
702
1453
|
match.each(&:compact!) unless match.nil?
|
|
703
1454
|
match
|
|
704
1455
|
end
|
|
705
1456
|
|
|
706
1457
|
def vlan_mapping=(should_list)
|
|
707
|
-
|
|
1458
|
+
Feature.vni_enable
|
|
708
1459
|
|
|
709
1460
|
# Process a hash of vlan_mapping cmds from delta_add_remove().
|
|
710
1461
|
# The vlan_mapping cli does not allow commands to be updated, they must
|
|
@@ -714,16 +1465,14 @@ module Cisco
|
|
|
714
1465
|
return if delta_hash.values.flatten.empty?
|
|
715
1466
|
# Process :remove first to ensure "update" commands will not fail.
|
|
716
1467
|
[:remove, :add].each do |action|
|
|
717
|
-
|
|
718
|
-
|
|
1468
|
+
Cisco::Logger.debug("vlan_mapping delta #{@get_args}\n"\
|
|
1469
|
+
"#{action}: #{delta_hash[action]}")
|
|
719
1470
|
delta_hash[action].each do |original, translated|
|
|
720
1471
|
state = (action == :add) ? '' : 'no'
|
|
721
|
-
config_set('interface', 'vlan_mapping', @name,
|
|
722
|
-
state, original, translated)
|
|
1472
|
+
config_set('interface', 'vlan_mapping', name: @name,
|
|
1473
|
+
state: state, original: original, translated: translated)
|
|
723
1474
|
end
|
|
724
1475
|
end
|
|
725
|
-
rescue Cisco::CliError => e
|
|
726
|
-
raise "[#{@name}] '#{e.command}' : #{e.clierror}"
|
|
727
1476
|
end
|
|
728
1477
|
|
|
729
1478
|
# cli: switchport vlan mapping enable
|
|
@@ -732,12 +1481,12 @@ module Cisco
|
|
|
732
1481
|
end
|
|
733
1482
|
|
|
734
1483
|
def vlan_mapping_enable
|
|
735
|
-
config_get('interface', 'vlan_mapping_enable', @name)
|
|
1484
|
+
config_get('interface', 'vlan_mapping_enable', name: @name)
|
|
736
1485
|
end
|
|
737
1486
|
|
|
738
1487
|
def vlan_mapping_enable=(state)
|
|
739
|
-
config_set('interface', 'vlan_mapping_enable',
|
|
740
|
-
state ? '' : 'no')
|
|
1488
|
+
config_set('interface', 'vlan_mapping_enable',
|
|
1489
|
+
name: @name, state: state ? '' : 'no')
|
|
741
1490
|
end
|
|
742
1491
|
|
|
743
1492
|
def default_switchport_trunk_native_vlan
|
|
@@ -782,16 +1531,15 @@ module Cisco
|
|
|
782
1531
|
end
|
|
783
1532
|
|
|
784
1533
|
def switchport_vtp
|
|
785
|
-
return
|
|
786
|
-
config_get('interface', 'vtp', @name)
|
|
1534
|
+
return nil unless switchport_vtp_mode_capable?
|
|
1535
|
+
config_get('interface', 'vtp', name: @name)
|
|
787
1536
|
end
|
|
788
1537
|
|
|
789
1538
|
def switchport_vtp=(vtp_set)
|
|
1539
|
+
# TODO: throw UnsupportedError instead of returning false?
|
|
790
1540
|
return false unless switchport_vtp_mode_capable?
|
|
791
1541
|
no_cmd = (vtp_set) ? '' : 'no'
|
|
792
|
-
config_set('interface', 'vtp', @name, no_cmd)
|
|
793
|
-
rescue Cisco::CliError => e
|
|
794
|
-
raise "[#{@name}] '#{e.command}' : #{e.clierror}"
|
|
1542
|
+
config_set('interface', 'vtp', name: @name, state: no_cmd)
|
|
795
1543
|
end
|
|
796
1544
|
|
|
797
1545
|
def svi_cmd_allowed?(cmd)
|
|
@@ -802,13 +1550,14 @@ module Cisco
|
|
|
802
1550
|
# svi_autostate is exclusive to svi interfaces
|
|
803
1551
|
def svi_autostate
|
|
804
1552
|
return nil unless @name[/^vlan/i]
|
|
805
|
-
config_get('interface', 'svi_autostate', @name)
|
|
1553
|
+
config_get('interface', 'svi_autostate', name: @name)
|
|
806
1554
|
end
|
|
807
1555
|
|
|
808
1556
|
def svi_autostate=(val)
|
|
809
|
-
|
|
1557
|
+
check_switchport(:disabled)
|
|
810
1558
|
svi_cmd_allowed?('autostate')
|
|
811
|
-
config_set('interface', 'svi_autostate',
|
|
1559
|
+
config_set('interface', 'svi_autostate',
|
|
1560
|
+
name: @name, state: val ? '' : 'no')
|
|
812
1561
|
end
|
|
813
1562
|
|
|
814
1563
|
def default_svi_autostate
|
|
@@ -821,19 +1570,20 @@ module Cisco
|
|
|
821
1570
|
|
|
822
1571
|
def feature_vlan_set(val)
|
|
823
1572
|
return if feature_vlan? == val
|
|
824
|
-
config_set('interface', 'feature_vlan', val ? '' : 'no')
|
|
1573
|
+
config_set('interface', 'feature_vlan', state: val ? '' : 'no')
|
|
825
1574
|
end
|
|
826
1575
|
|
|
827
1576
|
# svi_management is exclusive to svi interfaces
|
|
828
1577
|
def svi_management
|
|
829
1578
|
return nil unless @name[/^vlan/i]
|
|
830
|
-
config_get('interface', 'svi_management', @name)
|
|
1579
|
+
config_get('interface', 'svi_management', name: @name)
|
|
831
1580
|
end
|
|
832
1581
|
|
|
833
1582
|
def svi_management=(val)
|
|
834
|
-
|
|
1583
|
+
check_switchport(:disabled)
|
|
835
1584
|
svi_cmd_allowed?('management')
|
|
836
|
-
config_set('interface', 'svi_management',
|
|
1585
|
+
config_set('interface', 'svi_management',
|
|
1586
|
+
name: @name, state: val ? '' : 'no')
|
|
837
1587
|
end
|
|
838
1588
|
|
|
839
1589
|
def default_svi_management
|
|
@@ -841,6 +1591,7 @@ module Cisco
|
|
|
841
1591
|
end
|
|
842
1592
|
|
|
843
1593
|
def default_switchport_vtp
|
|
1594
|
+
return nil unless switchport_vtp_mode_capable?
|
|
844
1595
|
config_get_default('interface', 'vtp')
|
|
845
1596
|
end
|
|
846
1597
|
|
|
@@ -848,22 +1599,36 @@ module Cisco
|
|
|
848
1599
|
config_get('vtp', 'feature')
|
|
849
1600
|
end
|
|
850
1601
|
|
|
851
|
-
def
|
|
852
|
-
|
|
853
|
-
|
|
1602
|
+
def switchport_status?(status)
|
|
1603
|
+
case status
|
|
1604
|
+
when :disabled
|
|
1605
|
+
return true if switchport_mode == status || switchport_mode.nil?
|
|
1606
|
+
when :access, :trunk
|
|
1607
|
+
return switchport_mode == status
|
|
1608
|
+
when Array
|
|
1609
|
+
return status.include?(switchport_mode)
|
|
1610
|
+
else
|
|
1611
|
+
return false
|
|
1612
|
+
end
|
|
1613
|
+
end
|
|
1614
|
+
|
|
1615
|
+
def check_switchport(status)
|
|
1616
|
+
return if switchport_status?(status)
|
|
1617
|
+
fail("#{caller[0][/`.*'/][1..-2]} cannot be set unless " \
|
|
1618
|
+
"switchport mode is #{status}")
|
|
854
1619
|
end
|
|
855
1620
|
|
|
856
1621
|
def vpc_id
|
|
857
|
-
config_get('interface', 'vpc_id', @name)
|
|
1622
|
+
config_get('interface', 'vpc_id', name: @name)
|
|
858
1623
|
end
|
|
859
1624
|
|
|
860
1625
|
def vpc_id=(num)
|
|
861
1626
|
if num
|
|
862
|
-
config_set('interface', 'vpc_id', @name, '', num)
|
|
1627
|
+
config_set('interface', 'vpc_id', name: @name, state: '', id: num)
|
|
863
1628
|
else
|
|
864
1629
|
# 'no vpc' doesn't work for phy ports, so do a get
|
|
865
1630
|
num = vpc_id
|
|
866
|
-
config_set('interface', 'vpc_id', @name, 'no', num)
|
|
1631
|
+
config_set('interface', 'vpc_id', name: @name, state: 'no', id: num)
|
|
867
1632
|
end
|
|
868
1633
|
end
|
|
869
1634
|
|
|
@@ -872,12 +1637,12 @@ module Cisco
|
|
|
872
1637
|
end
|
|
873
1638
|
|
|
874
1639
|
def vpc_peer_link
|
|
875
|
-
config_get('interface', 'vpc_peer_link', @name)
|
|
1640
|
+
config_get('interface', 'vpc_peer_link', name: @name)
|
|
876
1641
|
end
|
|
877
1642
|
|
|
878
1643
|
def vpc_peer_link=(state)
|
|
879
1644
|
no_cmd = (state ? '' : 'no')
|
|
880
|
-
config_set('interface', 'vpc_peer_link', @name, no_cmd)
|
|
1645
|
+
config_set('interface', 'vpc_peer_link', name: @name, state: no_cmd)
|
|
881
1646
|
end
|
|
882
1647
|
|
|
883
1648
|
def default_vpc_peer_link
|
|
@@ -885,22 +1650,48 @@ module Cisco
|
|
|
885
1650
|
end
|
|
886
1651
|
|
|
887
1652
|
def vrf
|
|
888
|
-
config_get('interface', 'vrf', @name)
|
|
889
|
-
end
|
|
890
|
-
|
|
891
|
-
def vrf=(
|
|
892
|
-
fail TypeError unless
|
|
893
|
-
if vrf
|
|
894
|
-
|
|
1653
|
+
config_get('interface', 'vrf', name: @name)
|
|
1654
|
+
end
|
|
1655
|
+
|
|
1656
|
+
def vrf=(v)
|
|
1657
|
+
fail TypeError unless v.is_a?(String)
|
|
1658
|
+
return if v == vrf
|
|
1659
|
+
# Changing the VRF can result in loss of IP address, so cache it
|
|
1660
|
+
addr_1 = ipv4_address
|
|
1661
|
+
mask_1 = ipv4_netmask_length
|
|
1662
|
+
addr_2 = ipv4_address_secondary
|
|
1663
|
+
mask_2 = ipv4_netmask_length_secondary
|
|
1664
|
+
# XR actually blocks you from changing the VRF if IP addr is present
|
|
1665
|
+
unless platform == :nexus
|
|
1666
|
+
ipv4_addr_mask_set(nil, nil, false) unless addr_1.nil?
|
|
1667
|
+
ipv4_addr_mask_set(nil, nil, true) unless addr_2.nil?
|
|
1668
|
+
end
|
|
1669
|
+
if v.empty?
|
|
1670
|
+
config_set('interface', 'vrf', name: @name, state: 'no', vrf: '')
|
|
895
1671
|
else
|
|
896
|
-
config_set('interface', 'vrf', @name, '', vrf)
|
|
1672
|
+
config_set('interface', 'vrf', name: @name, state: '', vrf: v)
|
|
897
1673
|
end
|
|
898
|
-
|
|
899
|
-
|
|
1674
|
+
ipv4_addr_mask_set(addr_1, mask_1, false) unless addr_1.nil?
|
|
1675
|
+
ipv4_addr_mask_set(addr_2, mask_2, true) unless addr_2.nil?
|
|
900
1676
|
end
|
|
901
1677
|
|
|
902
1678
|
def default_vrf
|
|
903
1679
|
config_get_default('interface', 'vrf')
|
|
904
1680
|
end
|
|
1681
|
+
|
|
1682
|
+
def set_range_based_params(list, param_name)
|
|
1683
|
+
list.each do |range, property_value|
|
|
1684
|
+
# if a particular range is set to default, use 'no' cmd
|
|
1685
|
+
if property_value == 'default'
|
|
1686
|
+
config_set('interface', param_name,
|
|
1687
|
+
name: @name, state: 'no',
|
|
1688
|
+
range: range, val: '')
|
|
1689
|
+
else
|
|
1690
|
+
config_set('interface', param_name,
|
|
1691
|
+
name: @name, state: '',
|
|
1692
|
+
range: range, val: property_value)
|
|
1693
|
+
end
|
|
1694
|
+
end
|
|
1695
|
+
end
|
|
905
1696
|
end # Class
|
|
906
1697
|
end # Module
|