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
@@ -0,0 +1,241 @@
|
|
1
|
+
module Libvirt
|
2
|
+
# Represents a domain within libvirt, which is a single virtual
|
3
|
+
# machine or environment, typically.
|
4
|
+
class Domain
|
5
|
+
# Initializes a new {Domain} object. If you're calling this directly,
|
6
|
+
# omit the `pointer` argument, since that is meant for internal use.
|
7
|
+
def initialize(pointer=nil)
|
8
|
+
@pointer = pointer if pointer.is_a?(FFI::Pointer)
|
9
|
+
ObjectSpace.define_finalizer(self, method(:finalize))
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns the name of the domain as a string.
|
13
|
+
#
|
14
|
+
# @return [String]
|
15
|
+
def name
|
16
|
+
FFI::Libvirt.virDomainGetName(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns the UUID of the domain as a string.
|
20
|
+
#
|
21
|
+
# @return [String]
|
22
|
+
def uuid
|
23
|
+
output_ptr = FFI::MemoryPointer.new(:char, 36)
|
24
|
+
FFI::Libvirt.virDomainGetUUIDString(self, output_ptr)
|
25
|
+
output_ptr.read_string
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns the hypervisor ID number for this domain.
|
29
|
+
#
|
30
|
+
# @return [Integer]
|
31
|
+
def id
|
32
|
+
FFI::Libvirt.virDomainGetID(self)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the OS type of the domain.
|
36
|
+
#
|
37
|
+
# @return [String]
|
38
|
+
def os_type
|
39
|
+
FFI::Libvirt.virDomainGetOSType(self)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns the current state this domain is in.
|
43
|
+
#
|
44
|
+
# @return [Symbol]
|
45
|
+
def state
|
46
|
+
domain_info[:state]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns the maximum memory (in KB) allowed on this domain.
|
50
|
+
#
|
51
|
+
# @return [Integer]
|
52
|
+
def max_memory
|
53
|
+
domain_info[:maxMem]
|
54
|
+
end
|
55
|
+
|
56
|
+
# Sets the maximum memory (in KB) allowed on this domain.
|
57
|
+
#
|
58
|
+
# @return [Boolean] Success of the command.
|
59
|
+
def max_memory=(value)
|
60
|
+
FFI::Libvirt.virDomainSetMaxMemory(self, value) == 0
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns the memory (in KB) currently allocated to this domain.
|
64
|
+
#
|
65
|
+
# @return [Integer]
|
66
|
+
def memory
|
67
|
+
domain_info[:memory]
|
68
|
+
end
|
69
|
+
|
70
|
+
# Sets the memory (in KB) on an active domain.
|
71
|
+
#
|
72
|
+
# @return [Boolean] Success of the command.
|
73
|
+
def memory=(value)
|
74
|
+
FFI::Libvirt.virDomainSetMemory(self, value) == 0
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns the number of virtual CPUs for this domain.
|
78
|
+
#
|
79
|
+
# @return [Integer]
|
80
|
+
def virtual_cpus
|
81
|
+
domain_info[:nrVirtCpu]
|
82
|
+
end
|
83
|
+
|
84
|
+
# Sets the number of virtual CPUs for this domain.
|
85
|
+
#
|
86
|
+
# @return [Boolean] Success of the command.
|
87
|
+
def virtual_cpus=(value)
|
88
|
+
FFI::Libvirt.virDomainSetVcpus(self, value) == 0
|
89
|
+
end
|
90
|
+
|
91
|
+
# Returns the maximum number of virtual CPUs supported for this guest
|
92
|
+
# VM.
|
93
|
+
#
|
94
|
+
# @return [Integer]
|
95
|
+
def max_virtual_cpus
|
96
|
+
FFI::Libvirt.virDomainGetMaxVcpus(self)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns the CPU time used in nanoseconds.
|
100
|
+
#
|
101
|
+
# @return [Integer]
|
102
|
+
def cpu_time_used
|
103
|
+
domain_info[:cpuTime]
|
104
|
+
end
|
105
|
+
|
106
|
+
# Returns the XML description of this domain.
|
107
|
+
#
|
108
|
+
# @return [String]
|
109
|
+
def xml
|
110
|
+
# TODO: The flags in the 2nd parameter
|
111
|
+
FFI::Libvirt.virDomainGetXMLDesc(self, 0)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Returns boolean of whether the domain is active (running) or not.
|
115
|
+
#
|
116
|
+
# @return [Boolean]
|
117
|
+
def active?
|
118
|
+
result = FFI::Libvirt.virDomainIsActive(self)
|
119
|
+
return nil if result == -1
|
120
|
+
result == 1
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns boolean of whether the domain is persistent, or whether it
|
124
|
+
# will still exist after it is shut down.
|
125
|
+
#
|
126
|
+
# @return [Boolean]
|
127
|
+
def persistent?
|
128
|
+
result = FFI::Libvirt.virDomainIsPersistent(self)
|
129
|
+
return nil if result == -1
|
130
|
+
result == 1
|
131
|
+
end
|
132
|
+
|
133
|
+
# Returns boolean of whether the domain autostarts on boot.
|
134
|
+
#
|
135
|
+
# @return [Boolean]
|
136
|
+
def autostart?
|
137
|
+
output_ptr = FFI::MemoryPointer.new(:int)
|
138
|
+
return nil if FFI::Libvirt.virDomainGetAutostart(self, output_ptr) < 0
|
139
|
+
output_ptr.read_int == 1
|
140
|
+
end
|
141
|
+
|
142
|
+
# Sets the autostart status. This assignment sets the value immediately
|
143
|
+
# on the domain.
|
144
|
+
#
|
145
|
+
# @param [Boolean] value
|
146
|
+
# @return [Boolean] The set value
|
147
|
+
def autostart=(value)
|
148
|
+
FFI::Libvirt.virDomainSetAutostart(self, value ? 1 : 0)
|
149
|
+
value
|
150
|
+
end
|
151
|
+
|
152
|
+
# Starts the domain (moves it from the inactive to running state), and
|
153
|
+
# returns a boolean of whether the call succeeded or not.
|
154
|
+
#
|
155
|
+
# @return [Boolean]
|
156
|
+
def create
|
157
|
+
return true if active?
|
158
|
+
FFI::Libvirt.virDomainCreate(self) == 0
|
159
|
+
end
|
160
|
+
alias :start :create
|
161
|
+
|
162
|
+
# Stops a running domain and returns a boolean of whether the call succeeded
|
163
|
+
# or not.
|
164
|
+
#
|
165
|
+
# @return [Boolean]
|
166
|
+
def destroy
|
167
|
+
FFI::Libvirt.virDomainDestroy(self) == 0
|
168
|
+
end
|
169
|
+
alias :stop :destroy
|
170
|
+
|
171
|
+
# Suspends an active domain, the process is frozen but the memory is still
|
172
|
+
# allocated. Returns a boolean of whether the call succeeded or not.
|
173
|
+
#
|
174
|
+
# @return [Boolean]
|
175
|
+
def suspend
|
176
|
+
FFI::Libvirt.virDomainSuspend(self) == 0
|
177
|
+
end
|
178
|
+
|
179
|
+
# Resumes a suspended domain, returns a boolean of whether the call
|
180
|
+
# succeeded or not.
|
181
|
+
#
|
182
|
+
# @return [Boolean]
|
183
|
+
def resume
|
184
|
+
return true if active?
|
185
|
+
FFI::Libvirt.virDomainResume(self) == 0
|
186
|
+
end
|
187
|
+
|
188
|
+
# Reboots the domain.
|
189
|
+
#
|
190
|
+
# @return [Boolean]
|
191
|
+
def reboot
|
192
|
+
FFI::Libvirt.virDomainReboot(self, 0) == 0
|
193
|
+
end
|
194
|
+
|
195
|
+
# Shutdown a domain, stopping the domain OS.
|
196
|
+
#
|
197
|
+
# @return [Boolean]
|
198
|
+
def shutdown
|
199
|
+
FFI::Libvirt.virDomainShutdown(self) == 0
|
200
|
+
end
|
201
|
+
|
202
|
+
# Undefine a domain. This will not stop it if it is running.
|
203
|
+
#
|
204
|
+
# @return [Boolean]
|
205
|
+
def undefine
|
206
|
+
FFI::Libvirt.virDomainUndefine(self) == 0
|
207
|
+
end
|
208
|
+
|
209
|
+
# Provides the pointer to the domain. This allows this object to be used
|
210
|
+
# directly with the FFI layer which expects a `virDomainPtr`.
|
211
|
+
#
|
212
|
+
# @return [FFI::Pointer]
|
213
|
+
def to_ptr
|
214
|
+
@pointer
|
215
|
+
end
|
216
|
+
|
217
|
+
# Provide a meaningful equality check so that two domains can easily
|
218
|
+
# be checked for equality. This works by comparing UUIDs.
|
219
|
+
#
|
220
|
+
# @return [Boolean]
|
221
|
+
def ==(other)
|
222
|
+
other.is_a?(Domain) && other.uuid == uuid
|
223
|
+
end
|
224
|
+
|
225
|
+
protected
|
226
|
+
|
227
|
+
# Queries the domain info from libvirt to get standard information
|
228
|
+
# about this domain.
|
229
|
+
def domain_info
|
230
|
+
result = FFI::Libvirt::DomainInfo.new
|
231
|
+
FFI::Libvirt.virDomainGetInfo(self, result.to_ptr)
|
232
|
+
result
|
233
|
+
end
|
234
|
+
|
235
|
+
# Cleans the `virDomainPtr` underlying the class when the class is
|
236
|
+
# released.
|
237
|
+
def finalize(*args)
|
238
|
+
FFI::Libvirt.virDomainFree(self)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Libvirt
|
2
|
+
# Represents the actual `libvirt` error object which most erroneous
|
3
|
+
# events set. This contains important information such as the message,
|
4
|
+
# domain, etc.
|
5
|
+
class Error
|
6
|
+
@@error_block = nil
|
7
|
+
@@raise_errors = true
|
8
|
+
|
9
|
+
attr_reader :interface
|
10
|
+
|
11
|
+
class << self
|
12
|
+
# Gets the last error (if there is one) and returns the {Error}
|
13
|
+
# representing it.
|
14
|
+
#
|
15
|
+
# @return [Error]
|
16
|
+
def last_error
|
17
|
+
pointer = FFI::Libvirt.virGetLastError
|
18
|
+
return nil if pointer.null?
|
19
|
+
new(pointer)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Sets an error handling function. This will call the given block
|
23
|
+
# whenever an error occurs within libvirt.
|
24
|
+
def on_error(&block)
|
25
|
+
@@error_block = block
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns whether or not Libvirt is currently configured to raise
|
29
|
+
# errors automatically when it is reported.
|
30
|
+
#
|
31
|
+
# @return [Boolean]
|
32
|
+
def raise_errors; @@raise_errors; end
|
33
|
+
|
34
|
+
# Set this to a boolean true/false to control whether the library
|
35
|
+
# automatically raises {Exception::LibvirtError} whenever an error
|
36
|
+
# occurs.
|
37
|
+
#
|
38
|
+
# @param [Boolean] value
|
39
|
+
def raise_errors=(value)
|
40
|
+
@@raise_errors = !!value
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def error_handler(userdata, error_ptr)
|
46
|
+
error_object = new(error_ptr)
|
47
|
+
@@error_block.call(error_object) if @@error_block
|
48
|
+
|
49
|
+
# Raise the exception
|
50
|
+
raise Exception::LibvirtError, error_object if @@raise_errors
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# This proc needs to be assigned to a constant so that it is never GC'd
|
55
|
+
# and can be assigned as a callback to the API.
|
56
|
+
ERROR_HANDLER_PROC = method(:error_handler)
|
57
|
+
FFI::Libvirt.virSetErrorFunc(nil, ERROR_HANDLER_PROC)
|
58
|
+
|
59
|
+
# Initializes a new error object. This shouldn't be called publicly.
|
60
|
+
# Instead use {last_error} or obtain the error from any of the exceptions
|
61
|
+
# which the library raises.
|
62
|
+
def initialize(pointer)
|
63
|
+
@interface = FFI::Libvirt::Error.new(pointer)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns the error code of the error. Internally, this is represented
|
67
|
+
# by a C `enum`, so this will actually return a Ruby `Symbol` representation
|
68
|
+
# of the error.
|
69
|
+
#
|
70
|
+
# @return [Symbol]
|
71
|
+
def code
|
72
|
+
interface[:code]
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns the domain or "category" in which this error occured. This
|
76
|
+
# is represented internally as a C `enum`, so this will actually return
|
77
|
+
# a Ruby `symbol`.
|
78
|
+
#
|
79
|
+
# @return [Symbol]
|
80
|
+
def domain
|
81
|
+
interface[:domain]
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns a human-friendly message related to the error.
|
85
|
+
#
|
86
|
+
# @return [String]
|
87
|
+
def message
|
88
|
+
interface[:message]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Libvirt
|
2
|
+
# Contains all the potential exceptions which the library can
|
3
|
+
# throw. This is different from a {Libvirt::Error}, which represents
|
4
|
+
# an actual `libvirt` error object.
|
5
|
+
module Exception
|
6
|
+
# Represents an exceptional event within the Libvirt library.
|
7
|
+
# This contains an `error` readable attribute which, if available,
|
8
|
+
# is a {Libvirt::Error} object, which contains more details
|
9
|
+
# about the error which occurred.
|
10
|
+
class LibvirtError < StandardError
|
11
|
+
attr_reader :error
|
12
|
+
|
13
|
+
def initialize(error)
|
14
|
+
@error = error
|
15
|
+
super(error.message)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module Libvirt
|
2
|
+
# Represents a network within libvirt, which is a network interface
|
3
|
+
# such as a host-only network for VirtualBox, for example.
|
4
|
+
class Network
|
5
|
+
# Initializes a new {Network} object given a `virNetworkPtr`. Please
|
6
|
+
# do not call this directly. Instead, use the {Connection#networks}
|
7
|
+
# object.
|
8
|
+
def initialize(pointer)
|
9
|
+
@pointer = pointer
|
10
|
+
ObjectSpace.define_finalizer(self, method(:finalize))
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the name of the network as a string.
|
14
|
+
#
|
15
|
+
# @return [String]
|
16
|
+
def name
|
17
|
+
FFI::Libvirt.virNetworkGetName(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the XML descriptions of this network.
|
21
|
+
#
|
22
|
+
# @return [String]
|
23
|
+
def xml
|
24
|
+
FFI::Libvirt.virNetworkGetXMLDesc(self, 0)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the UUID of the network as a string.
|
28
|
+
#
|
29
|
+
# @return [String]
|
30
|
+
def uuid
|
31
|
+
output_ptr = FFI::MemoryPointer.new(:char, 36)
|
32
|
+
FFI::Libvirt.virNetworkGetUUIDString(self, output_ptr)
|
33
|
+
output_ptr.read_string
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns the bridge that this network is attached to.
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
def bridge
|
40
|
+
FFI::Libvirt.virNetworkGetBridgeName(self)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Determine if the network is set to autostart on boot or not.
|
44
|
+
#
|
45
|
+
# @return [Boolean]
|
46
|
+
def autostart?
|
47
|
+
output_ptr = FFI::MemoryPointer.new(:int)
|
48
|
+
return nil if FFI::Libvirt.virNetworkGetAutostart(self, output_ptr) < 0
|
49
|
+
output_ptr.read_int == 1
|
50
|
+
end
|
51
|
+
|
52
|
+
# Set the autostart value on the network.
|
53
|
+
#
|
54
|
+
# @return [Boolean]
|
55
|
+
def autostart=(value)
|
56
|
+
FFI::Libvirt.virNetworkSetAutostart(self, value ? 1 : 0)
|
57
|
+
value
|
58
|
+
end
|
59
|
+
|
60
|
+
# Determine if the network is active or not.
|
61
|
+
#
|
62
|
+
# @return [Boolean]
|
63
|
+
def active?
|
64
|
+
FFI::Libvirt.virNetworkIsActive(self) == 1
|
65
|
+
end
|
66
|
+
|
67
|
+
# Determine if the network is persistent or not.
|
68
|
+
#
|
69
|
+
# @return [Boolean]
|
70
|
+
def persistent?
|
71
|
+
FFI::Libvirt.virNetworkIsPersistent(self) == 1
|
72
|
+
end
|
73
|
+
|
74
|
+
# Starts a network.
|
75
|
+
def create
|
76
|
+
FFI::Libvirt.virNetworkCreate(self)
|
77
|
+
end
|
78
|
+
alias :start :create
|
79
|
+
|
80
|
+
# Stops a network.
|
81
|
+
def destroy
|
82
|
+
FFI::Libvirt.virNetworkDestroy(self)
|
83
|
+
end
|
84
|
+
alias :stop :destroy
|
85
|
+
|
86
|
+
# Undefines the network, but will not stop it if it is
|
87
|
+
# running.
|
88
|
+
def undefine
|
89
|
+
FFI::Libvirt.virNetworkUndefine(self)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Converts to the actual `virNetworkPtr` of this structure. This allows
|
93
|
+
# this object to be used directly with the FFI layer which expects a
|
94
|
+
# `virNetworkPtr`.
|
95
|
+
#
|
96
|
+
# @return [FFI::Pointer]
|
97
|
+
def to_ptr
|
98
|
+
@pointer
|
99
|
+
end
|
100
|
+
|
101
|
+
# Provide a meaningful equality check for two networks by comparing
|
102
|
+
# UUID.
|
103
|
+
#
|
104
|
+
# @return [Boolean]
|
105
|
+
def ==(other)
|
106
|
+
other.is_a?(Network) && other.uuid == uuid
|
107
|
+
end
|
108
|
+
|
109
|
+
protected
|
110
|
+
|
111
|
+
# Cleans up the `virNetworkPtr` and releases the resources associated
|
112
|
+
# with it. This is automatically called when this object is garbage
|
113
|
+
# collected.
|
114
|
+
def finalize(*args)
|
115
|
+
FFI::Libvirt.virNetworkFree(self)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
data/lib/libvirt/node.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
module Libvirt
|
2
|
+
# Represents a node which libvirt resides on.
|
3
|
+
class Node
|
4
|
+
# Initializes a node object with the given {Connection} pointer. This
|
5
|
+
# shouldn't be called directly. Instead, retrieve the node using
|
6
|
+
# {Connection#node}.
|
7
|
+
def initialize(pointer)
|
8
|
+
# This pointer can either be a `virConnectPtr` directly or a
|
9
|
+
# {Connection} since it implements `to_ptr`.
|
10
|
+
@pointer = pointer
|
11
|
+
|
12
|
+
# We increase the reference count on the connection while this
|
13
|
+
# node object is in use.
|
14
|
+
FFI::Libvirt.virConnectRef(connection)
|
15
|
+
|
16
|
+
# Register finalizer for reference cleanup
|
17
|
+
ObjectSpace.define_finalizer(self, method(:finalize))
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the connection this node belongs to as a {Connection}
|
21
|
+
# object.
|
22
|
+
#
|
23
|
+
# @return [Connection]
|
24
|
+
def connection
|
25
|
+
@connection ||= @pointer.is_a?(Connection) ? @pointer : Connection.new(@pointer)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns the devices connected to this node.
|
29
|
+
#
|
30
|
+
# @return [Collection::NodeDeviceCollection]
|
31
|
+
def devices
|
32
|
+
Collection::NodeDeviceCollection.new(connection)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the free memory available on the node. This is returned
|
36
|
+
# in bytes.
|
37
|
+
#
|
38
|
+
# @return [Integer]
|
39
|
+
def free_memory
|
40
|
+
FFI::Libvirt.virNodeGetFreeMemory(connection)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns the CPU model of the node.
|
44
|
+
#
|
45
|
+
# @return [String]
|
46
|
+
def cpu_model
|
47
|
+
info[:model]
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the memory size in kilobytes.
|
51
|
+
#
|
52
|
+
# @return [Integer]
|
53
|
+
def memory
|
54
|
+
info[:memory]
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns the number of active CPUs.
|
58
|
+
#
|
59
|
+
# @return [Integer]
|
60
|
+
def cpus
|
61
|
+
info[:cpus]
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns the expected CPU frequency in MHz.
|
65
|
+
#
|
66
|
+
# @return [Integer]
|
67
|
+
def mhz
|
68
|
+
info[:mhz]
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns the number of NUMA cell, 1 for uniform memory access.
|
72
|
+
#
|
73
|
+
# @return [Integer]
|
74
|
+
def nodes
|
75
|
+
info[:nodes]
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the number of CPU sockets per node.
|
79
|
+
#
|
80
|
+
# @return [Integer]
|
81
|
+
def sockets
|
82
|
+
info[:sockets]
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns the number of cores per socket.
|
86
|
+
#
|
87
|
+
# @return [Integer]
|
88
|
+
def cores
|
89
|
+
info[:cores]
|
90
|
+
end
|
91
|
+
|
92
|
+
# Returns the number of threads per core.
|
93
|
+
#
|
94
|
+
# @return [Integer]
|
95
|
+
def threads
|
96
|
+
info[:threads]
|
97
|
+
end
|
98
|
+
|
99
|
+
protected
|
100
|
+
|
101
|
+
# Returns the {FFI::Libvirt::NodeInfo} structure associated with this
|
102
|
+
# node. The various fields of this structure are accessed using the
|
103
|
+
# other methods in this class.
|
104
|
+
#
|
105
|
+
# @return [FFI::Libvirt::NodeInfo]
|
106
|
+
def info
|
107
|
+
result = FFI::Libvirt::NodeInfo.new
|
108
|
+
FFI::Libvirt.virNodeGetInfo(connection, result.to_ptr)
|
109
|
+
result
|
110
|
+
end
|
111
|
+
|
112
|
+
# Releases the reference to the underlying connection structure.
|
113
|
+
# This is automatically called when the object is garbage collected.
|
114
|
+
def finalize(*args)
|
115
|
+
FFI::Libvirt.virConnectClose(connection)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Libvirt
|
2
|
+
# Represents a device on a node.
|
3
|
+
class NodeDevice
|
4
|
+
# Initializes a node device with the given `virNodeDevicePtr`. This
|
5
|
+
# should not be called directly. Instead, call {Node#devices} to get
|
6
|
+
# a list of the devices.
|
7
|
+
#
|
8
|
+
# @param [FFI::Pointer] pointer
|
9
|
+
def initialize(pointer)
|
10
|
+
@pointer = pointer
|
11
|
+
ObjectSpace.define_finalizer(self, method(:finalize))
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the name of this device.
|
15
|
+
#
|
16
|
+
# @return [String]
|
17
|
+
def name
|
18
|
+
FFI::Libvirt.virNodeDeviceGetName(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the XML specification for this device.
|
22
|
+
#
|
23
|
+
# @return [String]
|
24
|
+
def xml
|
25
|
+
FFI::Libvirt.virNodeDeviceGetXMLDesc(self, 0)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Detaches the device from the node itself so that it may be bound to
|
29
|
+
# a guest domain.
|
30
|
+
#
|
31
|
+
# @return [Boolean]
|
32
|
+
def dettach
|
33
|
+
FFI::Libvirt.virNodeDeviceDettach(self) == 0
|
34
|
+
end
|
35
|
+
|
36
|
+
# Reattach the device onto the node.
|
37
|
+
#
|
38
|
+
# @return [Boolena]
|
39
|
+
def reattach
|
40
|
+
FFI::Libvirt.virNodeDeviceReAttach(self) == 0
|
41
|
+
end
|
42
|
+
|
43
|
+
# Reset the device. The exact semantics of this method are hypervisor
|
44
|
+
# specific.
|
45
|
+
#
|
46
|
+
# @return [Boolena]
|
47
|
+
def reset
|
48
|
+
FFI::Libvirt.virNodeDeviceReset(self) == 0
|
49
|
+
end
|
50
|
+
|
51
|
+
# Destroy the device, removing the virtual device from the host operating
|
52
|
+
# system.
|
53
|
+
#
|
54
|
+
# @return [Boolean]
|
55
|
+
def destroy
|
56
|
+
FFI::Libvirt.virNodeDeviceDestroy(self) == 0
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the underlying `virNodeDevicePtr`. This allows this object to
|
60
|
+
# be used directly with FFI methods.
|
61
|
+
#
|
62
|
+
# @return [FFI::Pointer]
|
63
|
+
def to_ptr
|
64
|
+
@pointer
|
65
|
+
end
|
66
|
+
|
67
|
+
protected
|
68
|
+
|
69
|
+
# Frees the underlying resources of the node device. This is called
|
70
|
+
# automatically when this object is garbage collected.
|
71
|
+
def finalize(*args)
|
72
|
+
FFI::Libvirt.virNodeDeviceFree(self)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|