moob 0.3.4 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/moob +18 -13
- data/lib/moob.rb +6 -4
- data/lib/moob/idrac7.rb +177 -0
- metadata +66 -46
data/bin/moob
CHANGED
@@ -87,21 +87,26 @@ begin
|
|
87
87
|
lom.authenticate
|
88
88
|
Moob.inform "Authenticated on #{h}."
|
89
89
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
90
|
+
begin
|
91
|
+
options[:actions].each do |action|
|
92
|
+
action = action.to_sym
|
93
|
+
|
94
|
+
Moob.inform "Trying to perform #{action} on #{h}..."
|
95
|
+
|
96
|
+
case action
|
97
|
+
when :jnlp
|
98
|
+
Moob.start_jnlp lom
|
99
|
+
else
|
100
|
+
res = lom.send action
|
101
|
+
puts res if res
|
102
|
+
end
|
103
|
+
|
104
|
+
Moob.inform "Performed #{action} on #{h}."
|
99
105
|
end
|
100
|
-
|
106
|
+
ensure
|
107
|
+
lom.logout
|
108
|
+
Moob.inform "Logged out of #{h}."
|
101
109
|
end
|
102
|
-
|
103
|
-
lom.logout
|
104
|
-
Moob.inform "Logged out of #{h}."
|
105
110
|
end
|
106
111
|
puts 'There might be a delay before Java Web Start shows up...' if options[:action] == :jnlp
|
107
112
|
|
data/lib/moob.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Moob
|
2
|
-
VERSION = [0,3,
|
2
|
+
VERSION = [0,3,5]
|
3
3
|
|
4
4
|
class ResponseError < Exception
|
5
5
|
def initialize response
|
@@ -12,15 +12,17 @@ module Moob
|
|
12
12
|
|
13
13
|
autoload :BaseLom, 'moob/baselom.rb'
|
14
14
|
autoload :Idrac6, 'moob/idrac6.rb'
|
15
|
+
autoload :Idrac7, 'moob/idrac7.rb'
|
15
16
|
autoload :Megatrends, 'moob/megatrends.rb'
|
16
17
|
autoload :SunILom, 'moob/sunilom.rb'
|
17
18
|
autoload :IbmEServer, 'moob/ibmeserver.rb'
|
18
19
|
|
19
20
|
TYPES = {
|
20
|
-
:idrac6
|
21
|
+
:idrac6 => Idrac6,
|
22
|
+
:idrac7 => Idrac7,
|
21
23
|
:megatrends => Megatrends,
|
22
|
-
:sun
|
23
|
-
:ibm
|
24
|
+
:sun => SunILom,
|
25
|
+
:ibm => IbmEServer
|
24
26
|
}
|
25
27
|
|
26
28
|
def self.lom type, hostname, options = {}
|
data/lib/moob/idrac7.rb
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
module Moob
|
2
|
+
class Idrac7 < BaseLom
|
3
|
+
@name = 'Dell iDrac 7'
|
4
|
+
|
5
|
+
INFO_FIELDS = %w[
|
6
|
+
biosVer svcTag expSvcCode hostName
|
7
|
+
osName osVersion sysDesc sysRev datetime initCountdown presentCountdown
|
8
|
+
fwVersion fwUpdated LCCfwVersion
|
9
|
+
firstBootDevice vmBootOnce
|
10
|
+
racName hwVersionmacAddr recoveryAction
|
11
|
+
NicEtherMac1 NicEtherMac2 NicEtherMac3 NicEtherMac4
|
12
|
+
NiciSCSIMac1 NiciSCSIMac2 NiciSCSIMac3 NiciSCSIMac4
|
13
|
+
NicEtherVMac1 NicEtherVMac2 NicEtherVMac3 NicEtherVMac4
|
14
|
+
v4Enabled v4IPAddr v4Gateway v4NetMask
|
15
|
+
v6Enabled v6Addr v6Gateway v6Prefix v6LinkLocal
|
16
|
+
v4DHCPEnabled v4DHCPServers v4DNS1 v4DNS2
|
17
|
+
v6DHCPEnabled v6DHCPServers v6DNS1 v6DNS2
|
18
|
+
v6SiteLocal v6SiteLocal3 v6SiteLocal4 v6SiteLocal5 v6SiteLocal6 v6SiteLocal7 v6SiteLocal8
|
19
|
+
v6SiteLocal9 v6SiteLocal10 v6SiteLocal11 v6SiteLocal12 v6SiteLocal13 v6SiteLocal14 v6SiteLocal15
|
20
|
+
]
|
21
|
+
|
22
|
+
def initialize hostname, options = {}
|
23
|
+
super hostname, options
|
24
|
+
@username ||= 'root'
|
25
|
+
@password ||= 'calvin'
|
26
|
+
@index = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def authenticate
|
30
|
+
@session.handle_cookies("./cookies.txt")
|
31
|
+
|
32
|
+
login = @session.get 'login.html'
|
33
|
+
|
34
|
+
raise ResponseError.new login unless login.status == 200
|
35
|
+
|
36
|
+
auth = @session.post 'data/login', "user=#{@username}&password=#{@password}"
|
37
|
+
|
38
|
+
raise ResponseError.new auth unless auth.status == 200
|
39
|
+
|
40
|
+
auth.body =~ /<authResult>([^<]+)<\/authResult>/
|
41
|
+
|
42
|
+
raise 'Cannot find auth result' unless $&
|
43
|
+
raise "Auth failed with: \"#{auth.body}\"" unless $1 == "0"
|
44
|
+
|
45
|
+
auth.body =~ /<forwardUrl>([^<]+)<\/forwardUrl>/
|
46
|
+
|
47
|
+
raise 'Cannot find the authenticated index url after auth' unless $&
|
48
|
+
|
49
|
+
@indexurl = $1
|
50
|
+
@authhash = @indexurl.split('?')[1]
|
51
|
+
|
52
|
+
@index = @session.get @indexurl
|
53
|
+
|
54
|
+
# someone decided it was a good idea to include a ST2 token in every XHR
|
55
|
+
# request. We need it for a lot of our features.
|
56
|
+
@index.body =~ /var TOKEN_VALUE = "([0-9a-f]+)";/
|
57
|
+
raise ResponseError.new @index unless @index.status == 200
|
58
|
+
@st2 = $1
|
59
|
+
|
60
|
+
@session.headers['ST2'] = @st2
|
61
|
+
|
62
|
+
puts @authhash
|
63
|
+
puts @indexurl
|
64
|
+
puts "ST2: #{@st2}"
|
65
|
+
|
66
|
+
return self
|
67
|
+
end
|
68
|
+
|
69
|
+
def logout
|
70
|
+
out = @session.get 'data/logout'
|
71
|
+
raise ResponseError.new out unless out.status == 200
|
72
|
+
return self
|
73
|
+
end
|
74
|
+
|
75
|
+
def detect
|
76
|
+
begin
|
77
|
+
home = @session.get 'login.html'
|
78
|
+
home.body =~ /Integrated Dell Remote Access Controller 7/
|
79
|
+
rescue
|
80
|
+
false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
action :jnlp, 'Remote control'
|
85
|
+
|
86
|
+
def jnlp
|
87
|
+
@index.body =~ /var tmpHN += +"([^"]+)"/
|
88
|
+
raise "Couldn't find the DNS name" unless $&
|
89
|
+
dns_name = $1
|
90
|
+
|
91
|
+
@index.body =~ /var sysNameStr += +"([^"]+)"/
|
92
|
+
raise "Couldn't find the system name" unless $&
|
93
|
+
sys_name = $1 # eg PowerEdge R610
|
94
|
+
|
95
|
+
# eg escaped "idrac-A1BCD2E, PowerEdge R610, User:root"
|
96
|
+
title = CGI::escape "#{dns_name}, #{sys_name}, User:#{@username}"
|
97
|
+
|
98
|
+
viewer = @session.get "viewer.jnlp(#{@hostname}@0@#{title}@#{Time.now.to_i * 1000}@#{@authhash})"
|
99
|
+
raise ResponseError.new viewer unless viewer.status == 200
|
100
|
+
|
101
|
+
return viewer.body
|
102
|
+
end
|
103
|
+
|
104
|
+
def power_control action
|
105
|
+
req = @session.post "data?set=pwState:#{action}", {}
|
106
|
+
raise ResponseError.new req unless req.status == 200
|
107
|
+
return nil
|
108
|
+
end
|
109
|
+
|
110
|
+
def boot_on level
|
111
|
+
req = @session.post "data?set=vmBootOnce:1,firstBootDevice:#{level}", {}
|
112
|
+
raise ResponseError.new req unless req.status == 200
|
113
|
+
return nil
|
114
|
+
end
|
115
|
+
|
116
|
+
[
|
117
|
+
[0, :poff, 'Power Off System'],
|
118
|
+
[1, :pon, 'Power On System'],
|
119
|
+
[2, :pcycle, 'Power Cycle System (cold boot)'],
|
120
|
+
[3, :preset, 'Reset System (warm boot)'],
|
121
|
+
[4, :nmi, 'NMI (Non-Masking Interrupt)'],
|
122
|
+
[5, :shutdown, 'Graceful Shutdown']
|
123
|
+
].each do |code, name, desc|
|
124
|
+
action name, desc
|
125
|
+
class_eval %{def #{name}; power_control #{code}; end}
|
126
|
+
end
|
127
|
+
|
128
|
+
[
|
129
|
+
[0, :bnone, 'Do not change the next boot'],
|
130
|
+
[1, :bpxe, 'Boot on PXE once'],
|
131
|
+
[6, :bbios, 'Boot on BIOS setup once'],
|
132
|
+
[15, :blfloppy, 'Boot on Local Floppy/Primary Removable Media once'],
|
133
|
+
[5, :blcd, 'Boot on Local CD/DVD once'],
|
134
|
+
[2, :blhd, 'Boot on Hard Drive once'],
|
135
|
+
[9, :biscsi, 'Boot on NIC BEV iSCSI once'],
|
136
|
+
[7, :bvfloppy, 'Boot on Virtual Floppy once'],
|
137
|
+
[8, :bvcd, 'Boot on Virtual CD/DVD/ISO once'],
|
138
|
+
[16, :blsd, 'Boot on Local SD Card once'],
|
139
|
+
[11, :bvflash, 'Boot on vFlash once']
|
140
|
+
].each do |code, name, desc|
|
141
|
+
action name, desc
|
142
|
+
class_eval %{def #{name}; boot_on #{code}; end}
|
143
|
+
end
|
144
|
+
|
145
|
+
action :pstatus, 'Power status'
|
146
|
+
def pstatus
|
147
|
+
case get_infos(['pwState'])['pwState']
|
148
|
+
when '0'
|
149
|
+
return :off
|
150
|
+
when '1'
|
151
|
+
return :on
|
152
|
+
else
|
153
|
+
return nil
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
action :infos, 'Get system information'
|
158
|
+
def infos
|
159
|
+
return JSON.pretty_generate get_infos INFO_FIELDS
|
160
|
+
end
|
161
|
+
|
162
|
+
def get_infos keys
|
163
|
+
infos = @session.post "data?get=#{keys.join(',')}", {}
|
164
|
+
|
165
|
+
raise ResponseError.new infos unless infos.status == 200
|
166
|
+
raise "The status isn't OK" unless infos.body =~ /<status>ok<\/status>/
|
167
|
+
|
168
|
+
return Hash[keys.collect do |k|
|
169
|
+
if infos.body =~ /<#{k}>(.*?)<\/#{k}>/
|
170
|
+
[k, $1]
|
171
|
+
else
|
172
|
+
[k, nil]
|
173
|
+
end
|
174
|
+
end]
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
metadata
CHANGED
@@ -1,87 +1,107 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: moob
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 25
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 3
|
9
|
+
- 5
|
10
|
+
version: 0.3.5
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Pierre Carrier
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2012-09-07 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
15
21
|
name: patron
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ~>
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: 0.4.14
|
22
|
-
type: :runtime
|
23
22
|
prerelease: false
|
24
|
-
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
24
|
none: false
|
26
|
-
requirements:
|
25
|
+
requirements:
|
27
26
|
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 19
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
- 4
|
32
|
+
- 14
|
29
33
|
version: 0.4.14
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: json
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
|
-
requirements:
|
35
|
-
- - ~>
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: 1.5.3
|
38
34
|
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: json
|
39
38
|
prerelease: false
|
40
|
-
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
40
|
none: false
|
42
|
-
requirements:
|
41
|
+
requirements:
|
43
42
|
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 5
|
45
|
+
segments:
|
46
|
+
- 1
|
47
|
+
- 5
|
48
|
+
- 3
|
45
49
|
version: 1.5.3
|
50
|
+
type: :runtime
|
51
|
+
version_requirements: *id002
|
46
52
|
description: Control systems using Web-based out-of-band managers without a browser
|
47
|
-
email:
|
53
|
+
email:
|
48
54
|
- pierre@spotify.com
|
49
|
-
executables:
|
55
|
+
executables:
|
50
56
|
- moob
|
51
57
|
extensions: []
|
58
|
+
|
52
59
|
extra_rdoc_files: []
|
53
|
-
|
60
|
+
|
61
|
+
files:
|
54
62
|
- bin/moob
|
55
|
-
- lib/moob/sunilom.rb
|
56
|
-
- lib/moob/idrac6.rb
|
57
|
-
- lib/moob/ibmeserver.rb
|
58
63
|
- lib/moob/baselom.rb
|
64
|
+
- lib/moob/ibmeserver.rb
|
65
|
+
- lib/moob/idrac6.rb
|
66
|
+
- lib/moob/sunilom.rb
|
59
67
|
- lib/moob/megatrends.rb
|
68
|
+
- lib/moob/idrac7.rb
|
60
69
|
- lib/moob.rb
|
61
70
|
- COPYING
|
62
71
|
homepage: https://github.com/spotify/moob
|
63
|
-
licenses:
|
72
|
+
licenses:
|
64
73
|
- ISC
|
65
74
|
post_install_message:
|
66
75
|
rdoc_options: []
|
67
|
-
|
76
|
+
|
77
|
+
require_paths:
|
68
78
|
- lib
|
69
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
80
|
none: false
|
71
|
-
requirements:
|
72
|
-
- -
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
|
75
|
-
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
89
|
none: false
|
77
|
-
requirements:
|
78
|
-
- -
|
79
|
-
- !ruby/object:Gem::Version
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
hash: 31
|
94
|
+
segments:
|
95
|
+
- 1
|
96
|
+
- 2
|
97
|
+
- 0
|
80
98
|
version: 1.2.0
|
81
99
|
requirements: []
|
100
|
+
|
82
101
|
rubyforge_project: moob
|
83
|
-
rubygems_version: 1.8.
|
102
|
+
rubygems_version: 1.8.15
|
84
103
|
signing_key:
|
85
104
|
specification_version: 3
|
86
105
|
summary: Manage Out-Of-Band!
|
87
106
|
test_files: []
|
107
|
+
|