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,32 @@
1
+ Junos::Ez::Facts::Keeper.define( :version ) do |ndev, facts|
2
+
3
+ f_master, f_persona = uses :master, :personality
4
+
5
+ case f_persona
6
+ when :MX
7
+ swver = ndev.rpc.command "show version invoke-on all-routing-engines"
8
+ when :SWITCH
9
+ swver = ndev.rpc.command "show version all-members"
10
+ else
11
+ swver = ndev.rpc.command "show version"
12
+ end
13
+
14
+ if swver.name == 'multi-routing-engine-results'
15
+ swver_infos = swver.xpath('//software-information')
16
+ swver_infos.each do |re_sw|
17
+ re_name = re_sw.xpath('preceding-sibling::re-name').text.upcase
18
+ re_sw.xpath('package-information[1]/comment').text =~ /\[(.*)\]/
19
+ ver_key = ('version_' + re_name).to_sym
20
+ facts[ver_key] = $1
21
+ end
22
+ master_id = f_master
23
+ facts[:version] =
24
+ facts[("version_" + "RE" + master_id).to_sym] ||
25
+ facts[('version_' + "FPC" + master_id).to_sym]
26
+ else
27
+ junos = swver.xpath('//package-information[name = "junos"]/comment').text
28
+ junos =~ /\[(.*)\]/
29
+ facts[:version] = $1
30
+ end
31
+
32
+ end
@@ -0,0 +1,85 @@
1
+ require 'junos-ez/provider'
2
+
3
+ ### -----------------------------------------------------------------
4
+ ### Junos::Ez module devices the toplevel Provider and associated
5
+ ### Facts class & methods
6
+ ### -----------------------------------------------------------------
7
+
8
+ module Junos::Ez
9
+
10
+ attr_accessor :providers, :facts
11
+
12
+ def self.Provider( ndev )
13
+ ndev.extend Junos::Ez
14
+ ndev.providers = []
15
+ ndev.facts = Junos::Ez::Facts::Keeper.new( ndev )
16
+ ndev.facts.read!
17
+ true
18
+ end
19
+
20
+ def fact( name ); facts[name] end
21
+ end;
22
+
23
+ module Junos::Ez::Facts
24
+
25
+ class Keeper
26
+ attr_accessor :known
27
+
28
+ def initialize( ndev )
29
+ @ndev = ndev
30
+ @known = Hash.new
31
+ end
32
+
33
+ def clear; @known.clear end
34
+
35
+ def list; @known.keys end
36
+ def list!; read!; list; end
37
+
38
+ def catalog; @known end
39
+ def catalog!; read!; catalog end
40
+
41
+ def uses( *facts )
42
+ values = facts.collect do |f|
43
+ self.send( "fact_read_#{f}", @ndev, @known ) unless @known[f]
44
+ self[f]
45
+ end
46
+ (values.count == 1) ? values[0] : values
47
+ end
48
+
49
+ def self.define( fact, &block )
50
+ define_method( "fact_read_#{fact}".to_sym, block )
51
+ end
52
+
53
+ def []=(key,value)
54
+ @known[key] = value
55
+ end
56
+
57
+ def [](key)
58
+ @known[key]
59
+ end
60
+
61
+ def read!
62
+ @known.clear
63
+ fact_readers = self.methods.grep /^fact_read_/
64
+ fact_readers.each do |getter|
65
+ getter =~ /^fact_read_(\w+)/
66
+ fact = $1.to_sym
67
+ self.send( getter, @ndev, @known ) unless @known[fact]
68
+ end
69
+ end
70
+
71
+ end # class
72
+ end
73
+
74
+ ### -----------------------------------------------------------------
75
+ ### Load all of the fact files
76
+ ### -----------------------------------------------------------------
77
+
78
+ Dir[File.dirname(__FILE__) + "/facts/*.rb"].each do |file|
79
+ require file
80
+ end
81
+
82
+
83
+
84
+
85
+
@@ -0,0 +1,149 @@
1
+ class Junos::Ez::IPports::Provider::CLASSIC < Junos::Ez::IPports::Provider
2
+
3
+ ### ---------------------------------------------------------------
4
+ ### XML top placement
5
+ ### ---------------------------------------------------------------
6
+
7
+ def xml_at_top
8
+
9
+ # if just the IFD is given as the name, default to unit "0"
10
+ @ifd, @ifl = @name.split '.'
11
+ @ifl ||= "0"
12
+
13
+ Nokogiri::XML::Builder.new{ |x| x.configuration{
14
+ x.interfaces { x.interface { x.name @ifd
15
+ x.unit {
16
+ x.name @ifl
17
+ return x
18
+ }
19
+ }}
20
+ }}
21
+ end
22
+
23
+ def xml_element_rename( new_name )
24
+
25
+ # if just the IFD is given as the name, default to unit "0"
26
+ n_ifd, n_ifl = new_name.split '.'
27
+ n_ifl ||= "0"
28
+
29
+ # do not allow rename to different IFD.
30
+ return false unless @ifd == n_ifd
31
+
32
+ # return the new element name
33
+ return n_ifl
34
+ end
35
+
36
+ ### ---------------------------------------------------------------
37
+ ### XML readers
38
+ ### ---------------------------------------------------------------
39
+
40
+ def xml_get_has_xml( xml )
41
+ xml.xpath('//unit')[0]
42
+ end
43
+
44
+ def xml_read_parser( as_xml, as_hash )
45
+ set_has_status( as_xml, as_hash )
46
+
47
+ ifa_inet = as_xml.xpath('family/inet')
48
+
49
+ as_hash[:tag_id] = as_xml.xpath('vlan-id').text.to_i
50
+ as_hash[:description] = as_xml.xpath('description').text
51
+ as_hash[:mtu] = ifa_inet.xpath('mtu').text.to_i || nil
52
+ as_hash[:address] = ifa_inet.xpath('address/name').text || nil
53
+ as_hash[:admin] = as_xml.xpath('disable').empty? ? :up : :down
54
+
55
+ return true
56
+ end
57
+
58
+ ### ---------------------------------------------------------------
59
+ ### XML writers
60
+ ### ---------------------------------------------------------------
61
+
62
+ def xml_change_address( xml )
63
+ xml.family { xml.inet {
64
+ if @has[:address]
65
+ xml.address( Netconf::JunosConfig::DELETE ) {
66
+ xml.name @has[:address]
67
+ }
68
+ end
69
+ xml.address {
70
+ xml.name @should[:address]
71
+ }
72
+ }}
73
+ end
74
+
75
+ def xml_change_tag_id( xml )
76
+ xml_set_or_delete( xml, 'vlan-id', @should[:tag_id] )
77
+ end
78
+
79
+ def xml_change_mtu( xml )
80
+ xml.family { xml.inet {
81
+ xml_set_or_delete( xml, 'mtu', @should[:mtu] )
82
+ }}
83
+ end
84
+
85
+ end
86
+
87
+ ##### ---------------------------------------------------------------
88
+ ##### Provider collection methods
89
+ ##### ---------------------------------------------------------------
90
+
91
+ class Junos::Ez::IPports::Provider::CLASSIC
92
+
93
+ def build_list
94
+ from_junos_get_ifa_xml.collect do |ifa|
95
+ ifa.xpath('name').text.strip
96
+ end
97
+ end
98
+
99
+ def build_catalog
100
+ @catalog = {}
101
+
102
+ ## do the equivalent of "show interfaces ..." to retrieve the list
103
+ ## of known interfaces that have an IFA == 'inet'. Note that this
104
+ ## list will *not* include anything that has been deactivated.
105
+
106
+ ifa_list = from_junos_get_ifa_xml
107
+
108
+ ## from this list of IFA, retrieve the configurations
109
+
110
+ got_xml_cfg = @ndev.rpc.get_configuration do |cfg|
111
+ cfg.interfaces {
112
+ ifa_list.each do |ifa|
113
+ ifa_name = ifa.xpath('name').text.strip
114
+ ifa_ifd, ifa_ifl = ifa_name.split '.'
115
+ cfg.interface {
116
+ cfg.name ifa_ifd
117
+ cfg.unit { cfg.name ifa_ifl }
118
+ }
119
+ end
120
+ }
121
+ end
122
+
123
+ ## now create the object property hashes for each of the instances
124
+
125
+ got_xml_cfg.xpath('interfaces/interface/unit').each do |ifl|
126
+ ifd = ifl.xpath('preceding-sibling::name').text.strip
127
+ unit = ifl.xpath('name').text.strip
128
+ obj_name = ifd + '.' + unit
129
+
130
+ @catalog[obj_name] = {}
131
+ xml_read_parser( ifl, @catalog[obj_name] )
132
+ end
133
+
134
+ return @catalog
135
+ end
136
+
137
+ private
138
+
139
+ def from_junos_get_ifa_xml
140
+
141
+ xml_data = @ndev.rpc.get_interface_information(
142
+ :terse => true,
143
+ :interface_name => '[xgf]e-*/*/*.*' )
144
+
145
+ ifa_list = xml_data.xpath('logical-interface[normalize-space(address-family/address-family-name) = "inet"]')
146
+
147
+ end
148
+
149
+ end
@@ -0,0 +1,28 @@
1
+
2
+ require "junos-ez/provider"
3
+
4
+ module Junos::Ez::IPports
5
+
6
+ PROPERTIES = [
7
+ :admin, # [:up, :down]
8
+ :description, # general description text
9
+ :tag_id, # VLAN tag-id for vlan-tag enabled ports
10
+ :mtu, # MTU value as number
11
+ :address # ip/prefix as text, e.g. "192.168.10.22/24"
12
+ ]
13
+
14
+ def self.Provider( ndev, varsym )
15
+ newbie = Junos::Ez::IPports::Provider::CLASSIC.new( ndev )
16
+ newbie.properties = Junos::Ez::Provider::PROPERTIES + PROPERTIES
17
+ Junos::Ez::Provider.attach_instance_variable( ndev, varsym, newbie )
18
+ end
19
+
20
+ class Provider < Junos::Ez::Provider::Parent
21
+ # common parenting goes here ...
22
+ end
23
+
24
+ end
25
+
26
+ require 'junos-ez/ip_ports/classic'
27
+
28
+
@@ -0,0 +1,87 @@
1
+ class Junos::Ez::L1ports::Provider::CLASSIC < Junos::Ez::L1ports::Provider
2
+
3
+ ### ---------------------------------------------------------------
4
+ ### XML top placement
5
+ ### ---------------------------------------------------------------
6
+
7
+ def xml_at_top
8
+ xml = Nokogiri::XML::Builder.new {|xml| xml.configuration {
9
+ xml.interfaces {
10
+ xml.interface {
11
+ xml.name @name
12
+ return xml
13
+ }
14
+ }
15
+ }}
16
+ end
17
+
18
+ ### ---------------------------------------------------------------
19
+ ### XML property readers
20
+ ### ---------------------------------------------------------------
21
+
22
+ def xml_read_filter( xml )
23
+ xml.description
24
+ xml.disable
25
+ xml.mtu
26
+ xml.speed
27
+ xml.send(:'link-mode')
28
+ xml.unit({:recurse => 'false'})
29
+ end
30
+
31
+ def xml_config_read!
32
+ xml = xml_at_top
33
+ xml_read_filter( xml )
34
+ @ndev.rpc.get_configuration( xml )
35
+ end
36
+
37
+ def xml_read_parser( as_xml, as_hash )
38
+ set_has_status( as_xml, as_hash )
39
+
40
+ as_hash[:admin] = as_xml.xpath('disable').empty? ? :up : :down
41
+
42
+ unless (desc = as_xml.xpath('description').text.chomp).empty?
43
+ as_hash[:description] = desc
44
+ end
45
+
46
+ if mtu = as_xml.xpath('mtu')[0]; as_hash[:mtu] = mtu.text.to_i end
47
+
48
+ as_hash[:duplex] = case as_xml.xpath('link-mode').text.chomp
49
+ when 'full-duplex' then :full
50
+ when 'half-duplex' then :half
51
+ else :auto
52
+ end
53
+
54
+ as_hash[:speed] = ( speed = as_xml.xpath('speed')[0] ) ? speed.text : :auto
55
+ as_hash[:unit_count] = as_xml.xpath('unit').count
56
+
57
+ return true
58
+ end
59
+
60
+ ### ---------------------------------------------------------------
61
+ ### XML property writers
62
+ ### ---------------------------------------------------------------
63
+
64
+ def xml_change_speed( xml )
65
+ if @should[:speed] == :auto
66
+ if is_new?
67
+ xml.speed Netconf::JunosConfig::DELETE
68
+ end
69
+ else
70
+ xml.speed @should[:speed]
71
+ end
72
+ end
73
+
74
+ def xml_change_duplex( xml )
75
+ if @should[:duplex] == :auto
76
+ unless is_new?
77
+ xml.send( :'link-mode', Netconf::JunosConfig::DELETE )
78
+ end
79
+ else
80
+ xml.send( :'link-mode', case @should[:duplex]
81
+ when :full then 'full-duplex'
82
+ when :half then 'half-duplex'
83
+ end )
84
+ end
85
+ end
86
+
87
+ end
@@ -0,0 +1,134 @@
1
+ class Junos::Ez::L1ports::Provider::SWITCH < Junos::Ez::L1ports::Provider
2
+
3
+ ### ---------------------------------------------------------------
4
+ ### XML top placement
5
+ ### ---------------------------------------------------------------
6
+
7
+ def xml_at_top
8
+ xml = Nokogiri::XML::Builder.new {|xml| xml.configuration {
9
+ xml.interfaces {
10
+ xml.interface {
11
+ xml.name @name
12
+ return xml
13
+ }
14
+ }
15
+ }}
16
+ end
17
+
18
+ ### ---------------------------------------------------------------
19
+ ### XML property readers
20
+ ### ---------------------------------------------------------------
21
+
22
+ def xml_read_filter( xml )
23
+ xml.description
24
+ xml.disable
25
+ xml.mtu
26
+ xml.send(:'ether-options')
27
+ xml.unit({:recurse => 'false'})
28
+ end
29
+
30
+ def xml_config_read!
31
+ xml = xml_at_top
32
+ xml_read_filter( xml )
33
+ @ndev.rpc.get_configuration( xml )
34
+ end
35
+
36
+ def xml_read_parser( as_xml, as_hash )
37
+ set_has_status( as_xml, as_hash )
38
+
39
+ xml_when_item(as_xml.xpath('description')){|i| as_hash[:description] = i.text}
40
+ as_hash[:admin] = as_xml.xpath('disable').empty? ? :up : :down
41
+ xml_when_item(as_xml.xpath('mtu')){|i| as_hash[:mtu] = i.text.to_i }
42
+
43
+ phy_options = as_xml.xpath('ether-options')
44
+ if phy_options.empty?
45
+ as_hash[:speed] = :auto
46
+ as_hash[:duplex] = :auto
47
+ else
48
+ ## :duplex
49
+ as_hash[:duplex] = case phy_options.xpath('link-mode').text.chomp
50
+ when 'full-duplex' then :full
51
+ when 'half-duplex' then :half
52
+ else :auto
53
+ end
54
+ ## :speed
55
+ if speed = phy_options.xpath('speed')[0]
56
+ as_hash[:speed] = _speed_from_junos_( speed.first_element_child.name )
57
+ else
58
+ as_hash[:speed] = :auto
59
+ end
60
+ end
61
+
62
+ as_hash[:unit_count] = as_xml.xpath('unit').count
63
+ return true
64
+ end
65
+
66
+ ### ---------------------------------------------------------------
67
+ ### XML property writers
68
+ ### ---------------------------------------------------------------
69
+
70
+ def xml_change_speed( xml )
71
+ xml.send(:'ether-options') {
72
+ xml.speed {
73
+ if @should[:speed] == :auto
74
+ unless @has[:speed] == :auto
75
+ xml.send( _speed_to_junos_( @has[:speed] ), Netconf::JunosConfig::DELETE )
76
+ end
77
+ else
78
+ xml.send( _speed_to_junos_( @should[:speed] ))
79
+ end
80
+ }
81
+ }
82
+ end
83
+
84
+ def xml_change_duplex( xml )
85
+ xml.send(:'ether-options') {
86
+ if @should[:duplex] == :auto
87
+ unless @has[:duplex] == :auto
88
+ xml.send( :'link-mode', Netconf::JunosConfig::DELETE )
89
+ end
90
+ else
91
+ xml.send( :'link-mode', case @should[:duplex]
92
+ when :full then 'full-duplex'
93
+ when :half then 'half-duplex'
94
+ end )
95
+ end
96
+ }
97
+ end
98
+
99
+
100
+ end
101
+
102
+ ### -----------------------------------------------------------------
103
+ ### PRIVATE METHODS
104
+ ### -----------------------------------------------------------------
105
+
106
+ class Junos::Ez::L1ports::Provider::SWITCH
107
+ private
108
+
109
+ def _speed_to_junos_( pval )
110
+ # @@@ TODO: could remove case-statement and to
111
+ # @@@ string processing ...
112
+ case pval
113
+ when '10g' then :'ethernet-10g'
114
+ when '1g' then :'ethernet-1g'
115
+ when '100m' then :'ethernet-100m'
116
+ when '10m' then :'ethernet-10m'
117
+ else :auto
118
+ end
119
+ end
120
+
121
+ def _speed_from_junos_( jval )
122
+ # @@@ TODO: could remove case-statement and to
123
+ # @@@ string processing ...
124
+ case jval
125
+ when 'ethernet-100m' then '100m'
126
+ when 'ethernet-10m' then '10m'
127
+ when 'ethernet-1g' then '1g'
128
+ when 'ethernet-10g' then '10g'
129
+ else :auto
130
+ end
131
+ end
132
+
133
+ end
134
+
@@ -0,0 +1,81 @@
1
+ require "junos-ez/provider"
2
+
3
+ module Junos::Ez::L1ports
4
+
5
+ PROPERTIES = [
6
+ :admin, # [ :up, :down ]
7
+ :description, # string
8
+ :mtu, # number
9
+ :speed, # [ :auto, '10m', '100m', '1g', '10g' ]
10
+ :duplex, # [ :auto, :half, :full ]
11
+ :unit_count, # number of configured units
12
+ ]
13
+
14
+ def self.Provider( ndev, varsym )
15
+ newbie = case ndev.fact( :ifd_style )
16
+ when :SWITCH
17
+ Junos::Ez::L1ports::Provider::SWITCH.new( ndev )
18
+ when :CLASSIC
19
+ Junos::Ez::L1ports::Provider::CLASSIC.new( ndev )
20
+ end
21
+
22
+ newbie.properties = Junos::Ez::Provider::PROPERTIES + PROPERTIES
23
+ Junos::Ez::Provider.attach_instance_variable( ndev, varsym, newbie )
24
+ end
25
+
26
+ end
27
+
28
+ class Junos::Ez::L1ports::Provider < Junos::Ez::Provider::Parent
29
+
30
+ ### ---------------------------------------------------------------
31
+ ### XML readers
32
+ ### ---------------------------------------------------------------
33
+
34
+ def xml_get_has_xml( xml )
35
+ xml.xpath('//interface')[0]
36
+ end
37
+
38
+ def xml_change_mtu( xml )
39
+ xml_set_or_delete( xml, 'mtu', @should[:mtu] )
40
+ end
41
+
42
+ ### ---------------------------------------------------------------
43
+ ### Collection methods
44
+ ### ---------------------------------------------------------------
45
+
46
+ def build_list
47
+ @ndev.rpc.get_interface_information({
48
+ :media => true,
49
+ :terse => true,
50
+ :interface_name => '[fgx]e-*'
51
+ }).xpath('physical-interface/name').collect do |ifs|
52
+ ifs.text.strip
53
+ end
54
+ end
55
+
56
+ def build_catalog
57
+ @catalog = {}
58
+
59
+ @ndev.rpc.get_configuration{|xml|
60
+ xml.interfaces {
61
+ list!.each do |ifs|
62
+ xml.interface {
63
+ xml.name ifs
64
+ xml_read_filter( xml )
65
+ }
66
+ end
67
+ }
68
+ }.xpath('interfaces/interface').each do |ifs_xml|
69
+ ifs_name = ifs_xml.xpath('name').text
70
+ @catalog[ifs_name] = {}
71
+ xml_read_parser( ifs_xml, @catalog[ifs_name] )
72
+ end
73
+
74
+ return @catalog
75
+ end
76
+
77
+ end
78
+
79
+ require 'junos-ez/l1_ports/switch'
80
+ require 'junos-ez/l1_ports/classic'
81
+
File without changes