net-ops 0.0.4.pre → 0.0.5.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/net/ops.rb +47 -46
- data/lib/net/transport/ssh.rb +39 -0
- data/lib/net/transport/telnet.rb +53 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ddd5aa75208c9e4c9cca7e3b132134453117747
|
4
|
+
data.tar.gz: 7f7cb228b4234a18e901c3d0bf77d19a0c637c90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 024cbbd43efc3e9381db9fa65446fee4f08626cb424cebeefefe04ec039f9679f23cd85d9d6fcbde32f95cc956af0f0212b5f1a089164ecb107c47f106ff8ad0
|
7
|
+
data.tar.gz: b74d3628a96ae7753f37268c5031be99251ee92321b3985255bdb2a209274211fd189e9ec4a0b9cd1088cd73aab24c52e105829af685321de3434d1ac5afcfb8
|
data/lib/net/ops.rb
CHANGED
@@ -2,17 +2,19 @@ require 'yaml'
|
|
2
2
|
require 'logger'
|
3
3
|
require 'thread/pool'
|
4
4
|
|
5
|
-
Dir['../lib/net/transport/*.rb'].each { |file| require file }
|
5
|
+
#Dir['../lib/net/transport/*.rb'].each { |file| require file }
|
6
|
+
require 'net/transport/ssh'
|
7
|
+
require 'net/transport/telnet'
|
6
8
|
|
7
9
|
module Net
|
8
10
|
module Ops
|
9
|
-
|
11
|
+
|
10
12
|
# Provides a DSL for interacting with Cisco switches and routers.
|
11
13
|
class Session
|
12
|
-
|
14
|
+
|
13
15
|
attr_reader :transport
|
14
16
|
attr_reader :transports
|
15
|
-
|
17
|
+
|
16
18
|
# Initialize a new session.
|
17
19
|
#
|
18
20
|
# @param [String] host the target host.
|
@@ -24,14 +26,14 @@ module Net
|
|
24
26
|
# @param [Logger] logger the logger to use.
|
25
27
|
#
|
26
28
|
# @return [Session] the new session.
|
27
|
-
def initialize(host, options = { timeout: 10, prompt: /.+(
|
29
|
+
def initialize(host, options = { timeout: 10, prompt: /.+(#|>|\])/ }, logger = nil)
|
28
30
|
@host = host
|
29
31
|
@options = options
|
30
|
-
@transports = []
|
31
|
-
|
32
|
+
@transports = []
|
33
|
+
|
32
34
|
setup_logger(logger)
|
33
|
-
|
34
|
-
Net::Ops::Transport.constants.each do |c|
|
35
|
+
|
36
|
+
Net::Ops::Transport.constants.each do |c|
|
35
37
|
register_transport(c) if Class === Net::Ops::Transport.const_get(c)
|
36
38
|
end
|
37
39
|
end
|
@@ -48,7 +50,7 @@ module Net
|
|
48
50
|
@credentials = credentials
|
49
51
|
|
50
52
|
@logger.debug(@host) { "Opening session as #{ credentials[:username] }" }
|
51
|
-
|
53
|
+
|
52
54
|
@transports.each do |transport|
|
53
55
|
@transport ||= transport.open(@host, @options, credentials)
|
54
56
|
end
|
@@ -86,13 +88,13 @@ module Net
|
|
86
88
|
output = ''
|
87
89
|
@transport.cmd(command) { |c| output += c }
|
88
90
|
|
89
|
-
@logger.debug("#{ @host } (#{ get_mode })") { output }
|
91
|
+
# @logger.debug("#{ @host } (#{ get_mode })") { output }
|
90
92
|
# @logger.warn(@host) { 'Net::Ops::IOSInvalidInput'; puts output } if /nvalid input detected/.match(output)
|
91
93
|
fail Net::Ops::IOSInvalidInput if /nvalid input detected/.match(output)
|
92
|
-
|
94
|
+
|
93
95
|
output
|
94
96
|
end
|
95
|
-
|
97
|
+
|
96
98
|
# Get the specified item on the device.
|
97
99
|
# Equivalent to the Cisco show command.
|
98
100
|
#
|
@@ -110,7 +112,7 @@ module Net
|
|
110
112
|
def set(item, value)
|
111
113
|
run("#{ item } #{ value }")
|
112
114
|
end
|
113
|
-
|
115
|
+
|
114
116
|
# Enable the specified item on the device.
|
115
117
|
#
|
116
118
|
# @param item [String] the item to enable.
|
@@ -127,14 +129,14 @@ module Net
|
|
127
129
|
def disable(item)
|
128
130
|
run("no #{ item }")
|
129
131
|
end
|
130
|
-
|
132
|
+
|
131
133
|
def zeroize(item)
|
132
134
|
@logger.debug(@host) { "Executing #{ item } zeroize" }
|
133
|
-
|
135
|
+
|
134
136
|
@transport.cmd('String' => "#{ item } zeroize", 'Match' => /.+/)
|
135
137
|
@transport.cmd('yes')
|
136
138
|
end
|
137
|
-
|
139
|
+
|
138
140
|
def generate(item, options)
|
139
141
|
run("#{ item } generate #{ options }")
|
140
142
|
end
|
@@ -184,37 +186,37 @@ module Net
|
|
184
186
|
|
185
187
|
write! if options == :enforce_save
|
186
188
|
end
|
187
|
-
|
189
|
+
|
188
190
|
def interface(interface, &block)
|
189
191
|
ensure_mode(:configuration)
|
190
|
-
|
192
|
+
|
191
193
|
run("interface #{ interface }")
|
192
194
|
instance_eval(&block)
|
193
195
|
end
|
194
|
-
|
196
|
+
|
195
197
|
def interfaces(interfaces = /.+/, &block)
|
196
198
|
ints = privileged do
|
197
|
-
get('interfaces status').select do |int|
|
199
|
+
get('interfaces status').select do |int|
|
198
200
|
interfaces.match("#{ int['short_type'] }#{ int['port_number'] }")
|
199
201
|
end
|
200
202
|
end
|
201
|
-
|
203
|
+
|
202
204
|
ints.each do |int|
|
203
205
|
interface("#{ int['short_type'] }#{ int['port_number'] }") do
|
204
206
|
instance_eval(&block)
|
205
207
|
end
|
206
208
|
end
|
207
209
|
end
|
208
|
-
|
210
|
+
|
209
211
|
def lines(lines, &block)
|
210
212
|
ensure_mode(:configuration)
|
211
|
-
|
213
|
+
|
212
214
|
run("line #{ lines }")
|
213
215
|
instance_eval(&block)
|
214
216
|
end
|
215
217
|
|
216
218
|
private
|
217
|
-
|
219
|
+
|
218
220
|
def register_transport(klass)
|
219
221
|
@logger.debug(@host) { "Registering transport #{ klass }" }
|
220
222
|
@transports << Net::Ops::Transport.const_get(klass)
|
@@ -229,8 +231,7 @@ module Net
|
|
229
231
|
@logger = logger
|
230
232
|
|
231
233
|
# Otherwise we create a new one.
|
232
|
-
|
233
|
-
logger = Logger.new('log.log')
|
234
|
+
logger = Logger.new(STDOUT)
|
234
235
|
logger.level = Logger::DEBUG
|
235
236
|
@logger ||= logger
|
236
237
|
end
|
@@ -240,9 +241,9 @@ module Net
|
|
240
241
|
# @return [Symbol] the current command mode.
|
241
242
|
def get_mode
|
242
243
|
prompt = ''
|
243
|
-
@transport.cmd('') { |c| prompt += c }
|
244
|
+
@transport.cmd('') { |c| prompt += c }
|
244
245
|
match = /(?<hostname>[^\(-\)]+)(\((?<text>[\w\-]+)\))?(?<char>#|>)/.match(prompt)
|
245
|
-
|
246
|
+
|
246
247
|
mode = nil
|
247
248
|
|
248
249
|
if match && match['char']
|
@@ -252,12 +253,12 @@ module Net
|
|
252
253
|
when '#' then :privileged
|
253
254
|
end
|
254
255
|
|
255
|
-
end
|
256
|
-
|
256
|
+
end
|
257
|
+
|
257
258
|
if match && match['text']
|
258
259
|
mode = match['text'].to_sym
|
259
260
|
end
|
260
|
-
|
261
|
+
|
261
262
|
mode
|
262
263
|
end
|
263
264
|
|
@@ -273,7 +274,7 @@ module Net
|
|
273
274
|
|
274
275
|
when :privileged
|
275
276
|
run('end') if configuration?
|
276
|
-
enable_privileged(@credentials[
|
277
|
+
enable_privileged(@credentials[:password]) if user?
|
277
278
|
|
278
279
|
when :configuration
|
279
280
|
run('configure terminal') unless configuration?
|
@@ -312,7 +313,7 @@ module Net
|
|
312
313
|
end
|
313
314
|
|
314
315
|
end
|
315
|
-
|
316
|
+
|
316
317
|
class Parser
|
317
318
|
|
318
319
|
def initialize(file)
|
@@ -320,16 +321,16 @@ module Net
|
|
320
321
|
end
|
321
322
|
|
322
323
|
def parse(command, output)
|
323
|
-
results = []
|
324
|
+
results = []
|
324
325
|
path = explore_tree(command.split(/ /))
|
325
|
-
|
326
|
+
|
326
327
|
if path.has_key?('regex')
|
327
328
|
regex = Regexp.new(path.fetch('regex').delete(' '))
|
328
|
-
|
329
|
+
|
329
330
|
output.each_line do |line|
|
330
331
|
results << regex.match(line) if regex.match(line)
|
331
332
|
end
|
332
|
-
|
333
|
+
|
333
334
|
else results = output
|
334
335
|
end
|
335
336
|
|
@@ -342,40 +343,40 @@ module Net
|
|
342
343
|
level = @regexs['cisco']
|
343
344
|
|
344
345
|
path.each { |p| level[p] ? level = level[p] : break }
|
345
|
-
|
346
|
+
|
346
347
|
level
|
347
348
|
end
|
348
349
|
|
349
350
|
end
|
350
|
-
|
351
|
+
|
351
352
|
class Task
|
352
353
|
include Net::Ops
|
353
354
|
|
354
355
|
def initialize(id)
|
355
356
|
@id = id
|
356
|
-
|
357
|
+
|
357
358
|
@logger = Logger.new(STDOUT)
|
358
359
|
@logger.level = Logger::INFO
|
359
360
|
end
|
360
|
-
|
361
|
+
|
361
362
|
def log(severity, message)
|
362
363
|
@logger.add(severity, message, @id)
|
363
364
|
end
|
364
|
-
|
365
|
+
|
365
366
|
def info(message)
|
366
367
|
log(Logger::INFO, message)
|
367
368
|
end
|
368
|
-
|
369
|
+
|
369
370
|
def warn(message)
|
370
371
|
log(Logger::WARN, message)
|
371
372
|
end
|
372
|
-
|
373
|
+
|
373
374
|
def error(message)
|
374
375
|
log(Logger::ERROR, message)
|
375
376
|
end
|
376
377
|
|
377
378
|
end
|
378
|
-
|
379
|
+
|
379
380
|
#
|
380
381
|
class TransportUnavailable < Exception; end
|
381
382
|
class IOSInvalidInput < Exception; end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'net/ssh/telnet'
|
2
|
+
|
3
|
+
module Net
|
4
|
+
module Ops
|
5
|
+
module Transport
|
6
|
+
|
7
|
+
#
|
8
|
+
class SSH
|
9
|
+
|
10
|
+
# Open an SSH session to the specified host using net/ssh/telnet.
|
11
|
+
#
|
12
|
+
# @param host [String] the destination host.
|
13
|
+
# @param options [Hash]
|
14
|
+
# @param credentials [Hash] credentials to use to connect.
|
15
|
+
def self.open(host, options, credentials)
|
16
|
+
session = nil
|
17
|
+
|
18
|
+
ssh = Net::SSH.start(host, credentials[:username], :password => credentials[:password])
|
19
|
+
session = Net::SSH::Telnet.new('Session' => ssh,
|
20
|
+
'Timeout' => options[:timeout],
|
21
|
+
'Prompt' => options[:prompt])
|
22
|
+
|
23
|
+
rescue Errno::ECONNREFUSED => e
|
24
|
+
session = nil
|
25
|
+
|
26
|
+
rescue Net::SSH::AuthenticationFailed => e
|
27
|
+
session = nil
|
28
|
+
|
29
|
+
rescue Exception => e
|
30
|
+
session = nil
|
31
|
+
|
32
|
+
return session
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'net/telnet'
|
2
|
+
|
3
|
+
module Net
|
4
|
+
module Ops
|
5
|
+
module Transport
|
6
|
+
|
7
|
+
#
|
8
|
+
class Telnet
|
9
|
+
|
10
|
+
# Open a Telnet session to the specified host using net/ssh.
|
11
|
+
#
|
12
|
+
# @param host [String] the destination host.
|
13
|
+
# @param options [Hash]
|
14
|
+
# @param credentials [Hash] credentials to use to connect.
|
15
|
+
def self.open(host, options, credentials)
|
16
|
+
session = nil
|
17
|
+
|
18
|
+
session = Net::Telnet.new('Host' => host,
|
19
|
+
'Timeout' => options[:timeout],
|
20
|
+
'Prompt' => options[:prompt])
|
21
|
+
|
22
|
+
output = ''
|
23
|
+
session.cmd('String' => '', 'Match' => /.+/) { |c| output += c }
|
24
|
+
|
25
|
+
if /[Uu]sername:/.match(output) then
|
26
|
+
session.cmd('String' => credentials[:username],
|
27
|
+
'Match' => /.+/)
|
28
|
+
session.cmd(credentials[:password])
|
29
|
+
end
|
30
|
+
|
31
|
+
if /[Pp]assword:/.match(output) then
|
32
|
+
session.cmd(credentials[:password])
|
33
|
+
end
|
34
|
+
|
35
|
+
return session
|
36
|
+
|
37
|
+
rescue Errno::ECONNREFUSED => e
|
38
|
+
session = nil
|
39
|
+
|
40
|
+
rescue Net::OpenTimeout => e
|
41
|
+
session = nil
|
42
|
+
|
43
|
+
rescue Exception => e
|
44
|
+
session = nil
|
45
|
+
|
46
|
+
return session
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: net-ops
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maxime Mouchet
|
@@ -38,7 +38,7 @@ dependencies:
|
|
38
38
|
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.0.2
|
41
|
-
description: Framework
|
41
|
+
description: Framework to automate daily operations on network devices.
|
42
42
|
email:
|
43
43
|
- max@maxmouchet.com
|
44
44
|
executables: []
|
@@ -46,6 +46,8 @@ extensions: []
|
|
46
46
|
extra_rdoc_files: []
|
47
47
|
files:
|
48
48
|
- lib/net/ops.rb
|
49
|
+
- lib/net/transport/ssh.rb
|
50
|
+
- lib/net/transport/telnet.rb
|
49
51
|
homepage: http://github.com/maxmouchet/qscripts
|
50
52
|
licenses:
|
51
53
|
- MIT
|