2011-06-28 09:47:16 -04:00
|
|
|
require 'fog/core/model'
|
2011-08-29 11:24:39 -04:00
|
|
|
require 'fog/libvirt/models/compute/util'
|
2011-08-03 06:48:44 -04:00
|
|
|
require 'rexml/document'
|
|
|
|
require 'erb'
|
|
|
|
require 'securerandom'
|
2011-06-28 09:47:16 -04:00
|
|
|
|
|
|
|
module Fog
|
|
|
|
module Compute
|
|
|
|
class Libvirt
|
|
|
|
|
|
|
|
class Volume < Fog::Model
|
|
|
|
|
2011-08-03 06:48:44 -04:00
|
|
|
include Fog::Compute::LibvirtUtil
|
|
|
|
|
2011-08-09 17:03:40 -04:00
|
|
|
identity :id , :aliases => 'key'
|
2011-08-01 09:18:00 -04:00
|
|
|
|
2011-08-09 11:11:15 -04:00
|
|
|
attribute :pool_name
|
2011-08-08 17:22:55 -04:00
|
|
|
|
2011-08-01 09:18:00 -04:00
|
|
|
attribute :xml
|
2011-08-08 17:22:55 -04:00
|
|
|
|
2011-08-09 11:11:15 -04:00
|
|
|
attribute :key
|
2011-08-03 06:48:44 -04:00
|
|
|
attribute :path
|
|
|
|
attribute :name
|
|
|
|
attribute :capacity
|
|
|
|
attribute :allocation
|
2011-08-09 11:11:15 -04:00
|
|
|
attribute :format_type
|
2011-08-03 06:48:44 -04:00
|
|
|
|
2011-08-08 17:22:55 -04:00
|
|
|
# Can be created by passing in :xml => "<xml to create volume>"
|
2011-08-09 11:11:15 -04:00
|
|
|
# A volume always belongs to a pool, :pool_name => "<name of pool>"
|
2011-08-01 09:18:00 -04:00
|
|
|
#
|
|
|
|
# @returns volume created
|
|
|
|
def initialize(attributes={} )
|
|
|
|
self.xml ||= nil unless attributes[:xml]
|
2011-08-09 11:11:15 -04:00
|
|
|
self.key = nil
|
|
|
|
self.format_type ||= "raw" unless attributes[:format_type]
|
|
|
|
extension = self.format_type=="raw" ? "img" : self.format_type
|
2011-08-09 17:03:40 -04:00
|
|
|
self.name ||= "fog-#{SecureRandom.random_number*10E14.to_i.round}.#{extension}" unless attributes[:name]
|
2011-08-09 11:11:15 -04:00
|
|
|
self.capacity ||= "10G" unless attributes[:capacity]
|
|
|
|
self.allocation ||= "1G" unless attributes[:allocation]
|
2011-08-01 09:18:00 -04:00
|
|
|
super
|
2011-08-08 17:22:55 -04:00
|
|
|
|
2011-08-09 11:11:15 -04:00
|
|
|
#We need a connection to calculate the poolname
|
|
|
|
#This is why we do this after super
|
|
|
|
self.pool_name ||= default_pool_name unless attributes[:pool_name]
|
|
|
|
end
|
|
|
|
|
|
|
|
# Try to guess the default/first pool of no pool_name was specificed
|
|
|
|
def default_pool_name
|
|
|
|
default_name="default"
|
|
|
|
default_pool=@connection.pools.all(:name => default_name)
|
|
|
|
|
2011-08-03 06:48:44 -04:00
|
|
|
if default_pool.nil?
|
2011-08-09 11:11:15 -04:00
|
|
|
first_pool=@connection.pools.first
|
2011-08-03 06:48:44 -04:00
|
|
|
if first_pool.nil?
|
|
|
|
raise Fog::Errors::Error.new('We could not find a pool called "default" and there was no other pool defined')
|
2011-08-08 17:22:55 -04:00
|
|
|
else
|
2011-08-09 11:11:15 -04:00
|
|
|
default_name=first_pool.name
|
2011-08-03 06:48:44 -04:00
|
|
|
end
|
|
|
|
end
|
2011-08-09 11:11:15 -04:00
|
|
|
return default_name
|
2011-08-01 09:18:00 -04:00
|
|
|
end
|
|
|
|
|
2011-08-09 11:11:15 -04:00
|
|
|
# Takes a pool and either :xml or other settings
|
2011-08-01 09:18:00 -04:00
|
|
|
def save
|
2011-08-09 11:11:15 -04:00
|
|
|
requires :pool_name
|
|
|
|
|
2011-08-09 17:03:40 -04:00
|
|
|
raise Fog::Errors::Error.new('Resaving an existing volume may create a duplicate') if key
|
|
|
|
|
2011-08-09 11:11:15 -04:00
|
|
|
xml=xml_from_template if xml.nil?
|
|
|
|
|
|
|
|
begin
|
|
|
|
volume=nil
|
|
|
|
pool=connection.lookup_storage_pool_by_name(pool_name)
|
|
|
|
volume=pool.create_volume_xml(xml)
|
|
|
|
self.raw=volume
|
|
|
|
true
|
|
|
|
rescue
|
|
|
|
raise Fog::Errors::Error.new("Error creating volume: #{$!}")
|
|
|
|
false
|
2011-08-01 09:18:00 -04:00
|
|
|
end
|
2011-08-03 06:48:44 -04:00
|
|
|
|
2011-08-01 09:18:00 -04:00
|
|
|
end
|
2011-08-08 17:22:55 -04:00
|
|
|
|
2011-08-09 11:11:15 -04:00
|
|
|
def split_size_unit(text)
|
|
|
|
matcher=text.match(/(\d+)(.+)/)
|
|
|
|
size=matcher[1]
|
|
|
|
unit=matcher[2]
|
|
|
|
return size , unit
|
2011-08-08 17:30:09 -04:00
|
|
|
end
|
2011-08-01 09:18:00 -04:00
|
|
|
|
2011-08-09 11:11:15 -04:00
|
|
|
# Create a valid xml for the volume based on the template
|
|
|
|
def xml_from_template
|
2011-06-28 09:47:16 -04:00
|
|
|
|
2011-08-09 11:11:15 -04:00
|
|
|
allocation_size,allocation_unit=split_size_unit(self.allocation)
|
|
|
|
capacity_size,capacity_unit=split_size_unit(self.capacity)
|
2011-08-08 17:22:55 -04:00
|
|
|
|
2011-08-09 11:11:15 -04:00
|
|
|
template_options={
|
|
|
|
:name => self.name,
|
|
|
|
:format_type => self.format_type,
|
|
|
|
:allocation_size => allocation_size,
|
|
|
|
:allocation_unit => allocation_unit,
|
|
|
|
:capacity_size => capacity_size,
|
|
|
|
:capacity_unit => capacity_unit
|
|
|
|
}
|
2011-08-08 17:22:55 -04:00
|
|
|
|
2011-08-09 11:11:15 -04:00
|
|
|
# We only want specific variables for ERB
|
2011-08-08 17:30:09 -04:00
|
|
|
vars = ErbBinding.new(template_options)
|
|
|
|
template_path=File.join(File.dirname(__FILE__),"templates","volume.xml.erb")
|
|
|
|
template=File.open(template_path).readlines.join
|
|
|
|
erb = ERB.new(template)
|
|
|
|
vars_binding = vars.send(:get_binding)
|
|
|
|
result=erb.result(vars_binding)
|
|
|
|
return result
|
|
|
|
end
|
2011-06-28 09:47:16 -04:00
|
|
|
|
2011-08-08 17:30:09 -04:00
|
|
|
# Destroy a volume
|
|
|
|
def destroy
|
|
|
|
requires :raw
|
|
|
|
raw.delete
|
|
|
|
true
|
|
|
|
end
|
2011-08-03 06:48:44 -04:00
|
|
|
|
2011-08-08 17:30:09 -04:00
|
|
|
# Wipes a volume , zeroes disk
|
|
|
|
def wipe
|
|
|
|
requires :raw
|
|
|
|
raw.wipe
|
|
|
|
true
|
|
|
|
end
|
2011-08-03 06:48:44 -04:00
|
|
|
|
2011-08-08 17:30:09 -04:00
|
|
|
# Clones this volume to the name provided
|
|
|
|
def clone(name)
|
|
|
|
pool=@raw.pool
|
2011-09-12 14:11:58 -04:00
|
|
|
xml = REXML::Document.new(self.xml)
|
2011-08-08 17:30:09 -04:00
|
|
|
xml.root.elements['/volume/name'].text=name
|
|
|
|
xml.root.elements['/volume/key'].text=name
|
|
|
|
xml.delete_element('/volume/target/path')
|
|
|
|
pool.create_volume_xml_from(xml.to_s,@raw)
|
|
|
|
return connection.volumes.all(:name => name).first
|
|
|
|
end
|
2011-08-03 06:48:44 -04:00
|
|
|
|
2011-09-12 14:11:58 -04:00
|
|
|
#def xml_desc
|
|
|
|
#requires :raw
|
|
|
|
#raw.xml_desc
|
|
|
|
#end
|
2011-08-03 06:48:44 -04:00
|
|
|
|
2011-08-08 17:30:09 -04:00
|
|
|
private
|
|
|
|
def raw
|
|
|
|
@raw
|
|
|
|
end
|
2011-08-03 06:48:44 -04:00
|
|
|
|
2011-08-08 17:30:09 -04:00
|
|
|
def raw=(new_raw)
|
|
|
|
@raw = new_raw
|
2011-08-03 06:48:44 -04:00
|
|
|
|
2011-08-09 11:11:15 -04:00
|
|
|
xml = REXML::Document.new(new_raw.xml_desc)
|
|
|
|
format_type=xml.root.elements['/volume/target/format'].attributes['type']
|
|
|
|
|
2011-08-08 17:30:09 -04:00
|
|
|
raw_attributes = {
|
|
|
|
:key => new_raw.key,
|
2011-08-09 17:03:40 -04:00
|
|
|
:id => new_raw.key,
|
2011-08-08 17:30:09 -04:00
|
|
|
:path => new_raw.path,
|
|
|
|
:name => new_raw.name,
|
2011-08-09 11:11:15 -04:00
|
|
|
:format_type => format_type,
|
2011-08-08 17:30:09 -04:00
|
|
|
:allocation => new_raw.info.allocation,
|
|
|
|
:capacity => new_raw.info.capacity,
|
2011-09-12 14:11:58 -04:00
|
|
|
:xml => new_raw.xml_desc
|
2011-08-08 17:30:09 -04:00
|
|
|
}
|
2011-06-28 09:47:16 -04:00
|
|
|
|
2011-08-08 17:30:09 -04:00
|
|
|
merge_attributes(raw_attributes)
|
2011-06-28 09:47:16 -04:00
|
|
|
end
|
|
|
|
|
2011-08-03 06:48:44 -04:00
|
|
|
end
|
2011-06-28 09:47:16 -04:00
|
|
|
|
2011-08-08 17:30:09 -04:00
|
|
|
end
|
2011-08-03 06:48:44 -04:00
|
|
|
end
|
2011-08-08 17:30:09 -04:00
|
|
|
|
|
|
|
end
|