net-ops 0.0.5.pre → 0.0.6.pre

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.
@@ -0,0 +1,6 @@
1
+ conf t
2
+ hostname testhostname
3
+ end
4
+ wr
5
+ reload
6
+ yes
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'net/ops'
3
+ require 'yaml'
4
+
5
+ credentials = YAML.load_file('credentials.yml')
6
+ commands = File.open('commands.txt')
7
+ hosts = File.open('hosts.txt')
8
+
9
+ hosts.each_line do |host|
10
+
11
+ session = Net::Ops::Session.new(host)
12
+ session.open({ username: credentials.fetch('username'),
13
+ password: credentials.fetch('password') })
14
+
15
+ session.privileged { set 'terminal length', 0 }
16
+
17
+ commands.each_line do |command|
18
+ puts @session.run(command)
19
+ end
20
+
21
+ end
@@ -0,0 +1,2 @@
1
+ netops.test
2
+ 192.168.0.104
data/lib/net/ops.rb CHANGED
@@ -2,384 +2,21 @@ require 'yaml'
2
2
  require 'logger'
3
3
  require 'thread/pool'
4
4
 
5
- #Dir['../lib/net/transport/*.rb'].each { |file| require file }
6
- require 'net/transport/ssh'
7
- require 'net/transport/telnet'
5
+ require 'net/ops/version'
6
+ require 'net/ops/task'
7
+ require 'net/ops/parser'
8
+ require 'net/ops/session'
9
+ require 'net/ops/transport/ssh'
10
+ require 'net/ops/transport/telnet'
8
11
 
9
12
  module Net
10
- module Ops
11
-
12
- # Provides a DSL for interacting with Cisco switches and routers.
13
- class Session
14
-
15
- attr_reader :transport
16
- attr_reader :transports
17
-
18
- # Initialize a new session.
19
- #
20
- # @param [String] host the target host.
21
- #
22
- # @param [Hash<Symbol, String>] options an Hash containing the transport options.
23
- # @option options [String] :timeout The timeout before raising an exception while waiting for output.
24
- # @option options [String, Regexp] :prompt A String or a Regexp that match the prompt of the device.
25
- #
26
- # @param [Logger] logger the logger to use.
27
- #
28
- # @return [Session] the new session.
29
- def initialize(host, options = { timeout: 10, prompt: /.+(#|>|\])/ }, logger = nil)
30
- @host = host
31
- @options = options
32
- @transports = []
33
-
34
- setup_logger(logger)
35
-
36
- Net::Ops::Transport.constants.each do |c|
37
- register_transport(c) if Class === Net::Ops::Transport.const_get(c)
38
- end
39
- end
40
-
41
- # Open the session to the device.
42
- #
43
- # @param [Hash<Symbol, String>] credentials an Hash containing the credentials used to login.
44
- # @option credentials [String] :username The username.
45
- # @option credentials [String] :password The password.
46
- #
47
- # @return [void]
48
- # @raise [Net::Ops::TransportUnavailable] if the session cannot be opened.
49
- def open(credentials)
50
- @credentials = credentials
51
-
52
- @logger.debug(@host) { "Opening session as #{ credentials[:username] }" }
53
-
54
- @transports.each do |transport|
55
- @transport ||= transport.open(@host, @options, credentials)
56
- end
57
-
58
- fail Net::Ops::TransportUnavailable unless @transport
59
- end
60
-
61
- # Close the session to the device.
62
- #
63
- # @return [void]
64
- def close
65
- @logger.debug(@host) { 'Closing session' }
66
- @transport.close
67
- @transport = nil
68
- end
69
-
70
- # Measure the latency.
71
- #
72
- # @return [Integer] the time to run and retrieve the output of a command in milliseconds.
73
- def latency
74
- t1 = Time.now
75
- @transport.cmd('')
76
- t2 = Time.now
77
-
78
- (t2 - t1) * 1000.0
79
- end
80
-
81
- # Send the specified command to the device and wait for the output.
82
- #
83
- # @param [String] command the command to run.
84
- # @return [String] the output of the command.
85
- def run(command)
86
- @logger.debug("#{ @host } (#{ get_mode })") { "Executing #{ command }" }
87
-
88
- output = ''
89
- @transport.cmd(command) { |c| output += c }
90
-
91
- # @logger.debug("#{ @host } (#{ get_mode })") { output }
92
- # @logger.warn(@host) { 'Net::Ops::IOSInvalidInput'; puts output } if /nvalid input detected/.match(output)
93
- fail Net::Ops::IOSInvalidInput if /nvalid input detected/.match(output)
94
-
95
- output
96
- end
97
-
98
- # Get the specified item on the device.
99
- # Equivalent to the Cisco show command.
100
- #
101
- # @param item [String] the item to get.
102
- # @return [String] the item.
103
- def get(item)
104
- run("show #{ item }")
105
- end
106
-
107
- # Set the value for the specified item on the device.
108
- #
109
- # @param item [String] the item to configure.
110
- # @param value [String] the value to assign to the item.
111
- # @return [String] the eventual output of the command.
112
- def set(item, value)
113
- run("#{ item } #{ value }")
114
- end
115
-
116
- # Enable the specified item on the device.
117
- #
118
- # @param item [String] the item to enable.
119
- # @return [String] the eventual output of the command.
120
- def enable(item)
121
- run(item)
122
- end
123
-
124
- # Disable the specified item on the device.
125
- # Equivalent to the Cisco no command.
126
- #
127
- # @param item [String] the item to enable.
128
- # @return [String] the eventual output of the command.
129
- def disable(item)
130
- run("no #{ item }")
131
- end
132
-
133
- def zeroize(item)
134
- @logger.debug(@host) { "Executing #{ item } zeroize" }
135
-
136
- @transport.cmd('String' => "#{ item } zeroize", 'Match' => /.+/)
137
- @transport.cmd('yes')
138
- end
139
-
140
- def generate(item, options)
141
- run("#{ item } generate #{ options }")
142
- end
143
-
144
- # Run the specified command in the privileged mode on the device.
145
- #
146
- # @param [String] command the command to run.
147
- # @return [String] the output of the command.
148
- def exec(command)
149
- ensure_mode(:privileged)
150
- run(command)
151
- end
152
-
153
- # Run the specified command in the configuration mode on the device.
154
- #
155
- # @param [String] command the command to run.
156
- # @return [String] the output of the command.
157
- def config(command)
158
- ensure_mode(:configuration)
159
- run(command)
160
- end
161
-
162
- # Save the configuration of the device.
163
- # Equivalent to the Cisco copy running-config startup-config command.
164
- # @return [void]
165
- def write!
166
- ensure_mode(:privileged)
167
- exec('write memory')
168
- end
169
-
170
- # Run the specified block in the privileged mode on the device.
171
- #
172
- # @param [Block] block the block to run.
173
- # @return [void]
174
- def privileged(&block)
175
- ensure_mode(:privileged)
176
- instance_eval(&block)
177
- end
178
-
179
- # Run the specified block in the configuration mode on the device.
180
- #
181
- # @param [Block] block the block to run.
182
- # @return [void]
183
- def configuration(options = nil, &block)
184
- ensure_mode(:configuration)
185
- instance_eval(&block)
186
-
187
- write! if options == :enforce_save
188
- end
189
-
190
- def interface(interface, &block)
191
- ensure_mode(:configuration)
192
-
193
- run("interface #{ interface }")
194
- instance_eval(&block)
195
- end
196
-
197
- def interfaces(interfaces = /.+/, &block)
198
- ints = privileged do
199
- get('interfaces status').select do |int|
200
- interfaces.match("#{ int['short_type'] }#{ int['port_number'] }")
201
- end
202
- end
203
-
204
- ints.each do |int|
205
- interface("#{ int['short_type'] }#{ int['port_number'] }") do
206
- instance_eval(&block)
207
- end
208
- end
209
- end
210
-
211
- def lines(lines, &block)
212
- ensure_mode(:configuration)
213
-
214
- run("line #{ lines }")
215
- instance_eval(&block)
216
- end
217
-
218
- private
219
-
220
- def register_transport(klass)
221
- @logger.debug(@host) { "Registering transport #{ klass }" }
222
- @transports << Net::Ops::Transport.const_get(klass)
223
- end
224
-
225
- # Create a default logger if none is specified.
226
- #
227
- # @param [Logger] logger the logger to use.
228
- # @return [void]
229
- def setup_logger(logger = nil)
230
- # If a logger is specified we replace the existing.
231
- @logger = logger
232
13
 
233
- # Otherwise we create a new one.
234
- logger = Logger.new(STDOUT)
235
- logger.level = Logger::DEBUG
236
- @logger ||= logger
237
- end
238
-
239
- # Get the current command mode.
240
- #
241
- # @return [Symbol] the current command mode.
242
- def get_mode
243
- prompt = ''
244
- @transport.cmd('') { |c| prompt += c }
245
- match = /(?<hostname>[^\(-\)]+)(\((?<text>[\w\-]+)\))?(?<char>#|>)/.match(prompt)
246
-
247
- mode = nil
248
-
249
- if match && match['char']
250
-
251
- mode = case match['char']
252
- when '>' then :user
253
- when '#' then :privileged
254
- end
255
-
256
- end
257
-
258
- if match && match['text']
259
- mode = match['text'].to_sym
260
- end
261
-
262
- mode
263
- end
264
-
265
- # Ensure the CLI is currently in the specified command mode.
266
- #
267
- # @param [Symbol] mode the target command mode.
268
- # @return [void]
269
- def ensure_mode(mode)
270
- case mode
271
-
272
- when :user
273
- run('end') if configuration?
274
-
275
- when :privileged
276
- run('end') if configuration?
277
- enable_privileged(@credentials[:password]) if user?
278
-
279
- when :configuration
280
- run('configure terminal') unless configuration?
281
-
282
- end
283
- end
284
-
285
- # Check if the CLI is in user mode.
286
- #
287
- # @return [Boolean]
288
- def user?
289
- get_mode == :user
290
- end
291
-
292
- # Check if the CLI is in privileged mode.
293
- #
294
- # @return [Boolean]
295
- def privileged?
296
- get_mode == :privileged
297
- end
298
-
299
- # Check if the CLI is in configuration mode.
300
- #
301
- # @return [Boolean]
302
- def configuration?
303
- get_mode.to_s.include?('config')
304
- end
305
-
306
- # Go from user mode to privileged mode.
307
- #
308
- # @param [String] the enable password.
309
- # @return [void]
310
- def enable_privileged(password)
311
- @transport.cmd('String' => 'enable', 'Match' => /.+assword.+/)
312
- @transport.cmd(password)
313
- end
314
-
315
- end
316
-
317
- class Parser
318
-
319
- def initialize(file)
320
- @regexs = YAML.load_file(file)
321
- end
322
-
323
- def parse(command, output)
324
- results = []
325
- path = explore_tree(command.split(/ /))
326
-
327
- if path.has_key?('regex')
328
- regex = Regexp.new(path.fetch('regex').delete(' '))
329
-
330
- output.each_line do |line|
331
- results << regex.match(line) if regex.match(line)
332
- end
333
-
334
- else results = output
335
- end
336
-
337
- results
338
- end
339
-
340
- private
341
-
342
- def explore_tree(path)
343
- level = @regexs['cisco']
344
-
345
- path.each { |p| level[p] ? level = level[p] : break }
346
-
347
- level
348
- end
349
-
350
- end
351
-
352
- class Task
353
- include Net::Ops
354
-
355
- def initialize(id)
356
- @id = id
357
-
358
- @logger = Logger.new(STDOUT)
359
- @logger.level = Logger::INFO
360
- end
361
-
362
- def log(severity, message)
363
- @logger.add(severity, message, @id)
364
- end
365
-
366
- def info(message)
367
- log(Logger::INFO, message)
368
- end
369
-
370
- def warn(message)
371
- log(Logger::WARN, message)
372
- end
373
-
374
- def error(message)
375
- log(Logger::ERROR, message)
376
- end
377
-
378
- end
14
+ #
15
+ module Ops
379
16
 
380
- #
381
17
  class TransportUnavailable < Exception; end
382
- class IOSInvalidInput < Exception; end
18
+ class IOSInvalidInput < Exception; end
383
19
 
384
20
  end
21
+
385
22
  end
@@ -0,0 +1,39 @@
1
+ module Net; module Ops
2
+
3
+ #
4
+ class Parser
5
+
6
+ def initialize(file)
7
+ @regexs = YAML.load_file(file)
8
+ end
9
+
10
+ def parse(command, output)
11
+ results = []
12
+ path = explore_tree(command.split(/ /))
13
+
14
+ if path.has_key?('regex')
15
+ regex = Regexp.new(path.fetch('regex').delete(' '))
16
+
17
+ output.each_line do |line|
18
+ results << regex.match(line) if regex.match(line)
19
+ end
20
+
21
+ else results = output
22
+ end
23
+
24
+ results
25
+ end
26
+
27
+ private
28
+
29
+ def explore_tree(path)
30
+ level = @regexs['cisco']
31
+
32
+ path.each { |p| level[p] ? level = level[p] : break }
33
+
34
+ level
35
+ end
36
+
37
+ end
38
+
39
+ end; end