moob 0.3.3 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +12 -3
- data/bin/moob +83 -78
- data/lib/moob.rb +52 -51
- data/lib/moob/baselom.rb +39 -38
- data/lib/moob/ibmeserver.rb +55 -56
- data/lib/moob/idrac6.rb +147 -196
- data/lib/moob/megatrends.rb +65 -65
- data/lib/moob/sunilom.rb +42 -42
- metadata +54 -66
data/COPYING
CHANGED
@@ -1,4 +1,13 @@
|
|
1
|
-
Copyright (c) 2011,
|
1
|
+
Copyright (c) 2011-2012, Spotify AB
|
2
2
|
|
3
|
-
Permission
|
4
|
-
|
3
|
+
Permission to use, copy, modify, and/or distribute this software
|
4
|
+
for any purpose with or without fee is hereby granted, provided that
|
5
|
+
the above copyright notice and this permission notice appear in all copies.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
8
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
9
|
+
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
10
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
11
|
+
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
12
|
+
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
13
|
+
THIS SOFTWARE.
|
data/bin/moob
CHANGED
@@ -4,106 +4,111 @@ require 'optparse'
|
|
4
4
|
require 'moob'
|
5
5
|
|
6
6
|
options = {
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
:actions => [:jnlp],
|
8
|
+
:type => :auto,
|
9
|
+
:machines => [],
|
10
|
+
:password => ENV['PASSWORD'],
|
11
|
+
:transport => 'https',
|
11
12
|
}
|
12
13
|
|
13
14
|
OptionParser.new do |opts|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
15
|
+
opts.on '-t', '--type t',
|
16
|
+
'LOM type, \'auto\' for autodetection, \'list\' to list',
|
17
|
+
'Defaults to auto' do |t|
|
18
|
+
if t == 'list'
|
19
|
+
Moob::TYPES.each do |sym, klass|
|
20
|
+
puts "#{sym} (#{klass.name})"
|
21
|
+
end
|
22
|
+
exit 0
|
23
|
+
else
|
24
|
+
options[:type] = t.to_sym
|
25
25
|
end
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
else
|
38
|
-
puts "#{sym} doesn't have any actions"
|
39
|
-
end
|
40
|
-
end
|
41
|
-
exit 0
|
28
|
+
opts.on '-a', '--actions a,b,c', Array,
|
29
|
+
'Actions to perform, \'list\' to list',
|
30
|
+
'Defaults to jnlp' do |a|
|
31
|
+
if a == ['list']
|
32
|
+
Moob::TYPES.each do |sym, klass|
|
33
|
+
if klass.actions
|
34
|
+
puts "#{sym}:"
|
35
|
+
klass.actions.each do |name, descr|
|
36
|
+
puts " #{name}: #{descr}"
|
37
|
+
end
|
42
38
|
else
|
43
|
-
|
39
|
+
puts "#{sym} doesn't have any actions"
|
44
40
|
end
|
41
|
+
end
|
42
|
+
exit 0
|
43
|
+
else
|
44
|
+
options[:actions] = a
|
45
45
|
end
|
46
|
+
end
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
opts.on '-u', '--username u',
|
49
|
+
'LOM username',
|
50
|
+
'Defaults to the model\'s default if known' do |u|
|
51
|
+
options[:username] = u
|
52
|
+
end
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
54
|
+
opts.on '-p', '--password p',
|
55
|
+
'LOM password',
|
56
|
+
'Defaults to the model\'s default if known',
|
57
|
+
'Use the environment variable PASSWORD instead!' do |p|
|
58
|
+
options[:password] = p
|
59
|
+
end
|
59
60
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
opts.on '-m', '--machines a,b,c', Array,
|
62
|
+
'Comma-separated list of LOM hostnames (or - to read from stdin)' do |m|
|
63
|
+
options[:machines] = m
|
64
|
+
end
|
64
65
|
|
65
|
-
|
66
|
-
|
67
|
-
|
66
|
+
opts.on '-n', '--no-ssl' do
|
67
|
+
options[:transport] = 'http'
|
68
|
+
end
|
69
|
+
|
70
|
+
opts.on '-v', '--verbose' do
|
71
|
+
$VERBOSE = true
|
72
|
+
end
|
68
73
|
end.parse!
|
69
74
|
|
70
75
|
if options[:machines].empty?
|
71
|
-
|
72
|
-
|
76
|
+
$stderr.puts 'No LOMs selected.'
|
77
|
+
exit 1
|
73
78
|
elsif options[:machines] == %w[-]
|
74
|
-
|
79
|
+
options[:machines] = $stdin.read.split
|
75
80
|
end
|
76
81
|
|
77
82
|
begin
|
78
|
-
|
79
|
-
|
83
|
+
options[:machines].each do |h|
|
84
|
+
lom = Moob.lom options[:type], h, options
|
80
85
|
|
81
|
-
|
82
|
-
|
83
|
-
|
86
|
+
Moob.inform "Trying to authenticate to #{h}..."
|
87
|
+
lom.authenticate
|
88
|
+
Moob.inform "Authenticated on #{h}."
|
84
89
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
end
|
97
|
-
|
98
|
-
lom.logout
|
99
|
-
Moob.inform "Logged out of #{h}."
|
90
|
+
options[:actions].each do |action|
|
91
|
+
action = action.to_sym
|
92
|
+
Moob.inform "Trying to perform #{action} on #{h}..."
|
93
|
+
case action
|
94
|
+
when :jnlp
|
95
|
+
Moob.start_jnlp lom
|
96
|
+
else
|
97
|
+
res = lom.send action
|
98
|
+
puts res if res
|
99
|
+
end
|
100
|
+
Moob.inform "Performed #{action} on #{h}."
|
100
101
|
end
|
101
|
-
|
102
|
+
|
103
|
+
lom.logout
|
104
|
+
Moob.inform "Logged out of #{h}."
|
105
|
+
end
|
106
|
+
puts 'There might be a delay before Java Web Start shows up...' if options[:action] == :jnlp
|
102
107
|
|
103
108
|
rescue Exception => e
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
+
$stderr.puts "\033[31mFailure: #{e.class} (#{e})\033[0m\n\n" \
|
110
|
+
"Backtrace to provide in any support request:\033[2;34m"
|
111
|
+
$stderr.puts e.backtrace
|
112
|
+
$stderr.puts "\033[0m"
|
113
|
+
exit 1
|
109
114
|
end
|
data/lib/moob.rb
CHANGED
@@ -1,62 +1,63 @@
|
|
1
1
|
module Moob
|
2
|
-
|
2
|
+
VERSION = [0,3,4]
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
end
|
8
|
-
def to_s
|
9
|
-
"#{@response.url} failed (status #{@response.status})"
|
10
|
-
end
|
4
|
+
class ResponseError < Exception
|
5
|
+
def initialize response
|
6
|
+
@response = response
|
11
7
|
end
|
12
|
-
|
13
|
-
|
14
|
-
autoload :Idrac6, 'moob/idrac6.rb'
|
15
|
-
autoload :Megatrends, 'moob/megatrends.rb'
|
16
|
-
autoload :SunILom, 'moob/sunilom.rb'
|
17
|
-
autoload :IbmEServer, 'moob/ibmeserver.rb'
|
18
|
-
|
19
|
-
TYPES = {
|
20
|
-
:idrac6 => Idrac6,
|
21
|
-
:megatrends => Megatrends,
|
22
|
-
:sun => SunILom,
|
23
|
-
:ibm => IbmEServer
|
24
|
-
}
|
25
|
-
|
26
|
-
def self.lom type, hostname, options = {}
|
27
|
-
case type
|
28
|
-
when :auto
|
29
|
-
TYPES.find do |sym, klass|
|
30
|
-
Moob.inform "Trying type #{sym}..."
|
31
|
-
lom = klass.new hostname, options
|
32
|
-
if lom.detect
|
33
|
-
Moob.inform "Type #{sym} detected."
|
34
|
-
return lom
|
35
|
-
end
|
36
|
-
false
|
37
|
-
end
|
38
|
-
raise "Couldn't detect a known LOM type"
|
39
|
-
else
|
40
|
-
return TYPES[type].new hostname, options
|
41
|
-
end
|
8
|
+
def to_s
|
9
|
+
"#{@response.url} failed (status #{@response.status})"
|
42
10
|
end
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
11
|
+
end
|
12
|
+
|
13
|
+
autoload :BaseLom, 'moob/baselom.rb'
|
14
|
+
autoload :Idrac6, 'moob/idrac6.rb'
|
15
|
+
autoload :Megatrends, 'moob/megatrends.rb'
|
16
|
+
autoload :SunILom, 'moob/sunilom.rb'
|
17
|
+
autoload :IbmEServer, 'moob/ibmeserver.rb'
|
18
|
+
|
19
|
+
TYPES = {
|
20
|
+
:idrac6 => Idrac6,
|
21
|
+
:megatrends => Megatrends,
|
22
|
+
:sun => SunILom,
|
23
|
+
:ibm => IbmEServer
|
24
|
+
}
|
25
|
+
|
26
|
+
def self.lom type, hostname, options = {}
|
27
|
+
case type
|
28
|
+
when :auto
|
29
|
+
TYPES.find do |sym, klass|
|
30
|
+
Moob.inform "Trying type #{sym}..."
|
31
|
+
lom = klass.new hostname, options
|
32
|
+
if lom.detect
|
33
|
+
Moob.inform "Type #{sym} detected."
|
34
|
+
return lom
|
49
35
|
end
|
36
|
+
false
|
37
|
+
end
|
38
|
+
raise 'Couldn\'t detect a known LOM type'
|
39
|
+
else
|
40
|
+
raise "Type #{type} unknown" unless TYPES[type]
|
41
|
+
return TYPES[type].new hostname, options
|
42
|
+
end
|
43
|
+
end
|
50
44
|
|
51
|
-
|
52
|
-
|
53
|
-
f.write jnlp
|
54
|
-
end
|
45
|
+
def self.start_jnlp lom
|
46
|
+
jnlp = lom.jnlp
|
55
47
|
|
56
|
-
|
48
|
+
unless jnlp[/<\/jnlp>/]
|
49
|
+
raise "Invalid JNLP file (\"#{jnlp}\")"
|
57
50
|
end
|
58
51
|
|
59
|
-
|
60
|
-
|
52
|
+
filepath = "/tmp/#{lom.hostname}_#{Time.now.to_i}.jnlp"
|
53
|
+
File.open filepath, 'w' do |f|
|
54
|
+
f.write jnlp
|
61
55
|
end
|
56
|
+
|
57
|
+
raise 'javaws failed' unless system "javaws -wait #{filepath}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.inform msg
|
61
|
+
$stderr.puts "\033[36m#{msg}\033[0m" if $VERBOSE
|
62
|
+
end
|
62
63
|
end
|
data/lib/moob/baselom.rb
CHANGED
@@ -5,42 +5,43 @@ require 'json'
|
|
5
5
|
require 'set'
|
6
6
|
|
7
7
|
class Moob::BaseLom
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
8
|
+
@name = "Unknown"
|
9
|
+
|
10
|
+
def initialize hostname, options = {}
|
11
|
+
@hostname = hostname
|
12
|
+
@transport = options[:transport] or 'https'
|
13
|
+
@username = options[:username]
|
14
|
+
@password = options[:password]
|
15
|
+
|
16
|
+
@session = Patron::Session.new
|
17
|
+
@session.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; '\
|
18
|
+
'Intel Mac OS X 10.7; rv:5.0.1) Gecko/20100101 Firefox/5.0.1'
|
19
|
+
@session.base_url = "#{@transport}://#{hostname}/"
|
20
|
+
@session.connect_timeout = 10_000
|
21
|
+
@session.timeout = 10_000
|
22
|
+
@session.insecure = true
|
23
|
+
@session.default_response_charset = 'ISO-8859-1'
|
24
|
+
end
|
25
|
+
|
26
|
+
def logout
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :hostname, :username
|
30
|
+
|
31
|
+
def detect
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.name
|
36
|
+
@name
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.actions
|
40
|
+
@actions
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.action sym, descr
|
44
|
+
@actions ||= []
|
45
|
+
@actions << [sym, descr]
|
46
|
+
end
|
46
47
|
end
|
data/lib/moob/ibmeserver.rb
CHANGED
@@ -1,75 +1,74 @@
|
|
1
1
|
module Moob
|
2
2
|
class IbmEServer < BaseLom
|
3
|
-
|
3
|
+
@name = 'IBM eServer Remote Supervisor Adapter'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
def initialize hostname, options = {}
|
6
|
+
super hostname, options
|
7
|
+
@username ||= 'USERID'
|
8
|
+
@password ||= 'PASSW0RD'
|
9
|
+
end
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
def authenticate
|
12
|
+
@session.handle_cookies nil
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
home = @session.get ''
|
15
|
+
raise ResponseError.new home unless home.status == 200
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
auth = @session.post 'private/check_userlogin', {
|
18
|
+
'userid' => @username,
|
19
|
+
'passwd' => @password
|
20
|
+
}
|
21
|
+
raise ResponseError.new auth unless auth.status == 200
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
init = @session.post 'private/start_menus', {
|
24
|
+
'JUNK' => '1',
|
25
|
+
'TIMEOUT' => '05'
|
26
|
+
}
|
27
|
+
raise ResponseError.new init unless init.status == 200
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
return self
|
30
|
+
end
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
action :infos, 'Vital Product Data'
|
33
|
+
def infos
|
34
|
+
return JSON.pretty_generate get_infos
|
35
|
+
end
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
37
|
+
def detect
|
38
|
+
begin
|
39
|
+
home = @session.get 'private/userlogin.ssi'
|
40
|
+
home.body =~ /Remote Supervisor Adapter/
|
41
|
+
rescue
|
42
|
+
false
|
43
|
+
end
|
44
|
+
end
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
def logout
|
47
|
+
page = @session.get 'private/logoff'
|
48
|
+
raise ResponseError.new page unless page.status == 200
|
49
|
+
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
def get_infos
|
52
|
+
page = @session.get 'private/vpd.ssi'
|
53
|
+
raise ResponseError.new page unless page.status == 200
|
54
54
|
|
55
|
-
|
55
|
+
infos = {}
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
57
|
+
infos[:macs] = Hash[
|
58
|
+
page.body.scan /<TR><TD[^>]*>MAC ([^:]*):<\/TD><TD[^>]*>([^<]*)<\/TD><\/TR>/
|
59
|
+
]
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
61
|
+
infos[:type] = grab page.body, 'Machine type'
|
62
|
+
infos[:model] = grab page.body, 'Machine model'
|
63
|
+
infos[:serial] = grab page.body, 'Serial number'
|
64
|
+
infos[:uuid] = grab page.body, 'UUID'
|
65
|
+
end
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
67
|
+
private
|
68
|
+
def grab contents, name
|
69
|
+
if contents =~ /<TR><TD[^>]*>#{name}:<\/TD><TD[^>]*>([^<]*)<\/TD><\/TR>/
|
70
|
+
return $1
|
72
71
|
end
|
73
|
-
|
72
|
+
end
|
74
73
|
end
|
75
74
|
end
|