lxc 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,193 @@
1
+ class LXC
2
+ class ContainerError < Error; end
3
+
4
+ class Container
5
+
6
+ # An array containing the valid container states extracted from the LXC
7
+ # c-source code.
8
+ STATES = %w(stopped starting running stopping aborting freezing frozen thawed)
9
+
10
+ # @!method stopped?
11
+ # Returns true if the container is stopped, false otherwise.
12
+ # @return [Boolean]
13
+ #
14
+ # @!method starting?
15
+ # Returns true if the container is starting, false otherwise.
16
+ # @return [Boolean]
17
+ #
18
+ # @!method running?
19
+ # Returns true if the container is running, false otherwise.
20
+ # @return [Boolean]
21
+ #
22
+ # @!method stopping?
23
+ # Returns true if the container is stopping, false otherwise.
24
+ # @return [Boolean]
25
+ #
26
+ # @!method aborting?
27
+ # Returns true if the container is aborting, false otherwise.
28
+ # @return [Boolean]
29
+ #
30
+ # @!method freezing?
31
+ # Returns true if the container is freezing, false otherwise.
32
+ # @return [Boolean]
33
+ #
34
+ # @!method frozen?
35
+ # Returns true if the container is frozen, false otherwise.
36
+ # @return [Boolean]
37
+ #
38
+ # @!method thawed?
39
+ # Returns true if the container is thawed, false otherwise.
40
+ # @return [Boolean]
41
+ STATES.each do |state|
42
+ define_method "#{state.downcase}?" do
43
+ (self.state == state.downcase.to_sym)
44
+ end
45
+ end
46
+
47
+ # RegEx pattern for extracting the container state from the "lxc-info"
48
+ # command output.
49
+ REGEX_STATE = /^state:\s+([\w]+)$/
50
+
51
+ # RegEx pattern for extracting the container PID from the "lxc-info"
52
+ # command output.
53
+ REGEX_PID = /^pid:\s+([\d]+)$/
54
+
55
+ # Returns the container name
56
+ #
57
+ # @return [String] Container name
58
+ attr_reader :name
59
+
60
+ def initialize(lxc, name)
61
+ raise ContainerError, "You must supply a LXC object!" if lxc.nil?
62
+ raise ContainerError, "You must supply a container name!" if (name.nil? || name.empty?)
63
+
64
+ @lxc = lxc
65
+ @name = name
66
+ end
67
+
68
+ # Start the container
69
+ #
70
+ # Runs the "lxc-start" command with the "--daemon" flag.
71
+ #
72
+ # @param [Array] args Additional command-line arguments.
73
+ # @return [Symbol] The state of the container.
74
+ def start(*args)
75
+ self.exec("start", "--daemon", *args)
76
+ self.state
77
+ end
78
+
79
+ # Stop the container
80
+ #
81
+ # Runs the "lxc-stop" command.
82
+ #
83
+ # @param [Array] args Additional command-line arguments.
84
+ # @return [Symbol] The state of the container.
85
+ def stop(*args)
86
+ self.exec("stop", *args)
87
+ self.state
88
+ end
89
+
90
+ # Restart the container
91
+ def restart(options={})
92
+ self.stop
93
+ self.start
94
+ end
95
+ alias :reload :restart
96
+
97
+ # Freeze the container
98
+ #
99
+ # Runs the "lxc-freeze" command.
100
+ #
101
+ # @param [Array] args Additional command-line arguments.
102
+ # @return [Symbol] The state of the container.
103
+ def freeze(*args)
104
+ self.exec("freeze", *args)
105
+ self.state
106
+ end
107
+
108
+ # Unfreeze (thaw) the container
109
+ #
110
+ # Runs the "lxc-unfreeze" command.
111
+ #
112
+ # @param [Array] args Additional command-line arguments.
113
+ # @return [Symbol] The state of the container.
114
+ def unfreeze(*args)
115
+ self.exec("unfreeze", *args)
116
+ self.state
117
+ end
118
+
119
+ # Information on the container
120
+ #
121
+ # Runs the "lxc-info" command.
122
+ #
123
+ # @param [Array] args Additional command-line arguments.
124
+ # @return [Array] Lines of output from the executed command.
125
+ def info(*args)
126
+ self.exec("info", *args).split("\n").uniq.flatten
127
+ end
128
+
129
+ # State of the container
130
+ #
131
+ # Runs the "lxc-info" command with the "--state" flag.
132
+ #
133
+ # @param [Array] args Additional command-line arguments.
134
+ # @return [Symbol] Current state of the container.
135
+ def state(*args)
136
+ result = self.info("--state", *args).collect{ |str| str.scan(REGEX_STATE) }
137
+ result.flatten!.compact!
138
+
139
+ result.first.strip.downcase.to_sym
140
+ end
141
+
142
+ # PID of the container
143
+ #
144
+ # Runs the "lxc-info" command with the "--pid" flag.
145
+ #
146
+ # @param [Array] args Additional command-line arguments.
147
+ # @return [Integer] Current PID of the container.
148
+ def pid(*args)
149
+ result = self.info("--pid", *args).collect{ |str| str.scan(REGEX_PID) }
150
+ result.flatten!.compact!
151
+
152
+ result.first.strip.to_i
153
+ end
154
+
155
+ # Does the container exist?
156
+ #
157
+ # @return [Boolean] Returns true if the container exists, false otherwise.
158
+ def exists?
159
+ @lxc.exists?(self.name)
160
+ end
161
+
162
+ # Linux container command execution wrapper
163
+ #
164
+ # Executes the supplied command by injecting the container name into the
165
+ # argument list and then passes to the arguments to the top-level LXC class
166
+ # exec method.
167
+ #
168
+ # @param [Array] args Additional command-line arguments.
169
+ # @return [Array<String>] Stripped output text of the executed command.
170
+ #
171
+ # @see LXC#exec
172
+ def exec(*args)
173
+ arguments = Array.new
174
+ arguments << args.shift
175
+ arguments << "--name=#{self.name}"
176
+ arguments << args
177
+ arguments.flatten!.compact!
178
+
179
+ @lxc.exec(*arguments)
180
+ end
181
+
182
+ # Provides a concise string representation of the class
183
+ # @return [String]
184
+ def inspect
185
+ tags = Array.new
186
+ tags << "name=#{self.name.inspect}"
187
+ tags = tags.join(' ')
188
+
189
+ "#<LXC::Container #{tags}>"
190
+ end
191
+
192
+ end
193
+ end
data/lib/lxc/version.rb CHANGED
@@ -1,3 +1,3 @@
1
- module Lxc
2
- VERSION = "0.0.1" unless const_defined?(:VERSION)
1
+ class LXC
2
+ VERSION = "0.0.2" unless const_defined?(:VERSION)
3
3
  end
data/lxc.gemspec CHANGED
@@ -1,17 +1,30 @@
1
- # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/lxc/version', __FILE__)
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'lxc/version'
3
5
 
4
- Gem::Specification.new do |gem|
5
- gem.authors = ["Zachary Patten"]
6
- gem.email = ["zachary@jovelabs.com"]
7
- gem.description = %q{Gem for controlling local or remote Linux Containers (LXC)}
8
- gem.summary = %q{Gem for controlling local or remote Linux Containers (LXC)}
9
- gem.homepage = "https://github.com/zpatten/lxc"
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "lxc"
8
+ spec.version = LXC::VERSION
9
+ spec.authors = ["Zachary Patten"]
10
+ spec.email = ["zachary@jovelabs.com"]
11
+ spec.description = %q(An interface for controlling local or remote Linux Containers (LXC))
12
+ spec.summary = %q(An interface for controlling local or remote Linux Containers (LXC))
13
+ spec.homepage = "https://github.com/zpatten/lxc"
14
+ spec.license = "Apache 2.0"
10
15
 
11
- gem.files = `git ls-files`.split($\)
12
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
- gem.name = "lxc"
15
- gem.require_paths = ["lib"]
16
- gem.version = Lxc::VERSION
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency("ztk")
22
+
23
+ spec.add_development_dependency("bundler", "~> 1.3")
24
+ spec.add_development_dependency("pry")
25
+ spec.add_development_dependency("rake")
26
+ spec.add_development_dependency("redcarpet")
27
+ spec.add_development_dependency("rspec")
28
+ spec.add_development_dependency("simplecov")
29
+ spec.add_development_dependency("yard")
17
30
  end
@@ -0,0 +1,28 @@
1
+ Kernel config /proc/config.gz not found, looking in other places...
2
+ Found kernel config file /boot/config-3.2.0-23-generic
3
+ --- Namespaces ---
4
+ Namespaces: enabled
5
+ Utsname namespace: enabled
6
+ Ipc namespace: enabled
7
+ Pid namespace: enabled
8
+ User namespace: enabled
9
+ Network namespace: enabled
10
+ Multiple /dev/pts instances: enabled
11
+
12
+ --- Control groups ---
13
+ Cgroup: enabled
14
+ Cgroup clone_children flag: enabled
15
+ Cgroup device: enabled
16
+ Cgroup sched: enabled
17
+ Cgroup cpu account: enabled
18
+ Cgroup memory controller: enabled
19
+ Cgroup cpuset: enabled
20
+
21
+ --- Misc ---
22
+ Veth pair device: enabled
23
+ Macvlan: enabled
24
+ Vlan: enabled
25
+ File capabilities: enabled
26
+
27
+ Note : Before booting a new kernel, you can check its configuration
28
+ usage : CONFIG=/path/to/config /usr/bin/lxc-checkconfig
@@ -0,0 +1,2 @@
1
+ devop-test-1
2
+ devop-test-1
File without changes
@@ -0,0 +1,4 @@
1
+ CONTAINER PID TTY TIME CMD
2
+ 11848 pts/7 00:00:00 lxc-ps
3
+ 11849 pts/7 00:00:00 ps
4
+ 32105 pts/7 00:00:01 bash
@@ -0,0 +1 @@
1
+ lxc version: 0.7.5
@@ -0,0 +1,28 @@
1
+ Kernel config /proc/config.gz not found, looking in other places...
2
+ Found kernel config file /boot/config-2.6.32-358.2.1.el6.centos.plus.x86_64
3
+ --- Namespaces ---
4
+ Namespaces: enabled
5
+ Utsname namespace: enabled
6
+ Ipc namespace: enabled
7
+ Pid namespace: enabled
8
+ User namespace: enabled
9
+ Network namespace: enabled
10
+ Multiple /dev/pts instances: enabled
11
+
12
+ --- Control groups ---
13
+ Cgroup: enabled
14
+ Cgroup namespace: enabled
15
+ Cgroup device: enabled
16
+ Cgroup sched: enabled
17
+ Cgroup cpu account: enabled
18
+ Cgroup memory controller: enabled
19
+ Cgroup cpuset: enabled
20
+
21
+ --- Misc ---
22
+ Veth pair device: enabled
23
+ Macvlan: enabled
24
+ Vlan: enabled
25
+ File capabilities: enabled
26
+
27
+ Note : Before booting a new kernel, you can check its configuration
28
+ usage : CONFIG=/path/to/config /usr/bin/lxc-checkconfig
@@ -0,0 +1,2 @@
1
+ devop-test-1
2
+ devop-test-1
File without changes
@@ -0,0 +1,4 @@
1
+ CONTAINER PID TTY TIME CMD
2
+ 11848 pts/7 00:00:00 lxc-ps
3
+ 11849 pts/7 00:00:00 ps
4
+ 32105 pts/7 00:00:01 bash
@@ -0,0 +1 @@
1
+ lxc version: 0.8.0-rc2
data/spec/lxc_spec.rb ADDED
@@ -0,0 +1,193 @@
1
+ require "spec_helper"
2
+
3
+ describe LXC do
4
+
5
+ subject { LXC.new }
6
+
7
+ describe "class" do
8
+
9
+ it "should be an instance of LXC" do
10
+ subject.should be_an_instance_of LXC
11
+ end
12
+
13
+ describe "defaults" do
14
+
15
+ it "should have use_sudo set to false" do
16
+ subject.use_sudo.should == false
17
+ end
18
+
19
+ it "should have use_ssh set to nil" do
20
+ subject.use_ssh.should == nil
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
27
+ describe "methods" do
28
+
29
+ LXC_VERSIONS.each do |lxc_version|
30
+
31
+ context "LXC Target Version #{lxc_version}" do
32
+
33
+ describe "ls" do
34
+
35
+ context "with containers" do
36
+
37
+ it "should return an array of strings populated with container names" do
38
+ subject.stub(:exec) { lxc_fixture(lxc_version, "lxc-ls-w-containers.out") }
39
+
40
+ subject.ls.should be_kind_of(Array)
41
+ subject.ls.should_not be_empty
42
+ subject.ls.size.should eq(1)
43
+ end
44
+
45
+ end
46
+
47
+ context "without containers" do
48
+
49
+ it "should return an empty array" do
50
+ subject.stub(:exec) { lxc_fixture(lxc_version, "lxc-ls-wo-containers.out") }
51
+
52
+ subject.ls.should be_kind_of(Array)
53
+ subject.ls.should be_empty
54
+ subject.ls.size.should eq(0)
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+
61
+ describe "exists?" do
62
+
63
+ context "with containers" do
64
+
65
+ it "should return false if the container does not exist" do
66
+ subject.stub(:exec) { lxc_fixture(lxc_version, "lxc-ls-w-containers.out") }
67
+ subject.exists?("abc-123-test-container-name").should == false
68
+ end
69
+
70
+ it "should return true if the container does exist" do
71
+ subject.stub(:exec) { lxc_fixture(lxc_version, "lxc-ls-w-containers.out") }
72
+ subject.exists?("devop-test-1").should == true
73
+ end
74
+
75
+ end
76
+
77
+ context "without containers" do
78
+
79
+ it "should return false if the container does not exist" do
80
+ subject.stub(:exec) { lxc_fixture(lxc_version, "lxc-ls-wo-containers.out") }
81
+ subject.exists?("abc-123-test-container-name").should == false
82
+ end
83
+
84
+ it "should return false if the container does not exist" do
85
+ subject.stub(:exec) { lxc_fixture(lxc_version, "lxc-ls-wo-containers.out") }
86
+ subject.exists?("devop-test-1").should == false
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+
93
+ describe "ps" do
94
+ it "should return an array of strings representing the lxc process list" do
95
+ subject.stub(:exec) { lxc_fixture(lxc_version, "lxc-ps.out") }
96
+
97
+ subject.ps.should be_kind_of(Array)
98
+ subject.ps.should_not be_empty
99
+ end
100
+ end
101
+
102
+ describe "version" do
103
+ it "should return a string representation of the installed LXC version" do
104
+ subject.stub(:exec) { lxc_fixture(lxc_version, 'lxc-version.out') }
105
+
106
+ subject.version.should be_kind_of(String)
107
+ subject.version.should_not be_empty
108
+ subject.version.should == lxc_version
109
+ end
110
+ end
111
+
112
+ describe "checkconfig" do
113
+ it "should return an array of strings representing the LXC configuration" do
114
+ subject.stub(:exec) { lxc_fixture(lxc_version, 'lxc-checkconfig.out') }
115
+
116
+ subject.checkconfig.should be_kind_of(Array)
117
+ subject.checkconfig.should_not be_empty
118
+
119
+ subject.checkconfig.first.should be_kind_of(String)
120
+ subject.checkconfig.first.should_not be_empty
121
+ end
122
+ end
123
+
124
+ describe "container" do
125
+ it "should return a container object for the requested container" do
126
+ result = subject.container("devop-test-1")
127
+ result.should be_an_instance_of(::LXC::Container)
128
+ end
129
+ end
130
+
131
+ describe "containers" do
132
+
133
+ context "with containers" do
134
+ it "should return an array of container objects" do
135
+ subject.stub(:exec) { lxc_fixture(lxc_version, "lxc-ls-w-containers.out") }
136
+
137
+ subject.containers.should be_kind_of(Array)
138
+ subject.containers.size.should eq(1)
139
+ end
140
+ end
141
+
142
+ context "without containers" do
143
+ it "should return an empty array" do
144
+ subject.stub(:exec) { lxc_fixture(lxc_version, "lxc-ls-wo-containers.out") }
145
+
146
+ subject.containers.should be_kind_of(Array)
147
+ subject.containers.size.should eq(0)
148
+ end
149
+ end
150
+
151
+ end
152
+
153
+ describe "inspect" do
154
+ it "should return an information string about our class instance" do
155
+ subject.inspect.should be_kind_of(String)
156
+ subject.inspect.length.should be > 0
157
+ end
158
+ end
159
+
160
+ describe "exec" do
161
+
162
+ context "against local host" do
163
+ it "should exec the supplied LXC command" do
164
+ subject.stub(:exec) { lxc_fixture(lxc_version, "lxc-version.out") }
165
+
166
+ subject.exec("version").should be_kind_of(String)
167
+ end
168
+ end
169
+
170
+ context "against remote host" do
171
+ before(:each) do
172
+ @ssh_connection = ::ZTK::SSH.new(
173
+ :host_name => "127.0.0.1",
174
+ :user => ENV['USER'],
175
+ :keys => "#{ENV['HOME']}/.ssh/id_rsa"
176
+ ).ssh
177
+ end
178
+
179
+ it "should exec the supplied LXC command" do
180
+ subject.use_ssh = @ssh_connection
181
+ subject.exec("version").should be_kind_of(String)
182
+ end
183
+ end if !ENV['CI'] && !ENV['TRAVIS']
184
+
185
+ end
186
+
187
+ end # LXC Version Context
188
+
189
+ end # LXC_VERSIONS
190
+
191
+ end
192
+
193
+ end