cisco_node_utils 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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