Class: Junos::Ez::L2ports::Provider::VLAN

Inherits:
Junos::Ez::L2ports::Provider show all
Defined in:
lib/junos-ez/l2_ports/vlan.rb,
lib/junos-ez/l2_ports/vlan.rb,
lib/junos-ez/l2_ports/vlan.rb

Overview


Provider collection methods


Instance Attribute Summary

Attributes inherited from Provider::Parent

#catalog, #has, #list, #name, #ndev, #parent, #properties, #providers, #should

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Junos::Ez::L2ports::Provider

#is_trunk?, #mode_changed?, #should_trunk?

Methods inherited from Provider::Parent

#[], #[]=, #activate!, #active?, #catalog!, #create, #create!, #create_from_hash!, #create_from_yaml!, #deactivate!, #delete!, #each, #exists?, #init_has, #initialize, #is_new?, #is_provider?, #list!, #name_decorated, #need_write?, #read!, #rename!, #reorder!, #select, #to_h, #to_h_expanded, #to_yaml, #write!, #xml_at_edit, #xml_change__active, #xml_change__exist, #xml_change_admin, #xml_config_read!, #xml_element_newname, #xml_on_create, #xml_on_delete

Constructor Details

This class inherits a constructor from Junos::Ez::Provider::Parent

Class Method Details

.ac_ac_nountg(this, xml) ⇒ Object


The following are all the change transition functions for each of the use-cases




228
229
230
# File 'lib/junos-ez/l2_ports/vlan.rb', line 228

def self.ac_ac_nountg( this, xml )
  xml.vlan Netconf::JunosConfig::DELETE
end

.ac_ac_untg(this, xml) ⇒ Object



249
250
251
252
253
# File 'lib/junos-ez/l2_ports/vlan.rb', line 249

def self.ac_ac_untg( this, xml )
  xml.vlan( Netconf::JunosConfig::REPLACE ) {
    xml.members this.should[:untagged_vlan]
  }            
end

.ac_tr_nountg(this, xml) ⇒ Object



232
233
234
235
236
237
238
# File 'lib/junos-ez/l2_ports/vlan.rb', line 232

def self.ac_tr_nountg( this, xml )      
  unless (untg_vlan = this.has[:tagged_vlans]).nil?
    xml.vlan {
      xml.members untg_vlan, Netconf::JunosConfig::DELETE
    }              
  end
end

.ac_tr_untg(this, xml) ⇒ Object



255
256
257
258
259
260
261
262
# File 'lib/junos-ez/l2_ports/vlan.rb', line 255

def self.ac_tr_untg( this, xml )      
  was_untg_vlan = this.has[:untagged_vlan]
  
  xml.vlan( Netconf::JunosConfig::REPLACE ) { 
    xml.members was_untg_vlan, Netconf::JunosConfig::DELETE if was_untg_vlan
  }
  xml.send :'native-vlan-id', this.should[:untagged_vlan]              
end

.change_untagged_vlan(this, xml) ⇒ Object

invoke the correct method from the jump table based on the three criteria to select the action



217
218
219
220
221
# File 'lib/junos-ez/l2_ports/vlan.rb', line 217

def self.change_untagged_vlan( this, xml )
  @@ez_l2_jmptbl ||= init_jump_table    
  proc = @@ez_l2_jmptbl[this.is_trunk?][this.should_trunk?][this.should[:untagged_vlan].nil?]
  proc.call( this, xml )
end

.init_jump_tableObject

creating some class definitions … this is a bit complicated because we need to handle port-mode change transitions; basically dealing with the fact that trunk ports use ‘native-vlan-id’ and access ports have a vlan member definition; i.e. they don’t use native-vlan-id, ugh. Rather than doing all this logic as if/then/else statements, I’ve opted to using a proc jump-table technique. Lessons learned from lots of embedded systems programming :-)



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/junos-ez/l2_ports/vlan.rb', line 187

def self.init_jump_table
  
  # auto-hash table, majik!
  hash = Hash.new(&(p=lambda{|h,k| h[k] = Hash.new(&p)}))
  
  # ------------------------------------------------------------------
  # -   jump table for handling various untagged vlan change use-cases      
  # ------------------------------------------------------------------      
  # There are three criteria for selection:  
  # | is_trunk | will_trunk | no_untg |
  # ------------------------------------------------------------------
  
  # - will not have untagged vlan 
  hash[false][false][true] = self.method(:ac_ac_nountg)
  hash[false][true][true] = self.method(:ac_tr_nountg)
  hash[true][false][true] = self.method(:tr_ac_nountg)
  hash[true][true][true] = self.method(:tr_tr_nountg)
  
  # - will have untagged vlan 
  hash[false][false][false] = self.method(:ac_ac_untg)
  hash[false][true][false] = self.method(:ac_tr_untg)
  hash[true][false][false] = self.method(:tr_ac_untg)
  hash[true][true][false] = self.method(:tr_tr_untg)
  
  hash
end

.tr_ac_nountg(this, xml) ⇒ Object



240
241
242
243
# File 'lib/junos-ez/l2_ports/vlan.rb', line 240

def self.tr_ac_nountg( this, xml )
  xml.send :'native-vlan-id', Netconf::JunosConfig::DELETE              
  xml.vlan( Netconf::JunosConfig::DELETE ) if this.has[:tagged_vlans]
end

.tr_ac_untg(this, xml) ⇒ Object



264
265
266
267
268
269
# File 'lib/junos-ez/l2_ports/vlan.rb', line 264

def self.tr_ac_untg( this, xml )
  xml.send :'native-vlan-id', Netconf::JunosConfig::DELETE              
  xml.vlan( Netconf::JunosConfig::REPLACE ) {
    xml.members this.should[:untagged_vlan]
  }            
end

.tr_tr_nountg(this, xml) ⇒ Object



245
246
247
# File 'lib/junos-ez/l2_ports/vlan.rb', line 245

def self.tr_tr_nountg( this, xml )
  xml.send :'native-vlan-id', Netconf::JunosConfig::DELETE              
end

.tr_tr_untg(this, xml) ⇒ Object



271
272
273
# File 'lib/junos-ez/l2_ports/vlan.rb', line 271

def self.tr_tr_untg( this, xml )
  xml.send :'native-vlan-id', this.should[:untagged_vlan]              
end

Instance Method Details

#build_catalogObject



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'lib/junos-ez/l2_ports/vlan.rb', line 294

def build_catalog
  @catalog = {}    
  return @catalog if list.empty?
  
  @ndev.rpc.get_configuration{ |xml|
    xml.interfaces {
      list.each do |port_name|
        Nokogiri::XML::Builder.with( xml.parent ) do |x1|
          x1.interface { x1.name port_name
            x1.unit { x1.name '0' }
          }
        end        
      end
    }      
  }.xpath('interfaces/interface').each do |ifs|
    ifs_name = ifs.xpath('name').text
    unit = ifs.xpath('unit')[0]
    @catalog[ifs_name] = {}
    xml_read_parser( unit, @catalog[ifs_name] )
  end
  @catalog
end

#build_listObject



282
283
284
285
286
287
288
289
290
291
292
# File 'lib/junos-ez/l2_ports/vlan.rb', line 282

def build_list
  
  begin
    got = @ndev.rpc.get_ethernet_switching_interface_information(:summary=>true)
  rescue => e
    # in this case, no ethernet-switching is enabled so return empty list
    return []
  end
  
  got.xpath('interface/interface-name').collect{ |ifn| ifn.text.split('.')[0] }
end

#upd_tagged_vlans(xml) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/junos-ez/l2_ports/vlan.rb', line 129

def upd_tagged_vlans( xml )        
  return false unless should_trunk?
  
  v_should = @should[:tagged_vlans] || []
  
  if v_should.empty?
    xml.vlan Netconf::JunosConfig::DELETE
    return true
 end
  
  v_has = @has[:tagged_vlans] || []    
  v_has = v_has.map(&:to_s)    
  v_should = v_should.map(&:to_s)    
  
  del = v_has - v_should
  add = v_should - v_has 
  
  if add or del
    xml.vlan {
      del.each { |v| xml.members v, Netconf::JunosConfig::DELETE }
      add.each { |v| xml.members v }
    }  
  end
  
  return true    
end

#upd_untagged_vlan(xml) ⇒ Object



165
166
167
# File 'lib/junos-ez/l2_ports/vlan.rb', line 165

def upd_untagged_vlan( xml )
  self.class.change_untagged_vlan( self, xml )
end

#xml_at_element_top(xml, name) ⇒ Object

set the edit anchor inside the ethernet-switching stanza we will need to ‘up-out’ when making changes to the unit information, like description



19
20
21
22
23
24
25
26
27
# File 'lib/junos-ez/l2_ports/vlan.rb', line 19

def xml_at_element_top( xml, name )
  xml.interface {
    xml.name name
    xml.unit { 
      xml.name '0'
      return xml
    }
  }    
end

#xml_at_topObject


XML top placement




7
8
9
10
11
12
13
# File 'lib/junos-ez/l2_ports/vlan.rb', line 7

def xml_at_top
  Nokogiri::XML::Builder.new {|xml| xml.configuration {
    xml.interfaces {
      return xml_at_element_top( xml, @name )
    }
  }}
end

#xml_build_at_here(xml) ⇒ Object

overload the xml_build_change method so we can ‘copy-thru’ some of the has -> should values. this way we don’t need to munge all of the state-transition code.



75
76
77
78
79
80
81
# File 'lib/junos-ez/l2_ports/vlan.rb', line 75

def xml_build_at_here( xml )
  xml.family {
    xml.send(:'ethernet-switching') {
      return xml
    }
  }
end

#xml_build_change(xml_at_here = nil) ⇒ Object



83
84
85
86
# File 'lib/junos-ez/l2_ports/vlan.rb', line 83

def xml_build_change( xml_at_here = nil )
  @should[:untagged_vlan] ||= @has[:untagged_vlan]    
  super xml_build_at_here( xml_at_top )
end

#xml_change_description(xml) ⇒ Object

overload default method since we need to “up-out” of the ethernet-switching stanza



95
96
97
98
99
100
# File 'lib/junos-ez/l2_ports/vlan.rb', line 95

def xml_change_description( xml )
  unit = xml.parent.xpath('ancestor::unit')[0]
  Nokogiri::XML::Builder.with( unit ){ |x| 
    xml_set_or_delete( x, 'description', @should[:description] )
  }
end

#xml_change_tagged_vlans(xml) ⇒ Object


:tagged_vlans




124
125
126
127
# File 'lib/junos-ez/l2_ports/vlan.rb', line 124

def xml_change_tagged_vlans( xml )  
  return false if mode_changed?  
  upd_tagged_vlans( xml )
end

#xml_change_untagged_vlan(xml) ⇒ Object


:untagged_vlan




160
161
162
163
# File 'lib/junos-ez/l2_ports/vlan.rb', line 160

def xml_change_untagged_vlan( xml )   
  return false if mode_changed?         
  upd_untagged_vlan( xml )
end

#xml_change_vlan_tagging(xml) ⇒ Object


:vlan_tagging




106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/junos-ez/l2_ports/vlan.rb', line 106

def xml_change_vlan_tagging( xml )    
  port_mode = should_trunk? ? 'trunk' : 'access'
  xml.send(:'port-mode', port_mode )
  
  # when the vlan_tagging value changes then this method
  # will trigger updates to the untagged_vlan and tagged_vlans
  # resource values as well.
  
  upd_untagged_vlan( xml )
  upd_tagged_vlans( xml ) 
  
  return true
end

#xml_get_has_xml(xml) ⇒ Object


XML property readers




33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/junos-ez/l2_ports/vlan.rb', line 33

def xml_get_has_xml( xml )              
  # second unit contains the family/ethernet-switching stanza
  got = xml.xpath('//unit')[0]
  
  # if this resource doesn't exist we need to default some 
  # values into has/should variables
  
  unless got
    @has[:vlan_tagging] = false
    @should = @has.clone
  end
  
  got
end

#xml_read_parser(as_xml, as_hash) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/junos-ez/l2_ports/vlan.rb', line 48

def xml_read_parser( as_xml, as_hash )    
  set_has_status( as_xml, as_hash )  
  
  xml_when_item(as_xml.xpath('description')){|i| as_hash[:description] = i.text}

  f_eth = as_xml.xpath('family/ethernet-switching')        
  as_hash[:vlan_tagging] = f_eth.xpath('port-mode').text.chomp == 'trunk' 

  # --- access port        
  if as_hash[:vlan_tagging] == false
    xml_when_item(f_eth.xpath('vlan/members')){|i| as_hash[:untagged_vlan] = i.text.chomp }
    return
  end
  
  # --- trunk port    
  xml_when_item(f_eth.xpath('native-vlan-id')){|i| as_hash[:untagged_vlan] = i.text.chomp }
  as_hash[:tagged_vlans] = f_eth.xpath('vlan/members').collect { |v| v.text.chomp }    
end