rubber 2.5.5 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +15 -0
- data/Gemfile.1.8.7 +1 -0
- data/lib/rubber/cloud/aws.rb +17 -11
- data/lib/rubber/cloud/base.rb +4 -0
- data/lib/rubber/cloud/fog.rb +30 -1
- data/lib/rubber/cloud/vsphere.rb +291 -0
- data/lib/rubber/recipes/rubber/instances.rb +2 -2
- data/lib/rubber/recipes/rubber/setup.rb +21 -2
- data/lib/rubber/recipes/rubber/volumes.rb +15 -14
- data/lib/rubber/version.rb +1 -1
- data/rubber.gemspec +1 -1
- data/templates/base/config/rubber/rubber-ruby.yml +1 -1
- data/templates/mysql/config/rubber/common/database.yml +1 -1
- metadata +3 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ec3be4c2c2b486ddd2528e9db6b72b96d1fbf2f
|
4
|
+
data.tar.gz: ad0afb86cac74f88bc397e87a851434015d6683c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1184ac231a4cbdaad613d17749e53bf4a993d6affae6830ffd0b65a1ea9ea7af9a2a2965e86cc0408344cb4625f97a8071a1d8ac9b27963490687ba53a20f280
|
7
|
+
data.tar.gz: 3f25823f1f87443b3d4f9f0b189e5c3572a74dd5deafd3cdc7368339168308b2d50181b3b717d33343308918049e3742ada873919d1c17e051ced82914efb3bd
|
data/CHANGELOG
CHANGED
@@ -1,9 +1,24 @@
|
|
1
|
+
2.6.0 (11/05/2013)
|
2
|
+
|
3
|
+
New Features:
|
4
|
+
============
|
5
|
+
|
6
|
+
[core] Added a new provider for vSphere. See https://github.com/rubber/rubber/wiki/Providers for configuration details.
|
7
|
+
|
8
|
+
Improvements:
|
9
|
+
============
|
10
|
+
|
11
|
+
[base] Upgraded to ruby-build 20131030 <214423d>
|
12
|
+
[base] Enhances database.yml to respond to active environment, not just 'production' <3843caf>
|
13
|
+
|
14
|
+
|
1
15
|
2.5.5 (10/16/2013)
|
2
16
|
|
3
17
|
New Features:
|
4
18
|
============
|
5
19
|
|
6
20
|
[base, core, postgresql] Added a uniform way of handling private network address blocks <61c5e0c>
|
21
|
+
[core] Added cleanup hook for 'vagrant destroy' for Vagrant version >= 1.3.0. <2a3c441>
|
7
22
|
|
8
23
|
Improvements:
|
9
24
|
============
|
data/Gemfile.1.8.7
CHANGED
data/lib/rubber/cloud/aws.rb
CHANGED
@@ -301,21 +301,27 @@ module Rubber
|
|
301
301
|
groups
|
302
302
|
end
|
303
303
|
|
304
|
-
def create_volume(
|
305
|
-
volume = @compute_provider.volumes.create(:size => size
|
306
|
-
|
304
|
+
def create_volume(instance, volume_spec)
|
305
|
+
volume = @compute_provider.volumes.create(:size => volume_spec['size'], :availability_zone => volume_spec['zone'])
|
306
|
+
volume.id
|
307
307
|
end
|
308
308
|
|
309
|
-
def
|
309
|
+
def after_create_volume(instance, volume_id, volume_spec)
|
310
|
+
# After we create an EBS volume, we need to attach it to the instance.
|
310
311
|
volume = @compute_provider.volumes.get(volume_id)
|
311
|
-
server = @compute_provider.servers.get(instance_id)
|
312
|
+
server = @compute_provider.servers.get(instance.instance_id)
|
312
313
|
volume.device = device
|
313
314
|
volume.server = server
|
314
315
|
end
|
315
316
|
|
316
|
-
def
|
317
|
+
def before_destroy_volume(volume_id)
|
318
|
+
# Before we can destroy an EBS volume, we must detach it from any running instances.
|
317
319
|
volume = @compute_provider.volumes.get(volume_id)
|
318
|
-
|
320
|
+
volume.force_detach
|
321
|
+
end
|
322
|
+
|
323
|
+
def destroy_volume(volume_id)
|
324
|
+
@compute_provider.volumes.get(volume_id).destroy
|
319
325
|
end
|
320
326
|
|
321
327
|
def describe_volumes(volume_id=nil)
|
@@ -323,21 +329,21 @@ module Rubber
|
|
323
329
|
opts = {}
|
324
330
|
opts[:'volume-id'] = volume_id if volume_id
|
325
331
|
response = @compute_provider.volumes.all(opts)
|
332
|
+
|
326
333
|
response.each do |item|
|
327
334
|
volume = {}
|
328
335
|
volume[:id] = item.id
|
329
336
|
volume[:status] = item.state
|
337
|
+
|
330
338
|
if item.server_id
|
331
339
|
volume[:attachment_instance_id] = item.server_id
|
332
340
|
volume[:attachment_status] = item.attached_at ? "attached" : "waiting"
|
333
341
|
end
|
342
|
+
|
334
343
|
volumes << volume
|
335
344
|
end
|
336
|
-
return volumes
|
337
|
-
end
|
338
345
|
|
339
|
-
|
340
|
-
@compute_provider.volumes.get(volume_id).destroy
|
346
|
+
volumes
|
341
347
|
end
|
342
348
|
|
343
349
|
# resource_id is any Amazon resource ID (e.g., instance ID or volume ID)
|
data/lib/rubber/cloud/base.rb
CHANGED
data/lib/rubber/cloud/fog.rb
CHANGED
@@ -31,7 +31,8 @@ module Rubber
|
|
31
31
|
:flavor_id => ami_type,
|
32
32
|
:groups => security_groups,
|
33
33
|
:availability_zone => availability_zone,
|
34
|
-
:key_name => env.key_name
|
34
|
+
:key_name => env.key_name,
|
35
|
+
:name => instance_alias)
|
35
36
|
|
36
37
|
response.id
|
37
38
|
end
|
@@ -120,6 +121,34 @@ module Rubber
|
|
120
121
|
def describe_load_balancers(name=nil)
|
121
122
|
raise NotImplementedError, "describe_load_balancers not implemented in generic fog adapter"
|
122
123
|
end
|
124
|
+
|
125
|
+
def before_create_volume(instance, volume_spec)
|
126
|
+
# No-op by default.
|
127
|
+
end
|
128
|
+
|
129
|
+
def create_volume(instance, volume_spec)
|
130
|
+
# No-op by default.
|
131
|
+
end
|
132
|
+
|
133
|
+
def after_create_volume(instance, volume_id, volume_spec)
|
134
|
+
# No-op by default.
|
135
|
+
end
|
136
|
+
|
137
|
+
def before_destroy_volume(volume_id)
|
138
|
+
# No-op by default.
|
139
|
+
end
|
140
|
+
|
141
|
+
def destroy_volume(volume_id)
|
142
|
+
# No-op by default.
|
143
|
+
end
|
144
|
+
|
145
|
+
def after_destroy_volume(volume_id)
|
146
|
+
# No-op by default.
|
147
|
+
end
|
148
|
+
|
149
|
+
def should_destroy_volume_when_instance_destroyed?
|
150
|
+
false
|
151
|
+
end
|
123
152
|
end
|
124
153
|
|
125
154
|
end
|
@@ -0,0 +1,291 @@
|
|
1
|
+
require 'rubber/cloud/fog'
|
2
|
+
|
3
|
+
module Rubber
|
4
|
+
module Cloud
|
5
|
+
class Vsphere < Fog
|
6
|
+
def initialize(env, capistrano)
|
7
|
+
compute_credentials = {
|
8
|
+
:provider => 'vsphere',
|
9
|
+
:vsphere_username => env.vcenter_username,
|
10
|
+
:vsphere_password => env.vcenter_password,
|
11
|
+
:vsphere_server => env.vcenter_host,
|
12
|
+
:vsphere_expected_pubkey_hash => env.expected_pubkey_hash
|
13
|
+
}
|
14
|
+
|
15
|
+
if env.cloud_providers && env.cloud_providers.aws
|
16
|
+
storage_credentials = {
|
17
|
+
:provider => 'AWS',
|
18
|
+
:aws_access_key_id => env.cloud_providers.aws.access_key,
|
19
|
+
:aws_secret_access_key => env.cloud_providers.aws.secret_access_key
|
20
|
+
}
|
21
|
+
|
22
|
+
storage_credentials[:region] = env.cloud_providers.aws.region
|
23
|
+
|
24
|
+
env['storage_credentials'] = storage_credentials
|
25
|
+
end
|
26
|
+
|
27
|
+
env['compute_credentials'] = compute_credentials
|
28
|
+
super(env, capistrano)
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_instance(instance_alias, image_name, image_type, security_groups, availability_zone, datacenter)
|
32
|
+
if env.domain.nil?
|
33
|
+
raise "'domain' value must be configured"
|
34
|
+
end
|
35
|
+
|
36
|
+
rubber_cfg = Rubber::Configuration.get_configuration(Rubber.env)
|
37
|
+
host_env = rubber_cfg.environment.bind(nil, instance_alias)
|
38
|
+
|
39
|
+
if host_env.public_nic.nil? && host_env.private_nic.nil?
|
40
|
+
raise "You must configure a private or a public NIC for this host in your rubber YAML"
|
41
|
+
end
|
42
|
+
|
43
|
+
if host_env.public_nic && env.public_network_name.nil?
|
44
|
+
raise "You must configure the 'public_network_name' in the provider configuration"
|
45
|
+
end
|
46
|
+
|
47
|
+
if host_env.private_nic && env.private_network_name.nil?
|
48
|
+
raise "You must configure the 'private_network_name' in the provider configuration"
|
49
|
+
end
|
50
|
+
|
51
|
+
nics = []
|
52
|
+
|
53
|
+
if host_env.public_nic
|
54
|
+
nic = nic_to_vsphere_config(host_env.public_nic, env.public_nic || {})
|
55
|
+
validate_nic_vsphere_config(nic, :public)
|
56
|
+
nics << nic
|
57
|
+
end
|
58
|
+
|
59
|
+
if host_env.private_nic
|
60
|
+
nic = nic_to_vsphere_config(host_env.private_nic, env.private_nic || {})
|
61
|
+
validate_nic_vsphere_config(nic, :private)
|
62
|
+
nics << nic
|
63
|
+
end
|
64
|
+
|
65
|
+
vm_clone_options = {
|
66
|
+
'datacenter' => datacenter,
|
67
|
+
'template_path' => image_name,
|
68
|
+
'name' => instance_alias,
|
69
|
+
'power_on' => false
|
70
|
+
}
|
71
|
+
|
72
|
+
if host_env.memory
|
73
|
+
vm_clone_options['memoryMB'] = host_env.memory
|
74
|
+
end
|
75
|
+
|
76
|
+
if host_env.cpus
|
77
|
+
vm_clone_options['numCPUs'] = host_env.cpus
|
78
|
+
end
|
79
|
+
|
80
|
+
vm = compute_provider.vm_clone(vm_clone_options)
|
81
|
+
|
82
|
+
server = compute_provider.servers.get(vm['new_vm']['id'])
|
83
|
+
|
84
|
+
# Destroy all existing NICs. We need the public and private IPs to line up with the NICs attached to the
|
85
|
+
# correct virtual switches. Rather than take the cross-product and try to work that out, it's easier to
|
86
|
+
# just start fresh and guarantee everything works as intended.
|
87
|
+
server.interfaces.each(&:destroy)
|
88
|
+
|
89
|
+
server.interfaces.create(:network => env.public_network_name) if host_env.public_nic
|
90
|
+
server.interfaces.create(:network => env.private_network_name) if host_env.private_nic
|
91
|
+
|
92
|
+
vm_ref = compute_provider.send(:get_vm_ref, server.id)
|
93
|
+
vm_ref.CustomizeVM_Task(:spec => customization_spec(instance_alias, nics))
|
94
|
+
|
95
|
+
server.start
|
96
|
+
|
97
|
+
vm['new_vm']['id']
|
98
|
+
end
|
99
|
+
|
100
|
+
def describe_instances(instance_id=nil)
|
101
|
+
instances = []
|
102
|
+
opts = {}
|
103
|
+
|
104
|
+
if instance_id
|
105
|
+
response = [compute_provider.servers.get(instance_id)]
|
106
|
+
else
|
107
|
+
response = compute_provider.servers.all(opts)
|
108
|
+
end
|
109
|
+
|
110
|
+
response.each do |item|
|
111
|
+
rubber_cfg = Rubber::Configuration.get_configuration(Rubber.env)
|
112
|
+
host_env = rubber_cfg.environment.bind(nil, item.name)
|
113
|
+
|
114
|
+
instance = {}
|
115
|
+
instance[:id] = item.id
|
116
|
+
instance[:state] = item.tools_state
|
117
|
+
|
118
|
+
# We can't trust the describe operation when the instance is newly created because the VM customization
|
119
|
+
# step likely hasn't completed yet. This means we'll get back the IP address for the VM template, rather
|
120
|
+
# than the one we just configured.
|
121
|
+
if host_env.public_nic
|
122
|
+
instance[:external_ip] = host_env.public_nic.ip_address
|
123
|
+
|
124
|
+
if host_env.private_nic.nil?
|
125
|
+
instance[:internal_ip] = host_env.public_nic.ip_address
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
if host_env.private_nic
|
130
|
+
instance[:internal_ip] = host_env.private_nic.ip_address
|
131
|
+
|
132
|
+
if host_env.public_nic.nil?
|
133
|
+
instance[:external_ip] = host_env.private_nic.ip_address
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
instance[:region_id] = item.datacenter
|
138
|
+
instance[:provider] = 'vsphere'
|
139
|
+
instance[:platform] = 'linux'
|
140
|
+
instances << instance
|
141
|
+
end
|
142
|
+
|
143
|
+
return instances
|
144
|
+
end
|
145
|
+
|
146
|
+
def active_state
|
147
|
+
'toolsOk'
|
148
|
+
end
|
149
|
+
|
150
|
+
def create_volume(instance, volume_spec)
|
151
|
+
server = @compute_provider.servers.get(instance.instance_id)
|
152
|
+
datastore = volume_spec['datastore']
|
153
|
+
thin_disk = volume_spec.has_key?('thin') ? volume_spec['thin'] : true
|
154
|
+
|
155
|
+
# This craziness here is so we can map the device name to an appropriate SCSI channel index, which is zero-based.
|
156
|
+
# E.g., /dev/sdc would correspond to a unit_number of 2. We do this by chopping off the SCSI device letter and
|
157
|
+
# then doing some ASCII value math to convert to the appropriate decimal value.
|
158
|
+
unit_number = volume_spec['device'][-1].ord - 97
|
159
|
+
|
160
|
+
config = { :size_gb => volume_spec['size'], :unit_number => unit_number }
|
161
|
+
|
162
|
+
if datastore
|
163
|
+
config[:datastore] = datastore
|
164
|
+
end
|
165
|
+
|
166
|
+
unless thin_disk
|
167
|
+
eager_zero = volume_spec.has_key?('eager_zero') ? volume_spec['eager_zero'] : false
|
168
|
+
|
169
|
+
config[:thin] = false
|
170
|
+
config[:eager_zero] = eager_zero
|
171
|
+
end
|
172
|
+
|
173
|
+
volume = server.volumes.create(config)
|
174
|
+
|
175
|
+
volume.id
|
176
|
+
end
|
177
|
+
|
178
|
+
def destroy_volume(volume_id)
|
179
|
+
# TODO (nirvdrum 10/28/13): Fog currently lacks the ability to fetch a volume by ID, so we need to fetch all volumes for all servers to find the volume we want. This is terribly inefficient and fog should be updated.
|
180
|
+
volume = @compute_provider.servers.collect { |s| s.volumes.all }.flatten.find { |v| v.id == volume_id }
|
181
|
+
|
182
|
+
if volume.unit_number == 0
|
183
|
+
raise "Cannot destroy volume because it is the VM root device. Destroy the VM if you really want to free this volume."
|
184
|
+
end
|
185
|
+
|
186
|
+
volume.destroy
|
187
|
+
end
|
188
|
+
|
189
|
+
def describe_volumes(volume_id=nil)
|
190
|
+
volumes = []
|
191
|
+
opts = {}
|
192
|
+
opts[:'volume-id'] = volume_id if volume_id
|
193
|
+
|
194
|
+
if volume_id
|
195
|
+
response = [@compute_provider.servers.collect { |s| s.volumes.all }.flatten.find { |v| v.id == volume_id }]
|
196
|
+
else
|
197
|
+
response = @compute_provider.servers.collect { |s| s.volumes.all }.flatten
|
198
|
+
end
|
199
|
+
|
200
|
+
response.each do |item|
|
201
|
+
volume = {}
|
202
|
+
volume[:id] = item.id
|
203
|
+
volume[:status] = item.unit_number == 0 ? 'root' : 'extra'
|
204
|
+
|
205
|
+
if item.server_id
|
206
|
+
volume[:attachment_instance_id] = item.server_id
|
207
|
+
volume[:attachment_status] = Thread.current[:detach_volume] == item.id ? 'detached' : 'attached'
|
208
|
+
end
|
209
|
+
|
210
|
+
volumes << volume
|
211
|
+
end
|
212
|
+
|
213
|
+
volumes
|
214
|
+
end
|
215
|
+
|
216
|
+
def should_destroy_volume_when_instance_destroyed?
|
217
|
+
true
|
218
|
+
end
|
219
|
+
|
220
|
+
def should_disable_password_based_ssh_login?
|
221
|
+
true
|
222
|
+
end
|
223
|
+
|
224
|
+
private
|
225
|
+
|
226
|
+
def validate_nic_vsphere_config(nic_config, type)
|
227
|
+
%w[ip subnetMask dnsServerList].each do |attr|
|
228
|
+
if nic_config[attr].nil?
|
229
|
+
raise "Missing '#{attr}' for #{type} NIC configuaration"
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
nic_config
|
234
|
+
end
|
235
|
+
|
236
|
+
def nic_to_vsphere_config(nic, default_nic)
|
237
|
+
hash = {
|
238
|
+
'ip' => nic['ip_address'],
|
239
|
+
'subnetMask' => nic['subnet_mask'] || default_nic['subnet_mask'],
|
240
|
+
'dnsServerList' => nic['dns_servers'] || default_nic['dns_servers']
|
241
|
+
}
|
242
|
+
|
243
|
+
# We want to allow overriding the gateway on a per-host basis by setting the value to nil. As such, we
|
244
|
+
# can't fall back to the default config just because the value is nil.
|
245
|
+
if nic.has_key?('gateway')
|
246
|
+
|
247
|
+
# Null values are represented as "null" in YAML, but Rubyists tend to use "nil", which will get translated
|
248
|
+
# to the literal String "nil". Which guarding against this is arguably bad, letting "nil" go through as a valid
|
249
|
+
# gateway value is even worse.
|
250
|
+
puts "\n\nGateway: #{nic['gateway']}\n\n"
|
251
|
+
if nic['gateway'] && nic['gateway'] != 'nil'
|
252
|
+
hash['gateway'] = [nic['gateway']]
|
253
|
+
end
|
254
|
+
|
255
|
+
elsif default_nic['gateway']
|
256
|
+
hash['gateway'] = [default_nic['gateway']]
|
257
|
+
end
|
258
|
+
|
259
|
+
hash
|
260
|
+
end
|
261
|
+
|
262
|
+
def customization_spec(instance_alias, ip_settings)
|
263
|
+
nics = []
|
264
|
+
|
265
|
+
ip_settings.each do |nic|
|
266
|
+
custom_ip_settings = RbVmomi::VIM::CustomizationIPSettings.new(nic)
|
267
|
+
custom_ip_settings.ip = RbVmomi::VIM::CustomizationFixedIp("ipAddress" => nic['ip'])
|
268
|
+
custom_ip_settings.dnsDomain = env.domain
|
269
|
+
|
270
|
+
nics << custom_ip_settings
|
271
|
+
end
|
272
|
+
|
273
|
+
custom_global_ip_settings = RbVmomi::VIM::CustomizationGlobalIPSettings.new
|
274
|
+
custom_global_ip_settings.dnsServerList = nics.first.dnsServerList
|
275
|
+
custom_global_ip_settings.dnsSuffixList = [env.domain]
|
276
|
+
|
277
|
+
custom_adapter_mapping = nics.collect { |nic| RbVmomi::VIM::CustomizationAdapterMapping.new("adapter" => nic) }
|
278
|
+
|
279
|
+
custom_prep = RbVmomi::VIM::CustomizationLinuxPrep.new(
|
280
|
+
:domain => env.domain,
|
281
|
+
:hostName => RbVmomi::VIM::CustomizationFixedName.new(:name => instance_alias))
|
282
|
+
|
283
|
+
puts "Adapters: #{custom_adapter_mapping}"
|
284
|
+
|
285
|
+
RbVmomi::VIM::CustomizationSpec.new(:identity => custom_prep,
|
286
|
+
:globalIPSettings => custom_global_ip_settings,
|
287
|
+
:nicSettingMap => custom_adapter_mapping)
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
@@ -440,8 +440,8 @@ namespace :rubber do
|
|
440
440
|
end
|
441
441
|
|
442
442
|
if instance_item.volumes
|
443
|
-
value = Capistrano::CLI.ui.ask("Instance has persistent volumes, do you want to destroy them? [y/N]?: ") unless force
|
444
|
-
if value =~ /^y/ || force
|
443
|
+
value = Capistrano::CLI.ui.ask("Instance has persistent volumes, do you want to destroy them? [y/N]?: ") unless force || cloud.should_destroy_volume_when_instance_destroyed?
|
444
|
+
if value =~ /^y/ || force || cloud.should_destroy_volume_when_instance_destroyed?
|
445
445
|
instance_item.volumes.clone.each do |volume_id|
|
446
446
|
destroy_volume(volume_id)
|
447
447
|
end
|
@@ -26,7 +26,15 @@ namespace :rubber do
|
|
26
26
|
# We special-case the 'ubuntu' user since the Canonical AMIs on EC2 don't set the password for
|
27
27
|
# this account, making any password prompt potentially confusing.
|
28
28
|
orig_password = fetch(:password)
|
29
|
-
|
29
|
+
initial_ssh_password = fetch(:initial_ssh_password, nil)
|
30
|
+
|
31
|
+
if initial_ssh_user == 'ubuntu' || ENV.has_key?('RUN_FROM_VAGRANT')
|
32
|
+
set(:password, nil)
|
33
|
+
elsif initial_ssh_password
|
34
|
+
set(:password, initial_ssh_password)
|
35
|
+
else
|
36
|
+
set(:password, Capistrano::CLI.password_prompt("Password for #{initial_ssh_user} @ #{ip}: "))
|
37
|
+
end
|
30
38
|
|
31
39
|
task :_ensure_key_file_present, :hosts => "#{initial_ssh_user}@#{ip}" do
|
32
40
|
public_key_filename = "#{cloud.env.key_file}.pub"
|
@@ -50,9 +58,19 @@ namespace :rubber do
|
|
50
58
|
rsudo "mkdir -p /root/.ssh && cp /home/#{initial_ssh_user}/.ssh/authorized_keys /root/.ssh/"
|
51
59
|
end
|
52
60
|
|
61
|
+
task :_disable_password_based_ssh_login, :hosts => "#{initial_ssh_user}@#{ip}" do
|
62
|
+
rubber.sudo_script 'disable_password_based_ssh_login', <<-ENDSCRIPT
|
63
|
+
if ! grep -q 'PasswordAuthentication no' /etc/ssh/sshd_config; then
|
64
|
+
echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config
|
65
|
+
service ssh restart
|
66
|
+
fi
|
67
|
+
ENDSCRIPT
|
68
|
+
end
|
69
|
+
|
53
70
|
begin
|
54
71
|
_ensure_key_file_present
|
55
72
|
_allow_root_ssh
|
73
|
+
_disable_password_based_ssh_login if cloud.should_disable_password_based_ssh_login?
|
56
74
|
rescue ConnectionError => e
|
57
75
|
if e.message =~ /Net::SSH::AuthenticationFailed/
|
58
76
|
logger.info "Can't connect as user #{initial_ssh_user} to #{ip}, assuming root allowed"
|
@@ -332,7 +350,8 @@ namespace :rubber do
|
|
332
350
|
core_packages = [
|
333
351
|
'python-software-properties', # Needed for add-apt-repository, which we use for adding PPAs.
|
334
352
|
'bc', # Needed for comparing version numbers in bash, which we do for various setup functions.
|
335
|
-
'update-notifier-common'
|
353
|
+
'update-notifier-common', # Needed for notifying us when a package upgrade requires a reboot.
|
354
|
+
'scsitools' # Needed to rescan SCSI channels for any added devices.
|
336
355
|
]
|
337
356
|
|
338
357
|
rsudo "apt-get -q update"
|
@@ -38,6 +38,10 @@ namespace :rubber do
|
|
38
38
|
setup_lvm_group(ic, lvm_volume_group_spec)
|
39
39
|
end
|
40
40
|
end
|
41
|
+
|
42
|
+
# The act of setting up volumes might blow away previously deployed code, so reset the update state so it can
|
43
|
+
# be deployed again if needed.
|
44
|
+
set :rubber_code_was_updated, false
|
41
45
|
end
|
42
46
|
|
43
47
|
desc <<-DESC
|
@@ -72,26 +76,18 @@ namespace :rubber do
|
|
72
76
|
detach_volume(volume_id)
|
73
77
|
end
|
74
78
|
|
75
|
-
def create_volume(size, zone)
|
76
|
-
volumeId = cloud.create_volume(size.to_s, zone)
|
77
|
-
fatal "Failed to create volume" if volumeId.nil?
|
78
|
-
return volumeId
|
79
|
-
end
|
80
|
-
|
81
|
-
def attach_volume(vol_id, instance_id, device)
|
82
|
-
cloud.attach_volume(vol_id, instance_id, device)
|
83
|
-
end
|
84
|
-
|
85
79
|
def setup_volume(ic, vol_spec)
|
86
80
|
created = nil
|
87
81
|
key = "#{ic.name}_#{vol_spec['device']}"
|
88
82
|
artifacts = rubber_instances.artifacts
|
89
83
|
vol_id = artifacts['volumes'][key]
|
90
84
|
|
85
|
+
cloud.before_create_volume(ic, vol_spec)
|
86
|
+
|
91
87
|
# first create the volume if we don't have a global record (artifacts) for it
|
92
88
|
if ! vol_id
|
93
89
|
logger.info "Creating volume for #{ic.full_name}:#{vol_spec['device']}"
|
94
|
-
vol_id = create_volume(
|
90
|
+
vol_id = cloud.create_volume(ic, vol_spec)
|
95
91
|
artifacts['volumes'][key] = vol_id
|
96
92
|
rubber_instances.save
|
97
93
|
created = vol_spec['device']
|
@@ -101,7 +97,7 @@ namespace :rubber do
|
|
101
97
|
ic.volumes ||= []
|
102
98
|
if ! ic.volumes.include?(vol_id)
|
103
99
|
logger.info "Attaching volume #{vol_id} to #{ic.full_name}:#{vol_spec['device']}"
|
104
|
-
|
100
|
+
cloud.after_create_volume(ic, vol_id, vol_spec)
|
105
101
|
ic.volumes << vol_id
|
106
102
|
rubber_instances.save
|
107
103
|
|
@@ -119,13 +115,16 @@ namespace :rubber do
|
|
119
115
|
# then format/mount/etc if we don't have an entry in hosts file
|
120
116
|
task :_setup_volume, :hosts => ic.external_ip do
|
121
117
|
rubber.sudo_script 'setup_volume', <<-ENDSCRIPT
|
118
|
+
# Make sure the newly added volume was found.
|
119
|
+
rescan-scsi-bus || true
|
120
|
+
|
122
121
|
if ! grep -q '#{vol_spec['mount']}' /etc/fstab; then
|
123
122
|
if mount | grep -q '#{vol_spec['mount']}'; then
|
124
123
|
umount '#{vol_spec['mount']}'
|
125
124
|
fi
|
126
125
|
mv /etc/fstab /etc/fstab.bak
|
127
126
|
cat /etc/fstab.bak | grep -v '#{vol_spec['mount']}' > /etc/fstab
|
128
|
-
if [ `lsb_release -r -s | sed 's/[.].*//'` -gt "10" ]; then
|
127
|
+
if [ #{rubber_env.cloud_provider == 'aws'} && `lsb_release -r -s | sed 's/[.].*//'` -gt "10" ]; then
|
129
128
|
device=`echo #{vol_spec['device']} | sed 's/sd/xvd/'`
|
130
129
|
else
|
131
130
|
device='#{vol_spec['device']}'
|
@@ -416,11 +415,13 @@ namespace :rubber do
|
|
416
415
|
end
|
417
416
|
|
418
417
|
def destroy_volume(volume_id)
|
419
|
-
|
418
|
+
cloud.before_destroy_volume(volume_id)
|
420
419
|
|
421
420
|
logger.info "Deleting volume #{volume_id}"
|
422
421
|
cloud.destroy_volume(volume_id) rescue logger.info("Volume did not exist in cloud")
|
423
422
|
|
423
|
+
cloud.after_destroy_volume(volume_id)
|
424
|
+
|
424
425
|
logger.info "Removing volume #{volume_id} from rubber instances file"
|
425
426
|
artifacts = rubber_instances.artifacts
|
426
427
|
artifacts['volumes'].delete_if {|k,v| v == volume_id}
|
data/lib/rubber/version.rb
CHANGED
data/rubber.gemspec
CHANGED
@@ -33,7 +33,7 @@ Gem::Specification.new do |s|
|
|
33
33
|
s.add_dependency 'thor'
|
34
34
|
s.add_dependency 'clamp'
|
35
35
|
s.add_dependency 'open4'
|
36
|
-
s.add_dependency 'fog', '~> 1.6'
|
36
|
+
s.add_dependency 'fog', '~> 1.6'
|
37
37
|
s.add_dependency 'json'
|
38
38
|
|
39
39
|
s.add_development_dependency('rake')
|
@@ -12,7 +12,7 @@ packages: [build-essential, git-core, subversion, curl, autoconf, bison, ruby, z
|
|
12
12
|
|
13
13
|
# REQUIRED: The version of ruby-build to use for building ruby.
|
14
14
|
# It must be one of the versions from https://github.com/sstephenson/ruby-build/blob/master/CHANGELOG.md
|
15
|
-
ruby_build_version:
|
15
|
+
ruby_build_version: 20131030
|
16
16
|
|
17
17
|
# REQUIRED: Set to the version string for the ruby version you wish to use
|
18
18
|
# Run "ruby-build --definitions" to see the list of possible options or look through the list of
|
@@ -3,7 +3,7 @@
|
|
3
3
|
%>
|
4
4
|
|
5
5
|
<%= Rubber.env %>:
|
6
|
-
adapter: <%= YAML::load(File.open("#{Rubber.root}/config/database.yml"))[
|
6
|
+
adapter: <%= YAML::load(File.open("#{Rubber.root}/config/database.yml"))[Rubber.env]["adapter"] %>
|
7
7
|
encoding: utf8
|
8
8
|
database: <%= rubber_env.db_name %>
|
9
9
|
username: <%= rubber_env.db_user %>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Conway
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-11-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: capistrano
|
@@ -88,9 +88,6 @@ dependencies:
|
|
88
88
|
- - ~>
|
89
89
|
- !ruby/object:Gem::Version
|
90
90
|
version: '1.6'
|
91
|
-
- - <
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: 1.16.0
|
94
91
|
type: :runtime
|
95
92
|
prerelease: false
|
96
93
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -98,9 +95,6 @@ dependencies:
|
|
98
95
|
- - ~>
|
99
96
|
- !ruby/object:Gem::Version
|
100
97
|
version: '1.6'
|
101
|
-
- - <
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: 1.16.0
|
104
98
|
- !ruby/object:Gem::Dependency
|
105
99
|
name: json
|
106
100
|
requirement: !ruby/object:Gem::Requirement
|
@@ -223,6 +217,7 @@ files:
|
|
223
217
|
- lib/rubber/cloud/fog_storage.rb
|
224
218
|
- lib/rubber/cloud/generic.rb
|
225
219
|
- lib/rubber/cloud/vagrant.rb
|
220
|
+
- lib/rubber/cloud/vsphere.rb
|
226
221
|
- lib/rubber/commands/config.rb
|
227
222
|
- lib/rubber/commands/cron.rb
|
228
223
|
- lib/rubber/commands/util.rb
|