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
@@ -117,7 +117,7 @@ module Cisco
117
117
  # aaa authorization login <type> <name> /
118
118
  # local | group <group1 [group2, ...]> [local]
119
119
  def groups_method_set(grps, m)
120
- fail TypeError unless grps.is_a? Array
120
+ grps = Array(grps) unless grps.is_a? Array
121
121
  fail TypeError unless grps.all? { |x| x.is_a? String }
122
122
  fail TypeError unless m.is_a? Symbol
123
123
  # only the following are supported (unselected = blank)
@@ -17,7 +17,7 @@ require_relative 'node_util'
17
17
  module Cisco
18
18
  # Ace - node utility class for Ace Configuration
19
19
  class Ace < NodeUtil
20
- attr_reader :afi, :acl_name, :seqno
20
+ attr_reader :afi, :acl_name
21
21
 
22
22
  def initialize(afi, acl_name, seqno)
23
23
  @afi = Acl.afi_cli(afi)
@@ -70,18 +70,27 @@ module Cisco
70
70
  str = config_get('acl', 'ace', @get_args)
71
71
  return nil if str.nil?
72
72
 
73
- # remark is a description field, needs a separate regex
74
- # Example: <MatchData "20 remark foo bar" seqno:"20" remark:"foo bar">
75
73
  remark = Regexp.new('(?<seqno>\d+) remark (?<remark>.*)').match(str)
76
74
  return remark unless remark.nil?
77
75
 
78
76
  # rubocop:disable Metrics/LineLength
79
77
  regexp = Regexp.new('(?<seqno>\d+) (?<action>\S+)'\
80
78
  ' *(?<proto>\d+|\S+)'\
81
- ' *(?<src_addr>any|host \S+|\S+\/\d+|\S+ [:\.0-9a-fA-F]+|addrgroup \S+)*'\
82
- ' *(?<src_port>eq \S+|neq \S+|lt \S+|''gt \S+|range \S+ \S+|portgroup \S+)?'\
83
- ' *(?<dst_addr>any|host \S+|\S+\/\d+|\S+ [:\.0-9a-fA-F]+|addrgroup \S+)'\
84
- ' *(?<dst_port>eq \S+|neq \S+|lt \S+|gt \S+|range \S+ \S+|portgroup \S+)?')
79
+ ' *(?<src_addr>any|host \S+|[:\.0-9a-fA-F]+ [:\.0-9a-fA-F]+|[:\.0-9a-fA-F]+\/\d+|addrgroup \S+)'\
80
+ ' *(?<src_port>range \S+ \S+|(lt|eq|gt|neq|portgroup) \S+)?'\
81
+ ' *(?<dst_addr>any|host \S+|[:\.0-9a-fA-F]+ [:\.0-9a-fA-F]+|[:\.0-9a-fA-F]+\/\d+|addrgroup \S+)'\
82
+ ' *(?<dst_port>range \S+ \S+|(lt|eq|gt|neq|portgroup) \S+)?'\
83
+ ' *(?<tcp_flags>(ack *|fin *|urg *|syn *|psh *|rst *)*)?'\
84
+ ' *(?<established>established)?'\
85
+ ' *(?<precedence>precedence \S+)?'\
86
+ ' *(?<dscp>dscp \S+)?'\
87
+ ' *(?<time_range>time-range \S+)?'\
88
+ ' *(?<packet_length>packet-length (range \d+ \d+|(lt|eq|gt|neq) \d+))?'\
89
+ ' *(?<ttl>ttl \d+)?'\
90
+ ' *(?<http_method>http-method (\d+|connect|delete|get|head|post|put|trace))?'\
91
+ ' *(?<tcp_option_length>tcp-option-length \d+)?'\
92
+ ' *(?<redirect>redirect \S+)?'\
93
+ ' *(?<log>log)?')
85
94
  # rubocop:enable Metrics/LineLength
86
95
  regexp.match(str)
87
96
  end
@@ -99,22 +108,64 @@ module Cisco
99
108
 
100
109
  if attrs[:remark]
101
110
  cmd = 'ace_remark'
111
+ set_args_keys(attrs)
102
112
  else
103
113
  cmd = 'ace'
114
+ set_args_keys_default
115
+ set_args_keys(attrs)
104
116
  [:action,
105
117
  :proto,
106
118
  :src_addr,
107
119
  :src_port,
108
120
  :dst_addr,
109
121
  :dst_port,
122
+ :tcp_flags,
123
+ :established,
124
+ :precedence,
125
+ :dscp,
126
+ :time_range,
127
+ :packet_length,
128
+ :ttl,
129
+ :http_method,
130
+ :tcp_option_length,
131
+ :redirect,
132
+ :log,
110
133
  ].each do |p|
111
134
  attrs[p] = '' if attrs[p].nil?
135
+ send(p.to_s + '=', attrs[p])
112
136
  end
137
+ @get_args = @set_args
113
138
  end
114
- set_args_keys(attrs)
115
139
  config_set('acl', cmd, @set_args)
116
140
  end
117
141
 
142
+ # UTILITY FUNCTIONS
143
+ # -----------------
144
+
145
+ # extract value of property from ace
146
+ def extract_value(prop, prefix=nil)
147
+ prefix = prop if prefix.nil?
148
+ ace_match = ace_get
149
+
150
+ # matching ace not found
151
+ return nil if ace_match.nil? # no matching ace found
152
+
153
+ # property not defined for matching ace
154
+ return nil unless ace_match.names.include?(prop)
155
+
156
+ # extract and return value that follows prefix + <space>
157
+ regexp = Regexp.new("#{Regexp.escape(prefix)} (?<extracted>.*)")
158
+ value_match = regexp.match(ace_match[prop])
159
+ return nil if value_match.nil?
160
+ value_match[:extracted]
161
+ end
162
+
163
+ # prepend property name prefix/keyword to value
164
+ def attach_prefix(val, prop, prefix=nil)
165
+ prefix = prop.to_s if prefix.nil?
166
+ @set_args[prop] = val.to_s.empty? ? val : "#{prefix} #{val}"
167
+ end
168
+
118
169
  # PROPERTIES
119
170
  # ----------
120
171
  def seqno
@@ -155,8 +206,11 @@ module Cisco
155
206
 
156
207
  def src_addr
157
208
  match = ace_get
158
- return nil if match.nil?
159
- match.names.include?('src_addr') ? match[:src_addr] : nil
209
+ return nil if match.nil? || !match.names.include?('src_addr')
210
+ addr = match[:src_addr]
211
+ # Normalize addr. Some platforms zero_pad ipv6 addrs.
212
+ addr.gsub!(/^0*/, '').gsub!(/:0*/, ':')
213
+ addr
160
214
  end
161
215
 
162
216
  def src_addr=(src_addr)
@@ -175,8 +229,11 @@ module Cisco
175
229
 
176
230
  def dst_addr
177
231
  match = ace_get
178
- return nil if match.nil?
179
- match.names.include?('dst_addr') ? match[:dst_addr] : nil
232
+ return nil if match.nil? || !match.names.include?('dst_addr')
233
+ addr = match[:dst_addr]
234
+ # Normalize addr. Some platforms zero_pad ipv6 addrs.
235
+ addr.gsub!(/^0*/, '').gsub!(/:0*/, ':')
236
+ addr
180
237
  end
181
238
 
182
239
  def dst_addr=(dst_addr)
@@ -192,5 +249,101 @@ module Cisco
192
249
  def dst_port=(src_port)
193
250
  @set_args[:dst_port] = src_port
194
251
  end
252
+
253
+ def tcp_flags
254
+ match = ace_get
255
+ return nil if match.nil?
256
+ match.names.include?('tcp_flags') ? match[:tcp_flags].strip : nil
257
+ end
258
+
259
+ def tcp_flags=(tcp_flags)
260
+ @set_args[:tcp_flags] = tcp_flags.strip
261
+ end
262
+
263
+ def established
264
+ match = ace_get
265
+ return false if match.nil?
266
+ return false unless match.names.include?('established')
267
+ match[:established] == 'established' ? true : false
268
+ end
269
+
270
+ def established=(established)
271
+ @set_args[:established] = established.to_s == 'true' ? 'established' : ''
272
+ end
273
+
274
+ def precedence
275
+ extract_value('precedence')
276
+ end
277
+
278
+ def precedence=(precedence)
279
+ attach_prefix(precedence, :precedence)
280
+ end
281
+
282
+ def dscp
283
+ extract_value('dscp')
284
+ end
285
+
286
+ def dscp=(dscp)
287
+ attach_prefix(dscp, :dscp)
288
+ end
289
+
290
+ def time_range
291
+ extract_value('time_range', 'time-range')
292
+ end
293
+
294
+ def time_range=(time_range)
295
+ attach_prefix(time_range, :time_range, 'time-range')
296
+ end
297
+
298
+ def packet_length
299
+ extract_value('packet_length', 'packet-length')
300
+ end
301
+
302
+ def packet_length=(packet_length)
303
+ attach_prefix(packet_length, :packet_length, 'packet-length')
304
+ end
305
+
306
+ def ttl
307
+ extract_value('ttl')
308
+ end
309
+
310
+ def ttl=(ttl)
311
+ attach_prefix(ttl, :ttl)
312
+ end
313
+
314
+ def http_method
315
+ extract_value('http_method', 'http-method')
316
+ end
317
+
318
+ def http_method=(http_method)
319
+ attach_prefix(http_method, :http_method, 'http-method')
320
+ end
321
+
322
+ def tcp_option_length
323
+ extract_value('tcp_option_length', 'tcp-option-length')
324
+ end
325
+
326
+ def tcp_option_length=(tcp_option_length)
327
+ attach_prefix(tcp_option_length, :tcp_option_length, 'tcp-option-length')
328
+ end
329
+
330
+ def redirect
331
+ extract_value('redirect')
332
+ end
333
+
334
+ def redirect=(redirect)
335
+ attach_prefix(redirect, :redirect)
336
+ end
337
+
338
+ def log
339
+ match = ace_get
340
+ return false if match.nil?
341
+ return false unless match.names.include?('log')
342
+ match[:log] == 'log' ? true : false
343
+ end
344
+
345
+ def log=(log)
346
+ @set_args[:log] = log.to_s == 'true' ? 'log' : ''
347
+ end
195
348
  end
196
349
  end
@@ -45,7 +45,8 @@ module Cisco
45
45
  def self.afi_cli(afi)
46
46
  fail ArgumentError, "Argument afi must be 'ipv4' or 'ipv6'" unless
47
47
  afi[/(ipv4|ipv6)/]
48
- afi[/ipv4/] ? 'ip' : afi
48
+ afi = 'ip' if platform == :nexus && afi[/ipv4/]
49
+ afi
49
50
  end
50
51
 
51
52
  def create
@@ -14,9 +14,10 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
+ require_relative 'cisco_cmn_utils'
17
18
  require_relative 'node_util'
18
19
  require_relative 'feature'
19
- require_relative 'bgp_af'
20
+ require_relative 'logger'
20
21
 
21
22
  module Cisco
22
23
  # RouterBgp - node utility class for BGP general config management
@@ -32,6 +33,10 @@ module Cisco
32
33
  create if instantiate
33
34
  end
34
35
 
36
+ def to_s
37
+ "BGP #{asnum} VRF '#{vrf}'"
38
+ end
39
+
35
40
  # Create a hash of all router bgp default and non-default
36
41
  # vrf instances
37
42
  def self.routers
@@ -80,8 +85,9 @@ module Cisco
80
85
 
81
86
  # Create one router bgp instance
82
87
  def create
83
- Feature.bgp_enable
88
+ Feature.bgp_enable if platform == :nexus
84
89
  router_bgp
90
+ wait_for_process_initialized
85
91
  end
86
92
 
87
93
  # Destroy router bgp instance
@@ -89,6 +95,24 @@ module Cisco
89
95
  router_bgp('no')
90
96
  end
91
97
 
98
+ def process_initialized?
99
+ config_get('bgp', 'process_initialized')
100
+ end
101
+
102
+ def wait_for_process_initialized
103
+ return unless node.product_id[/N(5|6)/]
104
+
105
+ # Hack for slow-start platforms which will have setter failures if the
106
+ # bgp instance is still initializing. To see this problem in a sandbox
107
+ # do 'router bgp 1 ; router bgp 1 ; shutdown'.
108
+ 4.times do
109
+ return if process_initialized?
110
+ sleep 1
111
+ node.cache_flush
112
+ end
113
+ fail 'BGP process is not initialized yet'
114
+ end
115
+
92
116
  # Helper method to delete @set_args hash keys
93
117
  def set_args_keys_default
94
118
  @set_args = { asnum: @asnum }
@@ -98,6 +122,12 @@ module Cisco
98
122
 
99
123
  # Attributes:
100
124
 
125
+ # nsr Getter
126
+ def nsr
127
+ return nil if platform == :ios_xr && @vrf != 'default'
128
+ config_get('bgp', 'nsr', @get_args)
129
+ end
130
+
101
131
  # Bestpath Getters
102
132
  def bestpath_always_compare_med
103
133
  config_get('bgp', 'bestpath_always_compare_med', @get_args)
@@ -116,6 +146,7 @@ module Cisco
116
146
  end
117
147
 
118
148
  def bestpath_med_confed
149
+ return nil if platform == :ios_xr && @vrf != 'default'
119
150
  config_get('bgp', 'bestpath_med_confed', @get_args)
120
151
  end
121
152
 
@@ -127,6 +158,17 @@ module Cisco
127
158
  config_get('bgp', 'bestpath_med_non_deterministic', @get_args)
128
159
  end
129
160
 
161
+ # nsr Setter
162
+ def nsr=(enable)
163
+ if platform == :ios_xr && @vrf != 'default'
164
+ fail Cisco::UnsupportedError.new('bgp', 'nsr', 'set', 'nsr is not ' \
165
+ 'configurable on a per-VRF basis on ios_xr')
166
+ end
167
+ @set_args[:state] = (enable ? '' : 'no')
168
+ config_set('bgp', 'nsr', @set_args)
169
+ set_args_keys_default
170
+ end
171
+
130
172
  # Bestpath Setters
131
173
  def bestpath_always_compare_med=(enable)
132
174
  @set_args[:state] = (enable ? '' : 'no')
@@ -153,6 +195,12 @@ module Cisco
153
195
  end
154
196
 
155
197
  def bestpath_med_confed=(enable)
198
+ if platform == :ios_xr && @vrf != 'default'
199
+ fail Cisco::UnsupportedError.new('bgp', 'bestpath_med_confed', 'set',
200
+ 'bestpath_med_confed is not ' \
201
+ 'configurable on a per-VRF basis ' \
202
+ 'on IOS XR')
203
+ end
156
204
  @set_args[:state] = (enable ? '' : 'no')
157
205
  config_set('bgp', 'bestpath_med_confed', @set_args)
158
206
  set_args_keys_default
@@ -170,6 +218,12 @@ module Cisco
170
218
  set_args_keys_default
171
219
  end
172
220
 
221
+ # nsr Default
222
+ def default_nsr
223
+ return nil if platform == :ios_xr && @vrf != 'default'
224
+ config_get_default('bgp', 'nsr')
225
+ end
226
+
173
227
  # Bestpath Defaults
174
228
  def default_bestpath_always_compare_med
175
229
  config_get_default('bgp', 'bestpath_always_compare_med')
@@ -188,6 +242,7 @@ module Cisco
188
242
  end
189
243
 
190
244
  def default_bestpath_med_confed
245
+ return nil if platform == :ios_xr && @vrf != 'default'
191
246
  config_get_default('bgp', 'bestpath_med_confed')
192
247
  end
193
248
 
@@ -201,6 +256,7 @@ module Cisco
201
256
 
202
257
  # Cluster Id (Getter/Setter/Default)
203
258
  def cluster_id
259
+ return nil if platform == :ios_xr && @vrf != 'default'
204
260
  config_get('bgp', 'cluster_id', @get_args)
205
261
  end
206
262
 
@@ -208,7 +264,11 @@ module Cisco
208
264
  # In order to remove a bgp cluster_id you cannot simply issue
209
265
  # 'no bgp cluster-id'. IMO this should be possible because you
210
266
  # can only configure a single bgp cluster-id.
211
- #
267
+ if platform == :ios_xr && @vrf != 'default'
268
+ fail Cisco::UnsupportedError.new('bgp', 'cluster_id', 'set',
269
+ 'cluster-id is not configurable ' \
270
+ 'on a per-VRF basis on IOS XR')
271
+ end
212
272
  # HACK: specify a dummy id when removing the property.
213
273
  dummy_id = 1
214
274
  if id == default_cluster_id
@@ -223,11 +283,13 @@ module Cisco
223
283
  end
224
284
 
225
285
  def default_cluster_id
286
+ return nil if platform == :ios_xr && @vrf != 'default'
226
287
  config_get_default('bgp', 'cluster_id')
227
288
  end
228
289
 
229
290
  # Confederation Id (Getter/Setter/Default)
230
291
  def confederation_id
292
+ return nil if platform == :ios_xr && @vrf != 'default'
231
293
  config_get('bgp', 'confederation_id', @get_args)
232
294
  end
233
295
 
@@ -235,7 +297,12 @@ module Cisco
235
297
  # In order to remove a bgp confed id you cannot simply issue
236
298
  # 'no bgp confederation id'. IMO this should be possible
237
299
  # because you can only configure a single bgp confed id.
238
- #
300
+ if platform == :ios_xr && @vrf != 'default'
301
+ fail Cisco::UnsupportedError.new('bgp', 'confederation_id', 'set',
302
+ 'confederation-id is not ' \
303
+ 'configurable ' \
304
+ 'on a per-VRF basis on IOS XR')
305
+ end
239
306
  # HACK: specify a dummy id when removing the property.
240
307
  dummy_id = 1
241
308
  if id == default_confederation_id
@@ -250,6 +317,7 @@ module Cisco
250
317
  end
251
318
 
252
319
  def default_confederation_id
320
+ return nil if platform == :ios_xr && @vrf != 'default'
253
321
  config_get_default('bgp', 'confederation_id')
254
322
  end
255
323
 
@@ -324,6 +392,14 @@ module Cisco
324
392
  end
325
393
 
326
394
  def enforce_first_as=(enable)
395
+ # TODO: write a helper method for this repeated logic
396
+ # enforce_first_as is on by default (=>true)
397
+ # XR=>true = enable enforce_first_as = 'no bgp enforce-first-as disable'
398
+ # XR=>false = disable enforce_first_as = 'bgp enforce-first-as disable'
399
+ # Nexus nvgens the 'no' command.
400
+ # Nexus=>true = enable enforce_first_as = 'enforce-first-as'
401
+ # Nexus=>false = disable enforce_first_as = 'no enforce-first-as'
402
+ enable = !enable if platform == :ios_xr
327
403
  @set_args[:state] = (enable ? '' : 'no')
328
404
  config_set('bgp', 'enforce_first_as', @set_args)
329
405
  set_args_keys_default
@@ -433,6 +509,14 @@ module Cisco
433
509
  end
434
510
 
435
511
  def fast_external_fallover=(enable)
512
+ # TODO: write a helper method for this repeated logic
513
+ # fast_external_fallover is on by default (=>true)
514
+ # XR=>true = 'no bgp fast-external-fallover disable'
515
+ # XR=>false = 'bgp fast-external-fallover disable'
516
+ # Nexus nvgens the 'no' command.
517
+ # Nexus=>true = 'fast-external-fallover'
518
+ # Nexus=>false = 'no fast-external-fallover'
519
+ enable = !enable if platform == :ios_xr
436
520
  @set_args[:state] = (enable ? '' : 'no')
437
521
  config_set('bgp', 'fast_external_fallover', @set_args)
438
522
  set_args_keys_default
@@ -459,54 +543,92 @@ module Cisco
459
543
 
460
544
  # Confederation Peers (Getter/Setter/Default)
461
545
  def confederation_peers
462
- config_get('bgp', 'confederation_peers', @get_args)
463
- end
464
-
465
- def confederation_peers_set(peers)
466
- # The confederation peers command is additive so we first need to
467
- # remove any existing peers.
468
- unless confederation_peers.empty?
469
- @set_args[:state] = 'no'
470
- @set_args[:peer_list] = confederation_peers
471
- config_set('bgp', 'confederation_peers', @set_args)
546
+ # NX: confederation peers is retrieved as a string '1 2 3'
547
+ # XR: retrieved as an array.
548
+ # So make it an array in the NX case.
549
+ # Sort the end results to make it consistent across both platforms.
550
+ return nil if platform == :ios_xr && @vrf != 'default'
551
+ peers = config_get('bgp', 'confederation_peers', @get_args)
552
+ peers = peers.split(' ') if peers.is_a?(String)
553
+ peers.sort
554
+ end
555
+
556
+ def confederation_peers=(should)
557
+ # confederation peers are additive. So create a delta hash of entries
558
+ # and only apply the changes
559
+ if platform == :ios_xr && @vrf != 'default'
560
+ fail Cisco::UnsupportedError.new('bgp', 'confederation_peers', 'set',
561
+ 'confederation-peers is not ' \
562
+ 'configurable ' \
563
+ 'on a per-VRF basis on IOS XR')
472
564
  end
473
- unless peers == default_confederation_peers
474
- @set_args[:state] = ''
475
- @set_args[:peer_list] = peers
476
- config_set('bgp', 'confederation_peers', @set_args)
565
+ should = should.flatten
566
+ is = confederation_peers
567
+
568
+ delta_hash = Utils.delta_add_remove(should, is)
569
+ return if delta_hash.values.flatten.empty?
570
+ [:add, :remove].each do |action|
571
+ Cisco::Logger.debug('confederation_peers delta ' \
572
+ "#{@get_args}\n #{action}: " \
573
+ "#{delta_hash[action]}")
574
+ delta_hash[action].each do |peer|
575
+ state = (action == :add) ? '' : 'no'
576
+ @set_args[:state] = state
577
+ @set_args[:peer] = peer
578
+
579
+ config_set('bgp', 'confederation_peers', @set_args)
580
+ end
477
581
  end
478
- set_args_keys_default
479
582
  end
480
583
 
481
584
  def default_confederation_peers
585
+ return nil if platform == :ios_xr && @vrf != 'default'
482
586
  config_get_default('bgp', 'confederation_peers')
483
587
  end
484
588
 
485
589
  # Graceful Restart Getters
486
590
  def graceful_restart
591
+ return nil if platform == :ios_xr && @vrf != 'default'
487
592
  config_get('bgp', 'graceful_restart', @get_args)
488
593
  end
489
594
 
490
595
  def graceful_restart_timers_restart
596
+ return nil if platform == :ios_xr && @vrf != 'default'
491
597
  config_get('bgp', 'graceful_restart_timers_restart', @get_args)
492
598
  end
493
599
 
494
600
  def graceful_restart_timers_stalepath_time
601
+ return nil if platform == :ios_xr && @vrf != 'default'
495
602
  config_get('bgp', 'graceful_restart_timers_stalepath_time', @get_args)
496
603
  end
497
604
 
498
605
  def graceful_restart_helper
606
+ return nil if platform == :ios_xr && @vrf != 'default'
499
607
  config_get('bgp', 'graceful_restart_helper', @get_args)
500
608
  end
501
609
 
502
610
  # Graceful Restart Setters
503
611
  def graceful_restart=(enable)
612
+ if platform == :ios_xr && @vrf != 'default'
613
+ fail Cisco::UnsupportedError.new('bgp', 'graceful_restart', 'set',
614
+ 'graceful_restart is not ' \
615
+ 'configurable ' \
616
+ 'on a per-VRF basis on IOS XR')
617
+ end
504
618
  @set_args[:state] = (enable ? '' : 'no')
505
619
  config_set('bgp', 'graceful_restart', @set_args)
506
620
  set_args_keys_default
507
621
  end
508
622
 
509
623
  def graceful_restart_timers_restart=(seconds)
624
+ if platform == :ios_xr && @vrf != 'default'
625
+ fail Cisco::UnsupportedError.new('bgp',
626
+ 'graceful_restart_timers_restart',
627
+ 'set',
628
+ 'graceful_restart_timers_restart is ' \
629
+ 'not configurable ' \
630
+ 'on a per-VRF basis on IOS XR')
631
+ end
510
632
  if seconds == default_graceful_restart_timers_restart
511
633
  @set_args[:state] = 'no'
512
634
  @set_args[:seconds] = ''
@@ -519,6 +641,14 @@ module Cisco
519
641
  end
520
642
 
521
643
  def graceful_restart_timers_stalepath_time=(seconds)
644
+ if platform == :ios_xr && @vrf != 'default'
645
+ fail Cisco::UnsupportedError.new('bgp',
646
+ 'graceful_restart_timers_' \
647
+ 'stalepath_time', 'set',
648
+ 'graceful_restart_timers_' \
649
+ 'stalepath_time is not configurable ' \
650
+ 'on a per-VRF basis on IOS XR')
651
+ end
522
652
  if seconds == default_graceful_restart_timers_stalepath_time
523
653
  @set_args[:state] = 'no'
524
654
  @set_args[:seconds] = ''
@@ -531,6 +661,13 @@ module Cisco
531
661
  end
532
662
 
533
663
  def graceful_restart_helper=(enable)
664
+ if platform == :ios_xr && @vrf != 'default'
665
+ fail Cisco::UnsupportedError.new('bgp',
666
+ 'graceful_restart_helper', 'set',
667
+ 'graceful_restart_helper ' \
668
+ 'is not configurable ' \
669
+ 'on a per-VRF basis on IOS XR')
670
+ end
534
671
  @set_args[:state] = (enable ? '' : 'no')
535
672
  config_set('bgp', 'graceful_restart_helper', @set_args)
536
673
  set_args_keys_default
@@ -538,18 +675,22 @@ module Cisco
538
675
 
539
676
  # Graceful Restart Defaults
540
677
  def default_graceful_restart
678
+ return nil if platform == :ios_xr && @vrf != 'default'
541
679
  config_get_default('bgp', 'graceful_restart')
542
680
  end
543
681
 
544
682
  def default_graceful_restart_timers_restart
683
+ return nil if platform == :ios_xr && @vrf != 'default'
545
684
  config_get_default('bgp', 'graceful_restart_timers_restart')
546
685
  end
547
686
 
548
687
  def default_graceful_restart_timers_stalepath_time
688
+ return nil if platform == :ios_xr && @vrf != 'default'
549
689
  config_get_default('bgp', 'graceful_restart_timers_stalepath_time')
550
690
  end
551
691
 
552
692
  def default_graceful_restart_helper
693
+ return nil if platform == :ios_xr && @vrf != 'default'
553
694
  config_get_default('bgp', 'graceful_restart_helper')
554
695
  end
555
696
 
@@ -595,6 +736,13 @@ module Cisco
595
736
  end
596
737
 
597
738
  def log_neighbor_changes=(enable)
739
+ # XR logging is on by default (=>true)
740
+ # XR=>true = enable logging = 'no bgp log neighbor changes disable'
741
+ # XR=>false = disable logging = 'bgp log neighbor changes disable'
742
+ # Nexus logging is off by default (=>false)
743
+ # Nexus=>true = enable logging = 'log-neighbor-changes'
744
+ # Nexus=>false = disable logging = 'no log-neighbor-changes'
745
+ enable = !enable if platform == :ios_xr
598
746
  @set_args[:state] = (enable ? '' : 'no')
599
747
  config_set('bgp', 'log_neighbor_changes', @set_args)
600
748
  set_args_keys_default
@@ -643,14 +791,26 @@ module Cisco
643
791
  # route_distinguisher
644
792
  # Note that this property is supported by both bgp and vrf providers.
645
793
  def route_distinguisher
794
+ return nil if @vrf.nil? || @vrf == 'default'
646
795
  config_get('bgp', 'route_distinguisher', @get_args)
647
796
  end
648
797
 
649
798
  def route_distinguisher=(rd)
650
- Feature.nv_overlay_evpn_enable
799
+ if @vrf.nil? || @vrf == 'default'
800
+ fail Cisco::UnsupportedError.new('bgp', 'route_distinguisher', 'set',
801
+ 'route_distinguisher is not ' \
802
+ 'configurable on a default VRF')
803
+ end
804
+
805
+ # N3k I2 images require 'nv overlay evpn' for rd and also require
806
+ # explicit values when removing the rd command. These restrictions are
807
+ # not not needed in I3 and newer images.
808
+ Feature.nv_overlay_evpn_enable if Utils.nexus_i2_image
809
+
651
810
  if rd == default_route_distinguisher
811
+ return if route_distinguisher.empty?
652
812
  @set_args[:state] = 'no'
653
- @set_args[:rd] = ''
813
+ @set_args[:rd] = route_distinguisher
654
814
  else
655
815
  @set_args[:state] = ''
656
816
  @set_args[:rd] = rd
@@ -660,6 +820,7 @@ module Cisco
660
820
  end
661
821
 
662
822
  def default_route_distinguisher
823
+ return nil if @vrf.nil? || @vrf == 'default'
663
824
  config_get_default('bgp', 'route_distinguisher')
664
825
  end
665
826
 
@@ -792,10 +953,12 @@ module Cisco
792
953
  end
793
954
 
794
955
  def default_timer_bestpath_limit
956
+ return nil if platform == :ios_xr && @vrf != 'default'
795
957
  config_get_default('bgp', 'timer_bestpath_limit')
796
958
  end
797
959
 
798
960
  def default_timer_bestpath_limit_always
961
+ return nil if platform == :ios_xr && @vrf != 'default'
799
962
  config_get_default('bgp', 'timer_bestpath_limit_always')
800
963
  end
801
964
  end