junos-ez-stdlib 0.0.10

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 (52) hide show
  1. data/LICENSE +26 -0
  2. data/README.md +181 -0
  3. data/docs/Config_Utils.md +3 -0
  4. data/docs/Facts.md +106 -0
  5. data/docs/Filesys_Utils.md +3 -0
  6. data/docs/IPports.md +3 -0
  7. data/docs/L1ports.md +3 -0
  8. data/docs/L2ports.md +3 -0
  9. data/docs/Providers_Resources.md +304 -0
  10. data/docs/RE_utils.md +3 -0
  11. data/docs/StaticHosts.md +3 -0
  12. data/docs/StaticRoutes.md +3 -0
  13. data/docs/Vlans.md +3 -0
  14. data/examples/config/config_file.rb +72 -0
  15. data/examples/config/config_template_object.rb +81 -0
  16. data/examples/config/config_template_simple.rb +76 -0
  17. data/examples/config/multi_config.rb +60 -0
  18. data/examples/fs_utils.rb +31 -0
  19. data/examples/re_upgrade.rb +90 -0
  20. data/examples/re_utils.rb +30 -0
  21. data/examples/simple.rb +47 -0
  22. data/examples/st_hosts.rb +33 -0
  23. data/examples/vlans.rb +25 -0
  24. data/junos-ez-stdlib.gemspec +15 -0
  25. data/lib/junos-ez/facts/chassis.rb +45 -0
  26. data/lib/junos-ez/facts/ifd_style.rb +14 -0
  27. data/lib/junos-ez/facts/personality.rb +22 -0
  28. data/lib/junos-ez/facts/switch_style.rb +22 -0
  29. data/lib/junos-ez/facts/version.rb +32 -0
  30. data/lib/junos-ez/facts.rb +85 -0
  31. data/lib/junos-ez/ip_ports/classic.rb +149 -0
  32. data/lib/junos-ez/ip_ports.rb +28 -0
  33. data/lib/junos-ez/l1_ports/classic.rb +87 -0
  34. data/lib/junos-ez/l1_ports/switch.rb +134 -0
  35. data/lib/junos-ez/l1_ports.rb +81 -0
  36. data/lib/junos-ez/l2_ports/bridge_domain.rb +0 -0
  37. data/lib/junos-ez/l2_ports/vlan.rb +317 -0
  38. data/lib/junos-ez/l2_ports/vlan_l2ng.rb +0 -0
  39. data/lib/junos-ez/l2_ports.rb +57 -0
  40. data/lib/junos-ez/provider.rb +608 -0
  41. data/lib/junos-ez/stdlib.rb +16 -0
  42. data/lib/junos-ez/system/st_hosts.rb +74 -0
  43. data/lib/junos-ez/system/st_routes.rb +135 -0
  44. data/lib/junos-ez/system/syscfg.rb +103 -0
  45. data/lib/junos-ez/system.rb +98 -0
  46. data/lib/junos-ez/utils/config.rb +205 -0
  47. data/lib/junos-ez/utils/fs.rb +376 -0
  48. data/lib/junos-ez/utils/re.rb +371 -0
  49. data/lib/junos-ez/vlans/bridge_domain.rb +85 -0
  50. data/lib/junos-ez/vlans/vlan.rb +112 -0
  51. data/lib/junos-ez/vlans.rb +31 -0
  52. metadata +111 -0
@@ -0,0 +1,317 @@
1
+ class Junos::Ez::L2ports::Provider::VLAN < 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.unit {
23
+ xml.name '0'
24
+ return xml
25
+ }
26
+ }
27
+ end
28
+
29
+ ### ---------------------------------------------------------------
30
+ ### XML property readers
31
+ ### ---------------------------------------------------------------
32
+
33
+ def xml_get_has_xml( xml )
34
+ # second unit contains the family/ethernet-switching stanza
35
+ got = xml.xpath('//unit')[0]
36
+
37
+ # if this resource doesn't exist we need to default some
38
+ # values into has/should variables
39
+
40
+ unless got
41
+ @has[:vlan_tagging] = false
42
+ @should = @has.clone
43
+ end
44
+
45
+ got
46
+ end
47
+
48
+ def xml_read_parser( as_xml, as_hash )
49
+ set_has_status( as_xml, as_hash )
50
+
51
+ xml_when_item(as_xml.xpath('description')){|i| as_hash[:description] = i.text}
52
+
53
+ f_eth = as_xml.xpath('family/ethernet-switching')
54
+ as_hash[:vlan_tagging] = f_eth.xpath('port-mode').text.chomp == 'trunk'
55
+
56
+ # --- access port
57
+ if as_hash[:vlan_tagging] == false
58
+ xml_when_item(f_eth.xpath('vlan/members')){|i| as_hash[:untagged_vlan] = i.text.chomp }
59
+ return
60
+ end
61
+
62
+ # --- trunk port
63
+ xml_when_item(f_eth.xpath('native-vlan-id')){|i| as_hash[:untagged_vlan] = i.text.chomp }
64
+ as_hash[:tagged_vlans] = f_eth.xpath('vlan/members').collect { |v| v.text.chomp }
65
+ end
66
+
67
+ ### ---------------------------------------------------------------
68
+ ### XML property writers
69
+ ### ---------------------------------------------------------------
70
+
71
+ ## overload the xml_build_change method so we can 'copy-thru'
72
+ ## some of the has -> should values. this way we don't need
73
+ ## to munge all of the state-transition code.
74
+
75
+ def xml_build_at_here( xml )
76
+ xml.family {
77
+ xml.send(:'ethernet-switching') {
78
+ return xml
79
+ }
80
+ }
81
+ end
82
+
83
+ def xml_build_change( xml_at_here = nil )
84
+ @should[:untagged_vlan] ||= @has[:untagged_vlan]
85
+ super xml_build_at_here( xml_at_top )
86
+ end
87
+
88
+ ## ----------------------------------------------------------------
89
+ ## :description
90
+ ## ----------------------------------------------------------------
91
+
92
+ ## overload default method since we need to "up-out" of the
93
+ ## ethernet-switching stanza
94
+
95
+ def xml_change_description( xml )
96
+ unit = xml.parent.xpath('ancestor::unit')[0]
97
+ Nokogiri::XML::Builder.with( unit ){ |x|
98
+ xml_set_or_delete( x, 'description', @should[:description] )
99
+ }
100
+ end
101
+
102
+ ## ----------------------------------------------------------------
103
+ ## :vlan_tagging
104
+ ## ----------------------------------------------------------------
105
+
106
+ def xml_change_vlan_tagging( xml )
107
+ port_mode = should_trunk? ? 'trunk' : 'access'
108
+ xml.send(:'port-mode', port_mode )
109
+
110
+ # when the vlan_tagging value changes then this method
111
+ # will trigger updates to the untagged_vlan and tagged_vlans
112
+ # resource values as well.
113
+
114
+ upd_untagged_vlan( xml )
115
+ upd_tagged_vlans( xml )
116
+
117
+ return true
118
+ end
119
+
120
+ ## ----------------------------------------------------------------
121
+ ## :tagged_vlans
122
+ ## ----------------------------------------------------------------
123
+
124
+ def xml_change_tagged_vlans( xml )
125
+ return false if mode_changed?
126
+ upd_tagged_vlans( xml )
127
+ end
128
+
129
+ def upd_tagged_vlans( xml )
130
+ return false unless should_trunk?
131
+
132
+ v_should = @should[:tagged_vlans] || []
133
+
134
+ if v_should.empty?
135
+ xml.vlan Netconf::JunosConfig::DELETE
136
+ return true
137
+ end
138
+
139
+ v_has = @has[:tagged_vlans] || []
140
+ v_has = v_has.map(&:to_s)
141
+ v_should = v_should.map(&:to_s)
142
+
143
+ del = v_has - v_should
144
+ add = v_should - v_has
145
+
146
+ if add or del
147
+ xml.vlan {
148
+ del.each { |v| xml.members v, Netconf::JunosConfig::DELETE }
149
+ add.each { |v| xml.members v }
150
+ }
151
+ end
152
+
153
+ return true
154
+ end
155
+
156
+ ## ----------------------------------------------------------------
157
+ ## :untagged_vlan
158
+ ## ----------------------------------------------------------------
159
+
160
+ def xml_change_untagged_vlan( xml )
161
+ return false if mode_changed?
162
+ upd_untagged_vlan( xml )
163
+ end
164
+
165
+ def upd_untagged_vlan( xml )
166
+ self.class.change_untagged_vlan( self, xml )
167
+ end
168
+
169
+ end
170
+
171
+ ##### ---------------------------------------------------------------
172
+ ##### Class methods for handling state-transitions between
173
+ ##### configurations (tagged/untagged)
174
+ ##### ---------------------------------------------------------------
175
+
176
+ class Junos::Ez::L2ports::Provider::VLAN
177
+
178
+ # creating some class definitions ...
179
+ # this is a bit complicated because we need to handle port-mode
180
+ # change transitions; basically dealing with the fact that
181
+ # trunk ports use 'native-vlan-id' and access ports have a
182
+ # vlan member definition; i.e. they don't use native-vlan-id, ugh.
183
+ # Rather than doing all this logic as if/then/else statements,
184
+ # I've opted to using a proc jump-table technique. Lessons
185
+ # learned from lots of embedded systems programming :-)
186
+
187
+ def self.init_jump_table
188
+
189
+ # auto-hash table, majik!
190
+ hash = Hash.new(&(p=lambda{|h,k| h[k] = Hash.new(&p)}))
191
+
192
+ # ------------------------------------------------------------------
193
+ # - jump table for handling various untagged vlan change use-cases
194
+ # ------------------------------------------------------------------
195
+ # There are three criteria for selection:
196
+ # | is_trunk | will_trunk | no_untg |
197
+ # ------------------------------------------------------------------
198
+
199
+ # - will not have untagged vlan
200
+ hash[false][false][true] = self.method(:ac_ac_nountg)
201
+ hash[false][true][true] = self.method(:ac_tr_nountg)
202
+ hash[true][false][true] = self.method(:tr_ac_nountg)
203
+ hash[true][true][true] = self.method(:tr_tr_nountg)
204
+
205
+ # - will have untagged vlan
206
+ hash[false][false][false] = self.method(:ac_ac_untg)
207
+ hash[false][true][false] = self.method(:ac_tr_untg)
208
+ hash[true][false][false] = self.method(:tr_ac_untg)
209
+ hash[true][true][false] = self.method(:tr_tr_untg)
210
+
211
+ hash
212
+ end
213
+
214
+ ### invoke the correct method from the jump table
215
+ ### based on the three criteria to select the action
216
+
217
+ def self.change_untagged_vlan( this, xml )
218
+ @@ez_l2_jmptbl ||= init_jump_table
219
+ proc = @@ez_l2_jmptbl[this.is_trunk?][this.should_trunk?][this.should[:untagged_vlan].nil?]
220
+ proc.call( this, xml )
221
+ end
222
+
223
+ ### -------------------------------------------------------------
224
+ ### The following are all the change transition functions for
225
+ ### each of the use-cases
226
+ ### -------------------------------------------------------------
227
+
228
+ def self.ac_ac_nountg( this, xml )
229
+ xml.vlan Netconf::JunosConfig::DELETE
230
+ end
231
+
232
+ def self.ac_tr_nountg( this, xml )
233
+ unless (untg_vlan = this.has[:tagged_vlans]).nil?
234
+ xml.vlan {
235
+ xml.members untg_vlan, Netconf::JunosConfig::DELETE
236
+ }
237
+ end
238
+ end
239
+
240
+ def self.tr_ac_nountg( this, xml )
241
+ xml.send :'native-vlan-id', Netconf::JunosConfig::DELETE
242
+ xml.vlan( Netconf::JunosConfig::DELETE ) if this.has[:tagged_vlans]
243
+ end
244
+
245
+ def self.tr_tr_nountg( this, xml )
246
+ xml.send :'native-vlan-id', Netconf::JunosConfig::DELETE
247
+ end
248
+
249
+ def self.ac_ac_untg( this, xml )
250
+ xml.vlan( Netconf::JunosConfig::REPLACE ) {
251
+ xml.members this.should[:untagged_vlan]
252
+ }
253
+ end
254
+
255
+ def self.ac_tr_untg( this, xml )
256
+ was_untg_vlan = this.has[:untagged_vlan]
257
+
258
+ xml.vlan( Netconf::JunosConfig::REPLACE ) {
259
+ xml.members was_untg_vlan, Netconf::JunosConfig::DELETE if was_untg_vlan
260
+ }
261
+ xml.send :'native-vlan-id', this.should[:untagged_vlan]
262
+ end
263
+
264
+ def self.tr_ac_untg( this, xml )
265
+ xml.send :'native-vlan-id', Netconf::JunosConfig::DELETE
266
+ xml.vlan( Netconf::JunosConfig::REPLACE ) {
267
+ xml.members this.should[:untagged_vlan]
268
+ }
269
+ end
270
+
271
+ def self.tr_tr_untg( this, xml )
272
+ xml.send :'native-vlan-id', this.should[:untagged_vlan]
273
+ end
274
+ end
275
+
276
+ ##### ---------------------------------------------------------------
277
+ ##### Provider collection methods
278
+ ##### ---------------------------------------------------------------
279
+
280
+ class Junos::Ez::L2ports::Provider::VLAN
281
+
282
+ def build_list
283
+
284
+ begin
285
+ got = @ndev.rpc.get_ethernet_switching_interface_information(:summary=>true)
286
+ rescue => e
287
+ # in this case, no ethernet-switching is enabled so return empty list
288
+ return []
289
+ end
290
+
291
+ got.xpath('interface/interface-name').collect{ |ifn| ifn.text.split('.')[0] }
292
+ end
293
+
294
+ def build_catalog
295
+ @catalog = {}
296
+ return @catalog if list.empty?
297
+
298
+ @ndev.rpc.get_configuration{ |xml|
299
+ xml.interfaces {
300
+ list.each do |port_name|
301
+ Nokogiri::XML::Builder.with( xml.parent ) do |x1|
302
+ x1.interface { x1.name port_name
303
+ x1.unit { x1.name '0' }
304
+ }
305
+ end
306
+ end
307
+ }
308
+ }.xpath('interfaces/interface').each do |ifs|
309
+ ifs_name = ifs.xpath('name').text
310
+ unit = ifs.xpath('unit')[0]
311
+ @catalog[ifs_name] = {}
312
+ xml_read_parser( unit, @catalog[ifs_name] )
313
+ end
314
+ @catalog
315
+ end
316
+
317
+ end
File without changes
@@ -0,0 +1,57 @@
1
+
2
+ require "junos-ez/provider"
3
+
4
+ module Junos::Ez::L2ports
5
+
6
+ PROPERTIES = [
7
+ :description, # String | nil
8
+ :untagged_vlan, # String | nil
9
+ :tagged_vlans, # Array of String | nil
10
+ :vlan_tagging # true | false
11
+ ]
12
+
13
+ def self.Provider( ndev, varsym )
14
+
15
+ newbie = case ndev.fact( :switch_style )
16
+ when :VLAN
17
+ Junos::Ez::L2ports::Provider::VLAN.new( ndev )
18
+ when :VLAN_NG
19
+ raise ArgumentError, "under development"
20
+ Junos::Ez::L2ports::Provider::VLAN_NG.new( ndev )
21
+ when :BRIDGE_DOMAIN
22
+ raise ArgumentError, "under development"
23
+ Junos::Ez::L2ports::Provider::BRIDGE_DOMAIN.new( ndev )
24
+ end
25
+
26
+ newbie.properties = Junos::Ez::Provider::PROPERTIES + PROPERTIES
27
+ Junos::Ez::Provider.attach_instance_variable( ndev, varsym, newbie )
28
+ end
29
+
30
+ class Provider < Junos::Ez::Provider::Parent
31
+ # common parenting ...
32
+
33
+ def is_trunk?
34
+ @has[:vlan_tagging] == true
35
+ end
36
+
37
+ def should_trunk?
38
+ (@should[:vlan_tagging].nil?) ? @has[:vlan_tagging] : @should[:vlan_tagging]
39
+ end
40
+
41
+ def mode_changed?
42
+ return true if is_new?
43
+ return false if @should[:vlan_tagging].nil?
44
+ @should[:vlan_tagging] != @has[:vlan_tagging]
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+
51
+ require 'junos-ez/l2_ports/vlan'
52
+ =begin
53
+ require 'junos-ez/l2ports/vlan_l2ng' ... under development
54
+ require 'junos-ez/l2ports/bridge_domain' ... under development
55
+ =end
56
+
57
+