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.
- data/LICENSE +26 -0
- data/README.md +181 -0
- data/docs/Config_Utils.md +3 -0
- data/docs/Facts.md +106 -0
- data/docs/Filesys_Utils.md +3 -0
- data/docs/IPports.md +3 -0
- data/docs/L1ports.md +3 -0
- data/docs/L2ports.md +3 -0
- data/docs/Providers_Resources.md +304 -0
- data/docs/RE_utils.md +3 -0
- data/docs/StaticHosts.md +3 -0
- data/docs/StaticRoutes.md +3 -0
- data/docs/Vlans.md +3 -0
- data/examples/config/config_file.rb +72 -0
- data/examples/config/config_template_object.rb +81 -0
- data/examples/config/config_template_simple.rb +76 -0
- data/examples/config/multi_config.rb +60 -0
- data/examples/fs_utils.rb +31 -0
- data/examples/re_upgrade.rb +90 -0
- data/examples/re_utils.rb +30 -0
- data/examples/simple.rb +47 -0
- data/examples/st_hosts.rb +33 -0
- data/examples/vlans.rb +25 -0
- data/junos-ez-stdlib.gemspec +15 -0
- data/lib/junos-ez/facts/chassis.rb +45 -0
- data/lib/junos-ez/facts/ifd_style.rb +14 -0
- data/lib/junos-ez/facts/personality.rb +22 -0
- data/lib/junos-ez/facts/switch_style.rb +22 -0
- data/lib/junos-ez/facts/version.rb +32 -0
- data/lib/junos-ez/facts.rb +85 -0
- data/lib/junos-ez/ip_ports/classic.rb +149 -0
- data/lib/junos-ez/ip_ports.rb +28 -0
- data/lib/junos-ez/l1_ports/classic.rb +87 -0
- data/lib/junos-ez/l1_ports/switch.rb +134 -0
- data/lib/junos-ez/l1_ports.rb +81 -0
- data/lib/junos-ez/l2_ports/bridge_domain.rb +0 -0
- data/lib/junos-ez/l2_ports/vlan.rb +317 -0
- data/lib/junos-ez/l2_ports/vlan_l2ng.rb +0 -0
- data/lib/junos-ez/l2_ports.rb +57 -0
- data/lib/junos-ez/provider.rb +608 -0
- data/lib/junos-ez/stdlib.rb +16 -0
- data/lib/junos-ez/system/st_hosts.rb +74 -0
- data/lib/junos-ez/system/st_routes.rb +135 -0
- data/lib/junos-ez/system/syscfg.rb +103 -0
- data/lib/junos-ez/system.rb +98 -0
- data/lib/junos-ez/utils/config.rb +205 -0
- data/lib/junos-ez/utils/fs.rb +376 -0
- data/lib/junos-ez/utils/re.rb +371 -0
- data/lib/junos-ez/vlans/bridge_domain.rb +85 -0
- data/lib/junos-ez/vlans/vlan.rb +112 -0
- data/lib/junos-ez/vlans.rb +31 -0
- 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
|
+
|