class Mist::LXCContainer
Attributes
distro[R]
ips[R]
name[R]
release[R]
Public Class Methods
new(name, distro = nil, release = nil)
click to toggle source
# File lib/mist/lxc_container.rb, line 21 def initialize(name, distro = nil, release = nil) @name = name @distro = distro @release = release @container = LXC::Container.new(@name) @ips = [] end
Public Instance Methods
create(config, startup_script)
click to toggle source
# File lib/mist/lxc_container.rb, line 34 def create(config, startup_script) raise "Container #{@name} already exists!" if exists? # Find the template for this container; if one does not exist on the host, # create it. template = LXCTemplate.new(distro, release) unless template.exists? Mist.logger.info "Template for #{distro}-#{release} does not exist" template.create(config) end # Fast-clone a new container from the template Mist.logger.info 'Cloning template...' container = template.clone(@name) begin # Start the container Mist.logger.info "Starting #{@name}" container.start container.wait(:running, 30) # Wait for the network to start Mist.logger.info 'Waiting for network...' @ips = [] start = Time.now loop do @ips = container.ip_addresses break unless @ips.empty? sleep 1 raise 'timed out waiting for network' \ if (Time.now - start) >= 30 end # Give the container a few more seconds to allow SSH to start socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0) sockaddr = Socket.sockaddr_in(22, @ips.first) start = Time.now loop do begin if socket.connect_nonblock(sockaddr) == 0 Mist.logger.info 'SSH started' socket.close break else sleep 0.5 end raise 'timed out waiting for SSH' \ if (Time.now - start) >= 30 rescue Errno::ECONNREFUSED, Errno::EWOULDBLOCK, Errno::EINPROGRESS # Ignored end end # Find the rootfs on the host so that we can copy in the startup-script rootfs = container.config_item('lxc.rootfs') match = rootfs.match(/\Aoverlayfs:(.*):(.*)\Z/) rootfs = match[2] if match Mist.logger.debug "rootfs=#{rootfs}" internal_path = File.join('/', 'var', 'lib', 'mist') internal_file = File.join(internal_path, 'startup') external_path = File.join(rootfs, internal_path) external_file = File.join(external_path, 'startup') begin ::FileUtils.mkdir_p(external_path) ::FileUtils.cp startup_script, external_file rescue StandardError => ex Mist.logger.error "failed to copy startup script: #{ex}" raise 'could not copy startup script to container' end # Run the startup script Mist.logger.debug 'running startup script' container.attach(wait: true, stdin: File.open('/dev/null')) do LXC.run_command("/bin/bash #{internal_file}") end rescue StandardError => ex Mist.logger.error "Failed to start container #{@name}: #{ex}" # Attempt to clean up container.stop if container.running? container.destroy if container.defined? raise end @container = container end
destroy()
click to toggle source
# File lib/mist/lxc_container.rb, line 130 def destroy raise "Container #{@name} does not exist!" unless exists? begin @container.stop @container.wait(:stopped, 60) @container.destroy @container = nil @ips = [] rescue StandardError => ex Mist.logger.error "Failed to destroy container #{@name}: #{ex}" raise end end
exists?()
click to toggle source
# File lib/mist/lxc_container.rb, line 30 def exists? @container.defined? end