moob 0.1.0

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/COPYING ADDED
@@ -0,0 +1,4 @@
1
+ Copyright (c) 2011, Pierre Carrier <pierre@gcarrier.fr>
2
+
3
+ Permission is granted to copy, modify and/or distribute this work and/or
4
+ license, without conditions.
data/bin/moob ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'moob'
5
+
6
+ options = {
7
+ :action => :jnlp,
8
+ :type => :idrac6,
9
+ :machines => []
10
+ }
11
+
12
+ OptionParser.new do |opts|
13
+ opts.on '-l', '--list',
14
+ 'List LOM types' do
15
+ Moob::TYPES.each do |k, v|
16
+ puts "#{k} (#{v.name})"
17
+ end
18
+ exit 0
19
+ end
20
+ opts.on '-t', '--type t',
21
+ 'LOM type (idrac6 by default)' do |t|
22
+ options[:type] = t.to_sym
23
+ end
24
+ opts.on '-u', '--username u',
25
+ 'LOM username' do |u|
26
+ options[:username] = u
27
+ end
28
+ opts.on '-p', '--password p',
29
+ 'LOM password' do |p|
30
+ options[:password] = p
31
+ end
32
+
33
+ opts.on '-m', '--machines a,b,c', Array,
34
+ 'Comma-separated list of machines' do |m|
35
+ options[:machines] = m
36
+ end
37
+ end.parse!
38
+
39
+ if options[:machines].empty?
40
+ $stderr.puts 'No machines selected.'
41
+ exit 1
42
+ end
43
+
44
+ options[:machines].each do |h|
45
+ case options[:action]
46
+ when :jnlp
47
+ Moob.start_jnlp options[:type], h, options
48
+ end
49
+ end
data/lib/moob.rb ADDED
@@ -0,0 +1,48 @@
1
+ require 'socket'
2
+ require 'cgi'
3
+ require 'patron'
4
+
5
+ module Moob
6
+ VERSION = [0,1,0]
7
+
8
+ autoload :BaseLom, 'moob/baselom.rb'
9
+ autoload :Idrac6, 'moob/idrac6.rb'
10
+ autoload :Megatrends, 'moob/megatrends.rb'
11
+ autoload :SunILom, 'moob/sunilom.rb'
12
+
13
+ TYPES = {
14
+ :idrac6 => Idrac6,
15
+ :megatrends => Megatrends,
16
+ :sun => SunILom
17
+ }
18
+
19
+ class ResponseError < Exception
20
+ def initialize response
21
+ @response = response
22
+ end
23
+ def to_s
24
+ "#{@response.url} failed (status #{@response.status})"
25
+ end
26
+ end
27
+
28
+ def self.start_jnlp type, hostname, options = {}
29
+
30
+ lom = TYPES[type].new hostname, options
31
+ jnlp = lom.authenticate.jnlp
32
+
33
+ unless jnlp[/<\/jnlp>/]
34
+ raise RuntimeError.new "Invalid JNLP file (\"#{jnlp}\")"
35
+ end
36
+
37
+ filepath = "/tmp/#{hostname}.jnlp"
38
+ File.open filepath, 'w' do |f|
39
+ f.write jnlp
40
+ end
41
+
42
+ system "javaws #{filepath}"
43
+ end
44
+
45
+ def self.cmdline
46
+ start_jnlp :megatrends, 'brenda.lom.sto.spotify.net'
47
+ end
48
+ end
@@ -0,0 +1,34 @@
1
+ class Moob::BaseLom
2
+ @@name = 'Unknown'
3
+
4
+ def initialize hostname, options = {}
5
+ @hostname = hostname
6
+ @username = options[:username]
7
+ @password = options[:password]
8
+
9
+ @session = Patron::Session.new
10
+ @session.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; '\
11
+ 'Intel Mac OS X 10.7; rv:5.0.1) Gecko/20100101 Firefox/5.0.1'
12
+ @session.base_url = "https://#{hostname}/"
13
+ @session.connect_timeout = 10_000
14
+ @session.timeout = 10_000
15
+ @session.insecure = true
16
+ @session.ignore_content_length = true
17
+ end
18
+
19
+ def jnlp
20
+ raise new NoMethodError
21
+ end
22
+
23
+ def self.name
24
+ @@name
25
+ end
26
+
27
+ protected
28
+ # Get rid of security checks.
29
+ # Might break some features,
30
+ # please let me know if that's the case!
31
+ def desecurize_jnlp jnlp
32
+ jnlp.sub /<security>.*<\/security>/m, ''
33
+ end
34
+ end
@@ -0,0 +1,49 @@
1
+ class Moob::Idrac6 < Moob::BaseLom
2
+ @@name = 'Dell iDrac 6'
3
+
4
+ def initialize hostname, options = {}
5
+ super hostname, options
6
+ @username ||= 'root'
7
+ @password ||= 'calvin'
8
+ end
9
+
10
+ def authenticate
11
+ @session.handle_cookies nil
12
+ start = @session.get 'start.html'
13
+ raise ResponseError.new start unless start.status == 200
14
+
15
+ auth = @session.post 'data/login',
16
+ "user=#{@username}&password=#{@password}"
17
+ raise ResponseError.new auth unless auth.status == 200
18
+
19
+ result_match = auth.body.match /<authResult>([^<]+)<\/authResult>/
20
+ raise Exception.new 'Cannot find auth result' unless result_match
21
+ result_code = result_match[1]
22
+ unless result_code == "0"
23
+ raise Exception.new "Auth failed with: \"#{auth.body}\""
24
+ end
25
+ return self
26
+ end
27
+
28
+ def jnlp
29
+ idx = @session.get 'index.html'
30
+ raise ResponseError.new idx unless idx.status == 200
31
+
32
+ name_match = idx.body.match /var DnsName += +"([^"]+)"/
33
+ raise Exception.new 'Couldn\'t find the DNS name' unless name_match
34
+ dns_name = name_match[1]
35
+
36
+ sys_match = idx.body.match /var sysNameStr += +"([^"]+)"/
37
+ raise Exception.new 'Couldn\'t find the system name' unless name_match
38
+ sys_name = sys_match[1] # eg PowerEdge R610
39
+
40
+ # eg escaped "idrac-D4MHZ4J, PowerEdge R610, User:root"
41
+ title = CGI::escape "#{dns_name}, #{sys_name}, User:#{@username}"
42
+ path = "viewer.jnlp(#{@hostname}@0@#{title}@#{Time.now.to_i * 1000})"
43
+
44
+ viewer = @session.get path
45
+ raise ResponseError.new viewer unless viewer.status == 200
46
+
47
+ return desecurize_jnlp viewer.body
48
+ end
49
+ end
@@ -0,0 +1,37 @@
1
+ class Moob::Megatrends < Moob::BaseLom
2
+ @@name = 'American Megatrends'
3
+
4
+ def initialize hostname, options = {}
5
+ super hostname, options
6
+ @username ||= 'root'
7
+ @password ||= 'superuser'
8
+ begin
9
+ @ip = Socket.getaddrinfo(hostname, nil)[0][2]
10
+ rescue
11
+ raise Exception.new "Couldn't resolve \"#{hostname}\""
12
+ end
13
+ @session.base_url = "https://#{@ip}/"
14
+ end
15
+
16
+ def authenticate
17
+ auth = @session.post 'rpc/WEBSES/create.asp',
18
+ { 'WEBVAR_USERNAME' => @username, 'WEBVAR_PASSWORD' => @password }
19
+
20
+ raise ResponseError.new auth unless auth.status == 200
21
+
22
+ cookie_match = auth.body.match /'SESSION_COOKIE' *: *'([^']+)'/
23
+ unless cookie_match
24
+ raise Exception.new "Couldn't find auth cookie in \"#{auth.body}\""
25
+ end
26
+
27
+ @cookie = "test=1; path=/; SessionCookie=#{cookie_match[1]}"
28
+ return self
29
+ end
30
+
31
+ def jnlp
32
+ viewer = @session.get 'Java/jviewer.jnlp', { 'Cookie' => @cookie }
33
+ raise ResponseError.new viewer unless viewer.status == 200
34
+
35
+ return desecurize_jnlp viewer.body
36
+ end
37
+ end
@@ -0,0 +1,33 @@
1
+ class Moob::SunILom < Moob::BaseLom
2
+ @@name = 'Sun Integrated Lights Out Manager'
3
+
4
+ def initialize hostname, options = {}
5
+ super hostname, options
6
+ @username ||= 'root'
7
+ @password ||= 'changeme'
8
+ end
9
+
10
+ def authenticate
11
+ auth = @session.post 'iPages/loginProcessor.asp', {
12
+ 'username' => @username,
13
+ 'password' => @password
14
+ }
15
+
16
+ raise ResponseError.new auth unless auth.status == 200
17
+
18
+ cookie_match = auth.body.match /SetWebSessionString\("([^"]+)","([^"]+)"\);/
19
+ unless cookie_match
20
+ raise Exception.new "Couldn't find session cookie in \"#{auth.body}\""
21
+ end
22
+
23
+ @cookie = "#{cookie_match[1]}=#{cookie_match[2]}; langsetting=EN"
24
+ return self
25
+ end
26
+
27
+ def jnlp
28
+ viewer = @session.get 'cgi-bin/jnlpgenerator-8', { 'Cookie' => @cookie }
29
+ raise ResponseError.new viewer unless viewer.status == 200
30
+
31
+ return viewer.body
32
+ end
33
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: moob
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Pierre Carrier
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-07-25 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: patron
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 21
30
+ segments:
31
+ - 0
32
+ - 4
33
+ - 13
34
+ version: 0.4.13
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description: Control systems using Web-based out-of-band managers without a browser
38
+ email:
39
+ - pierre@gcarrier.fr
40
+ executables:
41
+ - moob
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - bin/moob
48
+ - lib/moob/baselom.rb
49
+ - lib/moob/idrac6.rb
50
+ - lib/moob/megatrends.rb
51
+ - lib/moob/sunilom.rb
52
+ - lib/moob.rb
53
+ - COPYING
54
+ has_rdoc: true
55
+ homepage: http://github.com/pcarrier/moob
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options: []
60
+
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 23
78
+ segments:
79
+ - 1
80
+ - 3
81
+ - 6
82
+ version: 1.3.6
83
+ requirements: []
84
+
85
+ rubyforge_project: moob
86
+ rubygems_version: 1.6.2
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Manage Out-Of-Band!
90
+ test_files: []
91
+