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.
data/regexs.yml ADDED
@@ -0,0 +1,12 @@
1
+ cisco:
2
+ interfaces:
3
+ status:
4
+ regex: >
5
+ (?<short_type>Fa|Gi|Te)
6
+ (?<port_number>\d+\/\d+(\/\d+)?)\s+
7
+ (?<description>.+)?\s+
8
+ (?<status>connected|notconnect|disabled|err-disabled)\s+
9
+ (?<vlan>\w+|\d+)\s+
10
+ (?<duplex>auto|(a-)?full)\s+
11
+ (?<speed>auto|a-1000|10G)\s+
12
+ (?<type>.+)
@@ -0,0 +1,144 @@
1
+ # Task for converting hostname to lowercase.
2
+ # Handle devices with SSH by regenerating crypto key.
3
+
4
+ require '../lib/net/ops'
5
+
6
+ class DowncaseHostnameTask < Net::Ops::Task
7
+
8
+ def initialize(host, options, credentials)
9
+ @host = host
10
+ @options = options
11
+ @credentials = credentials
12
+
13
+ @session = Session.new(host, options)
14
+
15
+ super(host)
16
+ end
17
+
18
+ # This is where all the logic is.
19
+ def work
20
+
21
+ # First we need to open the session.
22
+ # I create a helper because we will have to
23
+ # (dis)connect several times during this task.
24
+ connect
25
+
26
+ # Set terminal length to 0 otherwise too long outputs will cause
27
+ # Net::Telnet to timeout while waiting for the prompt.
28
+ @session.privileged { set 'terminal length', 0 }
29
+
30
+ # Check ip http secure-server
31
+ https = /^ip http secure-server/.match(@session.get('run | i ip http'))
32
+
33
+ # Get hostname from show version.
34
+ match = /(?<hostname>.+)\s+uptime.+/.match(@session.get('version'))
35
+
36
+ # Check if we found the hostname
37
+ # and convert it if needed.
38
+ # `match['hostname'].downcase!` return nil
39
+ # if the hostname is already in lowercase.
40
+ if !https && match && match['hostname'].downcase!
41
+
42
+ # If we are connected using SSH we enable Telnet
43
+ # in case bad crypto key prevent us from logging.
44
+ enable_telnet if ssh?
45
+
46
+ # Convert the hostname
47
+ info "Converting #{ match['hostname'] } => #{ match['hostname'].downcase }"
48
+ @session.configuration(:enforce_save) { set 'hostname', match['hostname'].downcase }
49
+
50
+ # If SSH is enabled regenerate crypto key
51
+ # and verify SSH is still working.
52
+ if ssh?
53
+
54
+ # Delete the existing crypto key
55
+ # then regenerate it.
56
+ regenerate_crypto
57
+
58
+ # Close the session and reopen it
59
+ # to see if we are still able to
60
+ # connect via SSH.
61
+ info 'Verifying SSH is still working'
62
+ reconnect
63
+
64
+ # If SSH is still working we can disable Telnet.
65
+ if ssh?
66
+ info 'Hooray SSH is still working !'
67
+ disable_telnet
68
+ else warn 'SSH is not working :('
69
+ end
70
+
71
+ end
72
+
73
+ elsif match && !match['hostname'].downcase! then info 'Nothing to do'
74
+ else error 'Unable to find hostname'; end
75
+
76
+ @session.close
77
+ end
78
+
79
+ # Below are the helpers methods.
80
+ # I wrote them to be DRY and reduce code.
81
+
82
+ # Open the session and show the transport used.
83
+ def connect
84
+ info "Connecting to #{ @host }"
85
+
86
+ begin @session.open(@credentials)
87
+ rescue Exception => e
88
+ error e.message
89
+ end
90
+
91
+ info "Transport is #{ @session.transport.class }"
92
+ end
93
+
94
+ # Alias for session.close
95
+ def disconnect
96
+ @session.close
97
+ end
98
+
99
+ # Disconnect, then reconnect.
100
+ def reconnect
101
+ disconnect; connect
102
+ end
103
+
104
+ # True if the transport it SSH.
105
+ def ssh?
106
+ @session.transport.class.to_s.include?('SSH')
107
+ end
108
+
109
+ # Enable Telnet and SSH on all VTY lines.
110
+ def enable_telnet
111
+ info 'Enabling Telnet'
112
+
113
+ @session.configuration(:enforce_save) do
114
+ lines('vty 0 4') { set 'transport input', 'ssh telnet' }
115
+ # lines('vty 5 15') { set 'transport input', 'ssh telnet' }
116
+ end
117
+ end
118
+
119
+ # Set SSH only on all VTY lines.
120
+ def disable_telnet
121
+ info 'Disabling Telnet'
122
+
123
+ @session.configuration(:enforce_save) do
124
+ lines('vty 0 4') { set 'transport input', 'ssh' }
125
+ # lines('vty 5 15') { set 'transport input', 'ssh' }
126
+ end
127
+ end
128
+
129
+ # Delete the crypto key then regenerate it.
130
+ def regenerate_crypto
131
+ info 'Regenerate crypto key'
132
+
133
+ @session.configuration(:enforce_save) do
134
+ zeroize 'crypto key'
135
+ begin
136
+ generate 'crypto key', 'rsa general-keys modulus 2048'
137
+ rescue Exception => e
138
+ generate 'crypto key', 'rsa modulus 2048'
139
+ end
140
+ set 'ip ssh version', 2
141
+ end
142
+ end
143
+
144
+ end
data/tasks/test.rb ADDED
@@ -0,0 +1,21 @@
1
+ require './downcase_hostname_task'
2
+
3
+ hosts = %w( 192.168.0.104 )
4
+
5
+ credentials = YAML.load_file('credentials.yml')
6
+
7
+
8
+ options = { timeout: 30, prompt: /.+(#|>)/ }
9
+ credentials = { username: credentials.fetch('username'),
10
+ password: credentials.fetch('username') }
11
+
12
+ pool = Thread.pool(10)
13
+
14
+ hosts.each do |host|
15
+ # pool.process do
16
+ t = DowncaseHostnameTask.new(host, options, credentials)
17
+ t.work
18
+ # end
19
+ end
20
+
21
+ pool.shutdown
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-ops
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5.pre
4
+ version: 0.0.6.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maxime Mouchet
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-16 00:00:00.000000000 Z
11
+ date: 2013-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thread
@@ -38,16 +38,61 @@ dependencies:
38
38
  - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.0.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  description: Framework to automate daily operations on network devices.
42
70
  email:
43
- - max@maxmouchet.com
71
+ - mouchet.max@gmail.com
44
72
  executables: []
45
73
  extensions: []
46
74
  extra_rdoc_files: []
47
75
  files:
76
+ - .gitignore
77
+ - Gemfile
78
+ - LICENSE
79
+ - README.md
80
+ - Rakefile
81
+ - examples/basic_script.rb
82
+ - examples/commands.txt
83
+ - examples/exec_file.rb
84
+ - examples/hosts.txt
48
85
  - lib/net/ops.rb
49
- - lib/net/transport/ssh.rb
50
- - lib/net/transport/telnet.rb
86
+ - lib/net/ops/parser.rb
87
+ - lib/net/ops/session.rb
88
+ - lib/net/ops/task.rb
89
+ - lib/net/ops/transport/ssh.rb
90
+ - lib/net/ops/transport/telnet.rb
91
+ - lib/net/ops/version.rb
92
+ - net-ops.gemspec
93
+ - regexs.yml
94
+ - tasks/downcase_hostname_task.rb
95
+ - tasks/test.rb
51
96
  homepage: http://github.com/maxmouchet/qscripts
52
97
  licenses:
53
98
  - MIT
@@ -1,39 +0,0 @@
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
@@ -1,53 +0,0 @@
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