lib/elecksee/ephemeral.rb in elecksee-1.0.8 vs lib/elecksee/ephemeral.rb in elecksee-1.0.10
- old
+ new
@@ -2,42 +2,25 @@
require 'fileutils'
require 'tmpdir'
require 'etc'
%w(
- helpers lxc storage/overlay_directory
- storage/overlay_mount storage/virtual_device
+ 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
class Ephemeral
include Helpers
+ include Helpers::Options
+ include Helpers::Copies
- NAME_FILES = %w(fstab config)
- HOSTNAME_FILES = %w(
- rootfs/etc/hostname
- rootfs/etc/hosts
- rootfs/etc/sysconfig/network
- rootfs/etc/sysconfig/network-scripts/ifcfg-eth0
- )
-
- class << self
- attr_reader :options
-
- def option(name, short, type, args={})
- @options ||= {}
- @options[name] = args.merge(:short => short, :type => type)
- instance_eval do
- attr_accessor name.to_sym
- end
- end
- end
-
option :original, '-o', :string, :required => true, :desc => 'Original container name'
option :ipaddress, '-I', :string, :desc => 'Custom IP address'
option :gateway, '-G', :string, :desc => 'Custom gateway'
option :netmask, '-N', :string, :default => '255.255.255.0', :desc => 'Custom netmask'
option :device, '-D', :integer, :desc => 'Create VBD for overlay of size {SIZE}M'
@@ -47,10 +30,11 @@
option :bind, '-b', :string, :desc => 'Bind provided directory (non-ephemeral)'
option :user, '-u', :string, :desc => 'Deprecated: Provided for compatibility'
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'
attr_reader :name
attr_reader :cli
attr_reader :hostname
attr_reader :path
@@ -61,10 +45,11 @@
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)
@name = File.basename(@path)
@hostname = @name.gsub(%r{[^A-Za-z0-9\-]}, '')
@ephemeral_binds = []
@lxc = nil
end
@@ -79,34 +64,40 @@
if(cli)
puts "New ephemeral container started. (#{name})"
puts " - Connect using: sudo ssh -i #{ssh_key} root@#{lxc.container_ip(10)}"
end
end
+
+ def start_action
+ begin
+ lxc.start
+ if(ephemeral_command)
+ lxc.container_command(ephemeral_command)
+ else
+ cli_output
+ lxc.wait_for_state(:stopped)
+ end
+ ensure
+ cleanup
+ end
+ true
+ end
def start!(*args)
register_traps
setup
if(daemon)
if(args.include?(:fork))
fork do
- lxc.start
- cli_output
- lxc.wait_for_state(:stopped)
- cleanup
+ start_action
end
else
Process.daemon
- lxc.start
- cli_output
- lxc.wait_for_state(:stopped)
- cleanup
+ start_action
end
else
- lxc.start
- cli_output
- lxc.wait_for_state(:stopped)
- cleanup
+ start_action
end
end
def cleanup
lxc.stop
@@ -121,43 +112,11 @@
false
end
end
private
-
- def configure!(args)
- self.class.options.each do |name, opts|
- argv = args.detect{|k,v| (Array(opts[:aliases]) + Array(opts[:short]) + [name]).include?(k.to_sym)}
- argv = argv.last if argv
- argv ||= opts[:default]
- if(argv)
- check_type!(name, argv, opts[:type])
- self.send("#{name}=", argv)
- else
- if(opts[:required])
- raise ArgumentError.new "Missing required argument: #{name}"
- end
- end
- end
- if(ipaddress && gateway.nil?)
- self.gateway = ipaddress.sub(%r{\d+$}, '1')
- end
- end
-
- def check_type!(arg_name, val, type)
- valid = false
- case type
- when :string
- valid = val.is_a?(String)
- when :boolean
- valid = val.is_a?(TrueClass) || val.is_a?(FalseClass)
- when :integer
- valid = val.is_a?(Numeric)
- end
- raise ArgumentError.new "Invalid type provided for #{arg_name}. Expecting value type of: #{type.inspect} Got: #{val.class} - #{val}" unless valid
- end
-
+
def setup
create
build_overlay
update_naming
discover_binds
@@ -172,139 +131,52 @@
@ephemeral_device.mount
end
@ephemeral_overlay = OverlayMount.new(
:base => Lxc.new(original).rootfs.to_path,
:overlay => ephemeral_device.target_path,
- :target => lxc.rootfs.to_path,
+ :target => lxc.path.join('rootfs').to_path,
:overlay_type => union
)
@ephemeral_overlay.mount
end
-
- def writable_path!(path)
- unless(File.directory?(File.dirname(path)))
- command("mkdir -p #{File.dirname(path)}", :sudo => true)
- end
- unless(File.exists?(path))
- command("touch #{path}", :sudo => true)
- end
- command("chown #{Etc.getlogin} #{path}", :sudo => true)
- end
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
- command("chown -R #{Etc.getlogin} #{path}", :sudo => true)
@lxc = Lxc.new(name)
- Dir.mkdir(lxc.rootfs.to_path)
- contents = File.readlines(lxc.config)
- File.open(lxc.config, 'w') do |file|
- contents.each do |line|
- if(line.strip.start_with?('lxc.network.hwaddr'))
- file.write "00:16:3e#{SecureRandom.hex(3).gsub(/(..)/, ':\1')}"
- else
- file.write line
- end
- end
- end
+ command("mkdir -p '#{lxc.path.join('rootfs')}'", :sudo => true)
+ update_net_hwaddr
end
# TODO: Discovered binds for ephemeral are all tmpfs for now.
+ # TODO: We should default to overlay mount, make virt dev optional
def discover_binds
- contents = File.readlines(lxc.path.join('fstab'))
- File.open(lxc.path.join('fstab'), 'w') do |file|
- contents.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.mount
- FileUtils.mkdir_p(container_target)
- ephemeral_binds << device
- if(union == 'overlayfs')
- file.write "none #{container_target} overlayfs upperdir=#{device.mount_path},lowerdir=#{source} 0 0"
- else
- file.write "none #{container_target} aufs br=#{device.mount_path}=rw:#{source}=ro,noplink 0 0"
- end
+ 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.mount
+ FileUtils.mkdir_p(container_target)
+ ephemeral_binds << device
+ if(union == 'overlayfs')
+ "none #{container_target} overlayfs upperdir=#{device.mount_path},lowerdir=#{source} 0 0"
else
- file.write line
+ "none #{container_target} aufs br=#{device.mount_path}=rw:#{source}=ro,noplink 0 0"
end
+ else
+ line
end
- # If bind option used, bind in for rw
- if(bind)
- command("mkdir -p #{lxc.rootfs.join(bind).to_path}", :sudo => true)
- file.puts "#{bind} #{lxc.rootfs.join(bind)} none bind 0 0"
- end
end
- end
-
- def update_naming
- NAME_FILES.each do |file|
- next unless File.exists?(lxc.path.join(file))
- writable_path!(lxc.path.join(file).to_path)
- contents = File.read(lxc.path.join(file))
- File.open(lxc.path.join(file), 'w') do |new_file|
- new_file.write contents.gsub(original, name)
- end
+ # If bind option used, bind in for rw
+ 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
- HOSTNAME_FILES.each do |file|
- next unless File.exists?(lxc.path.join(file))
- writable_path!(lxc.path.join(file).to_path)
- contents = File.read(lxc.path.join(file))
- File.open(lxc.path.join(file), 'w') do |new_file|
- new_file.write contents.gsub(original, hostname)
- end
- end
- end
-
- def el_platform?
- lxc.rootfs.join('etc/redhat-release').exist?
- end
-
- def apply_custom_networking
- if(el_platform?)
- writable_path!(path = lxc.rootfs.join('etc/sysconfig/network-scripts/ifcfg-eth0'))
- File.open(path, 'w') do |file|
- file.write <<-EOF
-DEVICE=eth0
-BOOTPROTO=static
-NETMASK=#{netmask}
-IPADDR=#{ipaddress}
-ONBOOT=yes
-TYPE=Ethernet
-USERCTL=yes
-PEERDNS=yes
-IPV6INIT=no
-GATEWAY=#{gateway}
-EOF
- end
- writable_path!(path = lxc.rootfs.join('etc/sysconfig/network'))
- File.open(path, 'w') do |file|
- file.write <<-EOF
-NETWORKING=yes
-HOSTNAME=#{hostname}
-EOF
- end
- File.open(@lxc.rootfs.join('etc/rc.local'), 'w') do |file|
- file.puts "hostname #{hostname}"
- end
- else
- writable_path!(path = lxc.rootfs.join('etc/network/interfaces'))
- File.open(path, 'w') do |file|
- file.write <<-EOF
-auto lo
-iface lo inet loopback
-auto eth0
-iface eth0 inet static
-address #{ipaddress}
-netmask #{netmask}
-gateway #{gateway}
-EOF
- end
- end
+ write_file(lxc.path.join('fstab'), contents.join)
end
end
end