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
@@ -15,31 +15,41 @@
15
15
  # limitations under the License.
16
16
 
17
17
  require_relative 'node'
18
+ require_relative 'exceptions'
18
19
 
19
20
  module Cisco
20
21
  # NodeUtil - generic functionality for node utility subclasses to use
21
22
  class NodeUtil
22
- # rubocop:disable Style/ClassVars
23
- # We want this to be inherited to all child classes, it's a singleton.
24
- @@node = nil
25
- # rubocop:enable Style/ClassVars
26
-
27
23
  def self.node
28
- # rubocop:disable Style/ClassVars
29
- @@node ||= Cisco::Node.instance
30
- # rubocop:enable Style/ClassVars
24
+ @node ||= Cisco::Node.instance
31
25
  end
32
26
 
33
27
  def node
34
28
  self.class.node
35
29
  end
36
30
 
31
+ def self.client
32
+ node.client
33
+ end
34
+
35
+ def client
36
+ node.client
37
+ end
38
+
37
39
  def self.config_get(*args)
38
40
  node.config_get(*args)
41
+ rescue Cisco::RequestFailed => e
42
+ e2 = e.class.new("[#{self}] #{e}", **e.kwargs)
43
+ e2.set_backtrace(e.backtrace)
44
+ raise e2
39
45
  end
40
46
 
41
47
  def config_get(*args)
42
48
  node.config_get(*args)
49
+ rescue Cisco::RequestFailed => e
50
+ e2 = e.class.new("[#{self}] #{e}", **e.kwargs)
51
+ e2.set_backtrace(e.backtrace)
52
+ raise e2
43
53
  end
44
54
 
45
55
  def self.config_get_default(*args)
@@ -52,14 +62,50 @@ module Cisco
52
62
 
53
63
  def self.config_set(*args)
54
64
  node.config_set(*args)
65
+ rescue Cisco::RequestFailed => e
66
+ e2 = e.class.new("[#{self}] #{e}", **e.kwargs)
67
+ e2.set_backtrace(e.backtrace)
68
+ raise e2
55
69
  end
56
70
 
57
71
  def config_set(*args)
58
72
  node.config_set(*args)
73
+ rescue Cisco::RequestFailed => e
74
+ e2 = e.class.new("[#{self}] #{e}", **e.kwargs)
75
+ e2.set_backtrace(e.backtrace)
76
+ raise e2
77
+ end
78
+
79
+ def self.supports?(api)
80
+ client.supports?(api)
81
+ end
82
+
83
+ def supports?(api)
84
+ client.supports?(api)
85
+ end
86
+
87
+ def self.platform
88
+ client.platform
89
+ end
90
+
91
+ def platform
92
+ client.platform
93
+ end
94
+
95
+ def get(**kwargs)
96
+ node.get(**kwargs)
97
+ rescue Cisco::RequestFailed => e
98
+ e2 = e.class.new("[#{self}] #{e}", **e.kwargs)
99
+ e2.set_backtrace(e.backtrace)
100
+ raise e2
101
+ end
102
+
103
+ def ios_xr?
104
+ platform == :ios_xr
59
105
  end
60
106
 
61
- def show(*args)
62
- node.show(*args)
107
+ def nexus?
108
+ platform == :nexus
63
109
  end
64
110
  end
65
111
  end
@@ -51,6 +51,7 @@ module Cisco
51
51
  end
52
52
 
53
53
  def dup_host_ip_addr_detection_set(host_moves, timeout)
54
+ Feature.fabric_forwarding_enable
54
55
  Feature.nv_overlay_evpn_enable
55
56
  if host_moves == default_dup_host_ip_addr_detection_host_moves &&
56
57
  timeout == default_dup_host_ip_addr_detection_timeout
@@ -127,8 +128,7 @@ module Cisco
127
128
  def anycast_gateway_mac
128
129
  return nil unless Feature.nv_overlay_evpn_enabled?
129
130
  mac = config_get('overlay_global', 'anycast_gateway_mac')
130
- # This value gets 0-padded when nvgened, so we need to convert it.
131
- Utils.zero_pad_macaddr(mac).nil? ? default_anycast_gateway_mac : mac
131
+ mac.nil? || mac.empty? ? default_anycast_gateway_mac : mac.downcase
132
132
  end
133
133
 
134
134
  def anycast_gateway_mac=(mac_addr)
@@ -32,19 +32,7 @@ module Cisco
32
32
  @afi = Pim.afi_cli(afi)
33
33
  set_args_keys_default
34
34
 
35
- Pim.feature_enable if instantiate
36
- end
37
-
38
- def self.feature_enabled
39
- config_get('pim', 'feature')
40
- rescue Cisco::CliError => e
41
- # cmd will syntax reject when feature is not enabled
42
- raise unless e.clierror =~ /Syntax error/
43
- return false
44
- end
45
-
46
- def self.feature_enable
47
- config_set('pim', 'feature')
35
+ Feature.pim_enable if instantiate
48
36
  end
49
37
 
50
38
  # self.pims returns a hash of all current pim objects.
@@ -99,6 +87,7 @@ module Cisco
99
87
  # For that reason destroy needs to explicitly set each property
100
88
  # to its default state.
101
89
  def destroy
90
+ return unless Feature.pim_enabled?
102
91
  self.ssm_range = ''
103
92
  end
104
93
 
@@ -93,7 +93,7 @@ module Cisco
93
93
  # Create pim grouplist instance
94
94
  # ---------------------------------
95
95
  def create
96
- Pim.feature_enable unless Pim.feature_enabled
96
+ Feature.pim_enable
97
97
  set_args_keys(state: '')
98
98
  config_set('pim', 'group_list', @set_args)
99
99
  end
@@ -87,7 +87,7 @@ module Cisco
87
87
  # Create pim rp_addr instance
88
88
  # ------------------------------
89
89
  def create
90
- Pim.feature_enable unless Pim.feature_enabled
90
+ Feature.pim_enable
91
91
  set_args_keys(state: '')
92
92
  config_set('pim', 'rp_address', @set_args)
93
93
  end
@@ -19,6 +19,13 @@ require_relative 'node_util'
19
19
  module Cisco
20
20
  # Platform - class for gathering platform hardware and software information
21
21
  class Platform < NodeUtil
22
+ #
23
+ # NX: 7.0(3)I2(3) [build 7.0(3)I2(2.118)]
24
+ # XR: 6.1.1.04I
25
+ def self.image_version
26
+ config_get('show_version', 'version')
27
+ end
28
+
22
29
  # ex: 'n3500-uk9.6.0.2.A3.0.40.bin'
23
30
  def self.system_image
24
31
  config_get('show_version', 'boot_image')
@@ -50,23 +57,20 @@ module Cisco
50
57
  # 'used' => '5909004K',
51
58
  # 'free' => '10493248K' }
52
59
  def self.memory
53
- total = config_get('memory', 'total')
54
- used = config_get('memory', 'used')
55
- free = config_get('memory', 'free')
56
-
57
- fail 'failed to retrieve platform memory information' if
58
- total.nil? || used.nil? || free.nil?
59
-
60
60
  {
61
- 'total' => total,
62
- 'used' => used,
63
- 'free' => free,
61
+ 'total' => config_get('memory', 'total'),
62
+ 'used' => config_get('memory', 'used'),
63
+ 'free' => config_get('memory', 'free'),
64
64
  }
65
65
  end
66
66
 
67
67
  # Ex: 'Processor Board ID FOC15430TEY'
68
68
  def self.board
69
69
  config_get('show_version', 'board')
70
+ rescue RuntimeError => e
71
+ # Some Nexus platforms may fail to report this value.
72
+ return nil if /No key/ =~ e.message
73
+ raise
70
74
  end
71
75
 
72
76
  # Ex: '1 day(s), 21 hour(s), 46 minute(s), 54 second(s)'
@@ -79,6 +83,10 @@ module Cisco
79
83
  # Ex: '23113 usecs after Mon Jul 1 15:24:29 2013'
80
84
  def self.last_reset
81
85
  config_get('show_version', 'last_reset_time')
86
+ rescue RuntimeError => e
87
+ # Some Nexus platforms may fail to report this value.
88
+ return nil if /No key/ =~ e.message
89
+ raise
82
90
  end
83
91
 
84
92
  # Ex: 'Reset Requested by CLI command reload'
@@ -93,7 +101,12 @@ module Cisco
93
101
  # 'sn' => 'SAL1812NTBP' }
94
102
  def self.chassis
95
103
  node.cache_flush # TODO: investigate why this is needed
96
- chas = config_get('inventory', 'chassis')
104
+ all = config_get('inventory', 'chassis')
105
+ return nil if all.nil?
106
+
107
+ # item['name'] value is "\"Chassis\"" on most platforms,
108
+ # but n5k/n6k use "Chassis" so make the quotes optional.
109
+ chas = all.find { |item| item['name'][/^"?Chassis"?$/] }
97
110
  return nil if chas.nil?
98
111
  {
99
112
  'descr' => chas['desc'].tr('"', ''),
@@ -112,16 +125,34 @@ module Cisco
112
125
  def self.inventory_of(type)
113
126
  node.cache_flush # TODO: investigate why this is needed
114
127
  inv = config_get('inventory', 'all')
115
- return {} if inv.nil?
116
- inv.select! { |x| x['name'].include? type }
117
- return {} if inv.empty?
118
- # match desired output format
119
128
  inv_hsh = {}
120
- inv.each do |s|
121
- inv_hsh[s['name'].tr('"', '')] = { 'descr' => s['desc'].tr('"', ''),
122
- 'pid' => s['productid'],
123
- 'vid' => s['vendorid'],
124
- 'sn' => s['serialnum'] }
129
+ return inv_hsh if inv.nil?
130
+ if platform == :ios_xr
131
+ # XR gets a string so we have to process it directly
132
+ inv_arr = inv.scan(
133
+ /NAME:\s+"(#{type}[^"]*)",\s+
134
+ DESCR:\s+"([^"]*)"\s*
135
+ \n
136
+ PID:\s+(\S+)\s*,\s+
137
+ VID:\s+(\S+)\s*,\s+
138
+ SN:\s+(\S+)\s*/x).flatten
139
+ inv_arr.each do |entry|
140
+ inv_hsh[entry[0]] = { 'descr' => entry[1],
141
+ 'pid' => entry[2],
142
+ 'vid' => entry[3],
143
+ 'sn' => entry[4] }
144
+ end
145
+ else
146
+ # Nexus gets structured output
147
+ inv.select! { |x| x['name'].include? type }
148
+ return inv_hsh if inv.empty?
149
+ # match desired output format
150
+ inv.each do |s|
151
+ inv_hsh[s['name'].tr('"', '')] = { 'descr' => s['desc'].tr('"', ''),
152
+ 'pid' => s['productid'],
153
+ 'vid' => s['vendorid'],
154
+ 'sn' => s['serialnum'] }
155
+ end
125
156
  end
126
157
  inv_hsh
127
158
  end
@@ -158,7 +189,7 @@ module Cisco
158
189
  # { ... }}
159
190
  def self.virtual_services
160
191
  virts = config_get('virtual_service', 'services')
161
- return [] if virts.nil?
192
+ return {} if virts.nil?
162
193
  # NXAPI returns hash instead of array if there's only 1
163
194
  virts = [virts] if virts.is_a? Hash
164
195
  # convert to expected format
@@ -27,6 +27,10 @@ module Cisco
27
27
  @name = name.downcase
28
28
  end
29
29
 
30
+ def to_s
31
+ "portchannel_global #{name}"
32
+ end
33
+
30
34
  def self.globals
31
35
  { 'default' => PortChannelGlobal.new('default') }
32
36
  end
@@ -35,6 +39,10 @@ module Cisco
35
39
  # PROPERTIES #
36
40
  ########################################################
37
41
 
42
+ def load_balance_type
43
+ config_get('portchannel_global', 'load_balance_type')
44
+ end
45
+
38
46
  def hash_distribution
39
47
  config_get('portchannel_global', 'hash_distribution')
40
48
  end
@@ -42,8 +50,6 @@ module Cisco
42
50
  def hash_distribution=(val)
43
51
  config_set('portchannel_global',
44
52
  'hash_distribution', val)
45
- rescue Cisco::CliError => e
46
- raise "[#{@name}] '#{e.command}' : #{e.clierror}"
47
53
  end
48
54
 
49
55
  def default_hash_distribution
@@ -56,8 +62,6 @@ module Cisco
56
62
 
57
63
  def load_defer=(val)
58
64
  config_set('portchannel_global', 'load_defer', val)
59
- rescue Cisco::CliError => e
60
- raise "[#{@name}] '#{e.command}' : #{e.clierror}"
61
65
  end
62
66
 
63
67
  def default_load_defer
@@ -72,8 +76,6 @@ module Cisco
72
76
  fail TypeError unless state == true || state == false
73
77
  no_cmd = (state ? '' : 'no')
74
78
  config_set('portchannel_global', 'resilient', no_cmd)
75
- rescue Cisco::CliError => e
76
- raise "[#{@name}] '#{e.command}' : #{e.clierror}"
77
79
  end
78
80
 
79
81
  def default_resilient
@@ -105,10 +107,14 @@ module Cisco
105
107
  params = line.split
106
108
  lb_type = config_get('portchannel_global', 'load_balance_type')
107
109
  case lb_type.to_sym
110
+ when :no_rotate # n3k
111
+ _parse_no_rotate_params(hash, params, line)
108
112
  when :ethernet # n6k
109
113
  _parse_ethernet_params(hash, params)
110
114
  when :asymmetric # n7k
111
115
  _parse_asymmetric_params(hash, params, line)
116
+ when :no_hash # n8k
117
+ _parse_no_hash_params(hash, params)
112
118
  when :symmetry # n9k
113
119
  _parse_symmetry_params(hash, params, line)
114
120
  end
@@ -156,11 +162,6 @@ module Cisco
156
162
  port_channel_load_balance[:hash_poly]
157
163
  end
158
164
 
159
- def default_hash_poly
160
- config_get_default('portchannel_global',
161
- 'hash_poly')
162
- end
163
-
164
165
  def rotate
165
166
  port_channel_load_balance[:rotate]
166
167
  end
@@ -182,6 +183,19 @@ module Cisco
182
183
  def port_channel_load_balance=(bselect, bhash, hpoly, asy, sy, conc, rot)
183
184
  lb_type = config_get('portchannel_global', 'load_balance_type')
184
185
  case lb_type.to_sym
186
+ when :no_rotate # n3k
187
+ sym = sy ? 'symmetric' : ''
188
+ if bselect == 'src'
189
+ sel = 'source'
190
+ elsif bselect == 'dst'
191
+ sel = 'destination'
192
+ else
193
+ sel = 'source-dest'
194
+ end
195
+ sel_hash = sel + '-' + bhash
196
+ # port-channel load-balance ethernet source-dest-ip symmetric
197
+ config_set('portchannel_global', 'port_channel_load_balance',
198
+ 'ethernet', sel_hash, sym, '', '', '')
185
199
  when :ethernet # n6k
186
200
  if bselect == 'src'
187
201
  sel = 'source'
@@ -199,6 +213,12 @@ module Cisco
199
213
  # port-channel load-balance dst ip-l4port rotate 4 asymmetric
200
214
  config_set('portchannel_global', 'port_channel_load_balance',
201
215
  bselect, bhash, 'rotate', rot.to_s, asym, '')
216
+ when :no_hash # n8k
217
+ # port-channel load-balance dst ip-l4port rotate 4
218
+ rot_str = rot.zero? ? '' : 'rotate'
219
+ rot_val = rot.zero? ? '' : rot.to_s
220
+ config_set('portchannel_global', 'port_channel_load_balance',
221
+ bselect, bhash, rot_str, rot_val, '', '')
202
222
  when :symmetry # n9k
203
223
  sym = sy ? 'symmetric' : ''
204
224
  concat = conc ? 'concatenation' : ''
@@ -208,19 +228,58 @@ module Cisco
208
228
  config_set('portchannel_global', 'port_channel_load_balance',
209
229
  bselect, bhash, rot_str, rot_val, concat, sym)
210
230
  end
211
- rescue Cisco::CliError => e
212
- raise "[#{@name}] '#{e.command}' : #{e.clierror}"
213
231
  end
214
232
 
215
- # on n6k, the bundle hash and bundle select are
216
- # merged into one and so we need to break them apart,
217
- # also they are called source and destination instead of
218
- # src and dst as in other devices, so we convert them
233
+ # N3k: The bundle hash and bundle select are merged into one output;
234
+ # also note that the field names are source & destination instead of
235
+ # src & dst as in other devices.
236
+ def _parse_no_rotate_params(hash, params, line)
237
+ sym = (line.include? 'symmetric') ? true : false
238
+
239
+ select_hash = params[1]
240
+ lparams = select_hash.split('-')
241
+ if lparams[0].downcase == 'destination'
242
+ bselect = 'dst'
243
+ bhash = lparams[1]
244
+ # there are bundles hashes like ip-gre which
245
+ # need extra processing
246
+ bhash += '-gre' if select_hash.include? 'gre'
247
+ else
248
+ if select_hash.include? '-dest-'
249
+ bselect = 'src-dst'
250
+ bhash = lparams[2]
251
+ bhash += '-gre' if select_hash.include? 'gre'
252
+ # there are bundles hashes like ip-only and
253
+ # port-only specific to src-dst
254
+ bhash += '-only' if select_hash.include? 'only'
255
+ else
256
+ bselect = 'src'
257
+ bhash = lparams[1]
258
+ # there are bundles hashes like ip-gre which
259
+ # need extra processing
260
+ bhash += '-gre' if select_hash.include? 'gre'
261
+ end
262
+ end
263
+ hash[:bundle_select] = bselect
264
+ hash[:bundle_hash] = bhash
265
+ hash[:symmetry] = sym
266
+ hash
267
+ end
268
+
269
+ # N5k/N6k: The bundle hash and bundle select are merged into one output;
270
+ # also note that the field names are source & destination instead of
271
+ # src & dst as in other devices.
219
272
  def _parse_ethernet_params(hash, params)
220
273
  hash_poly = params[2]
221
- # hash_poly is not shown on the running config
222
- # if it is default under some circumstatnces
274
+
275
+ # Depending on the chipset, hash_poly may have have a different
276
+ # default value within the same platform family (this is done to
277
+ # avoid polarization) but there is currently no command available
278
+ # to dynamically determine the default state. As a result the
279
+ # getter simply hard-codes a default value which means it may
280
+ # encounter occasional idempotence issues.
223
281
  hash_poly = hash_poly.nil? ? 'CRC10b' : hash_poly
282
+
224
283
  select_hash = params[1]
225
284
  lparams = select_hash.split('-')
226
285
  if lparams[0].downcase == 'destination'
@@ -258,6 +317,17 @@ module Cisco
258
317
  hash
259
318
  end
260
319
 
320
+ def _parse_no_hash_params(hash, params)
321
+ bselect = params[0]
322
+ bhash = params[1]
323
+ ri = params.index('rotate')
324
+ rotate = params[ri + 1].to_i
325
+ hash[:bundle_select] = bselect
326
+ hash[:bundle_hash] = bhash
327
+ hash[:rotate] = rotate
328
+ hash
329
+ end
330
+
261
331
  def _parse_symmetry_params(hash, params, line)
262
332
  bselect = params[0]
263
333
  bhash = params[1]