junos-ez-stdlib 0.0.12 → 0.0.15

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 (43) hide show
  1. data/CHANGELOG.md +17 -3
  2. data/README.md +10 -0
  3. data/docs/Providers/IPports.md +61 -0
  4. data/docs/Providers/L1ports.md +29 -0
  5. data/docs/Providers/L2ports.md +43 -0
  6. data/docs/Providers/StaticHosts.md +26 -0
  7. data/docs/Providers/StaticRoutes.md +37 -0
  8. data/docs/Providers/UserAuths.md +32 -0
  9. data/docs/{Users.md → Providers/Users.md} +17 -0
  10. data/docs/Providers/Vlans.md +43 -0
  11. data/docs/Providers_Resources.md +24 -0
  12. data/docs/README_FIRST.md +27 -0
  13. data/docs/Utils/Config.md +161 -0
  14. data/docs/Utils/Filesystem.md +78 -0
  15. data/docs/Utils/Routing-Engine.md +248 -0
  16. data/examples/re_upgrade.rb +1 -1
  17. data/examples/re_utils.rb +1 -0
  18. data/examples/vlans.rb +7 -1
  19. data/lib/junos-ez/ip_ports.rb +3 -1
  20. data/lib/junos-ez/ip_ports/classic.rb +49 -14
  21. data/lib/junos-ez/l1_ports.rb +51 -11
  22. data/lib/junos-ez/l2_ports.rb +1 -1
  23. data/lib/junos-ez/l2_ports/vlan.rb +176 -60
  24. data/lib/junos-ez/provider.rb +4 -1
  25. data/lib/junos-ez/system/st_hosts.rb +0 -0
  26. data/lib/junos-ez/system/st_routes.rb +0 -0
  27. data/lib/junos-ez/system/userauths.rb +0 -0
  28. data/lib/junos-ez/system/users.rb +0 -0
  29. data/lib/junos-ez/utils/config.rb +33 -2
  30. data/lib/junos-ez/utils/re.rb +22 -3
  31. data/lib/junos-ez/vlans.rb +5 -3
  32. data/lib/junos-ez/vlans/vlan.rb +6 -0
  33. metadata +14 -13
  34. data/docs/Config_Utils.md +0 -3
  35. data/docs/Filesys_Utils.md +0 -3
  36. data/docs/IPports.md +0 -3
  37. data/docs/L1ports.md +0 -3
  38. data/docs/L2ports.md +0 -3
  39. data/docs/RE_utils.md +0 -3
  40. data/docs/StaticHosts.md +0 -3
  41. data/docs/StaticRoutes.md +0 -3
  42. data/docs/Vlans.md +0 -3
  43. data/lib/junos-ez/system/user_ssh_keys.rb +0 -113
@@ -0,0 +1,78 @@
1
+ # Filesystem Utilities
2
+
3
+ A collection of methods to access filesystem specific functions and information. These methods return data in
4
+ Hash / Array structures so the information can be programmatically accessible, rather than scraping CLI or navigating
5
+ Junos XML.
6
+
7
+ # USAGE
8
+ ```ruby
9
+
10
+ # bind :fs to access the file-system utilities
11
+
12
+ Junos::Ez::FS::Utils( ndev, :fs )
13
+
14
+ # get a listing of my home directory files:
15
+
16
+ pp ndev.fs.ls '/var/home/jeremy', :detail => true
17
+ ->
18
+ {"/var/home/jeremy"=>
19
+ {:fileblocks=>11244,
20
+ :files=>
21
+ "key1.pub"=>
22
+ {:owner=>"jeremy",
23
+ :group=>"staff",
24
+ :links=>1,
25
+ :size=>405,
26
+ :permissions_text=>"-rw-r--r--",
27
+ :permissions=>644,
28
+ :date=>"Apr 27 15:00",
29
+ :date_epoc=>1367074832},
30
+ "template-policy-options.conf"=>
31
+ {:owner=>"jeremy",
32
+ :group=>"staff",
33
+ :links=>1,
34
+ :size=>4320,
35
+ :permissions_text=>"-rw-r--r--",
36
+ :permissions=>644,
37
+ :date=>"Nov 6 2011",
38
+ :date_epoc=>1320564278}},
39
+ :dirs=>
40
+ {".ssh"=>
41
+ {:owner=>"jeremy",
42
+ :group=>"staff",
43
+ :links=>2,
44
+ :size=>512,
45
+ :permissions_text=>"drwxr-xr-x",
46
+ :permissions=>755,
47
+ :date=>"Apr 27 19:48",
48
+ :date_epoc=>1367092112},
49
+ "bak"=>
50
+ {:owner=>"jeremy",
51
+ :group=>"staff",
52
+ :links=>2,
53
+ :size=>512,
54
+ :permissions_text=>"drwxr-xr-x",
55
+ :permissions=>755,
56
+ :date=>"Apr 16 2010",
57
+ :date_epoc=>1271441068}}}}
58
+ ```
59
+
60
+ # METHODS
61
+
62
+ - `cat` - returns the String contents of a file
63
+ - `checksum` - returns the checksum of a file (MD5, SHA1, SHA256 options)
64
+ - `cleanup?` - returns a Hash of files that *would be* removed from "request system storage cleanup"
65
+ - `cleanup!` - "request system storage cleanup" (!! NO CONFIRM !!)
66
+ - `cp!` - copies a file relative on the device filesystem
67
+ - `cwd` - changes the current working directory
68
+ - `pwd` - returns a String of the current working directory
69
+ - `df` - "show system storage"
70
+ - `ls` - "file list", i.e. get a file / directory listing, returns a Hash
71
+ - `mv!` - "file move", i.e. move / rename files
72
+ - `rm!` - "file delete", i.e. deletes files
73
+
74
+ # GORY DETAILS
75
+
76
+ ... more docs comming ...
77
+
78
+
@@ -0,0 +1,248 @@
1
+ # Junos::Ez::RE::Utils
2
+
3
+ A collection of methods to access routing-engine specific functions and information. These methods return data in Hash / Array structures so the information can be programmatically accessible, rather than scraping CLI or navigating Junos XML.
4
+
5
+ # USAGE
6
+
7
+ ```ruby
8
+
9
+ # bind :re to access the routing-engine utitities
10
+ Junos::Ez::RE::Utils( ndev, :re )
11
+
12
+ # show the uptime information on this device
13
+ pp ndev.re.uptime
14
+ ->
15
+ {"re0"=>
16
+ {:time_now=>"2013-04-27 22:28:24 UTC",
17
+ :active_users=>1,
18
+ :load_avg=>[0.08, 0.05, 0.01],
19
+ :uptime=>{:at=>"10:28PM", :ago=>"27 days, 2:58"},
20
+ :time_boot=>{:at=>"2013-03-31 19:30:47 UTC", :ago=>"3w6d 02:57"},
21
+ :protocols_started=>{:at=>"2013-03-31 19:34:53 UTC", :ago=>"3w6d 02:53"},
22
+ :last_config=>
23
+ {:at=>"2013-04-27 19:48:42 UTC", :ago=>"02:39:42", :by=>"jeremy"}}}
24
+ ```
25
+
26
+ # METHODS
27
+
28
+ ## Information
29
+
30
+ - `status` - "show chassis routing-engine" information
31
+ - `uptime` - "show system uptime" information
32
+ - `system_alarms` - "show system alarms" information
33
+ - `chassis_alarms` - "show chassis alarms" information
34
+ - `memory` - "show system memory" information
35
+ - `users` - "show system users" information
36
+
37
+ ## Software Image
38
+
39
+ - `validate_software?` - "request system software validate..."
40
+ - `install_software!` - "request system software add ..."
41
+ - `rollback_software!` - "request system software rollback"
42
+
43
+ ## System Controls
44
+
45
+ - `reboot!` - "request system reboot" (!! NO CONFIRM !!)
46
+ - `shutdown!` - "request system power-off" (!! NO CONFIRM !!)
47
+
48
+ # GORY DETAILS
49
+
50
+ ## status
51
+
52
+ Returns a Hash structure of "show chassis routing-engine" information. Each Hash key is the RE identifier. For example, on a target with a single RE:
53
+ ```ruby
54
+ pp ndev.re.status
55
+ ->
56
+ {"re0"=>
57
+ {:model=>"JUNOSV-FIREFLY RE",
58
+ :serialnumber=>"",
59
+ :temperature=>{:system=>"", :cpu=>""},
60
+ :memory=>{:total_size=>0, :buffer_util=>0},
61
+ :cpu_util=>{:user=>0, :background=>0, :system=>2, :interrupt=>0, :idle=>98},
62
+ :uptime=>
63
+ {:at=>"2013-05-02 17:37:51 UTC",
64
+ :ago=>"3 minutes, 4 seconds",
65
+ :reboot_reason=>"Router rebooted after a normal shutdown."},
66
+ :load_avg=>[0.06, 0.13, 0.07]}}
67
+ ```
68
+
69
+ ## uptime
70
+
71
+ Returns a Hash structure of "show system uptime" information. Each Hash key is the RE identifier. For example, on a target with a single RE:
72
+ ```ruby
73
+ pp ndev.re.uptime
74
+ ->
75
+ {"re0"=>
76
+ {:time_now=>"2013-05-02 17:42:09 UTC",
77
+ :active_users=>0,
78
+ :load_avg=>[0.02, 0.1, 0.06],
79
+ :uptime=>{:at=>"5:42PM", :ago=>"4 mins"},
80
+ :time_boot=>{:at=>"2013-05-02 17:37:51 UTC", :ago=>"00:04:18"},
81
+ :protocols_started=>{:at=>"2013-05-02 17:38:08 UTC", :ago=>"00:04:01"},
82
+ :last_config=>
83
+ {:at=>"2013-04-27 15:00:55 UTC", :ago=>"5d 02:41", :by=>"root"}}}
84
+ ```
85
+ ## system_alarms
86
+
87
+ Returns an Array of Hash structure of "show system alarms" information. If there are no alarms, this method returns `nil`. For example, a target with a single alarm:
88
+ ```ruby
89
+ pp ndev.re.system_alarms
90
+ ->
91
+ [{:at=>"2013-05-02 17:38:03 UTC",
92
+ :class=>"Minor",
93
+ :description=>"Rescue configuration is not set",
94
+ :type=>"Configuration"}]
95
+ ```
96
+
97
+ ## chassis_alarms
98
+
99
+ Returns an Array Hash structure of "show chassis alarms" information. If there are no alarms, this method returns `nil`. For example, a target with no chassis alarms:
100
+ ```ruby
101
+ pp ndev.re.chassis_alarms
102
+ ->
103
+ nil
104
+ ```
105
+
106
+ ## memory
107
+
108
+ Returns a Hash structure of "show system memory" information. Each key is the RE indentifier. A target with a single RE would look like the following. Note that the `:procs` Array is the process array, with each element as a Hash of process specific information.
109
+ ```ruby
110
+ pp ndev.re.memory
111
+ ->
112
+ {"re0"=>
113
+ {:memory_summary=>
114
+ {:total=>{:size=>1035668, :percentage=>100},
115
+ :reserved=>{:size=>18688, :percentage=>1},
116
+ :wired=>{:size=>492936, :percentage=>47},
117
+ :active=>{:size=>184152, :percentage=>17},
118
+ :inactive=>{:size=>65192, :percentage=>6},
119
+ :cache=>{:size=>261140, :percentage=>25},
120
+ :free=>{:size=>12660, :percentage=>1}},
121
+ :procs=>
122
+ [{:name=>"kernel",
123
+ :pid=>0,
124
+ :size=>569704,
125
+ :size_pct=>54.49,
126
+ :resident=>90304,
127
+ :resident_pct=>8.71},
128
+ {:name=>"/sbin/pmap",
129
+ :pid=>2768,
130
+ :size=>4764,
131
+ :size_pct=>0.15,
132
+ :resident=>1000,
133
+ :resident_pct=>0.09},
134
+ {:name=>"file: (mgd) /proc/2766/file (jeremy)",
135
+ :pid=>2765,
136
+ :size=>727896,
137
+ :size_pct=>23.16,
138
+ :resident=>18904,
139
+ :resident_pct=>1.82},
140
+ #
141
+ # snip, omitted full array for sake of sanity ...
142
+ #
143
+ ]}}
144
+ ```
145
+
146
+ ## users
147
+
148
+ Returns a Array structure of "show system users" information. Each Array item is a Hash structure of user information. A target with a single user logged in would look like:
149
+ ```ruby
150
+ pp ndev.re.users
151
+ ->
152
+ [{:name=>"jeremy",
153
+ :tty=>"p0",
154
+ :from=>"192.168.56.1",
155
+ :login_time=>"5:45PM",
156
+ :idle_time=>"",
157
+ :command=>"-cli (cli)"}]
158
+ ```
159
+
160
+ ## validate_software?
161
+
162
+ Performs the equivalent of "request system software validate..." and returns `true` if the software passes validation or a String indicating the error message. The following is an example that simply checks for true:
163
+ ```ruby
164
+ unless ndev.re.validate_software?( file_on_junos )
165
+ puts "The softare does not validate!"
166
+ ndev.close
167
+ exit 1
168
+ end
169
+ ```
170
+
171
+ ## install_software!
172
+
173
+ Performs the equivalent of "request system software add ..." and returns `true` if the operation was successful or a String indicating the error message. The following example illustrates an error message:
174
+
175
+ ```ruby
176
+ puts "Installing image ... please wait ..."
177
+ rc = ndev.re.install_software!( :package => file_on_junos, :no_validate => true )
178
+ if rc != true
179
+ puts rc
180
+ end
181
+ ```
182
+ With the results of the `rc` String:
183
+ ```
184
+ Verified junos-boot-vsrx-12.1I20130415_junos_121_x44_d15.0-576602.tgz signed by PackageDevelopment_12_1_0
185
+ Verified junos-vsrx-12.1I20130415_junos_121_x44_d15.0-576602-domestic signed by PackageDevelopment_12_1_0
186
+
187
+ WARNING: The software that is being installed has limited support.
188
+ WARNING: Run 'file show /etc/notices/unsupported.txt' for details.
189
+
190
+ Available space: -49868 require: 4641
191
+
192
+ WARNING: The /cf filesystem is low on free disk space.
193
+ WARNING: This package requires 4641k free, but there
194
+ WARNING: is only -49868k available.
195
+
196
+ WARNING: This installation attempt will be aborted.
197
+ WARNING: If you wish to force the installation despite these warnings
198
+ WARNING: you may use the 'force' option on the command line.
199
+ ERROR: junos-12.1I20130415_junos_121_x44_d15.0-576602-domestic fails requirements check
200
+ Installation failed for package '/var/tmp/junos-vsrx-domestic.tgz'
201
+ WARNING: Not enough space in /var/tmp to unpack junos-12.1I20130415_junos_121_x44_d15.0-576602.tgz
202
+ WARNING: Use 'request system storage cleanup' and
203
+ WARNING: the 'unlink' option to improve the chances of success
204
+ ```
205
+
206
+ ## rollback_software!
207
+
208
+ Performs the equivalent of "request system software rollback". The result of the operation is returned as a String. For example, a successful rollback would look like this:
209
+ ```ruby
210
+ pp ndev.re.rollback_software!
211
+ ->
212
+ "Restoring boot file package\njunos-12.1I20130422_2129_jni-domestic will become active at next reboot\nWARNING: A reboot is required to load this software correctly\nWARNING: Use the 'request system reboot' command\nWARNING: when software installation is complete"
213
+ ```
214
+ An unsuccessful rollback would look like this:
215
+ ```ruby
216
+ pp ndev.re.rollback_software!
217
+ ->
218
+ "WARNING: Cannot rollback, /packages/junos is not valid"
219
+ ```
220
+
221
+ ## reboot!( opts = {} )
222
+
223
+ Performs the "request system reboot" action. There is **NO** confirmation prompt, so once you've executed this method, the action begins. Once this command executes the NETCONF session to the target will eventually terminate. You can trap the `Net::SSH::Disconnect` exception to detect this event.
224
+
225
+ The option Hash provides for the following controls:
226
+ ```
227
+ :in => Fixnum
228
+ ```
229
+ Instructs Junos to reboot after `:in` minutes from the time of calling `reboot!`
230
+ ```
231
+ :at => String
232
+ ```
233
+ Instructs Junos to reboot at a specific date and time. The format of `:at` is YYYYMMDDHHMM, where HH is the 24-hour (military) time. For example HH = 01 is 1am and HH=13 is 1pm. If you omit the YYYY, MM, or DD options the current values apply. For example `:at => 1730` is 1:30pm today.
234
+
235
+ ## shutdown!( opts = {} )
236
+
237
+ Performs the "request system power-off" action. There is **NO** confirmation prompt, so once you've executed this method, the action begins. Once this command executes the NETCONF session to the target will eventually terminate. You can trap the `Net::SSH::Disconnect` exception to detect this event.
238
+
239
+ The option Hash provides for the following controls:
240
+ ```
241
+ :in => Fixnum
242
+ ```
243
+ Instructs Junos to reboot after `:in` minutes from the time of calling `reboot!`
244
+ ```
245
+ :at => String
246
+ ```
247
+ Instructs Junos to reboot at a specific date and time. The format of `:at` is YYYYMMDDHHMM, where HH is the 24-hour (military) time. For example HH = 01 is 1am and HH=13 is 1pm. If you omit the YYYY, MM, or DD options the current values apply. For example `:at => 1730` is 1:30pm today.
248
+
@@ -73,7 +73,7 @@ unless ndev.re.validate_software?( file_on_junos )
73
73
  exit 1
74
74
  end
75
75
 
76
- puts "Installing image ... place wait ..."
76
+ puts "Installing image ... please wait ..."
77
77
  rc = ndev.re.install_software!( :package => file_on_junos, :no_validate => true )
78
78
  if rc != true
79
79
  puts rc
data/examples/re_utils.rb CHANGED
@@ -24,6 +24,7 @@ puts "OK!"
24
24
  Junos::Ez::Provider( ndev )
25
25
  Junos::Ez::RE::Utils( ndev, :re )
26
26
  Junos::Ez::FS::Utils( ndev, :fs )
27
+ Junos::Ez::Config::Utils( ndev, :cu )
27
28
 
28
29
  binding.pry
29
30
 
data/examples/vlans.rb CHANGED
@@ -1,8 +1,12 @@
1
1
  require 'net/netconf/jnpr'
2
2
  require 'junos-ez/stdlib'
3
3
 
4
- # login information for NETCONF session
4
+ unless ARGV[0]
5
+ puts "You must specify a target"
6
+ exit 1
7
+ end
5
8
 
9
+ # login information for NETCONF session
6
10
  login = { :target => ARGV[0], :username => 'jeremy', :password => 'jeremy1', }
7
11
 
8
12
  ## create a NETCONF object to manage the device and open the connection ...
@@ -15,7 +19,9 @@ $stdout.puts "OK!"
15
19
  Junos::Ez::Provider( ndev )
16
20
  Junos::Ez::Config::Utils( ndev, :cu )
17
21
  Junos::Ez::Vlans::Provider( ndev, :vlans )
22
+ Junos::Ez::L1ports::Provider( ndev, :l1_ports )
18
23
  Junos::Ez::L2ports::Provider( ndev, :l2_ports )
24
+ Junos::Ez::IPports::Provider( ndev, :ip_ports )
19
25
 
20
26
  pp ndev.vlans.list
21
27
  pp ndev.vlans.catalog
@@ -8,7 +8,9 @@ module Junos::Ez::IPports
8
8
  :description, # general description text
9
9
  :tag_id, # VLAN tag-id for vlan-tag enabled ports
10
10
  :mtu, # MTU value as number
11
- :address # ip/prefix as text, e.g. "192.168.10.22/24"
11
+ :address, # ip/prefix as text, e.g. "192.168.10.22/24"
12
+ :acl_in, # input ACL name
13
+ :acl_out, # output ACL name
12
14
  ]
13
15
 
14
16
  def self.Provider( ndev, varsym )
@@ -7,13 +7,13 @@ class Junos::Ez::IPports::Provider::CLASSIC < Junos::Ez::IPports::Provider
7
7
  def xml_at_top
8
8
 
9
9
  # if just the IFD is given as the name, default to unit "0"
10
- @ifd, @ifl = @name.split '.'
11
- @ifl ||= "0"
10
+ @ifd, @ifd_unit = @name.split '.'
11
+ @ifd_unit ||= "0"
12
12
 
13
13
  Nokogiri::XML::Builder.new{ |x| x.configuration{
14
14
  x.interfaces { x.interface { x.name @ifd
15
15
  x.unit {
16
- x.name @ifl
16
+ x.name @ifd_unit
17
17
  return x
18
18
  }
19
19
  }}
@@ -43,14 +43,22 @@ class Junos::Ez::IPports::Provider::CLASSIC < Junos::Ez::IPports::Provider
43
43
 
44
44
  def xml_read_parser( as_xml, as_hash )
45
45
  set_has_status( as_xml, as_hash )
46
-
46
+
47
+ as_hash[:admin] = as_xml.xpath('disable').empty? ? :up : :down
47
48
  ifa_inet = as_xml.xpath('family/inet')
48
49
 
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
50
+ xml_when_item(as_xml.xpath('vlan-id')){ |i| as_hash[:tag_id] = i.text.to_i }
51
+ xml_when_item(as_xml.xpath('description')){ |i| as_hash[:description] = i.text }
52
+ xml_when_item(ifa_inet.xpath('mtu')){ |i| as_hash[:mtu] = i.text.to_i }
53
+
54
+ # @@@ assuming a single IP address; prolly need to be more specific ...
52
55
  as_hash[:address] = ifa_inet.xpath('address/name').text || nil
53
- as_hash[:admin] = as_xml.xpath('disable').empty? ? :up : :down
56
+
57
+ # check for firewall-filters (aka ACLs)
58
+ if (fw_acl = ifa_inet.xpath('filter')[0])
59
+ xml_when_item( fw_acl.xpath('input/filter-name')){ |i| as_hash[:acl_in] = i.text.strip }
60
+ xml_when_item( fw_acl.xpath('output/filter-name')){ |i| as_hash[:acl_out] = i.text.strip }
61
+ end
54
62
 
55
63
  return true
56
64
  end
@@ -61,14 +69,11 @@ class Junos::Ez::IPports::Provider::CLASSIC < Junos::Ez::IPports::Provider
61
69
 
62
70
  def xml_change_address( xml )
63
71
  xml.family { xml.inet {
72
+ # delete the old address and replace it with the new one ...
64
73
  if @has[:address]
65
- xml.address( Netconf::JunosConfig::DELETE ) {
66
- xml.name @has[:address]
67
- }
74
+ xml.address( Netconf::JunosConfig::DELETE ) { xml.name @has[:address] }
68
75
  end
69
- xml.address {
70
- xml.name @should[:address]
71
- }
76
+ xml.address { xml.name @should[:address] }
72
77
  }}
73
78
  end
74
79
 
@@ -81,9 +86,39 @@ class Junos::Ez::IPports::Provider::CLASSIC < Junos::Ez::IPports::Provider
81
86
  xml_set_or_delete( xml, 'mtu', @should[:mtu] )
82
87
  }}
83
88
  end
89
+
90
+ def xml_change_acl_in( xml )
91
+ xml.family { xml.inet { xml.filter { xml.input {
92
+ xml_set_or_delete( xml, 'filter-name', @should[:acl_in] )
93
+ }}}}
94
+ end
95
+
96
+ def xml_change_acl_out( xml )
97
+ xml.family { xml.inet { xml.filter { xml.output {
98
+ xml_set_or_delete( xml, 'filter-name', @should[:acl_out] )
99
+ }}}}
100
+ end
84
101
 
85
102
  end
86
103
 
104
+ ##### ---------------------------------------------------------------
105
+ ##### Resource Methods
106
+ ##### ---------------------------------------------------------------
107
+
108
+ class Junos::Ez::IPports::Provider::CLASSIC
109
+ def status
110
+ got = @ndev.rpc.get_interface_information( :interface_name => @ifd+'.'+@ifd_unit )
111
+ ifs = got.xpath('logical-interface')[0]
112
+ ret_h = {}
113
+ ret_h[:l1_oper_status] = (ifs.xpath('if-config-flags/iff-device-down')[0]) ? :down : :up
114
+ ret_h[:oper_status] = (ifs.xpath('address-family//ifaf-down')[0]) ? :down : :up
115
+ ret_h[:snmp_index] = ifs.xpath('snmp-index').text.to_i
116
+ ret_h[:packets_rx] = ifs.xpath('traffic-statistics/input-packets').text.to_i
117
+ ret_h[:packets_tx] = ifs.xpath('traffic-statistics/output-packets').text.to_i
118
+ ret_h
119
+ end
120
+ end
121
+
87
122
  ##### ---------------------------------------------------------------
88
123
  ##### Provider collection methods
89
124
  ##### ---------------------------------------------------------------