class LXC::Container

Main Container Class

@author Zachary Patten <zachary AT jovelabs DOT com>

Constants

REGEX_PID

RegEx pattern for extracting the container PID from the “lxc-info” command output.

REGEX_STATE

RegEx pattern for extracting the container state from the “lxc-info” command output.

STATES

An array containing the valid container states extracted from the LXC c-source code.

Attributes

lxc[R]

Returns the parent LXC class instance

@return [LXC] Parent LXC class instance.

name[R]

Returns the container name

@return [String] Container name

Public Class Methods

new(options={}) click to toggle source

@param [Hash] options Options hash. @option options [LXC] :lxc Our parent LXC class instance. @option options [String] :name The name of the container.

# File lib/lxc/container.rb, line 75
def initialize(options={})
  @lxc  = options[:lxc]
  @name = options[:name]

  raise ContainerError, "You must supply a LXC object!" if @lxc.nil?
  raise ContainerError, "You must supply a container name!" if (@name.nil? || @name.empty?)
end

Public Instance Methods

attach(*args) click to toggle source

Run an application inside a container

Executes the supplied application inside a container. The container must already be running.

@see lxc-attach

# File lib/lxc/container.rb, line 243
def attach(*args)
  self.exec("lxc-attach", *args)
end
bootstrap(content) click to toggle source

Bootstrap a container

Renders the supplied text blob inside a container as a script and executes it via lxc-attach. The container must already be running.

@see lxc-attach

@param [String] content The content to render in the container and

execute.  This is generally a bash script of some sort for example.

@return [String] The output of lxc-attach.

# File lib/lxc/container.rb, line 257
def bootstrap(content)
  output = nil

  ZTK::RescueRetry.try(:tries => 5, :on => ContainerError) do
    tempfile = Tempfile.new("bootstrap")
    lxc_tempfile  = File.join("", "tmp", File.basename(tempfile.path))
    host_tempfile = File.join(self.fs_root, lxc_tempfile)

    self.lxc.runner.file(:target => host_tempfile, :chmod => '0755', :chown => 'root:root') do |file|
      file.puts(content)
    end

    output = self.attach(%(-- /bin/bash #{lxc_tempfile}))

    if !(output =~ /#{lxc_tempfile}: No such file or directory/).nil?
      raise ContainerError, "We could not find the bootstrap file!"
    end
  end

  output
end
clone(*args) click to toggle source

Clone the container

Runs the “lxc-clone” command.

@return [Array<String>] Lines of output from the executed command. @see lxc-clone

# File lib/lxc/container.rb, line 140
def clone(*args)
  self.lxc.exec("lxc-clone", *args)
end
config() click to toggle source

LXC configuration class

Gets the LXC configuration class object

@return [LXC::Config] Returns the LXC configuration object.

# File lib/lxc/container.rb, line 88
def config
  @config ||= LXC::Config.new(@lxc, "/etc/lxc/#{@name}")
end
console() click to toggle source

Launch a console for the container

@see lxc-console

# File lib/lxc/container.rb, line 282
def console
  self.exec("lxc-console")
end
container_root() click to toggle source

Directory for the container

@return [String] The directory for the container.

# File lib/lxc/container.rb, line 378
def container_root
  File.join('/', 'var', 'lib', 'lxc', self.name)
end
cpu_usage() click to toggle source

CPU Time in Seconds

# File lib/lxc/container.rb, line 323
def cpu_usage
  result = self.exec(%(lxc-cgroup), %(cpuacct.usage))
  (result.empty? ? 0 : (result.to_i / 1E9).to_i)
end
create(*args) click to toggle source

Create the container

Runs the “lxc-create” command.

@param [Array] args Additional command-line arguments. @return [Array<String>] Lines of output from the executed command.

# File lib/lxc/container.rb, line 98
def create(*args)
  self.exec("lxc-create", *args)
end
destroy(*args) click to toggle source

Destroy the container

Runs the “lxc-destroy” command. If the container has not been stopped first then this will fail unless '-f' is passed as an argument. See the 'lxc-destroy' man page for more details.

@param [Array] args Additional command-line arguments. @return [Array<String>] Lines of output from the executed command.

# File lib/lxc/container.rb, line 110
def destroy(*args)
  self.exec("lxc-destroy", *args)
end
disk_usage(ephemeral=false) click to toggle source

Current Disk Usage

# File lib/lxc/container.rb, line 329
def disk_usage(ephemeral=false)
  result = (@lxc.exec(%(du -sb #{self.fs_root(ephemeral)})).split.first rescue nil)
  ((result.nil? || result.empty?) ? 0 : result.to_i)
end
exec(*args) click to toggle source

Linux container command execution wrapper

Executes the supplied command by injecting the container name into the argument list and then passes to the arguments to the top-level LXC class exec method.

@param [Array] args Additional command-line arguments. @return [Array<String>] Stripped output text of the executed command.

@see LXC#exec

# File lib/lxc/container.rb, line 344
def exec(*args)
  arguments = Array.new
  arguments << args.shift
  arguments << %(-n #{self.name})
  arguments << args
  arguments.flatten!.compact!

  @lxc.exec(*arguments)
end
execute(*args) click to toggle source

Run an application inside a container

Launches the container, executing the supplied application inside it.

@see lxc-execute

# File lib/lxc/container.rb, line 233
def execute(*args)
  self.exec("lxc-execute", "-f", self.config.filename, "--", *args)
end
exists?() click to toggle source

Does the container exist?

@return [Boolean] Returns true if the container exists, false otherwise.

# File lib/lxc/container.rb, line 224
def exists?
  @lxc.exists?(self.name)
end
freeze(*args) click to toggle source

Freeze the container

Runs the “lxc-freeze” command.

@param [Array] args Additional command-line arguments. @return [Array<String>] Lines of output from the executed command.

# File lib/lxc/container.rb, line 167
def freeze(*args)
  self.exec("lxc-freeze", *args)
end
fs_root(ephemeral=false) click to toggle source

Root directory for the containers file system

@param [Boolean] ephemeral True if we should construct a path to the

union filesystem used by ephemeral containers.  False if we should
construct a traditional path.

@return [String] The root directory for the container.

# File lib/lxc/container.rb, line 360
def fs_root(ephemeral=false)
  if (ephemeral == true)
    File.join(self.container_root, 'delta0')
  else
    File.join(self.container_root, 'rootfs')
  end
end
fs_tab() click to toggle source

Static information about the containers filesystems

@return [String] The path to the containers fstab.

# File lib/lxc/container.rb, line 371
def fs_tab
  File.join(self.container_root, 'fstab')
end
info(*args) click to toggle source

Information on the container

Runs the “lxc-info” command.

@param [Array] args Additional command-line arguments. @return [Array<String>] Lines of output from the executed command.

# File lib/lxc/container.rb, line 187
def info(*args)
  self.exec("lxc-info", *args).split("\n").uniq.flatten
end
inspect() click to toggle source

Provides a concise string representation of the class @return [String]

# File lib/lxc/container.rb, line 384
def inspect
  tags = Array.new
  tags << "name=#{self.name.inspect}"
  tags = tags.join(' ')

  "#<LXC::Container #{tags}>"
end
memory_usage() click to toggle source

Current Memory Usage

# File lib/lxc/container.rb, line 317
def memory_usage
  result = self.exec(%(lxc-cgroup), %(memory.usage_in_bytes))
  (result.empty? ? 0 : result.to_i)
end
pid(*args) click to toggle source

PID of the container

Runs the “lxc-info” command with the “–pid” flag.

@param [Array] args Additional command-line arguments. @return [Integer] Current PID of the container.

# File lib/lxc/container.rb, line 214
def pid(*args)
  result = self.info("--pid", *args).collect{ |str| str.scan(REGEX_PID) }
  result.flatten!.compact!

  (result.first.strip.to_i rescue -1)
end
reload(options={})
Alias for: restart
restart(options={}) click to toggle source

Restart the container

# File lib/lxc/container.rb, line 155
def restart(options={})
  self.stop
  self.start
end
Also aliased as: reload
start(*args) click to toggle source

Start the container

Runs the “lxc-start” command.

@param [Array] args Additional command-line arguments. @return [Array<String>] Lines of output from the executed command.

# File lib/lxc/container.rb, line 120
def start(*args)
  self.exec("lxc-start", *args)
end
start_ephemeral(*args) click to toggle source

Start an ephemeral copy of the container

Runs the “lxc-start-ephemeral” command.

@return [Array<String>] Lines of output from the executed command. @see lxc-start-ephemeral

# File lib/lxc/container.rb, line 130
def start_ephemeral(*args)
  self.lxc.exec("lxc-start-ephemeral", *args)
end
state(*args) click to toggle source

State of the container

Runs the “lxc-info” command with the “–state” flag.

@param [Array] args Additional command-line arguments. @return [Symbol] Current state of the container.

# File lib/lxc/container.rb, line 197
def state(*args)
  if self.exists?
    result = self.info("--state", *args).collect{ |str| str.scan(REGEX_STATE) }
    result.flatten!.compact!

    (result.first.strip.downcase.to_sym rescue :unknown)
  else
    :not_created
  end
end
stop(*args) click to toggle source

Stop the container

Runs the “lxc-stop” command.

@param [Array] args Additional command-line arguments. @return [Array<String>] Lines of output from the executed command.

# File lib/lxc/container.rb, line 150
def stop(*args)
  self.exec("lxc-stop", *args)
end
unfreeze(*args) click to toggle source

Unfreeze (thaw) the container

Runs the “lxc-unfreeze” command.

@param [Array] args Additional command-line arguments. @return [Array<String>] Lines of output from the executed command.

# File lib/lxc/container.rb, line 177
def unfreeze(*args)
  self.exec("lxc-unfreeze", *args)
end
wait(states, timeout=60) click to toggle source

Wait for a specific container state

Runs the “lxc-wait” command.

The timeout only works when using remote control via SSH and will orphan the process ('lxc-wait') on the remote host.

@param [Symbol,Array] states A single symbol or an array of symbols

representing container states for which we will wait for the container
to change state to.

@param [Integer] timeout How long in seconds we will wait before the

operation times out.

@return [Boolean] Returns true of the state change happened, false

otherwise.
# File lib/lxc/container.rb, line 300
def wait(states, timeout=60)
  state_arg = [states].flatten.map do |state|
    state.to_s.upcase.strip
  end.join('|')

  begin
    Timeout.timeout(timeout) do
      self.exec("lxc-wait", "-s", %('#{state_arg}'))
    end
  rescue Timeout::Error => e
    return false
  end

  true
end