elecksee 1.0.2 → 1.0.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/CHANGELOG.md +4 -0
- data/bin/lxc-awesome-ephemeral +57 -2
- data/lib/elecksee/clone.rb +15 -0
- data/lib/elecksee/ephemeral.rb +310 -0
- data/lib/elecksee/helpers.rb +70 -0
- data/lib/elecksee/lxc.rb +409 -5
- data/lib/elecksee/lxc_file_config.rb +86 -0
- data/lib/elecksee/storage/overlay_directory.rb +31 -0
- data/lib/elecksee/storage/overlay_mount.rb +60 -0
- data/lib/elecksee/storage/virtual_device.rb +81 -0
- data/lib/elecksee/version.rb +1 -1
- metadata +9 -39
- data/Gemfile.lock +0 -18
- data/lib/elecksee/awesome.rb +0 -14
- data/lib/elecksee/vendor/lxc/CHANGELOG.md +0 -37
- data/lib/elecksee/vendor/lxc/Gemfile +0 -4
- data/lib/elecksee/vendor/lxc/Gemfile.lock +0 -41
- data/lib/elecksee/vendor/lxc/README.md +0 -112
- data/lib/elecksee/vendor/lxc/attributes/default.rb +0 -28
- data/lib/elecksee/vendor/lxc/files/default/knife_lxc +0 -228
- data/lib/elecksee/vendor/lxc/files/default/lxc-awesome-ephemeral +0 -495
- data/lib/elecksee/vendor/lxc/libraries/lxc.rb +0 -366
- data/lib/elecksee/vendor/lxc/libraries/lxc_expanded_resources.rb +0 -40
- data/lib/elecksee/vendor/lxc/libraries/lxc_file_config.rb +0 -84
- data/lib/elecksee/vendor/lxc/libraries/monkey.rb +0 -51
- data/lib/elecksee/vendor/lxc/metadata.rb +0 -12
- data/lib/elecksee/vendor/lxc/providers/config.rb +0 -75
- data/lib/elecksee/vendor/lxc/providers/container.rb +0 -318
- data/lib/elecksee/vendor/lxc/providers/default.rb +0 -57
- data/lib/elecksee/vendor/lxc/providers/ephemeral.rb +0 -40
- data/lib/elecksee/vendor/lxc/providers/fstab.rb +0 -30
- data/lib/elecksee/vendor/lxc/providers/interface.rb +0 -45
- data/lib/elecksee/vendor/lxc/providers/service.rb +0 -53
- data/lib/elecksee/vendor/lxc/recipes/containers.rb +0 -13
- data/lib/elecksee/vendor/lxc/recipes/default.rb +0 -58
- data/lib/elecksee/vendor/lxc/recipes/install_dependencies.rb +0 -15
- data/lib/elecksee/vendor/lxc/recipes/knife.rb +0 -37
- data/lib/elecksee/vendor/lxc/resources/config.rb +0 -19
- data/lib/elecksee/vendor/lxc/resources/container.rb +0 -54
- data/lib/elecksee/vendor/lxc/resources/default.rb +0 -12
- data/lib/elecksee/vendor/lxc/resources/ephemeral.rb +0 -13
- data/lib/elecksee/vendor/lxc/resources/fstab.rb +0 -12
- data/lib/elecksee/vendor/lxc/resources/interface.rb +0 -13
- data/lib/elecksee/vendor/lxc/resources/service.rb +0 -5
- data/lib/elecksee/vendor/lxc/templates/default/client.rb.erb +0 -13
- data/lib/elecksee/vendor/lxc/templates/default/default-lxc.erb +0 -3
- data/lib/elecksee/vendor/lxc/templates/default/file_content.erb +0 -2
- data/lib/elecksee/vendor/lxc/templates/default/fstab.erb +0 -5
- data/lib/elecksee/vendor/lxc/templates/default/interface.erb +0 -27
data/CHANGELOG.md
CHANGED
data/bin/lxc-awesome-ephemeral
CHANGED
@@ -1,5 +1,60 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require 'elecksee/
|
3
|
+
require 'elecksee/ephemeral'
|
4
|
+
require 'getoptlong'
|
4
5
|
|
5
|
-
|
6
|
+
require 'pp'
|
7
|
+
|
8
|
+
opts = Lxc::Ephemeral.options.map do |k,v|
|
9
|
+
res = [
|
10
|
+
["--#{k}", v[:short], v[:type] == :boolean ? GetoptLong::NO_ARGUMENT : GetoptLong::REQUIRED_ARGUMENT]
|
11
|
+
]
|
12
|
+
if(v[:aliases])
|
13
|
+
Array(v[:aliases]).each do |al|
|
14
|
+
res << ["--#{al}", v[:type] == :boolean ? GetoptLong::NO_ARGUMENT : GetoptLong::REQUIRED_ARGUMENT]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
res
|
18
|
+
end.flatten(1) << ['--help', '-h', GetoptLong::NO_ARGUMENT]
|
19
|
+
|
20
|
+
opts = GetoptLong.new(*opts)
|
21
|
+
|
22
|
+
config = {}
|
23
|
+
opts.each do |opt,arg|
|
24
|
+
case opt
|
25
|
+
when '--help'
|
26
|
+
puts 'Usage: lxc-awesome-ephemeral [OPTS] -o NAME'
|
27
|
+
output = []
|
28
|
+
Lxc::Ephemeral.options.map do |k,v|
|
29
|
+
option = "--#{k} #{v[:short]}"
|
30
|
+
unless(v[:type] == :boolean)
|
31
|
+
option << ' VAL'
|
32
|
+
end
|
33
|
+
output << {:opt => option, :desc => v[:desc], :alias => v[:aliases]}
|
34
|
+
end
|
35
|
+
opt_len = output.map{|o| o[:opt].length}.max + 2
|
36
|
+
output.each do |option|
|
37
|
+
puts " #{option[:opt]}:#{' ' * (opt_len - option[:opt].length)}#{option[:desc]}"
|
38
|
+
Array(option[:alias]).each do |a|
|
39
|
+
puts " --#{a}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
exit -1
|
43
|
+
when '--version'
|
44
|
+
else
|
45
|
+
key = opt.sub('--', '').to_sym
|
46
|
+
opt_conf = Lxc::Ephemeral.options[key]
|
47
|
+
case opt_conf[:type]
|
48
|
+
when :boolean
|
49
|
+
val = true
|
50
|
+
when :integer
|
51
|
+
val = arg.to_i
|
52
|
+
else
|
53
|
+
val = arg
|
54
|
+
end
|
55
|
+
end
|
56
|
+
config[key] = val
|
57
|
+
end
|
58
|
+
|
59
|
+
ephemeral = Lxc::Ephemeral.new(config.merge(:cli => true))
|
60
|
+
ephemeral.start!
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'elecksee/helpers'
|
2
|
+
require 'elecksee/lxc'
|
3
|
+
|
4
|
+
class Lxc
|
5
|
+
class Clone
|
6
|
+
|
7
|
+
|
8
|
+
def initialize(args={})
|
9
|
+
args = Mash.new(args)
|
10
|
+
%w(original new_name).each do |key|
|
11
|
+
raise ArgumentError.new "Missing required parameter: #{key}" unless args[key]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,310 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'etc'
|
5
|
+
|
6
|
+
%w(
|
7
|
+
helpers lxc storage/overlay_directory
|
8
|
+
storage/overlay_mount storage/virtual_device
|
9
|
+
).each do |path|
|
10
|
+
require "elecksee/#{path}"
|
11
|
+
end
|
12
|
+
|
13
|
+
class Lxc
|
14
|
+
|
15
|
+
class Ephemeral
|
16
|
+
|
17
|
+
include Helpers
|
18
|
+
|
19
|
+
NAME_FILES = %w(fstab config)
|
20
|
+
HOSTNAME_FILES = %w(
|
21
|
+
rootfs/etc/hostname
|
22
|
+
rootfs/etc/hosts
|
23
|
+
rootfs/etc/sysconfig/network
|
24
|
+
rootfs/etc/sysconfig/network-scripts/ifcfg-eth0
|
25
|
+
)
|
26
|
+
|
27
|
+
class << self
|
28
|
+
attr_reader :options
|
29
|
+
|
30
|
+
def option(name, short, type, args={})
|
31
|
+
@options ||= {}
|
32
|
+
@options[name] = args.merge(:short => short, :type => type)
|
33
|
+
instance_eval do
|
34
|
+
attr_accessor name.to_sym
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
option :original, '-o', :string, :required => true, :desc => 'Original container name'
|
40
|
+
option :ipaddress, '-I', :string, :desc => 'Custom IP address'
|
41
|
+
option :gateway, '-G', :string, :desc => 'Custom gateway'
|
42
|
+
option :netmask, '-N', :string, :default => '255.255.255.0', :desc => 'Custom netmask'
|
43
|
+
option :device, '-D', :integer, :desc => 'Create VBD for overlay of size {SIZE}M'
|
44
|
+
option :directory, '-z', :boolean, :desc => 'Use host based directory for overlay'
|
45
|
+
option :union, '-U', :string, :desc => 'Overlay FS to use (overlayfs or aufs)'
|
46
|
+
option :daemon, '-d', :boolean, :desc => 'Run as a daemon'
|
47
|
+
option :bind, '-b', :string, :desc => 'Bind provided directory (non-ephemeral)'
|
48
|
+
option :user, '-u', :string, :desc => 'Deprecated: Provided for compatibility'
|
49
|
+
option :ssh_key, '-S', :string, :default => '/opt/hw-lxc-config/id_rsa', :aliases => 'ssh-key', :desc => 'Deprecated: Provided for compatibility'
|
50
|
+
option :lxc_dir, '-L', :string, :default => '/var/lib/lxc', :aliases => 'lxc-dir', :desc => 'Directory of LXC store'
|
51
|
+
option :tmp_dir, '-T', :string, :default => '/tmp/lxc/ephemerals', :aliases => 'tmp-dir', :desc => 'Directory of ephemeral temp files'
|
52
|
+
|
53
|
+
attr_reader :name
|
54
|
+
attr_reader :cli
|
55
|
+
attr_reader :hostname
|
56
|
+
attr_reader :path
|
57
|
+
attr_reader :lxc
|
58
|
+
attr_reader :ephemeral_device
|
59
|
+
attr_reader :ephemeral_overlay
|
60
|
+
attr_reader :ephemeral_binds
|
61
|
+
|
62
|
+
def initialize(args={})
|
63
|
+
configure!(args)
|
64
|
+
@cli = args[:cli]
|
65
|
+
@path = Dir.mktmpdir(File.join(lxc_dir, original))
|
66
|
+
@name = File.basename(@path)
|
67
|
+
@hostname = @name.gsub(%r{[^A-Za-z0-9\-]}, '')
|
68
|
+
@ephemeral_binds = []
|
69
|
+
@lxc = nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def register_traps
|
73
|
+
%w(TERM INT QUIT).each do |sig|
|
74
|
+
Signal.trap(sig){ cleanup }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def cli_output
|
79
|
+
if(cli)
|
80
|
+
puts "New ephemeral container started. (#{name})"
|
81
|
+
puts " - Connect using: sudo ssh -i #{ssh_key} root@#{lxc.container_ip(10)}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def start!(*args)
|
86
|
+
register_traps
|
87
|
+
setup
|
88
|
+
if(daemon)
|
89
|
+
if(args.include?(:fork))
|
90
|
+
fork do
|
91
|
+
lxc.start
|
92
|
+
cli_output
|
93
|
+
lxc.wait_for_state(:stopped)
|
94
|
+
cleanup
|
95
|
+
end
|
96
|
+
else
|
97
|
+
Process.daemon
|
98
|
+
lxc.start
|
99
|
+
cli_output
|
100
|
+
lxc.wait_for_state(:stopped)
|
101
|
+
cleanup
|
102
|
+
end
|
103
|
+
else
|
104
|
+
lxc.start
|
105
|
+
cli_output
|
106
|
+
lxc.wait_for_state(:stopped)
|
107
|
+
cleanup
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def cleanup
|
112
|
+
lxc.stop
|
113
|
+
@ephemeral_overlay.unmount
|
114
|
+
@ephemeral_binds.map(&:destroy)
|
115
|
+
@ephemeral_device.destroy
|
116
|
+
if(lxc.path.to_path.split('/').size > 1)
|
117
|
+
command("rm -rf #{lxc.path.to_path}", :sudo => true)
|
118
|
+
true
|
119
|
+
else
|
120
|
+
$stderr.puts "This path seems bad and I won't remove it: #{lxc.path.to_path}"
|
121
|
+
false
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
def configure!(args)
|
128
|
+
self.class.options.each do |name, opts|
|
129
|
+
argv = args.detect{|k,v| (Array(opts[:aliases]) + Array(opts[:short]) + [name]).include?(k.to_sym)}
|
130
|
+
argv = argv.last if argv
|
131
|
+
argv ||= opts[:default]
|
132
|
+
if(argv)
|
133
|
+
check_type!(name, argv, opts[:type])
|
134
|
+
self.send("#{name}=", argv)
|
135
|
+
else
|
136
|
+
if(opts[:required])
|
137
|
+
raise ArgumentError.new "Missing required argument: #{name}"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
if(ipaddress && gateway.nil?)
|
142
|
+
self.gateway = ipaddress.sub(%r{\d+$}, '1')
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def check_type!(arg_name, val, type)
|
147
|
+
valid = false
|
148
|
+
case type
|
149
|
+
when :string
|
150
|
+
valid = val.is_a?(String)
|
151
|
+
when :boolean
|
152
|
+
valid = val.is_a?(TrueClass) || val.is_a?(FalseClass)
|
153
|
+
when :integer
|
154
|
+
valid = val.is_a?(Numeric)
|
155
|
+
end
|
156
|
+
raise ArgumentError.new "Invalid type provided for #{arg_name}. Expecting value type of: #{type.inspect} Got: #{val.class} - #{val}" unless valid
|
157
|
+
end
|
158
|
+
|
159
|
+
def setup
|
160
|
+
create
|
161
|
+
build_overlay
|
162
|
+
update_naming
|
163
|
+
discover_binds
|
164
|
+
apply_custom_networking if ipaddress
|
165
|
+
end
|
166
|
+
|
167
|
+
def build_overlay
|
168
|
+
if(directory)
|
169
|
+
@ephemeral_device = OverlayDirectory.new(name, :tmp_dir => directory.is_a?(String) ? directory : tmp_dir)
|
170
|
+
else
|
171
|
+
@ephemeral_device = VirtualDevice.new(name, :size => device, :tmp_fs => !device, :tmp_dir => tmp_dir)
|
172
|
+
@ephemeral_device.mount
|
173
|
+
end
|
174
|
+
@ephemeral_overlay = OverlayMount.new(
|
175
|
+
:base => Lxc.new(original).rootfs.to_path,
|
176
|
+
:overlay => ephemeral_device.target_path,
|
177
|
+
:target => lxc.rootfs.to_path,
|
178
|
+
:overlay_type => union
|
179
|
+
)
|
180
|
+
@ephemeral_overlay.mount
|
181
|
+
end
|
182
|
+
|
183
|
+
def writable_path!(path)
|
184
|
+
unless(File.directory?(File.dirname(path)))
|
185
|
+
command("mkdir -p #{File.dirname(path)}", :sudo => true)
|
186
|
+
end
|
187
|
+
unless(File.exists?(path))
|
188
|
+
command("touch #{path}", :sudo => true)
|
189
|
+
end
|
190
|
+
command("chown #{Etc.getlogin} #{path}", :sudo => true)
|
191
|
+
end
|
192
|
+
|
193
|
+
def create
|
194
|
+
Dir.glob(File.join(lxc_dir, original, '*')).each do |o_path|
|
195
|
+
next unless File.file?(o_path)
|
196
|
+
command("cp #{o_path} #{File.join(path, File.basename(o_path))}", :sudo => true)
|
197
|
+
end
|
198
|
+
command("chown -R #{Etc.getlogin} #{path}", :sudo => true)
|
199
|
+
@lxc = Lxc.new(name)
|
200
|
+
Dir.mkdir(lxc.rootfs.to_path)
|
201
|
+
contents = File.readlines(lxc.config)
|
202
|
+
File.open(lxc.config, 'w') do |file|
|
203
|
+
contents.each do |line|
|
204
|
+
if(line.strip.start_with?('lxc.network.hwaddr'))
|
205
|
+
file.write "00:16:3e#{SecureRandom.hex(3).gsub(/(..)/, ':\1')}"
|
206
|
+
else
|
207
|
+
file.write line
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# TODO: Discovered binds for ephemeral are all tmpfs for now.
|
214
|
+
def discover_binds
|
215
|
+
contents = File.readlines(lxc.path.join('fstab'))
|
216
|
+
File.open(lxc.path.join('fstab'), 'w') do |file|
|
217
|
+
contents.each do |line|
|
218
|
+
parts = line.split(' ')
|
219
|
+
if(parts[3] == 'bind')
|
220
|
+
source = parts.first
|
221
|
+
target = parts[1].sub(%r{^.+rootfs/}, '')
|
222
|
+
container_target = lxc.rootfs.join(target).to_path
|
223
|
+
device = VirtualDevice.new(target.gsub('/', '_'), :tmp_fs => true)
|
224
|
+
device.mount
|
225
|
+
FileUtils.mkdir_p(container_target)
|
226
|
+
ephemeral_binds << device
|
227
|
+
if(union == 'overlayfs')
|
228
|
+
file.write "none #{container_target} overlayfs upperdir=#{device.mount_path},lowerdir=#{source} 0 0"
|
229
|
+
else
|
230
|
+
file.write "none #{container_target} aufs br=#{device.mount_path}=rw:#{source}=ro,noplink 0 0"
|
231
|
+
end
|
232
|
+
else
|
233
|
+
file.write line
|
234
|
+
end
|
235
|
+
end
|
236
|
+
# If bind option used, bind in for rw
|
237
|
+
if(bind)
|
238
|
+
command("mkdir -p #{lxc.rootfs.join(bind).to_path}", :sudo => true)
|
239
|
+
file.puts "#{bind} #{lxc.rootfs.join(bind)} none bind 0 0"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def update_naming
|
245
|
+
NAME_FILES.each do |file|
|
246
|
+
next unless File.exists?(lxc.path.join(file))
|
247
|
+
writable_path!(lxc.path.join(file).to_path)
|
248
|
+
contents = File.read(lxc.path.join(file))
|
249
|
+
File.open(lxc.path.join(file), 'w') do |new_file|
|
250
|
+
new_file.write contents.gsub(original, name)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
HOSTNAME_FILES.each do |file|
|
254
|
+
next unless File.exists?(lxc.path.join(file))
|
255
|
+
writable_path!(lxc.path.join(file).to_path)
|
256
|
+
contents = File.read(lxc.path.join(file))
|
257
|
+
File.open(lxc.path.join(file), 'w') do |new_file|
|
258
|
+
new_file.write contents.gsub(original, hostname)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def el_platform?
|
264
|
+
lxc.rootfs.join('etc/redhat-release').exist?
|
265
|
+
end
|
266
|
+
|
267
|
+
def apply_custom_networking
|
268
|
+
if(el_platform?)
|
269
|
+
writable_path!(path = lxc.rootfs.join('etc/sysconfig/network-scripts/ifcfg-eth0'))
|
270
|
+
File.open(path, 'w') do |file|
|
271
|
+
file.write <<-EOF
|
272
|
+
DEVICE=eth0
|
273
|
+
BOOTPROTO=static
|
274
|
+
NETMASK=#{netmask}
|
275
|
+
IPADDR=#{ipaddress}
|
276
|
+
ONBOOT=yes
|
277
|
+
TYPE=Ethernet
|
278
|
+
USERCTL=yes
|
279
|
+
PEERDNS=yes
|
280
|
+
IPV6INIT=no
|
281
|
+
GATEWAY=#{gateway}
|
282
|
+
EOF
|
283
|
+
end
|
284
|
+
writable_path!(path = lxc.rootfs.join('etc/sysconfig/network'))
|
285
|
+
File.open(path, 'w') do |file|
|
286
|
+
file.write <<-EOF
|
287
|
+
NETWORKING=yes
|
288
|
+
HOSTNAME=#{hostname}
|
289
|
+
EOF
|
290
|
+
end
|
291
|
+
File.open(@lxc.rootfs.join('etc/rc.local'), 'w') do |file|
|
292
|
+
file.puts "hostname #{hostname}"
|
293
|
+
end
|
294
|
+
else
|
295
|
+
writable_path!(path = lxc.rootfs.join('etc/network/interfaces'))
|
296
|
+
File.open(path, 'w') do |file|
|
297
|
+
file.write <<-EOF
|
298
|
+
auto lo
|
299
|
+
iface lo inet loopback
|
300
|
+
auto eth0
|
301
|
+
iface eth0 inet static
|
302
|
+
address #{ipaddress}
|
303
|
+
netmask #{netmask}
|
304
|
+
gateway #{gateway}
|
305
|
+
EOF
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
class Lxc
|
2
|
+
class CommandFailed < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
module Helpers
|
6
|
+
|
7
|
+
def sudo
|
8
|
+
Lxc.sudo
|
9
|
+
end
|
10
|
+
|
11
|
+
# Simple helper to shell out
|
12
|
+
def run_command(cmd, args={})
|
13
|
+
retries = args[:allow_failure_retry].to_i
|
14
|
+
cmd = [sudo, cmd].join(' ') if args[:sudo]
|
15
|
+
begin
|
16
|
+
shlout = Mixlib::ShellOut.new(cmd,
|
17
|
+
:logger => defined?(Chef) ? Chef::Log.logger : log,
|
18
|
+
:live_stream => args[:livestream] ? STDOUT : nil,
|
19
|
+
:timeout => args[:timeout] || 1200,
|
20
|
+
:environment => {'HOME' => detect_home}
|
21
|
+
)
|
22
|
+
shlout.run_command
|
23
|
+
shlout.error!
|
24
|
+
shlout
|
25
|
+
rescue Mixlib::ShellOut::ShellCommandFailed, CommandFailed, Mixlib::ShellOut::CommandTimeout
|
26
|
+
if(retries > 0)
|
27
|
+
log.warn "LXC run command failed: #{cmd}"
|
28
|
+
log.warn "Retrying command. #{args[:allow_failure_retry].to_i - retries} of #{args[:allow_failure_retry].to_i} retries remain"
|
29
|
+
sleep(0.3)
|
30
|
+
retries -= 1
|
31
|
+
retry
|
32
|
+
elsif(args[:allow_failure])
|
33
|
+
true
|
34
|
+
else
|
35
|
+
raise
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def command(*args)
|
41
|
+
run_command(*args)
|
42
|
+
end
|
43
|
+
|
44
|
+
def log
|
45
|
+
if(defined?(Chef))
|
46
|
+
Chef::Log
|
47
|
+
else
|
48
|
+
unless(@logger)
|
49
|
+
require 'logger'
|
50
|
+
@logger = Logger.new('/dev/null')
|
51
|
+
end
|
52
|
+
@logger
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Detect HOME environment variable. If not an acceptable
|
57
|
+
# value, set to /root or /tmp
|
58
|
+
def detect_home(set_if_missing=false)
|
59
|
+
if(ENV['HOME'] && Pathname.new(ENV['HOME']).absolute?)
|
60
|
+
ENV['HOME']
|
61
|
+
else
|
62
|
+
home = File.directory?('/root') && File.writable?('/root') ? '/root' : '/tmp'
|
63
|
+
if(set_if_missing)
|
64
|
+
ENV['HOME'] = home
|
65
|
+
end
|
66
|
+
home
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|