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
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 ...