libvirt 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|