lib/elecksee/ephemeral.rb in elecksee-1.0.22 vs lib/elecksee/ephemeral.rb in elecksee-1.1.0
- old
+ new
@@ -1,20 +1,13 @@
+require 'elecksee'
require 'securerandom'
require 'fileutils'
require 'tmpdir'
require 'etc'
-%w(
- helpers/base helpers/options helpers/copies lxc
- storage/overlay_directory storage/overlay_mount
- storage/virtual_device
-).each do |path|
- require "elecksee/#{path}"
-end
-
class Lxc
-
+ # Create ephemeral containers
class Ephemeral
include Helpers
include Helpers::Options
include Helpers::Copies
@@ -32,19 +25,31 @@
option :ssh_key, '-S', :string, :default => '/opt/hw-lxc-config/id_rsa', :aliases => 'ssh-key', :desc => 'Deprecated: Provided for compatibility'
option :lxc_dir, '-L', :string, :default => '/var/lib/lxc', :aliases => 'lxc-dir', :desc => 'Directory of LXC store'
option :tmp_dir, '-T', :string, :default => '/tmp/lxc/ephemerals', :aliases => 'tmp-dir', :desc => 'Directory of ephemeral temp files'
option :ephemeral_command, '-C', :string, :aliases => 'command'
+ # @return [String] name of container
attr_reader :name
+ # @return [TrueClass, FalseClass] enable CLI output
attr_reader :cli
+ # @return [String] hostname of container
attr_reader :hostname
+ # @return [String] path to container
attr_reader :path
+ # @return [Lxc] instance of ephemeral
attr_reader :lxc
+ # @return [Storage::OverlayDirectory, Storage::VirtualDevice]
attr_reader :ephemeral_device
+ # @return [Storage::OverlayMount]
attr_reader :ephemeral_overlay
+ # @return [Array<Storage::VirtualDevice]
attr_reader :ephemeral_binds
+ # Create new instance
+ #
+ # @param args [Hash]
+ # @option args [TrueClass, FalseClass] :cli enable CLI output
def initialize(args={})
configure!(args)
@cli = args[:cli]
@path = command("mktemp -d -p #{lxc_dir} #{original}-XXXXXXXXXXXX", :sudo => true).stdout.strip
command("chmod 0755 #{@path}", :sudo => true)
@@ -52,23 +57,38 @@
@hostname = @name.gsub(%r{[^A-Za-z0-9\-]}, '')
@ephemeral_binds = []
@lxc = nil
end
+ # Trap signals to force cleanup
+ #
+ # @return [TrueClass]
def register_traps
%w(TERM INT QUIT).each do |sig|
Signal.trap(sig){ cleanup && raise }
end
+ true
end
+ # Write output to CLI
+ #
+ # @return [TrueClass, FalseClass]
def cli_output
if(cli)
puts "New ephemeral container started. (#{name})"
puts " - Connect using: sudo ssh -i #{ssh_key} root@#{lxc.container_ip(10)}"
+ true
+ else
+ false
end
end
+ # Start the ephemeral container
+ #
+ # @return [TrueClass]
+ # @note generally should not be called directly
+ # @see start!
def start_action
begin
lxc.start
if(ephemeral_command)
lxc.wait_for_state(:running)
@@ -81,14 +101,23 @@
cleanup
end
true
end
+ # Create the ephemeral container
+ #
+ # @return [TrueClass]
def create!
setup
+ true
end
+ # Start the ephemeral container
+ #
+ # @param args [Symbol] argument list
+ # @return [TrueClass]
+ # @note use :fork to fork startup
def start!(*args)
register_traps
setup
if(daemon)
if(args.include?(:fork))
@@ -100,12 +129,16 @@
start_action
end
else
start_action
end
+ true
end
+ # Stop container and cleanup ephemeral items
+ #
+ # @return [TrueClass, FalseClass]
def cleanup
lxc.stop
@ephemeral_overlay.unmount
@ephemeral_binds.map(&:destroy)
@ephemeral_device.destroy
@@ -118,54 +151,69 @@
end
end
private
+ # Setup the ephemeral container resources
+ #
+ # @return [TrueClass]
def setup
create
build_overlay
update_naming
discover_binds
apply_custom_networking if ipaddress
+ true
end
+ # Create the overlay
+ #
+ # @return [TrueClass, FalseClass]
def build_overlay
if(directory)
- @ephemeral_device = OverlayDirectory.new(name, :tmp_dir => directory.is_a?(String) ? directory : tmp_dir)
+ @ephemeral_device = Storage::OverlayDirectory.new(name, :tmp_dir => directory.is_a?(String) ? directory : tmp_dir)
else
- @ephemeral_device = VirtualDevice.new(name, :size => device, :tmp_fs => !device, :tmp_dir => tmp_dir)
+ @ephemeral_device = Storage::VirtualDevice.new(name, :size => device, :tmp_fs => !device, :tmp_dir => tmp_dir)
@ephemeral_device.mount
end
- @ephemeral_overlay = OverlayMount.new(
+ @ephemeral_overlay = Storage::OverlayMount.new(
:base => Lxc.new(original).rootfs.to_path,
:overlay => ephemeral_device.target_path,
:target => lxc.path.join('rootfs').to_path,
:overlay_type => union
)
@ephemeral_overlay.mount
end
+ # Create the container
+ #
+ # @return [TrueClass]
def create
Dir.glob(File.join(lxc_dir, original, '*')).each do |o_path|
next unless File.file?(o_path)
command("cp #{o_path} #{File.join(path, File.basename(o_path))}", :sudo => true)
end
@lxc = Lxc.new(name)
command("mkdir -p #{lxc.path.join('rootfs')}", :sudo => true)
update_net_hwaddr
+ true
end
- # TODO: Discovered binds for ephemeral are all tmpfs for now.
- # TODO: We should default to overlay mount, make virt dev optional
+ # Discover any bind mounts defined
+ #
+ # @return [TrueClass]
+ # @todo discovered binds for ephemeral are all tmpfs for
+ # now. should default to overlay mount, make virtual
+ # device and tmpfs optional
def discover_binds
contents = File.readlines(lxc.path.join('fstab')).each do |line|
parts = line.split(' ')
if(parts[3] == 'bind')
source = parts.first
target = parts[1].sub(%r{^.+rootfs/}, '')
container_target = lxc.rootfs.join(target).to_path
- device = VirtualDevice.new(target.gsub('/', '_'), :tmp_fs => true)
+ device = Storage::VirtualDevice.new(target.gsub('/', '_'), :tmp_fs => true)
device.mount
FileUtils.mkdir_p(container_target)
ephemeral_binds << device
if(union == 'overlayfs')
"none #{container_target} overlayfs upperdir=#{device.mount_path},lowerdir=#{source} 0 0"
@@ -180,8 +228,10 @@
if(bind)
command("mkdir -p #{lxc.rootfs.join(bind).to_path}", :sudo => true)
contents << "#{bind} #{lxc.rootfs.join(bind)} none bind 0 0\n"
end
write_file(lxc.path.join('fstab'), contents.join)
+ true
end
+
end
end