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.
Files changed (255) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +13 -0
  5. data/.travis.yml +4 -1
  6. data/CHANGELOG.md +81 -2
  7. data/CONTRIBUTING.md +2 -17
  8. data/Gemfile +5 -0
  9. data/README.md +92 -47
  10. data/Rakefile +23 -1
  11. data/bin/git/hooks/hook_lib +7 -0
  12. data/bin/git/hooks/pre-commit/check_unstaged_changes +18 -0
  13. data/bin/git/hooks/pre-commit/rubocop +7 -2
  14. data/bin/git/hooks/pre-commit/validate-diffs +18 -4
  15. data/bin/git/hooks/pre-commit/validate-yaml +18 -0
  16. data/bin/git/update-hooks +64 -6
  17. data/cisco_node_utils.gemspec +9 -6
  18. data/docs/README-develop-best-practices.md +149 -50
  19. data/docs/README-develop-node-utils-APIs.md +92 -42
  20. data/docs/README-maintainers.md +7 -4
  21. data/docs/README-test-execution.md +57 -0
  22. data/docs/cisco_node_utils.yaml.example +30 -0
  23. data/docs/template-router.rb +4 -0
  24. data/ext/mkrf_conf.rb +63 -0
  25. data/lib/.rubocop.yml +2 -2
  26. data/lib/cisco_node_utils.rb +5 -0
  27. data/lib/cisco_node_utils/aaa_authentication_login.rb +5 -6
  28. data/lib/cisco_node_utils/aaa_authorization_service.rb +1 -1
  29. data/lib/cisco_node_utils/ace.rb +165 -12
  30. data/lib/cisco_node_utils/acl.rb +2 -1
  31. data/lib/cisco_node_utils/bgp.rb +184 -21
  32. data/lib/cisco_node_utils/bgp_af.rb +94 -249
  33. data/lib/cisco_node_utils/bgp_neighbor.rb +94 -14
  34. data/lib/cisco_node_utils/bgp_neighbor_af.rb +75 -8
  35. data/lib/cisco_node_utils/bridge_domain.rb +183 -0
  36. data/lib/cisco_node_utils/bridge_domain_vni.rb +206 -0
  37. data/lib/cisco_node_utils/cisco_cmn_utils.rb +85 -2
  38. data/lib/cisco_node_utils/client.rb +35 -0
  39. data/lib/cisco_node_utils/client/client.rb +234 -0
  40. data/lib/cisco_node_utils/client/grpc.rb +33 -0
  41. data/lib/cisco_node_utils/client/grpc/client.rb +311 -0
  42. data/lib/cisco_node_utils/client/grpc/ems.proto +148 -0
  43. data/lib/cisco_node_utils/client/grpc/ems.rb +111 -0
  44. data/lib/cisco_node_utils/client/grpc/ems_services.rb +49 -0
  45. data/lib/cisco_node_utils/client/nxapi.rb +31 -0
  46. data/lib/cisco_node_utils/client/nxapi/client.rb +305 -0
  47. data/lib/cisco_node_utils/client/utils.rb +164 -0
  48. data/lib/cisco_node_utils/cmd_ref/README_YAML.md +222 -254
  49. data/lib/cisco_node_utils/cmd_ref/aaa_auth_login_service.yaml +11 -8
  50. data/lib/cisco_node_utils/cmd_ref/aaa_authentication_login.yaml +22 -15
  51. data/lib/cisco_node_utils/cmd_ref/aaa_authorization_service.yaml +11 -8
  52. data/lib/cisco_node_utils/cmd_ref/acl.yaml +21 -16
  53. data/lib/cisco_node_utils/cmd_ref/bgp.yaml +239 -109
  54. data/lib/cisco_node_utils/cmd_ref/bgp_af.yaml +114 -55
  55. data/lib/cisco_node_utils/cmd_ref/bgp_neighbor.yaml +76 -52
  56. data/lib/cisco_node_utils/cmd_ref/bgp_neighbor_af.yaml +106 -62
  57. data/lib/cisco_node_utils/cmd_ref/bridge_domain.yaml +71 -0
  58. data/lib/cisco_node_utils/cmd_ref/bridge_domain_vni.yaml +33 -0
  59. data/lib/cisco_node_utils/cmd_ref/dnsclient.yaml +35 -14
  60. data/lib/cisco_node_utils/cmd_ref/encapsulation.yaml +25 -0
  61. data/lib/cisco_node_utils/cmd_ref/evpn_vni.yaml +23 -17
  62. data/lib/cisco_node_utils/cmd_ref/fabricpath.yaml +94 -83
  63. data/lib/cisco_node_utils/cmd_ref/fabricpath_topology.yaml +22 -17
  64. data/lib/cisco_node_utils/cmd_ref/feature.yaml +76 -26
  65. data/lib/cisco_node_utils/cmd_ref/images.yaml +3 -2
  66. data/lib/cisco_node_utils/cmd_ref/interface.yaml +381 -153
  67. data/lib/cisco_node_utils/cmd_ref/interface_channel_group.yaml +21 -11
  68. data/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +21 -21
  69. data/lib/cisco_node_utils/cmd_ref/interface_portchannel.yaml +30 -21
  70. data/lib/cisco_node_utils/cmd_ref/interface_service_vni.yaml +18 -13
  71. data/lib/cisco_node_utils/cmd_ref/inventory.yaml +26 -31
  72. data/lib/cisco_node_utils/cmd_ref/itd_device_group.yaml +83 -0
  73. data/lib/cisco_node_utils/cmd_ref/itd_service.yaml +119 -0
  74. data/lib/cisco_node_utils/cmd_ref/memory.yaml +17 -6
  75. data/lib/cisco_node_utils/cmd_ref/ntp_config.yaml +10 -3
  76. data/lib/cisco_node_utils/cmd_ref/ntp_server.yaml +17 -5
  77. data/lib/cisco_node_utils/cmd_ref/ospf.yaml +33 -29
  78. data/lib/cisco_node_utils/cmd_ref/overlay_global.yaml +12 -10
  79. data/lib/cisco_node_utils/cmd_ref/pim.yaml +16 -19
  80. data/lib/cisco_node_utils/cmd_ref/portchannel_global.yaml +40 -25
  81. data/lib/cisco_node_utils/cmd_ref/radius_global.yaml +17 -12
  82. data/lib/cisco_node_utils/cmd_ref/radius_server.yaml +71 -35
  83. data/lib/cisco_node_utils/cmd_ref/radius_server_group.yaml +10 -5
  84. data/lib/cisco_node_utils/cmd_ref/show_system.yaml +6 -2
  85. data/lib/cisco_node_utils/cmd_ref/show_version.yaml +47 -43
  86. data/lib/cisco_node_utils/cmd_ref/snmp_community.yaml +13 -11
  87. data/lib/cisco_node_utils/cmd_ref/snmp_group.yaml +4 -2
  88. data/lib/cisco_node_utils/cmd_ref/snmp_notification_receiver.yaml +23 -21
  89. data/lib/cisco_node_utils/cmd_ref/snmp_server.yaml +26 -22
  90. data/lib/cisco_node_utils/cmd_ref/snmp_user.yaml +19 -17
  91. data/lib/cisco_node_utils/cmd_ref/snmpnotification.yaml +18 -6
  92. data/lib/cisco_node_utils/cmd_ref/stp_global.yaml +234 -0
  93. data/lib/cisco_node_utils/cmd_ref/syslog_server.yaml +24 -9
  94. data/lib/cisco_node_utils/cmd_ref/syslog_settings.yaml +5 -3
  95. data/lib/cisco_node_utils/cmd_ref/system.yaml +4 -3
  96. data/lib/cisco_node_utils/cmd_ref/tacacs_server.yaml +22 -20
  97. data/lib/cisco_node_utils/cmd_ref/tacacs_server_group.yaml +27 -15
  98. data/lib/cisco_node_utils/cmd_ref/tacacs_server_host.yaml +45 -16
  99. data/lib/cisco_node_utils/cmd_ref/vdc.yaml +21 -11
  100. data/lib/cisco_node_utils/cmd_ref/virtual_service.yaml +3 -2
  101. data/lib/cisco_node_utils/cmd_ref/vlan.yaml +60 -32
  102. data/lib/cisco_node_utils/cmd_ref/vpc.yaml +118 -101
  103. data/lib/cisco_node_utils/cmd_ref/vrf.yaml +54 -58
  104. data/lib/cisco_node_utils/cmd_ref/vrf_af.yaml +118 -0
  105. data/lib/cisco_node_utils/cmd_ref/vtp.yaml +19 -25
  106. data/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml +28 -18
  107. data/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml +34 -17
  108. data/lib/cisco_node_utils/cmd_ref/yum.yaml +6 -4
  109. data/lib/cisco_node_utils/command_reference.rb +261 -142
  110. data/lib/cisco_node_utils/constants.rb +33 -0
  111. data/lib/cisco_node_utils/encapsulation.rb +112 -0
  112. data/lib/cisco_node_utils/environment.rb +102 -0
  113. data/lib/cisco_node_utils/evpn_vni.rb +5 -3
  114. data/lib/cisco_node_utils/exceptions.rb +111 -0
  115. data/lib/cisco_node_utils/fabricpath_global.rb +52 -35
  116. data/lib/cisco_node_utils/fabricpath_topology.rb +44 -57
  117. data/lib/cisco_node_utils/feature.rb +165 -3
  118. data/lib/cisco_node_utils/interface.rb +1051 -260
  119. data/lib/cisco_node_utils/interface_channel_group.rb +11 -10
  120. data/lib/cisco_node_utils/interface_ospf.rb +1 -2
  121. data/lib/cisco_node_utils/interface_portchannel.rb +4 -12
  122. data/lib/cisco_node_utils/interface_service_vni.rb +7 -7
  123. data/lib/cisco_node_utils/itd_device_group.rb +248 -0
  124. data/lib/cisco_node_utils/itd_device_group_node.rb +144 -0
  125. data/lib/cisco_node_utils/itd_service.rb +523 -0
  126. data/lib/cisco_node_utils/logger.rb +75 -0
  127. data/lib/cisco_node_utils/node.rb +62 -192
  128. data/lib/cisco_node_utils/node_util.rb +56 -10
  129. data/lib/cisco_node_utils/overlay_global.rb +2 -2
  130. data/lib/cisco_node_utils/pim.rb +2 -13
  131. data/lib/cisco_node_utils/pim_group_list.rb +1 -1
  132. data/lib/cisco_node_utils/pim_rp_address.rb +1 -1
  133. data/lib/cisco_node_utils/platform.rb +52 -21
  134. data/lib/cisco_node_utils/portchannel_global.rb +89 -19
  135. data/lib/cisco_node_utils/radius_server.rb +168 -37
  136. data/lib/cisco_node_utils/router_ospf.rb +20 -35
  137. data/lib/cisco_node_utils/router_ospf_vrf.rb +4 -4
  138. data/lib/cisco_node_utils/snmpserver.rb +1 -6
  139. data/lib/cisco_node_utils/snmpuser.rb +6 -4
  140. data/lib/cisco_node_utils/stp_global.rb +676 -0
  141. data/lib/cisco_node_utils/syslog_server.rb +77 -18
  142. data/lib/cisco_node_utils/syslog_settings.rb +1 -1
  143. data/lib/cisco_node_utils/tacacs_server_group.rb +8 -4
  144. data/lib/cisco_node_utils/tacacs_server_host.rb +115 -25
  145. data/lib/cisco_node_utils/vdc.rb +12 -0
  146. data/lib/cisco_node_utils/version.rb +1 -1
  147. data/lib/cisco_node_utils/vlan.rb +147 -29
  148. data/lib/cisco_node_utils/vpc.rb +55 -3
  149. data/lib/cisco_node_utils/vrf.rb +72 -11
  150. data/lib/cisco_node_utils/vrf_af.rb +114 -29
  151. data/lib/cisco_node_utils/vtp.rb +34 -52
  152. data/lib/cisco_node_utils/vxlan_vtep.rb +34 -8
  153. data/lib/cisco_node_utils/vxlan_vtep_vni.rb +36 -4
  154. data/lib/minitest/environment_plugin.rb +31 -0
  155. data/lib/minitest/log_level_plugin.rb +41 -0
  156. data/spec/client_spec.rb +7 -0
  157. data/spec/environment_spec.rb +263 -0
  158. data/spec/grpc_client_spec.rb +23 -0
  159. data/spec/isolate/all_clients_spec.rb +9 -0
  160. data/spec/isolate/grpc_only_spec.rb +16 -0
  161. data/spec/isolate/no_clients_spec.rb +26 -0
  162. data/spec/isolate/nxapi_only_spec.rb +16 -0
  163. data/spec/nxapi_client_spec.rb +42 -0
  164. data/spec/schema.yaml +75 -0
  165. data/spec/shared_examples_for_clients.rb +14 -0
  166. data/spec/spec_helper.rb +91 -0
  167. data/spec/whitespace_spec.rb +10 -0
  168. data/spec/yaml_spec.rb +42 -0
  169. data/tests/.rubocop.yml +2 -2
  170. data/tests/CSCuxdublin-1.0.0-7.0.3.I3.1.lib32_n9000.rpm +0 -0
  171. data/tests/basetest.rb +96 -36
  172. data/tests/ciscotest.rb +220 -12
  173. data/tests/cmd_config.yaml +71 -49
  174. data/tests/cmd_config_invalid.yaml +1 -1
  175. data/tests/test_aaa_authentication_login.rb +1 -0
  176. data/tests/test_aaa_authentication_login_service.rb +9 -0
  177. data/tests/test_aaa_authorization_service.rb +173 -367
  178. data/tests/test_ace.rb +171 -100
  179. data/tests/test_acl.rb +10 -1
  180. data/tests/test_bgp_af.rb +395 -728
  181. data/tests/test_bgp_neighbor.rb +274 -115
  182. data/tests/test_bgp_neighbor_af.rb +178 -77
  183. data/tests/test_bridge_domain.rb +191 -0
  184. data/tests/test_bridge_domain_vni.rb +116 -0
  185. data/tests/test_client_utils.rb +111 -0
  186. data/tests/test_command_config.rb +9 -5
  187. data/tests/test_command_reference.rb +380 -102
  188. data/tests/test_dns_domain.rb +13 -3
  189. data/tests/test_domain_name.rb +13 -3
  190. data/tests/test_encapsulation.rb +77 -0
  191. data/tests/test_evpn_vni.rb +25 -7
  192. data/tests/test_fabricpath_global.rb +167 -163
  193. data/tests/test_fabricpath_topology.rb +12 -33
  194. data/tests/test_feature.rb +215 -0
  195. data/tests/test_grpc.rb +166 -0
  196. data/tests/test_interface.rb +585 -344
  197. data/tests/test_interface_bdi.rb +80 -0
  198. data/tests/test_interface_channel_group.rb +6 -3
  199. data/tests/test_interface_ospf.rb +26 -24
  200. data/tests/test_interface_portchannel.rb +1 -0
  201. data/tests/test_interface_private_vlan.rb +724 -0
  202. data/tests/test_interface_service_vni.rb +37 -66
  203. data/tests/test_interface_svi.rb +98 -101
  204. data/tests/test_interface_switchport.rb +419 -549
  205. data/tests/test_itd_device_group.rb +145 -0
  206. data/tests/test_itd_device_group_node.rb +199 -0
  207. data/tests/test_itd_service.rb +298 -0
  208. data/tests/test_logger.rb +43 -0
  209. data/tests/test_name_server.rb +11 -2
  210. data/tests/test_node.rb +16 -75
  211. data/tests/test_node_ext.rb +174 -163
  212. data/tests/test_node_util.rb +119 -0
  213. data/tests/test_ntp_config.rb +5 -1
  214. data/tests/test_ntp_server.rb +2 -2
  215. data/tests/test_nxapi.rb +221 -0
  216. data/tests/test_overlay_global.rb +47 -38
  217. data/tests/test_pim.rb +2 -0
  218. data/tests/test_pim_group_list.rb +2 -0
  219. data/tests/test_pim_rp_address.rb +2 -0
  220. data/tests/test_platform.rb +86 -39
  221. data/tests/test_portchannel_global.rb +211 -135
  222. data/tests/test_radius_global.rb +13 -5
  223. data/tests/test_radius_server.rb +256 -104
  224. data/tests/test_radius_server_group.rb +2 -0
  225. data/tests/test_router_bgp.rb +781 -485
  226. data/tests/test_router_ospf.rb +26 -103
  227. data/tests/test_router_ospf_vrf.rb +52 -57
  228. data/tests/test_snmp_notification_receiver.rb +2 -0
  229. data/tests/test_snmpcommunity.rb +2 -0
  230. data/tests/test_snmpgroup.rb +2 -0
  231. data/tests/test_snmpnotification.rb +40 -21
  232. data/tests/test_snmpserver.rb +2 -0
  233. data/tests/test_snmpuser.rb +2 -0
  234. data/tests/test_stp_global.rb +563 -0
  235. data/tests/test_syslog_server.rb +32 -8
  236. data/tests/test_syslog_settings.rb +22 -9
  237. data/tests/test_tacacs_server.rb +32 -27
  238. data/tests/test_tacacs_server_group.rb +100 -45
  239. data/tests/test_tacacs_server_host.rb +135 -43
  240. data/tests/test_vdc.rb +2 -16
  241. data/tests/test_vlan.rb +106 -54
  242. data/tests/test_vlan_mt_full.rb +11 -21
  243. data/tests/test_vlan_private.rb +669 -0
  244. data/tests/test_vpc.rb +312 -159
  245. data/tests/test_vrf.rb +122 -113
  246. data/tests/test_vrf_af.rb +238 -0
  247. data/tests/test_vtp.rb +58 -102
  248. data/tests/test_vxlan_vtep.rb +38 -17
  249. data/tests/test_vxlan_vtep_vni.rb +61 -9
  250. data/tests/test_yum.rb +49 -25
  251. metadata +122 -36
  252. data/lib/cisco_node_utils/cmd_ref/fex.yaml +0 -9
  253. data/lib/cisco_node_utils/cmd_ref/vni.yaml +0 -76
  254. data/lib/cisco_node_utils/vni.rb +0 -227
  255. data/tests/test_vni.rb +0 -106
@@ -0,0 +1,75 @@
1
+ #
2
+ # Cisco Logger Library.
3
+ #
4
+ # January 2015, Jie Yang
5
+ #
6
+ # Copyright (c) 2015 Cisco and/or its affiliates.
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+
20
+ require 'logger'
21
+
22
+ # Ensure module Cisco is defined
23
+ module Cisco
24
+ end
25
+
26
+ # Module for logging in CiscoNodeUtils. Will automatically
27
+ # tie into Puppet or Chef logging modules if available.
28
+ module Cisco::Logger
29
+ module_function
30
+
31
+ # Figure out what provider logging utility we
32
+ # should use: Puppet or Chef.
33
+ # If not found use the Ruby Logger/STDOUT/INFO.
34
+ if defined? (Puppet::Util::Logging)
35
+ @@logger = Puppet # rubocop:disable Style/ClassVars
36
+ def error(string)
37
+ @@logger.err(string)
38
+ end
39
+
40
+ def warn(string)
41
+ @@logger.warning(string)
42
+ end
43
+ else
44
+ if defined? (Chef::Log)
45
+ @@logger = Chef::Log # rubocop:disable Style/ClassVars
46
+ else
47
+ @@logger = Logger.new(STDOUT) # rubocop:disable Style/ClassVars
48
+ @@logger.level = Logger::INFO
49
+
50
+ def level
51
+ @@logger.level
52
+ end
53
+
54
+ def level=(level)
55
+ @@logger.level = level
56
+ end
57
+ end
58
+
59
+ def error(string)
60
+ @@logger.error(string)
61
+ end
62
+
63
+ def warn(string)
64
+ @@logger.warn(string)
65
+ end
66
+ end
67
+
68
+ def debug(string)
69
+ @@logger.debug(string)
70
+ end
71
+
72
+ def info(string)
73
+ @@logger.info(string)
74
+ end
75
+ end # module
@@ -18,47 +18,31 @@
18
18
  # See the License for the specific language governing permissions and
19
19
  # limitations under the License.
20
20
 
21
- require 'singleton'
22
-
23
- require 'cisco_nxapi'
21
+ require_relative 'client'
24
22
  require_relative 'command_reference'
23
+ require_relative 'exceptions'
24
+ require_relative 'logger'
25
25
 
26
26
  # Add node management classes and APIs to the Cisco namespace.
27
27
  module Cisco
28
- # Error class raised by the config_set and config_get APIs if the
29
- # device encounters an issue trying to act on the requested CLI.
30
- #
31
- # command - the specific CLI that was rejected
32
- # clierror - any error string from the device
33
- class CliError < RuntimeError
34
- attr_reader :command, :clierror, :previous
35
- def initialize(command, clierror, previous)
36
- @command = command
37
- @clierror = clierror.rstrip if clierror.kind_of? String
38
- @previous = previous
39
- end
40
-
41
- def to_s
42
- "CliError: '#{@command}' rejected with message:\n'#{@clierror}'"
43
- end
44
- end
45
-
46
28
  # class Cisco::Node
47
29
  # Singleton representing the network node (switch/router) that is
48
30
  # running this code. The singleton is lazily instantiated, meaning that
49
31
  # it doesn't exist until some client requests it (with Node.instance())
50
32
  class Node
51
- include Singleton
33
+ @instance = nil
52
34
 
53
- # Convenience wrapper for show(command, :structured).
35
+ # Convenience wrapper for get()
54
36
  # Uses CommandReference to look up the given show command and key
55
37
  # of interest, executes that command, and returns the value corresponding
56
38
  # to that key.
57
39
  #
58
40
  # @raise [IndexError] if the given (feature, name) pair is not in the
59
41
  # CommandReference data or if the data doesn't have values defined
60
- # for the 'config_get' and (optional) 'config_get_token' fields.
61
- # @raise [Cisco::CliError] if the given command is rejected by the device.
42
+ # for the 'get_command' and (optional) 'get_value' fields.
43
+ # @raise [Cisco::UnsupportedError] if the (feature, name) pair is flagged
44
+ # in the YAML as unsupported on this device.
45
+ # @raise [Cisco::RequestFailed] if the command is rejected by the device.
62
46
  #
63
47
  # @param feature [String]
64
48
  # @param name [String]
@@ -66,43 +50,30 @@ module Cisco
66
50
  # @example config_get("show_version", "system_image")
67
51
  # @example config_get("ospf", "router_id",
68
52
  # {name: "green", vrf: "one"})
69
- def config_get(feature, name, *args)
70
- fail 'lazy_connect specified but did not request connect' unless @cmd_ref
71
- ref = @cmd_ref.lookup(feature, name)
53
+ def config_get(feature, property, *args)
54
+ ref = @cmd_ref.lookup(feature, property)
72
55
 
73
- return ref.default_value if ref.default_only?
56
+ # If we have a default value but no getter, just return the default
57
+ return ref.default_value if ref.default_value? && !ref.getter?
74
58
 
75
- begin
76
- token = ref.config_get_token(*args)
77
- rescue IndexError
78
- # IndexError: no entry for config_get_token
79
- token = nil
80
- end
81
- if token.nil?
82
- # Just get the whole output
83
- return massage(show(ref.config_get, :structured), ref)
84
- elsif token[0].kind_of?(Regexp)
85
- return massage(Cisco.find_ascii(show(ref.config_get, :ascii),
86
- token[-1],
87
- *token[0..-2]), ref)
88
- else
89
- return massage(
90
- config_get_handle_structured(token,
91
- show(ref.config_get, :structured)),
92
- ref)
93
- end
59
+ get_args = ref.getter(*args)
60
+ massage(get(command: ref.get_command,
61
+ data_format: get_args[:data_format],
62
+ context: get_args[:context],
63
+ value: get_args[:value]),
64
+ ref)
94
65
  end
95
66
 
96
67
  # Attempt to massage the given value into the format specified by the
97
68
  # given CmdRef object.
98
69
  def massage(value, ref)
99
- CiscoLogger.debug "Massaging '#{value}' (#{value.inspect})"
70
+ Cisco::Logger.debug "Massaging '#{value}' (#{value.inspect})"
100
71
  if value.is_a?(Array) && !ref.multiple
101
72
  fail "Expected zero/one value but got '#{value}'" if value.length > 1
102
73
  value = value[0]
103
74
  end
104
75
  if (value.nil? || value.empty?) && ref.default_value? && ref.auto_default
105
- CiscoLogger.debug "Default: #{ref.default_value}"
76
+ Cisco::Logger.debug "Default: #{ref.default_value}"
106
77
  return ref.default_value
107
78
  end
108
79
  return value unless ref.kind
@@ -112,6 +83,8 @@ module Cisco
112
83
  value = false
113
84
  elsif /^no / =~ value
114
85
  value = false
86
+ elsif /disable$/ =~ value
87
+ value = false
115
88
  else
116
89
  value = true
117
90
  end
@@ -120,8 +93,10 @@ module Cisco
120
93
  when :string
121
94
  value = '' if value.nil?
122
95
  value = value.to_s.strip
96
+ when :symbol
97
+ value = value.to_sym unless value.nil?
123
98
  end
124
- CiscoLogger.debug "Massaged to '#{value}'"
99
+ Cisco::Logger.debug "Massaged to '#{value}'"
125
100
  value
126
101
  end
127
102
 
@@ -134,10 +109,10 @@ module Cisco
134
109
  # @param feature [String]
135
110
  # @param name [String]
136
111
  # @return [String]
112
+ # @return [nil] if this feature/name pair is marked as unsupported
137
113
  # @example config_get_default("vtp", "file")
138
- def config_get_default(feature, name)
139
- fail 'lazy_connect specified but did not request connect' unless @cmd_ref
140
- ref = @cmd_ref.lookup(feature, name)
114
+ def config_get_default(feature, property)
115
+ ref = @cmd_ref.lookup(feature, property)
141
116
  ref.default_value
142
117
  end
143
118
 
@@ -146,7 +121,8 @@ module Cisco
146
121
  #
147
122
  # @raise [IndexError] if no relevant cmd_ref config_set exists
148
123
  # @raise [ArgumentError] if too many or too few args are provided.
149
- # @raise [Cisco::CliError] if any command is rejected by the device.
124
+ # @raise [Cisco::UnsupportedError] if this feature/name is unsupported
125
+ # @raise [Cisco::RequestFailed] if any command is rejected by the device.
150
126
  #
151
127
  # @param feature [String]
152
128
  # @param name [String]
@@ -155,10 +131,10 @@ module Cisco
155
131
  # @example config_set("ospf", "router_id",
156
132
  # {:name => "green", :vrf => "one", :state => "",
157
133
  # :router_id => "192.0.0.1"})
158
- def config_set(feature, name, *args)
159
- fail 'lazy_connect specified but did not request connect' unless @cmd_ref
160
- ref = @cmd_ref.lookup(feature, name)
161
- config(ref.config_set(*args))
134
+ def config_set(feature, property, *args)
135
+ ref = @cmd_ref.lookup(feature, property)
136
+ set_args = ref.setter(*args)
137
+ set(**set_args)
162
138
  end
163
139
 
164
140
  # Clear the cache of CLI output results.
@@ -175,40 +151,25 @@ module Cisco
175
151
 
176
152
  attr_reader :cmd_ref, :client
177
153
 
178
- # For unit testing - we won't know the node connection info at load time.
179
- @lazy_connect = false
180
-
181
- class << self
182
- attr_reader :lazy_connect
183
- end
184
-
185
- class << self
186
- attr_writer :lazy_connect
154
+ def self.instance
155
+ @instance ||= new
187
156
  end
188
157
 
189
158
  def initialize
190
- @client = nil
159
+ @client = Cisco::Client.create
191
160
  @cmd_ref = nil
192
- connect unless self.class.lazy_connect
161
+ @cmd_ref = CommandReference.new(product: product_id,
162
+ platform: @client.platform,
163
+ data_formats: @client.data_formats)
164
+ cache_flush
193
165
  end
194
166
 
195
167
  def to_s
196
- @client.to_s
197
- end
198
-
199
- # "hidden" API - used for UT but shouldn't be used elsewhere
200
- def connect(*args)
201
- @client = CiscoNxapi::NxapiClient.new(*args)
202
- # Hard-code platform and cli for now
203
- @cmd_ref = CommandReference.new(product: product_id,
204
- platform: :nexus,
205
- cli: true)
206
- cache_flush
168
+ client.to_s
207
169
  end
208
170
 
209
- # TODO: remove me
210
- def reload
211
- @client.reload
171
+ def inspect
172
+ "Node: client:'#{client.inspect}' cmd_ref:'#{cmd_ref.inspect}'"
212
173
  end
213
174
 
214
175
  def cache_enable?
@@ -227,54 +188,22 @@ module Cisco
227
188
  @client.cache_auto = enable
228
189
  end
229
190
 
230
- # Helper method for config_get().
231
- # @param token [Array, Hash] lookup sequence
232
- # @param result [Array, Hash] structured output from node
233
- def config_get_handle_structured(token, result)
234
- token.each do |t|
235
- # if token is a hash and result is an array, check each
236
- # array index (which should return another hash) to see if
237
- # it contains the matching key/value pairs specified in token,
238
- # and return the first match (or nil)
239
- if t.kind_of?(Hash)
240
- fail "Expected array, got #{result.class}" unless result.is_a? Array
241
- result = result.select { |x| t.all? { |k, v| x[k] == v } }
242
- fail "Multiple matches found for #{t}" if result.length > 1
243
- fail "No match found for #{t}" if result.length == 0
244
- result = result[0]
245
- else # result is array or hash
246
- fail "No key \"#{t}\" in #{result}" if result[t].nil?
247
- result = result[t]
248
- end
249
- end
250
- result
251
- rescue RuntimeError
252
- # TODO: logging user story, Syslog isn't available here
253
- # Syslog.debug(e.message)
254
- nil
255
- end
256
-
257
191
  # Send a config command to the device.
258
192
  # In general, clients should use config_set() rather than calling
259
193
  # this function directly.
260
194
  #
261
- # @raise [Cisco::CliError] if any command is rejected by the device.
262
- def config(commands)
263
- CiscoLogger.debug("CLI Sent to device: #{commands}")
264
- @client.config(commands)
265
- rescue CiscoNxapi::CliError => e
266
- raise Cisco::CliError.new(e.input, e.clierror, e.previous)
195
+ # @raise [Cisco::RequestFailed] if any command is rejected by the device.
196
+ def set(**kwargs)
197
+ @client.set(**kwargs)
267
198
  end
268
199
 
269
200
  # Send a show command to the device.
270
201
  # In general, clients should use config_get() rather than calling
271
202
  # this function directly.
272
203
  #
273
- # @raise [Cisco::CliError] if any command is rejected by the device.
274
- def show(command, type=:ascii)
275
- @client.show(command, type)
276
- rescue CiscoNxapi::CliError => e
277
- raise Cisco::CliError.new(e.input, e.clierror, e.previous)
204
+ # @raise [Cisco::RequestFailed] if any command is rejected by the device.
205
+ def get(**kwargs)
206
+ @client.get(**kwargs)
278
207
  end
279
208
 
280
209
  # @return [String] such as "Cisco Nexus Operating System (NX-OS) Software"
@@ -300,8 +229,16 @@ module Cisco
300
229
  return config_get('inventory', 'productid')
301
230
  else
302
231
  # We use this function to *find* the appropriate CommandReference
303
- entries = show('show inventory', :structured)
304
- return entries['TABLE_inv']['ROW_inv'][0]['productid']
232
+ if @client.platform == :nexus
233
+ entries = get(command: 'show inventory',
234
+ data_format: :nxapi_structured)
235
+ return entries['TABLE_inv']['ROW_inv'][0]['productid']
236
+ elsif @client.platform == :ios_xr
237
+ # No support for structured output for this command yet
238
+ output = get(command: 'show inventory',
239
+ data_format: :cli)
240
+ return /NAME: "Rack 0".*\nPID: (\S+)/.match(output)[1]
241
+ end
305
242
  end
306
243
  end
307
244
 
@@ -349,7 +286,7 @@ module Cisco
349
286
  # @return [Float] combined user/kernel CPU utilization
350
287
  def system_cpu_utilization
351
288
  output = config_get('system', 'resources')
352
- fail 'failed to retrieve cpu utilization' if output.nil?
289
+ return output if output.nil?
353
290
  output['cpu_state_user'].to_f + output['cpu_state_kernel'].to_f
354
291
  end
355
292
 
@@ -365,71 +302,4 @@ module Cisco
365
302
  config_get('show_version', 'system_image')
366
303
  end
367
304
  end
368
-
369
- # Method for working with hierarchical show command output such as
370
- # "show running-config". Searches the given multi-line string
371
- # for all matches to the given regex_query. If parents is provided,
372
- # the matches will be filtered to only those that are located "under"
373
- # the given parent sequence (as determined by indentation).
374
- #
375
- # @param body [String] The body of text to search
376
- # @param regex_query [Regex] The regular expression to match
377
- # @param parents [*Regex] zero or more regular expressions defining
378
- # the parent configs to filter by.
379
- # @return [[String], nil] array of matching (sub)strings, else nil.
380
- #
381
- # @example Find all OSPF router names in the running-config
382
- # ospf_names = find_ascii(running_cfg, /^router ospf (\d+)/)
383
- #
384
- # @example Find all address-family types under the given BGP router
385
- # bgp_afs = find_ascii(show_run_bgp, /^address-family (.*)/,
386
- # /^router bgp #{ASN}/)
387
- def find_ascii(body, regex_query, *parent_cfg)
388
- return nil if body.nil? || regex_query.nil?
389
-
390
- # get subconfig
391
- parent_cfg.each { |p| body = find_subconfig(body, p) }
392
- if body.nil? || body.empty?
393
- return nil
394
- else
395
- # find matches and return as array of String if it only does one
396
- # match in the regex. Otherwise return array of array
397
- match = body.split("\n").map { |s| s.scan(regex_query) }
398
- match = match.flatten(1)
399
- return nil if match.empty?
400
- match = match.flatten if match[0].is_a?(Array) && match[0].length == 1
401
- return match
402
- end
403
- end
404
- module_function :find_ascii
405
-
406
- # Returns the subsection associated with the given
407
- # line of config
408
- # @param [String] the body of text to search
409
- # @param [Regex] the regex key of the config for which
410
- # to retrieve the subsection
411
- # @return [String, nil] the subsection of body, de-indented
412
- # appropriately, or nil if no such subsection exists.
413
- def find_subconfig(body, regex_query)
414
- return nil if body.nil? || regex_query.nil?
415
-
416
- rows = body.split("\n")
417
- match_row_index = rows.index { |row| regex_query =~ row }
418
- return nil if match_row_index.nil?
419
-
420
- cur = match_row_index + 1
421
- subconfig = []
422
-
423
- until (/\A\s+.*/ =~ rows[cur]).nil? || cur == rows.length
424
- subconfig << rows[cur]
425
- cur += 1
426
- end
427
- return nil if subconfig.empty?
428
- # Strip an appropriate minimal amount of leading whitespace from
429
- # all lines in the subconfig
430
- min_leading = subconfig.map { |line| line[/\A */].size }.min
431
- subconfig = subconfig.map { |line| line[min_leading..-1] }
432
- subconfig.join("\n")
433
- end
434
- module_function :find_subconfig
435
305
  end