cisco_node_utils_mgx 2.1.0.1
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 +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.rubocop.yml +96 -0
- data/.travis.yml +17 -0
- data/CHANGELOG.md +676 -0
- data/CONTRIBUTING.md +43 -0
- data/Gemfile +10 -0
- data/LICENSE +201 -0
- data/README.md +246 -0
- data/Rakefile +44 -0
- data/SUPPORT.md +3 -0
- data/bin/.rubocop.yml +18 -0
- data/bin/check_metric_limits.rb +109 -0
- data/bin/git/hooks/commit-msg/enforce_style +89 -0
- data/bin/git/hooks/hook_lib +115 -0
- data/bin/git/hooks/hooks-wrapper +38 -0
- data/bin/git/hooks/post-flow-hotfix-start/update-version +24 -0
- data/bin/git/hooks/post-flow-release-finish/update-version +29 -0
- data/bin/git/hooks/post-flow-release-start/update-version +19 -0
- data/bin/git/hooks/post-merge/update-hooks +6 -0
- data/bin/git/hooks/post-rewrite/update-hooks +6 -0
- data/bin/git/hooks/pre-commit/check_unstaged_changes +18 -0
- data/bin/git/hooks/pre-commit/rubocop +25 -0
- data/bin/git/hooks/pre-commit/validate-diffs +45 -0
- data/bin/git/hooks/pre-commit/validate-yaml +18 -0
- data/bin/git/hooks/pre-push/check-changelog +24 -0
- data/bin/git/hooks/pre-push/rubocop +7 -0
- data/bin/git/update-hooks +123 -0
- data/bin/show_running_yang.rb +233 -0
- data/cisco_node_utils.gemspec +41 -0
- data/docs/README-develop-best-practices.md +521 -0
- data/docs/README-develop-node-utils-APIs.md +570 -0
- data/docs/README-maintainers.md +77 -0
- data/docs/README-test-execution.md +57 -0
- data/docs/README-utilities.md +14 -0
- data/docs/agent_files.png +0 -0
- data/docs/cisco_node_utils.yaml.example +36 -0
- data/docs/template-router.rb +123 -0
- data/docs/template-test_router.rb +104 -0
- data/ext/mkrf_conf.rb +63 -0
- data/lib/.rubocop.yml +18 -0
- data/lib/cisco_node_utils/aaa_authentication_login.rb +95 -0
- data/lib/cisco_node_utils/aaa_authentication_login_service.rb +138 -0
- data/lib/cisco_node_utils/aaa_authorization_service.rb +156 -0
- data/lib/cisco_node_utils/ace.rb +467 -0
- data/lib/cisco_node_utils/acl.rb +101 -0
- data/lib/cisco_node_utils/banner.rb +63 -0
- data/lib/cisco_node_utils/bfd_global.rb +305 -0
- data/lib/cisco_node_utils/bgp.rb +988 -0
- data/lib/cisco_node_utils/bgp_af.rb +545 -0
- data/lib/cisco_node_utils/bgp_af_aggr_addr.rb +207 -0
- data/lib/cisco_node_utils/bgp_neighbor.rb +527 -0
- data/lib/cisco_node_utils/bgp_neighbor_af.rb +780 -0
- data/lib/cisco_node_utils/bridge_domain.rb +178 -0
- data/lib/cisco_node_utils/bridge_domain_vni.rb +206 -0
- data/lib/cisco_node_utils/cisco_cmn_utils.rb +444 -0
- data/lib/cisco_node_utils/client/client.rb +238 -0
- data/lib/cisco_node_utils/client/grpc/client.rb +395 -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/grpc.rb +33 -0
- data/lib/cisco_node_utils/client/nxapi/client.rb +368 -0
- data/lib/cisco_node_utils/client/nxapi.rb +31 -0
- data/lib/cisco_node_utils/client/utils.rb +180 -0
- data/lib/cisco_node_utils/client.rb +35 -0
- data/lib/cisco_node_utils/cmd_ref/README_YAML.md +590 -0
- data/lib/cisco_node_utils/cmd_ref/aaa_auth_login_service.yaml +25 -0
- data/lib/cisco_node_utils/cmd_ref/aaa_authentication_login.yaml +38 -0
- data/lib/cisco_node_utils/cmd_ref/aaa_authorization_service.yaml +40 -0
- data/lib/cisco_node_utils/cmd_ref/acl.yaml +48 -0
- data/lib/cisco_node_utils/cmd_ref/banner.yaml +11 -0
- data/lib/cisco_node_utils/cmd_ref/bfd_global.yaml +117 -0
- data/lib/cisco_node_utils/cmd_ref/bgp.yaml +383 -0
- data/lib/cisco_node_utils/cmd_ref/bgp_af.yaml +223 -0
- data/lib/cisco_node_utils/cmd_ref/bgp_af_aa.yaml +38 -0
- data/lib/cisco_node_utils/cmd_ref/bgp_neighbor.yaml +174 -0
- data/lib/cisco_node_utils/cmd_ref/bgp_neighbor_af.yaml +236 -0
- data/lib/cisco_node_utils/cmd_ref/bridge_domain.yaml +49 -0
- data/lib/cisco_node_utils/cmd_ref/bridge_domain_vni.yaml +33 -0
- data/lib/cisco_node_utils/cmd_ref/dhcp_relay_global.yaml +128 -0
- data/lib/cisco_node_utils/cmd_ref/dnsclient.yaml +55 -0
- data/lib/cisco_node_utils/cmd_ref/encapsulation.yaml +25 -0
- data/lib/cisco_node_utils/cmd_ref/evpn_multicast.yaml +12 -0
- data/lib/cisco_node_utils/cmd_ref/evpn_multisite.yaml +18 -0
- data/lib/cisco_node_utils/cmd_ref/evpn_stormcontrol.yaml +18 -0
- data/lib/cisco_node_utils/cmd_ref/evpn_vni.yaml +48 -0
- data/lib/cisco_node_utils/cmd_ref/fabricpath.yaml +183 -0
- data/lib/cisco_node_utils/cmd_ref/fabricpath_topology.yaml +40 -0
- data/lib/cisco_node_utils/cmd_ref/feature.yaml +126 -0
- data/lib/cisco_node_utils/cmd_ref/hostname.yaml +8 -0
- data/lib/cisco_node_utils/cmd_ref/hsrp_global.yaml +25 -0
- data/lib/cisco_node_utils/cmd_ref/images.yaml +8 -0
- data/lib/cisco_node_utils/cmd_ref/interface.yaml +781 -0
- data/lib/cisco_node_utils/cmd_ref/interface_channel_group.yaml +45 -0
- data/lib/cisco_node_utils/cmd_ref/interface_evpn_multisite.yaml +17 -0
- data/lib/cisco_node_utils/cmd_ref/interface_hsrp_group.yaml +120 -0
- data/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +112 -0
- data/lib/cisco_node_utils/cmd_ref/interface_portchannel.yaml +87 -0
- data/lib/cisco_node_utils/cmd_ref/interface_service_vni.yaml +42 -0
- data/lib/cisco_node_utils/cmd_ref/inventory.yaml +45 -0
- data/lib/cisco_node_utils/cmd_ref/ip_multicast.yaml +22 -0
- 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 +24 -0
- data/lib/cisco_node_utils/cmd_ref/ntp_auth_key.yaml +10 -0
- data/lib/cisco_node_utils/cmd_ref/ntp_config.yaml +27 -0
- data/lib/cisco_node_utils/cmd_ref/ntp_server.yaml +34 -0
- data/lib/cisco_node_utils/cmd_ref/object_group.yaml +32 -0
- data/lib/cisco_node_utils/cmd_ref/ospf.yaml +91 -0
- data/lib/cisco_node_utils/cmd_ref/ospf_area.yaml +91 -0
- data/lib/cisco_node_utils/cmd_ref/ospf_area_vlink.yaml +88 -0
- data/lib/cisco_node_utils/cmd_ref/overlay_global.yaml +37 -0
- data/lib/cisco_node_utils/cmd_ref/pim.yaml +43 -0
- data/lib/cisco_node_utils/cmd_ref/portchannel_global.yaml +86 -0
- data/lib/cisco_node_utils/cmd_ref/radius_global.yaml +37 -0
- data/lib/cisco_node_utils/cmd_ref/radius_server.yaml +100 -0
- data/lib/cisco_node_utils/cmd_ref/radius_server_group.yaml +19 -0
- data/lib/cisco_node_utils/cmd_ref/route_map.yaml +601 -0
- data/lib/cisco_node_utils/cmd_ref/show_system.yaml +9 -0
- data/lib/cisco_node_utils/cmd_ref/show_version.yaml +84 -0
- data/lib/cisco_node_utils/cmd_ref/snmp_community.yaml +81 -0
- data/lib/cisco_node_utils/cmd_ref/snmp_group.yaml +9 -0
- data/lib/cisco_node_utils/cmd_ref/snmp_notification_receiver.yaml +74 -0
- data/lib/cisco_node_utils/cmd_ref/snmp_server.yaml +91 -0
- data/lib/cisco_node_utils/cmd_ref/snmp_user.yaml +57 -0
- data/lib/cisco_node_utils/cmd_ref/snmpnotification.yaml +23 -0
- data/lib/cisco_node_utils/cmd_ref/span_session.yaml +65 -0
- data/lib/cisco_node_utils/cmd_ref/stp_global.yaml +235 -0
- data/lib/cisco_node_utils/cmd_ref/syslog_facility.yaml +10 -0
- data/lib/cisco_node_utils/cmd_ref/syslog_server.yaml +34 -0
- data/lib/cisco_node_utils/cmd_ref/syslog_settings.yaml +45 -0
- data/lib/cisco_node_utils/cmd_ref/system.yaml +7 -0
- data/lib/cisco_node_utils/cmd_ref/tacacs_global.yaml +37 -0
- data/lib/cisco_node_utils/cmd_ref/tacacs_server.yaml +63 -0
- data/lib/cisco_node_utils/cmd_ref/tacacs_server_group.yaml +45 -0
- data/lib/cisco_node_utils/cmd_ref/tacacs_server_host.yaml +64 -0
- data/lib/cisco_node_utils/cmd_ref/upgrade.yaml +38 -0
- data/lib/cisco_node_utils/cmd_ref/vdc.yaml +52 -0
- data/lib/cisco_node_utils/cmd_ref/virtual_service.yaml +8 -0
- data/lib/cisco_node_utils/cmd_ref/vlan.yaml +106 -0
- data/lib/cisco_node_utils/cmd_ref/vpc.yaml +233 -0
- data/lib/cisco_node_utils/cmd_ref/vrf.yaml +86 -0
- data/lib/cisco_node_utils/cmd_ref/vrf_af.yaml +139 -0
- data/lib/cisco_node_utils/cmd_ref/vtp.yaml +32 -0
- data/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml +114 -0
- data/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml +71 -0
- data/lib/cisco_node_utils/cmd_ref/yang.yaml +7 -0
- data/lib/cisco_node_utils/cmd_ref/yum.yaml +68 -0
- data/lib/cisco_node_utils/command_reference.rb +724 -0
- data/lib/cisco_node_utils/configparser_lib.rb +195 -0
- data/lib/cisco_node_utils/constants.rb +40 -0
- data/lib/cisco_node_utils/dhcp_relay_global.rb +302 -0
- data/lib/cisco_node_utils/dns_domain.rb +93 -0
- data/lib/cisco_node_utils/domain_name.rb +82 -0
- data/lib/cisco_node_utils/encapsulation.rb +112 -0
- data/lib/cisco_node_utils/environment.rb +110 -0
- data/lib/cisco_node_utils/evpn_multicast.rb +66 -0
- data/lib/cisco_node_utils/evpn_multisite.rb +96 -0
- data/lib/cisco_node_utils/evpn_stormcontrol.rb +84 -0
- data/lib/cisco_node_utils/evpn_vni.rb +159 -0
- data/lib/cisco_node_utils/exceptions.rb +140 -0
- data/lib/cisco_node_utils/fabricpath_global.rb +405 -0
- data/lib/cisco_node_utils/fabricpath_topology.rb +137 -0
- data/lib/cisco_node_utils/feature.rb +377 -0
- data/lib/cisco_node_utils/hostname.rb +62 -0
- data/lib/cisco_node_utils/hsrp_global.rb +97 -0
- data/lib/cisco_node_utils/interface.rb +2128 -0
- data/lib/cisco_node_utils/interface_channel_group.rb +142 -0
- data/lib/cisco_node_utils/interface_evpn_multisite.rb +72 -0
- data/lib/cisco_node_utils/interface_hsrp_group.rb +557 -0
- data/lib/cisco_node_utils/interface_ospf.rb +378 -0
- data/lib/cisco_node_utils/interface_portchannel.rb +180 -0
- data/lib/cisco_node_utils/interface_service_vni.rb +132 -0
- data/lib/cisco_node_utils/ip_multicast.rb +90 -0
- data/lib/cisco_node_utils/itd_device_group.rb +228 -0
- data/lib/cisco_node_utils/itd_device_group_node.rb +144 -0
- data/lib/cisco_node_utils/itd_service.rb +511 -0
- data/lib/cisco_node_utils/logger.rb +78 -0
- data/lib/cisco_node_utils/name_server.rb +64 -0
- data/lib/cisco_node_utils/node.rb +443 -0
- data/lib/cisco_node_utils/node_util.rb +111 -0
- data/lib/cisco_node_utils/ntp_auth_key.rb +67 -0
- data/lib/cisco_node_utils/ntp_config.rb +83 -0
- data/lib/cisco_node_utils/ntp_server.rb +86 -0
- data/lib/cisco_node_utils/object_group.rb +75 -0
- data/lib/cisco_node_utils/object_group_entry.rb +143 -0
- data/lib/cisco_node_utils/overlay_global.rb +142 -0
- data/lib/cisco_node_utils/pim.rb +131 -0
- data/lib/cisco_node_utils/pim_group_list.rb +109 -0
- data/lib/cisco_node_utils/pim_rp_address.rb +103 -0
- data/lib/cisco_node_utils/platform.rb +217 -0
- data/lib/cisco_node_utils/portchannel_global.rb +347 -0
- data/lib/cisco_node_utils/radius_global.rb +165 -0
- data/lib/cisco_node_utils/radius_server.rb +421 -0
- data/lib/cisco_node_utils/radius_server_group.rb +117 -0
- data/lib/cisco_node_utils/route_map.rb +2540 -0
- data/lib/cisco_node_utils/router_ospf.rb +77 -0
- data/lib/cisco_node_utils/router_ospf_area.rb +416 -0
- data/lib/cisco_node_utils/router_ospf_area_vlink.rb +313 -0
- data/lib/cisco_node_utils/router_ospf_vrf.rb +342 -0
- data/lib/cisco_node_utils/snmp_notification_receiver.rb +176 -0
- data/lib/cisco_node_utils/snmpcommunity.rb +109 -0
- data/lib/cisco_node_utils/snmpgroup.rb +54 -0
- data/lib/cisco_node_utils/snmpnotification.rb +57 -0
- data/lib/cisco_node_utils/snmpserver.rb +132 -0
- data/lib/cisco_node_utils/snmpuser.rb +403 -0
- data/lib/cisco_node_utils/span_session.rb +149 -0
- data/lib/cisco_node_utils/stp_global.rb +676 -0
- data/lib/cisco_node_utils/syslog_facility.rb +64 -0
- data/lib/cisco_node_utils/syslog_server.rb +146 -0
- data/lib/cisco_node_utils/syslog_settings.rb +174 -0
- data/lib/cisco_node_utils/tacacs_global.rb +137 -0
- data/lib/cisco_node_utils/tacacs_server.rb +173 -0
- data/lib/cisco_node_utils/tacacs_server_group.rb +149 -0
- data/lib/cisco_node_utils/tacacs_server_host.rb +216 -0
- data/lib/cisco_node_utils/upgrade.rb +122 -0
- data/lib/cisco_node_utils/vdc.rb +118 -0
- data/lib/cisco_node_utils/version.rb +21 -0
- data/lib/cisco_node_utils/vlan.rb +301 -0
- data/lib/cisco_node_utils/vpc.rb +466 -0
- data/lib/cisco_node_utils/vrf.rb +192 -0
- data/lib/cisco_node_utils/vrf_af.rb +327 -0
- data/lib/cisco_node_utils/vtp.rb +125 -0
- data/lib/cisco_node_utils/vxlan_vtep.rb +286 -0
- data/lib/cisco_node_utils/vxlan_vtep_vni.rb +331 -0
- data/lib/cisco_node_utils/yang.rb +160 -0
- data/lib/cisco_node_utils/yum.rb +213 -0
- data/lib/cisco_node_utils.rb +21 -0
- 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 +384 -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 +82 -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 +18 -0
- data/tests/CSCuxdublin-1.0.0-7.0.3.I3.1.lib32_n9000.rpm +0 -0
- data/tests/basetest.rb +243 -0
- data/tests/ciscotest.rb +577 -0
- data/tests/cmd_config.yaml +75 -0
- data/tests/cmd_config_invalid.yaml +16 -0
- data/tests/n9000_sample-1.0.0-7.0.3.x86_64.rpm +0 -0
- data/tests/noop.rb +7 -0
- data/tests/platform_info.rb +63 -0
- data/tests/tacacs_server.yaml.example +6 -0
- data/tests/test_aaa_authentication_login.rb +243 -0
- data/tests/test_aaa_authentication_login_service.rb +761 -0
- data/tests/test_aaa_authorization_service.rb +874 -0
- data/tests/test_ace.rb +304 -0
- data/tests/test_acl.rb +185 -0
- data/tests/test_banner.rb +85 -0
- data/tests/test_bfd_global.rb +272 -0
- data/tests/test_bgp_af.rb +875 -0
- data/tests/test_bgp_af_aa.rb +108 -0
- data/tests/test_bgp_neighbor.rb +596 -0
- data/tests/test_bgp_neighbor_af.rb +781 -0
- data/tests/test_bridge_domain.rb +198 -0
- data/tests/test_bridge_domain_vni.rb +109 -0
- data/tests/test_client_utils.rb +111 -0
- data/tests/test_cmn_utils.rb +76 -0
- data/tests/test_command_config.rb +206 -0
- data/tests/test_command_reference.rb +669 -0
- data/tests/test_dhcp_relay_global.rb +286 -0
- data/tests/test_dns_domain.rb +123 -0
- data/tests/test_domain_name.rb +96 -0
- data/tests/test_encapsulation.rb +75 -0
- data/tests/test_evpn_multicast.rb +65 -0
- data/tests/test_evpn_multisite.rb +70 -0
- data/tests/test_evpn_stormcontrol.rb +56 -0
- data/tests/test_evpn_vni.rb +131 -0
- data/tests/test_fabricpath_global.rb +246 -0
- data/tests/test_fabricpath_topology.rb +77 -0
- data/tests/test_feature.rb +272 -0
- data/tests/test_grpc.rb +166 -0
- data/tests/test_hostname.rb +64 -0
- data/tests/test_hsrp_global.rb +79 -0
- data/tests/test_interface.rb +1958 -0
- data/tests/test_interface_bdi.rb +80 -0
- data/tests/test_interface_channel_group.rb +131 -0
- data/tests/test_interface_evpn_multisite.rb +94 -0
- data/tests/test_interface_hsrp.rb +134 -0
- data/tests/test_interface_hsrp_group.rb +570 -0
- data/tests/test_interface_ospf.rb +820 -0
- data/tests/test_interface_portchannel.rb +135 -0
- data/tests/test_interface_private_vlan.rb +365 -0
- data/tests/test_interface_service_vni.rb +203 -0
- data/tests/test_interface_svi.rb +210 -0
- data/tests/test_interface_switchport.rb +468 -0
- data/tests/test_ip_multicast.rb +80 -0
- 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 +314 -0
- data/tests/test_logger.rb +43 -0
- data/tests/test_name_server.rb +94 -0
- data/tests/test_node.rb +50 -0
- data/tests/test_node_ext.rb +406 -0
- data/tests/test_node_util.rb +119 -0
- data/tests/test_ntp_auth_key.rb +77 -0
- data/tests/test_ntp_config.rb +100 -0
- data/tests/test_ntp_server.rb +146 -0
- data/tests/test_nxapi.rb +236 -0
- data/tests/test_object_group.rb +122 -0
- data/tests/test_overlay_global.rb +108 -0
- data/tests/test_pim.rb +203 -0
- data/tests/test_pim_group_list.rb +147 -0
- data/tests/test_pim_rp_address.rb +155 -0
- data/tests/test_platform.rb +254 -0
- data/tests/test_portchannel_global.rb +322 -0
- data/tests/test_radius_global.rb +108 -0
- data/tests/test_radius_server.rb +377 -0
- data/tests/test_radius_server_group.rb +151 -0
- data/tests/test_route_map.rb +1479 -0
- data/tests/test_router_bgp.rb +1325 -0
- data/tests/test_router_ospf.rb +56 -0
- data/tests/test_router_ospf_area.rb +433 -0
- data/tests/test_router_ospf_area_vlink.rb +298 -0
- data/tests/test_router_ospf_vrf.rb +690 -0
- data/tests/test_snmp_notification_receiver.rb +169 -0
- data/tests/test_snmpcommunity.rb +422 -0
- data/tests/test_snmpgroup.rb +71 -0
- data/tests/test_snmpnotification.rb +91 -0
- data/tests/test_snmpserver.rb +251 -0
- data/tests/test_snmpuser.rb +666 -0
- data/tests/test_span_session.rb +155 -0
- data/tests/test_stp_global.rb +575 -0
- data/tests/test_syslog_facility.rb +80 -0
- data/tests/test_syslog_server.rb +119 -0
- data/tests/test_syslog_settings.rb +123 -0
- data/tests/test_tacacs_global.rb +109 -0
- data/tests/test_tacacs_server.rb +436 -0
- data/tests/test_tacacs_server_group.rb +434 -0
- data/tests/test_tacacs_server_host.rb +427 -0
- data/tests/test_upgrade.rb +105 -0
- data/tests/test_vdc.rb +64 -0
- data/tests/test_vlan.rb +386 -0
- data/tests/test_vlan_private.rb +656 -0
- data/tests/test_vpc.rb +548 -0
- data/tests/test_vrf.rb +248 -0
- data/tests/test_vrf_af.rb +288 -0
- data/tests/test_vtp.rb +278 -0
- data/tests/test_vxlan_vtep.rb +327 -0
- data/tests/test_vxlan_vtep_vni.rb +326 -0
- data/tests/test_yang.rb +369 -0
- data/tests/test_yum.rb +109 -0
- data/tests/upgrade_info.yaml.example +3 -0
- data/tests/yum_package.yaml +94 -0
- metadata +534 -0
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
# Common Utilities for Puppet Resources.
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2014-2016 Cisco and/or its affiliates.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
# Add some general-purpose constants and APIs to the Cisco namespace
|
|
18
|
+
module Cisco
|
|
19
|
+
# global constants
|
|
20
|
+
DEFAULT_INSTANCE_NAME = 'default'
|
|
21
|
+
|
|
22
|
+
# Encryption - helper class for translating encryption type CLI
|
|
23
|
+
class Encryption
|
|
24
|
+
# password encryption types
|
|
25
|
+
def self.cli_to_symbol(cli)
|
|
26
|
+
case cli
|
|
27
|
+
when '0', 0, 'clear'
|
|
28
|
+
:cleartext
|
|
29
|
+
when '3', 3
|
|
30
|
+
:"3des" # yuck :-(
|
|
31
|
+
when '5', 5, 'encrypted'
|
|
32
|
+
:md5
|
|
33
|
+
when '6', 6
|
|
34
|
+
:aes
|
|
35
|
+
when '7', 7
|
|
36
|
+
:cisco_type_7
|
|
37
|
+
else
|
|
38
|
+
fail KeyError
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.symbol_to_cli(symbol)
|
|
43
|
+
symbol = symbol.downcase if symbol.is_a? String
|
|
44
|
+
case symbol
|
|
45
|
+
when :cleartext, :none, 'cleartext', 'none', '0', 0
|
|
46
|
+
'0'
|
|
47
|
+
when :"3des", '3des', '3', 3
|
|
48
|
+
'3'
|
|
49
|
+
when :md5, 'md5', '5', 5
|
|
50
|
+
'5'
|
|
51
|
+
when :aes, 'aes', '6', 6
|
|
52
|
+
'6'
|
|
53
|
+
when :cisco_type_7, :type_7, 'cisco_type_7', 'type_7', '7', 7
|
|
54
|
+
'7'
|
|
55
|
+
else
|
|
56
|
+
fail KeyError
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# ChefUtils - helper class for Chef code generation
|
|
62
|
+
class ChefUtils
|
|
63
|
+
def self.generic_prop_set(klass, rlbname, props)
|
|
64
|
+
props.each do |prop|
|
|
65
|
+
klass.instance_eval do
|
|
66
|
+
# Helper Chef setter method, e.g.:
|
|
67
|
+
# if @new_resource.foo.nil?
|
|
68
|
+
# def_prop = @rlb.default_foo
|
|
69
|
+
# @new_resource.foo(def_prop)
|
|
70
|
+
# end
|
|
71
|
+
# current = @rlb.foo
|
|
72
|
+
# if current != @new_resource.foo
|
|
73
|
+
# converge_by("update foo '#{current}' => " +
|
|
74
|
+
# "'#{@new_resource.foo}'") do
|
|
75
|
+
# @rlb.foo=(@new_resource.foo)
|
|
76
|
+
# end
|
|
77
|
+
# end
|
|
78
|
+
if @new_resource.send(prop).nil?
|
|
79
|
+
def_prop = instance_variable_get(rlbname).send("default_#{prop}")
|
|
80
|
+
# Set resource to default if recipe property is not specified
|
|
81
|
+
@new_resource.send(prop, def_prop)
|
|
82
|
+
end
|
|
83
|
+
current = instance_variable_get(rlbname).send(prop)
|
|
84
|
+
if current != @new_resource.send(prop)
|
|
85
|
+
converge_by("update #{prop} '#{current}' => " \
|
|
86
|
+
"'#{@new_resource.send(prop)}'") do
|
|
87
|
+
instance_variable_get(rlbname).send("#{prop}=",
|
|
88
|
+
@new_resource.send(prop))
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end # class ChefUtils
|
|
95
|
+
|
|
96
|
+
# General utility class
|
|
97
|
+
class Utils
|
|
98
|
+
require 'ipaddr'
|
|
99
|
+
|
|
100
|
+
# Helper utility to check for older Nexus I2 images
|
|
101
|
+
def self.nexus_i2_image
|
|
102
|
+
require_relative 'platform'
|
|
103
|
+
true if Platform.image_version[/7.0.3.I2/]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def self.image_version?(ver_regexp)
|
|
107
|
+
require_relative 'platform'
|
|
108
|
+
return true if Platform.image_version[ver_regexp]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def self.chassis_pid?(ver_regexp)
|
|
112
|
+
require_relative 'platform'
|
|
113
|
+
return true if Platform.chassis['pid'][ver_regexp]
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def self.fretta?
|
|
117
|
+
require_relative 'platform'
|
|
118
|
+
Platform.slots.each do |_x, row|
|
|
119
|
+
return true if row['pid'][/-R/]
|
|
120
|
+
end
|
|
121
|
+
false
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Helper utility method for ip/prefix format networks.
|
|
125
|
+
# For ip/prefix format '1.1.1.1/24' or '2000:123:38::34/64',
|
|
126
|
+
# we need to mask the address using the prefix length so that they
|
|
127
|
+
# are converted to '1.1.1.0/24' or '2000:123:38::/64'
|
|
128
|
+
def self.process_network_mask(network)
|
|
129
|
+
mask = network.split('/')[1]
|
|
130
|
+
address = IPAddr.new(network).to_s
|
|
131
|
+
network = address + '/' + mask unless mask.nil?
|
|
132
|
+
network
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Helper to build a hash of add/remove commands for a nested array.
|
|
136
|
+
# Useful for network, redistribute, etc.
|
|
137
|
+
# should: an array of expected cmds (manifest/recipe)
|
|
138
|
+
# current: an array of existing cmds on the device
|
|
139
|
+
def self.depth(a)
|
|
140
|
+
return 0 unless a.is_a?(Array)
|
|
141
|
+
1 + depth(a[0])
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def self.delta_add_remove(should, current=[], opt=nil)
|
|
145
|
+
current = [] if current.nil?
|
|
146
|
+
should = [] if should.nil?
|
|
147
|
+
|
|
148
|
+
# Remove nil entries from array
|
|
149
|
+
should.each(&:compact!) if depth(should) > 1
|
|
150
|
+
delta = { add: should - current, remove: current - should }
|
|
151
|
+
|
|
152
|
+
# Some cli properties cannot be updated, thus must be removed first
|
|
153
|
+
return delta if opt == :updates_not_allowed
|
|
154
|
+
|
|
155
|
+
# Delete entries from :remove if f1 is an update to an existing command
|
|
156
|
+
delta[:add].each do |id, _|
|
|
157
|
+
# Differentiate between comparing nested and unnested arrays by
|
|
158
|
+
# checking the depth of the array.
|
|
159
|
+
if depth(should) == 1
|
|
160
|
+
delta[:remove].delete_if { |f1| [f1] if f1.to_s == id.to_s }
|
|
161
|
+
else
|
|
162
|
+
delta[:remove].delete_if { |f1, f2| [f1, f2] if f1.to_s == id.to_s }
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
delta
|
|
166
|
+
end # delta_add_remove
|
|
167
|
+
|
|
168
|
+
def self.length_to_bitmask(length)
|
|
169
|
+
IPAddr.new('255.255.255.255').mask(length).to_s
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def self.bitmask_to_length(bitmask)
|
|
173
|
+
# Convert bitmask to a 32-bit integer,
|
|
174
|
+
# convert that to binary, and count the 1s
|
|
175
|
+
IPAddr.new(bitmask).to_i.to_s(2).count('1')
|
|
176
|
+
rescue IPAddr::InvalidAddressError => e
|
|
177
|
+
raise ArgumentError, "bitmask '#{bitmask}' is not valid: #{e}"
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Helper to 0-pad a mac address.
|
|
181
|
+
def self.zero_pad_macaddr(mac)
|
|
182
|
+
return nil if mac.nil? || mac.empty?
|
|
183
|
+
o1, o2, o3 = mac.split('.').map { |o| o.to_i(16).to_s(10) }
|
|
184
|
+
sprintf('%04x.%04x.%04x', o1, o2, o3)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# For spanning tree range based parameters, the range
|
|
188
|
+
# is very dynamic and so before the parameters are set,
|
|
189
|
+
# the rest of the range needs to be reset
|
|
190
|
+
# For ex: if the ranges 2-42 and 83-200 are getting set,
|
|
191
|
+
# and the total range of the given parameter is 1-4000
|
|
192
|
+
# then 1,43-82,201-4000 needs to be reset. This method
|
|
193
|
+
# takes the set ranges and gives back the range to be reset
|
|
194
|
+
def self.get_reset_range(total_range, remove_ranges)
|
|
195
|
+
fail 'invalid range' unless total_range.include?('-')
|
|
196
|
+
return total_range if remove_ranges.empty?
|
|
197
|
+
|
|
198
|
+
trs = total_range.gsub('-', '..')
|
|
199
|
+
tra = trs.split('..').map { |d| Integer(d) }
|
|
200
|
+
tr = tra[0]..tra[1]
|
|
201
|
+
tarray = tr.to_a
|
|
202
|
+
remove_ranges.each do |rr, _val|
|
|
203
|
+
rarray = rr.gsub('-', '..').split(',')
|
|
204
|
+
rarray.each do |elem|
|
|
205
|
+
if elem.include?('..')
|
|
206
|
+
elema = elem.split('..').map { |d| Integer(d) }
|
|
207
|
+
ele = elema[0]..elema[1]
|
|
208
|
+
tarray -= ele.to_a
|
|
209
|
+
else
|
|
210
|
+
tarray.delete(elem.to_i)
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
Utils.array_to_str(tarray)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# This method converts an array to string form
|
|
218
|
+
# for ex: if the array has 1, 2 to 10, 83 to 2014, 3022
|
|
219
|
+
# and the string will be "1,2-10,83-2014,3022"
|
|
220
|
+
def self.array_to_str(array, sort=true)
|
|
221
|
+
farray = sort ? array.compact.uniq.sort : array.compact
|
|
222
|
+
lranges = []
|
|
223
|
+
unless farray.empty?
|
|
224
|
+
l = array.first
|
|
225
|
+
r = nil
|
|
226
|
+
farray.each do |aelem|
|
|
227
|
+
if r && aelem != r.succ
|
|
228
|
+
if l == r
|
|
229
|
+
lranges << l
|
|
230
|
+
else
|
|
231
|
+
lranges << Range.new(l, r)
|
|
232
|
+
end
|
|
233
|
+
l = aelem
|
|
234
|
+
end
|
|
235
|
+
r = aelem
|
|
236
|
+
end
|
|
237
|
+
if l == r
|
|
238
|
+
lranges << l
|
|
239
|
+
else
|
|
240
|
+
lranges << Range.new(l, r)
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
lranges.to_s.gsub('..', '-').delete('[').delete(']').delete(' ')
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# normalize_range_array
|
|
247
|
+
#
|
|
248
|
+
# Given a list of ranges, merge any overlapping ranges and sort them.
|
|
249
|
+
#
|
|
250
|
+
# Note: The ranges are converted to ruby ranges for easy merging,
|
|
251
|
+
# then converted back to a cli-syntax range.
|
|
252
|
+
#
|
|
253
|
+
# Accepts an array or string:
|
|
254
|
+
# ["2-5", "9", "4-6"] -or- '2-5, 9, 4-6' -or- ["2-5, 9, 4-6"]
|
|
255
|
+
# Returns a merged and ordered range as an array or string:
|
|
256
|
+
# ["2-6", "9"] -or- '2-6,9'
|
|
257
|
+
#
|
|
258
|
+
def self.normalize_range_array(range, fmt=:array)
|
|
259
|
+
return range if range.nil? || range.empty?
|
|
260
|
+
range = range.clone
|
|
261
|
+
|
|
262
|
+
# Handle string within an array: ["2-5, 9, 4-6"] to '2-5, 9, 4-6'
|
|
263
|
+
range = range.shift if range.is_a?(Array) && range.length == 1
|
|
264
|
+
|
|
265
|
+
# Handle string only: '2-5, 9, 4-6' to ["2-5", "9", "4-6"]
|
|
266
|
+
range = range.split(',') if range.is_a?(String)
|
|
267
|
+
|
|
268
|
+
# Convert to ruby-syntax ranges
|
|
269
|
+
range = dash_range_to_ruby_range(range)
|
|
270
|
+
|
|
271
|
+
# Sort & Merge
|
|
272
|
+
merged = merge_range(range)
|
|
273
|
+
|
|
274
|
+
# Convert back to cli dash-syntax
|
|
275
|
+
merged_array = ruby_range_to_dash_range(merged)
|
|
276
|
+
|
|
277
|
+
return merged_array.join(',') if fmt == :string
|
|
278
|
+
merged_array
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# Convert a cli-dash-syntax range to ruby-range. This is useful for
|
|
282
|
+
# preparing inputs to merge_range().
|
|
283
|
+
#
|
|
284
|
+
# Inputs an array or string of dash-syntax ranges -> returns an array
|
|
285
|
+
# of ruby ranges.
|
|
286
|
+
#
|
|
287
|
+
# Accepts an array or string: ["2-5", "9", "4-6"] or '2-5, 9, 4-6'
|
|
288
|
+
# Returns an array of ranges: [2..5, 9..9, 4..6]
|
|
289
|
+
#
|
|
290
|
+
def self.dash_range_to_ruby_range(range)
|
|
291
|
+
range = range.split(',') if range.is_a?(String)
|
|
292
|
+
range.map! do |rng|
|
|
293
|
+
if rng[/-/]
|
|
294
|
+
# '2-5' -> 2..5
|
|
295
|
+
rng.split('-').inject { |a, e| a.to_i..e.to_i }
|
|
296
|
+
else
|
|
297
|
+
# '9' -> 9..9
|
|
298
|
+
rng.to_i..rng.to_i
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
range
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# Convert a ruby-range to cli-dash-syntax.
|
|
305
|
+
#
|
|
306
|
+
# Inputs an array of ruby ranges -> returns an array or string of
|
|
307
|
+
# dash-syntax ranges.
|
|
308
|
+
#
|
|
309
|
+
# when (:array) [2..6, 9..9] -> ['2-6', '9']
|
|
310
|
+
#
|
|
311
|
+
# when (:string) [2..6, 9..9] -> '2-6, 9'
|
|
312
|
+
#
|
|
313
|
+
def self.ruby_range_to_dash_range(range, type=:array)
|
|
314
|
+
fail unless range.is_a?(Array)
|
|
315
|
+
range.map! do |r|
|
|
316
|
+
if r.first == r.last
|
|
317
|
+
# 9..9 -> '9'
|
|
318
|
+
r.first.to_s
|
|
319
|
+
else
|
|
320
|
+
# 2..6 -> '2-6'
|
|
321
|
+
r.first.to_s + '-' + r.last.to_s
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
return range.join(', ') if type == :string
|
|
325
|
+
range
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
# Convert a dash-range set into individual elements.
|
|
329
|
+
# This is useful for preparing inputs to delta_add_remove().
|
|
330
|
+
#
|
|
331
|
+
# Inputs an array or string of dash-ranges:
|
|
332
|
+
# ["2-5", "9", "4-6"] or '2-5, 9, 4-6' or ['2-5, 9, 4-6']
|
|
333
|
+
# Returns an array of range elements:
|
|
334
|
+
# ["2", "3", "4", "5", "6", "9"]
|
|
335
|
+
#
|
|
336
|
+
def self.dash_range_to_elements(range)
|
|
337
|
+
return [] if range.nil?
|
|
338
|
+
range = range.shift if range.is_a?(Array) && range.length == 1
|
|
339
|
+
range = range.split(',') if range.is_a?(String)
|
|
340
|
+
|
|
341
|
+
final = []
|
|
342
|
+
range = dash_range_to_ruby_range(range)
|
|
343
|
+
range.each do |rng|
|
|
344
|
+
# 2..5 maps to ["2", "3", "4", "5"]
|
|
345
|
+
final << rng.map(&:to_s)
|
|
346
|
+
end
|
|
347
|
+
final.flatten.uniq.sort
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
# Merge overlapping ranges.
|
|
351
|
+
#
|
|
352
|
+
# Inputs an array of ruby ranges: [2..5, 9..9, 4..6]
|
|
353
|
+
# Returns an array of merged ruby ranges: [2..6, 9..9]
|
|
354
|
+
#
|
|
355
|
+
def self.merge_range(range)
|
|
356
|
+
# sort to lowest range 'first' values:
|
|
357
|
+
# [2..5, 9..9, 4..6] -> [2..5, 4..6, 9..9]
|
|
358
|
+
range = range.sort_by(&:first)
|
|
359
|
+
|
|
360
|
+
*merged = range.shift
|
|
361
|
+
range.each do |r|
|
|
362
|
+
lastr = merged[-1]
|
|
363
|
+
if lastr.last >= r.first - 1
|
|
364
|
+
merged[-1] = lastr.first..[r.last, lastr.last].max
|
|
365
|
+
else
|
|
366
|
+
merged.push(r)
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
merged
|
|
370
|
+
end # merge_range
|
|
371
|
+
|
|
372
|
+
def self.add_quotes(value)
|
|
373
|
+
return value if image_version?(/7.3.[0-1]/) || value.nil?
|
|
374
|
+
value = "'#{value}'" unless
|
|
375
|
+
value.start_with?('"', "'") && value.end_with?('"', "'")
|
|
376
|
+
value
|
|
377
|
+
end # add_quotes
|
|
378
|
+
|
|
379
|
+
# This method is used in config_get for CLIs which
|
|
380
|
+
# have multiple properties in the same output
|
|
381
|
+
# Given a match_method which defines regex pattern and the
|
|
382
|
+
# match criteria, this method, extracts the value of
|
|
383
|
+
# a property with or without a prefix.
|
|
384
|
+
# For ex. if the regex pattern is something like:
|
|
385
|
+
# (?<action>\S+)?
|
|
386
|
+
# the property to extract is action and prefix is nil
|
|
387
|
+
# for (?<src_port>range \S+)
|
|
388
|
+
# the property to extract is src_port and prefix is range
|
|
389
|
+
def self.extract_value(match_method, prop, prefix=nil)
|
|
390
|
+
prefix = prop if prefix.nil?
|
|
391
|
+
mm = match_method
|
|
392
|
+
|
|
393
|
+
return nil if mm.nil?
|
|
394
|
+
|
|
395
|
+
return nil unless mm.names.include?(prop)
|
|
396
|
+
|
|
397
|
+
# extract and return value that follows prefix + <space>
|
|
398
|
+
regexp = Regexp.new("#{Regexp.escape(prefix)} (?<extracted>.*)")
|
|
399
|
+
value_match = regexp.match(mm[prop])
|
|
400
|
+
return nil if value_match.nil?
|
|
401
|
+
value_match[:extracted]
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
# This method is used in config_set for CLIs which
|
|
405
|
+
# can set multiple properties using the same CLI.
|
|
406
|
+
# This method attaches prefix to the given property
|
|
407
|
+
# when the prefix is different from the property name
|
|
408
|
+
# else it attaches property name itself. It also
|
|
409
|
+
# appends the value to be set.
|
|
410
|
+
# For ex. if the set_value is <precedence> <time_range>
|
|
411
|
+
# the prop for precedence could be 'precedence', and
|
|
412
|
+
# for time_range, the prop and prefix could be 'time_range'
|
|
413
|
+
# and 'time-range'
|
|
414
|
+
def self.attach_prefix(val, prop, prefix=nil)
|
|
415
|
+
prefix = prop.to_s if prefix.nil?
|
|
416
|
+
val.to_s.empty? ? val : "#{prefix} #{val}"
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
# Helper utility to normalize the interface name pattern to be filtered.
|
|
420
|
+
# This is only a problem on N7k which has to use a section filter
|
|
421
|
+
# due to a show run int bug (no 'all' keyword for some interfaces).
|
|
422
|
+
def self.normalize_intf_pattern(show_name)
|
|
423
|
+
return '' if show_name.nil? || show_name.empty?
|
|
424
|
+
require_relative 'platform'
|
|
425
|
+
return show_name unless Platform.hardware_type[/Nexus7/]
|
|
426
|
+
return show_name if show_name[-1] == '$' # already normalized
|
|
427
|
+
pat = show_name.downcase + '$'
|
|
428
|
+
case pat
|
|
429
|
+
when /ethernet/
|
|
430
|
+
pat.sub!(/ethernet/, 'Ethernet')
|
|
431
|
+
when /loopback/
|
|
432
|
+
pat.sub!(/loopback/, 'loopback')
|
|
433
|
+
when /port-channel/
|
|
434
|
+
pat.sub!(/port-channel/, 'port-channel')
|
|
435
|
+
when /vlan/
|
|
436
|
+
pat.sub!(/vlan/, 'Vlan')
|
|
437
|
+
else
|
|
438
|
+
# wildcard the first char of the name
|
|
439
|
+
pat.sub!(/./, '.')
|
|
440
|
+
end
|
|
441
|
+
pat
|
|
442
|
+
end
|
|
443
|
+
end # class Utils
|
|
444
|
+
end # module Cisco
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
#
|
|
3
|
+
# October 2015, Glenn F. Matthews
|
|
4
|
+
#
|
|
5
|
+
# Copyright (c) 2015-2016 Cisco and/or its affiliates.
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
|
|
19
|
+
require_relative '../environment'
|
|
20
|
+
require_relative '../exceptions'
|
|
21
|
+
require_relative 'utils'
|
|
22
|
+
require_relative '../constants'
|
|
23
|
+
require_relative '../logger'
|
|
24
|
+
|
|
25
|
+
include Cisco::Logger
|
|
26
|
+
|
|
27
|
+
# Base class for clients of various RPC formats
|
|
28
|
+
class Cisco::Client
|
|
29
|
+
@@clients = [] # rubocop:disable Style/ClassVars
|
|
30
|
+
|
|
31
|
+
def self.clients
|
|
32
|
+
@@clients
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Each subclass should call this method to register itself.
|
|
36
|
+
def self.register_client(client)
|
|
37
|
+
@@clients << client
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
attr_reader :data_formats, :platform
|
|
41
|
+
|
|
42
|
+
def initialize(data_formats: [],
|
|
43
|
+
platform: nil,
|
|
44
|
+
**kwargs)
|
|
45
|
+
if self.class == Cisco::Client
|
|
46
|
+
fail NotImplementedError, 'Cisco::Client is an abstract class. ' \
|
|
47
|
+
"Instantiate one of #{@@clients} or use Cisco::Client.create() instead"
|
|
48
|
+
end
|
|
49
|
+
self.class.validate_args(**kwargs)
|
|
50
|
+
@host = kwargs[:host]
|
|
51
|
+
@port = kwargs[:port]
|
|
52
|
+
@address = @port.nil? ? @host : "#{@host}:#{@port}"
|
|
53
|
+
@username = kwargs[:username]
|
|
54
|
+
@password = kwargs[:password]
|
|
55
|
+
self.data_formats = data_formats
|
|
56
|
+
self.platform = platform
|
|
57
|
+
@cache_enable = true
|
|
58
|
+
@cache_auto = true
|
|
59
|
+
cache_flush
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def self.validate_args(**kwargs)
|
|
63
|
+
host = kwargs[:host]
|
|
64
|
+
unless host.nil?
|
|
65
|
+
fail TypeError, 'invalid address' unless host.is_a?(String)
|
|
66
|
+
fail ArgumentError, 'empty address' if host.empty?
|
|
67
|
+
end
|
|
68
|
+
username = kwargs[:username]
|
|
69
|
+
unless username.nil?
|
|
70
|
+
fail TypeError, 'invalid username' unless username.is_a?(String)
|
|
71
|
+
fail ArgumentError, 'empty username' if username.empty?
|
|
72
|
+
end
|
|
73
|
+
password = kwargs[:password]
|
|
74
|
+
unless password.nil?
|
|
75
|
+
fail TypeError, 'invalid password' unless password.is_a?(String)
|
|
76
|
+
fail ArgumentError, 'empty password' if password.empty?
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def supports?(data_format)
|
|
81
|
+
data_formats.include?(data_format)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Try to create an instance of an appropriate subclass
|
|
85
|
+
def self.create(environment_name=nil)
|
|
86
|
+
fail 'No client implementations available!' if clients.empty?
|
|
87
|
+
debug "Trying to establish client connection. clients = #{clients}"
|
|
88
|
+
environment = Cisco::Environment.environment(environment_name)
|
|
89
|
+
host = environment[:host]
|
|
90
|
+
errors = []
|
|
91
|
+
clients.each do |client_class|
|
|
92
|
+
begin
|
|
93
|
+
debug "Trying to connect to #{host} as #{client_class}"
|
|
94
|
+
client = client_class.new(**environment)
|
|
95
|
+
debug "#{client_class} connected successfully"
|
|
96
|
+
return client
|
|
97
|
+
rescue Cisco::ClientError, TypeError, ArgumentError => e
|
|
98
|
+
debug "Unable to connect to #{host} as #{client_class}: #{e.message}"
|
|
99
|
+
debug e.backtrace.join("\n ")
|
|
100
|
+
errors << e
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
handle_errors(errors)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def self.handle_errors(errors)
|
|
107
|
+
# ClientError means we tried to connect but failed,
|
|
108
|
+
# so it's 'more significant' than input validation errors.
|
|
109
|
+
client_errors = errors.select { |e| e.kind_of? Cisco::ClientError }
|
|
110
|
+
if !client_errors.empty?
|
|
111
|
+
# Reraise the specific error if just one
|
|
112
|
+
fail client_errors[0] if client_errors.length == 1
|
|
113
|
+
# Otherwise clump them together into a new error
|
|
114
|
+
e_cls = client_errors[0].class
|
|
115
|
+
unless client_errors.all? { |e| e.class == e_cls }
|
|
116
|
+
e_cls = Cisco::ClientError
|
|
117
|
+
end
|
|
118
|
+
fail e_cls, ("Unable to establish any client connection:\n" +
|
|
119
|
+
errors.each(&:message).join("\n"))
|
|
120
|
+
elsif errors.any? { |e| e.kind_of? ArgumentError }
|
|
121
|
+
fail ArgumentError, ("Invalid arguments:\n" +
|
|
122
|
+
errors.each(&:message).join("\n"))
|
|
123
|
+
elsif errors.any? { |e| e.kind_of? TypeError }
|
|
124
|
+
fail TypeError, ("Invalid arguments:\n" +
|
|
125
|
+
errors.each(&:message).join("\n"))
|
|
126
|
+
end
|
|
127
|
+
fail Cisco::ClientError, 'No client connected, but no errors were reported?'
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def to_s
|
|
131
|
+
@address.to_s
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def inspect
|
|
135
|
+
"<#{self.class} of #{@address}>"
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def cache_enable?
|
|
139
|
+
@cache_enable
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def cache_enable=(enable)
|
|
143
|
+
@cache_enable = enable
|
|
144
|
+
cache_flush unless enable
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def cache_auto?
|
|
148
|
+
@cache_auto
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
attr_writer :cache_auto
|
|
152
|
+
|
|
153
|
+
# Clear the cache of CLI output results.
|
|
154
|
+
#
|
|
155
|
+
# If cache_auto is true (default) then this will be performed automatically
|
|
156
|
+
# whenever a set() is called, but providers may also call this
|
|
157
|
+
# to explicitly force the cache to be cleared.
|
|
158
|
+
def cache_flush
|
|
159
|
+
# to be implemented by subclasses
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Configure the given state on the device.
|
|
163
|
+
#
|
|
164
|
+
# @raise [RequestNotSupported] if this client doesn't support the given
|
|
165
|
+
# data_format
|
|
166
|
+
#
|
|
167
|
+
# @param data_format one of Cisco::DATA_FORMATS. Default is :cli
|
|
168
|
+
# @param context [String, Array<String>] Context for the configuration
|
|
169
|
+
# @param values [String, Array<String>] Actual configuration to set
|
|
170
|
+
# @param kwargs data-format-specific args
|
|
171
|
+
def set(data_format: :cli,
|
|
172
|
+
context: nil,
|
|
173
|
+
values: nil,
|
|
174
|
+
**_kwargs)
|
|
175
|
+
# subclasses will generally want to call Client.munge_to_array()
|
|
176
|
+
# on context and/or values before calling super()
|
|
177
|
+
fail Cisco::RequestNotSupported unless self.supports?(data_format)
|
|
178
|
+
cache_flush if cache_auto?
|
|
179
|
+
Cisco::Logger.debug("Set state using data format '#{data_format}'")
|
|
180
|
+
Cisco::Logger.debug(" with context:\n #{context.join("\n ")}") \
|
|
181
|
+
unless context.nil? || context.empty?
|
|
182
|
+
Cisco::Logger.debug(" to value(s):\n #{values.join("\n ")}") \
|
|
183
|
+
unless values.nil? || values.empty?
|
|
184
|
+
# to be implemented by subclasses
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Get the given state from the device.
|
|
188
|
+
#
|
|
189
|
+
# Unlike set() this will not clear the CLI cache;
|
|
190
|
+
# multiple calls with the same parameters may return cached data
|
|
191
|
+
# rather than querying the device repeatedly.
|
|
192
|
+
#
|
|
193
|
+
# @raise [RequestNotSupported] if the client doesn't support the data_format
|
|
194
|
+
# @raise [RequestFailed] if the command is rejected by the device
|
|
195
|
+
#
|
|
196
|
+
# @param data_format one of Cisco::DATA_FORMATS. Default is :cli
|
|
197
|
+
# @param command [String] the get command to execute
|
|
198
|
+
# @param context [String, Array<String>] Context to refine/filter the results
|
|
199
|
+
# @param value [String, Regexp] Specific key or regexp to look up
|
|
200
|
+
# @param kwargs data-format-specific args
|
|
201
|
+
# @return [String, Hash, nil] The state found, or nil if not found.
|
|
202
|
+
def get(data_format: :cli,
|
|
203
|
+
command: nil,
|
|
204
|
+
context: nil,
|
|
205
|
+
value: nil,
|
|
206
|
+
**_kwargs)
|
|
207
|
+
# subclasses will generally want to call Client.munge_to_array()
|
|
208
|
+
# on context and/or value before calling super()
|
|
209
|
+
fail Cisco::RequestNotSupported unless self.supports?(data_format)
|
|
210
|
+
Cisco::Logger.debug("Get state using data format '#{data_format}'")
|
|
211
|
+
Cisco::Logger.debug(" executing command:\n #{command}") \
|
|
212
|
+
unless command.nil? || command.empty?
|
|
213
|
+
Cisco::Logger.debug(" with context:\n #{context.join("\n ")}") \
|
|
214
|
+
unless context.nil? || context.empty?
|
|
215
|
+
Cisco::Logger.debug(" to get value: #{value}") \
|
|
216
|
+
unless value.nil?
|
|
217
|
+
# to be implemented by subclasses
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
private
|
|
221
|
+
|
|
222
|
+
# Set the list of data formats supported by this client.
|
|
223
|
+
# If the client supports multiple formats, and a given feature or property
|
|
224
|
+
# can be managed by multiple formats, the list order indicates preference.
|
|
225
|
+
def data_formats=(data_formats)
|
|
226
|
+
data_formats = [data_formats] unless data_formats.is_a?(Array)
|
|
227
|
+
unknown = data_formats - Cisco::DATA_FORMATS
|
|
228
|
+
fail ArgumentError, "unknown data formats: #{unknown}" unless unknown.empty?
|
|
229
|
+
@data_formats = data_formats
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Set the platform of the node managed by this client.
|
|
233
|
+
def platform=(platform)
|
|
234
|
+
fail ArgumentError, "unknown platform #{platform}" \
|
|
235
|
+
unless Cisco::PLATFORMS.include?(platform)
|
|
236
|
+
@platform = platform
|
|
237
|
+
end
|
|
238
|
+
end
|