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
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ LICENSE (BSD-2)
2
+ ===============
3
+ Copyright (c) 2013, Jeremy Schulman, Juniper Networks
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ Redistributions of source code must retain the above copyright notice,
10
+ this list of conditions and the following disclaimer.
11
+
12
+ Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in
14
+ the documentation and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,181 @@
1
+ # OVERVIEW
2
+
3
+ Ruby framework to support Junos OS based device management automation.
4
+
5
+ This is the "standard library" or "core" set of functionality that should work on most/all Junos OS based devices.
6
+
7
+ This framework is build on top of the NETCONF gem which uses XML as the fundamental data-exchange. So no
8
+ "automating the CLI" or using SNMP. The purpose of this framework is to **enable automation development
9
+ without requiring specific Junos XML knowledge**.
10
+
11
+ Further documentation can be found in the *docs* subdirectory.
12
+
13
+ # FRAMEWORK
14
+
15
+ The framework is comprised of these basic eloements:
16
+
17
+ - Facts:
18
+
19
+ A Hash of name/value pairs of information auto-collected. Fact values can be Hash structures as well
20
+ so you can have deeply nested fact data. You can also define your own facts in addition to the "stdlib" facts.
21
+ The facts are used by the framework to create a platform indepent layer of abstraction. This means
22
+ that managing a VLAN, for example, is the same regardless of the underlying hardware platofrm (EX, QFX,
23
+ MX, SRX, ...)
24
+
25
+ - Resources:
26
+
27
+ Resources allow you to easily configure and perform operational functions on specific items within Junos,
28
+ for example VLANs, or switch ports. A resource has *properties* that you manipuate as Hash. You can
29
+ interact with Junos using resource methods like `read!`, `write!`, `delete!`, `activate!`, `deactivate!`, etc.
30
+ For a complete listing of resource methods, refer to the *docs* directory
31
+
32
+ - Providers:
33
+
34
+ Providers allow you to manage a collection of resource, and most commonly, select a resource.
35
+ The purpose of a provider/resource is to automate the life-cycle of common changes, like adding
36
+ VLANs, or ports to a VLAN. A provider also allows you to obtain a `list` of resources
37
+ (Array of *names*) or a `catalog` (Hash of resource properties). Providers may include resource
38
+ specific functionality, like using complex YAML/Hash data for easy import/export and provisioning
39
+ with Junos. If you need the ability to simply apply config-snippets that you do not need to model
40
+ as resources (as you might for initial device commissioning), the Utilities library is where you
41
+ want to start.
42
+
43
+ - Utilities:
44
+
45
+ Utilities are simply collections of functions. The **configuration** utilities, for example, will
46
+ allow you to easily push config snippets in "curly-brace", "set", or XML formats. Very useful
47
+ for unmanaged provider/resources (like initial configuration of the device). The
48
+ **routing-engine** utilities, for example, will allow you to easily upgrade software, check
49
+ memory usage, and do `ping` operations.
50
+
51
+ # EXAMPLE USAGE
52
+
53
+ ```ruby
54
+ require 'pp'
55
+ require 'net/netconf/jnpr'
56
+ require 'junos-ez/stdlib'
57
+
58
+ unless ARGV[0]
59
+ puts "You must specify a target"
60
+ exit 1
61
+ end
62
+
63
+ # login information for NETCONF session
64
+ login = { :target => ARGV[0], :username => 'jeremy', :password => 'jeremy1', }
65
+
66
+ ## create a NETCONF object to manage the device and open the connection ...
67
+
68
+ ndev = Netconf::SSH.new( login )
69
+ print "Connecting to device #{login[:target]} ... "
70
+ ndev.open
71
+ puts "OK!"
72
+
73
+ ## Now bind providers to the device object. The 'Junos::Ez::Provider' must be first.
74
+ ## This will retrieve the device 'facts'. The other providers allow you to define the
75
+ ## provider variables; so this example is using 'l1_ports' and 'ip_ports', but you could name
76
+ ## them what you like, yo!
77
+
78
+ Junos::Ez::Provider( ndev )
79
+ Junos::Ez::L1ports::Provider( ndev, :l1_ports )
80
+ Junos::Ez::IPports::Provider( ndev, :ip_ports )
81
+ Junoz::Ez::Config::Utils( ndev, :cu )
82
+
83
+ # -----------------------------------------------------------
84
+ # Facts ...
85
+ # -----------------------------------------------------------
86
+
87
+ # show the device softare version fact
88
+ pp ndev.fact :version
89
+
90
+ # show the device serial-number face
91
+ pp ndev.fact :serialnumber
92
+
93
+ # get a list of all available facts (Array)
94
+ pp ndev.facts.list
95
+
96
+ # get a hash of all facts and their associated values
97
+ pp ndev.facts.catalog
98
+
99
+ # -----------------------------------------------------------
100
+ # Layer 1 (physical ports) Resources ...
101
+ # -----------------------------------------------------------
102
+
103
+ pp ndev.l1_ports.list
104
+ pp ndev.l1_ports.catalog
105
+
106
+ # select port 'ge-0/0/0' and display the contents
107
+ # of the properties (like port, speed, description)
108
+
109
+ ge_0 = ndev.l1_ports['ge-0/0/0']
110
+ pp ge_0.to_h
111
+
112
+ # change port to disable, this will write the change
113
+ # but not commit it.
114
+
115
+ ge_0[:admin] = :down
116
+ ge_0.write!
117
+
118
+ # show the diff of the change to the screen
119
+
120
+ puts ndev.cu.diff?
121
+
122
+ # now rollback the change, since we don't want to save it.
123
+
124
+ ndev.cu.rollback!
125
+
126
+ ndev.close
127
+ ```
128
+
129
+ # PROVIDERS
130
+
131
+ Providers manage access to individual resources and their associated properties. Providers/resources exists
132
+ for managing life-cycle common changes that you generally need as part of a larger workflow process. For more
133
+ documentation on Providers/Resources, see the *docs* directory.
134
+
135
+ - L1ports: Physical port management
136
+ - L2ports: Ethernet port (VLAN) management
137
+ - Vlans: VLAN resource management
138
+ - IPports: IP v4 port management
139
+ - StaticHosts: Static Hosts [system static-host-mapping ...]
140
+ - StaticRoutes: Static Routes [routing-options static ...]
141
+
142
+ # UTILITIES
143
+
144
+ - Config:
145
+
146
+ These functions allow you to load config snippets, do commit checks, look at config diffs, etc.
147
+ Generally speaking, you would want to use the Providers/Resources framework to manage specific
148
+ items in the config. This utility library is very useful when doing the initial commissioning
149
+ process, where you do not (cannot) model every aspect of Junos. These utilities can also be
150
+ used in conjunction with Providers/Resources, specifically around locking/unlocking and committing
151
+ the configuration.
152
+
153
+ - Filesystem:
154
+
155
+ These functions provide you "unix-like" commands that return data in Hash forms rather than
156
+ as string output you'd normally have to screen-scraps. These methods include `ls`, `df`, `pwd`,
157
+ `cwd`, `cleanup`, and `cleanup!`
158
+
159
+ - Routing-Engine:
160
+
161
+ These functions provide a general collection to information and functioanlity for handling
162
+ routing-engine (RE) processes. These functions `reboot!`, `shutdown!`, `install_software!`,
163
+ `ping`. Information gathering such as memory-usage, current users, and RE status information
164
+ is also made available through this collection.
165
+
166
+ # DEPENDENCIES
167
+
168
+ * gem netconf
169
+ * Junos OS based products
170
+
171
+ # INSTALLATION
172
+
173
+ * gem install junos-ez-stdlib
174
+
175
+ # CONTRIBUTORS
176
+
177
+ * Jeremy Schulman, @nwkautomaniac
178
+
179
+ # LICENSES
180
+
181
+ BSD-2, See LICENSE file
@@ -0,0 +1,3 @@
1
+ # Configuration Utilities
2
+
3
+ Docs comming soon ...
data/docs/Facts.md ADDED
@@ -0,0 +1,106 @@
1
+ # Fact Keeping
2
+
3
+ This framework is *fact based*, meaning that the provider libraries will have access to information about each
4
+ target. Facts enable the framework to abstract the physical differences of the underlying hardware.
5
+
6
+ For example,the `Junos::Ez::Vlans::Provider` allows you to manage vlans without having to worry about the differences between the EX product family and the MX product family. To you, the programmer, you simply obtain a resource and manage the associated properties.
7
+
8
+ There are collection of standard facts that are always read by the framework. You can find a list of these and the assocaited code in the *libs/../facts* subdirectory. These facts are also avaialble to your program as well. So you can make programmatic decisions based on the facts of the device.
9
+
10
+ You can also define your own facts, and then go on to building your own provider libraries (but we're getting ahead of ourselfs here ...)
11
+
12
+ # Usage
13
+
14
+ Usage rule: you **MUST** call `Junos::Ez::Provider` on your netconf object:
15
+
16
+ - **AFTER** the object has connected to the target, since it will read facts
17
+
18
+ - **BEFORE** you add any other providers, since these may use the facts
19
+
20
+ Here is a basic example:
21
+
22
+ ```ruby
23
+ require 'pp'
24
+ require 'net/netconf/jnpr'
25
+ require 'junos-ez/stdlib'
26
+
27
+ login = { :target => ARGV[0], :username => 'jeremy', :password => 'jeremy1', }
28
+
29
+ # create a NETCONF object to manage the device
30
+
31
+ ndev = Netconf::SSH.new( login )
32
+
33
+ # open the NETCONF connetion, if this fails, the object will throw an exception
34
+ ndev.open
35
+
36
+ # now that the netconf session has been established, initialize the object for the
37
+ # Junos::Ez framework. This will add an instance variable called `@facts` and
38
+ # retrieve all known facts from the target
39
+
40
+ Junos::Ez::Provider( ndev )
41
+
42
+ # do a quick dump of all facts
43
+
44
+ pp ndev.facts.catalog
45
+
46
+ -> {:hardwaremodel=>"SRX210H",
47
+ :serialnumber=>"AD2909AA0096",
48
+ :hostname=>"srx210",
49
+ :domain=>"",
50
+ :fqdn=>"srx210",
51
+ :RE=>
52
+ {:status=>"OK",
53
+ :model=>"RE-SRX210H",
54
+ :up_time=>"26 days, 15 hours, 46 minutes, 4 seconds",
55
+ :last_reboot_reason=>"0x200:normal shutdown"},
56
+ :personality=>:SRX_BRANCH,
57
+ :ifd_style=>:CLASSIC,
58
+ :switch_style=>:VLAN,
59
+ :version=>"12.1X44-D10.4"}
60
+ ```
61
+
62
+ # Methods
63
+
64
+ - `read!` - reloads the facts from the target
65
+ - `[]` - retrieve a specific fact from the keeper
66
+ - `fact` - alternative method to retrieve a specific fact from the keeper
67
+ - `list`, `list!` - returns an Array of fact names (symbols)
68
+ - `catalog`, `catalog!` - returns a Hash of fact names and values
69
+
70
+ The bang (!) indicates that the method will re-read the value from the target, which the non-bang method uses the values cached in memory. If the cache does not exist, the framework will read the values. The use of the bang-methods are handy if/when you have facts whose values change at runtime, like the `ndev.fact(:RE)[:up_time]`
71
+
72
+ # Definig Custom Facts
73
+
74
+ You can define your own facts using `Junos::Ez::Facts::Keeper.define`. You can review the stdlib facts by looking the *libs/../facts* subdirectory of this repo. Here is the code for the `:chassis` fact. What is interesting about this example, is this code will actually create multiple facts about the chassis. So there is not a required one-to-one relationship between createing a custom fact and the actual number of facts it creates, yo!
75
+
76
+ When you define your fact, you must give it a unique "fact name*, and a block. The block takee two arguments: the first is the netconf object, which will provide you access to the underlying Junos XML netconf, an a Hash that allows you to write your facts into the Keeper:
77
+
78
+ ```ruby
79
+ Junos::Ez::Facts::Keeper.define( :chassis ) do |ndev, facts|
80
+
81
+ inv_info = ndev.rpc.get_chassis_inventory
82
+ chassis = inv_info.xpath('chassis')
83
+
84
+ facts[:hardwaremodel] = chassis.xpath('description').text
85
+ facts[:serialnumber] = chassis.xpath('serial-number').text
86
+
87
+ cfg = ndev.rpc.get_configuration{|xml|
88
+ xml.system {
89
+ xml.send(:'host-name')
90
+ xml.send(:'domain-name')
91
+ }
92
+ }
93
+
94
+ facts[:hostname] = cfg.xpath('//host-name').text
95
+ facts[:domain] = cfg.xpath('//domain-name').text
96
+ facts[:fqdn] = facts[:hostname]
97
+ facts[:fqdn] += ".#{facts[:domain]}" unless facts[:domain].empty?
98
+
99
+ end
100
+ ```
101
+
102
+
103
+
104
+
105
+
106
+
@@ -0,0 +1,3 @@
1
+ # Filesystem Utilities
2
+
3
+ Docs coming soon ...
data/docs/IPports.md ADDED
@@ -0,0 +1,3 @@
1
+ # IP v4 Port Provider
2
+
3
+ Docs comming soon...
data/docs/L1ports.md ADDED
@@ -0,0 +1,3 @@
1
+ # Layer 1 Physical Port Provider
2
+
3
+ Docs comming soon ...
data/docs/L2ports.md ADDED
@@ -0,0 +1,3 @@
1
+ # Layer 2 Switching Port Provider
2
+
3
+ Docs comming soon ...
@@ -0,0 +1,304 @@
1
+ # RESOURCES
2
+
3
+ Let's start with Resources before we get to Providers. Resources are generally where all "the action" happens.
4
+ The primary purpose of a resource is to allow you to make configuration changes without having to know
5
+ the underlying Junos XML configuration. When you have a resource, you can always get a list of the properties
6
+ available to you.
7
+
8
+ Here's an example of looking at a an ethernet switching port using the L2ports provider.
9
+ This is just a snippet of code, and they use the (->) notation to indicate standard output results.
10
+
11
+ For the following example assume that `l2_ports` is the provider assigned to the `ndev` object. The `ndev` object is of class `Netconf::SSH` (or has this as a parent class)
12
+
13
+ ```ruby
14
+
15
+ # select a port by name from the provider
16
+
17
+ port = ndev.l2_ports['ge-0/0/0']
18
+
19
+ # check to see if this actually exists in the config
20
+
21
+ unless port.exists?
22
+ puts "This port #{port.name} does not exist!"
23
+ exit 1
24
+ end
25
+
26
+ # now pretty-print the properties associated with this resource (which would be the same list for
27
+ # any L2port resource
28
+
29
+ pp port.properties
30
+
31
+ -> [:_exist, :_active, :description, :untagged_vlan, :tagged_vlans, :vlan_tagging]
32
+
33
+ # now look at the specific values for this resource by pp the assocaite hash
34
+
35
+ pp port.to_h
36
+
37
+ -> {"ge-0/0/0"=>
38
+ {:_active=>true,
39
+ :_exist=>true,
40
+ :vlan_tagging=>true,
41
+ :tagged_vlans=>["Red", "Green", "Blue"],
42
+ :untagged_vlan=>nil}}
43
+ ```
44
+
45
+ ## Resource Methods
46
+
47
+ - `read!` - reads the contents into the resource read-hash (@has)
48
+ - `write!` - writes the contents from the resource write-hash (@should) to the device
49
+ - `delete!` - delete the resource from the configuration
50
+ - `activate!` - activates the configuration for this resource
51
+ - `deactivate!` - deactivates the configuration for this resource
52
+ - `rename!` - renames the resource in the configuration
53
+ - `reorder!` - reorders (Junos `insert`) the resource in the configuration
54
+ - `exists?` - indicates if this resource exists in the configuration
55
+ - `active?` - indicates if this resource is active in the configuration
56
+ - `to_h` - return the read-from and write-to hash values
57
+
58
+ ## Instance Variables
59
+
60
+ Each resource include a hash structure containing the values read-from the device. This is
61
+ the `@has` variable. When modifying properties, the changed values are stored in the
62
+ write-to hash `@should` variable. These instance variable are made accessible, but you
63
+ should not access them directly. See next section for changing the property values.
64
+
65
+ ## Reading Properties
66
+
67
+ You can obtain the entire `@has` property hash has using the `to_h` method. This example selects the "ge-0/0/0" physical port and dumps the property hash:
68
+
69
+ ```ruby
70
+ port = ndev.l1_ports["ge-0/0/1"]
71
+
72
+ pp port.to_h
73
+
74
+ -> {"ge-0/0/1"=>
75
+ {:_active=>true,
76
+ :_exist=>true,
77
+ :admin=>:up,
78
+ :duplex=>:auto,
79
+ :speed=>:auto,
80
+ :unit_count=>26}}
81
+
82
+ ```
83
+
84
+ You can also obtain just a specific property using the `[]` operator:
85
+
86
+ ```ruby
87
+ pp port[:admin]
88
+
89
+ -> :up
90
+ ```
91
+
92
+
93
+
94
+ ## Modifying Properties
95
+
96
+ Modifying the resource property is simply making use of the `[]=` operator. For example,
97
+ setting the `:untagged_vlan` to "Black" and writing that back to the device would
98
+ look something like this:
99
+
100
+ ```ruby
101
+ port[:untagged_vlan] = "Black"
102
+ port.write!
103
+ ```
104
+
105
+ You can also obtain the `@should` property hash using the `to_h` method and providing the optional `:write` argument:
106
+
107
+ ```ruby
108
+ port[:admin] = :down
109
+
110
+ pp port.to_h( :write )
111
+
112
+ -> {"ge-0/0/1"=>{:admin=>:down}}
113
+ ```
114
+
115
+ _NOTE: The `@should` property hash only contains the changes that will be applied, not every property value._
116
+
117
+ When you execute the `write!` method, the framework will examine the contents of
118
+ the `@should` hash to determine what changes need to be made. On success the
119
+ values are then transfered into the `@has` hash.
120
+
121
+ If you're going to make changes to an array property, you would need to do something like this:
122
+
123
+ ```ruby
124
+ port[:tagged_vlans] += ["Purple"]
125
+ port[:tagged_vlans] -= ["Red", "Green"]
126
+ port.write!
127
+ ```
128
+
129
+ _NOTE: for Array values, do not use array methods like `delete` as they will operate
130
+ on the `@has` hash._
131
+
132
+ ## Special Properties
133
+
134
+ All resources include two special properties `_exist` and `_active`. These control whether or
135
+ not a resource exists (or should) and whether or not the resource is active (or deactive).
136
+ Generally speaking you should not modify these properties directly. Rather you should use the
137
+ `delete!` method to remove the resource and the `activate!` and `deactivate!` methods respectively.
138
+ That being said, if you have a Hash/YAML dataset that explicity has `:_exist => false` when that
139
+ resource is applied to the device, the resource is deleted. This is handy to ensure a specific
140
+ resource does not exist, for example.
141
+
142
+ # PROVIDERS
143
+
144
+ Providers enable access to, and information about resources. So how to you bind a provider to a
145
+ Netconf::SSH (netconf) object? This is done by the provider's `Provider` method. There are
146
+ two techniques for *bindng* a provider to a netconf object.
147
+
148
+ One method is to bind the provider after the call to `Netconf::SSH#open`. For example, if you want
149
+ to use the L2port provider, you bind it to the netconf object like so:
150
+
151
+ ```ruby
152
+
153
+ # creating a netconf object, here login is a hash defining login info
154
+
155
+ ndev = Netconf::SSH.new( login )
156
+
157
+ # connect to the target
158
+
159
+ ndev.open
160
+
161
+ # bind providers to this object
162
+
163
+ Junos::Ez::Provider( ndev )
164
+ Junos::Ez::L2ports::Provider( ndev, :l2_ports )
165
+ ```
166
+
167
+ But let's say that you want to create multiple `Netconf::SSH` objects and you don't want to
168
+ programmatically do the binding each time? You can define a new class inheriting `Netconf::SSH` and
169
+ overload the `open` method, for example:
170
+
171
+ ```ruby
172
+ class MyJunosSwitch < Netconf::SSH
173
+ def open
174
+ # must be first to open the connection to the target
175
+ super
176
+
177
+ # bind init provider, this will retrieve facts
178
+ Junos::Ez::Provider( self )
179
+
180
+ # bind other providers you want this object to have
181
+ Junos::Ez::L2ports::Provider( self, :l2_ports )
182
+ Junos::Ez::Vlans::Provider( self, :vlans )
183
+ end
184
+ end
185
+
186
+ # now open a few devices ...
187
+
188
+ dev1 = MyJunosSwitch.new( login )
189
+ dev2 = MyJunosSwitch.new( login )
190
+
191
+ dev1.open
192
+ dev2.open
193
+
194
+ pp dev1.vlans.list
195
+ pp dev2.vlans.list
196
+
197
+ dev1.close
198
+ dev2.close
199
+ ```
200
+
201
+ There are a few things to note on these example:
202
+
203
+ 1. This framework is built around the NETCONF gem as all of the underlying code access the Junos XML
204
+ API via the NETCONF protocol
205
+
206
+ 2. You **MUST** use the `Junos::Ez::Provider` before any other providers as this sets up the `Netconf::SSH`
207
+ object for future bindings and reads the `facts` from the target. These facts can then be
208
+ used by other provider libraries to abstract target specific differences
209
+
210
+ 3. **You** get to chose the provider instance variable name (in this case `l2_ports`, there are is no
211
+ hard-coding going on in this framework, yo! (except for the `facts` variable)
212
+
213
+ ## Listing Providers
214
+
215
+ When you bind providers to a netconf object, you can always get a list of what exists:
216
+
217
+ ```ruby
218
+ pp ndev.providers
219
+
220
+ -> [:l1_ports, :ip_ports, :l2_ports]
221
+ ```
222
+
223
+ ## Resource List
224
+
225
+ You can obtain a list of managed resources using the `list` or `list!` method. This method
226
+ will return an Array of names. Again these names could be simple strings or complex values.
227
+ The `list!` method causes the framework to re-read from the device. The `list` method uses the cached value.
228
+ If there is no-cached value, the framework will read from the device, so you don't need to explicity
229
+ use `list!` unless you need to force the cache update.
230
+
231
+ ```ruby
232
+ pp ndev.l2_ports.list
233
+
234
+ -> ["fe-0/0/2", "fe-0/0/3", "fe-0/0/6"]
235
+ ```
236
+
237
+ ## Resource Catalog
238
+
239
+ You can also obtain the provider's catalog, which is a Hash of resources keyed by name and
240
+ each value is the Hash of the associated properties. The `catalog` and `catalog!` methods
241
+ work the same as described in the list section above.
242
+
243
+ ```ruby
244
+ pp ndev.l2_ports.catalog
245
+
246
+ -> {"fe-0/0/2"=>
247
+ {:_active=>true,
248
+ :_exist=>true,
249
+ :vlan_tagging=>true,
250
+ :tagged_vlans=>["Red", "Green", "Blue"]},
251
+ "fe-0/0/3"=>{:_active=>true, :_exist=>true, :vlan_tagging=>false},
252
+ "fe-0/0/6"=>
253
+ {:_active=>true,
254
+ :_exist=>true,
255
+ :vlan_tagging=>false,
256
+ :untagged_vlan=>"Blue"}}
257
+ ```
258
+
259
+ ## Selecting a Resource from a Provider
260
+
261
+ You select a resource from a provider using the `[]` operator and identifying the resource by *name*. The
262
+ name could be a simple string as shown in the previous example, or could be a complex name
263
+ like an Array. If you take a look a the SRX library (separate repo), you can see that
264
+ the `Junos::Ez::SRX::Policies::Provider` name is an Array of [ from_zone_name, to_zone_name ].
265
+
266
+ Here is an example of selecting an ethernet switching port, "ge-0/0/0":
267
+
268
+ ```ruby
269
+ port = ndev.l2_ports['ge-0/0/0']
270
+ ```
271
+
272
+ When a resource is selected, the framework will automatically `read!` retrieve the configuration.
273
+
274
+ ## Creating a new Resource
275
+
276
+ There are two ways to create a resource. One is using the `create` or `create!` methods.
277
+ The `create` method is used to create the new resource but not write it do the device. The
278
+ `create!` method does both the creation and the write to the device. The `create` method
279
+ can also be given a block, so you can setup the contents of the new resource. Here's an
280
+ example that creates some config and then deactivates it.
281
+
282
+ ```ruby
283
+ ndev.l2_ports.create('ge-0/0/20') do |port|
284
+ port[:description] = "I am port 20"
285
+ port[:untagged_vlan] = "Blue"
286
+ port.write!
287
+ port.deactivate!
288
+ end
289
+ ```
290
+ The above example will also return the new resource object. So you could use the Ruby
291
+ block as a default initializer, and then continue to make changes to the resource.
292
+
293
+ The second way is to simply select a resource by name that doesn't exist. So let's
294
+ say you want to create a new L2port for `ge-0/0/20`. It would look something like this:
295
+
296
+ ```ruby
297
+ port = ndev.l2_ports['ge-0/0/20']
298
+
299
+ puts "I don't exist" unless port.exists?
300
+
301
+ port[:description] = "I am port 20"
302
+ port[:untagged_vlan] = "Storage"
303
+ port.write!
304
+ ```
data/docs/RE_utils.md ADDED
@@ -0,0 +1,3 @@
1
+ # Routing-Engine Utilities
2
+
3
+ Docs comming soon ...
@@ -0,0 +1,3 @@
1
+ # Static Host Entry Provider
2
+
3
+ Docs comming soon ...
@@ -0,0 +1,3 @@
1
+ # Static Routes Provider
2
+
3
+ Docs comming soon ...
data/docs/Vlans.md ADDED
@@ -0,0 +1,3 @@
1
+ # VLANs Provider
2
+
3
+ Docs comming soon ...