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
@@ -0,0 +1,58 @@
|
|
1
|
+
module Libvirt
|
2
|
+
module Spec
|
3
|
+
module Device
|
4
|
+
# Any device that looks like a disk, be it a floppy, harddisk,
|
5
|
+
# cdrom, or paravirtualized driver is specified via the disk
|
6
|
+
# element.
|
7
|
+
class Disk
|
8
|
+
attr_accessor :type
|
9
|
+
attr_accessor :source
|
10
|
+
attr_accessor :target_dev
|
11
|
+
attr_accessor :target_bus
|
12
|
+
attr_accessor :driver
|
13
|
+
attr_accessor :driver_type
|
14
|
+
attr_accessor :driver_cache
|
15
|
+
attr_accessor :shareable
|
16
|
+
attr_accessor :serial
|
17
|
+
|
18
|
+
# Initialize a new disk element with the given type. Examples
|
19
|
+
# of valid `type`s are "disk," "floppy," and "cdrom."
|
20
|
+
def initialize(type)
|
21
|
+
@type = type
|
22
|
+
@shareable = false
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the XML representation of this device.
|
26
|
+
def to_xml(xml=Nokogiri::XML::Builder.new)
|
27
|
+
xml.disk(:type => type) do |d|
|
28
|
+
if source
|
29
|
+
# Source tag, the attribute depends on the type.
|
30
|
+
attribute = type == :block ? :dev : :file
|
31
|
+
d.source(attribute => source)
|
32
|
+
end
|
33
|
+
|
34
|
+
if target_dev
|
35
|
+
# Target tag has optional "bus" parameter
|
36
|
+
options = { :dev => target_dev }
|
37
|
+
options[:bus] = target_bus if target_bus
|
38
|
+
d.target(options)
|
39
|
+
end
|
40
|
+
|
41
|
+
if driver
|
42
|
+
# Driver tag has a couple optional parameters
|
43
|
+
options = { :name => driver }
|
44
|
+
options[:type] = driver_type if driver_type
|
45
|
+
options[:cache] = driver_cache if driver_cache
|
46
|
+
d.driver(options)
|
47
|
+
end
|
48
|
+
|
49
|
+
d.shareable if shareable
|
50
|
+
d.serial serial if serial
|
51
|
+
end
|
52
|
+
|
53
|
+
xml.to_xml
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Libvirt
|
2
|
+
module Spec
|
3
|
+
module Device
|
4
|
+
class Emulator
|
5
|
+
attr_accessor :path
|
6
|
+
|
7
|
+
# Initialize an emulator device with the given path. The capabilities
|
8
|
+
# XML from {Connection} describes what emulators are available.
|
9
|
+
def initialize(path)
|
10
|
+
@path = path
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the XML for this device.
|
14
|
+
#
|
15
|
+
# @return [String]
|
16
|
+
def to_xml(xml=Nokogiri::XML::Builder.new)
|
17
|
+
xml.emulator path
|
18
|
+
xml.to_xml
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Libvirt
|
2
|
+
module Spec
|
3
|
+
class Domain
|
4
|
+
# The OS booting section of a domain specification indicates to libvirt
|
5
|
+
# how to configure the virtual machine to boot. There are three main ways
|
6
|
+
# to configure booting. Each hypervisor supports one or more of the following:
|
7
|
+
#
|
8
|
+
# 1. BIOS bootloader
|
9
|
+
# 2. Host bootloader
|
10
|
+
# 3. Direct kernel boot
|
11
|
+
#
|
12
|
+
# TODO: Host bootloader and direct kernel bootloader options.
|
13
|
+
class OSBooting
|
14
|
+
attr_accessor :type
|
15
|
+
attr_accessor :arch
|
16
|
+
attr_accessor :loader # Part of the BIOS bootloader
|
17
|
+
attr_accessor :boot
|
18
|
+
attr_accessor :bootmenu_enabled
|
19
|
+
|
20
|
+
# Host bootloader configuration options
|
21
|
+
attr_accessor :bootloader
|
22
|
+
attr_accessor :bootloader_args
|
23
|
+
|
24
|
+
# Direct kernel boot
|
25
|
+
attr_accessor :kernel
|
26
|
+
attr_accessor :initrd
|
27
|
+
attr_accessor :cmdline
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@boot = []
|
31
|
+
end
|
32
|
+
|
33
|
+
# Enables or disables the interactive boot menu prompt on guest startup.
|
34
|
+
def bootmenu_enabled=(value)
|
35
|
+
# Force a boolean value
|
36
|
+
@bootmenu_enabled = !!value
|
37
|
+
end
|
38
|
+
|
39
|
+
# Convert just the OS booting section to its XML representation.
|
40
|
+
def to_xml(parent=Nokogiri::XML::Builder.new)
|
41
|
+
parent.os do |os|
|
42
|
+
# Build the arguments for the OS booting type
|
43
|
+
type_args = [type]
|
44
|
+
type_args << { :arch => arch } if arch
|
45
|
+
|
46
|
+
# Setup the specification
|
47
|
+
os.type_ *type_args
|
48
|
+
os.loader loader if loader
|
49
|
+
os.bootmenu(:enable => bootmenu_enabled ? 'yes' : 'no') if !bootmenu_enabled.nil?
|
50
|
+
|
51
|
+
# Boot order for BIOS booting
|
52
|
+
boot.each { |dev| os.boot :dev => dev } if boot.is_a?(Array)
|
53
|
+
|
54
|
+
# Host bootloader configuration options
|
55
|
+
os.bootloader bootloader if bootloader
|
56
|
+
os.bootloader_args bootloader_args if bootloader_args
|
57
|
+
|
58
|
+
# Direct kernel boot options
|
59
|
+
os.kernel kernel if kernel
|
60
|
+
os.initrd initrd if initrd
|
61
|
+
os.cmdline cmdline if cmdline
|
62
|
+
end
|
63
|
+
|
64
|
+
parent.to_xml
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'libvirt/spec/domain/os_booting'
|
2
|
+
|
3
|
+
module Libvirt
|
4
|
+
module Spec
|
5
|
+
# A specification of a domain. This translates directly down to XML
|
6
|
+
# which can be used to define and launch domains on a node by libvirt.
|
7
|
+
#
|
8
|
+
# **Note:** This class may only be temporary, and the functionality
|
9
|
+
# may be merged back into {Domain}. Also, the interface will likely
|
10
|
+
# change.
|
11
|
+
class Domain
|
12
|
+
attr_accessor :hypervisor
|
13
|
+
attr_accessor :name
|
14
|
+
attr_accessor :uuid
|
15
|
+
attr_accessor :description
|
16
|
+
attr_accessor :os
|
17
|
+
attr_accessor :memory
|
18
|
+
attr_accessor :current_memory
|
19
|
+
attr_accessor :vcpu
|
20
|
+
|
21
|
+
attr_accessor :on_poweroff
|
22
|
+
attr_accessor :on_reboot
|
23
|
+
attr_accessor :on_crash
|
24
|
+
|
25
|
+
attr_accessor :devices
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@os = OSBooting.new
|
29
|
+
@devices = []
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the XML for this specification. This XML may be passed
|
33
|
+
# into libvirt to create a domain. This is actually the method which
|
34
|
+
# should be used for validation of this XML, since libvirt has
|
35
|
+
# great validation built in. If you define a domain and an error occurs,
|
36
|
+
# then it will notify you what is missing or wrong with the specification.
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
def to_xml
|
40
|
+
Nokogiri::XML::Builder.new do |xml|
|
41
|
+
xml.domain(:type => hypervisor) do
|
42
|
+
# Name and description
|
43
|
+
xml.name name if name
|
44
|
+
xml.uuid uuid if uuid
|
45
|
+
xml.description description if description
|
46
|
+
|
47
|
+
# Operating system boot information
|
48
|
+
os.to_xml(xml)
|
49
|
+
|
50
|
+
# Basic resources
|
51
|
+
xml.memory memory if memory
|
52
|
+
xml.currentMemory current_memory if current_memory
|
53
|
+
xml.vcpu vcpu if vcpu
|
54
|
+
|
55
|
+
# Lifecycle control
|
56
|
+
xml.on_poweroff on_poweroff if on_poweroff
|
57
|
+
xml.on_reboot on_reboot if on_reboot
|
58
|
+
xml.on_crash on_crash if on_crash
|
59
|
+
|
60
|
+
# Devices
|
61
|
+
if !devices.empty?
|
62
|
+
xml.devices do
|
63
|
+
devices.map { |d| d.to_xml(xml) }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end.to_xml
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/libvirt/spec.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module Libvirt
|
2
|
+
# This is the namespace which contains all the classes which define
|
3
|
+
# specifications for domains, networks, storage pools, etc. These
|
4
|
+
# specifications are used to define and launch them via libvirt.
|
5
|
+
# The specifications are converted down to XML for consumption by
|
6
|
+
# libvirt. Please view the example files for examples on how to use
|
7
|
+
# the specs.
|
8
|
+
module Spec
|
9
|
+
autoload :Device, 'libvirt/spec/device'
|
10
|
+
autoload :Domain, 'libvirt/spec/domain'
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
module Libvirt
|
2
|
+
# Represents a single storage pool.
|
3
|
+
class StoragePool
|
4
|
+
# Initializes a new {StoragePool} object given a `virStoragePoolPtr`.
|
5
|
+
# Do not call this directly. Instead, use the {Connection#storage_pools}
|
6
|
+
# object to retrieve a specific {StoragePool}.
|
7
|
+
def initialize(pointer)
|
8
|
+
@pointer = pointer
|
9
|
+
ObjectSpace.define_finalizer(self, method(:finalize))
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns the connection of this storage pool.
|
13
|
+
#
|
14
|
+
# @return [Connection]
|
15
|
+
def connection
|
16
|
+
Connection.new(FFI::Libvirt.virStoragePoolGetConnect(self))
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns the name of the network as a string.
|
20
|
+
#
|
21
|
+
# @return [String]
|
22
|
+
def name
|
23
|
+
FFI::Libvirt.virStoragePoolGetName(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns the UUID of the storage pool as a string.
|
27
|
+
#
|
28
|
+
# @return [String]
|
29
|
+
def uuid
|
30
|
+
output_ptr = FFI::MemoryPointer.new(:char, 36)
|
31
|
+
FFI::Libvirt.virStoragePoolGetUUIDString(self, output_ptr)
|
32
|
+
output_ptr.read_string
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the XML description of this storage pool.
|
36
|
+
#
|
37
|
+
# @return [String]
|
38
|
+
def xml
|
39
|
+
FFI::Libvirt.virStoragePoolGetXMLDesc(self, 0)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Deterine if the storage pool is active or not.
|
43
|
+
#
|
44
|
+
# @return [Boolean]
|
45
|
+
def active?
|
46
|
+
FFI::Libvirt.virStoragePoolIsActive(self) == 1
|
47
|
+
end
|
48
|
+
|
49
|
+
# Determine if the storage pool is persistent or not.
|
50
|
+
#
|
51
|
+
# @return [Boolean]
|
52
|
+
def persistent?
|
53
|
+
FFI::Libvirt.virStoragePoolIsPersistent(self) == 1
|
54
|
+
end
|
55
|
+
|
56
|
+
# Build the underlying storage pool.
|
57
|
+
#
|
58
|
+
# @return [Boolean]
|
59
|
+
def build
|
60
|
+
FFI::Libvirt.virStoragePoolBuild(self, 0) == 0
|
61
|
+
end
|
62
|
+
|
63
|
+
# Starts an inactive storage pool.
|
64
|
+
#
|
65
|
+
# @return [Boolean]
|
66
|
+
def create
|
67
|
+
return true if active?
|
68
|
+
FFI::Libvirt.virStoragePoolCreate(self, 0) == 0
|
69
|
+
end
|
70
|
+
alias :start :create
|
71
|
+
|
72
|
+
# Delete the underlying pool resources. This is a non-recoverable
|
73
|
+
# operation. This won't undefine the pool.
|
74
|
+
#
|
75
|
+
# @return [Boolean]
|
76
|
+
def delete(type=nil)
|
77
|
+
type ||= :normal
|
78
|
+
FFI::Libvirt.virStoragePoolDelete(self, type) == 0
|
79
|
+
end
|
80
|
+
|
81
|
+
# Stops an active storage pool.
|
82
|
+
#
|
83
|
+
# @return [Boolean]
|
84
|
+
def destroy
|
85
|
+
FFI::Libvirt.virStoragePoolDestroy(self) == 0
|
86
|
+
end
|
87
|
+
alias :stop :destroy
|
88
|
+
|
89
|
+
# Undefines the storage pool. This requires that the storage pool be
|
90
|
+
# inactive. This won't delete the underlying resources of the storage pool,
|
91
|
+
# however. Run {#delete} for that.
|
92
|
+
#
|
93
|
+
# @return [Boolean]
|
94
|
+
def undefine
|
95
|
+
FFI::Libvirt.virStoragePoolUndefine(self) == 0
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns the state of the storage pool as a symbol.
|
99
|
+
#
|
100
|
+
# @return [Symbol]
|
101
|
+
def state
|
102
|
+
info[:state]
|
103
|
+
end
|
104
|
+
|
105
|
+
# Returns the capacity in bytes.
|
106
|
+
#
|
107
|
+
# @return [Fixnum]
|
108
|
+
def capacity
|
109
|
+
info[:capacity]
|
110
|
+
end
|
111
|
+
|
112
|
+
# Returns the current allocation in bytes.
|
113
|
+
#
|
114
|
+
# @return [Fixnum]
|
115
|
+
def allocation
|
116
|
+
info[:allocation]
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns the available free space in bytes.
|
120
|
+
#
|
121
|
+
# @return [Fixnum]
|
122
|
+
def available
|
123
|
+
info[:available]
|
124
|
+
end
|
125
|
+
|
126
|
+
# Returns the volumes associated with this storage pool.
|
127
|
+
#
|
128
|
+
# @return [Collection::StorageVolumeCollection]
|
129
|
+
def volumes
|
130
|
+
Collection::StorageVolumeCollection.new(self)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Provide a meaningful equality check for two storage pools by comparing
|
134
|
+
# UUID.
|
135
|
+
#
|
136
|
+
# @return [Boolean]
|
137
|
+
def ==(other)
|
138
|
+
other.is_a?(StoragePool) && other.uuid == uuid
|
139
|
+
end
|
140
|
+
|
141
|
+
# Returns the actual `virStoragePoolPtr` underlying this structure.
|
142
|
+
#
|
143
|
+
# @return [FFI::Pointer]
|
144
|
+
def to_ptr
|
145
|
+
@pointer
|
146
|
+
end
|
147
|
+
|
148
|
+
protected
|
149
|
+
|
150
|
+
# Gets the virStoragePoolInfo structure for this storage pool.
|
151
|
+
#
|
152
|
+
# @return [Hash]
|
153
|
+
def info
|
154
|
+
result = FFI::Libvirt::StoragePoolInfo.new
|
155
|
+
FFI::Libvirt.virStoragePoolGetInfo(self, result.to_ptr)
|
156
|
+
result
|
157
|
+
end
|
158
|
+
|
159
|
+
# Frees the underlying memory associated with this object.
|
160
|
+
def finalize(*args)
|
161
|
+
FFI::Libvirt.virStoragePoolFree(self)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Libvirt
|
2
|
+
# Represents a single storage volume.
|
3
|
+
class StorageVolume
|
4
|
+
# Initializes a new {StorageVolume} object given a `virStorageVolPtr`.
|
5
|
+
# Do not call this directly. Instead, use the {StoragePool#volumes} collection
|
6
|
+
# object to retrieve a specific {StorageVolume}.
|
7
|
+
def initialize(pointer)
|
8
|
+
@pointer = pointer
|
9
|
+
ObjectSpace.define_finalizer(self, method(:finalize))
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns a key for this storage volume. The key is a unique identifier.
|
13
|
+
#
|
14
|
+
# @return [String]
|
15
|
+
def key
|
16
|
+
FFI::Libvirt.virStorageVolGetKey(self)
|
17
|
+
end
|
18
|
+
alias :uuid :key
|
19
|
+
|
20
|
+
# Returns the name of this storage volume.
|
21
|
+
#
|
22
|
+
# @return [String]
|
23
|
+
def name
|
24
|
+
FFI::Libvirt.virStorageVolGetName(self)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the path of this storage volume.
|
28
|
+
#
|
29
|
+
# @return [String]
|
30
|
+
def path
|
31
|
+
FFI::Libvirt.virStorageVolGetPath(self)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the type of this storage volume.
|
35
|
+
#
|
36
|
+
# @return [Symbol]
|
37
|
+
def type
|
38
|
+
info[:type]
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns the capacity of this volume in bytes.
|
42
|
+
#
|
43
|
+
# @return [Integer]
|
44
|
+
def capacity
|
45
|
+
info[:capacity]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the currently allocated number of bytes.
|
49
|
+
#
|
50
|
+
# @return [Integer]
|
51
|
+
def allocation
|
52
|
+
info[:allocation]
|
53
|
+
end
|
54
|
+
|
55
|
+
# Wipe the contents of a volume so it is not readable in the future.
|
56
|
+
#
|
57
|
+
# @return [Boolean]
|
58
|
+
def wipe
|
59
|
+
FFI::Libvirt.virStorageVolWipe(self, 0) == 0
|
60
|
+
end
|
61
|
+
|
62
|
+
# Delete the storage volume rom the pool.
|
63
|
+
#
|
64
|
+
# @return [Boolean]
|
65
|
+
def delete
|
66
|
+
FFI::Libvirt.virStorageVolDelete(self, 0) == 0
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns the XML description of this storage volume.
|
70
|
+
#
|
71
|
+
# @return [String]
|
72
|
+
def xml
|
73
|
+
FFI::Libvirt.virStorageVolGetXMLDesc(self, 0)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns the actual `virStorageVolPtr` underlying this structure.
|
77
|
+
#
|
78
|
+
# @return [FFI::Pointer]
|
79
|
+
def to_ptr
|
80
|
+
@pointer
|
81
|
+
end
|
82
|
+
|
83
|
+
# Provide a meaningful equality check so that two storage volumes
|
84
|
+
# can eaisly be checked for equality.
|
85
|
+
#
|
86
|
+
# @return [Boolean]
|
87
|
+
def ==(other)
|
88
|
+
other.is_a?(StorageVolume) && other.uuid == uuid
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
|
93
|
+
# Returns the {FFI::Libvirt::StorageVolumeInfo} object for this volume.
|
94
|
+
# The various fields of the info struct are accessible via other getters.
|
95
|
+
#
|
96
|
+
# @return [FFI::Libvirt::StorageVolumeInfo]
|
97
|
+
def info
|
98
|
+
result = FFI::Libvirt::StorageVolumeInfo.new
|
99
|
+
FFI::Libvirt.virStorageVolGetInfo(self, result.to_ptr)
|
100
|
+
result
|
101
|
+
end
|
102
|
+
|
103
|
+
# Release the resources underlying this storage volume. This is called
|
104
|
+
# automatically when this volume is garbage collected.
|
105
|
+
def finalize(*args)
|
106
|
+
FFI::Libvirt.virStorageVolFree(self)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/libvirt.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'ffi/libvirt'
|
3
|
+
|
4
|
+
# This module is the namespace for the higher level library on top of
|
5
|
+
# libvirt, in typicaly Ruby library style. In contrast with {FFI::Libvirt}
|
6
|
+
# which is a direct layer on top of FFI, this namespace abstracts much of
|
7
|
+
# the manual work away (especially pointer handling) and exposes aspects
|
8
|
+
# of the API through nice Ruby objects.
|
9
|
+
#
|
10
|
+
# Due to the nature of this side of the project, there may be certain features
|
11
|
+
# not readily available which are supported by the API. If this is the case,
|
12
|
+
# you can use the {FFI::Libvirt} library alongside this side.
|
13
|
+
module Libvirt
|
14
|
+
autoload :Collection, 'libvirt/collection'
|
15
|
+
autoload :Connection, 'libvirt/connection'
|
16
|
+
autoload :Domain, 'libvirt/domain'
|
17
|
+
autoload :Error, 'libvirt/error'
|
18
|
+
autoload :Exception, 'libvirt/exception'
|
19
|
+
autoload :Network, 'libvirt/network'
|
20
|
+
autoload :Node, 'libvirt/node'
|
21
|
+
autoload :NodeDevice, 'libvirt/node_device'
|
22
|
+
autoload :Spec, 'libvirt/spec'
|
23
|
+
autoload :StoragePool, 'libvirt/storage_pool'
|
24
|
+
autoload :StorageVolume, 'libvirt/storage_volume'
|
25
|
+
|
26
|
+
# Initializes the library by calling `virInitialize`. Most methods
|
27
|
+
# in libvirt actually call this themselves, so its not strictly
|
28
|
+
# necessary. However, it is good practice and is **highly** recommended
|
29
|
+
# that this is called at a same place in a multi-threaded environment.
|
30
|
+
def self.initialize!
|
31
|
+
FFI::Libvirt.virInitialize == 0
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the version of `libvirt` on the client machine. **This is
|
35
|
+
# not the version of the `libvirt` ruby library.** The result is
|
36
|
+
# return as an array of `[major, minor, patch]`.
|
37
|
+
#
|
38
|
+
# @return [Array]
|
39
|
+
def self.version
|
40
|
+
FFI::Libvirt.version
|
41
|
+
end
|
42
|
+
|
43
|
+
# Connect to a hypervisor using libvirt. This is a shortcut to
|
44
|
+
# instantiating a {Connection} object, therefore for documentation on
|
45
|
+
# the arguments and return value for this method, please consult
|
46
|
+
# {Connection#initialize}.
|
47
|
+
def self.connect(*args)
|
48
|
+
Connection.new(*args)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Disable the stderr output which libvirt defaults to.
|
53
|
+
Libvirt::Error.on_error
|
data/libvirt.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "libvirt/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "libvirt"
|
7
|
+
s.version = Libvirt::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Mitchell Hashimoto"]
|
10
|
+
s.email = ["mitchell.hashimoto@gmail.com"]
|
11
|
+
s.homepage = "http://rubygems.org/gems/libvirt"
|
12
|
+
s.summary = "A ruby client library providing the raw interface to libvirt via FFI."
|
13
|
+
s.description = "A ruby client library providing the raw interface to libvirt via FFI."
|
14
|
+
|
15
|
+
s.rubyforge_project = "libvirt"
|
16
|
+
|
17
|
+
s.add_dependency "ffi", "~> 0.6.3"
|
18
|
+
s.add_dependency "nokogiri", "~> 1.4.3"
|
19
|
+
|
20
|
+
s.add_development_dependency "protest", "~> 0.4.0"
|
21
|
+
s.add_development_dependency "mocha", "~> 0.9.8"
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
|
+
s.require_paths = ["lib"]
|
27
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
Protest.describe("abstract collection") do
|
4
|
+
setup do
|
5
|
+
@klass = Libvirt::Collection::AbstractCollection
|
6
|
+
|
7
|
+
@connection = mock("connection")
|
8
|
+
@instance = @klass.new(@connection)
|
9
|
+
end
|
10
|
+
|
11
|
+
should "have interface be available as an attribute" do
|
12
|
+
assert_equal @connection, @instance.interface
|
13
|
+
end
|
14
|
+
end
|