junos-ez-stdlib 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
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
+