mirror of
https://github.com/fog/fog.git
synced 2022-11-09 13:51:43 -05:00
Again major breakthrough
- restructured all command to allow filters - get only uses the identity to get it - ssh/scp proxied now work correctly on server - extended networks and interfaces
This commit is contained in:
parent
b2d5207fba
commit
1ed3ee3379
16 changed files with 883 additions and 463 deletions
|
@ -32,13 +32,39 @@ module Fog
|
|||
attr_reader :uri
|
||||
|
||||
def initialize(options={})
|
||||
@uri = ::Fog::Compute::LibvirtUtil::URI.new(options[:libvirt_uri])
|
||||
@uri = ::Fog::Compute::LibvirtUtil::URI.new(enhance_uri(options[:libvirt_uri]))
|
||||
|
||||
# libvirt is part of the gem => ruby-libvirt
|
||||
require 'libvirt'
|
||||
|
||||
|
||||
@connection = ::Libvirt::open(@uri.uri)
|
||||
end
|
||||
|
||||
def enhance_uri(uri)
|
||||
require 'cgi'
|
||||
append=""
|
||||
|
||||
# on macosx, chances are we are using libvirt through homebrew
|
||||
# the client will default to a socket location based on it's own location (/opt)
|
||||
# we conveniently point it to /var/run/libvirt/libvirt-sock
|
||||
# if no socket option has been specified explicitly
|
||||
|
||||
if RUBY_PLATFORM =~ /darwin/
|
||||
querystring=::URI.parse(uri).query
|
||||
if querystring.nil?
|
||||
append="?socket=/var/run/libvirt/libvirt-sock"
|
||||
else
|
||||
if !::CGI.parse(querystring).has_key?("socket")
|
||||
append="&socket=/var/run/libvirt/libvirt-sock"
|
||||
end
|
||||
end
|
||||
end
|
||||
newuri=uri+append
|
||||
return newuri
|
||||
end
|
||||
|
||||
|
||||
# hack to provide 'requests'
|
||||
def method_missing(method_sym, *arguments, &block)
|
||||
if @connection.respond_to?(method_sym)
|
||||
|
|
|
@ -6,12 +6,15 @@ module Fog
|
|||
|
||||
class Interface < Fog::Model
|
||||
|
||||
identity :id
|
||||
identity :name
|
||||
|
||||
attribute :mac
|
||||
attribute :name
|
||||
attribute :xml_desc
|
||||
|
||||
def save
|
||||
raise Fog::Errors::Error.new('Creating a new interface is not yet implemented. Contributions welcome!')
|
||||
end
|
||||
|
||||
def destroy
|
||||
requires :raw
|
||||
raw.delete
|
||||
|
@ -28,7 +31,6 @@ module Fog
|
|||
@raw = new_raw
|
||||
|
||||
raw_attributes = {
|
||||
:id => new_raw.name,
|
||||
:name => new_raw.name,
|
||||
:mac => new_raw.mac,
|
||||
:xml_desc => new_raw.xml_desc,
|
||||
|
|
|
@ -9,21 +9,51 @@ module Fog
|
|||
|
||||
model Fog::Compute::Libvirt::Interface
|
||||
|
||||
def all
|
||||
def all(filter=nil)
|
||||
data=[]
|
||||
connection.list_interfaces.each do |ifname|
|
||||
interface=connection.lookup_interface_by_name(ifname)
|
||||
data << { :raw => interface }
|
||||
end
|
||||
if filter.nil?
|
||||
connection.list_interfaces.each do |ifname|
|
||||
interface=connection.lookup_interface_by_name(ifname)
|
||||
data << { :raw => interface }
|
||||
end
|
||||
connection.list_defined_interfaces.each do |ifname|
|
||||
interface=connection.lookup_interface_by_name(ifname)
|
||||
data << { :raw => interface }
|
||||
end
|
||||
|
||||
else
|
||||
interface=nil
|
||||
begin
|
||||
interface=get_by_name(filter[:name]) if filter.has_key?(:name)
|
||||
interface=get_by_mac(filter[:mac]) if filter.has_key?(:mac)
|
||||
rescue ::Libvirt::RetrieveError
|
||||
return nil
|
||||
end
|
||||
data << { :raw => interface}
|
||||
end
|
||||
|
||||
load(data)
|
||||
end
|
||||
|
||||
def get(key)
|
||||
self.all(:name => name).first
|
||||
end
|
||||
|
||||
# Retrieve the interface by name
|
||||
def get_by_name(name)
|
||||
interface=connection.lookup_interface_by_name(name)
|
||||
return interface
|
||||
# new(:raw => interface)
|
||||
end
|
||||
|
||||
# Retrieve the interface by name
|
||||
def get(name)
|
||||
interface=connection.lookup_interface_by_name(name)
|
||||
new(:raw => interface)
|
||||
def get_by_mac(mac)
|
||||
interface=connection.lookup_interface_by_mac(mac)
|
||||
return interface
|
||||
# new(:raw => interface)
|
||||
end
|
||||
|
||||
|
||||
end #class
|
||||
|
||||
end #Class
|
||||
|
|
|
@ -9,15 +9,12 @@ module Fog
|
|||
|
||||
include Fog::Compute::LibvirtUtil
|
||||
|
||||
identity :id
|
||||
attribute :uuid
|
||||
identity :uuid
|
||||
|
||||
attribute :name
|
||||
attribute :bridge_name
|
||||
|
||||
attribute :xml_desc
|
||||
|
||||
attr_reader :template_path,:network_mode,:bridge_name
|
||||
|
||||
|
||||
##https://www.redhat.com/archives/libvirt-users/2011-May/msg00091.html
|
||||
# Bridged VLAN
|
||||
|
||||
|
@ -27,17 +24,16 @@ module Fog
|
|||
# http://wiki.libvirt.org/page/Networking
|
||||
#http://wiki.libvirt.org/page/VirtualNetworking#Virtual_network_switches
|
||||
def initialize(attributes = {})
|
||||
|
||||
@template_path = attributes[:template_path] || "network.xml.erb"
|
||||
@network_mode = attributes[:network_mode] || "nat"
|
||||
@bridge_name = attributes[:bridge_name] || "virbr0"
|
||||
template_xml
|
||||
super
|
||||
end
|
||||
|
||||
def save
|
||||
raise Fog::Errors::Error.new('Creating a new network is not yet implemented. Contributions welcome!')
|
||||
end
|
||||
|
||||
def destroy()
|
||||
requires :raw
|
||||
raw.destroy
|
||||
# raw.undefine
|
||||
true
|
||||
end
|
||||
|
||||
|
@ -51,7 +47,6 @@ module Fog
|
|||
@raw = new_raw
|
||||
|
||||
raw_attributes = {
|
||||
:id => new_raw.uuid,
|
||||
:uuid => new_raw.uuid,
|
||||
:name => new_raw.name,
|
||||
:bridge_name => new_raw.bridge_name,
|
||||
|
|
|
@ -9,20 +9,49 @@ module Fog
|
|||
|
||||
model Fog::Compute::Libvirt::Network
|
||||
|
||||
def all
|
||||
def all(filter=nil)
|
||||
data=[]
|
||||
connection.list_networks.each do |networkname|
|
||||
network=connection.lookup_network_by_name(networkname)
|
||||
data << { :raw => network }
|
||||
end
|
||||
if filter.nil?
|
||||
connection.list_networks.each do |networkname|
|
||||
network=connection.lookup_network_by_name(networkname)
|
||||
data << { :raw => network }
|
||||
end
|
||||
connection.list_defined_networks.each do |networkname|
|
||||
network=connection.lookup_network_by_name(networkname)
|
||||
data << { :raw => network}
|
||||
end
|
||||
else
|
||||
network=nil
|
||||
begin
|
||||
network=get_by_uuid(filter[:uuid]) if filter.has_key?(:uuid)
|
||||
network=get_by_name(filter[:name]) if filter.has_key?(:name)
|
||||
rescue ::Libvirt::RetrieveError
|
||||
return nil
|
||||
end
|
||||
data << { :raw => network}
|
||||
end
|
||||
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Retrieve the network by uuid
|
||||
def get(uuid)
|
||||
network=connection.lookup_network_by_uuid(uuid)
|
||||
new(:raw => network)
|
||||
self.all(:uuid => uuid).first
|
||||
end
|
||||
|
||||
# Retrieve the network by uuid
|
||||
def get_by_uuid(uuid)
|
||||
network=connection.lookup_network_by_uuid(uuid)
|
||||
return network
|
||||
# new(:raw => network)
|
||||
end
|
||||
|
||||
# Retrieve the network by name
|
||||
def get_by_name(name)
|
||||
network=connection.lookup_network_by_name(name)
|
||||
return network
|
||||
# new(:raw => network)
|
||||
end
|
||||
|
||||
|
||||
end #class
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ module Fog
|
|||
|
||||
class Pool < Fog::Model
|
||||
|
||||
identity :id
|
||||
identity :uuid
|
||||
|
||||
# These attributes are only used for creation
|
||||
attribute :xml
|
||||
|
@ -25,7 +25,7 @@ module Fog
|
|||
requires :xml
|
||||
unless xml.nil?
|
||||
pool=nil
|
||||
if create_persistent
|
||||
if self.create_persistent
|
||||
pool=connection.connection.define_storage_pool_xml(xml)
|
||||
else
|
||||
pool=connection.connection.create_storage_pool_xml(xml)
|
||||
|
@ -33,6 +33,7 @@ module Fog
|
|||
self.raw=pool
|
||||
true
|
||||
else
|
||||
raise Fog::Errors::Error.new('Creating a new pool requires proper xml')
|
||||
false
|
||||
end
|
||||
end
|
||||
|
@ -163,12 +164,12 @@ module Fog
|
|||
|
||||
end
|
||||
|
||||
# Retrieves the allocated disk space of the pool
|
||||
# Retrieves the volumes of this pool
|
||||
def volumes
|
||||
|
||||
volumes=Array.new
|
||||
@raw.list_volumes.each do |volume|
|
||||
fog_volume=connection.volumes.get(:name => volume)
|
||||
fog_volume=connection.volumes.all(:name => volume).first
|
||||
volumes << fog_volume
|
||||
end
|
||||
return volumes
|
||||
|
@ -184,7 +185,8 @@ module Fog
|
|||
@raw = new_raw
|
||||
|
||||
raw_attributes = {
|
||||
:id => new_raw.uuid,
|
||||
:uuid => new_raw.uuid,
|
||||
|
||||
}
|
||||
|
||||
merge_attributes(raw_attributes)
|
||||
|
|
|
@ -9,40 +9,48 @@ module Fog
|
|||
|
||||
model Fog::Compute::Libvirt::Pool
|
||||
|
||||
def all
|
||||
def all(filter=nil)
|
||||
data=[]
|
||||
connection.list_storage_pools.each do |poolname|
|
||||
pool=connection.lookup_storage_pool_by_name(poolname)
|
||||
data << { :raw => pool }
|
||||
end
|
||||
connection.list_defined_storage_pools.each do |poolname|
|
||||
data << {
|
||||
:raw => connection.lookup_storage_pool_by_name(poolname)
|
||||
}
|
||||
if filter.nil?
|
||||
connection.list_storage_pools.each do |poolname|
|
||||
pool=connection.lookup_storage_pool_by_name(poolname)
|
||||
data << { :raw => pool }
|
||||
end
|
||||
connection.list_defined_storage_pools.each do |poolname|
|
||||
data << {
|
||||
:raw => connection.lookup_storage_pool_by_name(poolname)
|
||||
}
|
||||
end
|
||||
else
|
||||
pool=nil
|
||||
begin
|
||||
pool=get_by_uuid(filter[:uuid]) if filter.has_key?(:uuid)
|
||||
pool=get_by_name(filter[:name]) if filter.has_key?(:name)
|
||||
rescue ::Libvirt::RetrieveError
|
||||
return nil
|
||||
end
|
||||
data << { :raw => pool}
|
||||
end
|
||||
|
||||
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Retrieve the pool by type
|
||||
def get(param)
|
||||
pool=nil
|
||||
pool=get_by_uuid(param[:uuid]) if param.has_key?(:uuid)
|
||||
pool=get_by_name(param[:name]) if param.has_key?(:name)
|
||||
return pool
|
||||
def get(uuid)
|
||||
self.all(:uuid => uuid).first
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
# Retrieve the pool by uuid
|
||||
def get_by_uuid(uuid)
|
||||
pool=connection.lookup_storage_pool_by_uuid(uuid)
|
||||
new(:raw => pool)
|
||||
return pool
|
||||
end
|
||||
|
||||
# Retrieve the pool by name
|
||||
def get_by_name(name)
|
||||
pool=connection.lookup_storage_pool_by_name(name)
|
||||
new(:raw => pool)
|
||||
return pool
|
||||
# new(:raw => pool)
|
||||
end
|
||||
|
||||
end #class
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
require 'fog/core/model'
|
||||
require 'fog/compute/models/libvirt/util'
|
||||
require 'net/ssh/proxy/command'
|
||||
require 'rexml/document'
|
||||
require 'erb'
|
||||
require 'securerandom'
|
||||
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
|
@ -11,227 +16,433 @@ module Fog
|
|||
|
||||
identity :id , :aliases => 'uuid'
|
||||
|
||||
attribute :memory_size
|
||||
attribute :name
|
||||
attribute :os, :aliases => :os_type_id
|
||||
attribute :xml_desc
|
||||
attribute :cpus
|
||||
attribute :arch
|
||||
attribute :bridge_name
|
||||
|
||||
attr_writer :private_key, :private_key_path, :public_key, :public_key_path, :username
|
||||
attr_reader :bridge_name,:arch, :cpus,:bridge_name, :name,:template_path,:memory_size,:os,:volume_path
|
||||
attribute :poolname
|
||||
attribute :xml
|
||||
attribute :create_persistent
|
||||
attribute :template_options
|
||||
attribute :template_erb
|
||||
|
||||
def initialize(attributes = {})
|
||||
super
|
||||
end
|
||||
|
||||
def create(attributes = {})
|
||||
@name = attributes[:name] || raise("we need a name")
|
||||
@bridge_name = attributes[:bridge_name] || "br0"
|
||||
@cpus = attributes[:cpus] || 1
|
||||
@memory_size = attributes[:memory_size] || 256
|
||||
@username = attributes[:username] || "mccloud"
|
||||
@os = attributes[:os] || "hvm"
|
||||
@arch = attributes[:arch] || "x86_64"
|
||||
@template_path = attributes[:template_path] || "guest.xml.erb"
|
||||
# super
|
||||
volume=connection.volumes.get("ubuntu-10_10_amd64.qcow2").clone("#{name}.qcow2")
|
||||
@volume_path=volume.path
|
||||
connection.define_domain_xml(template_xml)
|
||||
attr_accessor :password
|
||||
attr_writer :private_key, :private_key_path, :public_key, :public_key_path, :username
|
||||
|
||||
# Can be created by passing in :xml => "<xml to create domain/server>"
|
||||
# or by providing :template_options => {
|
||||
# :name => "", :cpus => 1, :memory_size => 256 , :volume_template
|
||||
# :}
|
||||
#
|
||||
# @returns server/domain created
|
||||
def initialize(attributes={} )
|
||||
self.xml ||= nil unless attributes[:xml]
|
||||
self.create_persistent ||=true unless attributes[:create_persistent]
|
||||
self.template_options ||=nil unless attributes[:template_options]
|
||||
super
|
||||
end
|
||||
|
||||
def save
|
||||
|
||||
end
|
||||
|
||||
def start
|
||||
requires :raw
|
||||
|
||||
unless @raw.active?
|
||||
begin
|
||||
@raw.create
|
||||
rescue
|
||||
print "An error occured :",$!,"\n"
|
||||
end
|
||||
raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if id
|
||||
|
||||
# first check if we have either xml or template_options
|
||||
if xml.nil? && template_options.nil?
|
||||
raise Fog::Errors::Error.new('Creating a new domain/server requires either xml or passing template_options')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def destroy(options={ :destroy_volumes => false})
|
||||
|
||||
#connection.volumes(name).destroy
|
||||
requires :raw
|
||||
if @raw.active?
|
||||
@raw.destroy
|
||||
end
|
||||
@raw.undefine
|
||||
end
|
||||
if !xml.nil? && !template_options.nil?
|
||||
raise Fog::Errors::Error.new('Creating a new domain/server requires either xml or passing template_options,not both')
|
||||
end
|
||||
|
||||
|
||||
def ready?
|
||||
|
||||
status == :running
|
||||
end
|
||||
# We have a template, let's generate some xml for it
|
||||
if !template_options.nil?
|
||||
|
||||
def reboot
|
||||
requires :raw
|
||||
|
||||
@raw.reboot
|
||||
end
|
||||
template_defaults={
|
||||
:cpus => 1,
|
||||
:memory_size => 256,
|
||||
:arch => "x86_64",
|
||||
:os => "hvm",
|
||||
:domain_type => "kvm",
|
||||
:name => "fog-#{SecureRandom.random_number*10E14.to_i.round}",
|
||||
|
||||
# Network options
|
||||
:interface_type => "nat", #or "bridge"
|
||||
:nat_network_name => "default",
|
||||
:bridge_name => "br0",
|
||||
|
||||
# Disk options
|
||||
:disk_type => "raw",
|
||||
:disk_size => 10,
|
||||
:disk_size_unit => "G",
|
||||
:disk_allocate => 1,
|
||||
:disk_allocate_unit => "G",
|
||||
:disk_extension => "img",
|
||||
:disk_template_name => nil,
|
||||
:poolname => nil,
|
||||
|
||||
# DVD options
|
||||
:iso_file => nil ,
|
||||
:iso_dir => "/var/lib/libvirt/images/"
|
||||
}
|
||||
|
||||
|
||||
def halt
|
||||
requires :raw
|
||||
|
||||
@raw.shutdown
|
||||
end
|
||||
|
||||
def resume
|
||||
requires :raw
|
||||
|
||||
@raw.resume
|
||||
end
|
||||
|
||||
def suspend
|
||||
requires :raw
|
||||
|
||||
@raw.suspend
|
||||
end
|
||||
|
||||
def status
|
||||
state=case @raw.info.state
|
||||
when 0 then :nostate
|
||||
when 1 then :running
|
||||
when 2 then :paused
|
||||
when 3 then :shuttingdown
|
||||
when 4 then :shutoff
|
||||
when 5 then :crashed
|
||||
template_options2=template_defaults.merge(template_options)
|
||||
template_options={ :disk_path => "#{template_options2[:name]}.#{template_options2[:disk_extension]}"}.merge(template_options2)
|
||||
|
||||
if !template_options[:disk_template_name].nil?
|
||||
# Clone the volume
|
||||
volume=connection.volumes.allocate(:name => template_options[:disk_template_name]).clone("#{template_options[:disk_path]}")
|
||||
template_options[:disk_path]=volume.path
|
||||
else
|
||||
# If no template volume was given, let's create our own volume
|
||||
volume=connection.volumes.create(:template_options => {
|
||||
:name => "#{template_options[:disk_name]}",
|
||||
:extension => "#{template_options[:disk_extension]}",
|
||||
:type => "#{template_options[:disk_type]}",
|
||||
:size => "#{template_options[:disk_size]}",
|
||||
:size_unit => "#{template_options[:disk_size_unit]}",
|
||||
:allocate => "#{template_options[:disk_allocate]}",
|
||||
:size_unit => "#{template_options[:disk_size_unit]}" })
|
||||
|
||||
template_options[:disk_path]=volume.path
|
||||
|
||||
end
|
||||
validate_template_options(template_options)
|
||||
|
||||
xml=xml_from_template(template_options)
|
||||
|
||||
end
|
||||
|
||||
# We either now have xml provided by the user or generated by the template
|
||||
if !xml.nil?
|
||||
domain=nil
|
||||
if create_persistent
|
||||
domain=connection.define_domain_xml(xml)
|
||||
else
|
||||
domain=connection.create_domain_xml(xml)
|
||||
end
|
||||
self.raw=domain
|
||||
end
|
||||
end
|
||||
|
||||
def validate_template_options(template_options)
|
||||
#if template_options[:disk_template_name].nil?
|
||||
# raise Fog::Errors::Error.new('In order to make the disk boot, we require a template volume we can clone')
|
||||
#end
|
||||
|
||||
end
|
||||
|
||||
def xml_from_template(template_options)
|
||||
|
||||
# We only want specific variables for ERB
|
||||
vars = ErbBinding.new(template_options)
|
||||
template_path=File.join(File.dirname(__FILE__),"templates","server.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
|
||||
|
||||
def username
|
||||
@username ||= 'root'
|
||||
end
|
||||
|
||||
def start
|
||||
requires :raw
|
||||
|
||||
unless @raw.active?
|
||||
begin
|
||||
@raw.create
|
||||
true
|
||||
rescue
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy(options={ :destroy_volumes => false})
|
||||
|
||||
#connection.volumes(name).destroy
|
||||
requires :raw
|
||||
if @raw.active?
|
||||
@raw.destroy
|
||||
end
|
||||
@raw.undefine
|
||||
end
|
||||
|
||||
|
||||
def reboot
|
||||
requires :raw
|
||||
|
||||
@raw.reboot
|
||||
end
|
||||
|
||||
|
||||
def halt
|
||||
requires :raw
|
||||
|
||||
@raw.shutdown
|
||||
end
|
||||
|
||||
def resume
|
||||
requires :raw
|
||||
|
||||
@raw.resume
|
||||
end
|
||||
|
||||
def suspend
|
||||
requires :raw
|
||||
|
||||
@raw.suspend
|
||||
end
|
||||
|
||||
def state
|
||||
state=case @raw.info.state
|
||||
when 0 then :nostate
|
||||
when 1 then :running
|
||||
when 2 then :paused
|
||||
when 3 then :shuttingdown
|
||||
when 4 then :shutoff
|
||||
when 5 then :crashed
|
||||
end
|
||||
return state
|
||||
end
|
||||
|
||||
def save()
|
||||
|
||||
raise Fog::Errors::Error.new('Updating an existing server is not yet implemented. Contributions welcome!')
|
||||
|
||||
def ready?
|
||||
state == :running
|
||||
end
|
||||
|
||||
def scp(local_path, remote_path, upload_options = {})
|
||||
raise 'Not Implemented'
|
||||
requires :addresses, :username
|
||||
|
||||
scp_options = {}
|
||||
scp_options[:key_data] = [private_key] if private_key
|
||||
Fog::SCP.new(addresses['public'].first, username, options).upload(local_path, remote_path, scp_options)
|
||||
end
|
||||
|
||||
def setup(credentials = {})
|
||||
requires :addresses, :identity, :public_key, :username
|
||||
Fog::SSH.new(addresses['public'].first, username, credentials).run([
|
||||
%{mkdir .ssh},
|
||||
%{echo "#{public_key}" >> ~/.ssh/authorized_keys},
|
||||
%{echo "#{attributes.to_json}" >> ~/attributes.json},
|
||||
%{echo "#{metadata.to_json}" >> ~/metadata.json}
|
||||
])
|
||||
rescue Errno::ECONNREFUSED
|
||||
sleep(1)
|
||||
retry
|
||||
end
|
||||
|
||||
|
||||
##Note this requires arpwatch to be running
|
||||
##and chmod o+x /var/lib/arpwatch
|
||||
|
||||
def addresses
|
||||
mac=self.mac
|
||||
options={}
|
||||
ipaddress=nil
|
||||
if connected_by_ssh?
|
||||
#command="arp -an|grep #{mac}|cut -d ' ' -f 2| cut -d '(' -f 2| cut -d ')' -f 1"
|
||||
#command="grep #{mac} /var/log/daemon.log |sed -e 's/^.*address //'|cut -d ' ' -f 1"
|
||||
command="grep #{mac} /var/lib/arpwatch/arp.dat|cut -f 2"
|
||||
result=Fog::SSH.new(connection.hostname, "patrick.debois", options).run(command)
|
||||
if result.first.status == 0
|
||||
ipaddress=result.first.stdout.strip
|
||||
#TODO check for valid IP
|
||||
#TODO check time validity
|
||||
else
|
||||
#cat /var/log/daemon.log|grep "52:54:00:52:f6:22"|
|
||||
end
|
||||
else
|
||||
#local execute arp -an to get the ip
|
||||
def stop
|
||||
requires :raw
|
||||
|
||||
@raw.shutdown
|
||||
end
|
||||
return { 'public' => [ipaddress], 'private' => [ipaddress]}
|
||||
end
|
||||
|
||||
def mac
|
||||
|
||||
def ssh(commands)
|
||||
requires :addresses, :identity, :username
|
||||
|
||||
options = {}
|
||||
#options[:key_data] = [private_key] if private_key
|
||||
|
||||
require 'net/ssh/proxy/command'
|
||||
options={ :password => "mccloud"}
|
||||
if connected_by_ssh?
|
||||
relay=connection.hostname
|
||||
proxy = Net::SSH::Proxy::Command.new('ssh -l patrick.debois '+relay+' nc %h %p')
|
||||
options[:proxy]= proxy
|
||||
end
|
||||
#Fog::SSH.new("192.168.122.48", "vagrant", options).run(commands)
|
||||
Fog::SSH.new(addresses['public'].first, "mccloud", options).run(commands)
|
||||
|
||||
end
|
||||
|
||||
def stop
|
||||
requires :raw
|
||||
|
||||
@raw.shutdown
|
||||
end
|
||||
|
||||
def username
|
||||
@username ||= 'root'
|
||||
end
|
||||
|
||||
def mac
|
||||
require "rexml/document"
|
||||
require 'erb'
|
||||
|
||||
mac = document("domain/devices/interface/mac", "address")
|
||||
return mac
|
||||
end
|
||||
|
||||
def vnc_port
|
||||
|
||||
port = document("domain/devices/graphics[@type='vnc']", "port")
|
||||
return port
|
||||
end
|
||||
|
||||
def name
|
||||
requires :raw
|
||||
raw.name
|
||||
end
|
||||
|
||||
def uuid
|
||||
requires :raw
|
||||
raw.uuid
|
||||
end
|
||||
|
||||
def memory_size
|
||||
requires :raw
|
||||
raw.memory_size
|
||||
end
|
||||
|
||||
def cpus
|
||||
requires :raw
|
||||
raw.cpus
|
||||
end
|
||||
|
||||
def os_type
|
||||
requires :raw
|
||||
raw.os_type
|
||||
end
|
||||
|
||||
def xml_desc
|
||||
requires :raw
|
||||
raw.xml_desc
|
||||
end
|
||||
|
||||
##Note this requires arpwatch to be running
|
||||
##and chmod o+x /var/lib/arpwatch
|
||||
|
||||
def addresses
|
||||
mac=self.mac
|
||||
ipaddress=nil
|
||||
if @connection.uri.ssh_enabled?
|
||||
#command="arp -an|grep #{mac}|cut -d ' ' -f 2| cut -d '(' -f 2| cut -d ')' -f 1"
|
||||
#command="grep #{mac} /var/log/daemon.log |sed -e 's/^.*address //'|cut -d ' ' -f 1"
|
||||
# TODO: check if this files exists
|
||||
# Check if it is readable
|
||||
command="grep #{mac} /var/lib/arpwatch/arp.dat|cut -f 2|tail -1"
|
||||
|
||||
# TODO: we need to take the time into account, when IP's are re-allocated, we might be executing
|
||||
# On the wrong host
|
||||
|
||||
# We can get the host, the
|
||||
user=connection.uri.user #could be nil
|
||||
host=connection.uri.host
|
||||
keyfile=connection.uri.keyfile
|
||||
port=connection.uri.port
|
||||
|
||||
options={}
|
||||
options[:keys]=[ keyfile ] unless keyfile.nil?
|
||||
options[:port]=port unless keyfile.nil?
|
||||
options[:paranoid]=true if connection.uri.no_verify?
|
||||
|
||||
result=Fog::SSH.new(host, user, options).run(command)
|
||||
if result.first.status == 0
|
||||
ipaddress=result.first.stdout.strip
|
||||
#TODO check for valid IP
|
||||
#TODO check time validity
|
||||
else
|
||||
# We couldn't retrieve any IP information
|
||||
return { :public => nil , :private => nil}
|
||||
end
|
||||
else
|
||||
# TODO for locat execute
|
||||
#No ssh just do it locally
|
||||
#cat /var/log/daemon.log|grep "52:54:00:52:f6:22"|
|
||||
# or local execute arp -an to get the ip (as a last resort)
|
||||
|
||||
end
|
||||
return { :public => [ipaddress], :private => [ipaddress]}
|
||||
end
|
||||
|
||||
def private_ip_address
|
||||
ip_address(:private)
|
||||
end
|
||||
|
||||
def public_ip_address
|
||||
ip_address(:public)
|
||||
end
|
||||
|
||||
def ip_address(key)
|
||||
ips=addresses[key]
|
||||
unless ips.nil?
|
||||
return ips.first
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def private_key_path
|
||||
@private_key_path ||= Fog.credentials[:private_key_path]
|
||||
@private_key_path &&= File.expand_path(@private_key_path)
|
||||
end
|
||||
|
||||
def private_key
|
||||
@private_key ||= private_key_path && File.read(private_key_path)
|
||||
end
|
||||
|
||||
def public_key_path
|
||||
@public_key_path ||= Fog.credentials[:public_key_path]
|
||||
@public_key_path &&= File.expand_path(@public_key_path)
|
||||
end
|
||||
|
||||
def public_key
|
||||
@public_key ||= public_key_path && File.read(public_key_path)
|
||||
end
|
||||
|
||||
def ssh(commands)
|
||||
requires :public_ip_address, :username
|
||||
|
||||
#requires :password, :private_key
|
||||
ssh_options={}
|
||||
ssh_options[:password] = password unless password.nil?
|
||||
ssh_options[:key_data] = [private_key] if private_key
|
||||
ssh_options[:proxy]= ssh_proxy unless ssh_proxy.nil?
|
||||
|
||||
Fog::SSH.new(public_ip_address, @username, ssh_options).run(commands)
|
||||
|
||||
end
|
||||
|
||||
|
||||
def ssh_proxy
|
||||
proxy=nil
|
||||
if @connection.uri.ssh_enabled?
|
||||
relay=connection.uri.host
|
||||
user_string=""
|
||||
user_string="-l #{connection.uri.user}" unless connection.uri.user.nil?
|
||||
proxy = Net::SSH::Proxy::Command.new("ssh #{user_string} "+relay+" nc %h %p")
|
||||
return proxy
|
||||
else
|
||||
return nil
|
||||
# This is a direct connection, so we don't need a proxy to be set
|
||||
end
|
||||
end
|
||||
|
||||
# Transfers a file
|
||||
def scp(local_path, remote_path, upload_options = {})
|
||||
requires :public_ip_address, :username
|
||||
|
||||
scp_options = {}
|
||||
scp_options[:password] = password unless self.password.nil?
|
||||
scp_options[:key_data] = [private_key] if self.private_key
|
||||
scp_options[:proxy]= ssh_proxy unless self.ssh_proxy.nil?
|
||||
|
||||
Fog::SCP.new(public_ip_address, username, scp_options).upload(local_path, remote_path, upload_options)
|
||||
end
|
||||
|
||||
|
||||
# Sets up a new key
|
||||
def setup(credentials = {})
|
||||
requires :public_key, :public_ip_address, :username
|
||||
require 'multi_json'
|
||||
|
||||
credentials[:proxy]= ssh_proxy unless ssh_proxy.nil?
|
||||
credentials[:password] = password unless self.password.nil?
|
||||
credentails[:key_data] = [private_key] if self.private_key
|
||||
|
||||
commands = [
|
||||
%{mkdir .ssh},
|
||||
# %{passwd -l #{username}}, #Not sure if we need this here
|
||||
# %{echo "#{MultiJson.encode(attributes)}" >> ~/attributes.json}
|
||||
]
|
||||
if public_key
|
||||
commands << %{echo "#{public_key}" >> ~/.ssh/authorized_keys}
|
||||
end
|
||||
|
||||
# wait for domain to be ready
|
||||
Timeout::timeout(360) do
|
||||
begin
|
||||
Timeout::timeout(8) do
|
||||
Fog::SSH.new(public_ip_address, username, credentials.merge(:timeout => 4)).run('pwd')
|
||||
end
|
||||
rescue Errno::ECONNREFUSED
|
||||
sleep(2)
|
||||
retry
|
||||
rescue Net::SSH::AuthenticationFailed, Timeout::Error
|
||||
retry
|
||||
end
|
||||
end
|
||||
Fog::SSH.new(public_ip_address, username, credentials).run(commands)
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def raw
|
||||
@raw
|
||||
end
|
||||
|
||||
def raw=(new_raw)
|
||||
@raw = new_raw
|
||||
|
||||
raw_attributes = {
|
||||
:id => new_raw.uuid,
|
||||
}
|
||||
|
||||
merge_attributes(raw_attributes)
|
||||
end
|
||||
|
||||
|
||||
# finds a value from xml
|
||||
def document path, attribute=nil
|
||||
xml = REXML::Document.new(xml_desc)
|
||||
attribute.nil? ? xml.elements[path].text : xml.elements[path].attributes[attribute]
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def raw
|
||||
@raw
|
||||
end
|
||||
|
||||
def raw=(new_raw)
|
||||
@raw = new_raw
|
||||
|
||||
raw_attributes = {
|
||||
:id => new_raw.uuid,
|
||||
:memory_size => new_raw.info.max_mem ,
|
||||
:name => new_raw.name,
|
||||
:cpus => new_raw.info.nr_virt_cpu,
|
||||
:os_type_id => new_raw.os_type,
|
||||
:xml_desc => new_raw.xml_desc,
|
||||
|
||||
}
|
||||
|
||||
merge_attributes(raw_attributes)
|
||||
end
|
||||
|
||||
# finds a value from xml
|
||||
def document path, attribute=nil
|
||||
xml = REXML::Document.new(xml_desc)
|
||||
attribute.nil? ? xml.elements[path].text : xml.elements[path].attributes[attribute]
|
||||
end
|
||||
|
||||
def connected_by_ssh?
|
||||
return connection.uri.include?("+ssh")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,21 +9,34 @@ module Fog
|
|||
|
||||
model Fog::Compute::Libvirt::Server
|
||||
|
||||
def all
|
||||
|
||||
data = connection.list_defined_domains.map do |machine|
|
||||
{
|
||||
:raw => connection.lookup_domain_by_name(machine)
|
||||
}
|
||||
def all(filter=nil)
|
||||
data=[]
|
||||
if filter.nil?
|
||||
connection.list_defined_domains.map do |server|
|
||||
data << { :raw => connection.lookup_domain_by_name(domain) }
|
||||
end
|
||||
|
||||
connection.list_domains.each do |domain|
|
||||
data << { :raw => connection.lookup_domain_by_id(domain) }
|
||||
end
|
||||
else
|
||||
domain=nil
|
||||
begin
|
||||
domain=self.get_by_name(filter[:name]) if filter.has_key?(:name)
|
||||
domain=self.get_by_uuid(filter[:uuid]) if filter.has_key?(:uuid)
|
||||
|
||||
rescue ::Libvirt::RetrieveError
|
||||
return nil
|
||||
end
|
||||
data << { :raw => domain }
|
||||
end
|
||||
|
||||
connection.list_domains.each do |machine|
|
||||
data << {
|
||||
:raw => connection.lookup_domain_by_id(machine)
|
||||
}
|
||||
end
|
||||
load(data)
|
||||
end
|
||||
|
||||
def get(key)
|
||||
self.all(:key => key).first
|
||||
end
|
||||
|
||||
def bootstrap(new_attributes = {})
|
||||
raise 'Not Implemented'
|
||||
|
@ -34,16 +47,19 @@ module Fog
|
|||
# server
|
||||
end
|
||||
|
||||
private
|
||||
# Retrieve the server by uuid
|
||||
def get(server_id)
|
||||
machine=connection.lookup_domain_by_uuid(server_id)
|
||||
new(:raw => machine)
|
||||
def get_by_uuid(uuid)
|
||||
server=connection.lookup_domain_by_uuid(uuid)
|
||||
return server
|
||||
# new(:raw => machine)
|
||||
end
|
||||
|
||||
# Retrieve the server by name
|
||||
def get_by_name(name)
|
||||
machine=connection.lookup_domain_by_name(name)
|
||||
new(:raw => machine)
|
||||
server=connection.lookup_domain_by_name(name)
|
||||
return server
|
||||
# new(:raw => machine)
|
||||
end
|
||||
|
||||
end #class
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
<domain type='kvm'>
|
||||
<name><%= name %></name>
|
||||
<memory><%= memory_size %></memory>
|
||||
<vcpu><%= cpus %></vcpu>
|
||||
<os>
|
||||
<type arch='<%= arch %>'><%= os %></type>
|
||||
<boot dev='hd'/>
|
||||
</os>
|
||||
<features>
|
||||
<acpi/>
|
||||
<apic/>
|
||||
<pae/>
|
||||
</features>
|
||||
<clock offset='utc'/>
|
||||
<devices>
|
||||
<disk type='file' device='disk'>
|
||||
<driver name='qemu' type='qcow2'/>
|
||||
<source file='<%= volume_path %>'/>
|
||||
<target dev='vda' bus='virtio'/>
|
||||
</disk>
|
||||
<interface type='bridge'>
|
||||
<source bridge='<%= @bridge_name %>'/>
|
||||
<model type='virtio'/>
|
||||
</interface>
|
||||
<serial type='pty'>
|
||||
<target port='0'/>
|
||||
</serial>
|
||||
<console type='pty'>
|
||||
<target port='0'/>
|
||||
</console>
|
||||
<input type='mouse' bus='ps2'/>
|
||||
<graphics type='vnc' port='-1' autoport='yes' keymap='en-us'/>
|
||||
<video>
|
||||
<model type='cirrus' vram='9216' heads='1'/>
|
||||
</video>
|
||||
</devices>
|
||||
</domain>
|
57
lib/fog/compute/models/libvirt/templates/server.xml.erb
Normal file
57
lib/fog/compute/models/libvirt/templates/server.xml.erb
Normal file
|
@ -0,0 +1,57 @@
|
|||
<domain type='<%= domain_type %>'>
|
||||
<name><%= name %></name>
|
||||
<memory><%= memory_size %></memory>
|
||||
<vcpu><%= cpus %></vcpu>
|
||||
<os>
|
||||
<type arch='<%= arch %>'><%= os %></type>
|
||||
<boot dev='hd'/>
|
||||
<% if !iso_file.nil? %>
|
||||
|
||||
<boot dev='cdrom'/>
|
||||
<% end %>
|
||||
</os>
|
||||
<features>
|
||||
<acpi/>
|
||||
<apic/>
|
||||
<pae/>
|
||||
</features>
|
||||
<clock offset='utc'/>
|
||||
<devices>
|
||||
<disk type='file' device='disk'>
|
||||
<driver name='qemu' type='<%= disk_type %>'/>
|
||||
<source file='<%= "#{disk_path}" %>'/>
|
||||
<target dev='vda' bus='virtio'/>
|
||||
</disk>
|
||||
<% if !iso_file.nil? %>
|
||||
<disk type='file' device='cdrom'>
|
||||
<driver name='qemu' type='raw'/>
|
||||
<source file='<%= "#{iso_dir}/#{iso_file}" %>'/>
|
||||
<target dev='hdc' bus='ide'/>
|
||||
<readonly/>
|
||||
<address type='drive' controller='0' bus='1' unit='0'/>
|
||||
</disk>
|
||||
<% end %>
|
||||
<% if interface_type=="bridge" %>
|
||||
<interface type="bridge">
|
||||
<source bridge='<%= bridge_name %>'/>
|
||||
<model type='virtio'/>
|
||||
<% end %>
|
||||
<% if interface_type=="nat" %>
|
||||
<interface type='network'>
|
||||
<source network='<%= nat_network_name %>'/>
|
||||
<model type='virtio'/>
|
||||
<% end %>
|
||||
</interface>
|
||||
<serial type='pty'>
|
||||
<target port='0'/>
|
||||
</serial>
|
||||
<console type='pty'>
|
||||
<target port='0'/>
|
||||
</console>
|
||||
<input type='mouse' bus='ps2'/>
|
||||
<graphics type='vnc' port='-1' autoport='yes' keymap='en-us'/>
|
||||
<video>
|
||||
<model type='cirrus' vram='9216' heads='1'/>
|
||||
</video>
|
||||
</devices>
|
||||
</domain>
|
|
@ -1,14 +0,0 @@
|
|||
<volume>
|
||||
<name>ubuntu.qcow2</name>
|
||||
<allocation unit="G">10</allocation>
|
||||
<capacity unit="G">10</capacity>
|
||||
<target>
|
||||
<format type="qcow2"/>
|
||||
<permissions>
|
||||
<owner>0</owner>
|
||||
<group>0</group>
|
||||
<mode>0744</mode>
|
||||
<label>virt_image_t</label>
|
||||
</permissions>
|
||||
</target>
|
||||
</volume>
|
14
lib/fog/compute/models/libvirt/templates/volume.xml.erb
Normal file
14
lib/fog/compute/models/libvirt/templates/volume.xml.erb
Normal file
|
@ -0,0 +1,14 @@
|
|||
<volume>
|
||||
<name><%= "#{name}.#{extension}" %></name>
|
||||
<allocation unit="<%= allocate_unit %>"><%= allocate %></allocation>
|
||||
<capacity unit="<%= size_unit %>"><%= size %></capacity>
|
||||
<target>
|
||||
<format type="<%= type %>"/>
|
||||
<permissions>
|
||||
<owner>0</owner>
|
||||
<group>0</group>
|
||||
<mode>0744</mode>
|
||||
<label>virt_image_t</label>
|
||||
</permissions>
|
||||
</target>
|
||||
</volume>
|
|
@ -1,21 +1,10 @@
|
|||
require "rexml/document"
|
||||
require 'erb'
|
||||
require 'ostruct'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
module LibvirtUtil
|
||||
# return templated xml to be used by libvirt
|
||||
def template_xml
|
||||
ERB.new(template, nil, '-').result(binding)
|
||||
end
|
||||
|
||||
private
|
||||
# template file that contain our xml template
|
||||
def template
|
||||
File.read("#{File.dirname(__FILE__)}/templates/#{template_path}")
|
||||
rescue => e
|
||||
warn "failed to read template #{template_path}: #{e}"
|
||||
end
|
||||
|
||||
# finds a value from xml
|
||||
def document path, attribute=nil
|
||||
|
@ -23,6 +12,14 @@ module Fog
|
|||
xml = REXML::Document.new(@xml_desc)
|
||||
attribute.nil? ? xml.elements[path].text : xml.elements[path].attributes[attribute]
|
||||
end
|
||||
|
||||
class ErbBinding < OpenStruct
|
||||
def get_binding
|
||||
return binding()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +1,8 @@
|
|||
require 'fog/core/model'
|
||||
require 'fog/compute/models/libvirt/util'
|
||||
require 'rexml/document'
|
||||
require 'erb'
|
||||
require 'securerandom'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
|
@ -6,130 +10,201 @@ module Fog
|
|||
|
||||
class Volume < Fog::Model
|
||||
|
||||
identity :id
|
||||
include Fog::Compute::LibvirtUtil
|
||||
|
||||
identity :key
|
||||
|
||||
attribute :poolname
|
||||
attribute :xml
|
||||
attribute :create_persistent
|
||||
|
||||
attribute :xml
|
||||
attribute :template_options
|
||||
|
||||
# attribute :key
|
||||
attribute :path
|
||||
attribute :name
|
||||
attribute :capacity
|
||||
attribute :allocation
|
||||
attribute :type
|
||||
|
||||
# Can be created by passing in :xml => "<xml to create volume>"
|
||||
# A volume always belongs to a pool, :pool => "<name of pool>"
|
||||
# A volume always belongs to a pool, :poolname => "<name of pool>"
|
||||
#
|
||||
# @returns volume created
|
||||
def initialize(attributes={} )
|
||||
self.xml ||= nil unless attributes[:xml]
|
||||
self.poolname ||= nil unless attributes[:poolname]
|
||||
self.create_persistent ||=true unless attribues[:create_persistent]
|
||||
|
||||
super
|
||||
|
||||
# Try to guess the default/first pool of no poolname was specificed
|
||||
default_pool_name="default"
|
||||
default_pool=connection.pools.all(:name => "default")
|
||||
if default_pool.nil?
|
||||
first_pool=connection.pools.first
|
||||
if first_pool.nil?
|
||||
raise Fog::Errors::Error.new('We could not find a pool called "default" and there was no other pool defined')
|
||||
else
|
||||
default_pool_name=first_pool.name
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
self.poolname ||= default_pool_name unless attributes[:poolname]
|
||||
|
||||
end
|
||||
|
||||
# Takes a pool and xml to create the volume
|
||||
# Takes a pool and either uses :xml or :template_options->xml to create the volume
|
||||
def save
|
||||
requires :xml
|
||||
requires :poolname
|
||||
|
||||
unless xml.nil?
|
||||
volume=nil
|
||||
unless poolname.nil?
|
||||
pool=connection.lookup_storage_pool_by_name(poolname)
|
||||
if create_persistent
|
||||
volume=pool.define_volume_xml(xml)
|
||||
else
|
||||
# requires :xml
|
||||
# requires :poolname
|
||||
|
||||
if poolname
|
||||
# :disk_type => "raw",
|
||||
# :disk_extension => "img",
|
||||
# :disk_size => "10000",
|
||||
# We have a template, let's generate some xml for it
|
||||
if !template_options.nil?
|
||||
|
||||
template_defaults={
|
||||
:type => "raw",
|
||||
:extension => "img",
|
||||
:name => "fog-#{SecureRandom.random_number*10E14.to_i.round}",
|
||||
:size => 10,
|
||||
:allocate_unit => "G",
|
||||
:size_unit => "G",
|
||||
:allocate => 1,
|
||||
}
|
||||
template_options2=template_defaults.merge(template_options)
|
||||
template_options={ :path => "#{template_options2[:name]}.#{template_options2[:extension]}"}.merge(template_options2)
|
||||
|
||||
validate_template_options(template_options)
|
||||
|
||||
xml=xml_from_template(template_options)
|
||||
# require 'pp'
|
||||
# pp xml
|
||||
# exit
|
||||
|
||||
end
|
||||
|
||||
unless xml.nil?
|
||||
volume=nil
|
||||
unless poolname.nil?
|
||||
pool=connection.lookup_storage_pool_by_name(poolname)
|
||||
volume=pool.create_volume_xml(xml)
|
||||
self.raw=volume
|
||||
true
|
||||
else
|
||||
raise Fog::Errors::Error.new('Creating a new volume requires a pool name or uuid')
|
||||
false
|
||||
end
|
||||
self.raw=volume
|
||||
true
|
||||
else
|
||||
raise Fog::Errors::Error.new('Creating a new volume requires a pool name or uuid')
|
||||
raise Fog::Errors::Error.new('Creating a new volume requires non empty xml')
|
||||
false
|
||||
end
|
||||
else
|
||||
raise Fog::Errors::Error.new('Creating a new volume requires non empty xml')
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def validate_template_options(template_options)
|
||||
# Here we can validate the template_options
|
||||
end
|
||||
|
||||
def xml_from_template(template_options)
|
||||
|
||||
# We only want specific variables for ERB
|
||||
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
|
||||
|
||||
# Destroy a volume
|
||||
def destroy
|
||||
requires :raw
|
||||
raw.delete
|
||||
true
|
||||
end
|
||||
|
||||
# Wipes a volume , zeroes disk
|
||||
def wipe
|
||||
requires :raw
|
||||
raw.wipe
|
||||
true
|
||||
end
|
||||
|
||||
# Clones this volume to the name provided
|
||||
def clone(name)
|
||||
pool=@raw.pool
|
||||
xml = REXML::Document.new(xml_desc)
|
||||
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)
|
||||
end
|
||||
|
||||
def key
|
||||
requires :raw
|
||||
raw.key
|
||||
end
|
||||
|
||||
def path
|
||||
requires :raw
|
||||
raw.path
|
||||
end
|
||||
|
||||
def name
|
||||
requires :raw
|
||||
raw.name
|
||||
end
|
||||
|
||||
def xml_desc
|
||||
requires :raw
|
||||
raw.xml_desc
|
||||
end
|
||||
|
||||
|
||||
# Destroy a volume
|
||||
def destroy
|
||||
requires :raw
|
||||
raw.delete
|
||||
true
|
||||
def allocation
|
||||
requires :raw
|
||||
raw.info.allocation
|
||||
end
|
||||
|
||||
def capacity
|
||||
requires :raw
|
||||
@capacity=raw.info.capacity
|
||||
end
|
||||
|
||||
def type
|
||||
requires :raw
|
||||
@type=raw.info.type
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def raw
|
||||
@raw
|
||||
end
|
||||
|
||||
def raw=(new_raw)
|
||||
@raw = new_raw
|
||||
|
||||
raw_attributes = {
|
||||
:key => new_raw.key,
|
||||
:path => new_raw.path,
|
||||
:name => new_raw.name,
|
||||
:allocation => new_raw.info.allocation,
|
||||
:capacity => new_raw.info.capacity,
|
||||
:type => new_raw.info.type
|
||||
}
|
||||
|
||||
merge_attributes(raw_attributes)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Wipes a volume , zeroes disk
|
||||
def wipe
|
||||
requires :raw
|
||||
raw.wipe
|
||||
true
|
||||
end
|
||||
|
||||
# Clones this volume to the name provided
|
||||
def clone(name)
|
||||
pool=@raw.pool
|
||||
xml = REXML::Document.new(xml_desc)
|
||||
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.get(:name => name)
|
||||
end
|
||||
|
||||
def key
|
||||
requires :raw
|
||||
raw.key
|
||||
end
|
||||
|
||||
def path
|
||||
requires :raw
|
||||
raw.path
|
||||
end
|
||||
|
||||
def name
|
||||
requires :raw
|
||||
raw.name
|
||||
end
|
||||
|
||||
def xml_desc
|
||||
requires :raw
|
||||
raw.xml_desc
|
||||
end
|
||||
|
||||
|
||||
def allocation
|
||||
requires :raw
|
||||
raw.info.allocation
|
||||
end
|
||||
|
||||
def capacity
|
||||
requires :raw
|
||||
raw.info.capacity
|
||||
end
|
||||
|
||||
def type
|
||||
requires :raw
|
||||
raw.info.type
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def raw
|
||||
@raw
|
||||
end
|
||||
|
||||
def raw=(new_raw)
|
||||
@raw = new_raw
|
||||
|
||||
raw_attributes = {
|
||||
:id => new_raw.key,
|
||||
}
|
||||
|
||||
merge_attributes(raw_attributes)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,36 +9,45 @@ module Fog
|
|||
|
||||
model Fog::Compute::Libvirt::Volume
|
||||
|
||||
def all
|
||||
def all(filter=nil)
|
||||
data=[]
|
||||
connection.list_storage_pools.each do |poolname|
|
||||
pool=connection.lookup_storage_pool_by_name(poolname)
|
||||
pool.list_volumes.each do |volumename|
|
||||
data << { :raw => pool.lookup_volume_by_name(volumename) }
|
||||
if filter.nil?
|
||||
connection.list_storage_pools.each do |poolname|
|
||||
pool=connection.lookup_storage_pool_by_name(poolname)
|
||||
pool.list_volumes.each do |volumename|
|
||||
data << { :raw => pool.lookup_volume_by_name(volumename) }
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
volume=nil
|
||||
begin
|
||||
volume=self.get_by_name(filter[:name]) if filter.has_key?(:name)
|
||||
volume=self.get_by_key(filter[:key]) if filter.has_key?(:key)
|
||||
volume=self.get_by_path(filter[:path]) if filter.has_key?(:path)
|
||||
rescue ::Libvirt::RetrieveError
|
||||
return nil
|
||||
end
|
||||
data << { :raw => volume}
|
||||
end
|
||||
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Retrieve the volume by type
|
||||
def get(param)
|
||||
volume=nil
|
||||
volume=get_by_key(param[:key]) if param.has_key?(:key)
|
||||
volume=get_by_path(param[:path]) if param.has_key?(:path)
|
||||
volume=get_by_name(param[:name]) if param.has_key?(:name)
|
||||
return volume
|
||||
def get(key)
|
||||
self.all(:key => key).first
|
||||
end
|
||||
|
||||
|
||||
# Retrieve the volume by name
|
||||
def get_by_name(name)
|
||||
connection.list_storage_pools.each do |poolname|
|
||||
pool=connection.lookup_storage_pool_by_name(poolname)
|
||||
volume=pool.lookup_volume_by_name(name)
|
||||
unless volume.nil?
|
||||
return new(:raw => volume)
|
||||
volume=pool.lookup_volume_by_name(name)
|
||||
unless volume.nil?
|
||||
return volume
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
@ -46,12 +55,12 @@ module Fog
|
|||
def get_by_key(key)
|
||||
connection.list_storage_pools.each do |poolname|
|
||||
pool=connection.lookup_storage_pool_by_name(poolname)
|
||||
volume=pool.lookup_volume_by_key(key)
|
||||
unless volume.nil?
|
||||
return new(:raw => volume)
|
||||
volume=pool.lookup_volume_by_key(key)
|
||||
unless volume.nil?
|
||||
return volume
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
@ -59,15 +68,15 @@ module Fog
|
|||
def get_by_path(path)
|
||||
connection.list_storage_pools.each do |poolname|
|
||||
pool=connection.lookup_storage_pool_by_name(poolname)
|
||||
volume=pool.lookup_volume_by_key(path)
|
||||
unless volume.nil?
|
||||
return new(:raw => volume)
|
||||
volume=pool.lookup_volume_by_key(path)
|
||||
unless volume.nil?
|
||||
return volume
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue