Merge pull request #2854 from frodenas/gce_disks

[google|compute] Improve Disks support
This commit is contained in:
Nat Welch 2014-04-21 11:25:16 +01:00
commit 2c189bfafb
8 changed files with 89 additions and 58 deletions

View File

@ -13,6 +13,7 @@ module Fog
request :list_addresses
request :list_aggregated_addresses
request :list_disks
request :list_aggregated_disks
request :list_firewalls
request :list_images
request :list_machine_types

View File

@ -8,21 +8,21 @@ module Fog
identity :name
attribute :kind, :aliases => 'kind'
attribute :id, :aliases => 'id'
attribute :kind
attribute :id
attribute :creation_timestamp, :aliases => 'creationTimestamp'
attribute :zone_name, :aliases => 'zone'
attribute :status, :aliases => 'status'
attribute :description, :aliases => 'description'
attribute :zone, :aliases => :zone_name
attribute :status
attribute :description
attribute :size_gb, :aliases => 'sizeGb'
attribute :self_link, :aliases => 'selfLink'
attribute :source_image, :aliases => 'sourceImage'
attribute :source_image_id, :aliases => 'sourceImageId'
attribute :source_snapshot, :aliases => 'sourceSnapshot'
attribute :source_snapshot_id, :aliases => 'sourceSnapshot'
attribute :source_snapshot_id, :aliases => 'sourceSnapshotId'
def save
requires :name
requires :zone_name
requires :name, :zone
options = {}
my_description = "Created with fog"
@ -37,32 +37,25 @@ module Fog
options['sizeGb'] = size_gb
options['description'] = description || my_description
data = service.insert_disk(name, zone_name, source_image, options).body
data = service.backoff_if_unfound {service.get_disk(name, zone_name).body}
service.disks.merge_attributes(data)
data = service.insert_disk(name, zone, source_image, options)
operation = Fog::Compute::Google::Operations.new(:service => service).get(data.body['name'], data.body['zone'])
operation.wait_for { !pending? }
reload
end
def destroy(async=true)
requires :name, :zone_name
operation = service.delete_disk(name, zone_name)
# wait until "DONE" to ensure the operation doesn't fail, raises exception on error
if not async
Fog.wait_for do
operation = service.get_zone_operation(zone_name, operation.body["name"])
operation.body["status"] == "DONE"
end
requires :name, :zone
data = service.delete_disk(name, zone_name)
operation = Fog::Compute::Google::Operations.new(:service => service).get(data.body['name'], data.body['zone'])
unless async
operation.wait_for { ready? }
end
operation
end
def zone
if self.zone_name.is_a? String
service.get_zone(self.zone_name.split('/')[-1]).body["name"]
elsif zone_name.is_a? Excon::Response
service.get_zone(zone_name.body["name"]).body["name"]
else
self.zone_name
end
def zone_name
zone.nil? ? nil : zone.split('/')[-1]
end
# auto_delete can only be applied to disks created before instance creation.
@ -89,8 +82,7 @@ module Fog
end
def reload
requires :identity
requires :zone_name
requires :identity, :zone
return unless data = begin
collection.get(identity, zone_name)
@ -104,8 +96,7 @@ module Fog
end
def create_snapshot(snapshot_name, snapshot_description="")
requires :name
requires :zone_name
requires :name, :zone
if snapshot_name.nil? or snapshot_name.empty?
raise ArgumentError, 'Invalid snapshot name'
@ -116,13 +107,9 @@ module Fog
'description' => snapshot_description,
}
service.insert_snapshot(name, self.zone, service.project, options)
data = service.backoff_if_unfound {
service.get_snapshot(snapshot_name, service.project).body
}
service.snapshots.merge_attributes(data)
# Try to return the representation of the snapshot we created
data = service.insert_snapshot(name, zone_name, service.project, options)
operation = Fog::Compute::Google::Operations.new(:service => service).get(data.body['name'], data.body['zone'])
operation.wait_for { !pending? }
service.snapshots.get(snapshot_name)
end

View File

@ -10,32 +10,32 @@ module Fog
model Fog::Compute::Google::Disk
def all(filters={})
if filters['zone'].nil?
data = []
service.list_zones.body['items'].each do |zone|
data += service.list_disks(zone['name']).body["items"] || []
end
if filters['zone']
data = service.list_disks(filters['zone']).body['items'] || []
else
data = service.list_disks(filters['zone']).body["items"] || []
data = []
service.list_aggregated_disks.body['items'].each_value do |zone|
data.concat(zone['disks']) if zone['disks']
end
end
load(data)
end
def get(identity, zone=nil)
response = nil
if zone.nil?
service.list_zones.body['items'].each do |zone|
begin
response = service.get_disk(identity, zone['name'])
break if response.status == 200
rescue Fog::Errors::Error
end
end
if zone
response = service.get_disk(identity, zone).body
else
response = service.get_disk(identity, zone)
disks = service.list_aggregated_disks(:filter => "name eq .*#{identity}").body['items']
disk = disks.each_value.select { |zone| zone.has_key?('disks') }
# It can only be 1 disk with the same name across all regions
response = disk.first['disks'].first unless disk.empty?
end
return nil if response.nil?
new(response.body)
new(response)
rescue Fog::Errors::NotFound
nil
end
end

View File

@ -35,7 +35,7 @@ module Fog
body_object = { 'name' => snap_name }
# Merge in any remaining options (description)
body_object.merge(opts)
body_object.merge!(opts)
result = self.build_result(api_method, parameters,
body_object)

View File

@ -0,0 +1,43 @@
module Fog
module Compute
class Google
class Mock
def list_aggregated_disks(options = {})
# Create a Hash of unique zones from the disks Array previously filled when disks are created
zones = Hash[self.data[:disks].values.map { |disk| ["zones/#{disk['zone'].split('/')[-1]}", {'disks' => [] }] }]
if options[:filter]
# Look up for the disk name
disk = self.data[:disks][options[:filter].gsub(/name eq \.\*/, '')]
# Fill the zones Hash with the disk (if it's found)
zones["zones/#{disk['zone'].split('/')[-1]}"]['disks'].concat([disk]) if disk
else
# Fill the zones Hash with the disks attached to each zone
self.data[:disks].values.each { |disk| zones["zones/#{disk['zone'].split('/')[-1]}"]['disks'].concat([disk]) }
end
build_response(:body => {
"kind" => "compute#diskAggregatedList",
"selfLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/aggregated/disks",
"id" => "projects/#{@project}/aggregated/disks",
"items" => zones
})
end
end
class Real
def list_aggregated_disks(options = {})
api_method = @compute.disks.aggregated_list
parameters = {
'project' => @project,
}
parameters['filter'] = options[:filter] if options[:filter]
result = self.build_result(api_method, parameters)
response = self.build_response(result)
end
end
end
end
end

View File

@ -4,7 +4,7 @@ def create_test_disk(connection, zone)
disk = connection.disks.create({
:name => "fogservername",
:size_gb => "2",
:zone_name => zone,
:zone => zone,
:source_image => "debian-7-wheezy-v20140408",
})
disk.wait_for { ready? }

View File

@ -1,5 +1,5 @@
Shindo.tests("Fog::Compute[:google] | disk model", ['google']) do
model_tests(Fog::Compute[:google].disks, {:name => 'fogdiskname', :zone_name => 'us-central1-a'})
model_tests(Fog::Compute[:google].disks, {:name => 'fogdiskname', :zone => 'us-central1-a'})
end

View File

@ -1,5 +1,5 @@
Shindo.tests("Fog::Compute[:google] | disks", ['google']) do
collection_tests(Fog::Compute[:google].disks, {:name => 'fogdiskname', :zone_name => 'us-central1-a'})
collection_tests(Fog::Compute[:google].disks, {:name => 'fogdiskname', :zone => 'us-central1-a'})
end