net-ops 0.0.4.pre → 0.0.5.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.
- 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
|