libvirt 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/.gitignore +10 -0
  2. data/.yardopts +3 -0
  3. data/CHANGELOG.md +3 -0
  4. data/Gemfile +12 -0
  5. data/Gemfile.lock +36 -0
  6. data/README.md +83 -0
  7. data/Rakefile +20 -0
  8. data/docs/user_guide.md +259 -0
  9. data/examples/README.md +10 -0
  10. data/examples/create_domain.rb +46 -0
  11. data/examples/print_domain_info.rb +46 -0
  12. data/examples/print_hypervisor_info.rb +40 -0
  13. data/lib/ffi/libvirt/domain_info.rb +12 -0
  14. data/lib/ffi/libvirt/error.rb +25 -0
  15. data/lib/ffi/libvirt/error_functions.rb +21 -0
  16. data/lib/ffi/libvirt/error_types.rb +125 -0
  17. data/lib/ffi/libvirt/functions.rb +363 -0
  18. data/lib/ffi/libvirt/node_info.rb +27 -0
  19. data/lib/ffi/libvirt/storage_pool_info.rb +11 -0
  20. data/lib/ffi/libvirt/storage_volume_info.rb +14 -0
  21. data/lib/ffi/libvirt/types.rb +61 -0
  22. data/lib/ffi/libvirt/util.rb +19 -0
  23. data/lib/ffi/libvirt/version.rb +46 -0
  24. data/lib/ffi/libvirt.rb +29 -0
  25. data/lib/libvirt/collection/abstract_collection.rb +49 -0
  26. data/lib/libvirt/collection/domain_collection.rb +98 -0
  27. data/lib/libvirt/collection/interface_collection.rb +16 -0
  28. data/lib/libvirt/collection/network_collection.rb +58 -0
  29. data/lib/libvirt/collection/node_device_collection.rb +29 -0
  30. data/lib/libvirt/collection/nwfilter_collection.rb +15 -0
  31. data/lib/libvirt/collection/storage_pool_collection.rb +58 -0
  32. data/lib/libvirt/collection/storage_volume_collection.rb +57 -0
  33. data/lib/libvirt/collection.rb +12 -0
  34. data/lib/libvirt/connection.rb +225 -0
  35. data/lib/libvirt/domain.rb +241 -0
  36. data/lib/libvirt/error.rb +91 -0
  37. data/lib/libvirt/exception.rb +19 -0
  38. data/lib/libvirt/network.rb +118 -0
  39. data/lib/libvirt/node.rb +118 -0
  40. data/lib/libvirt/node_device.rb +75 -0
  41. data/lib/libvirt/spec/device/disk.rb +58 -0
  42. data/lib/libvirt/spec/device/emulator.rb +23 -0
  43. data/lib/libvirt/spec/device.rb +8 -0
  44. data/lib/libvirt/spec/domain/os_booting.rb +69 -0
  45. data/lib/libvirt/spec/domain.rb +71 -0
  46. data/lib/libvirt/spec.rb +12 -0
  47. data/lib/libvirt/storage_pool.rb +164 -0
  48. data/lib/libvirt/storage_volume.rb +109 -0
  49. data/lib/libvirt/version.rb +3 -0
  50. data/lib/libvirt.rb +53 -0
  51. data/libvirt.gemspec +27 -0
  52. data/test/libvirt/collection/abstract_collection_test.rb +14 -0
  53. data/test/libvirt/collection/domain_collection_test.rb +122 -0
  54. data/test/libvirt/collection/interface_collection_test.rb +9 -0
  55. data/test/libvirt/collection/network_collection_test.rb +41 -0
  56. data/test/libvirt/collection/node_device_collection_test.rb +24 -0
  57. data/test/libvirt/collection/nwfilter_collection_test.rb +7 -0
  58. data/test/libvirt/collection/storage_pool_collection_test.rb +41 -0
  59. data/test/libvirt/collection/storage_volume_collection_test.rb +86 -0
  60. data/test/libvirt/connection_test.rb +133 -0
  61. data/test/libvirt/domain_test.rb +221 -0
  62. data/test/libvirt/error_test.rb +93 -0
  63. data/test/libvirt/libvirt_test.rb +16 -0
  64. data/test/libvirt/network_test.rb +76 -0
  65. data/test/libvirt/node_device_test.rb +16 -0
  66. data/test/libvirt/node_test.rb +24 -0
  67. data/test/libvirt/spec/devices/disk_test.rb +107 -0
  68. data/test/libvirt/spec/devices/emulator_test.rb +20 -0
  69. data/test/libvirt/spec/domain_test.rb +17 -0
  70. data/test/libvirt/storage_pool_test.rb +133 -0
  71. data/test/libvirt/storage_volume_test.rb +63 -0
  72. data/test/support/xml_assertions.rb +29 -0
  73. data/test/test_helper.rb +23 -0
  74. 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
@@ -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