wildcloud-keeper 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +3 -0
- data/LICENSE +620 -0
- data/README.md +7 -0
- data/bin/wildcloud-keeper +27 -0
- data/lib/wildcloud/keeper.rb +13 -0
- data/lib/wildcloud/keeper/configuration.rb +32 -0
- data/lib/wildcloud/keeper/deployers/aufs.rb +92 -0
- data/lib/wildcloud/keeper/isolators/lxc.rb +93 -0
- data/lib/wildcloud/keeper/logger.rb +41 -0
- data/lib/wildcloud/keeper/runtime.rb +196 -0
- data/lib/wildcloud/keeper/templates/app.config +40 -0
- data/lib/wildcloud/keeper/templates/app.fstab +2 -0
- data/lib/wildcloud/keeper/templates/interfaces +8 -0
- data/lib/wildcloud/keeper/transport/amqp.rb +70 -0
- data/lib/wildcloud/keeper/version.rb +19 -0
- metadata +95 -0
data/README.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright 2011 Marek Jelen
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
$: << File.expand_path('../../lib', __FILE__)
|
18
|
+
|
19
|
+
require 'rubygems'
|
20
|
+
|
21
|
+
require 'eventmachine'
|
22
|
+
|
23
|
+
require 'wildcloud/keeper/runtime'
|
24
|
+
|
25
|
+
EventMachine.run do
|
26
|
+
Wildcloud::Keeper::Runtime.new
|
27
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Copyright 2011 Marek Jelen
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Copyright 2011 Marek Jelen
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'yaml'
|
16
|
+
require 'wildcloud/keeper/logger'
|
17
|
+
|
18
|
+
module Wildcloud
|
19
|
+
module Keeper
|
20
|
+
|
21
|
+
def self.configuration
|
22
|
+
return @configuration if @configuration
|
23
|
+
file = '/etc/wildcloud/keeper.yml'
|
24
|
+
unless File.exists?(file)
|
25
|
+
file = './keeper.yml'
|
26
|
+
end
|
27
|
+
Keeper.logger.info('Configuration', "Loading from file #{file}")
|
28
|
+
@configuration = YAML.load_file(file)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# Copyright 2011 Marek Jelen
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'fileutils'
|
16
|
+
|
17
|
+
require 'wildcloud/keeper/configuration'
|
18
|
+
require 'wildcloud/keeper/logger'
|
19
|
+
|
20
|
+
module Wildcloud
|
21
|
+
module Keeper
|
22
|
+
module Deployers
|
23
|
+
class Aufs
|
24
|
+
|
25
|
+
def deploy(options = {})
|
26
|
+
options[:base_image] ||= 'base'
|
27
|
+
|
28
|
+
@id = options[:id]
|
29
|
+
@appid = options[:appid]
|
30
|
+
|
31
|
+
@temp_file = File.join(config['paths']['tmp'], "#{@id}.tar.gz")
|
32
|
+
@image_path = File.join(config['paths']['images'], "#{@id}")
|
33
|
+
@target_path = File.join(config['paths']['mounts'], "#{@id}")
|
34
|
+
@temp_path = File.join(config['paths']['temp'], "#{@id}")
|
35
|
+
|
36
|
+
FileUtils.mkdir_p(@image_path)
|
37
|
+
FileUtils.mkdir_p(@target_path)
|
38
|
+
FileUtils.mkdir_p(@temp_path)
|
39
|
+
|
40
|
+
@branches = "br=#{@image_path}=rw:#{File.join(config['paths']['images'], 'base')}=ro"
|
41
|
+
options[:root_path] = @image_path
|
42
|
+
|
43
|
+
unless options[:build]
|
44
|
+
run("curl -v -o #{@temp_file} -H 'X-Appid: #{config['storage']['id']}' #{config['storage']['url']}/#{@appid}.tar.gz")
|
45
|
+
run("tar -xf #{@temp_file} -C #{@image_path}")
|
46
|
+
@branches = "br=#{@temp_path}=rw:#{@image_path}=ro:#{File.join(config['paths']['images'], options[:base_image])}=ro"
|
47
|
+
options[:root_path] = @temp_path
|
48
|
+
end
|
49
|
+
|
50
|
+
run("mount -t aufs -o #{@branches} none #{@target_path}")
|
51
|
+
end
|
52
|
+
|
53
|
+
def undeploy(options)
|
54
|
+
|
55
|
+
@id ||= options[:id]
|
56
|
+
@appid ||= options[:appid]
|
57
|
+
|
58
|
+
@temp_file ||= File.join(config['paths']['tmp'], "#{@id}.tar.gz")
|
59
|
+
@image_path ||= File.join(config['paths']['images'], "#{@id}")
|
60
|
+
@target_path ||= File.join(config['paths']['mounts'], "#{@id}")
|
61
|
+
@temp_path ||= File.join(config['paths']['temp'], "#{@id}")
|
62
|
+
|
63
|
+
run("umount #{@target_path}")
|
64
|
+
|
65
|
+
if options[:persistent]
|
66
|
+
run("tar -zcf #{@temp_file} -C #{@image_path} .")
|
67
|
+
run("curl -v -X PUT -H 'X-Appid: #{config['storage']['id']}' -T #{@temp_file} #{config['storage']['url']}/#{@appid}.tar.gz")
|
68
|
+
end
|
69
|
+
|
70
|
+
FileUtils.rm_rf(@image_path)
|
71
|
+
FileUtils.rm_rf(@target_path)
|
72
|
+
FileUtils.rm_rf(@temp_path)
|
73
|
+
|
74
|
+
FileUtils.rm(@temp_file)
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def config
|
80
|
+
Keeper.configuration
|
81
|
+
end
|
82
|
+
|
83
|
+
def run(command)
|
84
|
+
Keeper.logger.debug('Aufs') { command }
|
85
|
+
stdout = `#{command}`
|
86
|
+
Keeper.logger.debug('Aufs') { stdout }
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# Copyright 2011 Marek Jelen
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'fileutils'
|
16
|
+
require 'erb'
|
17
|
+
|
18
|
+
require 'wildcloud/keeper/configuration'
|
19
|
+
require 'wildcloud/keeper/logger'
|
20
|
+
|
21
|
+
module Wildcloud
|
22
|
+
module Keeper
|
23
|
+
module Isolators
|
24
|
+
class Lxc
|
25
|
+
|
26
|
+
def start(options)
|
27
|
+
|
28
|
+
@id = options[:id]
|
29
|
+
@target_path = File.join(config['paths']['mounts'], "#{@id}")
|
30
|
+
|
31
|
+
@config_file = File.join(config['paths']['config'], "#{@id}.config")
|
32
|
+
@fstab_file = File.join(config['paths']['config'], "#{@id}.fstab")
|
33
|
+
|
34
|
+
vm_config = ERB.new(File.read(File.expand_path('../../templates/app.config', __FILE__))).result(binding)
|
35
|
+
vm_fstab = ERB.new(File.read(File.expand_path('../../templates/app.fstab', __FILE__))).result(binding)
|
36
|
+
|
37
|
+
FileUtils.mkdir_p(config['paths']['config'])
|
38
|
+
|
39
|
+
File.open(@config_file, 'w') { |file| file.write(vm_config) }
|
40
|
+
File.open(@fstab_file, 'w') { |file| file.write(vm_fstab) }
|
41
|
+
|
42
|
+
run("lxc-create -f #{@config_file} -n #{@id}")
|
43
|
+
run("lxc-start -d -n #{@id}")
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
def stop(options)
|
48
|
+
|
49
|
+
@id ||= options[:id]
|
50
|
+
@config_file ||= File.join(config['paths']['config'], "#{@id}.config")
|
51
|
+
@fstab_file ||= File.join(config['paths']['config'], "#{@id}.fstab")
|
52
|
+
|
53
|
+
|
54
|
+
if options[:build]
|
55
|
+
build_status_file = File.join(config['paths']['images'], "#{@id}", 'var', 'build.done')
|
56
|
+
until File.exists?(build_status_file)
|
57
|
+
sleep(5)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
run("lxc-stop -n #{@id}")
|
62
|
+
run("lxc-destroy -n #{@id}")
|
63
|
+
|
64
|
+
FileUtils.rm(@config_file)
|
65
|
+
FileUtils.rm(@fstab_file)
|
66
|
+
end
|
67
|
+
|
68
|
+
def resources(options)
|
69
|
+
|
70
|
+
@id ||= options[:id]
|
71
|
+
|
72
|
+
run("lxc-cgroup -n #{@id} memory.limit_in_bytes \"#{options[:memory]}\"") if options[:memory]
|
73
|
+
run("lxc-cgroup -n #{@id} memory.memsw.limit_in_bytes \"#{options[:swap]}\"") if options[:swap]
|
74
|
+
run("lxc-cgroup -n #{@id} cpuset.cpus \"#{options[:cpus]}\"") if options[:cpus]
|
75
|
+
run("lxc-cgroup -n #{@id} cpu.shares \"#{options[:cpu_share]}\"") if options[:cpu_share]
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def config
|
81
|
+
Keeper.configuration
|
82
|
+
end
|
83
|
+
|
84
|
+
def run(command)
|
85
|
+
Keeper.logger.debug('LXC') { command }
|
86
|
+
stdout = `#{command}`
|
87
|
+
Keeper.logger.debug('LXC') { stdout }
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Copyright 2011 Marek Jelen
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'wildcloud/logger'
|
16
|
+
require 'wildcloud/logger/middleware/console'
|
17
|
+
require 'wildcloud/logger/middleware/amqp'
|
18
|
+
require 'wildcloud/logger/middleware/json'
|
19
|
+
|
20
|
+
require 'json'
|
21
|
+
|
22
|
+
module Wildcloud
|
23
|
+
module Keeper
|
24
|
+
|
25
|
+
def self.logger
|
26
|
+
unless @logger
|
27
|
+
@logger = Wildcloud::Logger::Logger.new
|
28
|
+
@logger.application = 'wildcloud.keeper'
|
29
|
+
@logger.add(Wildcloud::Logger::Middleware::Console)
|
30
|
+
end
|
31
|
+
@logger
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.add_amqp_logger(amqp)
|
35
|
+
@logger.add(Wildcloud::Logger::Middleware::Json)
|
36
|
+
@topic = AMQP::Channel.new(amqp).topic('wildcloud.logger')
|
37
|
+
@logger.add(Wildcloud::Logger::Middleware::Amqp, :exchange => @topic, :routing_key => 'wildcloud.keeper')
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
# Copyright 2011 Marek Jelen
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'fileutils'
|
16
|
+
require 'thread'
|
17
|
+
require 'yaml'
|
18
|
+
|
19
|
+
require 'wildcloud/keeper/logger'
|
20
|
+
require 'wildcloud/keeper/configuration'
|
21
|
+
|
22
|
+
require 'wildcloud/keeper/isolators/lxc'
|
23
|
+
require 'wildcloud/keeper/deployers/aufs'
|
24
|
+
|
25
|
+
require 'wildcloud/keeper/transport/amqp'
|
26
|
+
|
27
|
+
module Wildcloud
|
28
|
+
module Keeper
|
29
|
+
class Runtime
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
@repository = {}
|
33
|
+
|
34
|
+
Keeper.logger.info('Runtime') { 'Starting transport' }
|
35
|
+
@transport = Transport::Amqp.new
|
36
|
+
|
37
|
+
Keeper.logger.info('Runtime') { 'Starting thread-pool' }
|
38
|
+
@queue = Queue.new
|
39
|
+
@thread_pool = []
|
40
|
+
|
41
|
+
Keeper.configuration['node']['workers'].times do |i|
|
42
|
+
Keeper.logger.debug('Runtime', "Starting thread ##{i}")
|
43
|
+
Thread.new(i) do |id|
|
44
|
+
Thread.current.abort_on_exception = false
|
45
|
+
loop do
|
46
|
+
Keeper.logger.debug('Runtime') { "Thread ##{id} waiting for task" }
|
47
|
+
begin
|
48
|
+
@queue.pop.call
|
49
|
+
rescue Exception => exception
|
50
|
+
Keeper.logger.fatal('Runtime') { "Exception in thread #{id}: #{exception.message}" }
|
51
|
+
Keeper.logger.debug('Runtime') { exception }
|
52
|
+
Keeper.logger.debug('Runtime') { exception.backtrace }
|
53
|
+
else
|
54
|
+
Keeper.logger.debug('Runtime') { "Thread ##{id} handled task successfully" }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
handler = self.method(:handle)
|
61
|
+
@transport.start(&handler)
|
62
|
+
@transport.send({:type => :sshkey, :node => Keeper.configuration['node']['name'], :key => File.read(File.expand_path('~/.ssh/id_rsa.pub')).strip}, :master)
|
63
|
+
heartbeat
|
64
|
+
end
|
65
|
+
|
66
|
+
def heartbeat
|
67
|
+
@transport.send({:type => 'heartbeat', :node => Keeper.configuration['node']['name']}, :master)
|
68
|
+
EM.add_timer(5, method(:heartbeat))
|
69
|
+
end
|
70
|
+
|
71
|
+
def handle(message)
|
72
|
+
Keeper.logger.debug('Runtime') { "Message received #{message.inspect}" }
|
73
|
+
method = "handle_#{message['type']}".to_sym
|
74
|
+
scope = self
|
75
|
+
@queue << proc do
|
76
|
+
scope.send(method, message)
|
77
|
+
end
|
78
|
+
rescue Exception => exception
|
79
|
+
Keeper.logger.fatal('Runtime') { "Exception in runtime: #{exception.message}" }
|
80
|
+
Keeper.logger.fatal(exception)
|
81
|
+
end
|
82
|
+
|
83
|
+
def handle_build(message)
|
84
|
+
handle_deploy(message)
|
85
|
+
handle_undeploy(message)
|
86
|
+
end
|
87
|
+
|
88
|
+
def instance(id, message)
|
89
|
+
unless @repository[id]
|
90
|
+
@repository[id] = {:isolator => Isolators::Lxc.new, :deployer => Deployers::Aufs.new}
|
91
|
+
@repository[id][:options] = {
|
92
|
+
:id => "instance_#{message['id']}",
|
93
|
+
:appid => message['appid'],
|
94
|
+
:base_image => message['image'],
|
95
|
+
:persistent => message['persistent'],
|
96
|
+
:ip_address => message['ip_address'],
|
97
|
+
:memory => message['memory'],
|
98
|
+
:swap => message['swap'],
|
99
|
+
:cpus => message['cpus'],
|
100
|
+
:cpu_share => message['cpu_share']
|
101
|
+
}
|
102
|
+
if message['type'] == 'build'
|
103
|
+
@repository[id][:options].merge!({
|
104
|
+
:id => "build_#{message['id']}",
|
105
|
+
:persistent => true,
|
106
|
+
:build => true,
|
107
|
+
:repository => message['repository'],
|
108
|
+
:revision => message['revision']
|
109
|
+
})
|
110
|
+
end
|
111
|
+
end
|
112
|
+
@repository[id]
|
113
|
+
end
|
114
|
+
|
115
|
+
def get_instance_name(message)
|
116
|
+
message['type'] == 'build' ? "build_#{message['id']}" : "instance_#{message['id']}"
|
117
|
+
end
|
118
|
+
|
119
|
+
def get_instance(message)
|
120
|
+
instance = instance(get_instance_name(message), message)
|
121
|
+
options = instance[:options]
|
122
|
+
[instance, options]
|
123
|
+
end
|
124
|
+
|
125
|
+
def handle_deploy(message)
|
126
|
+
instance, options = get_instance(message)
|
127
|
+
instance[:deployer].deploy(options)
|
128
|
+
write_system_configuration(options)
|
129
|
+
instance[:isolator].start(options)
|
130
|
+
unless options[:build]
|
131
|
+
@transport.send({:type => :deployed, :node => Keeper.configuration['node']['name'], :id => message['id']}, :master)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def handle_undeploy(message)
|
136
|
+
instance, options = get_instance(message)
|
137
|
+
instance[:isolator].stop(options)
|
138
|
+
clean_system_configuration(options)
|
139
|
+
if options[:build]
|
140
|
+
build_log = File.read(File.join(options[:root_path], 'var', 'build.log'))
|
141
|
+
end
|
142
|
+
instance[:deployer].undeploy(options)
|
143
|
+
if options[:build]
|
144
|
+
@transport.send({:type => :build_log, :node => Keeper.configuration['node']['name'], :id => message['id'], :content => build_log}, :master)
|
145
|
+
else
|
146
|
+
@transport.send({:type => :undeployed, :node => Keeper.configuration['node']['name'], :id => message['id']}, :master)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def handle_resources(message)
|
151
|
+
instance_name = get_instance_name(message)
|
152
|
+
instance = @repository[instance_name]
|
153
|
+
unless instance
|
154
|
+
return
|
155
|
+
end
|
156
|
+
options = instance[:options]
|
157
|
+
options[:memory] = message['memory']
|
158
|
+
options[:swap] = message['swap']
|
159
|
+
options[:cpus] = message['cpus']
|
160
|
+
options[:cpu_share] = message['cpu_share']
|
161
|
+
instance[:isolator].resources(options)
|
162
|
+
end
|
163
|
+
|
164
|
+
def write_system_configuration(options)
|
165
|
+
root = options[:root_path]
|
166
|
+
|
167
|
+
interfaces = ERB.new(File.read(File.expand_path('../templates/interfaces', __FILE__))).result(binding)
|
168
|
+
interfaces_path = File.join(root, 'etc', 'network', 'interfaces')
|
169
|
+
FileUtils.mkdir_p(File.dirname(interfaces_path))
|
170
|
+
File.open(interfaces_path, 'w') { |file| file.write(interfaces) }
|
171
|
+
|
172
|
+
if options[:build]
|
173
|
+
FileUtils.mkdir_p(File.join(root, 'root', '.ssh'))
|
174
|
+
FileUtils.cp(File.expand_path('~/.ssh/id_rsa'), File.join(root, 'root', '.ssh', 'id_rsa'))
|
175
|
+
FileUtils.cp(File.expand_path('~/.ssh/id_rsa.pub'), File.join(root, 'root', '.ssh', 'id_rsa.pub'))
|
176
|
+
|
177
|
+
File.open(File.join(root, 'root', 'build.yml'), 'w') { |file| file.write(YAML::dump(options)) }
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def clean_system_configuration(options)
|
182
|
+
root = options[:root_path]
|
183
|
+
|
184
|
+
if options[:build]
|
185
|
+
FileUtils.rm_rf(File.join(root, 'root', '.ssh'))
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def handle_quit
|
190
|
+
Keeper.logger.fatal('Runtime') { "Shutdown requested." }
|
191
|
+
EventMachine.stop_event_loop
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|