bosh_openstack_cpi 1.2539.0 → 1.2546.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/cloud/openstack/cloud.rb +102 -102
- data/lib/cloud/openstack/version.rb +1 -1
- metadata +10 -10
@@ -7,8 +7,8 @@ module Bosh::OpenStackCloud
|
|
7
7
|
class Cloud < Bosh::Cloud
|
8
8
|
include Helpers
|
9
9
|
|
10
|
-
BOSH_APP_DIR =
|
11
|
-
FIRST_DEVICE_NAME_LETTER =
|
10
|
+
BOSH_APP_DIR = '/var/vcap/bosh'
|
11
|
+
FIRST_DEVICE_NAME_LETTER = 'b'
|
12
12
|
|
13
13
|
attr_reader :openstack
|
14
14
|
attr_reader :registry
|
@@ -30,51 +30,51 @@ module Bosh::OpenStackCloud
|
|
30
30
|
|
31
31
|
@logger = Bosh::Clouds::Config.logger
|
32
32
|
|
33
|
-
@agent_properties = @options[
|
34
|
-
@openstack_properties = @options[
|
33
|
+
@agent_properties = @options['agent'] || {}
|
34
|
+
@openstack_properties = @options['openstack']
|
35
35
|
|
36
|
-
@default_key_name = @openstack_properties[
|
37
|
-
@default_security_groups = @openstack_properties[
|
38
|
-
@state_timeout = @openstack_properties[
|
39
|
-
@stemcell_public_visibility = @openstack_properties[
|
40
|
-
@wait_resource_poll_interval = @openstack_properties[
|
36
|
+
@default_key_name = @openstack_properties['default_key_name']
|
37
|
+
@default_security_groups = @openstack_properties['default_security_groups']
|
38
|
+
@state_timeout = @openstack_properties['state_timeout']
|
39
|
+
@stemcell_public_visibility = @openstack_properties['stemcell_public_visibility']
|
40
|
+
@wait_resource_poll_interval = @openstack_properties['wait_resource_poll_interval']
|
41
41
|
|
42
|
-
unless @openstack_properties[
|
43
|
-
@openstack_properties[
|
42
|
+
unless @openstack_properties['auth_url'].match(/\/tokens$/)
|
43
|
+
@openstack_properties['auth_url'] = @openstack_properties['auth_url'] + '/tokens'
|
44
44
|
end
|
45
45
|
|
46
46
|
openstack_params = {
|
47
|
-
:provider =>
|
48
|
-
:openstack_auth_url => @openstack_properties[
|
49
|
-
:openstack_username => @openstack_properties[
|
50
|
-
:openstack_api_key => @openstack_properties[
|
51
|
-
:openstack_tenant => @openstack_properties[
|
52
|
-
:openstack_region => @openstack_properties[
|
53
|
-
:openstack_endpoint_type => @openstack_properties[
|
47
|
+
:provider => 'OpenStack',
|
48
|
+
:openstack_auth_url => @openstack_properties['auth_url'],
|
49
|
+
:openstack_username => @openstack_properties['username'],
|
50
|
+
:openstack_api_key => @openstack_properties['api_key'],
|
51
|
+
:openstack_tenant => @openstack_properties['tenant'],
|
52
|
+
:openstack_region => @openstack_properties['region'],
|
53
|
+
:openstack_endpoint_type => @openstack_properties['endpoint_type'],
|
54
54
|
:connection_options => @openstack_properties['connection_options']
|
55
55
|
}
|
56
56
|
begin
|
57
57
|
@openstack = Fog::Compute.new(openstack_params)
|
58
58
|
rescue Exception => e
|
59
59
|
@logger.error(e)
|
60
|
-
cloud_error(
|
60
|
+
cloud_error('Unable to connect to the OpenStack Compute API. Check task debug log for details.')
|
61
61
|
end
|
62
62
|
|
63
63
|
glance_params = {
|
64
|
-
:provider =>
|
65
|
-
:openstack_auth_url => @openstack_properties[
|
66
|
-
:openstack_username => @openstack_properties[
|
67
|
-
:openstack_api_key => @openstack_properties[
|
68
|
-
:openstack_tenant => @openstack_properties[
|
69
|
-
:openstack_region => @openstack_properties[
|
70
|
-
:openstack_endpoint_type => @openstack_properties[
|
64
|
+
:provider => 'OpenStack',
|
65
|
+
:openstack_auth_url => @openstack_properties['auth_url'],
|
66
|
+
:openstack_username => @openstack_properties['username'],
|
67
|
+
:openstack_api_key => @openstack_properties['api_key'],
|
68
|
+
:openstack_tenant => @openstack_properties['tenant'],
|
69
|
+
:openstack_region => @openstack_properties['region'],
|
70
|
+
:openstack_endpoint_type => @openstack_properties['endpoint_type'],
|
71
71
|
:connection_options => @openstack_properties['connection_options']
|
72
72
|
}
|
73
73
|
begin
|
74
74
|
@glance = Fog::Image.new(glance_params)
|
75
75
|
rescue Exception => e
|
76
76
|
@logger.error(e)
|
77
|
-
cloud_error(
|
77
|
+
cloud_error('Unable to connect to the OpenStack Image Service API. Check task debug log for details.')
|
78
78
|
end
|
79
79
|
|
80
80
|
@metadata_lock = Mutex.new
|
@@ -100,16 +100,16 @@ module Bosh::OpenStackCloud
|
|
100
100
|
with_thread_name("create_stemcell(#{image_path}...)") do
|
101
101
|
begin
|
102
102
|
Dir.mktmpdir do |tmp_dir|
|
103
|
-
@logger.info(
|
103
|
+
@logger.info('Creating new image...')
|
104
104
|
image_params = {
|
105
105
|
:name => "BOSH-#{generate_unique_name}",
|
106
|
-
:disk_format => cloud_properties[
|
107
|
-
:container_format => cloud_properties[
|
106
|
+
:disk_format => cloud_properties['disk_format'],
|
107
|
+
:container_format => cloud_properties['container_format'],
|
108
108
|
:is_public => @stemcell_public_visibility.nil? ? false : @stemcell_public_visibility,
|
109
109
|
}
|
110
110
|
|
111
111
|
image_properties = {}
|
112
|
-
vanilla_options = [
|
112
|
+
vanilla_options = ['name', 'version', 'os_type', 'os_distro', 'architecture', 'auto_disk_config']
|
113
113
|
vanilla_options.reject{ |o| cloud_properties[o].nil? }.each do |key|
|
114
114
|
image_properties[key.to_sym] = cloud_properties[key]
|
115
115
|
end
|
@@ -118,13 +118,13 @@ module Bosh::OpenStackCloud
|
|
118
118
|
# If image_location is set in cloud properties, then pass the copy-from parm. Then Glance will fetch it
|
119
119
|
# from the remote location on a background job and store it in its repository.
|
120
120
|
# Otherwise, unpack image to temp directory and upload to Glance the root image.
|
121
|
-
if cloud_properties[
|
122
|
-
@logger.info("Using remote image from `#{cloud_properties[
|
123
|
-
image_params[:copy_from] = cloud_properties[
|
121
|
+
if cloud_properties['image_location']
|
122
|
+
@logger.info("Using remote image from `#{cloud_properties['image_location']}'...")
|
123
|
+
image_params[:copy_from] = cloud_properties['image_location']
|
124
124
|
else
|
125
125
|
@logger.info("Extracting stemcell file to `#{tmp_dir}'...")
|
126
126
|
unpack_image(tmp_dir, image_path)
|
127
|
-
image_params[:location] = File.join(tmp_dir,
|
127
|
+
image_params[:location] = File.join(tmp_dir, 'root.img')
|
128
128
|
end
|
129
129
|
|
130
130
|
# Upload image using Glance service
|
@@ -182,7 +182,7 @@ module Bosh::OpenStackCloud
|
|
182
182
|
def create_vm(agent_id, stemcell_id, resource_pool,
|
183
183
|
network_spec = nil, disk_locality = nil, environment = nil)
|
184
184
|
with_thread_name("create_vm(#{agent_id}, ...)") do
|
185
|
-
@logger.info(
|
185
|
+
@logger.info('Creating new server...')
|
186
186
|
server_name = "vm-#{generate_unique_name}"
|
187
187
|
|
188
188
|
network_configurator = NetworkConfigurator.new(network_spec)
|
@@ -201,8 +201,8 @@ module Bosh::OpenStackCloud
|
|
201
201
|
cloud_error("Image `#{stemcell_id}' not found") if image.nil?
|
202
202
|
@logger.debug("Using image: `#{stemcell_id}'")
|
203
203
|
|
204
|
-
flavor = with_openstack { @openstack.flavors.find { |f| f.name == resource_pool[
|
205
|
-
cloud_error("Flavor `#{resource_pool[
|
204
|
+
flavor = with_openstack { @openstack.flavors.find { |f| f.name == resource_pool['instance_type'] } }
|
205
|
+
cloud_error("Flavor `#{resource_pool['instance_type']}' not found") if flavor.nil?
|
206
206
|
if flavor_has_ephemeral_disk?(flavor)
|
207
207
|
if flavor.ram
|
208
208
|
# Ephemeral disk size should be at least the double of the vm total memory size, as agent will need:
|
@@ -210,14 +210,14 @@ module Bosh::OpenStackCloud
|
|
210
210
|
# - the rest for /vcar/vcap/data
|
211
211
|
min_ephemeral_size = (flavor.ram / 1024) * 2
|
212
212
|
if flavor.ephemeral < min_ephemeral_size
|
213
|
-
cloud_error("Flavor `#{resource_pool[
|
214
|
-
|
213
|
+
cloud_error("Flavor `#{resource_pool['instance_type']}' should have at least #{min_ephemeral_size}Gb " +
|
214
|
+
'of ephemeral disk')
|
215
215
|
end
|
216
216
|
end
|
217
217
|
end
|
218
|
-
@logger.debug("Using flavor: `#{resource_pool[
|
218
|
+
@logger.debug("Using flavor: `#{resource_pool['instance_type']}'")
|
219
219
|
|
220
|
-
keyname = resource_pool[
|
220
|
+
keyname = resource_pool['key_name'] || @default_key_name
|
221
221
|
keypair = with_openstack { @openstack.key_pairs.find { |k| k.name == keyname } }
|
222
222
|
cloud_error("Key-pair `#{keyname}' not found") if keypair.nil?
|
223
223
|
@logger.debug("Using key-pair: `#{keypair.name}' (#{keypair.fingerprint})")
|
@@ -231,12 +231,12 @@ module Bosh::OpenStackCloud
|
|
231
231
|
:nics => nics,
|
232
232
|
:user_data => Yajl::Encoder.encode(user_data(server_name, network_spec)),
|
233
233
|
:personality => [{
|
234
|
-
|
235
|
-
|
234
|
+
'path' => "#{BOSH_APP_DIR}/user_data.json",
|
235
|
+
'contents' => Yajl::Encoder.encode(user_data(server_name, network_spec, keypair.public_key))
|
236
236
|
}]
|
237
237
|
}
|
238
238
|
|
239
|
-
availability_zone = select_availability_zone(disk_locality, resource_pool[
|
239
|
+
availability_zone = select_availability_zone(disk_locality, resource_pool['availability_zone'])
|
240
240
|
server_params[:availability_zone] = availability_zone if availability_zone
|
241
241
|
|
242
242
|
@logger.debug("Using boot parms: `#{server_params.inspect}'")
|
@@ -335,7 +335,7 @@ module Bosh::OpenStackCloud
|
|
335
335
|
network_configurator.configure(@openstack, server)
|
336
336
|
|
337
337
|
update_agent_settings(server) do |settings|
|
338
|
-
settings[
|
338
|
+
settings['networks'] = network_spec
|
339
339
|
end
|
340
340
|
end
|
341
341
|
end
|
@@ -349,13 +349,13 @@ module Bosh::OpenStackCloud
|
|
349
349
|
# @return [String] OpenStack volume UUID
|
350
350
|
def create_disk(size, server_id = nil)
|
351
351
|
with_thread_name("create_disk(#{size}, #{server_id})") do
|
352
|
-
raise ArgumentError,
|
353
|
-
cloud_error(
|
354
|
-
cloud_error(
|
352
|
+
raise ArgumentError, 'Disk size needs to be an integer' unless size.kind_of?(Integer)
|
353
|
+
cloud_error('Minimum disk size is 1 GiB') if (size < 1024)
|
354
|
+
cloud_error('Maximum disk size is 1 TiB') if (size > 1024 * 1000)
|
355
355
|
|
356
356
|
volume_params = {
|
357
357
|
:name => "volume-#{generate_unique_name}",
|
358
|
-
:description =>
|
358
|
+
:description => '',
|
359
359
|
:size => (size / 1024.0).ceil
|
360
360
|
}
|
361
361
|
|
@@ -366,7 +366,7 @@ module Bosh::OpenStackCloud
|
|
366
366
|
end
|
367
367
|
end
|
368
368
|
|
369
|
-
@logger.info(
|
369
|
+
@logger.info('Creating new volume...')
|
370
370
|
volume = with_openstack { @openstack.volumes.create(volume_params) }
|
371
371
|
|
372
372
|
@logger.info("Creating new volume `#{volume.id}'...")
|
@@ -417,9 +417,9 @@ module Bosh::OpenStackCloud
|
|
417
417
|
device_name = attach_volume(server, volume)
|
418
418
|
|
419
419
|
update_agent_settings(server) do |settings|
|
420
|
-
settings[
|
421
|
-
settings[
|
422
|
-
settings[
|
420
|
+
settings['disks'] ||= {}
|
421
|
+
settings['disks']['persistent'] ||= {}
|
422
|
+
settings['disks']['persistent'][disk_id] = device_name
|
423
423
|
end
|
424
424
|
end
|
425
425
|
end
|
@@ -441,9 +441,9 @@ module Bosh::OpenStackCloud
|
|
441
441
|
detach_volume(server, volume)
|
442
442
|
|
443
443
|
update_agent_settings(server) do |settings|
|
444
|
-
settings[
|
445
|
-
settings[
|
446
|
-
settings[
|
444
|
+
settings['disks'] ||= {}
|
445
|
+
settings['disks']['persistent'] ||= {}
|
446
|
+
settings['disks']['persistent'].delete(disk_id)
|
447
447
|
end
|
448
448
|
end
|
449
449
|
end
|
@@ -461,7 +461,7 @@ module Bosh::OpenStackCloud
|
|
461
461
|
cloud_error("Volume `#{disk_id}' not found") unless volume
|
462
462
|
|
463
463
|
devices = []
|
464
|
-
volume.attachments.each { |attachment| devices << attachment[
|
464
|
+
volume.attachments.each { |attachment| devices << attachment['device'] unless attachment.empty? }
|
465
465
|
|
466
466
|
description = [:deployment, :job, :index].collect { |key| metadata[key] }
|
467
467
|
description << devices.first.split('/').last unless devices.empty?
|
@@ -566,7 +566,7 @@ module Bosh::OpenStackCloud
|
|
566
566
|
zones << default if default
|
567
567
|
zones.uniq!
|
568
568
|
cloud_error "can't use multiple availability zones: %s" %
|
569
|
-
zones.join(
|
569
|
+
zones.join(', ') unless zones.size == 1 || zones.empty?
|
570
570
|
end
|
571
571
|
|
572
572
|
private
|
@@ -588,12 +588,12 @@ module Bosh::OpenStackCloud
|
|
588
588
|
def user_data(server_name, network_spec, public_key = nil)
|
589
589
|
data = {}
|
590
590
|
|
591
|
-
data[
|
592
|
-
data[
|
593
|
-
data[
|
591
|
+
data['registry'] = { 'endpoint' => @registry.endpoint }
|
592
|
+
data['server'] = { 'name' => server_name }
|
593
|
+
data['openssh'] = { 'public_key' => public_key } if public_key
|
594
594
|
|
595
595
|
with_dns(network_spec) do |servers|
|
596
|
-
data[
|
596
|
+
data['dns'] = { 'nameserver' => servers }
|
597
597
|
end
|
598
598
|
|
599
599
|
data
|
@@ -606,8 +606,8 @@ module Bosh::OpenStackCloud
|
|
606
606
|
# @yield [Array]
|
607
607
|
def with_dns(network_spec)
|
608
608
|
network_spec.each_value do |properties|
|
609
|
-
if properties.has_key?(
|
610
|
-
yield properties[
|
609
|
+
if properties.has_key?('dns') && !properties['dns'].nil?
|
610
|
+
yield properties['dns']
|
611
611
|
return
|
612
612
|
end
|
613
613
|
end
|
@@ -631,19 +631,19 @@ module Bosh::OpenStackCloud
|
|
631
631
|
# @return [Hash] Agent settings
|
632
632
|
def initial_agent_settings(server_name, agent_id, network_spec, environment, has_ephemeral)
|
633
633
|
settings = {
|
634
|
-
|
635
|
-
|
634
|
+
'vm' => {
|
635
|
+
'name' => server_name
|
636
636
|
},
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
637
|
+
'agent_id' => agent_id,
|
638
|
+
'networks' => network_spec,
|
639
|
+
'disks' => {
|
640
|
+
'system' => '/dev/sda',
|
641
|
+
'persistent' => {}
|
642
642
|
}
|
643
643
|
}
|
644
644
|
|
645
|
-
settings[
|
646
|
-
settings[
|
645
|
+
settings['disks']['ephemeral'] = has_ephemeral ? '/dev/sdb' : nil
|
646
|
+
settings['env'] = environment if environment
|
647
647
|
settings.merge(@agent_properties)
|
648
648
|
end
|
649
649
|
|
@@ -652,7 +652,7 @@ module Bosh::OpenStackCloud
|
|
652
652
|
#
|
653
653
|
# @param [Fog::Compute::OpenStack::Server] server OpenStack server
|
654
654
|
def update_agent_settings(server)
|
655
|
-
raise ArgumentError,
|
655
|
+
raise ArgumentError, 'Block is not provided' unless block_given?
|
656
656
|
|
657
657
|
@logger.info("Updating settings for server `#{server.id}'...")
|
658
658
|
settings = @registry.read_settings(server.name)
|
@@ -691,17 +691,17 @@ module Bosh::OpenStackCloud
|
|
691
691
|
def attach_volume(server, volume)
|
692
692
|
@logger.info("Attaching volume `#{volume.id}' to server `#{server.id}'...")
|
693
693
|
volume_attachments = with_openstack { server.volume_attachments }
|
694
|
-
device = volume_attachments.find { |a| a[
|
694
|
+
device = volume_attachments.find { |a| a['volumeId'] == volume.id }
|
695
695
|
|
696
696
|
if device.nil?
|
697
697
|
device_name = select_device_name(volume_attachments, first_device_name_letter(server))
|
698
|
-
cloud_error(
|
698
|
+
cloud_error('Server has too many disks attached') if device_name.nil?
|
699
699
|
|
700
700
|
@logger.info("Attaching volume `#{volume.id}' to server `#{server.id}', device name is `#{device_name}'")
|
701
701
|
with_openstack { volume.attach(server.id, device_name) }
|
702
|
-
wait_resource(volume, :
|
702
|
+
wait_resource(volume, :'in-use')
|
703
703
|
else
|
704
|
-
device_name = device[
|
704
|
+
device_name = device['device']
|
705
705
|
@logger.info("Volume `#{volume.id}' is already attached to server `#{server.id}' in `#{device_name}'. Skipping.")
|
706
706
|
end
|
707
707
|
|
@@ -715,11 +715,11 @@ module Bosh::OpenStackCloud
|
|
715
715
|
# @param [String] first_device_name_letter First available letter for device names
|
716
716
|
# @return [String] First available device name or nil is none is available
|
717
717
|
def select_device_name(volume_attachments, first_device_name_letter)
|
718
|
-
(first_device_name_letter..
|
718
|
+
(first_device_name_letter..'z').each do |char|
|
719
719
|
# Some kernels remap device names (from sd* to vd* or xvd*).
|
720
720
|
device_names = ["/dev/sd#{char}", "/dev/vd#{char}", "/dev/xvd#{char}"]
|
721
721
|
# Bosh Agent will lookup for the proper device name if we set it initially to sd*.
|
722
|
-
return "/dev/sd#{char}" if volume_attachments.select { |v| device_names.include?( v[
|
722
|
+
return "/dev/sd#{char}" if volume_attachments.select { |v| device_names.include?( v['device']) }.empty?
|
723
723
|
@logger.warn("`/dev/sd#{char}' is already taken")
|
724
724
|
end
|
725
725
|
|
@@ -752,7 +752,7 @@ module Bosh::OpenStackCloud
|
|
752
752
|
def detach_volume(server, volume)
|
753
753
|
@logger.info("Detaching volume `#{volume.id}' from `#{server.id}'...")
|
754
754
|
volume_attachments = with_openstack { server.volume_attachments }
|
755
|
-
if volume_attachments.find { |a| a[
|
755
|
+
if volume_attachments.find { |a| a['volumeId'] == volume.id }
|
756
756
|
with_openstack { volume.detach(server.id, volume.id) }
|
757
757
|
wait_resource(volume, :available)
|
758
758
|
else
|
@@ -773,8 +773,8 @@ module Bosh::OpenStackCloud
|
|
773
773
|
|
774
774
|
unless actual_sg_names.sort == specified_sg_names.sort
|
775
775
|
raise Bosh::Clouds::NotSupported,
|
776
|
-
|
777
|
-
[actual_sg_names.join(
|
776
|
+
'security groups change requires VM recreation: %s to %s' %
|
777
|
+
[actual_sg_names.join(', '), specified_sg_names.join(', ')]
|
778
778
|
end
|
779
779
|
end
|
780
780
|
|
@@ -791,8 +791,8 @@ module Bosh::OpenStackCloud
|
|
791
791
|
|
792
792
|
unless specified_ip_address.nil? || actual_ip_addresses.include?(specified_ip_address)
|
793
793
|
raise Bosh::Clouds::NotSupported,
|
794
|
-
|
795
|
-
[actual_ip_addresses.join(
|
794
|
+
'IP address change requires VM recreation: %s to %s' %
|
795
|
+
[actual_ip_addresses.join(', '), specified_ip_address]
|
796
796
|
end
|
797
797
|
end
|
798
798
|
|
@@ -825,11 +825,11 @@ module Bosh::OpenStackCloud
|
|
825
825
|
if result.failed?
|
826
826
|
@logger.error("Extracting stemcell root image failed in dir #{tmp_dir}, " +
|
827
827
|
"tar returned #{result.exit_status}, output: #{result.output}")
|
828
|
-
cloud_error(
|
828
|
+
cloud_error('Extracting stemcell root image failed. Check task debug log for details.')
|
829
829
|
end
|
830
|
-
root_image = File.join(tmp_dir,
|
830
|
+
root_image = File.join(tmp_dir, 'root.img')
|
831
831
|
unless File.exists?(root_image)
|
832
|
-
cloud_error(
|
832
|
+
cloud_error('Root image is missing from stemcell archive')
|
833
833
|
end
|
834
834
|
end
|
835
835
|
|
@@ -840,21 +840,21 @@ module Bosh::OpenStackCloud
|
|
840
840
|
# @return [void]
|
841
841
|
# @raise [ArgumentError] if options are not valid
|
842
842
|
def validate_options
|
843
|
-
unless @options[
|
844
|
-
@options.has_key?(
|
845
|
-
@options[
|
846
|
-
@options[
|
847
|
-
@options[
|
848
|
-
@options[
|
849
|
-
raise ArgumentError,
|
843
|
+
unless @options['openstack'].is_a?(Hash) &&
|
844
|
+
@options.has_key?('openstack') &&
|
845
|
+
@options['openstack']['auth_url'] &&
|
846
|
+
@options['openstack']['username'] &&
|
847
|
+
@options['openstack']['api_key'] &&
|
848
|
+
@options['openstack']['tenant']
|
849
|
+
raise ArgumentError, 'Invalid OpenStack configuration parameters'
|
850
850
|
end
|
851
851
|
|
852
|
-
unless @options.has_key?(
|
853
|
-
@options[
|
854
|
-
@options[
|
855
|
-
@options[
|
856
|
-
@options[
|
857
|
-
raise ArgumentError,
|
852
|
+
unless @options.has_key?('registry') &&
|
853
|
+
@options['registry'].is_a?(Hash) &&
|
854
|
+
@options['registry']['endpoint'] &&
|
855
|
+
@options['registry']['user'] &&
|
856
|
+
@options['registry']['password']
|
857
|
+
raise ArgumentError, 'Invalid registry configuration parameters'
|
858
858
|
end
|
859
859
|
end
|
860
860
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bosh_openstack_cpi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2546.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-05-
|
12
|
+
date: 2014-05-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fog
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: 1.
|
37
|
+
version: 1.2546.0
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: 1.
|
45
|
+
version: 1.2546.0
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: bosh_cpi
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 1.
|
53
|
+
version: 1.2546.0
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 1.
|
61
|
+
version: 1.2546.0
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: bosh-registry
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
requirements:
|
67
67
|
- - ~>
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 1.
|
69
|
+
version: 1.2546.0
|
70
70
|
type: :runtime
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -74,7 +74,7 @@ dependencies:
|
|
74
74
|
requirements:
|
75
75
|
- - ~>
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: 1.
|
77
|
+
version: 1.2546.0
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
79
|
name: httpclient
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
version: 0.8.2
|
110
110
|
description: ! 'BOSH OpenStack CPI
|
111
111
|
|
112
|
-
|
112
|
+
e8aedb'
|
113
113
|
email: support@cloudfoundry.com
|
114
114
|
executables:
|
115
115
|
- bosh_openstack_console
|
@@ -153,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
153
153
|
version: '0'
|
154
154
|
segments:
|
155
155
|
- 0
|
156
|
-
hash:
|
156
|
+
hash: 367374751110787261
|
157
157
|
requirements: []
|
158
158
|
rubyforge_project:
|
159
159
|
rubygems_version: 1.8.23
|