junos-ez-stdlib 0.1.2 → 1.0.3

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 (62) hide show
  1. checksums.yaml +6 -14
  2. data/.gitignore +12 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +8 -0
  5. data/.travis.yml +18 -0
  6. data/CHANGELOG.md +60 -19
  7. data/Gemfile +7 -0
  8. data/README.md +41 -30
  9. data/Rakefile +6 -0
  10. data/SUGGESTION-BOX/README.md +32 -0
  11. data/docs/Providers/Group.md +61 -0
  12. data/docs/Providers/L2ports.md +1 -1
  13. data/docs/Providers/LAGports.md +57 -0
  14. data/docs/Providers/Vlans.md +1 -1
  15. data/examples/config/config_file.rb +0 -0
  16. data/examples/config/config_template_object.rb +0 -0
  17. data/examples/config/config_template_simple.rb +0 -0
  18. data/examples/config/load_sample.conf +129 -0
  19. data/examples/config/load_sample.set +3 -0
  20. data/examples/config/load_template_main.conf +7 -0
  21. data/examples/config/load_template_object.conf +7 -0
  22. data/examples/config/multi_config.rb +0 -0
  23. data/examples/fs_utils.rb +0 -0
  24. data/examples/lag_port.rb +27 -0
  25. data/examples/re_upgrade.rb +0 -0
  26. data/examples/re_utils.rb +0 -0
  27. data/examples/simple.rb +0 -1
  28. data/examples/st_hosts.rb +0 -0
  29. data/examples/user.rb +0 -0
  30. data/examples/vlans.rb +4 -4
  31. data/junos-ez-stdlib.gemspec +25 -14
  32. data/lib/junos-ez/exceptions.rb +0 -0
  33. data/lib/junos-ez/facts.rb +5 -7
  34. data/lib/junos-ez/facts/chassis.rb +6 -0
  35. data/lib/junos-ez/facts/ifd_style.rb +6 -3
  36. data/lib/junos-ez/facts/personality.rb +6 -6
  37. data/lib/junos-ez/facts/switch_style.rb +11 -2
  38. data/lib/junos-ez/facts/version.rb +24 -9
  39. data/lib/junos-ez/group.rb +206 -0
  40. data/lib/junos-ez/ip_ports.rb +0 -0
  41. data/lib/junos-ez/ip_ports/classic.rb +2 -2
  42. data/lib/junos-ez/l1_ports.rb +0 -0
  43. data/lib/junos-ez/l1_ports/classic.rb +0 -0
  44. data/lib/junos-ez/l1_ports/switch.rb +0 -0
  45. data/lib/junos-ez/l2_ports.rb +18 -9
  46. data/lib/junos-ez/l2_ports/bridge_domain.rb +499 -0
  47. data/lib/junos-ez/l2_ports/vlan.rb +3 -3
  48. data/lib/junos-ez/l2_ports/vlan_l2ng.rb +502 -0
  49. data/lib/junos-ez/lag_ports.rb +268 -0
  50. data/lib/junos-ez/provider.rb +4 -8
  51. data/lib/junos-ez/stdlib.rb +2 -0
  52. data/lib/junos-ez/system.rb +0 -0
  53. data/lib/junos-ez/system/users.rb +5 -7
  54. data/lib/junos-ez/utils/config.rb +0 -0
  55. data/lib/junos-ez/utils/fs.rb +0 -0
  56. data/lib/junos-ez/utils/re.rb +0 -0
  57. data/lib/junos-ez/version.rb +4 -1
  58. data/lib/junos-ez/vlans.rb +4 -1
  59. data/lib/junos-ez/vlans/bridge_domain.rb +7 -3
  60. data/lib/junos-ez/vlans/vlan.rb +4 -3
  61. data/lib/junos-ez/vlans/vlan_l2ng.rb +126 -0
  62. metadata +142 -64
@@ -51,7 +51,7 @@ class Junos::Ez::L2ports::Provider::VLAN < Junos::Ez::L2ports::Provider
51
51
  xml_when_item(as_xml.xpath('description')){|i| as_hash[:description] = i.text}
52
52
 
53
53
  f_eth = as_xml.xpath('family/ethernet-switching')
54
- as_hash[:vlan_tagging] = f_eth.xpath('port-mode').text.chomp == 'trunk'
54
+ as_hash[:vlan_tagging] = f_eth.xpath('interface-mode').text.chomp == 'trunk'
55
55
 
56
56
  # obtain a copy of the running state, this is needed in case the config
57
57
  # is located under the [edit vlans] stanza vs. [edit interfaces]
@@ -138,8 +138,8 @@ class Junos::Ez::L2ports::Provider::VLAN < Junos::Ez::L2ports::Provider
138
138
  ## ----------------------------------------------------------------
139
139
 
140
140
  def xml_change_vlan_tagging( xml )
141
- port_mode = should_trunk? ? 'trunk' : 'access'
142
- xml.send(:'port-mode', port_mode )
141
+ interface_mode = should_trunk? ? 'trunk' : 'access'
142
+ xml.send(:'interface-mode', interface_mode )
143
143
 
144
144
  # when the vlan_tagging value changes then this method
145
145
  # will trigger updates to the untagged_vlan and tagged_vlans
@@ -0,0 +1,502 @@
1
+ class Junos::Ez::L2ports::Provider::VLAN_L2NG < Junos::Ez::L2ports::Provider
2
+
3
+ ### ---------------------------------------------------------------
4
+ ### XML top placement
5
+ ### ---------------------------------------------------------------
6
+
7
+ def xml_at_top
8
+ Nokogiri::XML::Builder.new {|xml| xml.configuration {
9
+ xml.interfaces {
10
+ return xml_at_element_top( xml, @name )
11
+ }
12
+ }}
13
+ end
14
+
15
+ # set the edit anchor inside the ethernet-switching stanza
16
+ # we will need to 'up-out' when making changes to the
17
+ # unit information, like description
18
+
19
+ def xml_at_element_top( xml, name )
20
+ xml.interface {
21
+ xml.name name
22
+ xml.send(:'native-vlan-id')
23
+ xml.unit {
24
+ xml.name '0'
25
+ return xml
26
+ }
27
+ }
28
+ end
29
+
30
+ ### ---------------------------------------------------------------
31
+ ### XML property readers
32
+ ### ---------------------------------------------------------------
33
+
34
+ def xml_get_has_xml( xml )
35
+ # second unit contains the family/ethernet-switching stanza
36
+ got = xml.xpath('//unit')[0]
37
+
38
+ # if this resource doesn't exist we need to default some
39
+ # values into has/should variables
40
+
41
+ unless got
42
+ @has[:vlan_tagging] = false
43
+ @should = @has.clone
44
+ end
45
+
46
+ got
47
+ end
48
+
49
+ def xml_read_parser( as_xml, as_hash )
50
+ ## reading is anchored at the [... unit 0 ...] level
51
+ set_has_status( as_xml, as_hash )
52
+
53
+ xml_when_item(as_xml.xpath('description')){|i| as_hash[:description] = i.text}
54
+
55
+ f_eth = as_xml.xpath('family/ethernet-switching')
56
+ as_hash[:vlan_tagging] = f_eth.xpath('interface-mode').text.chomp == 'trunk'
57
+
58
+ # obtain a copy of the running state, this is needed in case the config
59
+ # is located under the [edit vlans] stanza vs. [edit interfaces]
60
+
61
+ ifs_name = @name || as_xml.xpath('ancestor::interface/name').text.strip
62
+ eth_port_vlans = _get_eth_port_vlans_h( ifs_name )
63
+ @under_vlans = []
64
+
65
+ # --- access port
66
+
67
+ if as_hash[:vlan_tagging] == false
68
+ xml_when_item(f_eth.xpath('vlan/members')){ |i| as_hash[:untagged_vlan] = i.text.chomp }
69
+ unless as_hash[:untagged_vlan]
70
+ as_hash[:untagged_vlan] = eth_port_vlans[:untagged]
71
+ @under_vlans << eth_port_vlans[:untagged]
72
+ end
73
+ return
74
+ end
75
+
76
+ # --- trunk port
77
+
78
+ as_hash[:untagged_vlan] ||= eth_port_vlans[:untagged]
79
+ as_hash[:tagged_vlans] = f_eth.xpath('vlan/members').collect { |v| v.text.chomp }.to_set
80
+ (eth_port_vlans[:tagged] - as_hash[:tagged_vlans]).each do |vlan|
81
+ as_hash[:tagged_vlans] << vlan
82
+ @under_vlans << vlan
83
+ end
84
+
85
+ # native-vlan-id is set at the interface level, and is the VLAN-ID, not the vlan
86
+ # name. So we need to do a bit of translating here. The *ASSUMPTION* is that the
87
+ # native-vlan-id value is a given VLAN in the tagged_vlan list. So we will use
88
+ # that list to do the reverse lookup on the tag-id => name
89
+
90
+ xml_when_item(f_eth.xpath('ancestor::interface/native-vlan-id')){ |i|
91
+ as_hash[:untagged_vlan] = _vlan_tag_id_to_name( i.text.chomp, as_hash )
92
+ }
93
+ end
94
+
95
+ ### ---------------------------------------------------------------
96
+ ### XML on_create, on_delete handlers
97
+ ### ---------------------------------------------------------------
98
+
99
+ ## overload the xml_on_delete method since we may need
100
+ ## to do some cleanup work in the [edit vlans] stanza
101
+
102
+ def xml_on_delete( xml )
103
+ @ifd = xml.instance_variable_get(:@parent).at_xpath('ancestor::interface')
104
+ @ifd.xpath('//native-vlan-id').remove ## remove the element from the get-config
105
+
106
+ return unless @under_vlans
107
+ return if @under_vlans.empty?
108
+
109
+ _xml_rm_under_vlans( xml, @under_vlans )
110
+ end
111
+
112
+ ### ---------------------------------------------------------------
113
+ ### XML property writers
114
+ ### ---------------------------------------------------------------
115
+
116
+ def xml_at_here( xml )
117
+ @ifd = xml.instance_variable_get(:@parent).at_xpath('ancestor::interface')
118
+ @ifd.xpath('//native-vlan-id').remove ## remove the element from the get-config
119
+
120
+ xml.family {
121
+ xml.send(:'ethernet-switching') {
122
+ return xml
123
+ }
124
+ }
125
+ end
126
+
127
+ def xml_build_change( nop = nil )
128
+ @under_vlans ||= [] # handles case for create'd port
129
+
130
+ if mode_changed?
131
+ @should[:untagged_vlan] ||= @has[:untagged_vlan]
132
+ end
133
+
134
+ super xml_at_here( xml_at_top )
135
+ end
136
+
137
+ ## ----------------------------------------------------------------
138
+ ## :description
139
+ ## ----------------------------------------------------------------
140
+
141
+ ## overload default method since we need to "up-out" of the
142
+ ## ethernet-switching stanza
143
+
144
+ def xml_change_description( xml )
145
+ unit = xml.parent.xpath('ancestor::unit')[0]
146
+ Nokogiri::XML::Builder.with( unit ){ |x|
147
+ xml_set_or_delete( x, 'description', @should[:description] )
148
+ }
149
+ end
150
+
151
+ ## ----------------------------------------------------------------
152
+ ## :vlan_tagging
153
+ ## ----------------------------------------------------------------
154
+
155
+ def xml_change_vlan_tagging( xml )
156
+ port_mode = should_trunk? ? 'trunk' : 'access'
157
+ xml.send(:'interface-mode', port_mode )
158
+
159
+ # when the vlan_tagging value changes then this method
160
+ # will trigger updates to the untagged_vlan and tagged_vlans
161
+ # resource values as well.
162
+ # !!! DO NOT SWAP THIS ORDER untagged processing *MUST* BE FIRST!
163
+
164
+ upd_untagged_vlan( xml )
165
+ upd_tagged_vlans( xml )
166
+
167
+ return true
168
+ end
169
+
170
+ ## ----------------------------------------------------------------
171
+ ## :tagged_vlans
172
+ ## ----------------------------------------------------------------
173
+
174
+ def xml_change_tagged_vlans( xml )
175
+ return false if mode_changed?
176
+ upd_tagged_vlans( xml )
177
+ end
178
+
179
+ def upd_tagged_vlans( xml )
180
+ return false unless should_trunk?
181
+
182
+ @should[:tagged_vlans] = @should[:tagged_vlans].to_set if @should[:tagged_vlans].kind_of? Array
183
+ @has[:tagged_vlans] = @has[:tagged_vlans].to_set if @has[:tagged_vlans].kind_of? Array
184
+
185
+ v_should = @should[:tagged_vlans] || Set.new
186
+ v_has = @has[:tagged_vlans] || Set.new
187
+
188
+ del = v_has - v_should
189
+ add = v_should - v_has
190
+
191
+ del_under_vlans = del & @under_vlans
192
+
193
+ unless del_under_vlans.empty?
194
+ del = del ^ @under_vlans
195
+ _xml_rm_under_vlans( xml, del_under_vlans )
196
+ @under_vlans = []
197
+ end
198
+
199
+ if add or del
200
+ xml.vlan {
201
+ del.each { |v| xml.members v, Netconf::JunosConfig::DELETE }
202
+ add.each { |v| xml.members v }
203
+ }
204
+ end
205
+
206
+ return true
207
+ end
208
+
209
+ ## ----------------------------------------------------------------
210
+ ## :untagged_vlan
211
+ ## ----------------------------------------------------------------
212
+
213
+ def xml_change_untagged_vlan( xml )
214
+ return false if mode_changed?
215
+ upd_untagged_vlan( xml )
216
+ end
217
+
218
+ def upd_untagged_vlan( xml )
219
+ self.class.change_untagged_vlan( self, xml )
220
+ end
221
+
222
+ end
223
+
224
+ ##### ---------------------------------------------------------------
225
+ ##### Class methods for handling state-transitions between
226
+ ##### configurations (tagged/untagged)
227
+ ##### ---------------------------------------------------------------
228
+
229
+ class Junos::Ez::L2ports::Provider::VLAN_L2NG
230
+
231
+ # creating some class definitions ...
232
+ # this is a bit complicated because we need to handle port-mode
233
+ # change transitions; basically dealing with the fact that
234
+ # trunk ports use 'native-vlan-id' and access ports have a
235
+ # vlan member definition; i.e. they don't use native-vlan-id, ugh.
236
+ # Rather than doing all this logic as if/then/else statements,
237
+ # I've opted to using a proc jump-table technique. Lessons
238
+ # learned from lots of embedded systems programming :-)
239
+
240
+ def self.init_jump_table
241
+
242
+ # auto-hash table, majik!
243
+ hash = Hash.new(&(p=lambda{|h,k| h[k] = Hash.new(&p)}))
244
+
245
+ # ------------------------------------------------------------------
246
+ # - jump table for handling various untagged vlan change use-cases
247
+ # ------------------------------------------------------------------
248
+ # There are three criteria for selection:
249
+ # | is_trunk | will_trunk | no_untg |
250
+ # ------------------------------------------------------------------
251
+
252
+ # - will not have untagged vlan
253
+ hash[false][false][true] = self.method(:ac_ac_nountg)
254
+ hash[false][true][true] = self.method(:ac_tr_nountg)
255
+ hash[true][false][true] = self.method(:tr_ac_nountg)
256
+ hash[true][true][true] = self.method(:tr_tr_nountg)
257
+
258
+ # - will have untagged vlan
259
+ hash[false][false][false] = self.method(:ac_ac_untg)
260
+ hash[false][true][false] = self.method(:ac_tr_untg)
261
+ hash[true][false][false] = self.method(:tr_ac_untg)
262
+ hash[true][true][false] = self.method(:tr_tr_untg)
263
+
264
+ hash
265
+ end
266
+
267
+ ### invoke the correct method from the jump table
268
+ ### based on the three criteria to select the action
269
+
270
+ def self.change_untagged_vlan( this, xml )
271
+ @@ez_l2_jmptbl ||= init_jump_table
272
+ proc = @@ez_l2_jmptbl[this.is_trunk?][this.should_trunk?][this.should[:untagged_vlan].nil?]
273
+ proc.call( this, xml )
274
+ end
275
+
276
+ ### -------------------------------------------------------------
277
+ ### The following are all the change transition functions for
278
+ ### each of the use-cases
279
+ ### -------------------------------------------------------------
280
+
281
+ def self.ac_ac_nountg( this, xml )
282
+ this._xml_rm_ac_untagged_vlan( xml )
283
+ end
284
+
285
+ def self.ac_tr_nountg( this, xml )
286
+ unless (untg_vlan = this.has[:untagged_vlan]).nil?
287
+ this._xml_rm_ac_untagged_vlan( xml )
288
+ end
289
+ end
290
+
291
+ def self.tr_ac_nountg( this, xml )
292
+ this._delete_native_vlan_id( xml )
293
+ this._xml_rm_these_vlans( xml, this.has[:tagged_vlans ] ) if this.has[:tagged_vlans]
294
+ end
295
+
296
+ def self.tr_tr_nountg( this, xml )
297
+ this._delete_native_vlan_id( xml )
298
+ end
299
+
300
+ ## ----------------------------------------------------------------
301
+ ## transition where port WILL-HAVE untagged-vlan
302
+ ## ----------------------------------------------------------------
303
+
304
+ def self.ac_ac_untg( this, xml )
305
+ this._xml_rm_ac_untagged_vlan( xml )
306
+ xml.vlan {
307
+ xml.members this.should[:untagged_vlan]
308
+ }
309
+ end
310
+
311
+ def self.ac_tr_untg( this, xml )
312
+ # move untagged vlan to native-vlan-id ...
313
+ was_untg_vlan = this.has[:untagged_vlan]
314
+ this._set_native_vlan_id( xml, this.should[:untagged_vlan] )
315
+ this._xml_rm_ac_untagged_vlan( xml ) if was_untg_vlan
316
+ end
317
+
318
+ def self.tr_ac_untg( this, xml )
319
+ this._delete_native_vlan_id( xml )
320
+ this._xml_rm_these_vlans( xml, this.has[:tagged_vlans ] ) if this.has[:tagged_vlans]
321
+ xml.vlan { xml.members this.should[:untagged_vlan] }
322
+ end
323
+
324
+ def self.tr_tr_untg( this, xml )
325
+ this._set_native_vlan_id( xml, this.should[:untagged_vlan] )
326
+ end
327
+ end
328
+
329
+ ##### ---------------------------------------------------------------
330
+ ##### Provider collection methods
331
+ ##### ---------------------------------------------------------------
332
+
333
+ class Junos::Ez::L2ports::Provider::VLAN_L2NG
334
+
335
+ def build_list
336
+ begin
337
+ got = @ndev.rpc.get_ethernet_switching_interface_information( :brief => true)
338
+ rescue => e
339
+ # in this case, no ethernet-switching is enabled so return empty list
340
+ return []
341
+ end
342
+ got.xpath('//l2iff-interface-name').collect{ |ifn| ifn.text.split('.')[0] }
343
+ end
344
+
345
+ def build_catalog
346
+ @catalog = {}
347
+ return @catalog if list!.empty?
348
+
349
+ list.each do |ifs_name|
350
+ @ndev.rpc.get_configuration{ |xml|
351
+ xml.interfaces {
352
+ xml_at_element_top( xml, ifs_name )
353
+ }
354
+ }.xpath('interfaces/interface').each do |ifs_xml|
355
+ @catalog[ifs_name] = {}
356
+ unit = xml_get_has_xml( ifs_xml )
357
+ xml_read_parser( unit, @catalog[ifs_name] )
358
+ end
359
+ end
360
+
361
+ @catalog
362
+ end
363
+
364
+ end
365
+
366
+ ##### ---------------------------------------------------------------
367
+ ##### !!!!! PRIVATE METHODS !!!!
368
+ ##### ---------------------------------------------------------------
369
+
370
+ class Junos::Ez::L2ports::Provider::VLAN_L2NG
371
+ private
372
+
373
+ def _get_eth_port_vlans_h( ifs_name )
374
+
375
+ got = @ndev.rpc.get_ethernet_switching_interface_information(:interface_name => ifs_name)
376
+ ret_h = {:untagged => nil, :tagged => Set.new }
377
+ got.xpath('//l2ng-l2ald-iff-interface-entry').each do |vlan|
378
+ # one of the node-set elements (the first one?) contains the interface name.
379
+ # this doesn't have any VLAN information, so skip it.
380
+ next if vlan.xpath('l2iff-interface-name')
381
+
382
+ vlan_name = vlan.xpath('l2iff-interface-vlan-name').text.strip
383
+ tgdy = vlan.xpath('l2iff-interface-vlan-member-tagness').text.strip
384
+ if tgdy == 'untagged'
385
+ ret_h[:untagged] = vlan_name
386
+ else
387
+ ret_h[:tagged] << vlan_name
388
+ end
389
+ end
390
+ ret_h
391
+ end
392
+
393
+ end
394
+
395
+
396
+ ### ---------------------------------------------------------------
397
+ ### [edit vlans] - for interfaces configured here ...
398
+ ### ---------------------------------------------------------------
399
+
400
+ class Junos::Ez::L2ports::Provider::VLAN_L2NG
401
+
402
+ def _xml_edit_under_vlans( xml )
403
+ Nokogiri::XML::Builder.with( xml.doc.root ) do |dot|
404
+ dot.vlans {
405
+ return dot
406
+ }
407
+ end
408
+ end
409
+
410
+ def _xml_rm_under_vlans( xml, vlans )
411
+ if vlans.any?
412
+ at_vlans = _xml_edit_under_vlans( xml )
413
+ vlans.each do |vlan_name|
414
+ Nokogiri::XML::Builder.with( at_vlans.parent ) do |this|
415
+ this.vlan {
416
+ this.name vlan_name
417
+ this.interface( Netconf::JunosConfig::DELETE ) { this.name @name }
418
+ }
419
+ end
420
+ end
421
+ end
422
+ end
423
+
424
+ def _xml_rm_ac_untagged_vlan( xml )
425
+ if @under_vlans.empty?
426
+ xml.vlan Netconf::JunosConfig::DELETE
427
+ else
428
+ _xml_rm_under_vlans( xml, [ @has[:untagged_vlan ] ] )
429
+ @under_vlans = []
430
+ end
431
+ end
432
+
433
+ def _xml_rm_these_vlans( xml, vlans )
434
+ if @under_vlans.empty?
435
+ xml.vlan( Netconf::JunosConfig::DELETE )
436
+ else
437
+ # could be a mix between [edit vlans] and [edit interfaces] ...
438
+ v_has = vlans.to_set
439
+ del_under_vlans = v_has & @under_vlans
440
+ _xml_rm_under_vlans( xml, del_under_vlans )
441
+ if v_has ^ @under_vlans
442
+ xml.vlan( Netconf::JunosConfig::DELETE )
443
+ end
444
+ @under_vlans = []
445
+ end
446
+ end
447
+
448
+ end
449
+
450
+
451
+ class Junos::Ez::L2ports::Provider::VLAN_L2NG
452
+
453
+ def _vlan_name_to_tag_id( vlan_name )
454
+ tag_id = @ndev.rpc.get_configuration { |xml|
455
+ xml.vlans { xml.vlan { xml.name vlan_name }}
456
+ }.xpath('//vlan-id').text.chomp
457
+
458
+ raise ArgumentError, "VLAN '#{vlan_name}' not found" if tag_id.empty?
459
+ return tag_id
460
+ end
461
+
462
+ def _vlan_tag_id_to_name( tag_id, my_hash )
463
+ # get the candidate configuration for each VLAN named in tagged_vlans and
464
+ # then map it to the corresponding vlan-id. this is not very effecient, but
465
+ # at present there is no other way without getting into a cache mech.
466
+ vlan_name = @ndev.rpc.get_configuration { |xml|
467
+ xml.vlans {
468
+ my_hash[:tagged_vlans].each do |v_name|
469
+ xml.vlan {
470
+ xml.name v_name
471
+ xml.send(:'vlan-id')
472
+ }
473
+ end
474
+ }
475
+ }.xpath("//vlan[vlan-id = '#{tag_id}']/name").text.chomp
476
+
477
+ raise ArgumentError, "VLAN-ID '#{tag_id}' not found" if vlan_name.empty?
478
+ return vlan_name
479
+ end
480
+
481
+ end
482
+
483
+ class Junos::Ez::L2ports::Provider::VLAN_L2NG
484
+ def _at_native_vlan_id( xml )
485
+
486
+ ifd
487
+ end
488
+
489
+ def _delete_native_vlan_id( xml )
490
+ Nokogiri::XML::Builder.with( @ifd ) do |dot|
491
+ dot.send :'native-vlan-id', Netconf::JunosConfig::DELETE
492
+ end
493
+ return true
494
+ end
495
+
496
+ def _set_native_vlan_id( xml, vlan_name )
497
+ Nokogiri::XML::Builder.with( @ifd ) do |dot|
498
+ dot.send :'native-vlan-id', _vlan_name_to_tag_id( vlan_name )
499
+ end
500
+ return true
501
+ end
502
+ end