avst-cloud 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,56 @@
1
+ # Copyright 2015 Adaptavist.com Ltd.
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_relative './cloud_server.rb'
16
+
17
+ module AvstCloud
18
+ class AwsServer < AvstCloud::CloudServer
19
+
20
+ def stop
21
+ if @server
22
+ logger.debug "Stopping #{@server_name}"
23
+ @server.stop
24
+ wait_for_state() {|serv| serv.state == 'stopped'}
25
+ logger.debug "[DONE]\n\n"
26
+ logger.debug "Server #{@server_name} stopped...".green
27
+ else
28
+ raise "Server #{@server_name} does not exist!".red
29
+ end
30
+ end
31
+
32
+ def start
33
+ if @server
34
+ logger.debug "Starting #{@server_name}"
35
+ @server.start
36
+ wait_for_state() {|serv| serv.ready?}
37
+ logger.debug "[DONE]\n\n"
38
+ logger.debug "Server #{@server_name} started...".green
39
+ else
40
+ raise "Server #{@server_name} does not exist!".red
41
+ end
42
+ end
43
+
44
+ def destroy
45
+ if @server
46
+ logger.debug "Killing #{@server_name}"
47
+ @server.destroy
48
+ wait_for_state() {|serv| serv.state == 'terminated'}
49
+ logger.debug "Server #{@server_name} destroyed...".green
50
+ else
51
+ raise "Server #{@server_name} does not exist!".red
52
+ end
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,39 @@
1
+ # Copyright 2015 Adaptavist.com Ltd.
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_relative './logging.rb'
16
+
17
+ module AvstCloud
18
+ class CloudConnection
19
+ include Logging
20
+ attr_accessor :connection, :provider, :provider_user, :provider_pass
21
+
22
+ def initialize(provider, provider_user, provider_pass)
23
+ @provider = provider
24
+ @provider_access_user = provider_user
25
+ @provider_access_pass = provider_pass
26
+ end
27
+
28
+ # Abstract classes to be implemented per provider
29
+ UNIMPLEMENTED="Unimplemented..."
30
+
31
+ def server(server_name, root_user, root_password, os=nil)
32
+ raise UNIMPLEMENTED
33
+ end
34
+
35
+ def list_known_servers
36
+ raise UNIMPLEMENTED
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,89 @@
1
+ # Copyright 2015 Adaptavist.com Ltd.
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_relative './logging.rb'
16
+ require_relative './task.rb'
17
+
18
+ module AvstCloud
19
+ class CloudServer
20
+ include Logging
21
+ attr_accessor :server, :server_name, :ip_address, :access_user, :access_password
22
+
23
+ def initialize(server, server_name, ip_address, access_user, access_password)
24
+ @server = server
25
+ @ip_address = ip_address
26
+ @server_name = server_name
27
+ @access_user = access_user
28
+ @access_password = access_password
29
+ end
30
+
31
+ def bootstrap(pre_upload_commands, custom_file_uploads, post_upload_commands, remote_server_debug, debug_structured_log)
32
+ logger.debug "Bootstrapping #{server_name}...".green
33
+ run_tasks([AvstCloud::WaitUntilReady.new])
34
+ disable_tty_task = AvstCloud::DisableRequireTty.new(@access_user)
35
+ pre_upload_commands_tasks = AvstCloud::SshCommandTask.new(pre_upload_commands, remote_server_debug, debug_structured_log)
36
+ custom_file_uploads_tasks = AvstCloud::ScpTask.new(custom_file_uploads)
37
+ post_upload_commands_tasks = AvstCloud::SshCommandTask.new(post_upload_commands, remote_server_debug, debug_structured_log)
38
+ run_tasks([disable_tty_task, pre_upload_commands_tasks, custom_file_uploads_tasks, post_upload_commands_tasks])
39
+ logger.debug "Bootstrap done. You can connect to server as #{@access_user} on #{@ip_address}"
40
+ end
41
+
42
+ def provision(git, branch, server_tmp_folder, reference, custom_provisioning_commands, puppet_runner, puppet_runner_prepare, destination_folder)
43
+ logger.debug "Provisioning #{@server_name}..."
44
+ provision_task = AvstCloud::CapistranoDeploymentTask.new(git, branch, server_tmp_folder, reference, custom_provisioning_commands, puppet_runner, puppet_runner_prepare, destination_folder)
45
+ run_tasks([AvstCloud::WaitUntilReady.new, provision_task])
46
+ logger.debug "Provisioning done. You can connect to server on #{@ip_address}"
47
+ end
48
+
49
+ def post_provisioning_cleanup(custom_commands, os, remote_server_debug, server_tmp_folder)
50
+ logger.debug "Cleaning up after provisioning #{server_name}..."
51
+ custom_cleanup_commands = AvstCloud::SshCommandTask.new(custom_commands, remote_server_debug, true)
52
+ run_tasks([AvstCloud::WaitUntilReady.new, AvstCloud::PostProvisionCleanup.new(os, remote_server_debug, server_tmp_folder), custom_cleanup_commands])
53
+ logger.debug "Post provisioning cleanup done. You can connect to server as #{@access_user} on #{@ip_address}"
54
+ end
55
+
56
+ def run_tasks(tasks)
57
+ Array(tasks).each do |task|
58
+ task.execute self
59
+ end
60
+ end
61
+
62
+ def status
63
+ @server.state
64
+ end
65
+
66
+ def wait_for_state(&cond)
67
+ logger.debug "Waiting for state change...".yellow
68
+ @server.wait_for(600, 5) do
69
+ print "."
70
+ STDOUT.flush
71
+ cond.call(self)
72
+ end
73
+ end
74
+
75
+ # Abstract classes to be implemented per provider
76
+ UNIMPLEMENTED="Unimplemented..."
77
+ def stop
78
+ raise UNIMPLEMENTED
79
+ end
80
+
81
+ def start
82
+ raise UNIMPLEMENTED
83
+ end
84
+
85
+ def destroy
86
+ raise UNIMPLEMENTED
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,36 @@
1
+ # Copyright 2015 Adaptavist.com Ltd.
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 'logger'
16
+
17
+ module Logging
18
+ def self.included(base)
19
+ class << base
20
+ def logger
21
+ @logger ||= Logger.new($stdout)
22
+ end
23
+
24
+ def logger=(logger)
25
+ @logger = logger
26
+ end
27
+ end
28
+ end
29
+
30
+ def logger
31
+ self.class.logger
32
+ end
33
+ def logger=(logger)
34
+ @logger = logger
35
+ end
36
+ end
@@ -0,0 +1,141 @@
1
+ # Copyright 2015 Adaptavist.com Ltd.
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_relative './cloud_connection.rb'
16
+
17
+ module AvstCloud
18
+
19
+ class RackspaceConnection < AvstCloud::CloudConnection
20
+
21
+ attr_accessor :region
22
+
23
+ def initialize(provider_access_user, provider_access_pass, region=:lon)
24
+ super('rackspace',provider_access_user, provider_access_pass)
25
+ @region = region
26
+ end
27
+
28
+ def server(server_name, root_user, root_password, os=nil)
29
+ server = find_fog_server(server_name)
30
+ if !root_user
31
+ root_user = "root"
32
+ end
33
+ AvstCloud::RackspaceServer.new(server, server_name, server.public_ip_address, root_user, root_password)
34
+ end
35
+
36
+ def create_server(server_name, image_id, flavor_id='4')
37
+ server_number, os="ubuntu14"
38
+
39
+ logger.debug "Creating Rackspace server:"
40
+ logger.debug "server_name - #{server_name}"
41
+ logger.debug "flavor_id - #{flavor_id}"
42
+ logger.debug "image_id - #{image_id}"
43
+
44
+ unless server_name and image_id
45
+ raise "Please provide server_name, image_id and flavor_id"
46
+ end
47
+
48
+ # Check existing server
49
+ existing_server = find_fog_server(server_name, false)
50
+ if existing_server && existing_server.state != 'SHUTOFF'
51
+ logger.debug "Server found in state: #{existing_server.state}"
52
+ raise "Server with the same name found!"
53
+ elsif existing_server && existing_server.state == 'SHUTOFF'
54
+ logger.debug "Server found and is stopped, restarting it."
55
+ existing_server.reboot 'HARD'
56
+ result_server = AvstCloud::RackspaceServer.new(existing_server, server_name, nil, nil , nil)
57
+ result_server.wait_for_state() {|serv| serv.ready?}
58
+ logger.debug "[DONE]\n\n"
59
+ logger.debug "The server was successfully re-started.\n\n"
60
+ else
61
+ # create server
62
+ server = connect.servers.create :name => server_name,
63
+ :flavor_id => flavor_id,
64
+ :image_id => image_id
65
+ begin
66
+ result_server = AvstCloud::RackspaceServer.new(server, server_name, nil, nil , nil)
67
+ # Check every 5 seconds to see if server is in the active state (ready?).
68
+ # If the server has not been built in 5 minutes (600 seconds) an exception will be raised.
69
+ result_server.wait_for_state() {|serv| serv.ready?}
70
+ logger.debug "[DONE]\n\n"
71
+
72
+ logger.debug "The server has been successfully created, to login onto the server:\n\n"
73
+ logger.debug "\t ssh #{server.username}@#{server.public_ip_address}\n\n"
74
+
75
+ rescue Fog::Errors::TimeoutError
76
+ logger.debug "[TIMEOUT]\n\n"
77
+ logger.debug "This server is currently #{server.progress}% into the build process and is taking longer to complete than expected."
78
+ logger.debug "You can continute to monitor the build process through the web console at https://mycloud.rackspace.com/\n\n"
79
+ raise "Timeout while creating Rackspace server #{server_name}"
80
+ end
81
+ logger.debug "The #{server.username} password is #{server.password}\n\n"
82
+ end
83
+ result_server.access_user = server.username
84
+ result_server.access_password = server.password
85
+ result_server.ip_address = server.public_ip_address
86
+ result_server
87
+ end
88
+
89
+ def server_status(server_name)
90
+ server = find_fog_server(server_name, false)
91
+ if server
92
+ server.state
93
+ else
94
+ 'not_created'
95
+ end
96
+ end
97
+
98
+ def list_flavours
99
+ connect.flavors.each do |fl|
100
+ logger.debug fl.inspect
101
+ end
102
+ end
103
+
104
+ def list_images
105
+ connect.images.each do |im|
106
+ logger.debug im.inspect
107
+ end
108
+ end
109
+
110
+ # Returns list of servers from fog
111
+ def list_known_servers
112
+ connect.servers.all
113
+ end
114
+
115
+ def find_fog_server(server_name, should_fail=true)
116
+ serv = connect.servers.find{|serv| serv.name == server_name}
117
+ unless serv
118
+ if should_fail
119
+ logger.debug "Server not found for name: #{server_name}"
120
+ raise "Server not found for name: #{server_name}"
121
+ end
122
+ end
123
+ serv
124
+ end
125
+
126
+ private
127
+ def connect
128
+ unless @connection
129
+ logger.debug "Creating new connection to rackspace: #{@provider_user} #{@provider_pass} #{@region}"
130
+ @connection = Fog::Compute.new({
131
+ :provider => 'rackspace',
132
+ :rackspace_username => @provider_access_user,
133
+ :rackspace_api_key => @provider_access_pass,
134
+ :version => :v2, # Use Next Gen Cloud Servers
135
+ :rackspace_region => @region
136
+ })
137
+ end
138
+ @connection
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,58 @@
1
+ # Copyright 2015 Adaptavist.com Ltd.
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_relative './cloud_server.rb'
16
+
17
+ module AvstCloud
18
+ class RackspaceServer < AvstCloud::CloudServer
19
+
20
+ def stop
21
+ if @server
22
+ logger.debug "Stopping #{@server_name}"
23
+
24
+ shutdown_command = AvstCloud::SshCommandTask.new(['shutdown -h now'])
25
+ run_tasks([AvstCloud::WaitUntilReady.new, shutdown_command])
26
+ logger.debug "Waiting for SHUTOFF state..."
27
+ wait_for_state() {|serv| serv.state == 'SHUTOFF'}
28
+ logger.debug "[DONE]\n\n"
29
+ logger.debug "Server #{@server_name} stopped...".green
30
+ else
31
+ raise "Server #{@server_name} does not exist!".red
32
+ end
33
+ end
34
+
35
+ def start
36
+ if @server
37
+ logger.debug "Starting #{@server_name}"
38
+ @server.reboot 'HARD'
39
+ logger.debug "Waiting for ACTIVE state..."
40
+ wait_for_state() {|serv| serv.ready?}
41
+ logger.debug "[DONE]\n\n"
42
+ logger.debug "Server #{@server_name} started...".green
43
+ else
44
+ raise "Server #{@server_name} does not exist!".red
45
+ end
46
+ end
47
+
48
+ def destroy
49
+ if @server
50
+ logger.debug "Killing #{@server_name}"
51
+ @server.destroy
52
+ logger.debug "Server #{@server_name} destroyed...".green
53
+ else
54
+ raise "Server #{@server_name} does not exist!".red
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,288 @@
1
+ # Copyright 2015 Adaptavist.com Ltd.
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_relative './logging.rb'
16
+
17
+ module AvstCloud
18
+ class Task
19
+ include Logging
20
+ def initialize(debug = false)
21
+ @debug = debug
22
+ end
23
+ def execute(server)
24
+ raise 'Unimplemented...'
25
+ end
26
+ end
27
+
28
+ class SshTask < AvstCloud::Task
29
+ include Logging
30
+ def execute(server)
31
+ unless server.ip_address
32
+ logger.error 'Can not find host'.red
33
+ raise 'Can not find ip address, access_user or access_password'
34
+ end
35
+
36
+ unless server.access_user
37
+ logger.error 'Access user not found. Please provide username for this server.'.red
38
+ raise 'Access user not found. Please provide username for this server.'
39
+ end
40
+
41
+ unless server.access_password
42
+ logger.error 'Password not found. Please provide password or pem key for this server.'.red
43
+ raise 'Password not found. Please provide root_password in config. for this server.'
44
+ end
45
+
46
+ logger.debug "Using #{server.access_user}@#{server.ip_address} with #{server.access_password} to perform ssh task."
47
+ attempts = 1
48
+ success = false
49
+ max_attempts = 50
50
+ while attempts < max_attempts and !success
51
+ begin
52
+ Net::SSH.start(server.ip_address, server.access_user, :password => server.access_password, :keys => [server.access_password]) do |session|
53
+ ssh_command session
54
+ end
55
+ success = true
56
+ rescue Errno::ECONNREFUSED
57
+ logger.debug "Connection refused. Server may not have booted yet. Sleeping #{attempts}/#{max_attempts}"
58
+ sleep(10)
59
+ attempts=attempts+1
60
+ rescue Errno::ETIMEDOUT
61
+ logger.debug "Connection timed out. Server may not have booted yet. Sleeping #{attempts}/#{max_attempts}"
62
+ sleep(10)
63
+ attempts=attempts+1
64
+ end
65
+ end
66
+ unless success
67
+ logger.error 'Bootstrapping: failed to find server to connect to'
68
+ raise 'Bootstrapping: failed to find server to connect to'
69
+ end
70
+ end
71
+
72
+ def ssh_command(session)
73
+ raise 'Unimplemented...'
74
+ end
75
+ end
76
+
77
+ class SshCommandTask < AvstCloud::SshTask
78
+ include Logging
79
+
80
+ def initialize(cmds, debug = false, structured_log = false)
81
+ @cmds = cmds
82
+ @debug = debug
83
+ @structured_log = structured_log
84
+ end
85
+
86
+ def ssh_command(session)
87
+ Array(@cmds).each do |cmd|
88
+ next unless cmd
89
+ cmd.strip!
90
+ next if cmd == ""
91
+ logger.debug("Running command on server as root: sudo su -c \"#{cmd}\"")
92
+ start_time = Time.now
93
+
94
+ session.exec!("sudo su -c \"#{cmd}\"") do |ch, stream, data|
95
+ if @debug
96
+ logger.debug "Got this on the #{stream} stream: "
97
+ if @structured_log && logger.methods.include?(:log_structured_code)
98
+ logger.log_structured_code(data)
99
+ else
100
+ logger.debug(data)
101
+ end
102
+ end
103
+ end
104
+ total_time = Time.now - start_time
105
+ logger.debug("Completed in #{total_time} seconds")
106
+ end
107
+ end
108
+ end
109
+
110
+ # In case Requiretty is set in sudoers disable it for bootstrapping and provisioning
111
+ # for user that performs it
112
+ class DisableRequireTty < AvstCloud::SshTask
113
+ include Logging
114
+ def initialize(for_user)
115
+ @for_user = for_user
116
+ end
117
+ def ssh_command(session)
118
+ session.open_channel do |channel|
119
+ channel.request_pty do |ch, success|
120
+ raise 'Error requesting pty' unless success
121
+
122
+ ch.send_channel_request('shell') do |ch, success|
123
+ raise 'Error opening shell' unless success
124
+ end
125
+ end
126
+ channel.on_data do |ch, data|
127
+ if @debug
128
+ STDOUT.print data
129
+ end
130
+ end
131
+ channel.on_extended_data do |ch, type, data|
132
+ STDOUT.print "Error: #{data}\n"
133
+ end
134
+ channel.send_data("sudo su -c 'echo 'Defaults:#{@for_user}\\ \\!requiretty' >> /etc/sudoers'\n")
135
+ channel.send_data("exit\n")
136
+ session.loop
137
+ end
138
+ end
139
+ end
140
+
141
+ class WaitUntilReady < AvstCloud::SshTask
142
+ include Logging
143
+
144
+ def ssh_command(session)
145
+ session.open_channel do |channel|
146
+ channel.request_pty do |ch, success|
147
+ raise 'Error requesting pty' unless success
148
+
149
+ ch.send_channel_request("shell") do |ch, success|
150
+ raise 'Error opening shell' unless success
151
+ end
152
+ end
153
+ channel.on_data do |ch, data|
154
+ if @debug
155
+ STDOUT.print data
156
+ end
157
+ end
158
+ channel.on_extended_data do |ch, type, data|
159
+ STDOUT.print "Error: #{data}\n"
160
+ end
161
+ channel.send_data("echo \"ready\"\n")
162
+ channel.send_data("exit\n")
163
+ session.loop
164
+ end
165
+ end
166
+ end
167
+
168
+ class CapistranoDeploymentTask < AvstCloud::Task
169
+ include Logging
170
+
171
+ def initialize(git, branch, server_tmp_folder = "/tmp/avst_cloud_tmp_#{Time.now.to_i}", reference = nil, custom_provisioning_commands = [], puppet_runner = nil, puppet_runner_prepare = nil, destination_folder = '/var/opt/puppet')
172
+ unless git and (branch or reference)
173
+ logger.debug "You have to provide git repo url #{git} and git branch #{branch} or git tag reference #{reference}".red
174
+ raise "You have to provide git repo url #{git} and git branch #{branch} or git tag reference #{reference}"
175
+ end
176
+
177
+ @git = git
178
+ @branch = branch
179
+ @server_tmp_folder = server_tmp_folder
180
+ @reference = reference
181
+ @custom_provisioning_commands = custom_provisioning_commands || []
182
+ @puppet_runner = puppet_runner
183
+ @puppet_runner_prepare = puppet_runner_prepare
184
+ @destination_folder = destination_folder || '/var/opt/puppet'
185
+ end
186
+
187
+ def execute(server)
188
+ unless server.ip_address
189
+ logger.error 'Can not find host'.red
190
+ raise 'Can not find ip address, access_user or access_password'
191
+ end
192
+
193
+ unless server.access_user
194
+ logger.error 'Access user not found. Please provide username for this server.'.red
195
+ raise 'Access user not found. Please provide username for this server.'
196
+ end
197
+
198
+ unless server.access_password
199
+ logger.error 'Password not found. Please provide password or pem key for this server.'.red
200
+ raise 'Password not found. Please provide root_password in config. for this server.'
201
+ end
202
+
203
+ logger.debug "Using #{server.access_user}@#{server.ip_address} with #{server.access_password}"
204
+
205
+
206
+ # Initiate capistrano deploy script to download the laters code and provision the server
207
+ require 'capistrano/all'
208
+ require 'capistrano/setup'
209
+ require 'capistrano/deploy'
210
+ Dir.glob("#{File.dirname __dir__}/capistrano/tasks/*.rake").each { |r| load r }
211
+ # cap production deploy
212
+ ENV['cap_git_repo_url'] = @git
213
+ ENV['cap_branch_name'] = @branch
214
+ ENV['cap_reference_name'] = @reference
215
+ ENV['cap_ip_address'] = server.ip_address
216
+ ENV['cap_access_password'] = server.access_password
217
+ ENV['cap_access_user'] = server.access_user
218
+ ENV['server_name'] = server.server_name
219
+ ENV['puppet_runner'] = @puppet_runner
220
+ ENV['puppet_runner_prepare'] = @puppet_runner_prepare
221
+ ENV['avst_cloud_tmp_folder'] = @server_tmp_folder
222
+ ENV['custom_provisioning_commands'] = @custom_provisioning_commands.to_json
223
+ ENV['destination_folder'] = @destination_folder
224
+ logger.debug "Using git #{@git} branch #{@branch} to provision #{server.ip_address}"
225
+
226
+ Capistrano::Application.invoke('production')
227
+ Capistrano::Application.invoke('deploy')
228
+ logger.debug "You can connect to server on #{server.ip_address}"
229
+ end
230
+ end
231
+
232
+ class PostProvisionCleanup < AvstCloud::SshCommandTask
233
+
234
+ def initialize(os, debug, tmp_folder = "/tmp/avst_cloud_tmp_#{Time.now.to_i}")
235
+ super(make_commands(os, tmp_folder), debug, false)
236
+ end
237
+
238
+ def make_commands(os, tmp_folder)
239
+ cmds = []
240
+ case os
241
+ when /ubuntu/, /debian/
242
+ cmds << 'apt-get clean'
243
+
244
+ when /centos/, /redhat/
245
+ cmds << 'yum clean all'
246
+ end
247
+ cmds << "rm -rf #{tmp_folder}"
248
+ cmds
249
+ end
250
+ end
251
+
252
+ class ScpTask < AvstCloud::Task
253
+ include Logging
254
+
255
+ def initialize(files)
256
+ @files = files
257
+ end
258
+
259
+ def execute(server)
260
+ unless server.ip_address
261
+ logger.error 'Can not find host'.red
262
+ raise 'Can not find ip address, access_user or access_password'
263
+ end
264
+
265
+ unless server.access_user
266
+ logger.error 'Access user not found. Please provide username for this server.'.red
267
+ raise 'Access user not found. Please provide username for this server.'
268
+ end
269
+
270
+ unless server.access_password
271
+ logger.error 'Password not found. Please provide password or pem key for this server.'.red
272
+ raise 'Password not found. Please provide root_password in config. for this server.'
273
+ end
274
+
275
+ logger.debug "Using #{server.access_user}@#{server.ip_address} with #{server.access_password}"
276
+ Net::SCP.start( server.ip_address, server.access_user, :password => server.access_password, :keys => [server.access_password] ) do |scp|
277
+ @files.each do |local_file, remote_path|
278
+ upload_file(scp, local_file, remote_path)
279
+ end
280
+ end
281
+ end
282
+
283
+ def upload_file(scp, local_path, remote_path)
284
+ logger.debug("Uploading file on server: #{local_path} to #{remote_path}")
285
+ scp.upload!( local_path, remote_path)
286
+ end
287
+ end
288
+ end