cisco_node_utils 2.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -0
  3. data/lib/cisco_node_utils/bfd_global.rb +4 -0
  4. data/lib/cisco_node_utils/cisco_cmn_utils.rb +25 -0
  5. data/lib/cisco_node_utils/cmd_ref/interface.yaml +18 -18
  6. data/lib/cisco_node_utils/cmd_ref/interface_channel_group.yaml +4 -1
  7. data/lib/cisco_node_utils/cmd_ref/interface_evpn_multisite.yaml +1 -1
  8. data/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +17 -15
  9. data/lib/cisco_node_utils/interface.rb +117 -118
  10. data/lib/cisco_node_utils/interface_channel_group.rb +17 -8
  11. data/lib/cisco_node_utils/interface_evpn_multisite.rb +15 -6
  12. data/lib/cisco_node_utils/interface_ospf.rb +126 -102
  13. data/lib/cisco_node_utils/itd_service.rb +8 -0
  14. data/lib/cisco_node_utils/node.rb +0 -1
  15. data/lib/cisco_node_utils/platform.rb +16 -32
  16. data/lib/cisco_node_utils/version.rb +1 -1
  17. data/lib/cisco_node_utils/vlan.rb +1 -2
  18. data/lib/cisco_node_utils/vxlan_vtep.rb +1 -1
  19. data/tests/test_interface.rb +74 -13
  20. data/tests/test_interface_bdi.rb +2 -2
  21. data/tests/test_interface_channel_group.rb +24 -17
  22. data/tests/test_interface_evpn_multisite.rb +35 -0
  23. data/tests/test_interface_ospf.rb +71 -3
  24. data/tests/test_itd_service.rb +16 -4
  25. data/tests/test_node_ext.rb +4 -1
  26. data/tests/test_portchannel_global.rb +3 -0
  27. data/tests/test_router_ospf_vrf.rb +2 -34
  28. data/tests/test_stp_global.rb +4 -0
  29. metadata +3 -6
  30. data/lib/cisco_node_utils/cmd_ref/DEPRECATED.yaml +0 -118
  31. data/lib/cisco_node_utils/interface_DEPRECATED.rb +0 -518
  32. data/lib/cisco_node_utils/vlan_DEPRECATED.rb +0 -108
@@ -21,39 +21,48 @@ require_relative 'feature'
21
21
  module Cisco
22
22
  # Interface - node utility class for general interface config management
23
23
  class InterfaceChannelGroup < NodeUtil
24
- attr_reader :name
24
+ attr_reader :name, :show_name
25
25
 
26
- def initialize(name)
27
- validate_args(name)
26
+ def initialize(name, show_name=nil)
27
+ validate_args(name, show_name)
28
28
  end
29
29
 
30
30
  def to_s
31
31
  "interface_channel_group #{name}"
32
32
  end
33
33
 
34
- def self.interfaces
34
+ def self.interfaces(show_name=nil)
35
35
  hash = {}
36
- all = config_get('interface_channel_group', 'all_interfaces')
36
+ show_name = Utils.normalize_intf_pattern(show_name)
37
+ begin
38
+ all = config_get('interface_channel_group', 'all_interfaces',
39
+ show_name: show_name)
40
+ rescue CliError => e
41
+ raise unless show_name
42
+ # ignore logical interfaces that do not exist
43
+ debug 'InterfaceChannelGroup.interfaces ignoring CliError => ' + e.to_s
44
+ end
37
45
  return hash if all.nil?
38
46
 
39
47
  all.each do |id|
40
48
  id = id.downcase
41
- hash[id] = InterfaceChannelGroup.new(id)
49
+ hash[id] = InterfaceChannelGroup.new(id, show_name)
42
50
  end
43
51
  hash
44
52
  end
45
53
 
46
- def validate_args(name)
54
+ def validate_args(name, show_name)
47
55
  fail TypeError unless name.is_a?(String)
48
56
  fail ArgumentError unless name.length > 0
49
57
  fail "channel_group is not supported on #{name}" unless
50
58
  name[/Ethernet/i]
51
59
  @name = name.downcase
60
+ @show_name = show_name.nil? ? '' : Utils.normalize_intf_pattern(show_name)
52
61
  set_args_keys
53
62
  end
54
63
 
55
64
  def set_args_keys(hash={}) # rubocop:disable Style/AccessorMethodName
56
- @get_args = { name: @name }
65
+ @get_args = { name: @name, show_name: @show_name }
57
66
  @set_args = @get_args.merge!(hash) unless hash.empty?
58
67
  end
59
68
 
@@ -19,22 +19,31 @@ require_relative 'node_util'
19
19
  module Cisco
20
20
  # node_utils class for interface_evpn_multisite
21
21
  class InterfaceEvpnMultisite < NodeUtil
22
- attr_reader :interface, :tracking
22
+ attr_reader :interface, :show_name, :tracking
23
23
 
24
- def initialize(interface)
24
+ def initialize(interface, show_name=nil)
25
25
  fail TypeError unless interface.is_a?(String)
26
26
  @interface = interface.downcase
27
- @get_args = @set_args = { interface: @interface }
27
+ @show_name = show_name.nil? ? '' : Utils.normalize_intf_pattern(show_name)
28
+ @get_args = @set_args = { interface: @interface, show_name: @show_name }
28
29
  end
29
30
 
30
- def self.interfaces
31
+ def self.interfaces(show_name=nil)
31
32
  hash = {}
32
- intf_list = config_get('interface_evpn_multisite', 'all_interfaces')
33
+ show_name = Utils.normalize_intf_pattern(show_name)
34
+ begin
35
+ intf_list = config_get('interface_evpn_multisite', 'all_interfaces',
36
+ show_name: show_name)
37
+ rescue CliError => e
38
+ raise unless show_name
39
+ # ignore logical interfaces that do not exist
40
+ debug 'InterfaceEvpnMultisite.interfaces ignoring CliError => ' + e.to_s
41
+ end
33
42
  return hash if intf_list.nil?
34
43
 
35
44
  intf_list.each do |id|
36
45
  id = id.downcase
37
- intf = InterfaceEvpnMultisite.new(id)
46
+ intf = InterfaceEvpnMultisite.new(id, show_name)
38
47
  hash[id] = intf if intf.tracking
39
48
  end
40
49
  hash
@@ -23,53 +23,66 @@ require_relative 'interface'
23
23
  module Cisco
24
24
  # InterfaceOspf - node utility class for per-interface OSPF config management
25
25
  class InterfaceOspf < NodeUtil
26
- attr_reader :interface, :ospf_name
26
+ attr_reader :intf_name, :ospf_name, :area, :show_name
27
27
 
28
- def initialize(int_name, ospf_name, area, create=true)
29
- fail TypeError unless int_name.is_a? String
28
+ def initialize(intf_name, ospf_name, area, create=true, show_name=nil)
29
+ fail TypeError unless intf_name.is_a? String
30
30
  fail TypeError unless ospf_name.is_a? String
31
31
  fail TypeError unless area.is_a? String
32
- fail ArgumentError unless int_name.length > 0
32
+ fail ArgumentError unless intf_name.length > 0
33
33
  fail ArgumentError unless ospf_name.length > 0
34
34
  fail ArgumentError unless area.length > 0
35
35
 
36
36
  # normalize
37
- int_name = int_name.downcase
38
- @interface = Interface.interfaces[int_name]
39
- fail "interface #{int_name} does not exist" if @interface.nil?
40
-
37
+ @intf_name = intf_name.downcase
38
+ @show_name = show_name.nil? ? '' : Utils.normalize_intf_pattern(show_name)
39
+ fail "interface #{@intf_name} does not exist" if
40
+ Interface.interfaces(nil, @intf_name)[@intf_name].nil?
41
41
  @ospf_name = ospf_name
42
+ @area = area
43
+ @get_args = { name: intf_name, show_name: @show_name }
44
+ set_args_keys_default
42
45
 
43
46
  return unless create
44
47
  Feature.ospf_enable
48
+ self.area = area
49
+ end
45
50
 
46
- config_set('interface_ospf', 'area', @interface.name,
47
- '', @ospf_name, area)
51
+ def set_args_keys_default
52
+ @set_args = { name: @intf_name, ospf_name: @ospf_name, area: @area }
48
53
  end
49
54
 
50
55
  # can't re-use Interface.interfaces because we need to filter based on
51
56
  # "ip router ospf <name>", which Interface doesn't retrieve
52
- def self.interfaces(ospf_name=nil)
57
+ def self.interfaces(ospf_name=nil, show_name=nil)
53
58
  fail TypeError unless ospf_name.is_a?(String) || ospf_name.nil?
54
59
  ints = {}
55
-
56
- intf_list = config_get('interface_ospf', 'all_interfaces')
60
+ show_name = Utils.normalize_intf_pattern(show_name)
61
+ begin
62
+ intf_list = config_get('interface_ospf', 'all_interfaces',
63
+ show_name: show_name)
64
+ rescue CliError => e
65
+ raise unless show_name
66
+ # ignore logical interfaces that do not exist
67
+ debug 'InterfaceOspf.interfaces ignoring CliError => ' + e.to_s
68
+ end
57
69
  return ints if intf_list.nil?
58
70
  intf_list.each do |name|
59
- match = config_get('interface_ospf', 'area', name)
71
+ # Find interfaces with 'ip router ospf <name> area <area>'
72
+ match = config_get('interface_ospf', 'area',
73
+ name: name, show_name: show_name)
60
74
  next if match.nil?
61
- # ip router ospf <name> area <area>
62
75
  ospf = match[0]
63
76
  area = match[1]
64
77
  next unless ospf_name.nil? || ospf == ospf_name
65
78
  int = name.downcase
66
- ints[int] = InterfaceOspf.new(int, ospf, area, false)
79
+ ints[int] = InterfaceOspf.new(int, ospf, area, false, show_name)
67
80
  end
68
81
  ints
69
82
  end
70
83
 
71
84
  def area
72
- match = config_get('interface_ospf', 'area', @interface.name)
85
+ match = config_get('interface_ospf', 'area', @get_args)
73
86
  return nil if match.nil?
74
87
  val = match[1]
75
88
  # Coerce numeric area to the expected dot-decimal format.
@@ -78,20 +91,20 @@ module Cisco
78
91
  end
79
92
 
80
93
  def area=(a)
81
- config_set('interface_ospf', 'area', @interface.name,
82
- '', @ospf_name, a)
94
+ config_set('interface_ospf', 'area',
95
+ @set_args.merge!(state: '', area: a))
96
+ set_args_keys_default
83
97
  end
84
98
 
85
99
  def destroy
86
- config_set('interface_ospf', 'area', @interface.name,
87
- 'no', @ospf_name, area)
100
+ config_set('interface_ospf', 'area', @set_args.merge!(state: 'no'))
101
+ set_args_keys_default
88
102
  # Reset everything else back to default as well:
89
103
  self.message_digest = default_message_digest
90
104
  message_digest_key_set(default_message_digest_key_id, '', '', '')
91
105
  self.cost = default_cost
92
- self.hello_interval = default_hello_interval
93
- config_set('interface_ospf', 'dead_interval',
94
- @interface.name, 'no', '')
106
+ destroy_interval('hello_interval')
107
+ destroy_interval('dead_interval')
95
108
  self.bfd = default_bfd
96
109
  self.mtu_ignore = default_mtu_ignore
97
110
  self.priority = default_priority
@@ -106,15 +119,14 @@ module Cisco
106
119
  end
107
120
 
108
121
  def message_digest
109
- config_get('interface_ospf', 'message_digest', @interface.name)
122
+ config_get('interface_ospf', 'message_digest', @get_args)
110
123
  end
111
124
 
112
- # interface %s
113
- # %s ip ospf authentication message-digest
114
125
  def message_digest=(enable)
115
126
  return if enable == message_digest
116
- config_set('interface_ospf', 'message_digest', @interface.name,
117
- enable ? '' : 'no')
127
+ @set_args[:state] = (enable ? '' : 'no')
128
+ config_set('interface_ospf', 'message_digest', @set_args)
129
+ set_args_keys_default
118
130
  end
119
131
 
120
132
  def default_message_digest_key_id
@@ -122,7 +134,7 @@ module Cisco
122
134
  end
123
135
 
124
136
  def message_digest_key_id
125
- config_get('interface_ospf', 'message_digest_key_id', @interface.name)
137
+ config_get('interface_ospf', 'message_digest_key_id', @get_args)
126
138
  end
127
139
 
128
140
  def default_message_digest_algorithm_type
@@ -132,7 +144,7 @@ module Cisco
132
144
 
133
145
  def message_digest_algorithm_type
134
146
  match = config_get('interface_ospf', 'message_digest_alg_type',
135
- @interface.name)
147
+ @get_args)
136
148
  match.to_sym
137
149
  end
138
150
 
@@ -143,101 +155,113 @@ module Cisco
143
155
 
144
156
  def message_digest_encryption_type
145
157
  match = config_get('interface_ospf', 'message_digest_enc_type',
146
- @interface.name)
158
+ @get_args)
147
159
  Encryption.cli_to_symbol(match)
148
160
  end
149
161
 
150
162
  def message_digest_password
151
- config_get('interface_ospf', 'message_digest_password', @interface.name)
163
+ config_get('interface_ospf', 'message_digest_password', @get_args)
152
164
  end
153
165
 
154
166
  def default_message_digest_password
155
167
  config_get_default('interface_ospf', 'message_digest_password')
156
168
  end
157
169
 
158
- # interface %s
159
- # %s ip ospf message-digest-key %d %s %d %s
160
- def message_digest_key_set(keyid, algtype, enctype, enc)
170
+ def message_digest_key_set(keyid, algtype, enctype, password)
161
171
  current_keyid = message_digest_key_id
162
172
  if keyid == default_message_digest_key_id && current_keyid != keyid
163
- config_set('interface_ospf', 'message_digest_key_set',
164
- @interface.name, 'no', current_keyid,
165
- '', '', '')
173
+ @set_args.merge!(state: 'no',
174
+ keyid: current_keyid,
175
+ algtype: '',
176
+ enctype: '',
177
+ password: '')
178
+ config_set('interface_ospf', 'message_digest_key_set', @set_args)
166
179
  elsif keyid != default_message_digest_key_id
167
- fail TypeError unless enc.is_a?(String)
168
- fail ArgumentError unless enc.length > 0
180
+ fail TypeError unless password.is_a?(String)
181
+ fail ArgumentError unless password.length > 0
169
182
  enctype = Encryption.symbol_to_cli(enctype)
170
- config_set('interface_ospf', 'message_digest_key_set',
171
- @interface.name, '', keyid, algtype, enctype, enc)
183
+ @set_args.merge!(state: '',
184
+ keyid: keyid,
185
+ algtype: algtype,
186
+ enctype: enctype,
187
+ password: password)
188
+ config_set('interface_ospf', 'message_digest_key_set', @set_args)
172
189
  end
190
+ set_args_keys_default
173
191
  end
174
192
 
175
193
  def cost
176
- config_get('interface_ospf', 'cost', @interface.name)
194
+ config_get('interface_ospf', 'cost', @get_args)
177
195
  end
178
196
 
179
197
  def default_cost
180
198
  config_get_default('interface_ospf', 'cost')
181
199
  end
182
200
 
183
- # interface %s
184
- # ip ospf cost %d
185
201
  def cost=(c)
186
202
  if c == default_cost
187
- config_set('interface_ospf', 'cost', @interface.name, 'no', '')
203
+ @set_args.merge!(state: 'no', cost: '')
188
204
  else
189
- config_set('interface_ospf', 'cost', @interface.name, '', c)
205
+ @set_args.merge!(state: '', cost: c)
190
206
  end
207
+ config_set('interface_ospf', 'cost', @set_args)
208
+ set_args_keys_default
191
209
  end
192
210
 
193
211
  def hello_interval
194
- config_get('interface_ospf', 'hello_interval', @interface.name)
212
+ config_get('interface_ospf', 'hello_interval', @get_args)
195
213
  end
196
214
 
197
215
  def default_hello_interval
198
216
  config_get_default('interface_ospf', 'hello_interval')
199
217
  end
200
218
 
201
- # interface %s
202
- # ip ospf hello-interval %d
203
219
  def hello_interval=(interval)
204
- config_set('interface_ospf', 'hello_interval',
205
- @interface.name, '', interval.to_i)
220
+ # Previous behavior always sets interval and ignores 'no' cmd
221
+ @set_args.merge!(state: '', interval: interval.to_i)
222
+ config_set('interface_ospf', 'hello_interval', @set_args)
223
+ set_args_keys_default
224
+ end
225
+
226
+ def destroy_interval(prop)
227
+ # Helper to remove cli completely
228
+ @set_args.merge!(state: 'no', interval: '')
229
+ config_set('interface_ospf', prop, @set_args)
230
+ set_args_keys_default
206
231
  end
207
232
 
208
233
  def dead_interval
209
- config_get('interface_ospf', 'dead_interval', @interface.name)
234
+ config_get('interface_ospf', 'dead_interval', @get_args)
210
235
  end
211
236
 
212
237
  def default_dead_interval
213
238
  config_get_default('interface_ospf', 'dead_interval')
214
239
  end
215
240
 
216
- # interface %s
217
- # ip ospf dead-interval %d
218
241
  def dead_interval=(interval)
219
- config_set('interface_ospf', 'dead_interval',
220
- @interface.name, '', interval.to_i)
242
+ # Previous behavior always sets interval and ignores 'no' cmd
243
+ @set_args.merge!(state: '', interval: interval.to_i)
244
+ config_set('interface_ospf', 'dead_interval', @set_args)
245
+ set_args_keys_default
221
246
  end
222
247
 
223
248
  # CLI can be either of the following or none
224
249
  # ip ospf bfd
225
250
  # ip ospf bfd disable
226
251
  def bfd
227
- val = config_get('interface_ospf', 'bfd', @interface.name)
252
+ val = config_get('interface_ospf', 'bfd', @get_args)
228
253
  return if val.nil?
229
254
  val.include?('disable') ? false : true
230
255
  end
231
256
 
232
- # interface %s
233
- # %s ip ospf bfd %s
234
257
  def bfd=(val)
235
258
  return if val == bfd
236
259
  Feature.bfd_enable
237
260
  state = (val == default_bfd) ? 'no' : ''
238
261
  disable = val ? '' : 'disable'
239
- config_set('interface_ospf', 'bfd', @interface.name,
240
- state, disable)
262
+ config_set('interface_ospf', 'bfd',
263
+ @set_args.merge!(state: state, disable: disable))
264
+ set_args_keys_default
241
265
  end
242
266
 
243
267
  def default_bfd
@@ -245,7 +269,7 @@ module Cisco
245
269
  end
246
270
 
247
271
  def default_network_type
248
- case @interface.name
272
+ case @intf_name
249
273
  when /loopback/i
250
274
  lookup = 'network_type_loopback_default'
251
275
  else
@@ -255,14 +279,13 @@ module Cisco
255
279
  end
256
280
 
257
281
  def mtu_ignore
258
- config_get('interface_ospf', 'mtu_ignore', @interface.name)
282
+ config_get('interface_ospf', 'mtu_ignore', @get_args)
259
283
  end
260
284
 
261
- # interface %s
262
- # %s ip ospf mtu-ignore
263
285
  def mtu_ignore=(enable)
264
- config_set('interface_ospf', 'mtu_ignore', @interface.name,
265
- enable ? '' : 'no')
286
+ @set_args[:state] = enable ? '' : 'no'
287
+ config_set('interface_ospf', 'mtu_ignore', @set_args)
288
+ set_args_keys_default
266
289
  end
267
290
 
268
291
  def default_mtu_ignore
@@ -270,20 +293,21 @@ module Cisco
270
293
  end
271
294
 
272
295
  def network_type
273
- type = config_get('interface_ospf', 'network_type', @interface.name)
296
+ type = config_get('interface_ospf', 'network_type', @get_args)
274
297
  return 'p2p' if type == 'point-to-point'
275
298
  return default_network_type if type.nil?
276
299
  type
277
300
  end
278
301
 
279
- # interface %s
280
- # %s ip ospf network %s
281
302
  def network_type=(type)
282
- no_cmd = (type == default_network_type) ? 'no' : ''
283
- network = (type == default_network_type) ? '' : type
284
- network = 'point-to-point' if type.to_s == 'p2p'
285
- config_set('interface_ospf', 'network_type', @interface.name,
286
- no_cmd, network)
303
+ if type == default_network_type
304
+ @set_args.merge!(state: 'no', network_type: '')
305
+ else
306
+ network = 'point-to-point' if type.to_s == 'p2p'
307
+ @set_args.merge!(state: '', network_type: network)
308
+ end
309
+ config_set('interface_ospf', 'network_type', @set_args)
310
+ set_args_keys_default
287
311
  end
288
312
 
289
313
  def default_passive_interface
@@ -291,28 +315,28 @@ module Cisco
291
315
  end
292
316
 
293
317
  def passive_interface
294
- config_get('interface_ospf', 'passive_interface', @interface.name)
318
+ config_get('interface_ospf', 'passive_interface', @get_args)
295
319
  end
296
320
 
297
- # interface %s
298
- # %s ip ospf passive-interface
299
321
  def passive_interface=(enable)
300
322
  fail TypeError unless enable == true || enable == false
301
- config_set('interface_ospf', 'passive_interface', @interface.name,
302
- enable ? '' : 'no')
323
+ @set_args[:state] = enable ? '' : 'no'
324
+ config_set('interface_ospf', 'passive_interface', @set_args)
325
+ set_args_keys_default
303
326
  end
304
327
 
305
328
  def priority
306
- config_get('interface_ospf', 'priority', @interface.name)
329
+ config_get('interface_ospf', 'priority', @get_args)
307
330
  end
308
331
 
309
- # interface %s
310
- # ip ospf priority %d
311
332
  def priority=(val)
312
- no_cmd = (val == default_priority) ? 'no' : ''
313
- pri = (val == default_priority) ? '' : val
314
- config_set('interface_ospf', 'priority',
315
- @interface.name, no_cmd, pri)
333
+ if val == default_priority
334
+ @set_args.merge!(state: 'no', priority: '')
335
+ else
336
+ @set_args.merge!(state: '', priority: val)
337
+ end
338
+ config_set('interface_ospf', 'priority', @set_args)
339
+ set_args_keys_default
316
340
  end
317
341
 
318
342
  def default_priority
@@ -320,14 +344,13 @@ module Cisco
320
344
  end
321
345
 
322
346
  def shutdown
323
- config_get('interface_ospf', 'shutdown', @interface.name)
347
+ config_get('interface_ospf', 'shutdown', @get_args)
324
348
  end
325
349
 
326
- # interface %s
327
- # %s ip ospf shutdown
328
- def shutdown=(state)
329
- config_set('interface_ospf', 'shutdown', @interface.name,
330
- state ? '' : 'no')
350
+ def shutdown=(enable)
351
+ @set_args[:state] = enable ? '' : 'no'
352
+ config_set('interface_ospf', 'shutdown', @set_args)
353
+ set_args_keys_default
331
354
  end
332
355
 
333
356
  def default_shutdown
@@ -335,16 +358,17 @@ module Cisco
335
358
  end
336
359
 
337
360
  def transmit_delay
338
- config_get('interface_ospf', 'transmit_delay', @interface.name)
361
+ config_get('interface_ospf', 'transmit_delay', @get_args)
339
362
  end
340
363
 
341
- # interface %s
342
- # ip ospf transmit-delay %d
343
364
  def transmit_delay=(val)
344
- no_cmd = (val == default_transmit_delay) ? 'no' : ''
345
- delay = (val == default_transmit_delay) ? '' : val
346
- config_set('interface_ospf', 'transmit_delay',
347
- @interface.name, no_cmd, delay)
365
+ if val == default_transmit_delay
366
+ @set_args.merge!(state: 'no', delay: '')
367
+ else
368
+ @set_args.merge!(state: '', delay: val)
369
+ end
370
+ config_set('interface_ospf', 'transmit_delay', @set_args)
371
+ set_args_keys_default
348
372
  end
349
373
 
350
374
  def default_transmit_delay