moob 0.3.3 → 0.3.4
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 +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
|