libvirt 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +10 -0
- data/.yardopts +3 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +36 -0
- data/README.md +83 -0
- data/Rakefile +20 -0
- data/docs/user_guide.md +259 -0
- data/examples/README.md +10 -0
- data/examples/create_domain.rb +46 -0
- data/examples/print_domain_info.rb +46 -0
- data/examples/print_hypervisor_info.rb +40 -0
- data/lib/ffi/libvirt/domain_info.rb +12 -0
- data/lib/ffi/libvirt/error.rb +25 -0
- data/lib/ffi/libvirt/error_functions.rb +21 -0
- data/lib/ffi/libvirt/error_types.rb +125 -0
- data/lib/ffi/libvirt/functions.rb +363 -0
- data/lib/ffi/libvirt/node_info.rb +27 -0
- data/lib/ffi/libvirt/storage_pool_info.rb +11 -0
- data/lib/ffi/libvirt/storage_volume_info.rb +14 -0
- data/lib/ffi/libvirt/types.rb +61 -0
- data/lib/ffi/libvirt/util.rb +19 -0
- data/lib/ffi/libvirt/version.rb +46 -0
- data/lib/ffi/libvirt.rb +29 -0
- data/lib/libvirt/collection/abstract_collection.rb +49 -0
- data/lib/libvirt/collection/domain_collection.rb +98 -0
- data/lib/libvirt/collection/interface_collection.rb +16 -0
- data/lib/libvirt/collection/network_collection.rb +58 -0
- data/lib/libvirt/collection/node_device_collection.rb +29 -0
- data/lib/libvirt/collection/nwfilter_collection.rb +15 -0
- data/lib/libvirt/collection/storage_pool_collection.rb +58 -0
- data/lib/libvirt/collection/storage_volume_collection.rb +57 -0
- data/lib/libvirt/collection.rb +12 -0
- data/lib/libvirt/connection.rb +225 -0
- data/lib/libvirt/domain.rb +241 -0
- data/lib/libvirt/error.rb +91 -0
- data/lib/libvirt/exception.rb +19 -0
- data/lib/libvirt/network.rb +118 -0
- data/lib/libvirt/node.rb +118 -0
- data/lib/libvirt/node_device.rb +75 -0
- data/lib/libvirt/spec/device/disk.rb +58 -0
- data/lib/libvirt/spec/device/emulator.rb +23 -0
- data/lib/libvirt/spec/device.rb +8 -0
- data/lib/libvirt/spec/domain/os_booting.rb +69 -0
- data/lib/libvirt/spec/domain.rb +71 -0
- data/lib/libvirt/spec.rb +12 -0
- data/lib/libvirt/storage_pool.rb +164 -0
- data/lib/libvirt/storage_volume.rb +109 -0
- data/lib/libvirt/version.rb +3 -0
- data/lib/libvirt.rb +53 -0
- data/libvirt.gemspec +27 -0
- data/test/libvirt/collection/abstract_collection_test.rb +14 -0
- data/test/libvirt/collection/domain_collection_test.rb +122 -0
- data/test/libvirt/collection/interface_collection_test.rb +9 -0
- data/test/libvirt/collection/network_collection_test.rb +41 -0
- data/test/libvirt/collection/node_device_collection_test.rb +24 -0
- data/test/libvirt/collection/nwfilter_collection_test.rb +7 -0
- data/test/libvirt/collection/storage_pool_collection_test.rb +41 -0
- data/test/libvirt/collection/storage_volume_collection_test.rb +86 -0
- data/test/libvirt/connection_test.rb +133 -0
- data/test/libvirt/domain_test.rb +221 -0
- data/test/libvirt/error_test.rb +93 -0
- data/test/libvirt/libvirt_test.rb +16 -0
- data/test/libvirt/network_test.rb +76 -0
- data/test/libvirt/node_device_test.rb +16 -0
- data/test/libvirt/node_test.rb +24 -0
- data/test/libvirt/spec/devices/disk_test.rb +107 -0
- data/test/libvirt/spec/devices/emulator_test.rb +20 -0
- data/test/libvirt/spec/domain_test.rb +17 -0
- data/test/libvirt/storage_pool_test.rb +133 -0
- data/test/libvirt/storage_volume_test.rb +63 -0
- data/test/support/xml_assertions.rb +29 -0
- data/test/test_helper.rb +23 -0
- metadata +219 -0
data/lib/ffi/libvirt.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module FFI
|
4
|
+
# The FFI Libvirt module contains the raw access to the Libvirt C
|
5
|
+
# API. This module contains no fluff or nice abstractions above the API,
|
6
|
+
# and is actually a way to access the C API directly. This also means
|
7
|
+
# that it is up to you to manage all the pointers and so on that come
|
8
|
+
# with this power.
|
9
|
+
module Libvirt
|
10
|
+
extend FFI::Library
|
11
|
+
ffi_lib "libvirt"
|
12
|
+
|
13
|
+
autoload :Util, 'ffi/libvirt/util'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# The order matters here, sadly. If you muck with the ordering and
|
18
|
+
# no exceptions are raised while running tests, you're probably okay.
|
19
|
+
# But, still, be careful.
|
20
|
+
require 'ffi/libvirt/types'
|
21
|
+
require 'ffi/libvirt/version'
|
22
|
+
require 'ffi/libvirt/functions'
|
23
|
+
require 'ffi/libvirt/error_types'
|
24
|
+
require 'ffi/libvirt/error_functions'
|
25
|
+
require 'ffi/libvirt/domain_info'
|
26
|
+
require 'ffi/libvirt/error'
|
27
|
+
require 'ffi/libvirt/node_info'
|
28
|
+
require 'ffi/libvirt/storage_pool_info'
|
29
|
+
require 'ffi/libvirt/storage_volume_info'
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Libvirt
|
4
|
+
module Collection
|
5
|
+
# Abstract parent class for all collections within libvirt.
|
6
|
+
#
|
7
|
+
# Subclasses of any collection are expected to implement the function
|
8
|
+
# `all` which returns all results of a collection. This will automatically
|
9
|
+
# make the enumerability work as well as some methods such as
|
10
|
+
# `first` and `length`.
|
11
|
+
class AbstractCollection
|
12
|
+
include Enumerable
|
13
|
+
extend Forwardable
|
14
|
+
def_delegators :all, :first, :last, :each, :length, :[], :inspect, :to_s
|
15
|
+
|
16
|
+
attr_reader :interface
|
17
|
+
|
18
|
+
# Initializes a new collection. All collections belong to a parent
|
19
|
+
# structure in some way, which is expected to be passed in here.
|
20
|
+
#
|
21
|
+
# @param [Object] Parent object
|
22
|
+
def initialize(interface)
|
23
|
+
@interface = interface
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
# A helper method to follow libvirt's API conventions to get the
|
29
|
+
# values of an array.
|
30
|
+
#
|
31
|
+
# @param [Symbol] getter Getter for the array
|
32
|
+
# @param [Symbol] count Method for getting the size of the array
|
33
|
+
# @param [Symbol] type Type of value returned
|
34
|
+
# @return [Array]
|
35
|
+
def read_array(getter, counter, type)
|
36
|
+
count_max = FFI::Libvirt.send(counter, interface)
|
37
|
+
output_ptr = FFI::MemoryPointer.new(:pointer, count_max)
|
38
|
+
count_returned = FFI::Libvirt.send(getter, interface, output_ptr, count_max)
|
39
|
+
output_ptr.send("get_array_of_#{type}", 0, count_returned)
|
40
|
+
end
|
41
|
+
|
42
|
+
# A helper method to wrap the resulting method call in an object
|
43
|
+
# if the pointer result is not null, or return nil otherwise.
|
44
|
+
def nil_or_object(result, klass)
|
45
|
+
result.null? ? nil : klass.new(result)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Libvirt
|
2
|
+
module Collection
|
3
|
+
# Represents a collection of domains. This is an enumerable (in the Ruby sense)
|
4
|
+
# object, but it is not directly an `Array`. This collection is a special enumerable
|
5
|
+
# which allows you to do things such as get only the active domains, create a new
|
6
|
+
# domain from a specification, etc.
|
7
|
+
#
|
8
|
+
# If you enumerate the entire collection, then this is equivalent to enumerating
|
9
|
+
# over {#all} domains. e.g. `collection.length` is equivalent to calling
|
10
|
+
# `collection.all.length` (where `collection` is a `DomainCollection` object).
|
11
|
+
class DomainCollection < AbstractCollection
|
12
|
+
# Searches for a domain. This will search first by name, then by ID,
|
13
|
+
# then by UUID, returning a result as soon as one is found.
|
14
|
+
#
|
15
|
+
# @return [Domain]
|
16
|
+
def find(value)
|
17
|
+
result = find_by_name(value) rescue nil
|
18
|
+
result ||= find_by_id(value) rescue nil
|
19
|
+
result ||= find_by_uuid(value) rescue nil
|
20
|
+
end
|
21
|
+
|
22
|
+
# Searches for a domain by name.
|
23
|
+
#
|
24
|
+
# @return [Domain]
|
25
|
+
def find_by_name(name)
|
26
|
+
nil_or_object(FFI::Libvirt.virDomainLookupByName(interface, name), Domain)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Searches for a domain by ID.
|
30
|
+
#
|
31
|
+
# @return [Domain]
|
32
|
+
def find_by_id(id)
|
33
|
+
nil_or_object(FFI::Libvirt.virDomainLookupByID(interface, id), Domain)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Searches for a domain by UUID.
|
37
|
+
#
|
38
|
+
# @return [Domain]
|
39
|
+
def find_by_uuid(uuid)
|
40
|
+
nil_or_object(FFI::Libvirt.virDomainLookupByUUIDString(interface, uuid), Domain)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Defines a new domain with the given valid specification. This method
|
44
|
+
# doesn't start the domain.
|
45
|
+
#
|
46
|
+
# @param [Object] spec
|
47
|
+
# @return [Domain]
|
48
|
+
def define(spec)
|
49
|
+
spec = spec.is_a?(String) ? spec : spec.to_xml
|
50
|
+
nil_or_object(FFI::Libvirt.virDomainDefineXML(interface, spec), Domain)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Creates a new domain and starts it. This domain configuration is not
|
54
|
+
# persisted, so it may disappear after the next reboot or shutdown.
|
55
|
+
#
|
56
|
+
# @param [Object] spec
|
57
|
+
# @return [Domain]
|
58
|
+
def create(spec)
|
59
|
+
spec = spec.is_a?(String) ? spec : spec.to_xml
|
60
|
+
nil_or_object(FFI::Libvirt.virDomainCreateXML(interface, spec, 0), Domain)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns all the active (running) domains for the connection which this
|
64
|
+
# collection belongs to.
|
65
|
+
#
|
66
|
+
# @return [Array<Domain>]
|
67
|
+
def active
|
68
|
+
# Do some pointer and array fiddling to extract the ids of the active
|
69
|
+
# domains from the libvirt API
|
70
|
+
ids = read_array(:virConnectListDomains, :virConnectNumOfDomains, :int)
|
71
|
+
|
72
|
+
# Lookup all the IDs and make them proper Domain objects
|
73
|
+
ids.collect { |id| find_by_id(id) }
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns all the inactive (not running) domains for the connection
|
77
|
+
# which this collection belongs to.
|
78
|
+
#
|
79
|
+
# @return [Array<Domain>]
|
80
|
+
def inactive
|
81
|
+
# Do some pointer and array fiddling to extract the names of the active
|
82
|
+
# domains from the libvirt API
|
83
|
+
ids = read_array(:virConnectListDefinedDomains, :virConnectNumOfDefinedDomains, :string)
|
84
|
+
|
85
|
+
# Lookup all the names and make them proper Domain objects
|
86
|
+
ids.collect { |id| find_by_name(id) }
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns all domains (active and inactive) for the connection this collection
|
90
|
+
# belongs to.
|
91
|
+
#
|
92
|
+
# @return [Array<Domain>]
|
93
|
+
def all
|
94
|
+
active + inactive
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Libvirt
|
2
|
+
module Collection
|
3
|
+
# Represents a collection of interfaces. This is an enumerable (in the
|
4
|
+
# Ruby sense) object, but it is not directly an `Array`.
|
5
|
+
class InterfaceCollection < AbstractCollection
|
6
|
+
# Returns all the active interfaces for the connection which this
|
7
|
+
# collection belongs to.
|
8
|
+
#
|
9
|
+
# @return [Array<Interface>]
|
10
|
+
def active
|
11
|
+
# TODO: Doesn't work on mac :) must dev on linux
|
12
|
+
# read_array(:virConnectListInterfaces, :virConnectNumOfInterfaces, :string)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Libvirt
|
2
|
+
module Collection
|
3
|
+
# Represents a collection of networks. This is an enumerable (in the
|
4
|
+
# Ruby sense) object, but it is not directly an `Array`.
|
5
|
+
class NetworkCollection < AbstractCollection
|
6
|
+
# Searches for a network. This will first search by name, then
|
7
|
+
# by UUID.
|
8
|
+
#
|
9
|
+
# @return [Network]
|
10
|
+
def find(value)
|
11
|
+
result = find_by_name(value) rescue nil
|
12
|
+
result ||= find_by_uuid(value) rescue nil
|
13
|
+
end
|
14
|
+
|
15
|
+
# Searches for a network by name.
|
16
|
+
#
|
17
|
+
# @return [Network]
|
18
|
+
def find_by_name(name)
|
19
|
+
nil_or_object(FFI::Libvirt.virNetworkLookupByName(interface, name), Network)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Searches for a network by UUID.
|
23
|
+
#
|
24
|
+
# @return [Network]
|
25
|
+
def find_by_uuid(uuid)
|
26
|
+
nil_or_object(FFI::Libvirt.virNetworkLookupByUUIDString(interface, uuid), Network)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns all the active networks for the connection which this
|
30
|
+
# collection belongs to.
|
31
|
+
#
|
32
|
+
# @return [Array<Network>]
|
33
|
+
def active
|
34
|
+
read_array(:virConnectListNetworks, :virConnectNumOfNetworks, :string).collect do |name|
|
35
|
+
find_by_name(name)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns all the inactive networks for the connection which this
|
40
|
+
# collection belongs to.
|
41
|
+
#
|
42
|
+
# @return [Array<Network>]
|
43
|
+
def inactive
|
44
|
+
read_array(:virConnectListDefinedNetworks, :virConnectNumOfDefinedNetworks, :string).collect do |name|
|
45
|
+
find_by_name(name)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns all networks (active and inactive) for the connection this
|
50
|
+
# collection belongs to.
|
51
|
+
#
|
52
|
+
# @return [Array<Netowrk>]
|
53
|
+
def all
|
54
|
+
active + inactive
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Libvirt
|
2
|
+
module Collection
|
3
|
+
# Represents a collection of devices on a given node. Retrieve
|
4
|
+
# this collection using {Node#devices}.
|
5
|
+
class NodeDeviceCollection < AbstractCollection
|
6
|
+
# Create a node device on the host system.
|
7
|
+
#
|
8
|
+
# @return [NodeDevice]
|
9
|
+
def create(spec)
|
10
|
+
nil_or_object(FFI::Libvirt.virNodeDeviceCreateXML(interface, spec, 0), NodeDevice)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns all of the node devices for the given connection.
|
14
|
+
#
|
15
|
+
# @return [Array<NodeDevice>]
|
16
|
+
def all
|
17
|
+
# We can't use the `read_array` helper here due to the methods being
|
18
|
+
# a bit different.
|
19
|
+
count_max = FFI::Libvirt.virNodeNumOfDevices(interface, nil, 0)
|
20
|
+
output_ptr = FFI::MemoryPointer.new(:pointer, count_max)
|
21
|
+
count_returned = FFI::Libvirt.virNodeListDevices(interface, nil, output_ptr, count_max, 0)
|
22
|
+
|
23
|
+
output_ptr.get_array_of_string(0, count_returned).collect do |name|
|
24
|
+
nil_or_object(FFI::Libvirt.virNodeDeviceLookupByName(interface, name), NodeDevice)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Libvirt
|
2
|
+
module Collection
|
3
|
+
# Represents a collection of network filters.
|
4
|
+
class NWFilterCollection < AbstractCollection
|
5
|
+
# Returns all network filters.
|
6
|
+
#
|
7
|
+
# @return [Array<NWFilter>]
|
8
|
+
def all
|
9
|
+
read_array(:virConnectListNWFilters, :virConnectNumOfNWFilters, :string).each do |name|
|
10
|
+
# TODO
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Libvirt
|
2
|
+
module Collection
|
3
|
+
# Represents a collection of storage pools.
|
4
|
+
class StoragePoolCollection < AbstractCollection
|
5
|
+
# Search for a storage pool. This will first search by name and
|
6
|
+
# then by UUID, returning the first result returned.
|
7
|
+
#
|
8
|
+
# @return [StoragePool]
|
9
|
+
def find(value)
|
10
|
+
result = find_by_name(value) rescue nil
|
11
|
+
result ||= find_by_uuid(value) rescue nil
|
12
|
+
end
|
13
|
+
|
14
|
+
# Search for a storage pool by name.
|
15
|
+
#
|
16
|
+
# @return [StoragePool]
|
17
|
+
def find_by_name(name)
|
18
|
+
nil_or_object(FFI::Libvirt.virStoragePoolLookupByName(interface, name), StoragePool)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Search for a storage pool by UUID.
|
22
|
+
#
|
23
|
+
# @return [StoragePool]
|
24
|
+
def find_by_uuid(uuid)
|
25
|
+
nil_or_object(FFI::Libvirt.virStoragePoolLookupByUUIDString(interface, uuid), StoragePool)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns the inactive storage pools.
|
29
|
+
#
|
30
|
+
# @return [Array<StoragePool>]
|
31
|
+
def inactive
|
32
|
+
read_array(:virConnectListDefinedStoragePools, :virConnectNumOfDefinedStoragePools, :string).collect do |name|
|
33
|
+
find_by_name(name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the active storage pools.
|
38
|
+
#
|
39
|
+
# @return [Array<StoragePool>]
|
40
|
+
def active
|
41
|
+
read_array(:virConnectListStoragePools, :virConnectNumOfStoragePools, :string).collect do |name|
|
42
|
+
find_by_name(name)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns all storage pools.
|
47
|
+
#
|
48
|
+
# @return [Array<StoragePool>]
|
49
|
+
def all
|
50
|
+
inactive + active
|
51
|
+
rescue Exception::LibvirtError
|
52
|
+
# If inactive isn't supported, then we just return the active
|
53
|
+
# storage pools.
|
54
|
+
active
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Libvirt
|
2
|
+
module Collection
|
3
|
+
# Represents a collection of storage volumes, which belongs to a
|
4
|
+
# storage pool.
|
5
|
+
class StorageVolumeCollection < AbstractCollection
|
6
|
+
# Searches for a storage volume. This will search by name, then by
|
7
|
+
# key, then finally by path. If no storage volume is found, nil will
|
8
|
+
# be returned.
|
9
|
+
#
|
10
|
+
# @return [StorageVolume]
|
11
|
+
def find(value)
|
12
|
+
result = find_by_name(value) rescue nil
|
13
|
+
result ||= find_by_key(value) rescue nil
|
14
|
+
result ||= find_by_path(value) rescue nil
|
15
|
+
end
|
16
|
+
|
17
|
+
# Searches for a storage volume by name.
|
18
|
+
#
|
19
|
+
# @return [StorageVolume]
|
20
|
+
def find_by_name(name)
|
21
|
+
nil_or_object(FFI::Libvirt.virStorageVolLookupByName(interface, name), StorageVolume)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Searches for a storage volume by key.
|
25
|
+
#
|
26
|
+
# @return [StorageVolume]
|
27
|
+
def find_by_key(key)
|
28
|
+
nil_or_object(FFI::Libvirt.virStorageVolLookupByKey(interface.connection, key), StorageVolume)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Searches for a storage volume by path.
|
32
|
+
#
|
33
|
+
# @return [StorageVolume]
|
34
|
+
def find_by_path(path)
|
35
|
+
nil_or_object(FFI::Libvirt.virStorageVolLookupByPath(interface.connection, path), StorageVolume)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Creates a new storage volume from an XML specification.
|
39
|
+
#
|
40
|
+
# @return [StorageVolume]
|
41
|
+
def create(spec)
|
42
|
+
nil_or_object(FFI::Libvirt.virStorageVolCreateXML(interface, spec, 0), StorageVolume)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns all storage volumes. Its unnecessary to call this directly
|
46
|
+
# since the {#all} array is delegated for the various `Array`-like
|
47
|
+
# methods.
|
48
|
+
#
|
49
|
+
# @return [Array]
|
50
|
+
def all
|
51
|
+
read_array(:virStoragePoolListVolumes, :virStoragePoolNumOfVolumes, :string).collect do |name|
|
52
|
+
find_by_name(name)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Libvirt
|
2
|
+
module Collection
|
3
|
+
autoload :AbstractCollection, 'libvirt/collection/abstract_collection'
|
4
|
+
autoload :DomainCollection, 'libvirt/collection/domain_collection'
|
5
|
+
autoload :InterfaceCollection, 'libvirt/collection/interface_collection'
|
6
|
+
autoload :NetworkCollection, 'libvirt/collection/network_collection'
|
7
|
+
autoload :NodeDeviceCollection, 'libvirt/collection/node_device_collection'
|
8
|
+
autoload :NWFilterCollection, 'libvirt/collection/nwfilter_collection'
|
9
|
+
autoload :StoragePoolCollection, 'libvirt/collection/storage_pool_collection'
|
10
|
+
autoload :StorageVolumeCollection, 'libvirt/collection/storage_volume_collection'
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
module Libvirt
|
2
|
+
# Describes a connection to an instance of libvirt. This instance may be local
|
3
|
+
# or remote.
|
4
|
+
#
|
5
|
+
# # Initiating a Connection
|
6
|
+
#
|
7
|
+
# ## Basic
|
8
|
+
#
|
9
|
+
# A basic example of initiating a connection is to just allow the libvirt client
|
10
|
+
# library to choose the best (first available) hypervisor for you. If you're only
|
11
|
+
# running one hypervisor or you're not sure what is available on your machine,
|
12
|
+
# then this is the easiest option to get started:
|
13
|
+
#
|
14
|
+
# conn = Libvirt::Connection.new
|
15
|
+
#
|
16
|
+
# A shortcut is also provided for your convenience:
|
17
|
+
#
|
18
|
+
# conn = Libvirt.connect
|
19
|
+
#
|
20
|
+
# ## Specifying a URI
|
21
|
+
#
|
22
|
+
# Libvirt connections are made by giving a URI to libvirt, which can describe
|
23
|
+
# a local or remote libvirt instance (remote being that `libvirtd` is running).
|
24
|
+
# The following is an example of a local VirtualBox connection:
|
25
|
+
#
|
26
|
+
# conn = Libvirt::Connection.new("vbox:///session")
|
27
|
+
#
|
28
|
+
# And perhaps a remote qemu connection:
|
29
|
+
#
|
30
|
+
# conn = Libvirt::Connection.new("qemu+tcp://10.0.0.1/system")
|
31
|
+
#
|
32
|
+
# # Readonly Connections
|
33
|
+
#
|
34
|
+
# A readonly connection can be made by specifying the `readonly` option to be
|
35
|
+
# truthy. A couple examples follow:
|
36
|
+
#
|
37
|
+
# conn = Libvirt::Connection.new("vbox:///session", :readonly => true)
|
38
|
+
# conn = Libvirt::Connection.new(:readonly => true)
|
39
|
+
#
|
40
|
+
# # Basic Information of a Connection
|
41
|
+
#
|
42
|
+
# Once you have a connection object, you can gather basic information about it
|
43
|
+
# by using methods such as {#name}, {#capabilities}, etc.:
|
44
|
+
#
|
45
|
+
# puts "Hypervisor type: #{conn.hypervisor}"
|
46
|
+
# puts "Hypervisor version: #{conn.hypervisor_verison}"
|
47
|
+
# puts "Library version: #{conn.lib_version}"
|
48
|
+
#
|
49
|
+
class Connection
|
50
|
+
# Opens a new connection to libvirt. This connection may be local or remote.
|
51
|
+
# If a `uri` is given, an attempt to connect to the given URI is made. The URI
|
52
|
+
# can be used to specify the location of libvirt along with the hypervisor
|
53
|
+
# to connect to.
|
54
|
+
#
|
55
|
+
# @param [String] uri
|
56
|
+
def initialize(*args)
|
57
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
58
|
+
uri = args.first
|
59
|
+
|
60
|
+
if args.first.is_a?(FFI::Pointer)
|
61
|
+
# Store away the pointer and increase the reference count, since
|
62
|
+
# we're taking ownership of this pointer directly.
|
63
|
+
@pointer = args.first
|
64
|
+
FFI::Libvirt.virConnectRef(self)
|
65
|
+
end
|
66
|
+
|
67
|
+
# If the pointer is not yet set, attempt to open a connection with
|
68
|
+
# the specified URI.
|
69
|
+
@pointer ||= if opts[:readonly]
|
70
|
+
FFI::Libvirt.virConnectOpenReadOnly(uri)
|
71
|
+
else
|
72
|
+
FFI::Libvirt.virConnectOpen(uri)
|
73
|
+
end
|
74
|
+
|
75
|
+
ObjectSpace.define_finalizer(self, method(:finalize))
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the domains (both active and inactive) related to this
|
79
|
+
# connection. The various states of the domains returned can be
|
80
|
+
# queried using {Domain#state}.
|
81
|
+
#
|
82
|
+
# @return [Collection::DomainCollection]
|
83
|
+
def domains
|
84
|
+
Collection::DomainCollection.new(self)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns the interfaces (both active and inactive) related to this
|
88
|
+
# connection.
|
89
|
+
#
|
90
|
+
# @return [Collection::InterfaceCollection]
|
91
|
+
def interfaces
|
92
|
+
Collection::InterfaceCollection.new(self)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns the networks related to this connection.
|
96
|
+
#
|
97
|
+
# @return [Collection::NetworkCollection]
|
98
|
+
def networks
|
99
|
+
Collection::NetworkCollection.new(self)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Returns the network filters related to this connection.
|
103
|
+
#
|
104
|
+
# @return [Collection::NWFilterCollection]
|
105
|
+
def nwfilters
|
106
|
+
Collection::NWFilterCollection.new(self)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Returns the storage pools related to this connection
|
110
|
+
#
|
111
|
+
# @return [Collection::StoragePoolCollection]
|
112
|
+
def storage_pools
|
113
|
+
Collection::StoragePoolCollection.new(self)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Returns a node object to retrieve information about the node which
|
117
|
+
# this connection is established to.
|
118
|
+
#
|
119
|
+
# @return [Node]
|
120
|
+
def node
|
121
|
+
Node.new(self)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Returns the capabilities of the connected hypervisor/driver. Returns them
|
125
|
+
# as an XML string. This method calls `virConnectGetCapabilities`. This will
|
126
|
+
# probably be parsed into a more useful format in the future.
|
127
|
+
#
|
128
|
+
# @return [String]
|
129
|
+
def capabilities
|
130
|
+
FFI::Libvirt.virConnectGetCapabilities(self)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Returns the system hostname on which the hypervisor is running. Therefore,
|
134
|
+
# if connected to a remote `libvirtd` daemon, then it will return the hostname
|
135
|
+
# of that machine.
|
136
|
+
#
|
137
|
+
# @return [String]
|
138
|
+
def hostname
|
139
|
+
FFI::Libvirt.virConnectGetHostname(self)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Returns the URI of the connection.
|
143
|
+
#
|
144
|
+
# @return [String]
|
145
|
+
def uri
|
146
|
+
FFI::Libvirt.virConnectGetURI(self)
|
147
|
+
end
|
148
|
+
|
149
|
+
# Returns the name of the hypervisor. This is named "type" since that is the
|
150
|
+
# terminology which libvirt itself uses. This is also aliased as `hypervisor`
|
151
|
+
# since that is more friendly.
|
152
|
+
#
|
153
|
+
# @return [String]
|
154
|
+
def type
|
155
|
+
FFI::Libvirt.virConnectGetType(self)
|
156
|
+
end
|
157
|
+
alias :hypervisor :type
|
158
|
+
|
159
|
+
# Returns the maximum number of virtual CPUs for a given domain type.
|
160
|
+
#
|
161
|
+
# @return [Integer]
|
162
|
+
def max_virtual_cpus(type)
|
163
|
+
FFI::Libvirt.virConnectGetMaxVcpus(self, type)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Returns a boolean of whether the connection is encrypted or not.
|
167
|
+
#
|
168
|
+
# @return [Boolean]
|
169
|
+
def encrypted?
|
170
|
+
result = FFI::Libvirt.virConnectIsEncrypted(self)
|
171
|
+
return nil if result == -1
|
172
|
+
result == 1
|
173
|
+
end
|
174
|
+
|
175
|
+
# Returns a boolean of whether the connection is secure or not.
|
176
|
+
#
|
177
|
+
# @return [Boolean]
|
178
|
+
def secure?
|
179
|
+
result = FFI::Libvirt.virConnectIsSecure(self)
|
180
|
+
return nil if result == -1
|
181
|
+
result == 1
|
182
|
+
end
|
183
|
+
|
184
|
+
# Returns the version of the hypervisor. This version is returned as an array
|
185
|
+
# representation as `[major, minor, patch]`.
|
186
|
+
#
|
187
|
+
# @return [Array]
|
188
|
+
def hypervisor_version
|
189
|
+
output_ptr = FFI::MemoryPointer.new(:ulong)
|
190
|
+
FFI::Libvirt.virConnectGetVersion(self, output_ptr)
|
191
|
+
FFI::Libvirt::Util.parse_version_number(output_ptr.get_ulong(0))
|
192
|
+
end
|
193
|
+
|
194
|
+
# Returns the version of `libvirt` which the daemon on the other side is
|
195
|
+
# running. If not connected to a remote daemon, it will return the version
|
196
|
+
# of libvirt on this machine. The result is an array representatin of the
|
197
|
+
# version, as `[major, minor, patch]`.
|
198
|
+
#
|
199
|
+
# @return [Array]
|
200
|
+
def lib_version
|
201
|
+
output_ptr = FFI::MemoryPointer.new(:ulong)
|
202
|
+
FFI::Libvirt.virConnectGetLibVersion(self, output_ptr)
|
203
|
+
FFI::Libvirt::Util.parse_version_number(output_ptr.get_ulong(0))
|
204
|
+
end
|
205
|
+
|
206
|
+
# Provides the pointer of the connection. This allows this object to be
|
207
|
+
# used directly with the FFI layer, as if this object were actually
|
208
|
+
# a `virConnectPtr`.
|
209
|
+
#
|
210
|
+
# @return [FFI::Pointer]
|
211
|
+
def to_ptr
|
212
|
+
@pointer
|
213
|
+
end
|
214
|
+
|
215
|
+
protected
|
216
|
+
|
217
|
+
# Cleans up the connection by releasing the connection object. This
|
218
|
+
# never needs to be called directly since there is a finalizer on
|
219
|
+
# this object to clean the connection. Therefore, to close the connection,
|
220
|
+
# simply release the reference to the connection.
|
221
|
+
def finalize(*args)
|
222
|
+
FFI::Libvirt.virConnectClose(self) rescue nil
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|