elecksee 1.0.20 → 1.0.22
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +2 -2
- data/lib/elecksee/helpers/base.rb +5 -2
- data/lib/elecksee/lxc.rb +76 -47
- data/lib/elecksee/storage/virtual_device.rb +12 -9
- data/lib/elecksee/version.rb +1 -4
- metadata +2 -2
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
elecksee (1.0.
|
4
|
+
elecksee (1.0.21)
|
5
5
|
mixlib-shellout
|
6
6
|
net-ssh
|
7
7
|
|
@@ -11,7 +11,7 @@ GEM
|
|
11
11
|
childprocess (0.3.9)
|
12
12
|
ffi (~> 1.0, >= 1.0.11)
|
13
13
|
ffi (1.9.3)
|
14
|
-
mixlib-shellout (1.
|
14
|
+
mixlib-shellout (1.3.0)
|
15
15
|
net-ssh (2.7.0)
|
16
16
|
|
17
17
|
PLATFORMS
|
@@ -49,6 +49,7 @@ class Lxc
|
|
49
49
|
|
50
50
|
# Simple helper to shell out
|
51
51
|
def run_command(cmd, args={})
|
52
|
+
result = nil
|
52
53
|
cmd_type = Lxc.shellout_helper
|
53
54
|
unless(cmd_type)
|
54
55
|
if(defined?(ChildProcess))
|
@@ -57,16 +58,18 @@ class Lxc
|
|
57
58
|
cmd_type = :mixlib_shellout
|
58
59
|
end
|
59
60
|
end
|
61
|
+
com_block = nil
|
60
62
|
case cmd_type
|
61
63
|
when :childprocess
|
62
64
|
require 'tempfile'
|
63
|
-
|
65
|
+
com_block = lambda{ child_process_command(cmd, args) }
|
64
66
|
when :mixlib_shellout
|
65
67
|
require 'mixlib/shellout'
|
66
|
-
|
68
|
+
com_block = lambda{ mixlib_shellout_command(cmd, args) }
|
67
69
|
else
|
68
70
|
raise ArgumentError.new("Unknown shellout helper provided: #{cmd_type}")
|
69
71
|
end
|
72
|
+
result = defined?(Bundler) ? Bundler.with_clean_env{ com_block.call } : com_block.call
|
70
73
|
result == false ? false : CommandResult.new(result)
|
71
74
|
end
|
72
75
|
|
data/lib/elecksee/lxc.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'elecksee/helpers/base'
|
2
|
+
require 'securerandom'
|
3
|
+
require 'shellwords'
|
2
4
|
require 'pathname'
|
3
5
|
require 'tmpdir'
|
4
6
|
|
@@ -71,18 +73,23 @@ class Lxc
|
|
71
73
|
# name:: Name of container
|
72
74
|
# Returns information about given container
|
73
75
|
def info(name)
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
76
|
+
info = run_command("#{sudo}lxc-info -n #{name}", :allow_failure_retry => 3, :allow_failure => true)
|
77
|
+
if(info)
|
78
|
+
Hash[
|
79
|
+
info.stdout.split("\n").map do |string|
|
80
|
+
string.split(': ').map(&:strip)
|
81
|
+
end.map do |key, value|
|
82
|
+
key = key.tr(' ', '_').downcase.to_sym
|
83
|
+
if(key == :state)
|
84
|
+
value = value.downcase.to_sym
|
85
|
+
elsif(value.to_i.to_s == value)
|
86
|
+
value = value.to_i
|
87
|
+
end
|
88
|
+
[key, value]
|
89
|
+
end
|
90
|
+
]
|
82
91
|
else
|
83
|
-
|
84
|
-
res[:pid] = -1
|
85
|
-
res
|
92
|
+
Hash[:state, :unknown, :pid, -1]
|
86
93
|
end
|
87
94
|
end
|
88
95
|
|
@@ -270,34 +277,34 @@ class Lxc
|
|
270
277
|
# Start the container
|
271
278
|
def start(*args)
|
272
279
|
if(args.include?(:no_daemon))
|
273
|
-
run_command("
|
280
|
+
run_command("lxc-start -n #{name}", :sudo => true)
|
274
281
|
else
|
275
|
-
run_command("
|
282
|
+
run_command("lxc-start -n #{name} -d", :sudo => true)
|
276
283
|
wait_for_state(:running)
|
277
284
|
end
|
278
285
|
end
|
279
286
|
|
280
287
|
# Stop the container
|
281
288
|
def stop
|
282
|
-
run_command("
|
289
|
+
run_command("lxc-stop -n #{name}", :allow_failure_retry => 3, :sudo => true)
|
283
290
|
wait_for_state(:stopped)
|
284
291
|
end
|
285
292
|
|
286
293
|
# Freeze the container
|
287
294
|
def freeze
|
288
|
-
run_command("
|
295
|
+
run_command("lxc-freeze -n #{name}", :sudo => true)
|
289
296
|
wait_for_state(:frozen)
|
290
297
|
end
|
291
298
|
|
292
299
|
# Unfreeze the container
|
293
300
|
def unfreeze
|
294
|
-
run_command("
|
301
|
+
run_command("lxc-unfreeze -n #{name}", :sudo => true)
|
295
302
|
wait_for_state(:running)
|
296
303
|
end
|
297
304
|
|
298
305
|
# Shutdown the container
|
299
306
|
def shutdown
|
300
|
-
run_command("
|
307
|
+
run_command("lxc-shutdown -n #{name}", :sudo => true)
|
301
308
|
wait_for_state(:stopped, :timeout => 120)
|
302
309
|
# This block is for fedora/centos/anyone else that does not like lxc-shutdown
|
303
310
|
if(running?)
|
@@ -315,7 +322,29 @@ class Lxc
|
|
315
322
|
unless stopped?
|
316
323
|
stop
|
317
324
|
end
|
318
|
-
run_command("
|
325
|
+
run_command("lxc-destroy -n #{name}", :sudo => true)
|
326
|
+
end
|
327
|
+
|
328
|
+
# command:: command string
|
329
|
+
# opts:: option hash (:networking)
|
330
|
+
# Execute command string within container
|
331
|
+
def execute(command, opts={})
|
332
|
+
if(stopped?)
|
333
|
+
cmd = Shellwords.split(command)
|
334
|
+
result = nil
|
335
|
+
begin
|
336
|
+
tmp_execute_script(command, opts) do |script_path|
|
337
|
+
result = run_command("lxc-execute -n #{name} -- #{script_path}", :sudo => true)
|
338
|
+
end
|
339
|
+
rescue => e
|
340
|
+
if(e.result.stderr.downcase.include?('failed to find an lxc-init'))
|
341
|
+
$stderr.puts "ERROR: Missing `lxc-init` installation on container (#{name}). Install lxc-init on container before using `#execute`!"
|
342
|
+
end
|
343
|
+
raise
|
344
|
+
end
|
345
|
+
else
|
346
|
+
raise "Cannot execute against running container (#{name})"
|
347
|
+
end
|
319
348
|
end
|
320
349
|
|
321
350
|
def direct_container_command(command, args={})
|
@@ -333,35 +362,7 @@ class Lxc
|
|
333
362
|
end
|
334
363
|
end
|
335
364
|
alias_method :knife_container, :direct_container_command
|
336
|
-
|
337
|
-
# Simple helper to shell out
|
338
|
-
def run_command(cmd, args={})
|
339
|
-
retries = args[:allow_failure_retry].to_i
|
340
|
-
begin
|
341
|
-
shlout = Mixlib::ShellOut.new(cmd,
|
342
|
-
:logger => defined?(Chef) ? Chef::Log.logger : log,
|
343
|
-
:live_stream => args[:livestream] ? nil : STDOUT,
|
344
|
-
:timeout => args[:timeout] || 1200,
|
345
|
-
:environment => {'HOME' => detect_home}
|
346
|
-
)
|
347
|
-
shlout.run_command
|
348
|
-
shlout.error!
|
349
|
-
shlout
|
350
|
-
rescue Mixlib::ShellOut::ShellCommandFailed, CommandFailed, Mixlib::ShellOut::CommandTimeout
|
351
|
-
if(retries > 0)
|
352
|
-
log.warn "LXC run command failed: #{cmd}"
|
353
|
-
log.warn "Retrying command. #{args[:allow_failure_retry].to_i - retries} of #{args[:allow_failure_retry].to_i} retries remain"
|
354
|
-
sleep(0.3)
|
355
|
-
retries -= 1
|
356
|
-
retry
|
357
|
-
elsif(args[:allow_failure])
|
358
|
-
true
|
359
|
-
else
|
360
|
-
raise
|
361
|
-
end
|
362
|
-
end
|
363
|
-
end
|
364
|
-
=end
|
365
|
+
|
365
366
|
def wait_for_state(desired_state, args={})
|
366
367
|
args[:sleep_interval] ||= 1.0
|
367
368
|
wait_total = 0.0
|
@@ -371,6 +372,34 @@ class Lxc
|
|
371
372
|
end
|
372
373
|
end
|
373
374
|
|
375
|
+
# command:: command string
|
376
|
+
# Write command to temporary script with networking support wrap
|
377
|
+
def tmp_execute_script(command, opts)
|
378
|
+
script_path = "tmp/#{SecureRandom.uuid}"
|
379
|
+
File.open(rootfs.join(script_path), 'w') do |file|
|
380
|
+
file.puts '#!/bin/sh'
|
381
|
+
unless(opts[:networking] == false)
|
382
|
+
file.write <<-EOS
|
383
|
+
/etc/network/if-pre-up.d/bridge > /dev/null 2>&1
|
384
|
+
ifdown eth0 > /dev/null 2>&1
|
385
|
+
ifup eth0 > /dev/null 2>&1
|
386
|
+
EOS
|
387
|
+
end
|
388
|
+
file.puts command
|
389
|
+
file.puts "RESULT=$?"
|
390
|
+
unless(opts[:networking] == false)
|
391
|
+
file.puts "ifdown eth0 > /dev/null 2>&1"
|
392
|
+
end
|
393
|
+
file.puts "exit $RESULT"
|
394
|
+
end
|
395
|
+
FileUtils.chmod(0755, rootfs.join(script_path))
|
396
|
+
begin
|
397
|
+
yield "/#{script_path}"
|
398
|
+
ensure
|
399
|
+
FileUtils.rm(rootfs.join(script_path))
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
374
403
|
# Detect HOME environment variable. If not an acceptable
|
375
404
|
# value, set to /root or /tmp
|
376
405
|
def detect_home(set_if_missing=false)
|
@@ -1,17 +1,17 @@
|
|
1
1
|
require 'elecksee/helpers/base'
|
2
2
|
|
3
3
|
class Lxc
|
4
|
-
|
4
|
+
|
5
5
|
class VirtualDevice
|
6
6
|
|
7
7
|
include Helpers
|
8
|
-
|
8
|
+
|
9
9
|
attr_reader :name
|
10
10
|
attr_reader :tmp_dir
|
11
11
|
attr_reader :size
|
12
12
|
attr_reader :tmp_fs
|
13
13
|
attr_reader :fs_type
|
14
|
-
|
14
|
+
|
15
15
|
def initialize(name, args={})
|
16
16
|
@name = name
|
17
17
|
@tmp_dir = args[:tmp_dir] || '/tmp/lxc/ephemerals'
|
@@ -23,7 +23,7 @@ class Lxc
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def device_path
|
26
|
-
tmp_fs ?
|
26
|
+
tmp_fs ? :none : File.join(tmp_dir, 'virt-imgs', name)
|
27
27
|
end
|
28
28
|
|
29
29
|
def mount_path
|
@@ -42,7 +42,7 @@ class Lxc
|
|
42
42
|
def mounted?
|
43
43
|
command("mount").stdout.include?(mount_path)
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
def mount
|
47
47
|
unless(mounted?)
|
48
48
|
command("mount -t #{fs_type}#{mount_options} #{device_path} #{mount_path}", :sudo => true)
|
@@ -59,9 +59,11 @@ class Lxc
|
|
59
59
|
|
60
60
|
def destroy
|
61
61
|
unmount
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
unless(device_path == :none)
|
63
|
+
File.delete(device_path) if File.file?(device_path)
|
64
|
+
FileUtils.rm_rf(device_path) if File.directory?(device_path)
|
65
|
+
end
|
66
|
+
FileUtils.rmdir(mount_path) if File.directory?(mount_path) unless mount_path == :none
|
65
67
|
end
|
66
68
|
|
67
69
|
private
|
@@ -69,9 +71,10 @@ class Lxc
|
|
69
71
|
def mount_options
|
70
72
|
' -o loop' unless tmp_fs
|
71
73
|
end
|
72
|
-
|
74
|
+
|
73
75
|
def make_directories!
|
74
76
|
[device_path, mount_path].each do |path|
|
77
|
+
next if path == :none
|
75
78
|
unless(File.directory?(path))
|
76
79
|
FileUtils.mkdir_p(path)
|
77
80
|
end
|
data/lib/elecksee/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elecksee
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.22
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-06-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mixlib-shellout
|