chef-metal-lxc 0.4 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/chef_metal/driver_init/lxc.rb +3 -0
- data/lib/chef_metal_lxc.rb +1 -1
- data/lib/chef_metal_lxc/lxc_driver.rb +166 -0
- data/lib/chef_metal_lxc/lxc_transport.rb +32 -26
- data/lib/chef_metal_lxc/version.rb +1 -1
- metadata +27 -32
- data/lib/chef_metal_lxc/lxc_provisioner.rb +0 -164
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 222f247414cedb23359fd5b9925b15a4264c8571
|
4
|
+
data.tar.gz: 3b857d0edcb88781b6106b467622d125d8d9c524
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25cb466ac9b171b94dd9c13502000616298a7293557f6f4666ab06f0612b14647fac06c79b8e1650577b090ac9e70ff471972450022f400204562192e6126151
|
7
|
+
data.tar.gz: 6c43f9e2d61768220c81d9c74f0215a86b51eaf24c9ac0f26478eea35f259d892fcab0bca7552124b0d71cfb9c8bb1078cc31c456d54c3a4d37b52cad9280cb5
|
data/lib/chef_metal_lxc.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
require 'chef_metal'
|
2
|
-
require 'chef_metal_lxc/
|
2
|
+
require 'chef_metal_lxc/lxc_driver'
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'chef/mixin/shell_out'
|
2
|
+
require 'chef_metal/driver'
|
3
|
+
require 'chef_metal/machine/unix_machine'
|
4
|
+
require 'chef_metal/convergence_strategy/install_cached'
|
5
|
+
require 'chef_metal_lxc/lxc_transport'
|
6
|
+
require 'chef_metal_lxc/version'
|
7
|
+
require 'lxc'
|
8
|
+
require 'shellwords'
|
9
|
+
|
10
|
+
module ChefMetalLXC
|
11
|
+
# Provisions machines in lxc.
|
12
|
+
class LXCDriver < ChefMetal::Driver
|
13
|
+
|
14
|
+
include Chef::Mixin::ShellOut
|
15
|
+
|
16
|
+
# URL scheme:
|
17
|
+
# lxc:<path>
|
18
|
+
# <path> defaults to LXC config 'lxc.lxcpath'
|
19
|
+
# canonical URL calls realpath on <path>
|
20
|
+
def self.from_url(driver_url, config)
|
21
|
+
LXCDriver.new(driver_url, config)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.canonicalize_url(driver_url, config)
|
25
|
+
scheme, lxc_path = driver_url.split(':', 2)
|
26
|
+
if lxc_path.nil? || lxc_path == ':'
|
27
|
+
lxc_path = LXC.global_config_item('lxc.lxcpath')
|
28
|
+
end
|
29
|
+
lxc_path = File.realpath(lxc_path)
|
30
|
+
[ "lxc:#{lxc_path}", config ]
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(driver_url, config)
|
34
|
+
super
|
35
|
+
end
|
36
|
+
|
37
|
+
def lxc_path
|
38
|
+
scheme, lxc_path = driver_url.split(':', 2)
|
39
|
+
lxc_path
|
40
|
+
end
|
41
|
+
|
42
|
+
# Valid machine options:
|
43
|
+
# :template - template name
|
44
|
+
# :template_options - additional arguments for templates
|
45
|
+
# :backingstore - backing storage (lvm, thinpools, btrfs etc)
|
46
|
+
# :config_file - <path> path to LXC file a la https://wiki.archlinux.org/index.php/Linux_Containers#Configuration_file
|
47
|
+
# :extra_config - { 'key' => 'value', ... } a set of LXC config key/value pairs to individually set. Merges with, and overrides any values in config_file.
|
48
|
+
def allocate_machine(action_handler, machine_spec, machine_options)
|
49
|
+
# Create the container if it does not exist
|
50
|
+
if machine_spec.location
|
51
|
+
ct = LXC::Container.new(machine_spec.location['name'], lxc_path)
|
52
|
+
else
|
53
|
+
ct = LXC::Container.new(machine_spec.name, lxc_path)
|
54
|
+
if ct.defined?
|
55
|
+
# Should this be a warning? Configurable, at least.
|
56
|
+
raise "container #{machine_spec.name} already exists and is not managed by this LXC driver."
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
unless ct.defined?
|
61
|
+
action_handler.perform_action "create lxc container #{ct.name}" do
|
62
|
+
#
|
63
|
+
# Set config
|
64
|
+
#
|
65
|
+
# TODO if config file changes, reload container?
|
66
|
+
if machine_options[:config_file]
|
67
|
+
ct.load_config(machine_options[:config_file])
|
68
|
+
end
|
69
|
+
if machine_options[:extra_config]
|
70
|
+
machine_options[:extra_config].each_pair do |key, value|
|
71
|
+
ct.set_config_item(key, value)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# Create the machine
|
77
|
+
#
|
78
|
+
ct.create(machine_options[:template], machine_options[:backingstore], machine_options[:devspecs], 0, machine_options[:template_options])
|
79
|
+
|
80
|
+
machine_spec.location = {
|
81
|
+
'driver_url' => driver_url,
|
82
|
+
'driver_version' => ChefMetalLXC::VERSION,
|
83
|
+
'name' => machine_spec.name,
|
84
|
+
'host_node' => action_handler.host_node,
|
85
|
+
'allocated_at' => Time.now.utc.to_s
|
86
|
+
}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def ready_machine(action_handler, machine_spec, machine_options)
|
92
|
+
ct = LXC::Container.new(machine_spec.location['name'], lxc_path)
|
93
|
+
|
94
|
+
# Unfreeze the frozen
|
95
|
+
if ct.state == :frozen
|
96
|
+
action_handler.perform_action "unfreeze lxc container #{machine_spec.location['name']} (state is #{ct.state})" do
|
97
|
+
ct.unfreeze
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Get stopped containers running
|
102
|
+
unless ct.running?
|
103
|
+
action_handler.perform_action "start lxc container #{machine_spec.location['name']} (state is #{ct.state})" do
|
104
|
+
# Have to shell out to lxc-start for now, ct.start holds server sockets open!
|
105
|
+
lxc_start = "lxc-start -d -n #{Shellwords.escape(machine_spec.location['name'])}"
|
106
|
+
# TODO add ability to change options on start
|
107
|
+
# if machine_options[:config_file]
|
108
|
+
# lxc_start << " -f #{Shellwords.escape(machine_options[:config_file])}"
|
109
|
+
# end
|
110
|
+
# if machine_options[:extra_config]
|
111
|
+
# machine_options[:extra_config].each_pair do |key,value|
|
112
|
+
# lxc_start << " -s #{Shellwords.escape("#{key}=#{value}")}"
|
113
|
+
# end
|
114
|
+
# end
|
115
|
+
shell_out!(lxc_start)
|
116
|
+
# ct.start
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Create machine object for callers to use
|
121
|
+
machine_for(machine_spec, machine_options)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Connect to machine without acquiring it
|
125
|
+
def connect_to_machine(machine_spec, machine_options)
|
126
|
+
machine_for(machine_spec, machine_options)
|
127
|
+
end
|
128
|
+
|
129
|
+
def destroy_machine(action_handler, machine_spec, machine_options)
|
130
|
+
if machine_spec.location
|
131
|
+
ct = LXC::Container.new(machine_spec.location['name'], lxc_path)
|
132
|
+
if ct.defined?
|
133
|
+
action_handler.perform_action "delete lxc container #{machine_spec.location['name']}" do
|
134
|
+
ct.destroy
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
convergence_strategy_for(machine_spec, machine_options).cleanup_convergence(action_handler, machine_spec)
|
139
|
+
end
|
140
|
+
|
141
|
+
def stop_machine(action_handler, node)
|
142
|
+
if machine_spec.location
|
143
|
+
ct = LXC::Container.new(machine_spec.location['name'], lxc_path)
|
144
|
+
if ct.running?
|
145
|
+
action_handler.perform_action "delete lxc container #{machine_spec.location['name']}" do
|
146
|
+
ct.stop
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
protected
|
153
|
+
|
154
|
+
def machine_for(machine_spec, machine_options)
|
155
|
+
ChefMetal::Machine::UnixMachine.new(machine_spec, transport_for(machine_spec), convergence_strategy_for(machine_spec, machine_options))
|
156
|
+
end
|
157
|
+
|
158
|
+
def convergence_strategy_for(machine_spec, machine_options)
|
159
|
+
ChefMetal::ConvergenceStrategy::InstallCached.new(machine_options[:convergence_options], config)
|
160
|
+
end
|
161
|
+
|
162
|
+
def transport_for(machine_spec)
|
163
|
+
ChefMetalLXC::LXCTransport.new(machine_spec.location['name'], lxc_path)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -25,7 +25,7 @@ module ChefMetalLXC
|
|
25
25
|
@options = options
|
26
26
|
@name = name
|
27
27
|
@lxc_path = lxc_path
|
28
|
-
@port_forwards =
|
28
|
+
@port_forwards = {}
|
29
29
|
@@active_transports << self
|
30
30
|
end
|
31
31
|
|
@@ -43,7 +43,7 @@ module ChefMetalLXC
|
|
43
43
|
|
44
44
|
def execute(command, options = {})
|
45
45
|
Chef::Log.info("Executing #{command} on #{name}")
|
46
|
-
container.execute do
|
46
|
+
container.execute(:timeout => (execute_timeout(options) || 0)) do
|
47
47
|
begin
|
48
48
|
# TODO support streaming (shell out needs work)
|
49
49
|
out = shell_out(command)
|
@@ -57,33 +57,37 @@ module ChefMetalLXC
|
|
57
57
|
def make_url_available_to_remote(local_url)
|
58
58
|
uri = URI(local_url)
|
59
59
|
host = Socket.getaddrinfo(uri.host, uri.scheme, nil, :STREAM)[0][3]
|
60
|
-
if host == '127.0.0.1' || host == '
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
60
|
+
if host == '127.0.0.1' || host == '::1'
|
61
|
+
unless @port_forwards[uri.port]
|
62
|
+
|
63
|
+
Chef::Log.debug("Forwarding container port #{uri.port} to local port #{uri.port}")
|
64
|
+
# Create the channel that will let the container and the host talk to each other
|
65
|
+
channel = LXC::Extra::Channel.new
|
66
|
+
|
67
|
+
# Start the container side of the proxy, listening for client connections
|
68
|
+
pid = container.attach do
|
69
|
+
begin
|
70
|
+
server = TCPServer.new(host, uri.port)
|
71
|
+
proxy = LXC::Extra::ProxyClientSide.new(channel, server)
|
72
|
+
proxy.start
|
73
|
+
rescue
|
74
|
+
Chef::Log.error("ERROR in proxy (container side): #{$!}\n#{$!.backtrace.join("\n")}")
|
75
|
+
raise
|
76
|
+
end
|
77
|
+
end
|
65
78
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
79
|
+
# Start the host side of the proxy, which contacts the real server
|
80
|
+
thread = Thread.new do
|
81
|
+
proxy = LXC::Extra::ProxyServerSide.new(channel) do
|
82
|
+
TCPSocket.new(host, uri.port)
|
83
|
+
end
|
71
84
|
proxy.start
|
72
|
-
rescue
|
73
|
-
Chef::Log.error("ERROR in proxy (container side): #{$!}\n#{$!.backtrace.join("\n")}")
|
74
|
-
raise
|
75
85
|
end
|
76
|
-
end
|
77
86
|
|
78
|
-
|
79
|
-
thread = Thread.new do
|
80
|
-
proxy = LXC::Extra::ProxyServerSide.new(channel) do
|
81
|
-
TCPSocket.new('127.0.0.1', uri.port)
|
82
|
-
end
|
83
|
-
proxy.start
|
84
|
-
end
|
87
|
+
Chef::Log.debug("Forwarded #{uri.port} on container #{name} to local port #{uri.port}. Container listener id PID #{pid}")
|
85
88
|
|
86
|
-
|
89
|
+
@port_forwards[uri.port] = [ pid, thread, channel ]
|
90
|
+
end
|
87
91
|
|
88
92
|
end
|
89
93
|
local_url
|
@@ -111,8 +115,10 @@ module ChefMetalLXC
|
|
111
115
|
end
|
112
116
|
|
113
117
|
def disconnect
|
114
|
-
@port_forwards.
|
118
|
+
@port_forwards.each_pair do |port, (pid, thread, channel)|
|
119
|
+
Chef::Log.debug("stopping port forward #{port} for container #{name}")
|
115
120
|
begin
|
121
|
+
Chef::Log.debug("Killing PID #{pid}")
|
116
122
|
Process.kill('KILL', pid)
|
117
123
|
rescue
|
118
124
|
end
|
@@ -121,7 +127,7 @@ module ChefMetalLXC
|
|
121
127
|
rescue
|
122
128
|
end
|
123
129
|
end
|
124
|
-
@port_forwards =
|
130
|
+
@port_forwards = {}
|
125
131
|
@@active_transports.delete(self)
|
126
132
|
end
|
127
133
|
|
metadata
CHANGED
@@ -1,109 +1,103 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-metal-lxc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.5'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ranjib Dey
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: chef-metal
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0.
|
33
|
+
version: '0.11'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0.
|
40
|
+
version: '0.11'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: ruby-lxc
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '1.
|
48
|
-
- - '>='
|
49
|
-
- !ruby/object:Gem::Version
|
50
|
-
version: 1.0.2
|
47
|
+
version: '1.1'
|
51
48
|
type: :runtime
|
52
49
|
prerelease: false
|
53
50
|
version_requirements: !ruby/object:Gem::Requirement
|
54
51
|
requirements:
|
55
|
-
- - ~>
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
version: '1.0'
|
58
|
-
- - '>='
|
52
|
+
- - "~>"
|
59
53
|
- !ruby/object:Gem::Version
|
60
|
-
version: 1.
|
54
|
+
version: '1.1'
|
61
55
|
- !ruby/object:Gem::Dependency
|
62
56
|
name: lxc-extra
|
63
57
|
requirement: !ruby/object:Gem::Requirement
|
64
58
|
requirements:
|
65
|
-
- - ~>
|
59
|
+
- - "~>"
|
66
60
|
- !ruby/object:Gem::Version
|
67
61
|
version: '0.0'
|
68
|
-
- -
|
62
|
+
- - ">="
|
69
63
|
- !ruby/object:Gem::Version
|
70
64
|
version: 0.0.3
|
71
65
|
type: :runtime
|
72
66
|
prerelease: false
|
73
67
|
version_requirements: !ruby/object:Gem::Requirement
|
74
68
|
requirements:
|
75
|
-
- - ~>
|
69
|
+
- - "~>"
|
76
70
|
- !ruby/object:Gem::Version
|
77
71
|
version: '0.0'
|
78
|
-
- -
|
72
|
+
- - ">="
|
79
73
|
- !ruby/object:Gem::Version
|
80
74
|
version: 0.0.3
|
81
75
|
- !ruby/object:Gem::Dependency
|
82
76
|
name: rspec
|
83
77
|
requirement: !ruby/object:Gem::Requirement
|
84
78
|
requirements:
|
85
|
-
- -
|
79
|
+
- - ">="
|
86
80
|
- !ruby/object:Gem::Version
|
87
81
|
version: '0'
|
88
82
|
type: :development
|
89
83
|
prerelease: false
|
90
84
|
version_requirements: !ruby/object:Gem::Requirement
|
91
85
|
requirements:
|
92
|
-
- -
|
86
|
+
- - ">="
|
93
87
|
- !ruby/object:Gem::Version
|
94
88
|
version: '0'
|
95
89
|
- !ruby/object:Gem::Dependency
|
96
90
|
name: rake
|
97
91
|
requirement: !ruby/object:Gem::Requirement
|
98
92
|
requirements:
|
99
|
-
- -
|
93
|
+
- - ">="
|
100
94
|
- !ruby/object:Gem::Version
|
101
95
|
version: '0'
|
102
96
|
type: :development
|
103
97
|
prerelease: false
|
104
98
|
version_requirements: !ruby/object:Gem::Requirement
|
105
99
|
requirements:
|
106
|
-
- -
|
100
|
+
- - ">="
|
107
101
|
- !ruby/object:Gem::Version
|
108
102
|
version: '0'
|
109
103
|
description: Provisioner for creating LXC containers in Chef Metal.
|
@@ -114,13 +108,14 @@ extra_rdoc_files:
|
|
114
108
|
- README.md
|
115
109
|
- LICENSE
|
116
110
|
files:
|
117
|
-
- Rakefile
|
118
111
|
- LICENSE
|
119
112
|
- README.md
|
120
|
-
-
|
113
|
+
- Rakefile
|
114
|
+
- lib/chef_metal/driver_init/lxc.rb
|
115
|
+
- lib/chef_metal_lxc.rb
|
116
|
+
- lib/chef_metal_lxc/lxc_driver.rb
|
121
117
|
- lib/chef_metal_lxc/lxc_transport.rb
|
122
118
|
- lib/chef_metal_lxc/version.rb
|
123
|
-
- lib/chef_metal_lxc.rb
|
124
119
|
homepage: https://github.com/opscode/chef-metal-lxc
|
125
120
|
licenses: []
|
126
121
|
metadata: {}
|
@@ -130,17 +125,17 @@ require_paths:
|
|
130
125
|
- lib
|
131
126
|
required_ruby_version: !ruby/object:Gem::Requirement
|
132
127
|
requirements:
|
133
|
-
- -
|
128
|
+
- - ">="
|
134
129
|
- !ruby/object:Gem::Version
|
135
130
|
version: '0'
|
136
131
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
132
|
requirements:
|
138
|
-
- -
|
133
|
+
- - ">="
|
139
134
|
- !ruby/object:Gem::Version
|
140
135
|
version: '0'
|
141
136
|
requirements: []
|
142
137
|
rubyforge_project:
|
143
|
-
rubygems_version: 2.
|
138
|
+
rubygems_version: 2.2.2
|
144
139
|
signing_key:
|
145
140
|
specification_version: 4
|
146
141
|
summary: Provisioner for creating LXC containers in Chef Metal.
|
@@ -1,164 +0,0 @@
|
|
1
|
-
require 'chef/mixin/shell_out'
|
2
|
-
require 'chef_metal/provisioner'
|
3
|
-
require 'chef_metal/machine/unix_machine'
|
4
|
-
require 'chef_metal/convergence_strategy/install_cached'
|
5
|
-
require 'chef_metal_lxc/lxc_transport'
|
6
|
-
require 'lxc'
|
7
|
-
require 'shellwords'
|
8
|
-
|
9
|
-
module ChefMetalLXC
|
10
|
-
# Provisions machines in lxc.
|
11
|
-
class LXCProvisioner < ChefMetal::Provisioner
|
12
|
-
|
13
|
-
include Chef::Mixin::ShellOut
|
14
|
-
|
15
|
-
def initialize(lxc_path = nil)
|
16
|
-
@lxc_path = lxc_path || LXC.global_config_item('lxc.lxcpath')
|
17
|
-
end
|
18
|
-
|
19
|
-
attr_reader :lxc_path
|
20
|
-
|
21
|
-
#
|
22
|
-
# Acquire a machine, generally by provisioning it. Returns a Machine
|
23
|
-
# object pointing at the machine, allowing useful actions like setup,
|
24
|
-
# converge, execute, file and directory. The Machine object will have a
|
25
|
-
# "node" property which must be saved to the server (if it is any
|
26
|
-
# different from the original node object).
|
27
|
-
#
|
28
|
-
# ## Parameters
|
29
|
-
# action_handler - the action_handler object that provides context.
|
30
|
-
# node - node object (deserialized json) representing this machine. If
|
31
|
-
# the node has a provisioner_options hash in it, these will be used
|
32
|
-
# instead of options provided by the provisioner. TODO compare and
|
33
|
-
# fail if different?
|
34
|
-
# node will have node['normal']['provisioner_options'] in it with any options.
|
35
|
-
# It is a hash with this format:
|
36
|
-
#
|
37
|
-
# -- provisioner_url: lxc:<lxc_path>
|
38
|
-
# -- template: template name
|
39
|
-
# -- template_options: additional arguments for templates
|
40
|
-
# -- backingstore: backing storage (lvm, thinpools, btrfs etc)
|
41
|
-
# -- config_file: <path> path to LXC file a la https://wiki.archlinux.org/index.php/Linux_Containers#Configuration_file
|
42
|
-
# -- extra_config: { 'key' => 'value', ... } a set of LXC config key/value pairs to individually set. Merges with, and overrides any values in config_file.
|
43
|
-
#
|
44
|
-
# node['normal']['provisioner_output'] will be populated with information
|
45
|
-
# about the created machine. For lxc, it is a hash with this
|
46
|
-
# format:
|
47
|
-
#
|
48
|
-
# -- provisioner_url: lxc:<lxc_path>
|
49
|
-
# -- name: container name
|
50
|
-
#
|
51
|
-
def acquire_machine(action_handler, node)
|
52
|
-
# TODO verify that the existing provisioner_url in the node is the same as ours
|
53
|
-
|
54
|
-
# Set up the modified node data
|
55
|
-
provisioner_options = node['normal']['provisioner_options']
|
56
|
-
provisioner_output = node['normal']['provisioner_output'] || {
|
57
|
-
'provisioner_url' => "lxc:#{lxc_path}",
|
58
|
-
'name' => node['name']
|
59
|
-
}
|
60
|
-
|
61
|
-
# Create the container if it does not exist
|
62
|
-
ct = LXC::Container.new(provisioner_output['name'], lxc_path)
|
63
|
-
unless ct.defined?
|
64
|
-
action_handler.perform_action "create lxc container #{provisioner_output['name']}" do
|
65
|
-
#
|
66
|
-
# Set config
|
67
|
-
#
|
68
|
-
# TODO if config file changes, reload container?
|
69
|
-
if provisioner_options['config_file']
|
70
|
-
ct.load_config(provisioner_options['config_file'])
|
71
|
-
end
|
72
|
-
if provisioner_options['extra_config']
|
73
|
-
provisioner_options['extra_config'].each_pair do |key, value|
|
74
|
-
ct.set_config_item(key, value)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
#
|
79
|
-
# Create the machine
|
80
|
-
#
|
81
|
-
ct.create(provisioner_options['template'], provisioner_options['backingstore'], 0, provisioner_options['template_options'])
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
# Unfreeze the frozen
|
86
|
-
if ct.state == :frozen
|
87
|
-
action_handler.perform_action "unfreeze lxc container #{provisioner_output['name']} (state is #{ct.state})" do
|
88
|
-
ct.unfreeze
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# Get stopped containers running
|
93
|
-
unless ct.running?
|
94
|
-
action_handler.perform_action "start lxc container #{provisioner_output['name']} (state is #{ct.state})" do
|
95
|
-
# Have to shell out to lxc-start for now, ct.start holds server sockets open!
|
96
|
-
lxc_start = "lxc-start -d -n #{Shellwords.escape(provisioner_output['name'])}"
|
97
|
-
# TODO add ability to change options on start
|
98
|
-
# if provisioner_options['config_file']
|
99
|
-
# lxc_start << " -f #{Shellwords.escape(provisioner_options['config_file'])}"
|
100
|
-
# end
|
101
|
-
# if provisioner_options['extra_config']
|
102
|
-
# provisioner_options['extra_config'].each_pair do |key,value|
|
103
|
-
# lxc_start << " -s #{Shellwords.escape("#{key}=#{value}")}"
|
104
|
-
# end
|
105
|
-
# end
|
106
|
-
shell_out!(lxc_start)
|
107
|
-
# ct.start
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
node['normal']['provisioner_output'] = provisioner_output
|
112
|
-
# Create machine object for callers to use
|
113
|
-
machine_for(node)
|
114
|
-
end
|
115
|
-
|
116
|
-
# Connect to machine without acquiring it
|
117
|
-
def connect_to_machine(node)
|
118
|
-
machine_for(node)
|
119
|
-
end
|
120
|
-
|
121
|
-
def delete_machine(action_handler, node)
|
122
|
-
if node['normal'] && node['normal']['provisioner_output']
|
123
|
-
provisioner_output = node['normal']['provisioner_output']
|
124
|
-
ct = LXC::Container.new(provisioner_output['name'], lxc_path)
|
125
|
-
if ct.defined?
|
126
|
-
action_handler.perform_action "delete lxc container #{provisioner_output['name']}" do
|
127
|
-
ct.destroy
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
convergence_strategy_for(node).delete_chef_objects(action_handler, node)
|
132
|
-
end
|
133
|
-
|
134
|
-
def stop_machine(action_handler, node)
|
135
|
-
provisioner_options = node['normal']['provisioner_options']
|
136
|
-
if node['normal'] && node['normal']['provisioner_output']
|
137
|
-
provisioner_output = node['normal']['provisioner_output']
|
138
|
-
ct = LXC::Container.new(provisioner_output['name'], lxc_path)
|
139
|
-
if ct.running?
|
140
|
-
action_handler.perform_action "delete lxc container #{provisioner_output['name']}" do
|
141
|
-
ct.stop
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
protected
|
148
|
-
|
149
|
-
def machine_for(node)
|
150
|
-
ChefMetal::Machine::UnixMachine.new(node, transport_for(node), convergence_strategy_for(node))
|
151
|
-
end
|
152
|
-
|
153
|
-
def convergence_strategy_for(node)
|
154
|
-
@convergence_strategy ||= begin
|
155
|
-
ChefMetal::ConvergenceStrategy::InstallCached.new
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
def transport_for(node)
|
160
|
-
provisioner_output = node['normal']['provisioner_output']
|
161
|
-
ChefMetalLXC::LXCTransport.new(provisioner_output['name'], lxc_path)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|