rubber 2.5.5 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|