2012-11-14 08:31:02 -05:00
|
|
|
module Fog
|
|
|
|
module Compute
|
|
|
|
class Vsphere
|
|
|
|
class Volume < Fog::Model
|
|
|
|
DISK_SIZE_TO_GB = 1048576
|
|
|
|
identity :id
|
|
|
|
|
|
|
|
attribute :datastore
|
|
|
|
attribute :mode
|
|
|
|
attribute :size
|
|
|
|
attribute :thin
|
2013-10-28 17:57:55 -04:00
|
|
|
attribute :eager_zero
|
2012-11-14 08:31:02 -05:00
|
|
|
attribute :name
|
|
|
|
attribute :filename
|
|
|
|
attribute :size_gb
|
2013-10-28 17:57:55 -04:00
|
|
|
attribute :key
|
|
|
|
attribute :unit_number
|
|
|
|
attribute :server_id
|
2012-11-14 08:31:02 -05:00
|
|
|
|
|
|
|
def initialize(attributes={} )
|
2013-10-28 17:57:55 -04:00
|
|
|
# Assign server first to prevent race condition with persisted?
|
|
|
|
self.server_id = attributes.delete(:server_id)
|
|
|
|
|
2012-11-14 08:31:02 -05:00
|
|
|
super defaults.merge(attributes)
|
|
|
|
end
|
|
|
|
|
|
|
|
def size_gb
|
|
|
|
attributes[:size_gb] ||= attributes[:size].to_i / DISK_SIZE_TO_GB if attributes[:size]
|
|
|
|
end
|
|
|
|
|
|
|
|
def size_gb= s
|
|
|
|
attributes[:size] = s.to_i * DISK_SIZE_TO_GB if s
|
|
|
|
end
|
|
|
|
|
|
|
|
def to_s
|
|
|
|
name
|
|
|
|
end
|
|
|
|
|
2013-10-28 17:57:55 -04:00
|
|
|
def destroy
|
|
|
|
requires :server_id, :key, :unit_number
|
|
|
|
|
|
|
|
service.destroy_vm_volume(self)
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
def save
|
|
|
|
raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted?
|
|
|
|
requires :server_id, :size, :datastore
|
|
|
|
|
|
|
|
if unit_number.nil?
|
2014-05-22 21:40:43 -04:00
|
|
|
used_unit_numbers = server.volumes.map { |volume| volume.unit_number }
|
2013-10-28 19:08:31 -04:00
|
|
|
max_unit_number = used_unit_numbers.max
|
|
|
|
|
|
|
|
if max_unit_number > server.volumes.size
|
|
|
|
# If the max ID exceeds the number of volumes, there must be a hole in the range. Find a hole and use it.
|
|
|
|
self.unit_number = max_unit_number.times.to_a.find { |i| used_unit_numbers.exclude?(i) }
|
|
|
|
else
|
|
|
|
self.unit_number = max_unit_number + 1
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if server.volumes.any? { |volume| volume.unit_number == self.unit_number && volume.id != self.id }
|
|
|
|
raise "A volume already exists with that unit_number, so we can't save the new volume"
|
|
|
|
end
|
2013-10-28 17:57:55 -04:00
|
|
|
end
|
|
|
|
|
2013-10-28 19:09:09 -04:00
|
|
|
data = service.add_vm_volume(self)
|
2013-10-28 17:57:55 -04:00
|
|
|
|
2013-10-28 19:09:09 -04:00
|
|
|
if data['task_state'] == 'success'
|
|
|
|
# We have to query vSphere to get the volume attributes since the task handle doesn't include that info.
|
|
|
|
created = server.volumes.all.find { |volume| volume.unit_number == self.unit_number }
|
|
|
|
|
|
|
|
self.id = created.id
|
|
|
|
self.key = created.key
|
|
|
|
self.filename = created.filename
|
|
|
|
|
|
|
|
true
|
|
|
|
else
|
|
|
|
false
|
|
|
|
end
|
2013-10-28 17:57:55 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def server
|
|
|
|
requires :server_id
|
|
|
|
service.servers.get(server_id)
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
2012-11-14 08:31:02 -05:00
|
|
|
|
|
|
|
def defaults
|
|
|
|
{
|
2013-10-28 17:57:55 -04:00
|
|
|
:thin => true,
|
|
|
|
:name => "Hard disk",
|
|
|
|
:mode => "persistent"
|
2012-11-14 08:31:02 -05:00
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|