right_agent 0.17.2 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/right_agent.rb +0 -1
- data/lib/right_agent/agent_config.rb +1 -1
- data/lib/right_agent/minimal.rb +8 -7
- data/lib/right_agent/monkey_patches.rb +4 -2
- data/lib/right_agent/monkey_patches/ruby_patch.rb +9 -9
- data/lib/right_agent/monkey_patches/ruby_patch/linux_patch/file_patch.rb +2 -2
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/file_patch.rb +21 -51
- data/lib/right_agent/packets.rb +5 -1
- data/lib/right_agent/platform.rb +727 -299
- data/lib/right_agent/platform/unix/darwin/platform.rb +102 -0
- data/lib/right_agent/platform/unix/linux/platform.rb +305 -0
- data/lib/right_agent/platform/unix/platform.rb +226 -0
- data/lib/right_agent/platform/windows/mingw/platform.rb +447 -0
- data/lib/right_agent/platform/windows/mswin/platform.rb +236 -0
- data/lib/right_agent/platform/windows/platform.rb +1808 -0
- data/right_agent.gemspec +13 -8
- data/spec/platform/spec_helper.rb +216 -0
- data/spec/platform/unix/darwin/platform_spec.rb +181 -0
- data/spec/platform/unix/linux/platform_spec.rb +540 -0
- data/spec/platform/unix/spec_helper.rb +149 -0
- data/spec/platform/windows/mingw/platform_spec.rb +222 -0
- data/spec/platform/windows/mswin/platform_spec.rb +259 -0
- data/spec/platform/windows/spec_helper.rb +720 -0
- metadata +45 -30
- data/lib/right_agent/platform/darwin.rb +0 -285
- data/lib/right_agent/platform/linux.rb +0 -537
- data/lib/right_agent/platform/windows.rb +0 -1384
- data/spec/platform/darwin_spec.rb +0 -13
- data/spec/platform/linux_spec.rb +0 -38
- data/spec/platform/linux_volume_manager_spec.rb +0 -201
- data/spec/platform/platform_spec.rb +0 -80
- data/spec/platform/windows_spec.rb +0 -13
- data/spec/platform/windows_volume_manager_spec.rb +0 -318
@@ -0,0 +1,102 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2013 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require ::File.expand_path('../../platform', __FILE__)
|
24
|
+
|
25
|
+
module RightScale
|
26
|
+
|
27
|
+
# Mac OS specific implementation
|
28
|
+
class Platform
|
29
|
+
|
30
|
+
# Provides utilities for managing volumes (disks).
|
31
|
+
class VolumeManager
|
32
|
+
|
33
|
+
# Overrides base VolumeManager#volumes
|
34
|
+
def volumes(conditions = nil)
|
35
|
+
raise ::NotImplementedError, 'Not yet supporting Mac OS volume query'
|
36
|
+
end
|
37
|
+
|
38
|
+
# Overrides base VolumeManager#mount_volume
|
39
|
+
def mount_volume(volume, mountpoint)
|
40
|
+
raise ::NotImplementedError, 'Not yet supporting Mac OS volume mounting'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Shell
|
45
|
+
|
46
|
+
# Overrides base Shell#uptime
|
47
|
+
def uptime
|
48
|
+
return (Time.now.to_i.to_f - booted_at.to_f) rescue 0.0
|
49
|
+
end
|
50
|
+
|
51
|
+
# Overrides base Shell#booted_at
|
52
|
+
def booted_at
|
53
|
+
output_text = execute('sysctl kern.boottime')
|
54
|
+
match = /sec = ([0-9]+)/.match(output_text)
|
55
|
+
if match && (match[1].to_i > 0)
|
56
|
+
return match[1].to_i
|
57
|
+
else
|
58
|
+
return nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end # Shell
|
62
|
+
|
63
|
+
class Controller
|
64
|
+
|
65
|
+
# Overrides base Controller#reboot
|
66
|
+
def reboot
|
67
|
+
execute('shutdown -r now 2>&1')
|
68
|
+
true
|
69
|
+
end
|
70
|
+
|
71
|
+
# Overrides base Controller#shutdown
|
72
|
+
def shutdown
|
73
|
+
execute('shutdown -h now 2>&1')
|
74
|
+
true
|
75
|
+
end
|
76
|
+
end # Controller
|
77
|
+
|
78
|
+
class Installer
|
79
|
+
|
80
|
+
# Overrides base Installer#install
|
81
|
+
def install(packages)
|
82
|
+
raise ::NotImplementedError, 'Not yet supporting Mac OS package install'
|
83
|
+
end
|
84
|
+
end # Installer
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
# Overrides base Platform#initialize_species
|
89
|
+
def initialize_species
|
90
|
+
@flavor = 'mac_os_x'
|
91
|
+
begin
|
92
|
+
@release = execute('sw_vers -productVersion 2>&1').strip
|
93
|
+
@codename = '' # TEAL FIX cannot find a way to query osx codename by CLI
|
94
|
+
rescue ::RightScale::Platform::CommandError
|
95
|
+
@release = @codename = 'unknown'
|
96
|
+
end
|
97
|
+
true
|
98
|
+
end
|
99
|
+
|
100
|
+
end # Platform
|
101
|
+
|
102
|
+
end # RightScale
|
@@ -0,0 +1,305 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2013 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require ::File.expand_path('../../platform', __FILE__)
|
24
|
+
|
25
|
+
module RightScale
|
26
|
+
|
27
|
+
# Linux specific implementation
|
28
|
+
class Platform
|
29
|
+
|
30
|
+
FEDORA_REL = '/etc/fedora-release'
|
31
|
+
FEDORA_SIG = /Fedora release ([0-9]+) \((.*)\)/
|
32
|
+
|
33
|
+
# Is this machine running Ubuntu?
|
34
|
+
#
|
35
|
+
# @return [TrueClass|FalseClass] true if Linux flavor is Ubuntu
|
36
|
+
def ubuntu?
|
37
|
+
!!(@flavor =~ /ubuntu/)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Is this machine running CentOS?
|
41
|
+
#
|
42
|
+
# @return [TrueClass|FalseClass] true if Linux flavor is CentOS
|
43
|
+
def centos?
|
44
|
+
!!(@flavor =~ /centos/)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Is this machine running Suse?
|
48
|
+
#
|
49
|
+
# @return [TrueClass|FalseClass] true if Linux flavor is Suse
|
50
|
+
def suse?
|
51
|
+
!!(@flavor =~ /suse/)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Is this machine running RHEL?
|
55
|
+
#
|
56
|
+
# @return [TrueClass|FalseClass] true if Linux flavor is RHEL
|
57
|
+
def rhel?
|
58
|
+
!!(@flavor =~ /redhatenterpriseserver/)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Provides utilities for managing volumes (disks).
|
62
|
+
class VolumeManager
|
63
|
+
|
64
|
+
# Overrides base VolumeManager#volumes
|
65
|
+
def volumes(conditions = nil)
|
66
|
+
blkid_resp = execute('blkid 2>&1')
|
67
|
+
return parse_volumes(blkid_resp, conditions)
|
68
|
+
rescue ::RightScale::Platform::CommandError => e
|
69
|
+
raise VolumeError, "Failed to list volumes: #{e.message}"
|
70
|
+
end
|
71
|
+
|
72
|
+
# Overrides base VolumeManager#mount_volume
|
73
|
+
def mount_volume(volume, mountpoint)
|
74
|
+
unless volume.is_a?(::Hash) && volume[:device]
|
75
|
+
raise ::ArgumentError, "Invalid volume argument = #{volume.inspect}"
|
76
|
+
end
|
77
|
+
mount_list_output = nil
|
78
|
+
begin
|
79
|
+
mount_list_output = execute('mount 2>&1')
|
80
|
+
rescue ::RightScale::Platform::CommandError => e
|
81
|
+
raise VolumeError, "Failed interrogation of current mounts: #{e.message}"
|
82
|
+
end
|
83
|
+
|
84
|
+
device_match = /^#{volume[:device]} on (.+?)\s/.match(mount_list_output)
|
85
|
+
mountpoint_from_device_match = device_match ? device_match[1] : mountpoint
|
86
|
+
unless (mountpoint_from_device_match && mountpoint_from_device_match == mountpoint)
|
87
|
+
raise VolumeError,
|
88
|
+
"Attempted to mount volume \"#{volume[:device]}\" at \"#{mountpoint}\" but it was already mounted at #{mountpoint_from_device_match}"
|
89
|
+
end
|
90
|
+
|
91
|
+
mountpoint_match = /^(.+?) on #{mountpoint}/.match(mount_list_output)
|
92
|
+
device_from_mountpoint_match = mountpoint_match ? mountpoint_match[1] : volume[:device]
|
93
|
+
unless (device_from_mountpoint_match && device_from_mountpoint_match == volume[:device])
|
94
|
+
raise VolumeError.new("Attempted to mount volume \"#{volume[:device]}\" at \"#{mountpoint}\" but \"#{device_from_mountpoint_match}\" was already mounted there.")
|
95
|
+
end
|
96
|
+
|
97
|
+
# The volume is already mounted at the correct mountpoint
|
98
|
+
return true if /^#{volume[:device]} on #{mountpoint}/.match(mount_list_output)
|
99
|
+
|
100
|
+
# TODO: Maybe validate that the mountpoint is valid *nix path?
|
101
|
+
begin
|
102
|
+
execute("mount -t #{volume[:filesystem].strip} #{volume[:device]} #{mountpoint} 2>&1")
|
103
|
+
rescue ::RightScale::Platform::CommandError => e
|
104
|
+
raise VolumeError, "Failed to mount volume to \"#{mountpoint}\" with device \"#{volume[:device]}\": #{e.message}"
|
105
|
+
end
|
106
|
+
true
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
# Parses raw output from `blkid` into a hash of volumes.
|
112
|
+
#
|
113
|
+
# The hash will contain the device name with a key of :device, and each
|
114
|
+
# key value pair for the device. In order to keep parity with the Windows
|
115
|
+
# VolumeManager.parse_volumes method, the :type key will be duplicated as
|
116
|
+
# :filesystem
|
117
|
+
#
|
118
|
+
# Example of raw output from `blkid`
|
119
|
+
# /dev/xvdh1: SEC_TYPE="msdos" LABEL="METADATA" UUID="681B-8C5D" TYPE="vfat"
|
120
|
+
# /dev/xvdb1: LABEL="SWAP-xvdb1" UUID="d51fcca0-6b10-4934-a572-f3898dfd8840" TYPE="swap"
|
121
|
+
# /dev/xvda1: UUID="f4746f9c-0557-4406-9267-5e918e87ca2e" TYPE="ext3"
|
122
|
+
# /dev/xvda2: UUID="14d88b9e-9fe6-4974-a8d6-180acdae4016" TYPE="ext3"
|
123
|
+
#
|
124
|
+
# @param [String] output_text from blkid
|
125
|
+
# @param [Hash] conditions to match (Default = no conditions)
|
126
|
+
#
|
127
|
+
# @return [Array] volume info as an array of hashes or empty
|
128
|
+
#
|
129
|
+
# @raise [ParserError] on failure to parse volume list
|
130
|
+
def parse_volumes(output_text, conditions = nil)
|
131
|
+
results = []
|
132
|
+
output_text.lines.each do |line|
|
133
|
+
volume = {}
|
134
|
+
line_regex = /^([\/a-z0-9_\-\.]+):(.*)/
|
135
|
+
volmatch = line_regex.match(line)
|
136
|
+
raise ParserError.new("Failed to parse volume info from #{line.inspect} using #{line_regex.inspect}") unless volmatch
|
137
|
+
volume[:device] = volmatch[1]
|
138
|
+
volmatch[2].split(' ').each do |pair|
|
139
|
+
pair_regex = /([a-zA-Z_\-]+)=(.*)/
|
140
|
+
match = pair_regex.match(pair)
|
141
|
+
raise ParserError.new("Failed to parse volume info from #{pair} using #{pair_regex.inspect}") unless match
|
142
|
+
volume[:"#{match[1].downcase}"] = match[2].gsub('"', '')
|
143
|
+
# Make this as much like the windows output as possible
|
144
|
+
if match[1] == 'TYPE'
|
145
|
+
volume[:filesystem] = match[2].gsub('"', '')
|
146
|
+
end
|
147
|
+
end
|
148
|
+
if conditions
|
149
|
+
matched = true
|
150
|
+
conditions.each do |key,value|
|
151
|
+
unless volume[key] == value
|
152
|
+
matched = false
|
153
|
+
break
|
154
|
+
end
|
155
|
+
end
|
156
|
+
results << volume if matched
|
157
|
+
else
|
158
|
+
results << volume
|
159
|
+
end
|
160
|
+
end
|
161
|
+
results
|
162
|
+
end
|
163
|
+
end # VolumeManager
|
164
|
+
|
165
|
+
class Shell
|
166
|
+
|
167
|
+
# Overrides base Shell#uptime
|
168
|
+
def uptime
|
169
|
+
return ::File.read('/proc/uptime').split(/\s+/)[0].to_f rescue 0.0
|
170
|
+
end
|
171
|
+
|
172
|
+
# Overrides base Shell#booted_at
|
173
|
+
def booted_at
|
174
|
+
match = /btime ([0-9]+)/.match(::File.read('/proc/stat')) rescue nil
|
175
|
+
if match && (match[1].to_i > 0)
|
176
|
+
return match[1].to_i
|
177
|
+
else
|
178
|
+
return nil
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end # Shell
|
182
|
+
|
183
|
+
class Controller
|
184
|
+
|
185
|
+
# Overrides base Controller#reboot
|
186
|
+
def reboot
|
187
|
+
execute('init 6 2>&1')
|
188
|
+
true
|
189
|
+
end
|
190
|
+
|
191
|
+
# Overrides base Controller#shutdown
|
192
|
+
def shutdown
|
193
|
+
execute('init 0 2>&1')
|
194
|
+
true
|
195
|
+
end
|
196
|
+
end # Controller
|
197
|
+
|
198
|
+
class Installer
|
199
|
+
|
200
|
+
# Does this machine have aptitude?
|
201
|
+
#
|
202
|
+
# @return [TrueClass|FalseClass] true if aptitude is available in the expected directory
|
203
|
+
def aptitude?
|
204
|
+
::File.executable? '/usr/bin/apt-get'
|
205
|
+
end
|
206
|
+
|
207
|
+
# Does this machine have yum?
|
208
|
+
#
|
209
|
+
# @return [TrueClass|FalseClass] true if yum is available in the expected directory
|
210
|
+
def yum?
|
211
|
+
::File.executable? '/usr/bin/yum'
|
212
|
+
end
|
213
|
+
|
214
|
+
# Does this machine have zypper?
|
215
|
+
#
|
216
|
+
# @return [TrueClass|FalseClass] true if zypper is available in the expected directory
|
217
|
+
def zypper?
|
218
|
+
::File.executable? '/usr/bin/zypper'
|
219
|
+
end
|
220
|
+
|
221
|
+
# Overrides base Installer#install
|
222
|
+
def install(packages)
|
223
|
+
packages = Array(packages)
|
224
|
+
return true if packages.empty?
|
225
|
+
|
226
|
+
packages = packages.uniq.join(' ')
|
227
|
+
|
228
|
+
if yum?
|
229
|
+
command = "yum install -y #{packages} 2>&1"
|
230
|
+
regex = /No package (.*) available\./
|
231
|
+
elsif aptitude?
|
232
|
+
old_debian_frontend = ENV['DEBIAN_FRONTEND']
|
233
|
+
ENV['DEBIAN_FRONTEND'] = 'noninteractive'
|
234
|
+
command = "apt-get install -y #{packages} 2>&1"
|
235
|
+
# note the error message for apt-get seems to have changed between
|
236
|
+
# versions of aptitude.
|
237
|
+
regex = /E: (Couldn't find package|Unable to locate package) (.*)/
|
238
|
+
elsif zypper?
|
239
|
+
command = "zypper --no-gpg-checks -n #{packages} 2>&1"
|
240
|
+
regex = /Package '(.*)' not found\./
|
241
|
+
else
|
242
|
+
raise PackageManagerNotFound,
|
243
|
+
'No package manager binary (apt, yum, zypper) found in /usr/bin'
|
244
|
+
end
|
245
|
+
|
246
|
+
failed_packages = nil
|
247
|
+
begin
|
248
|
+
# TEAL FIX it's not clear from legacy implementation if having failed
|
249
|
+
# packages consistently exits non-zero from all supported installers.
|
250
|
+
# for that reason, also scan for failed packages on exit zero.
|
251
|
+
failed_packages = scan_for_failed_packages(execute(command), regex)
|
252
|
+
rescue ::RightScale::Platform::CommandError => e
|
253
|
+
# command could fail for reasons other than failed packages (e.g. not
|
254
|
+
# being sudo) but legacy code raised a specific error for failed
|
255
|
+
# packages.
|
256
|
+
failed_packages = scan_for_failed_packages(e.output_text, regex)
|
257
|
+
raise if failed_packages.empty?
|
258
|
+
ensure
|
259
|
+
ENV['DEBIAN_FRONTEND'] = old_debian_frontend if aptitude?
|
260
|
+
end
|
261
|
+
unless failed_packages.empty?
|
262
|
+
raise PackageNotFound,
|
263
|
+
"The following packages were not available: #{failed_packages.join(', ')}"
|
264
|
+
end
|
265
|
+
true
|
266
|
+
end
|
267
|
+
|
268
|
+
private
|
269
|
+
|
270
|
+
def scan_for_failed_packages(output_text, regex)
|
271
|
+
@output = output_text
|
272
|
+
failed_packages = []
|
273
|
+
output_text.scan(regex) { |package| failed_packages << package.last }
|
274
|
+
failed_packages
|
275
|
+
end
|
276
|
+
end # Installer
|
277
|
+
|
278
|
+
private
|
279
|
+
|
280
|
+
# Overrides base Platform#initialize_species
|
281
|
+
def initialize_species
|
282
|
+
# Use the lsb_release utility if it's available
|
283
|
+
begin
|
284
|
+
# TEAL FIX: not sure if we really need to check if --help succeeds or
|
285
|
+
# if we would only need to call lsb_release -is but that was the legacy
|
286
|
+
# behavior and retesting all supported flavors of Linux isn't trivial.
|
287
|
+
execute('lsb_release --help >/dev/null 2>&1')
|
288
|
+
@flavor = execute('lsb_release -is', :raise_on_failure => false).strip.downcase
|
289
|
+
@release = execute('lsb_release -rs', :raise_on_failure => false).strip
|
290
|
+
@codename = execute('lsb_release -cs', :raise_on_failure => false).strip
|
291
|
+
rescue ::RightScale::Platform::CommandError
|
292
|
+
if ::File.exist?(FEDORA_REL) && (match = FEDORA_SIG.match(::File.read(FEDORA_REL)))
|
293
|
+
# Parse the fedora-release file if it exists
|
294
|
+
@flavor = 'fedora'
|
295
|
+
@release = match[1]
|
296
|
+
@codename = match[2]
|
297
|
+
else
|
298
|
+
@flavor = @release = @codename = 'unknown'
|
299
|
+
end
|
300
|
+
end
|
301
|
+
true
|
302
|
+
end
|
303
|
+
|
304
|
+
end # Platform
|
305
|
+
end # RightScale
|
@@ -0,0 +1,226 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2013 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require ::File.expand_path('../../../platform', __FILE__)
|
24
|
+
|
25
|
+
module RightScale
|
26
|
+
|
27
|
+
# Unix-specific implementation
|
28
|
+
class Platform
|
29
|
+
|
30
|
+
class Filesystem
|
31
|
+
|
32
|
+
# Overrides base Filesystem#find_executable_in_path
|
33
|
+
def find_executable_in_path(command_name)
|
34
|
+
::ENV['PATH'].split(/;|:/).each do |dir|
|
35
|
+
path = ::File.join(dir, command_name)
|
36
|
+
return path if ::File.executable?(path)
|
37
|
+
end
|
38
|
+
return nil
|
39
|
+
end
|
40
|
+
|
41
|
+
# Overrides base Filesystem#right_agent_cfg_dir
|
42
|
+
def right_agent_cfg_dir
|
43
|
+
'/var/lib/rightscale/right_agent'
|
44
|
+
end
|
45
|
+
|
46
|
+
# Overrides base Filesystem#right_scale_static_state_dir
|
47
|
+
def right_scale_static_state_dir
|
48
|
+
'/etc/rightscale.d'
|
49
|
+
end
|
50
|
+
|
51
|
+
# Overrides base Filesystem#right_link_static_state_dir
|
52
|
+
def right_link_static_state_dir
|
53
|
+
'/etc/rightscale.d/right_link'
|
54
|
+
end
|
55
|
+
|
56
|
+
# Overrides base Filesystem#right_link_dynamic_state_dir
|
57
|
+
def right_link_dynamic_state_dir
|
58
|
+
'/var/lib/rightscale/right_link'
|
59
|
+
end
|
60
|
+
|
61
|
+
# Overrides base Filesystem#spool_dir
|
62
|
+
def spool_dir
|
63
|
+
'/var/spool'
|
64
|
+
end
|
65
|
+
|
66
|
+
# Overrides base Filesystem#ssh_cfg_dir
|
67
|
+
def ssh_cfg_dir
|
68
|
+
'/etc/ssh'
|
69
|
+
end
|
70
|
+
|
71
|
+
# Overrides base Filesystem#cache_dir
|
72
|
+
def cache_dir
|
73
|
+
'/var/cache'
|
74
|
+
end
|
75
|
+
|
76
|
+
# Overrides base Filesystem#log_dir
|
77
|
+
def log_dir
|
78
|
+
'/var/log'
|
79
|
+
end
|
80
|
+
|
81
|
+
# Overrides base Filesystem#source_code_dir
|
82
|
+
def source_code_dir
|
83
|
+
'/usr/src'
|
84
|
+
end
|
85
|
+
|
86
|
+
# Overrides base Filesystem#temp_dir
|
87
|
+
def temp_dir
|
88
|
+
'/tmp'
|
89
|
+
end
|
90
|
+
|
91
|
+
# Overrides base Filesystem#pid_dir
|
92
|
+
def pid_dir
|
93
|
+
'/var/run'
|
94
|
+
end
|
95
|
+
|
96
|
+
# Overrides base Filesystem#right_link_home_dir
|
97
|
+
def right_link_home_dir
|
98
|
+
# TEAL FIX could the user choose a different directory when installing
|
99
|
+
# the RightLink v5.9+ package manually?
|
100
|
+
'/opt/rightscale'
|
101
|
+
end
|
102
|
+
|
103
|
+
# Overrides base Filesystem#private_bin_dir
|
104
|
+
def private_bin_dir
|
105
|
+
::File.join(right_link_home_dir, 'bin')
|
106
|
+
end
|
107
|
+
|
108
|
+
# Overrides base Filesystem#sandbox_dir
|
109
|
+
def sandbox_dir
|
110
|
+
::File.join(right_link_home_dir, 'sandbox')
|
111
|
+
end
|
112
|
+
|
113
|
+
# Overrides base Filesystem#long_path_to_short_path
|
114
|
+
def long_path_to_short_path(long_path)
|
115
|
+
return long_path
|
116
|
+
end
|
117
|
+
|
118
|
+
# Overrides base Filesystem#pretty_path
|
119
|
+
def pretty_path(path, native_fs_flag = false)
|
120
|
+
return path
|
121
|
+
end
|
122
|
+
|
123
|
+
# Overrides base Filesystem#ensure_local_drive_path
|
124
|
+
def ensure_local_drive_path(path, temp_dir_name)
|
125
|
+
return path
|
126
|
+
end
|
127
|
+
|
128
|
+
# Overrides base Filesystem#create_symlink
|
129
|
+
def create_symlink(from_path, to_path)
|
130
|
+
::File.symlink(from_path, to_path)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Provides utilities for managing volumes (disks).
|
135
|
+
class VolumeManager
|
136
|
+
|
137
|
+
# Mounts a volume (returned by VolumeManager.volumes) to the mountpoint
|
138
|
+
# specified.
|
139
|
+
#
|
140
|
+
# @param [Hash] volume info hash (as returned by VolumeManager.volumes)
|
141
|
+
# @param [String] mountpoint where the device will be mounted in the file system
|
142
|
+
#
|
143
|
+
# @return [TrueClass] always true
|
144
|
+
#
|
145
|
+
# @raise [VolumeError] on a failure to mount the device
|
146
|
+
def mount_volume(volume, mountpoint)
|
147
|
+
must_be_overridden
|
148
|
+
end
|
149
|
+
end # VolumeManager
|
150
|
+
|
151
|
+
class Shell
|
152
|
+
# defined for backward compatibility; use Shell#null_output_name
|
153
|
+
NULL_OUTPUT_NAME = '/dev/null'
|
154
|
+
|
155
|
+
# Overrides base Shell#null_output_name
|
156
|
+
def null_output_name
|
157
|
+
NULL_OUTPUT_NAME
|
158
|
+
end
|
159
|
+
|
160
|
+
# Overrides base Shell#format_script_file_name
|
161
|
+
def format_script_file_name(partial_script_file_path, default_extension = nil)
|
162
|
+
# shell files containing shebang are directly executable in Unix, so
|
163
|
+
# assume our scripts have shebang. if not, the error should be obvious.
|
164
|
+
return partial_script_file_path
|
165
|
+
end
|
166
|
+
|
167
|
+
# Overrides base Shell#format_executable_command
|
168
|
+
def format_executable_command(executable_file_path, *arguments)
|
169
|
+
escaped = []
|
170
|
+
space = ' '
|
171
|
+
double_quote = '"'
|
172
|
+
single_quote = "'"
|
173
|
+
[executable_file_path, arguments].flatten.each do |arg|
|
174
|
+
value = arg.to_s
|
175
|
+
needs_escape =
|
176
|
+
value.index(space) ||
|
177
|
+
value.index(double_quote) ||
|
178
|
+
value.index(single_quote)
|
179
|
+
escaped << (needs_escape ? "\"#{value.gsub(double_quote, "\\\"")}\"" : value)
|
180
|
+
end
|
181
|
+
return escaped.join(space)
|
182
|
+
end
|
183
|
+
|
184
|
+
# Overrides base Shell#format_shell_command
|
185
|
+
def format_shell_command(shell_script_file_path, *arguments)
|
186
|
+
# shell files containing shebang are directly executable in Unix, so
|
187
|
+
# assume our scripts have shebang. if not, the error should be obvious.
|
188
|
+
return format_executable_command(shell_script_file_path, arguments)
|
189
|
+
end
|
190
|
+
|
191
|
+
# Overrides base Shell#sandbox_ruby
|
192
|
+
def sandbox_ruby
|
193
|
+
"#{::RightScale::Platform.filesystem.sandbox_dir}/bin/ruby"
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
class Rng
|
198
|
+
|
199
|
+
# Overrides base Rng#pseudorandom_bytes
|
200
|
+
def pseudorandom_bytes(count)
|
201
|
+
result = nil
|
202
|
+
::File.open('/dev/urandom', 'r') { |f| result = f.read(count) }
|
203
|
+
result
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
class Process
|
208
|
+
|
209
|
+
# Overrides base Process#resident_set_size
|
210
|
+
def resident_set_size(pid = nil)
|
211
|
+
pid = $$ unless pid
|
212
|
+
output_text = execute("ps -o rss= -p #{pid}")
|
213
|
+
return output_text.to_i
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
private
|
218
|
+
|
219
|
+
# Overrides base Platform#initialize_genus
|
220
|
+
def initialize_genus
|
221
|
+
true # do nothing
|
222
|
+
end
|
223
|
+
|
224
|
+
end # Platform
|
225
|
+
|
226
|
+
end # RightScale
|