mirror of
https://github.com/fog/fog.git
synced 2022-11-09 13:51:43 -05:00
First cut at libvirt integration. Lots of features missing, but it proves the point
This commit is contained in:
parent
f3d92316b5
commit
1e31e1e41d
21 changed files with 914 additions and 1 deletions
|
@ -61,6 +61,7 @@ require 'fog/bin/dnsmadeeasy'
|
|||
require 'fog/bin/ecloud'
|
||||
require 'fog/bin/go_grid'
|
||||
require 'fog/bin/google'
|
||||
require 'fog/bin/libvirt'
|
||||
require 'fog/bin/linode'
|
||||
require 'fog/bin/local'
|
||||
require 'fog/bin/new_servers'
|
||||
|
|
53
lib/fog/bin/libvirt.rb
Normal file
53
lib/fog/bin/libvirt.rb
Normal file
|
@ -0,0 +1,53 @@
|
|||
module Libvirt # deviates from other bin stuff to accomodate gem
|
||||
class << self
|
||||
|
||||
def class_for(key)
|
||||
case key
|
||||
when :compute
|
||||
Fog::Compute::Libvirt
|
||||
else
|
||||
raise ArgumentError, "Unrecognized service: #{key}"
|
||||
end
|
||||
end
|
||||
|
||||
def [](service)
|
||||
@@connections ||= Hash.new do |hash, key|
|
||||
hash[key] = case key
|
||||
when :compute
|
||||
Formatador.display_line("[yellow][WARN] Libvirt[:compute] is deprecated, use Compute[:libvirt] instead[/]")
|
||||
Fog::Compute.new(:provider => 'Libvirt')
|
||||
else
|
||||
raise ArgumentError, "Unrecognized service: #{key.inspect}"
|
||||
end
|
||||
end
|
||||
@@connections[service]
|
||||
end
|
||||
|
||||
def available?
|
||||
availability = !Gem.source_index.find_name('ruby-libvirt').empty?
|
||||
if availability
|
||||
for service in services
|
||||
for collection in self.class_for(service).collections
|
||||
unless self.respond_to?(collection)
|
||||
self.class_eval <<-EOS, __FILE__, __LINE__
|
||||
def self.#{collection}
|
||||
self[:#{service}].#{collection}
|
||||
end
|
||||
EOS
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
availability
|
||||
end
|
||||
|
||||
def collections
|
||||
services.map {|service| self[service].collections}.flatten.sort_by {|service| service.to_s}
|
||||
end
|
||||
|
||||
def services
|
||||
Fog::Libvirt.services
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -47,6 +47,9 @@ module Fog
|
|||
when 'VirtualBox'
|
||||
require 'fog/compute/virtual_box'
|
||||
Fog::Compute::VirtualBox.new(attributes)
|
||||
when :libvirt
|
||||
require 'fog/compute/libvirt'
|
||||
Fog::Compute::Libvirt.new(attributes)
|
||||
when :voxel
|
||||
require 'fog/compute/voxel'
|
||||
Fog::Compute::Voxel.new(attributes)
|
||||
|
@ -57,7 +60,7 @@ module Fog
|
|||
|
||||
def self.servers
|
||||
servers = []
|
||||
for provider in [:aws, :bluebox, :brightbox, :ecloud, :gogrid, :linode, :newservers, :ninefold, :rackspace, :slicehost, :stormondemand, :virtualbox, :voxel]
|
||||
for provider in [:aws, :bluebox, :brightbox, :ecloud, :gogrid, :libvirt, :linode, :newservers, :ninefold, :rackspace, :slicehost, :stormondemand, :virtualbox, :voxel]
|
||||
begin
|
||||
servers.concat(self[provider].servers)
|
||||
rescue # ignore any missing credentials/etc
|
||||
|
|
49
lib/fog/compute/libvirt.rb
Normal file
49
lib/fog/compute/libvirt.rb
Normal file
|
@ -0,0 +1,49 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class Libvirt < Fog::Service
|
||||
|
||||
requires :libvirt_uri
|
||||
|
||||
model_path 'fog/compute/models/libvirt'
|
||||
model :server
|
||||
collection :servers
|
||||
model :network
|
||||
collection :networks
|
||||
model :interface
|
||||
collection :interfaces
|
||||
model :volume
|
||||
collection :volumes
|
||||
model :pool
|
||||
collection :pools
|
||||
|
||||
class Mock
|
||||
|
||||
def initialize(options={})
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Real
|
||||
|
||||
def initialize(options={})
|
||||
@uri = options[:libvirt_uri]
|
||||
|
||||
#libvirt is part of the gem => ruby-libvirt
|
||||
require 'libvirt'
|
||||
@connection = ::Libvirt::open(@uri)
|
||||
end
|
||||
|
||||
# hack to provide 'requests'
|
||||
def method_missing(method_sym, *arguments, &block)
|
||||
if @connection.respond_to?(method_sym)
|
||||
@connection.send(method_sym, *arguments)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
46
lib/fog/compute/models/libvirt/interface.rb
Normal file
46
lib/fog/compute/models/libvirt/interface.rb
Normal file
|
@ -0,0 +1,46 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Libvirt
|
||||
|
||||
class Interface < Fog::Model
|
||||
|
||||
identity :id
|
||||
|
||||
attribute :mac
|
||||
attribute :name
|
||||
attribute :xml_desc
|
||||
|
||||
def destroy
|
||||
requires :raw
|
||||
raw.delete
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def raw
|
||||
@raw
|
||||
end
|
||||
|
||||
def raw=(new_raw)
|
||||
@raw = new_raw
|
||||
|
||||
raw_attributes = {
|
||||
:id => new_raw.name,
|
||||
:name => new_raw.name,
|
||||
:mac => new_raw.mac,
|
||||
:xml_desc => new_raw.xml_desc,
|
||||
}
|
||||
|
||||
merge_attributes(raw_attributes)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
31
lib/fog/compute/models/libvirt/interfaces.rb
Normal file
31
lib/fog/compute/models/libvirt/interfaces.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/compute/models/libvirt/interface'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Libvirt
|
||||
|
||||
class Interfaces < Fog::Collection
|
||||
|
||||
model Fog::Compute::Libvirt::Interface
|
||||
|
||||
def all
|
||||
data=[]
|
||||
connection.list_interfaces.each do |ifname|
|
||||
interface=connection.lookup_interface_by_name(ifname)
|
||||
data << { :raw => interface }
|
||||
end
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Retrieve the interface by name
|
||||
def get(name)
|
||||
interface=connection.lookup_interface_by_name(name)
|
||||
new(:raw => interface)
|
||||
end
|
||||
|
||||
end #class
|
||||
|
||||
end #Class
|
||||
end #module
|
||||
end #module
|
70
lib/fog/compute/models/libvirt/network.rb
Normal file
70
lib/fog/compute/models/libvirt/network.rb
Normal file
|
@ -0,0 +1,70 @@
|
|||
require 'fog/core/model'
|
||||
require 'fog/compute/models/libvirt/util'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Libvirt
|
||||
|
||||
class Network < Fog::Model
|
||||
|
||||
include Fog::Compute::LibvirtUtil
|
||||
|
||||
identity :id
|
||||
attribute :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
|
||||
|
||||
# https://www.redhat.com/archives/libvirt-users/2011-April/msg00006.html
|
||||
# Routed network without IP
|
||||
|
||||
# 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
|
||||
end
|
||||
|
||||
def destroy()
|
||||
requires :raw
|
||||
raw.destroy
|
||||
# raw.undefine
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def raw
|
||||
@raw
|
||||
end
|
||||
|
||||
def raw=(new_raw)
|
||||
@raw = new_raw
|
||||
|
||||
raw_attributes = {
|
||||
:id => new_raw.uuid,
|
||||
:uuid => new_raw.uuid,
|
||||
:name => new_raw.name,
|
||||
:bridge_name => new_raw.bridge_name,
|
||||
:xml_desc => new_raw.xml_desc,
|
||||
}
|
||||
|
||||
merge_attributes(raw_attributes)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
31
lib/fog/compute/models/libvirt/networks.rb
Normal file
31
lib/fog/compute/models/libvirt/networks.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/compute/models/libvirt/network'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Libvirt
|
||||
|
||||
class Networks < Fog::Collection
|
||||
|
||||
model Fog::Compute::Libvirt::Network
|
||||
|
||||
def all
|
||||
data=[]
|
||||
connection.list_networks.each do |networkname|
|
||||
network=connection.lookup_network_by_name(networkname)
|
||||
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)
|
||||
end
|
||||
|
||||
end #class
|
||||
|
||||
end #Class
|
||||
end #module
|
||||
end #module
|
96
lib/fog/compute/models/libvirt/pool.rb
Normal file
96
lib/fog/compute/models/libvirt/pool.rb
Normal file
|
@ -0,0 +1,96 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Libvirt
|
||||
|
||||
class Pool < Fog::Model
|
||||
|
||||
identity :id
|
||||
|
||||
attribute :name
|
||||
attribute :uuid
|
||||
attribute :xml
|
||||
|
||||
attr_reader :allocation
|
||||
attr_reader :available
|
||||
attr_reader :xml_desc
|
||||
attr_reader :num_of_volumes
|
||||
attr_reader :state
|
||||
|
||||
# There are two options to initialize a new Pool
|
||||
# 1. provide :xml as an argument
|
||||
# 2. provide :name, :path
|
||||
def initialize(attributes={})
|
||||
# unless attributes.has_key?(:xml)
|
||||
# name = attributes[:name] || raise("Must provide a pool name")
|
||||
# path = attributes[:path] || "/var/lib/libvirt/images"
|
||||
# else
|
||||
# @xml = attributes[:xml]
|
||||
# end
|
||||
super
|
||||
|
||||
end
|
||||
|
||||
def save
|
||||
unless @xml.nil?
|
||||
#connection.
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
requires :raw
|
||||
|
||||
# Shutdown pool if active
|
||||
if raw.active?
|
||||
raw.destroy
|
||||
end
|
||||
# Delete corresponding data in this pool
|
||||
raw.delete
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def shutdown
|
||||
requires :raw
|
||||
raw.destroy
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def raw
|
||||
@raw
|
||||
end
|
||||
|
||||
def raw=(new_raw)
|
||||
@raw = new_raw
|
||||
|
||||
raw_attributes = {
|
||||
:id => new_raw.uuid,
|
||||
:uuid => new_raw.uuid,
|
||||
:name => new_raw.name,
|
||||
:xml_desc => new_raw.xml_desc,
|
||||
:num_of_volumes => new_raw.num_of_volumes,
|
||||
:allocation => new_raw.info.allocation,
|
||||
:available => new_raw.info.available,
|
||||
:capacity => new_raw.info.capacity,
|
||||
:state => new_raw.info.state,
|
||||
}
|
||||
|
||||
# State
|
||||
#INACTIVE = INT2NUM(VIR_STORAGE_POOL_INACTIVE) virStoragePoolState
|
||||
#BUILDING = INT2NUM(VIR_STORAGE_POOL_BUILDING)
|
||||
#RUNNING = INT2NUM(VIR_STORAGE_POOL_RUNNING)
|
||||
#DEGRADED = INT2NUM(VIR_STORAGE_POOL_DEGRADED)
|
||||
#INACCESSIBLE = INT2NUM(VIR_STORAGE_POOL_INACCESSIBLE)
|
||||
|
||||
merge_attributes(raw_attributes)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
31
lib/fog/compute/models/libvirt/pools.rb
Normal file
31
lib/fog/compute/models/libvirt/pools.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/compute/models/libvirt/pool'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Libvirt
|
||||
|
||||
class Pools < Fog::Collection
|
||||
|
||||
model Fog::Compute::Libvirt::Pool
|
||||
|
||||
def all
|
||||
data=[]
|
||||
connection.list_storage_pools.each do |poolname|
|
||||
pool=connection.lookup_storage_pool_by_name(poolname)
|
||||
data << { :raw => pool }
|
||||
end
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Retrieve the pool by uuid
|
||||
def get(uuid)
|
||||
pool=connection.lookup_storage_pool_by_uuid(uuid)
|
||||
new(:raw => pool)
|
||||
end
|
||||
|
||||
end #class
|
||||
|
||||
end #Class
|
||||
end #module
|
||||
end #module
|
237
lib/fog/compute/models/libvirt/server.rb
Normal file
237
lib/fog/compute/models/libvirt/server.rb
Normal file
|
@ -0,0 +1,237 @@
|
|||
require 'fog/core/model'
|
||||
require 'fog/compute/models/libvirt/util'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Libvirt
|
||||
|
||||
class Server < Fog::Model
|
||||
|
||||
include Fog::Compute::LibvirtUtil
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
end
|
||||
|
||||
def start
|
||||
requires :raw
|
||||
|
||||
unless @raw.active?
|
||||
begin
|
||||
@raw.create
|
||||
rescue
|
||||
print "An error occured :",$!,"\n"
|
||||
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 ready?
|
||||
|
||||
status == :running
|
||||
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 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
|
||||
end
|
||||
return state
|
||||
end
|
||||
|
||||
def save()
|
||||
|
||||
raise Fog::Errors::Error.new('Updating an existing server is not yet implemented. Contributions welcome!')
|
||||
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
|
||||
end
|
||||
return { 'public' => [ipaddress], 'private' => [ipaddress]}
|
||||
end
|
||||
|
||||
|
||||
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
|
||||
|
||||
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
|
52
lib/fog/compute/models/libvirt/servers.rb
Normal file
52
lib/fog/compute/models/libvirt/servers.rb
Normal file
|
@ -0,0 +1,52 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/compute/models/libvirt/server'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Libvirt
|
||||
|
||||
class Servers < Fog::Collection
|
||||
|
||||
model Fog::Compute::Libvirt::Server
|
||||
|
||||
def all
|
||||
|
||||
data = connection.list_defined_domains.map do |machine|
|
||||
{
|
||||
:raw => connection.lookup_domain_by_name(machine)
|
||||
}
|
||||
end
|
||||
|
||||
connection.list_domains.each do |machine|
|
||||
data << {
|
||||
:raw => connection.lookup_domain_by_id(machine)
|
||||
}
|
||||
end
|
||||
load(data)
|
||||
end
|
||||
|
||||
def bootstrap(new_attributes = {})
|
||||
raise 'Not Implemented'
|
||||
# server = create(new_attributes)
|
||||
# server.start
|
||||
# server.wait_for { ready? }
|
||||
# server.setup(:password => server.password)
|
||||
# server
|
||||
end
|
||||
|
||||
# Retrieve the server by uuid
|
||||
def get(server_id)
|
||||
machine=connection.lookup_domain_by_uuid(server_id)
|
||||
new(:raw => machine)
|
||||
end
|
||||
|
||||
# Retrieve the server by name
|
||||
def get_by_name(name)
|
||||
machine=connection.lookup_domain_by_name(name)
|
||||
new(:raw => machine)
|
||||
end
|
||||
|
||||
end #class
|
||||
end #Class
|
||||
end #module
|
||||
end #Module
|
37
lib/fog/compute/models/libvirt/templates/guest.xml.erb
Normal file
37
lib/fog/compute/models/libvirt/templates/guest.xml.erb
Normal file
|
@ -0,0 +1,37 @@
|
|||
<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>
|
6
lib/fog/compute/models/libvirt/templates/network.xml.erb
Normal file
6
lib/fog/compute/models/libvirt/templates/network.xml.erb
Normal file
|
@ -0,0 +1,6 @@
|
|||
<network>
|
||||
<name><%= name %></name>
|
||||
<forward mode='<%= network_mode %>'/>
|
||||
<bridge name='<%= bridge_name %>' stp='on' delay='0' />
|
||||
</ip>
|
||||
</network>
|
6
lib/fog/compute/models/libvirt/templates/pool.xml.erb
Normal file
6
lib/fog/compute/models/libvirt/templates/pool.xml.erb
Normal file
|
@ -0,0 +1,6 @@
|
|||
<pool type="dir">
|
||||
<name><%= name %></name>
|
||||
<target>
|
||||
<path><%= path %></path>
|
||||
</target>
|
||||
</pool>
|
14
lib/fog/compute/models/libvirt/templates/volume.xml
Normal file
14
lib/fog/compute/models/libvirt/templates/volume.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<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>
|
28
lib/fog/compute/models/libvirt/util.rb
Normal file
28
lib/fog/compute/models/libvirt/util.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
require "rexml/document"
|
||||
require 'erb'
|
||||
|
||||
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
|
||||
return nil if new?
|
||||
xml = REXML::Document.new(@xml_desc)
|
||||
attribute.nil? ? xml.elements[path].text : xml.elements[path].attributes[attribute]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
70
lib/fog/compute/models/libvirt/volume.rb
Normal file
70
lib/fog/compute/models/libvirt/volume.rb
Normal file
|
@ -0,0 +1,70 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Libvirt
|
||||
|
||||
class Volume < Fog::Model
|
||||
|
||||
identity :id
|
||||
|
||||
attribute :key
|
||||
attribute :path
|
||||
attribute :name
|
||||
attribute :type
|
||||
attribute :allocation
|
||||
attribute :capacity
|
||||
attribute :xml_desc
|
||||
|
||||
def destroy
|
||||
requires :raw
|
||||
raw.delete
|
||||
true
|
||||
end
|
||||
|
||||
def wipe
|
||||
requires :raw
|
||||
raw.wipe
|
||||
true
|
||||
end
|
||||
|
||||
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')
|
||||
puts "cloning this might take a while"
|
||||
pool.create_volume_xml_from(xml.to_s,@raw)
|
||||
return connection.volumes.get(name)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def raw
|
||||
@raw
|
||||
end
|
||||
|
||||
def raw=(new_raw)
|
||||
@raw = new_raw
|
||||
|
||||
raw_attributes = {
|
||||
:id => new_raw.key,
|
||||
:key => new_raw.key,
|
||||
:path => new_raw.path ,
|
||||
:name => new_raw.name,
|
||||
:xml_desc => new_raw.xml_desc,
|
||||
:allocation => new_raw.info.allocation,
|
||||
:capacity => new_raw.info.capacity,
|
||||
:type => new_raw.info.type
|
||||
}
|
||||
|
||||
merge_attributes(raw_attributes)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
40
lib/fog/compute/models/libvirt/volumes.rb
Normal file
40
lib/fog/compute/models/libvirt/volumes.rb
Normal file
|
@ -0,0 +1,40 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/compute/models/libvirt/volume'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Libvirt
|
||||
|
||||
class Volumes < Fog::Collection
|
||||
|
||||
model Fog::Compute::Libvirt::Volume
|
||||
|
||||
def all
|
||||
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) }
|
||||
end
|
||||
end
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Retrieve the volume by uuid
|
||||
def get(key)
|
||||
connection.list_storage_pools.each do |poolname|
|
||||
pool=connection.lookup_storage_pool_by_name(poolname)
|
||||
volume=pool.lookup_volume_by_name(key)
|
||||
unless volume.nil?
|
||||
return new(:raw => volume)
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -14,6 +14,7 @@ require 'fog/providers/dnsmadeeasy'
|
|||
require 'fog/providers/ecloud'
|
||||
require 'fog/providers/go_grid'
|
||||
require 'fog/providers/google'
|
||||
require 'fog/providers/libvirt'
|
||||
require 'fog/providers/linode'
|
||||
require 'fog/providers/local'
|
||||
require 'fog/providers/new_servers'
|
||||
|
|
11
lib/fog/providers/libvirt.rb
Normal file
11
lib/fog/providers/libvirt.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
require 'fog/core'
|
||||
|
||||
module Fog
|
||||
module Libvirt
|
||||
|
||||
extend Fog::Provider
|
||||
|
||||
service(:compute, 'compute/libvirt')
|
||||
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue