Class: LXC::Container

Inherits:
Object
  • Object
show all
Defined in:
lib/lxc/container.rb

Overview

Main Container Class

Author:

Constant Summary

STATES =

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

%w(stopped starting running stopping aborting freezing frozen thawed not_created).map(&:to_sym)
REGEX_STATE =

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

/^state:\s+([\w]+)$/
REGEX_PID =

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

/^pid:\s+([-\d]+)$/

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Container) initialize(options = {})

Returns a new instance of Container

Parameters:

  • options (Hash) (defaults to: {})

    Options hash.

Options Hash (options):

  • :lxc (LXC)

    Our parent LXC class instance.

  • :name (String)

    The name of the container.

Raises:



75
76
77
78
79
80
81
# 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

Instance Attribute Details

- (LXC) lxc (readonly)

Returns the parent LXC class instance

Returns:

  • (LXC)

    Parent LXC class instance.



70
71
72
# File 'lib/lxc/container.rb', line 70

def lxc
  @lxc
end

- (String) name (readonly)

Returns the container name

Returns:

  • (String)

    Container name



65
66
67
# File 'lib/lxc/container.rb', line 65

def name
  @name
end

Instance Method Details

- (Boolean) aborting?

Returns true if the container is aborting, false otherwise.

Returns:

  • (Boolean)


48
49
50
51
52
# File 'lib/lxc/container.rb', line 48

STATES.each do |state|
  define_method "#{state}?" do
    (self.state == state)
  end
end

- (Object) attach(*args)

Run an application inside a container

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

See Also:

  • lxc-attach


243
244
245
# File 'lib/lxc/container.rb', line 243

def attach(*args)
  self.exec("lxc-attach", *args)
end

- (String) bootstrap(content)

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.

Parameters:

  • content (String)

    The content to render in the container and execute. This is generally a bash script of some sort for example.

Returns:

  • (String)

    The output of lxc-attach.

See Also:

  • lxc-attach


257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# 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

- (Array<String>) clone(*args)

Clone the container

Runs the "lxc-clone" command.

Returns:

  • (Array<String>)

    Lines of output from the executed command.

See Also:

  • lxc-clone


140
141
142
# File 'lib/lxc/container.rb', line 140

def clone(*args)
  self.lxc.exec("lxc-clone", *args)
end

- (LXC::Config) config

LXC configuration class

Gets the LXC configuration class object

Returns:

  • (LXC::Config)

    Returns the LXC configuration object.



88
89
90
# File 'lib/lxc/container.rb', line 88

def config
  @config ||= LXC::Config.new(@lxc, "/etc/lxc/#{@name}")
end

- (Object) console

Launch a console for the container

See Also:

  • lxc-console


282
283
284
# File 'lib/lxc/container.rb', line 282

def console
  self.exec("lxc-console")
end

- (String) container_root

Directory for the container

Returns:

  • (String)

    The directory for the container.



378
379
380
# File 'lib/lxc/container.rb', line 378

def container_root
  File.join('/', 'var', 'lib', 'lxc', self.name)
end

- (Object) cpu_usage

CPU Time in Seconds



323
324
325
326
# 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

- (Array<String>) create(*args)

Create the container

Runs the "lxc-create" command.

Parameters:

  • args (Array)

    Additional command-line arguments.

Returns:

  • (Array<String>)

    Lines of output from the executed command.



98
99
100
# File 'lib/lxc/container.rb', line 98

def create(*args)
  self.exec("lxc-create", *args)
end

- (Array<String>) destroy(*args)

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.

Parameters:

  • args (Array)

    Additional command-line arguments.

Returns:

  • (Array<String>)

    Lines of output from the executed command.



110
111
112
# File 'lib/lxc/container.rb', line 110

def destroy(*args)
  self.exec("lxc-destroy", *args)
end

- (Object) disk_usage(ephemeral = false)

Current Disk Usage



329
330
331
332
# 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

- (Array<String>) exec(*args)

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.

Parameters:

  • args (Array)

    Additional command-line arguments.

Returns:

  • (Array<String>)

    Stripped output text of the executed command.

See Also:



344
345
346
347
348
349
350
351
352
# 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

- (Object) execute(*args)

Run an application inside a container

Launches the container, executing the supplied application inside it.

See Also:

  • lxc-execute


233
234
235
# File 'lib/lxc/container.rb', line 233

def execute(*args)
  self.exec("lxc-execute", "-f", self.config.filename, "--", *args)
end

- (Boolean) exists?

Does the container exist?

Returns:

  • (Boolean)

    Returns true if the container exists, false otherwise.



224
225
226
# File 'lib/lxc/container.rb', line 224

def exists?
  @lxc.exists?(self.name)
end

- (Array<String>) freeze(*args)

Freeze the container

Runs the "lxc-freeze" command.

Parameters:

  • args (Array)

    Additional command-line arguments.

Returns:

  • (Array<String>)

    Lines of output from the executed command.



167
168
169
# File 'lib/lxc/container.rb', line 167

def freeze(*args)
  self.exec("lxc-freeze", *args)
end

- (Boolean) freezing?

Returns true if the container is freezing, false otherwise.

Returns:

  • (Boolean)


48
49
50
51
52
# File 'lib/lxc/container.rb', line 48

STATES.each do |state|
  define_method "#{state}?" do
    (self.state == state)
  end
end

- (Boolean) frozen?

Returns true if the container is frozen, false otherwise.

Returns:

  • (Boolean)


48
49
50
51
52
# File 'lib/lxc/container.rb', line 48

STATES.each do |state|
  define_method "#{state}?" do
    (self.state == state)
  end
end

- (String) fs_root(ephemeral = false)

Root directory for the containers file system

Parameters:

  • ephemeral (Boolean) (defaults to: false)

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

Returns:

  • (String)

    The root directory for the container.



360
361
362
363
364
365
366
# 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

- (String) fs_tab

Static information about the containers filesystems

Returns:

  • (String)

    The path to the containers fstab.



371
372
373
# File 'lib/lxc/container.rb', line 371

def fs_tab
  File.join(self.container_root, 'fstab')
end

- (Array<String>) info(*args)

Information on the container

Runs the "lxc-info" command.

Parameters:

  • args (Array)

    Additional command-line arguments.

Returns:

  • (Array<String>)

    Lines of output from the executed command.



187
188
189
# File 'lib/lxc/container.rb', line 187

def info(*args)
  self.exec("lxc-info", *args).split("\n").uniq.flatten
end

- (String) inspect

Provides a concise string representation of the class

Returns:

  • (String)


384
385
386
387
388
389
390
# File 'lib/lxc/container.rb', line 384

def inspect
  tags = Array.new
  tags << "name=#{self.name.inspect}"
  tags = tags.join(' ')

  "#<LXC::Container #{tags}>"
end

- (Object) memory_usage

Current Memory Usage



317
318
319
320
# 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

- (Integer) pid(*args)

PID of the container

Runs the "lxc-info" command with the "--pid" flag.

Parameters:

  • args (Array)

    Additional command-line arguments.

Returns:

  • (Integer)

    Current PID of the container.



214
215
216
217
218
219
# 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

- (Object) restart(options = {}) Also known as: reload

Restart the container



155
156
157
158
# File 'lib/lxc/container.rb', line 155

def restart(options={})
  self.stop
  self.start
end

- (Boolean) running?

Returns true if the container is running, false otherwise.

Returns:

  • (Boolean)


48
49
50
51
52
# File 'lib/lxc/container.rb', line 48

STATES.each do |state|
  define_method "#{state}?" do
    (self.state == state)
  end
end

- (Array<String>) start(*args)

Start the container

Runs the "lxc-start" command.

Parameters:

  • args (Array)

    Additional command-line arguments.

Returns:

  • (Array<String>)

    Lines of output from the executed command.



120
121
122
# File 'lib/lxc/container.rb', line 120

def start(*args)
  self.exec("lxc-start", *args)
end

- (Array<String>) start_ephemeral(*args)

Start an ephemeral copy of the container

Runs the "lxc-start-ephemeral" command.

Returns:

  • (Array<String>)

    Lines of output from the executed command.

See Also:

  • lxc-start-ephemeral


130
131
132
# File 'lib/lxc/container.rb', line 130

def start_ephemeral(*args)
  self.lxc.exec("lxc-start-ephemeral", *args)
end

- (Boolean) starting?

Returns true if the container is starting, false otherwise.

Returns:

  • (Boolean)


48
49
50
51
52
# File 'lib/lxc/container.rb', line 48

STATES.each do |state|
  define_method "#{state}?" do
    (self.state == state)
  end
end

- (Symbol) state(*args)

State of the container

Runs the "lxc-info" command with the "--state" flag.

Parameters:

  • args (Array)

    Additional command-line arguments.

Returns:

  • (Symbol)

    Current state of the container.



197
198
199
200
201
202
203
204
205
206
# 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

- (Array<String>) stop(*args)

Stop the container

Runs the "lxc-stop" command.

Parameters:

  • args (Array)

    Additional command-line arguments.

Returns:

  • (Array<String>)

    Lines of output from the executed command.



150
151
152
# File 'lib/lxc/container.rb', line 150

def stop(*args)
  self.exec("lxc-stop", *args)
end

- (Boolean) stopped?

Returns true if the container is stopped, false otherwise.

Returns:

  • (Boolean)


48
49
50
51
52
# File 'lib/lxc/container.rb', line 48

STATES.each do |state|
  define_method "#{state}?" do
    (self.state == state)
  end
end

- (Boolean) stopping?

Returns true if the container is stopping, false otherwise.

Returns:

  • (Boolean)


48
49
50
51
52
# File 'lib/lxc/container.rb', line 48

STATES.each do |state|
  define_method "#{state}?" do
    (self.state == state)
  end
end

- (Boolean) thawed?

Returns true if the container is thawed, false otherwise.

Returns:

  • (Boolean)


48
49
50
51
52
# File 'lib/lxc/container.rb', line 48

STATES.each do |state|
  define_method "#{state}?" do
    (self.state == state)
  end
end

- (Array<String>) unfreeze(*args)

Unfreeze (thaw) the container

Runs the "lxc-unfreeze" command.

Parameters:

  • args (Array)

    Additional command-line arguments.

Returns:

  • (Array<String>)

    Lines of output from the executed command.



177
178
179
# File 'lib/lxc/container.rb', line 177

def unfreeze(*args)
  self.exec("lxc-unfreeze", *args)
end

- (Boolean) wait(states, timeout = 60)

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.

Parameters:

  • states (Symbol, Array)

    A single symbol or an array of symbols representing container states for which we will wait for the container to change state to.

  • timeout (Integer) (defaults to: 60)

    How long in seconds we will wait before the operation times out.

Returns:

  • (Boolean)

    Returns true of the state change happened, false otherwise.



300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
# 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