elecksee 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +2 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +18 -0
- data/README.md +48 -0
- data/bin/lxc-awesome-ephemeral +5 -0
- data/elecksee.gemspec +16 -0
- data/lib/elecksee/awesome.rb +14 -0
- data/lib/elecksee/lxc.rb +7 -0
- data/lib/elecksee/vendor/lxc/CHANGELOG.md +37 -0
- data/lib/elecksee/vendor/lxc/Gemfile +4 -0
- data/lib/elecksee/vendor/lxc/Gemfile.lock +41 -0
- data/lib/elecksee/vendor/lxc/README.md +112 -0
- data/lib/elecksee/vendor/lxc/attributes/default.rb +28 -0
- data/lib/elecksee/vendor/lxc/files/default/knife_lxc +228 -0
- data/lib/elecksee/vendor/lxc/files/default/lxc-awesome-ephemeral +495 -0
- data/lib/elecksee/vendor/lxc/libraries/lxc.rb +354 -0
- data/lib/elecksee/vendor/lxc/libraries/lxc_expanded_resources.rb +40 -0
- data/lib/elecksee/vendor/lxc/libraries/lxc_file_config.rb +84 -0
- data/lib/elecksee/vendor/lxc/libraries/monkey.rb +51 -0
- data/lib/elecksee/vendor/lxc/metadata.rb +12 -0
- data/lib/elecksee/vendor/lxc/providers/config.rb +75 -0
- data/lib/elecksee/vendor/lxc/providers/container.rb +318 -0
- data/lib/elecksee/vendor/lxc/providers/default.rb +57 -0
- data/lib/elecksee/vendor/lxc/providers/ephemeral.rb +40 -0
- data/lib/elecksee/vendor/lxc/providers/fstab.rb +30 -0
- data/lib/elecksee/vendor/lxc/providers/interface.rb +45 -0
- data/lib/elecksee/vendor/lxc/providers/service.rb +53 -0
- data/lib/elecksee/vendor/lxc/recipes/containers.rb +13 -0
- data/lib/elecksee/vendor/lxc/recipes/default.rb +58 -0
- data/lib/elecksee/vendor/lxc/recipes/install_dependencies.rb +15 -0
- data/lib/elecksee/vendor/lxc/recipes/knife.rb +37 -0
- data/lib/elecksee/vendor/lxc/resources/config.rb +19 -0
- data/lib/elecksee/vendor/lxc/resources/container.rb +54 -0
- data/lib/elecksee/vendor/lxc/resources/default.rb +12 -0
- data/lib/elecksee/vendor/lxc/resources/ephemeral.rb +13 -0
- data/lib/elecksee/vendor/lxc/resources/fstab.rb +12 -0
- data/lib/elecksee/vendor/lxc/resources/interface.rb +13 -0
- data/lib/elecksee/vendor/lxc/resources/service.rb +5 -0
- data/lib/elecksee/vendor/lxc/templates/default/client.rb.erb +13 -0
- data/lib/elecksee/vendor/lxc/templates/default/default-lxc.erb +3 -0
- data/lib/elecksee/vendor/lxc/templates/default/file_content.erb +2 -0
- data/lib/elecksee/vendor/lxc/templates/default/fstab.erb +5 -0
- data/lib/elecksee/vendor/lxc/templates/default/interface.erb +27 -0
- data/lib/elecksee/version.rb +6 -0
- data/lib/elecksee.rb +1 -0
- metadata +123 -0
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Elecksee
|
2
|
+
|
3
|
+
This is a simple library for interacting with LXC. It relies on
|
4
|
+
LXC tools being installed on the system to properly function.
|
5
|
+
It is extracted from the Chef LXC cookbook, so poke around there
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
|
11
|
+
require 'elecksee/lxc'
|
12
|
+
|
13
|
+
lxc = Lxc.new('my-container')
|
14
|
+
p lxc.info
|
15
|
+
```
|
16
|
+
|
17
|
+
## Awesome
|
18
|
+
|
19
|
+
Awesome ephemerals lets you create ephemeral nodes with different
|
20
|
+
overlays for the rootfs. Since tmpfs will place a size restriction
|
21
|
+
on ephemerals based on current memory available, this provides a
|
22
|
+
simple workaround. Currently supported is a raw temporary directory
|
23
|
+
on the host, or a VBD that defaults to 2GB.
|
24
|
+
|
25
|
+
### Using temporary directory
|
26
|
+
|
27
|
+
```
|
28
|
+
$ lxc-awesome-ephemeral -o ubuntu -d -z /tmp/lxc-roots
|
29
|
+
```
|
30
|
+
|
31
|
+
### Using VBD
|
32
|
+
|
33
|
+
```
|
34
|
+
$ lxc-awesome-ephemeral -o ubuntu -d -D 2000
|
35
|
+
```
|
36
|
+
|
37
|
+
This will create a 2GB virtual block device for the container
|
38
|
+
to use for the overlay.
|
39
|
+
|
40
|
+
Note
|
41
|
+
----
|
42
|
+
|
43
|
+
Overlays are not persistent (thus ephemeral) and will be automatically
|
44
|
+
cleaned up when the container has reached a stop state.
|
45
|
+
|
46
|
+
# Info
|
47
|
+
|
48
|
+
* Repository: https://github.com/chrisroberts/elecksee.git
|
data/elecksee.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__)) + '/lib/'
|
2
|
+
require 'elecksee/version'
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'elecksee'
|
5
|
+
s.version = Elecksee::VERSION.version
|
6
|
+
s.summary = 'LXC helpers'
|
7
|
+
s.author = 'Chris Roberts'
|
8
|
+
s.email = 'chrisroberts.code@gmail.com'
|
9
|
+
s.homepage = 'http://github.com/chrisroberts/elecksee'
|
10
|
+
s.description = 'LXC helpers'
|
11
|
+
s.require_path = 'lib'
|
12
|
+
s.executables = %w(lxc-awesome-ephemeral)
|
13
|
+
s.add_dependency 'mixlib-shellout'
|
14
|
+
s.add_dependency 'net-ssh'
|
15
|
+
s.files = Dir['**/*']
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Elecksee
|
2
|
+
class Awesome
|
3
|
+
class << self
|
4
|
+
def run!
|
5
|
+
path = File.expand_path(
|
6
|
+
File.join(
|
7
|
+
File.dirname(__FILE__), 'vendor/lxc/files/default/lxc-awesome-ephemeral'
|
8
|
+
)
|
9
|
+
)
|
10
|
+
exec("/bin/bash #{path} #{ARGV.join(' ')}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/elecksee/lxc.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
## v1.0.0
|
2
|
+
* Extract container actions out to new LWRP `lxc`
|
3
|
+
* Update `container` to use `lxc` resource for container actions
|
4
|
+
* Update `container` to allow nested subresources for `interface` and `fstab_mount`
|
5
|
+
* Fix `interface` LWRP to allow IPv6 based values
|
6
|
+
* Remove static_ip config set as it was introducing bogus route
|
7
|
+
* Provide assumed environment when not available (like when running via runit)
|
8
|
+
* Make chef enabled containers properly idempotent
|
9
|
+
* Clean up the `container` provider implementation to be more resource based
|
10
|
+
* Add `ephemeral` LWRP
|
11
|
+
* Add custom ephemeral script to allow host directory overlay or virtual block device
|
12
|
+
* Patches execute resource to provide streaming output
|
13
|
+
* Updates Lxc library to be more reusable
|
14
|
+
* Add proc based network detection for more robust address discovery
|
15
|
+
* Shell out directly to ssh for container commands instead of using knife ssh
|
16
|
+
|
17
|
+
## v0.1.0
|
18
|
+
* Abstracted out packages for cross-platform support later.
|
19
|
+
* Added the 'containers' recipe to create containers for the members of the node['lxc']['containers'] hash
|
20
|
+
* Add support for use of the apt::cacher-client settings if a proxy is in use.
|
21
|
+
* chef_enabled defaults to false on lxc_containers
|
22
|
+
* Better idempotency checks when building new containers
|
23
|
+
* Refactoring of lxc_service
|
24
|
+
* Container based commands run via knife::ssh providing proper logging feedback
|
25
|
+
* New networking related attributes added to lxc_container for easy basic network setups
|
26
|
+
|
27
|
+
## v0.0.3
|
28
|
+
* Remove resource for deprecated template
|
29
|
+
|
30
|
+
## v0.0.2
|
31
|
+
* Cleanup current config and container LWRPs
|
32
|
+
* Add new LWRPs (fstab and interface)
|
33
|
+
* Add better configuration build to prevent false updates
|
34
|
+
* Thanks to Sean Porter (https://github.com/portertech) for help debugging LWRP updates
|
35
|
+
|
36
|
+
## v0.0.1
|
37
|
+
* Initial release
|
@@ -0,0 +1,41 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git://github.com/opscode/test-kitchen.git
|
3
|
+
revision: ab1b878561e896c0619a780d168e71addff2ad91
|
4
|
+
branch: 1.0
|
5
|
+
specs:
|
6
|
+
test-kitchen (1.0.0.dev)
|
7
|
+
celluloid
|
8
|
+
mixlib-shellout
|
9
|
+
net-scp
|
10
|
+
net-ssh
|
11
|
+
pry
|
12
|
+
safe_yaml
|
13
|
+
thor
|
14
|
+
|
15
|
+
GEM
|
16
|
+
remote: https://rubygems.org/
|
17
|
+
specs:
|
18
|
+
celluloid (0.12.4)
|
19
|
+
facter (>= 1.6.12)
|
20
|
+
timers (>= 1.0.0)
|
21
|
+
coderay (1.0.9)
|
22
|
+
facter (1.6.17)
|
23
|
+
method_source (0.8.1)
|
24
|
+
mixlib-shellout (1.1.0)
|
25
|
+
net-scp (1.1.0)
|
26
|
+
net-ssh (>= 2.6.5)
|
27
|
+
net-ssh (2.6.6)
|
28
|
+
pry (0.9.12)
|
29
|
+
coderay (~> 1.0.5)
|
30
|
+
method_source (~> 0.8)
|
31
|
+
slop (~> 3.4)
|
32
|
+
safe_yaml (0.8.5)
|
33
|
+
slop (3.4.4)
|
34
|
+
thor (0.17.0)
|
35
|
+
timers (1.1.0)
|
36
|
+
|
37
|
+
PLATFORMS
|
38
|
+
ruby
|
39
|
+
|
40
|
+
DEPENDENCIES
|
41
|
+
test-kitchen!
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# LXC
|
2
|
+
|
3
|
+
Manage linux containers with Chef.
|
4
|
+
|
5
|
+
## Recipes
|
6
|
+
|
7
|
+
### default
|
8
|
+
|
9
|
+
Installs the packages and configuration files needed for lxc on the server. If
|
10
|
+
the node uses apt-cacher-ng as a client, the server will be reused when building
|
11
|
+
containers.
|
12
|
+
|
13
|
+
### install_dependencies
|
14
|
+
|
15
|
+
Installs the packages needed to support lxc's containers.
|
16
|
+
|
17
|
+
### containers
|
18
|
+
|
19
|
+
This recipe creates all of the containers defined in the `['lxc']['containers']`
|
20
|
+
hash. Here is an example of an `example` container:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
node['lxc']['containers']['example'] = {
|
24
|
+
'template' => 'ubuntu',
|
25
|
+
'initialize_commands' => ['apt-get update']
|
26
|
+
}
|
27
|
+
```
|
28
|
+
|
29
|
+
### knife
|
30
|
+
|
31
|
+
Install and manage containers via the knife-remotelxc plugin.
|
32
|
+
|
33
|
+
## LWRPs
|
34
|
+
|
35
|
+
### lxc
|
36
|
+
|
37
|
+
Allows for creation, deletion, and cloning of containers
|
38
|
+
|
39
|
+
### lxc_config
|
40
|
+
|
41
|
+
Allows configuration of the LXC configuration file
|
42
|
+
|
43
|
+
### lxc_fstab
|
44
|
+
|
45
|
+
Allows defining mounts to be used within the container
|
46
|
+
|
47
|
+
### lxc_interface
|
48
|
+
|
49
|
+
Allows configurations of network interfaces within a container
|
50
|
+
|
51
|
+
### lxc_ephemeral
|
52
|
+
|
53
|
+
Run a command within an ephemeral container
|
54
|
+
|
55
|
+
### lxc_container
|
56
|
+
|
57
|
+
Creates a container using the `lxc` LWRP and configures the container
|
58
|
+
as requested. This resource also allows nesting `lxc_fstab` and
|
59
|
+
`lxc_interface` within the container resource.
|
60
|
+
|
61
|
+
## Example
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
include_recipe 'lxc'
|
65
|
+
|
66
|
+
lxc_container 'my_container' do
|
67
|
+
action :create
|
68
|
+
validation_client 'my-validator'
|
69
|
+
server_uri 'https://api.opscode.com/organizations/myorg'
|
70
|
+
validator_pem content_from_encrypted_dbag
|
71
|
+
run_list ['role[base]']
|
72
|
+
chef_enabled true
|
73
|
+
fstab_mount "Persist" do
|
74
|
+
file_system '/opt/file_store'
|
75
|
+
mount_point '/opt/file_store'
|
76
|
+
type 'none'
|
77
|
+
options 'bind,rw'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
lxc_container 'my_container_clone' do
|
82
|
+
action :create
|
83
|
+
clone 'my_container'
|
84
|
+
chef_enabled true
|
85
|
+
end
|
86
|
+
|
87
|
+
lxc_service 'my_container_clone' do
|
88
|
+
action :start
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
Containers do not have to be Chef enabled but it does make them
|
93
|
+
extremely easy to configure. If you want the Omnibus installer
|
94
|
+
cached, you can set the attribute
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
node['omnibus_updater']['cache_omnibus_installer'] = true
|
98
|
+
```
|
99
|
+
|
100
|
+
in a role or environment (default is false). The `lxc_container`
|
101
|
+
resource also provides `initialize_commands` which an array of
|
102
|
+
commands can be provided that will be run after the container is
|
103
|
+
created.
|
104
|
+
|
105
|
+
### Repository:
|
106
|
+
|
107
|
+
* https://github.com/hw-cookbooks/lxc
|
108
|
+
|
109
|
+
### Contributors
|
110
|
+
|
111
|
+
* Sean Porter (https://github.com/portertech)
|
112
|
+
* Matt Ray (https://github.com/mattray)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
default[:lxc][:start_ipaddress] = nil
|
2
|
+
default[:lxc][:validator_pem] = nil
|
3
|
+
default[:lxc][:auto_start] = true
|
4
|
+
default[:lxc][:bridge] = 'lxcbr0'
|
5
|
+
default[:lxc][:use_bridge] = true
|
6
|
+
default[:lxc][:addr] = '10.0.3.1'
|
7
|
+
default[:lxc][:netmask] = '255.255.255.0'
|
8
|
+
default[:lxc][:network] = '10.0.3.0/24'
|
9
|
+
default[:lxc][:dhcp_range] = '10.0.3.2,10.0.3.254'
|
10
|
+
default[:lxc][:dhcp_max] = '253'
|
11
|
+
default[:lxc][:shutdown_timeout] = 120
|
12
|
+
default[:lxc][:allowed_types] = %w(debian ubuntu fedora)
|
13
|
+
default[:lxc][:container_directory] = '/var/lib/lxc'
|
14
|
+
default[:lxc][:dnsmasq_lease_file] = '/var/lib/misc/dnsmasq.leases'
|
15
|
+
|
16
|
+
default[:lxc][:knife] = {}
|
17
|
+
default[:lxc][:knife][:static_range] = ''
|
18
|
+
default[:lxc][:knife][:static_ips] = []
|
19
|
+
|
20
|
+
default[:lxc][:user_pass][:debian] = {:username => 'root', :password => 'root'}
|
21
|
+
default[:lxc][:user_pass][:ubuntu] = {:username => 'ubuntu', :password => 'ubuntu'}
|
22
|
+
default[:lxc][:user_pass][:fedora] = {:username => 'root', :password => 'root'}
|
23
|
+
|
24
|
+
default[:lxc][:packages] = %w(lxc)
|
25
|
+
default[:lxc][:mirror] = 'http://archive.ubuntu.com/ubuntu'
|
26
|
+
default[:lxc][:containers] = {}
|
27
|
+
|
28
|
+
default[:lxc][:awesome_ephemerals] = true
|
@@ -0,0 +1,228 @@
|
|
1
|
+
#!/opt/chef/embedded/bin/ruby
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'getoptlong'
|
5
|
+
|
6
|
+
LXC_HOME = '/var/lib/lxc'
|
7
|
+
|
8
|
+
opts = GetoptLong.new(
|
9
|
+
['--help', '-h', GetoptLong::NO_ARGUMENT],
|
10
|
+
['--version', '-v', GetoptLong::NO_ARGUMENT],
|
11
|
+
['--template', '-t', GetoptLong::REQUIRED_ARGUMENT]
|
12
|
+
)
|
13
|
+
|
14
|
+
# Default
|
15
|
+
template = 'ubuntu'
|
16
|
+
|
17
|
+
opts.each do |opt, arg|
|
18
|
+
case opt
|
19
|
+
when '--help'
|
20
|
+
show_usage
|
21
|
+
exit 0
|
22
|
+
when '--version'
|
23
|
+
show_version
|
24
|
+
exit 0
|
25
|
+
when '--template'
|
26
|
+
template = arg
|
27
|
+
raise 'Unsupported template provided' unless %w(debian fedora ubuntu).include?(template)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def conf
|
32
|
+
@c ||= JSON.load(File.read('/etc/knife-lxc/config.json'))
|
33
|
+
end
|
34
|
+
|
35
|
+
def lxc_exists?(lxc_name)
|
36
|
+
current_names = Dir.glob(File.join(LXC_HOME, '*')).map{|c| File.basename(c)}
|
37
|
+
current_names.include?(lxc_name)
|
38
|
+
end
|
39
|
+
|
40
|
+
def ensure_name_availability!(name)
|
41
|
+
raise 'Name already in use' if lxc_exists?(name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def available_ips
|
45
|
+
# TODO: Add range calculation
|
46
|
+
range = conf['address']['range']
|
47
|
+
if(range.to_s.empty?)
|
48
|
+
range = (range.split('-').first.split('.').last..range.split('-').last).map{|oct|
|
49
|
+
"#{range.split('-').first.split('.').slice(0,3).join('.')}.#{oct}"
|
50
|
+
}
|
51
|
+
else
|
52
|
+
range = []
|
53
|
+
end
|
54
|
+
(conf['addresses']['static'] + range).compact
|
55
|
+
end
|
56
|
+
|
57
|
+
def used_ips
|
58
|
+
Dir.glob(File.join(LXC_HOME, '*')).map{ |ctn|
|
59
|
+
File.readlines(File.join(ctn, 'rootfs', 'etc', 'network', 'interfaces')).detect{ |line|
|
60
|
+
line.include?('address')
|
61
|
+
}.to_s.split(' ').last.to_s.strip
|
62
|
+
}.reject{ |addr|
|
63
|
+
addr.empty?
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
def update_container_ip(name)
|
68
|
+
new_ip = (available_ips - used_ips).pop
|
69
|
+
raise 'no ips available' unless new_ip
|
70
|
+
update_network_interfaces(name, new_ip)
|
71
|
+
new_ip
|
72
|
+
end
|
73
|
+
|
74
|
+
def update_network_interfaces(name, address)
|
75
|
+
default_nm = '255.255.255.0'
|
76
|
+
(parts = address.split('.')).last.replace('1')
|
77
|
+
default_gw = parts.join('.')
|
78
|
+
File.open(File.join(LXC_HOME, name, 'rootfs', 'etc', 'network', 'interfaces'), 'w') do |file|
|
79
|
+
file.puts "auto lo eth0"
|
80
|
+
file.puts "iface lo inet loopback"
|
81
|
+
file.puts "iface eth0 inet static"
|
82
|
+
file.puts " address #{address}"
|
83
|
+
file.puts " gateway #{conf['gateway'] || default_gw}"
|
84
|
+
file.puts " netmask #{conf['netmask'] || default_nm}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def sudoable_ubuntu(name)
|
89
|
+
path = File.join(LXC_HOME, name, 'rootfs', 'etc', 'sudoers')
|
90
|
+
content = File.readlines(path).map do |line|
|
91
|
+
if(line.start_with?('%sudo'))
|
92
|
+
'%sudo ALL=(ALL) NOPASSWD:ALL'
|
93
|
+
else
|
94
|
+
line
|
95
|
+
end
|
96
|
+
end
|
97
|
+
File.open(path, 'w') do |file|
|
98
|
+
file.write(content.join("\n"))
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def clone_container(name, template)
|
103
|
+
%x{lxc-clone -o #{template}_base -n #{name}}
|
104
|
+
end
|
105
|
+
|
106
|
+
def start_container(name)
|
107
|
+
%x{lxc-start -n #{name} -d}
|
108
|
+
%x{lxc-wait -n #{name} -s RUNNING}
|
109
|
+
end
|
110
|
+
|
111
|
+
def stop_container(name)
|
112
|
+
%x{lxc-shutdown -n #{name} -d}
|
113
|
+
%x{lxc-wait -n #{name} -s STOPPED}
|
114
|
+
end
|
115
|
+
|
116
|
+
def create_lxc(lxc_name, template)
|
117
|
+
ensure_name_availability!(lxc_name)
|
118
|
+
clone_container(lxc_name, template)
|
119
|
+
address = update_container_ip(lxc_name)
|
120
|
+
# TODO: Update debian and fedora to use sudo user and remove root login
|
121
|
+
if(lxc_name == 'ubuntu')
|
122
|
+
sudoable_ubuntu(lxc_name)
|
123
|
+
end
|
124
|
+
start_container(lxc_name)
|
125
|
+
puts "LXC Node #{lxc_name} available at: #{address}"
|
126
|
+
end
|
127
|
+
|
128
|
+
def lxc_address(name)
|
129
|
+
if(File.exists?(int = File.join(LXC_HOME, name, 'rootfs', 'etc', 'network', 'interfaces')))
|
130
|
+
addr = File.readlines(int).detect{|l|l.include?('address')}.to_s.split(' ').last.to_s.strip
|
131
|
+
addr.empty? ? 'dynamic' : addr
|
132
|
+
else
|
133
|
+
'dynamic'
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def lxc_type(name)
|
138
|
+
base = File.join(LXC_HOME, name, 'rootfs', 'etc')
|
139
|
+
if(File.exists?(lsb = File.join(base, 'lsb-release')))
|
140
|
+
File.readlines(lsb).last.split('=').last.strip.gsub('"', '')
|
141
|
+
elsif(File.exists?(sys_rel = File.join(base, 'system-release')))
|
142
|
+
File.readlines(sys_rel).first.strip
|
143
|
+
elsif(File.exists?(deb_ver = File.join(base, 'debian_version')))
|
144
|
+
"Debain #{File.read(deb_ver).strip}"
|
145
|
+
else
|
146
|
+
'UNKNOWN'
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def list_lxcs
|
151
|
+
info = Hash[
|
152
|
+
*Dir.glob(File.join(LXC_HOME, '*')).map{|dir|
|
153
|
+
key = File.basename(dir)
|
154
|
+
[key, {:address => lxc_address(key), :type => lxc_type(key)}]
|
155
|
+
}.sort{|a,b|
|
156
|
+
a.first <=> b.first
|
157
|
+
}.flatten
|
158
|
+
]
|
159
|
+
info.each do |name, info|
|
160
|
+
puts "#{name}"
|
161
|
+
puts " Type: #{info[:type]}"
|
162
|
+
puts " Address: #{info[:address]}"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def info_lxc(lxc_name)
|
167
|
+
puts "#{lxc_name}"
|
168
|
+
puts " Type: #{lxc_type(lxc_name)}"
|
169
|
+
puts " Address: #{lxc_address(lxc_name)}"
|
170
|
+
end
|
171
|
+
|
172
|
+
def delete_lxc(lxc_name)
|
173
|
+
%x{lxc-stop -n #{lxc_name}}
|
174
|
+
%x{lxc-wait -n #{lxc_name} -s STOPPED}
|
175
|
+
%x{lxc-destroy -n #{lxc_name}}
|
176
|
+
end
|
177
|
+
|
178
|
+
action = ARGV.first.to_s
|
179
|
+
|
180
|
+
case action
|
181
|
+
when 'create'
|
182
|
+
lxc_name = ARGV[1]
|
183
|
+
create_lxc(lxc_name, template)
|
184
|
+
when 'list'
|
185
|
+
list_lxcs
|
186
|
+
when 'info'
|
187
|
+
lxc_name = ARGV[1]
|
188
|
+
if(lxc_exists?(lxc_name))
|
189
|
+
info_lxc(lxc_name)
|
190
|
+
else
|
191
|
+
$stderr.puts "Requested container does not exist: #{lxc_name}"
|
192
|
+
exit 2
|
193
|
+
end
|
194
|
+
when 'start'
|
195
|
+
lxc_name = ARGV[1]
|
196
|
+
if(lxc_exists?(lxc_name))
|
197
|
+
print "Starting container #{lxc_name}... "
|
198
|
+
start_lxc(lxc_name)
|
199
|
+
puts 'started'
|
200
|
+
else
|
201
|
+
$stderr.puts "Requested container does not exist: #{lxc_name}"
|
202
|
+
exit 2
|
203
|
+
end
|
204
|
+
when 'stop'
|
205
|
+
lxc_name = ARGV[1]
|
206
|
+
if(lxc_exists?(lxc_name))
|
207
|
+
print "Stopping container #{lxc_name}... "
|
208
|
+
stop_lxc(lxc_name)
|
209
|
+
puts 'stopped'
|
210
|
+
else
|
211
|
+
$stderr.puts "Requested container does not exist: #{lxc_name}"
|
212
|
+
exit 2
|
213
|
+
end
|
214
|
+
when 'delete'
|
215
|
+
lxc_name = ARGV[1]
|
216
|
+
if(lxc_exists?(lxc_name))
|
217
|
+
print "Deleting LXC #{lxc_name}... "
|
218
|
+
destroy_lxc(lxc_name)
|
219
|
+
puts 'done'
|
220
|
+
else
|
221
|
+
$stderr.puts "Requested container does not exist: #{lxc_name}"
|
222
|
+
exit 2
|
223
|
+
end
|
224
|
+
else
|
225
|
+
$stderr.puts "ERROR: Unknown action: #{action}"
|
226
|
+
exit 1
|
227
|
+
end
|
228
|
+
|