lib/lxc.rb
require 'ztk'
require 'lxc/version'
# Top-Level LXC Class
#
# @author Zachary Patten <zachary AT jovelabs DOT com>
class LXC
# Top-Level Error Class
class LXCError < StandardError; end
autoload :Config, 'lxc/config'
autoload :Container, 'lxc/container'
autoload :Runner, 'lxc/runner'
# The runner we will use to execute all LXC commands.
#
# @overload runner=(value)
# Sets the runner to use.
# @param [LXC::Runner] value
#
# @overload runner
# Gets the runner we are using, if any.
#
# @return [LXC::Runner] Returns the instance of the runner we are using.
attr_accessor :runner
# RegEx pattern for extracting the LXC Version from the "lxc-version" command
# output.
REGEX_VERSION = /^lxc version:\s+([\w\W]+)$/
# @param [Hash] options Options hash.
# @option options [Boolean] :use_sudo (false) Whether or not to prefix all
# commands with 'sudo'.
# @option options [Net::SSH,ZTK::SSH,nil] :use_ssh (nil) Whether or not to
# execute all commands remotely via an SSH connection.
def initialize(options={})
@ui = (options[:ui] || ZTK::UI.new)
@runner = (options[:runner] || LXC::Runner::Shell.new(:ui => @ui))
end
# LXC configuration class
#
# Gets the LXC configuration class object
#
# @return [LXC::Config] Returns the LXC configuration object.
def config
@config ||= LXC::Config.new(self, "/etc/lxc/lxc.conf")
end
# Initialize container object
#
# Initalizes an LXC::Container class for the supplied container name.
#
# @param [String] name The container name to initalize.
# @return [LXC::Container] Returns the container object.
def container(name)
LXC::Container.new(:lxc => self, :name => name)
end
# Current containers
#
# Initalizes an LXC::Container object for all containers and returns them in
# an Array.
#
# @return [Array<LXC::Container>]
def containers
container_names = self.ls
container_names.map do |container_name|
LXC::Container.new(:lxc => self, :name => container_name)
end
end
# List of containers
#
# Runs the "lxc-ls" command.
#
# @param [Array] args Additional command-line arguments.
# @return [Array<String>] A list of container names.
def ls(*args)
self.exec("lxc-ls", *args).split("\n").join(' ').split.uniq
end
# Check if a container exists
#
# Checks the container name list to see if the name supplied is an existing
# container.
#
# @param [String] name The name of the container to check.
# @return [Boolean] Returns true of the container exists, false otherwise.
def exists?(name)
self.ls(%(-1)).include?(name)
end
# Linux container processes
#
# Runs the "lxc-ps" command.
#
# @param [Array] args Additional command-line arguments.
# @return [Array<String>] Output text of the "lxc-ps" command.
def ps(*args)
self.exec("lxc-ps", *args).split("\n")
end
# Linux container version
#
# Runs the "lxc-version" command.
#
# @param [Array] args Additional command-line arguments.
# @return [String] The installed version of LXC. Returns nil if lxc-version
# is not found.
def version(*args)
result = self.exec("lxc-version", *args).scan(REGEX_VERSION).flatten.compact
result.first.strip
rescue
nil
end
# Linux container configuration check
#
# Runs the "lxc-checkconfig" command.
#
# @param [Array] args Additional command-line arguments.
# @return [Array<String>] Output text of the "lxc-checkconfig" command.
def checkconfig(*args)
ZTK::ANSI.uncolor(self.exec("lxc-checkconfig", *args)).split("\n")
end
# Linux containers installed?
#
# Checks the output of "lxc-checkconfig" to see if it returns a
# 'command not found' error.
#
# @return [Boolean] True if LXC is installed; false otherwise.
def installed?
if !!(self.checkconfig.join =~ /command not found/)
false
else
true
end
end
# Linux container command execution wrapper
#
# Runs the supplied LXC command. The first element in the "args" splat is the
# command to be execute, the rest of the elements are treated as command line
# arguments.
#
# If use_sudo is true then all commands will be prefix with "sudo".
# If use_ssh is non-nil then all commands will be execute via the assigned
# Net::SSH Session.
#
# @param [Array] args Additional command-line arguments.
# @return [Array<String>] Stripped output text of the executed command.
def exec(*args)
@runner.exec(*args)
end
# Provides a concise string representation of the class
# @return [String]
def inspect
tags = Array.new
tags << "version=#{self.version.inspect}"
tags << "runner=#{@runner.inspect}" if @runner
tags = tags.join(' ')
"#<LXC #{tags}>"
end
end