Release 0.7.0.
[ruby-libvirt.git] / ext / libvirt / domain.c
1 /*
2  * domain.c: virDomain methods
3  *
4  * Copyright (C) 2007,2010 Red Hat Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
19  */
20
21 #include <ruby.h>
22 #include <libvirt/libvirt.h>
23 #if HAVE_VIRDOMAINQEMUMONITORCOMMAND
24 #include <libvirt/libvirt-qemu.h>
25 #endif
26 #include <libvirt/virterror.h>
27 #include "common.h"
28 #include "connect.h"
29 #include "extconf.h"
30
31 VALUE c_domain;
32 static VALUE c_domain_info;
33 static VALUE c_domain_ifinfo;
34 static VALUE c_domain_security_label;
35 static VALUE c_domain_block_stats;
36 #if HAVE_TYPE_VIRDOMAINBLOCKINFOPTR
37 static VALUE c_domain_block_info;
38 #endif
39 #if HAVE_TYPE_VIRDOMAINMEMORYSTATPTR
40 static VALUE c_domain_memory_stats;
41 #endif
42 #if HAVE_TYPE_VIRDOMAINSNAPSHOTPTR
43 static VALUE c_domain_snapshot;
44 #endif
45 #if HAVE_TYPE_VIRDOMAINJOBINFOPTR
46 static VALUE c_domain_job_info;
47 #endif
48 static VALUE c_domain_vcpuinfo;
49
50 static void domain_free(void *d) {
51     generic_free(Domain, d);
52 }
53
54 static VALUE domain_new(virDomainPtr d, VALUE conn) {
55     return generic_new(c_domain, d, conn, domain_free);
56 }
57
58 static virDomainPtr domain_get(VALUE s) {
59     generic_get(Domain, s);
60 }
61
62 /*
63  * call-seq:
64  *   conn.num_of_domains -> fixnum
65  *
66  * Call +virConnectNumOfDomains+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfDomains]
67  * to retrieve the number of active domains on this connection.
68  */
69 static VALUE libvirt_conn_num_of_domains(VALUE s) {
70     gen_conn_num_of(s, Domains);
71 }
72
73 /*
74  * call-seq:
75  *   conn.list_domains -> list
76  *
77  * Call +virConnectListDomains+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListDomains]
78  * to retrieve a list of active domain IDs on this connection.
79  */
80 static VALUE libvirt_conn_list_domains(VALUE s) {
81     int i, r, num, *ids;
82     virConnectPtr conn = connect_get(s);
83     VALUE result;
84     int exception = 0;
85     struct rb_ary_push_arg args;
86
87     num = virConnectNumOfDomains(conn);
88     _E(num < 0, create_error(e_RetrieveError, "virConnectNumOfDomains", conn));
89     if (num == 0) {
90         result = rb_ary_new2(num);
91         return result;
92     }
93
94     ids = ALLOC_N(int, num);
95     r = virConnectListDomains(conn, ids, num);
96     if (r < 0) {
97         xfree(ids);
98         rb_exc_raise(create_error(e_RetrieveError, "virConnectListDomains",
99                                   conn));
100     }
101
102     result = rb_protect(rb_ary_new2_wrap, (VALUE)&num, &exception);
103     if (exception) {
104         xfree(ids);
105         rb_jump_tag(exception);
106     }
107
108     for (i = 0; i < num; i++) {
109         args.arr = result;
110         args. value = INT2NUM(ids[i]);
111         rb_protect(rb_ary_push_wrap, (VALUE)&args, &exception);
112         if (exception) {
113             xfree(ids);
114             rb_jump_tag(exception);
115         }
116     }
117     xfree(ids);
118     return result;
119 }
120
121 /*
122  * call-seq:
123  *   conn.num_of_defined_domains -> fixnum
124  *
125  * Call +virConnectNumOfDefinedDomains+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfDefinedDomains]
126  * to retrieve the number of inactive domains on this connection.
127  */
128 static VALUE libvirt_conn_num_of_defined_domains(VALUE s) {
129     gen_conn_num_of(s, DefinedDomains);
130 }
131
132 /*
133  * call-seq:
134  *   conn.list_defined_domains -> list
135  *
136  * Call +virConnectListDefinedDomains+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListDefinedDomains]
137  * to retrieve a list of inactive domain names on this connection.
138  */
139 static VALUE libvirt_conn_list_defined_domains(VALUE s) {
140     gen_conn_list_names(s, DefinedDomains);
141 }
142
143 /*
144  * call-seq:
145  *   conn.create_domain_linux(xml, flags=0) -> Libvirt::Domain
146  *
147  * Call +virDomainCreateLinux+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainCreateLinux]
148  * to start a transient domain from the given XML.  Deprecated; use
149  * dom.create_xml instead.
150  */
151 static VALUE libvirt_conn_create_linux(int argc, VALUE *argv, VALUE c) {
152     virDomainPtr dom;
153     virConnectPtr conn = connect_get(c);
154     VALUE flags, xml;
155
156     rb_scan_args(argc, argv, "11", &xml, &flags);
157
158     if (NIL_P(flags))
159         flags = INT2FIX(0);
160
161     dom = virDomainCreateLinux(conn, StringValueCStr(xml), NUM2UINT(flags));
162     _E(dom == NULL, create_error(e_Error, "virDomainCreateLinux", conn));
163
164     return domain_new(dom, c);
165 }
166
167 #if HAVE_VIRDOMAINCREATEXML
168 /*
169  * call-seq:
170  *   conn.create_domain_xml(xml, flags=0) -> Libvirt::Domain
171  *
172  * Call +virDomainCreateXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainCreateXML]
173  * to start a transient domain from the given XML.
174  */
175 static VALUE libvirt_conn_create_xml(int argc, VALUE *argv, VALUE c) {
176     virDomainPtr dom;
177     virConnectPtr conn = connect_get(c);
178     VALUE flags, xml;
179
180     rb_scan_args(argc, argv, "11", &xml, &flags);
181
182     if (NIL_P(flags))
183         flags = INT2FIX(0);
184
185     dom = virDomainCreateXML(conn, StringValueCStr(xml), NUM2UINT(flags));
186     _E(dom == NULL, create_error(e_Error, "virDomainCreateXML", conn));
187
188     return domain_new(dom, c);
189 }
190 #endif
191
192 /*
193  * call-seq:
194  *   conn.lookup_domain_by_name(name) -> Libvirt::Domain
195  *
196  * Call +virDomainLookupByName+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainLookupByName]
197  * to retrieve a domain object for name.
198  */
199 static VALUE libvirt_conn_lookup_domain_by_name(VALUE c, VALUE name) {
200     virDomainPtr dom;
201     virConnectPtr conn = connect_get(c);
202
203     dom = virDomainLookupByName(conn, StringValueCStr(name));
204     _E(dom == NULL, create_error(e_RetrieveError, "virDomainLookupByName",
205                                  conn));
206
207     return domain_new(dom, c);
208 }
209
210 /*
211  * call-seq:
212  *   conn.lookup_domain_by_id(id) -> Libvirt::Domain
213  *
214  * Call +virDomainLookupByID+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainLookupByID]
215  * to retrieve a domain object for id.
216  */
217 static VALUE libvirt_conn_lookup_domain_by_id(VALUE c, VALUE id) {
218     virDomainPtr dom;
219     virConnectPtr conn = connect_get(c);
220
221     dom = virDomainLookupByID(conn, NUM2INT(id));
222     _E(dom == NULL, create_error(e_RetrieveError, "virDomainLookupByID",
223                                  conn));
224
225     return domain_new(dom, c);
226 }
227
228 /*
229  * call-seq:
230  *   conn.lookup_domain_by_uuid(uuid) -> Libvirt::Domain
231  *
232  * Call +virDomainLookupByUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainLookupByUUIDString]
233  * to retrieve a domain object for uuid.
234  */
235 static VALUE libvirt_conn_lookup_domain_by_uuid(VALUE c, VALUE uuid) {
236     virDomainPtr dom;
237     virConnectPtr conn = connect_get(c);
238
239     dom = virDomainLookupByUUIDString(conn, StringValueCStr(uuid));
240     _E(dom == NULL, create_error(e_RetrieveError, "virDomainLookupByUUID",
241                                  conn));
242
243     return domain_new(dom, c);
244 }
245
246 /*
247  * call-seq:
248  *   conn.define_domain_xml(xml) -> Libvirt::Domain
249  *
250  * Call +virDomainDefineXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainDefineXML]
251  * to define a permanent domain on this connection.
252  */
253 static VALUE libvirt_conn_define_domain_xml(VALUE c, VALUE xml) {
254     virDomainPtr dom;
255     virConnectPtr conn = connect_get(c);
256
257     dom = virDomainDefineXML(conn, StringValueCStr(xml));
258     _E(dom == NULL, create_error(e_DefinitionError, "virDomainDefineXML",
259                                  conn));
260
261     return domain_new(dom, c);
262 }
263
264 #if HAVE_VIRCONNECTDOMAINXMLFROMNATIVE
265 /*
266  * call-seq:
267  *   conn.domain_xml_from_native(nativeFormat, xml, flags=0) -> string
268  *
269  * Call +virConnectDomainXMLFromNative+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainXMLFromNative]
270  * to convert a native hypervisor domain representation to libvirt XML.
271  */
272 static VALUE libvirt_conn_domain_xml_from_native(int argc, VALUE *argv, VALUE s) {
273     VALUE nativeFormat, xml, flags;
274     char *ret;
275     VALUE result;
276
277     rb_scan_args(argc, argv, "21", &nativeFormat, &xml, &flags);
278
279     if (NIL_P(flags))
280         flags = INT2FIX(0);
281
282     ret = virConnectDomainXMLFromNative(conn(s), StringValueCStr(nativeFormat),
283                                         StringValueCStr(xml), NUM2UINT(flags));
284     _E(ret == NULL, create_error(e_Error, "virConnectDomainXMLFromNative",
285                                  conn(s)));
286
287     result = rb_str_new2(ret);
288
289     free(ret);
290
291     return result;
292 }
293 #endif
294
295 #if HAVE_VIRCONNECTDOMAINXMLTONATIVE
296 /*
297  * call-seq:
298  *   conn.domain_xml_to_native(nativeFormat, xml, flags=0) -> string
299  *
300  * Call +virConnectDomainXMLToNative+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainXMLToNative]
301  * to convert libvirt XML to a native domain hypervisor representation.
302  */
303 static VALUE libvirt_conn_domain_xml_to_native(int argc, VALUE *argv, VALUE s) {
304     VALUE nativeFormat, xml, flags;
305     char *ret;
306     VALUE result;
307
308     rb_scan_args(argc, argv, "21", &nativeFormat, &xml, &flags);
309
310     if (NIL_P(flags))
311         flags = INT2FIX(0);
312
313     ret = virConnectDomainXMLToNative(conn(s), StringValueCStr(nativeFormat),
314                                       StringValueCStr(xml), NUM2UINT(flags));
315     _E(ret == NULL, create_error(e_Error, "virConnectDomainXMLToNative",
316                                  conn(s)));
317
318     result = rb_str_new2(ret);
319
320     free(ret);
321
322     return result;
323 }
324 #endif
325
326 /*
327  * call-seq:
328  *   dom.migrate(dconn, flags=0, dname=nil, uri=nil, bandwidth=0) -> Libvirt::Domain
329  *
330  * Call +virDomainMigrate+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainMigrate]
331  * to migrate a domain from the host on this connection to the connection
332  * referenced in dconn.
333  */
334 static VALUE libvirt_dom_migrate(int argc, VALUE *argv, VALUE s) {
335     VALUE dconn, flags, dname_val, uri_val, bandwidth;
336     virDomainPtr ddom = NULL;
337
338     rb_scan_args(argc, argv, "14", &dconn, &flags, &dname_val, &uri_val,
339                  &bandwidth);
340
341     if (NIL_P(bandwidth))
342         bandwidth = INT2FIX(0);
343     if (NIL_P(flags))
344         flags = INT2FIX(0);
345
346     ddom = virDomainMigrate(domain_get(s), conn(dconn), NUM2ULONG(flags),
347                             get_string_or_nil(dname_val),
348                             get_string_or_nil(uri_val), NUM2ULONG(bandwidth));
349
350     _E(ddom == NULL, create_error(e_Error, "virDomainMigrate", conn(s)));
351
352     return domain_new(ddom, dconn);
353 }
354
355 #if HAVE_VIRDOMAINMIGRATETOURI
356 /*
357  * call-seq:
358  *   dom.migrate_to_uri(duri, flags=0, dname=nil, bandwidth=0) -> nil
359  *
360  * Call +virDomainMigrateToURI+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainMigrateToURI]
361  * to migrate a domain from the host on this connection to the host whose
362  * libvirt URI is duri.
363  */
364 static VALUE libvirt_dom_migrate_to_uri(int argc, VALUE *argv, VALUE s) {
365     VALUE flags, dname_val, bandwidth, duri_val;
366     int ret;
367
368     rb_scan_args(argc, argv, "13", &duri_val, &flags, &dname_val, &bandwidth);
369
370     if (NIL_P(bandwidth))
371         bandwidth = INT2FIX(0);
372     if (NIL_P(flags))
373         flags = INT2FIX(0);
374
375     ret = virDomainMigrateToURI(domain_get(s), StringValueCStr(duri_val),
376                                 NUM2ULONG(flags), get_string_or_nil(dname_val),
377                                 NUM2ULONG(bandwidth));
378
379     _E(ret < 0, create_error(e_Error, "virDomainMigrateToURI", conn(s)));
380
381     return Qnil;
382 }
383 #endif
384
385 #if HAVE_VIRDOMAINMIGRATESETMAXDOWNTIME
386 /*
387  * call-seq:
388  *   dom.migrate_set_max_downtime(downtime, flags=0) -> nil
389  *
390  * Call +virDomainMigrateSetMaxDowntime+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainMigrateSetMaxDowntime]
391  * to set the maximum downtime desired for live migration.
392  */
393 static VALUE libvirt_dom_migrate_set_max_downtime(int argc, VALUE *argv, VALUE s) {
394     VALUE downtime, flags;
395     int ret;
396
397     rb_scan_args(argc, argv, "11", &downtime, &flags);
398
399     if (NIL_P(flags))
400         flags = INT2FIX(0);
401
402     ret = virDomainMigrateSetMaxDowntime(domain_get(s), NUM2ULL(downtime),
403                                          NUM2UINT(flags));
404
405     _E(ret < 0, create_error(e_Error, "virDomainMigrateSetMaxDowntime",
406                              conn(s)));
407
408     return Qnil;
409 }
410 #endif
411
412 /*
413  * call-seq:
414  *   dom.shutdown -> nil
415  *
416  * Call +virDomainShutdown+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainShutdown]
417  * to do a soft shutdown of the domain.
418  */
419 static VALUE libvirt_dom_shutdown(VALUE s) {
420     gen_call_void(virDomainShutdown, conn(s), domain_get(s));
421 }
422
423 /*
424  * call-seq:
425  *   dom.reboot(flags=0) -> nil
426  *
427  * Call +virDomainReboot+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainReboot]
428  * to do a reboot of the domain.
429  */
430 static VALUE libvirt_dom_reboot(int argc, VALUE *argv, VALUE s) {
431     VALUE flags;
432
433     rb_scan_args(argc, argv, "01", &flags);
434
435     if (NIL_P(flags))
436         flags = INT2FIX(0);
437
438     gen_call_void(virDomainReboot, conn(s), domain_get(s), NUM2UINT(flags));
439 }
440
441 /*
442  * call-seq:
443  *   dom.destroy -> nil
444  *
445  * Call +virDomainDestroy+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainDestroy]
446  * to do a hard power-off of the domain.
447  */
448 static VALUE libvirt_dom_destroy(VALUE s) {
449     gen_call_void(virDomainDestroy, conn(s), domain_get(s));
450 }
451
452 /*
453  * call-seq:
454  *   dom.suspend -> nil
455  *
456  * Call +virDomainSuspend+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSuspend]
457  * to stop the domain from executing.  The domain will still continue to
458  * consume memory, but will not take any CPU time.
459  */
460 static VALUE libvirt_dom_suspend(VALUE s) {
461     gen_call_void(virDomainSuspend, conn(s), domain_get(s));
462 }
463
464 /*
465  * call-seq:
466  *   dom.resume -> nil
467  *
468  * Call +virDomainResume+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainResume]
469  * to resume a suspended domain.  After this call the domain will start
470  * consuming CPU resources again.
471  */
472 static VALUE libvirt_dom_resume(VALUE s) {
473     gen_call_void(virDomainResume, conn(s), domain_get(s));
474 }
475
476 /*
477  * call-seq:
478  *   dom.save(filename) -> nil
479  *
480  * Call +virDomainSave+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSave]
481  * to save the domain state to filename.  After this call, the domain will no
482  * longer be consuming any resources.
483  */
484 static VALUE libvirt_dom_save(VALUE s, VALUE to) {
485     gen_call_void(virDomainSave, conn(s), domain_get(s), StringValueCStr(to));
486 }
487
488 #if HAVE_VIRDOMAINMANAGEDSAVE
489 /*
490  * call-seq:
491  *   dom.managed_save(flags=0) -> nil
492  *
493  * Call +virDomainManagedSave+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainManagedSave]
494  * to do a managed save of the domain.  The domain will be saved to a place
495  * of libvirt's choosing.
496  */
497 static VALUE libvirt_dom_managed_save(int argc, VALUE *argv, VALUE s) {
498     VALUE flags;
499
500     rb_scan_args(argc, argv, "01", &flags);
501
502     if (NIL_P(flags))
503         flags = INT2FIX(0);
504
505     gen_call_void(virDomainManagedSave, conn(s), domain_get(s),
506                   NUM2UINT(flags));
507 }
508
509 /*
510  * call-seq:
511  *   dom.has_managed_save?(flags=0) -> [True|False]
512  *
513  * Call +virDomainHasManagedSaveImage+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainHasManagedSaveImage]
514  * to determine if a particular domain has a managed save image.
515  */
516 static VALUE libvirt_dom_has_managed_save(int argc, VALUE *argv, VALUE s) {
517     VALUE flags;
518
519     rb_scan_args(argc, argv, "01", &flags);
520
521     if (NIL_P(flags))
522         flags = INT2FIX(0);
523
524     gen_call_truefalse(virDomainHasManagedSaveImage, conn(s), domain_get(s),
525                        NUM2UINT(flags));
526 }
527
528 /*
529  * call-seq:
530  *   dom.managed_save_remove(flags=0) -> nil
531  *
532  * Call +virDomainManagedSaveRemove+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainManagedSaveRemove]
533  * to remove the managed save image for a domain.
534  */
535 static VALUE libvirt_dom_managed_save_remove(int argc, VALUE *argv, VALUE s) {
536     VALUE flags;
537
538     rb_scan_args(argc, argv, "01", &flags);
539
540     if (NIL_P(flags))
541         flags = INT2FIX(0);
542
543     gen_call_void(virDomainManagedSaveRemove, conn(s), domain_get(s),
544                   NUM2UINT(flags));
545 }
546 #endif
547
548 /*
549  * call-seq:
550  *   dom.core_dump(filename, flags=0) -> nil
551  *
552  * Call +virDomainCoreDump+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainCoreDump]
553  * to do a full memory dump of the domain to filename.
554  */
555 static VALUE libvirt_dom_core_dump(int argc, VALUE *argv, VALUE s) {
556     VALUE to, flags;
557
558     rb_scan_args(argc, argv, "11", &to, &flags);
559
560     if (NIL_P(flags))
561         flags = INT2FIX(0);
562
563     gen_call_void(virDomainCoreDump, conn(s), domain_get(s),
564                   StringValueCStr(to), NUM2INT(flags));
565 }
566
567 /*
568  * call-seq:
569  *   dom.restore(filename) -> nil
570  *
571  * Call +virDomainRestore+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainRestore]
572  * to restore the domain from the filename.
573  */
574 static VALUE libvirt_dom_restore(VALUE s, VALUE from) {
575     gen_call_void(virDomainRestore, conn(s), connect_get(s),
576                   StringValueCStr(from));
577 }
578
579 /*
580  * call-seq:
581  *   Libvirt::Domain::restore(conn, filename) -> nil
582  *
583  * Call +virDomainRestore+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainRestore]
584  * to restore the domain from the filename.  Note that this singleton method
585  * is deprecated in favor of dom.restore.
586  */
587 static VALUE libvirt_dom_s_restore(VALUE klass, VALUE c, VALUE from) {
588     gen_call_void(virDomainRestore, conn(c), connect_get(c),
589                   StringValueCStr(from));
590 }
591
592 /*
593  * call-seq:
594  *   dom.info -> Libvirt::Domain::Info
595  *
596  * Call +virDomainGetInfo+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetInfo]
597  * to retrieve domain information.
598  */
599 static VALUE libvirt_dom_info(VALUE s) {
600     virDomainPtr dom = domain_get(s);
601     virDomainInfo info;
602     int r;
603     VALUE result;
604
605     r = virDomainGetInfo(dom, &info);
606     _E(r < 0, create_error(e_RetrieveError, "virDomainGetInfo", conn(s)));
607
608     result = rb_class_new_instance(0, NULL, c_domain_info);
609     rb_iv_set(result, "@state", CHR2FIX(info.state));
610     rb_iv_set(result, "@max_mem", ULONG2NUM(info.maxMem));
611     rb_iv_set(result, "@memory", ULONG2NUM(info.memory));
612     rb_iv_set(result, "@nr_virt_cpu", INT2FIX((int) info.nrVirtCpu));
613     rb_iv_set(result, "@cpu_time", ULL2NUM(info.cpuTime));
614     return result;
615 }
616
617 #if HAVE_VIRDOMAINGETSECURITYLABEL
618 /*
619  * call-seq:
620  *   dom.security_label -> Libvirt::Domain::SecurityLabel
621  *
622  * Call +virDomainGetSecurityLabel+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetSecurityLabel]
623  * to retrieve the security label applied to this domain.
624  */
625 static VALUE libvirt_dom_security_label(VALUE s) {
626     virDomainPtr dom = domain_get(s);
627     virSecurityLabel seclabel;
628     int r;
629     VALUE result;
630
631     r = virDomainGetSecurityLabel(dom, &seclabel);
632     _E(r < 0, create_error(e_RetrieveError, "virDomainGetSecurityLabel",
633                            conn(s)));
634
635     result = rb_class_new_instance(0, NULL, c_domain_security_label);
636     rb_iv_set(result, "@label", rb_str_new2(seclabel.label));
637     rb_iv_set(result, "@enforcing", INT2NUM(seclabel.enforcing));
638
639     return result;
640 }
641 #endif
642
643 /*
644  * call-seq:
645  *   dom.block_stats(path) -> Libvirt::Domain::BlockStats
646  *
647  * Call +virDomainBlockStats+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainBlockStats]
648  * to retrieve statistics about guest block device path.
649  */
650 static VALUE libvirt_dom_block_stats(VALUE s, VALUE path) {
651     virDomainPtr dom = domain_get(s);
652     virDomainBlockStatsStruct stats;
653     int r;
654     VALUE result;
655
656     r = virDomainBlockStats(dom, StringValueCStr(path), &stats, sizeof(stats));
657     _E(r < 0, create_error(e_RetrieveError, "virDomainBlockStats", conn(s)));
658
659     result = rb_class_new_instance(0, NULL, c_domain_block_stats);
660     rb_iv_set(result, "@rd_req", LL2NUM(stats.rd_req));
661     rb_iv_set(result, "@rd_bytes", LL2NUM(stats.rd_bytes));
662     rb_iv_set(result, "@wr_req", LL2NUM(stats.wr_req));
663     rb_iv_set(result, "@wr_bytes", LL2NUM(stats.wr_bytes));
664     rb_iv_set(result, "@errs", LL2NUM(stats.errs));
665
666     return result;
667 }
668
669 #if HAVE_TYPE_VIRDOMAINMEMORYSTATPTR
670 /*
671  * call-seq:
672  *   dom.memory_stats(flags=0) -> [ Libvirt::Domain::MemoryStats ]
673  *
674  * Call +virDomainMemoryStats+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainMemoryStats]
675  * to retrieve statistics about the amount of memory consumed by a domain.
676  */
677 static VALUE libvirt_dom_memory_stats(int argc, VALUE *argv, VALUE s) {
678     virDomainPtr dom = domain_get(s);
679     virDomainMemoryStatStruct stats[6];
680     int r;
681     VALUE result;
682     VALUE flags;
683     VALUE tmp;
684     int i;
685
686     rb_scan_args(argc, argv, "01", &flags);
687
688     if (NIL_P(flags))
689         flags = INT2FIX(0);
690
691     r = virDomainMemoryStats(dom, stats, 6, NUM2UINT(flags));
692     _E(r < 0, create_error(e_RetrieveError, "virDomainMemoryStats", conn(s)));
693
694     /* FIXME: the right rubyish way to have done this would have been to
695      * create a hash with the values, something like:
696      *
697      * { 'SWAP_IN' => 0, 'SWAP_OUT' => 98, 'MAJOR_FAULT' => 45,
698      *   'MINOR_FAULT' => 55, 'UNUSED' => 455, 'AVAILABLE' => 98 }
699      *
700      * Unfortunately this has already been released with the array version
701      * so we have to maintain compatibility with that.  We should probably add
702      * a new memory_stats-like call that properly creates the hash.
703      */
704     result = rb_ary_new2(r);
705     for (i=0; i<r; i++) {
706         tmp = rb_class_new_instance(0, NULL, c_domain_memory_stats);
707         rb_iv_set(tmp, "@tag", INT2NUM(stats[i].tag));
708         rb_iv_set(tmp, "@val", ULL2NUM(stats[i].val));
709
710         rb_ary_push(result, tmp);
711     }                                           \
712
713     return result;
714 }
715 #endif
716
717 #if HAVE_TYPE_VIRDOMAINBLOCKINFOPTR
718 /*
719  * call-seq:
720  *   dom.blockinfo(path, flags=0) -> Libvirt::Domain::BlockInfo
721  *
722  * Call +virDomainGetBlockInfo+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetBlockInfo]
723  * to retrieve information about the backing file path for the domain.
724  */
725 static VALUE libvirt_dom_block_info(int argc, VALUE *argv, VALUE s) {
726     virDomainPtr dom = domain_get(s);
727     virDomainBlockInfo info;
728     int r;
729     VALUE result;
730     VALUE flags;
731     VALUE path;
732
733     rb_scan_args(argc, argv, "11", &path, &flags);
734
735     if (NIL_P(flags))
736         flags = INT2FIX(0);
737
738     r = virDomainGetBlockInfo(dom, StringValueCStr(path), &info,
739                               NUM2UINT(flags));
740     _E(r < 0, create_error(e_RetrieveError, "virDomainGetBlockInfo", conn(s)));
741
742     result = rb_class_new_instance(0, NULL, c_domain_block_info);
743     rb_iv_set(result, "@capacity", ULL2NUM(info.capacity));
744     rb_iv_set(result, "@allocation", ULL2NUM(info.allocation));
745     rb_iv_set(result, "@physical", ULL2NUM(info.physical));
746
747     return result;
748 }
749 #endif
750
751 /*
752  * call-seq:
753  *   dom.block_peek(path, offset, size, flags=0) -> string
754  *
755  * Call +virDomainBlockPeek+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainBlockPeek]
756  * to read size number of bytes, starting at offset offset from domain backing
757  * file path.  Due to limitations of the libvirt remote protocol, the user
758  * should never request more than 64k bytes.
759  */
760 static VALUE libvirt_dom_block_peek(int argc, VALUE *argv, VALUE s) {
761     virDomainPtr dom = domain_get(s);
762     VALUE path_val, offset_val, size_val, flags_val;
763     char *buffer;
764     int r;
765     VALUE ret;
766     char *path;
767     unsigned int size, flags;
768     unsigned long long offset;
769     struct rb_str_new_arg args;
770     int exception = 0;
771
772     rb_scan_args(argc, argv, "31", &path_val, &offset_val, &size_val,
773                  &flags_val);
774
775     if (NIL_P(flags_val))
776         flags_val = INT2FIX(0);
777
778     path = StringValueCStr(path_val);
779     offset = NUM2ULL(offset_val);
780     size = NUM2UINT(size_val);
781     flags = NUM2UINT(flags_val);
782
783     buffer = ALLOC_N(char, size);
784
785     r = virDomainBlockPeek(dom, path, offset, size, buffer, flags);
786
787     if (r < 0) {
788         xfree(buffer);
789         rb_exc_raise(create_error(e_RetrieveError, "virDomainBlockPeek",
790                                   conn(s)));
791     }
792
793     args.val = buffer;
794     args.size = size;
795     ret = rb_protect(rb_str_new_wrap, (VALUE)&args, &exception);
796     xfree(buffer);
797     if (exception)
798         rb_jump_tag(exception);
799
800     return ret;
801 }
802
803 /*
804  * call-seq:
805  *   dom.memory_peek(start, size, flags=Libvirt::Domain::MEMORY_VIRTUAL) -> string
806  *
807  * Call +virDomainMemoryPeek+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainMemoryPeek]
808  * to read size number of bytes from offset start from the domain memory.
809  * Due to limitations of the libvirt remote protocol, the user
810  * should never request more than 64k bytes.
811  */
812 static VALUE libvirt_dom_memory_peek(int argc, VALUE *argv, VALUE s) {
813     virDomainPtr dom = domain_get(s);
814     VALUE start_val, size_val, flags_val;
815     char *buffer;
816     int r;
817     VALUE ret;
818     unsigned int size, flags;
819     unsigned long long start;
820     struct rb_str_new_arg args;
821     int exception = 0;
822
823     rb_scan_args(argc, argv, "21", &start_val, &size_val, &flags_val);
824
825     if (NIL_P(flags_val))
826         flags_val = INT2FIX(VIR_MEMORY_VIRTUAL);
827
828     start = NUM2UINT(start_val);
829     size = NUM2UINT(size_val);
830     flags = NUM2UINT(flags_val);
831
832     buffer = ALLOC_N(char, size);
833
834     r = virDomainMemoryPeek(dom, start, size, buffer, flags);
835
836     if (r < 0) {
837         xfree(buffer);
838         rb_exc_raise(create_error(e_RetrieveError, "virDomainMemoryPeek",
839                                   conn(s)));
840     }
841
842     args.val = buffer;
843     args.size = size;
844     ret = rb_protect(rb_str_new_wrap, (VALUE)&args, &exception);
845     xfree(buffer);
846     if (exception)
847         rb_jump_tag(exception);
848
849     return ret;
850 }
851
852 /* call-seq:
853  *   dom.get_vcpus -> [ Libvirt::Domain::VCPUInfo ]
854  *
855  * Call +virDomainGetVcpus+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetVcpus]
856  * to retrieve detailed information about the state of a domain's virtual CPUs.
857  */
858 static VALUE libvirt_dom_get_vcpus(VALUE s) {
859     virDomainPtr dom = domain_get(s);
860     virNodeInfo nodeinfo;
861     virDomainInfo dominfo;
862     virVcpuInfoPtr cpuinfo;
863     unsigned char *cpumap;
864     int cpumaplen;
865     int r, i, j;
866     VALUE vcpuinfo;
867     VALUE p2vcpumap;
868     VALUE result;
869     int exception = 0;
870     struct rb_ary_push_arg args;
871     struct rb_iv_set_arg iv_args;
872     struct rb_class_new_instance_arg klass_args;
873
874     r = virNodeGetInfo(conn(s), &nodeinfo);
875     _E(r < 0, create_error(e_RetrieveError, "virNodeGetInfo", conn(s)));
876
877     r = virDomainGetInfo(dom, &dominfo);
878     _E(r < 0, create_error(e_RetrieveError, "virDomainGetInfo", conn(s)));
879
880     cpuinfo = ALLOC_N(virVcpuInfo, dominfo.nrVirtCpu);
881
882     cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
883
884     /* we use malloc instead of ruby_xmalloc here to avoid a memory leak
885      * if ruby_xmalloc raises an exception
886      */
887     cpumap = malloc(dominfo.nrVirtCpu * cpumaplen);
888     if (cpumap == NULL) {
889         xfree(cpuinfo);
890         rb_memerror();
891     }
892
893     r = virDomainGetVcpus(dom, cpuinfo, dominfo.nrVirtCpu, cpumap, cpumaplen);
894     if (r < 0) {
895         xfree(cpuinfo);
896         free(cpumap);
897         rb_exc_raise(create_error(e_RetrieveError, "virDomainGetVcpus",
898                                   conn(s)));
899     }
900
901     result = rb_protect(rb_ary_new_wrap, (VALUE)NULL, &exception);
902     if (exception) {
903         xfree(cpuinfo);
904         free(cpumap);
905         rb_jump_tag(exception);
906     }
907
908     for (i = 0; i < dominfo.nrVirtCpu; i++) {
909         klass_args.argc = 0;
910         klass_args.argv = NULL;
911         klass_args.klass = c_domain_vcpuinfo;
912         vcpuinfo = rb_protect(rb_class_new_instance_wrap, (VALUE)&klass_args,
913                               &exception);
914         if (exception) {
915             xfree(cpuinfo);
916             free(cpumap);
917             rb_jump_tag(exception);
918         }
919
920         iv_args.klass = vcpuinfo;
921         iv_args.member = "@number";
922         iv_args.value = UINT2NUM(cpuinfo[i].number);
923         rb_protect(rb_iv_set_wrap, (VALUE)&iv_args, &exception);
924         if (exception) {
925             xfree(cpuinfo);
926             free(cpumap);
927             rb_jump_tag(exception);
928         }
929         iv_args.member = "@state";
930         iv_args.value = INT2NUM(cpuinfo[i].state);
931         rb_protect(rb_iv_set_wrap, (VALUE)&iv_args, &exception);
932         if (exception) {
933             xfree(cpuinfo);
934             free(cpumap);
935             rb_jump_tag(exception);
936         }
937         iv_args.member = "@cpu_time";
938         iv_args.value = ULL2NUM(cpuinfo[i].cpuTime);
939         rb_protect(rb_iv_set_wrap, (VALUE)&iv_args, &exception);
940         if (exception) {
941             xfree(cpuinfo);
942             free(cpumap);
943             rb_jump_tag(exception);
944         }
945         iv_args.member = "@cpu";
946         iv_args.value = INT2NUM(cpuinfo[i].cpu);
947         rb_protect(rb_iv_set_wrap, (VALUE)&iv_args, &exception);
948         if (exception) {
949             xfree(cpuinfo);
950             free(cpumap);
951             rb_jump_tag(exception);
952         }
953
954         p2vcpumap = rb_protect(rb_ary_new_wrap, (VALUE)NULL, &exception);
955         if (exception) {
956             xfree(cpuinfo);
957             free(cpumap);
958             rb_jump_tag(exception);
959         }
960
961         for (j = 0; j < VIR_NODEINFO_MAXCPUS(nodeinfo); j++) {
962             args.arr = p2vcpumap;
963             args.value = (VIR_CPU_USABLE(cpumap, cpumaplen, i, j)) ? Qtrue : Qfalse;
964             rb_protect(rb_ary_push_wrap, (VALUE)&args, &exception);
965             if (exception) {
966                 xfree(cpuinfo);
967                 free(cpumap);
968                 rb_jump_tag(exception);
969             }
970         }
971
972         iv_args.klass = vcpuinfo;
973         iv_args.member = "@cpumap";
974         iv_args.value = p2vcpumap;
975         rb_protect(rb_iv_set_wrap, (VALUE)&iv_args, &exception);
976         if (exception) {
977             xfree(cpuinfo);
978             free(cpumap);
979             rb_jump_tag(exception);
980         }
981
982         args.arr = result;
983         args.value = vcpuinfo;
984         rb_protect(rb_ary_push_wrap, (VALUE)&args, &exception);
985         if (exception) {
986             xfree(cpuinfo);
987             free(cpumap);
988             rb_jump_tag(exception);
989         }
990     }
991
992     free(cpumap);
993     xfree(cpuinfo);
994
995     return result;
996 }
997
998 #if HAVE_VIRDOMAINISACTIVE
999 /*
1000  * call-seq:
1001  *   dom.active? -> [true|false]
1002  *
1003  * Call +virDomainIsActive+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainIsActive]
1004  * to determine if this domain is currently active.
1005  */
1006 static VALUE libvirt_dom_active_p(VALUE d) {
1007     gen_call_truefalse(virDomainIsActive, conn(d), domain_get(d));
1008 }
1009 #endif
1010
1011 #if HAVE_VIRDOMAINISPERSISTENT
1012 /*
1013  * call-seq:
1014  *   dom.persistent? -> [true|false]
1015  *
1016  * Call +virDomainIsPersistent+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainIsPersistent]
1017  * to determine if this is a persistent domain.
1018  */
1019 static VALUE libvirt_dom_persistent_p(VALUE d) {
1020     gen_call_truefalse(virDomainIsPersistent, conn(d), domain_get(d));
1021 }
1022 #endif
1023
1024 /*
1025  * call-seq:
1026  *   dom.ifinfo(if) -> Libvirt::Domain::IfInfo
1027  *
1028  * Call +virDomainInterfaceStats+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainInterfaceStats]
1029  * to retrieve statistics about domain interface if.
1030  */
1031 static VALUE libvirt_dom_if_stats(VALUE s, VALUE sif) {
1032     virDomainPtr dom = domain_get(s);
1033     char *ifname = get_string_or_nil(sif);
1034     virDomainInterfaceStatsStruct ifinfo;
1035     int r;
1036     VALUE result = Qnil;
1037
1038     if (ifname) {
1039         r = virDomainInterfaceStats(dom, ifname, &ifinfo,
1040                                     sizeof(virDomainInterfaceStatsStruct));
1041         _E(r < 0, create_error(e_RetrieveError, "virDomainInterfaceStats",
1042                                conn(s)));
1043
1044         result = rb_class_new_instance(0, NULL, c_domain_ifinfo);
1045         rb_iv_set(result, "@rx_bytes", LL2NUM(ifinfo.rx_bytes));
1046         rb_iv_set(result, "@rx_packets", LL2NUM(ifinfo.rx_packets));
1047         rb_iv_set(result, "@rx_errs", LL2NUM(ifinfo.rx_errs));
1048         rb_iv_set(result, "@rx_drop", LL2NUM(ifinfo.rx_drop));
1049         rb_iv_set(result, "@tx_bytes", LL2NUM(ifinfo.tx_bytes));
1050         rb_iv_set(result, "@tx_packets", LL2NUM(ifinfo.tx_packets));
1051         rb_iv_set(result, "@tx_errs", LL2NUM(ifinfo.tx_errs));
1052         rb_iv_set(result, "@tx_drop", LL2NUM(ifinfo.tx_drop));
1053     }
1054     return result;
1055 }
1056
1057 /*
1058  * call-seq:
1059  *   dom.name -> string
1060  *
1061  * Call +virDomainGetName+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetName]
1062  * to retrieve the name of this domain.
1063  */
1064 static VALUE libvirt_dom_name(VALUE s) {
1065     gen_call_string(virDomainGetName, conn(s), 0, domain_get(s));
1066 }
1067
1068 /*
1069  * call-seq:
1070  *   dom.id -> fixnum
1071  *
1072  * Call +virDomainGetID+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetID]
1073  * to retrieve the ID of this domain.  If the domain isn't running, this will
1074  * be -1.
1075  */
1076 static VALUE libvirt_dom_id(VALUE s) {
1077     virDomainPtr dom = domain_get(s);
1078     unsigned int id;
1079     int out;
1080
1081     id = virDomainGetID(dom);
1082     _E(id == (unsigned int)-1, create_error(e_RetrieveError, "virDomainGetID",
1083                                             conn(s)));
1084
1085     /* we need to cast the unsigned int id to a signed int out to handle the
1086      * -1 case
1087      */
1088     out = id;
1089
1090     return INT2NUM(out);
1091 }
1092
1093 /*
1094  * call-seq:
1095  *   dom.uuid -> string
1096  *
1097  * Call +virDomainGetUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetUUIDString]
1098  * to retrieve the UUID of this domain.
1099  */
1100 static VALUE libvirt_dom_uuid(VALUE s) {
1101     virDomainPtr dom = domain_get(s);
1102     char uuid[VIR_UUID_STRING_BUFLEN];
1103     int r;
1104
1105     r = virDomainGetUUIDString(dom, uuid);
1106     _E(r < 0, create_error(e_RetrieveError, "virDomainGetUUIDString", conn(s)));
1107
1108     return rb_str_new2((char *) uuid);
1109 }
1110
1111 /*
1112  * call-seq:
1113  *   dom.os_type -> string
1114  *
1115  * Call +virDomainGetOSType+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetOSType]
1116  * to retrieve the os_type of this domain.  In libvirt terms, os_type determines
1117  * whether this domain is fully virtualized, paravirtualized, or a container.
1118  */
1119 static VALUE libvirt_dom_os_type(VALUE s) {
1120     gen_call_string(virDomainGetOSType, conn(s), 1, domain_get(s));
1121 }
1122
1123 /*
1124  * call-seq:
1125  *   dom.max_memory -> fixnum
1126  *
1127  * Call +virDomainGetMaxMemory+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetMaxMemory]
1128  * to retrieve the maximum amount of memory this domain is allowed to access.
1129  * Note that the current amount of memory this domain is allowed to access may
1130  * be different (see dom.memory_set).
1131  */
1132 static VALUE libvirt_dom_max_memory(VALUE s) {
1133     virDomainPtr dom = domain_get(s);
1134     unsigned long max_memory;
1135
1136     max_memory = virDomainGetMaxMemory(dom);
1137     _E(max_memory == 0, create_error(e_RetrieveError, "virDomainGetMaxMemory",
1138                                      conn(s)));
1139
1140     return ULONG2NUM(max_memory);
1141 }
1142
1143 /*
1144  * call-seq:
1145  *   dom.max_memory = Fixnum
1146  *
1147  * Call +virDomainSetMaxMemory+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetMaxMemory]
1148  * to set the maximum amount of memory (in kilobytes) this domain should be
1149  * allowed to access.
1150  */
1151 static VALUE libvirt_dom_max_memory_set(VALUE s, VALUE max_memory) {
1152     virDomainPtr dom = domain_get(s);
1153     int r;
1154
1155     r = virDomainSetMaxMemory(dom, NUM2ULONG(max_memory));
1156     _E(r < 0, create_error(e_DefinitionError, "virDomainSetMaxMemory",
1157                            conn(s)));
1158
1159     return ULONG2NUM(max_memory);
1160 }
1161
1162 /*
1163  * call-seq:
1164  *   dom.memory = Fixnum
1165  *
1166  * Call +virDomainSetMemory+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetMemory]
1167  * to set the amount of memory (in kilobytes) this domain should currently
1168  * have.  Note this will only succeed if both the hypervisor and the domain on
1169  * this connection support ballooning.
1170  */
1171 static VALUE libvirt_dom_memory_set(VALUE s, VALUE memory) {
1172     virDomainPtr dom = domain_get(s);
1173     int r;
1174
1175     r = virDomainSetMemory(dom, NUM2ULONG(memory));
1176     _E(r < 0, create_error(e_DefinitionError, "virDomainSetMemory", conn(s)));
1177
1178     return ULONG2NUM(memory);
1179 }
1180
1181 /*
1182  * call-seq:
1183  *   dom.max_vcpus -> fixnum
1184  *
1185  * Call +virDomainGetMaxVcpus+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetMaxVcpus]
1186  * to retrieve the maximum number of virtual CPUs this domain can use.
1187  */
1188 static VALUE libvirt_dom_max_vcpus(VALUE s) {
1189     virDomainPtr dom = domain_get(s);
1190     int vcpus;
1191
1192     vcpus = virDomainGetMaxVcpus(dom);
1193     _E(vcpus < 0, create_error(e_RetrieveError, "virDomainGetMaxVcpus",
1194                                conn(s)));
1195
1196     return INT2NUM(vcpus);
1197 }
1198
1199
1200 /*
1201  * call-seq:
1202  *   dom.vcpus = Fixnum
1203  *
1204  * Call +virDomainSetVcpus+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetVcpus]
1205  * to set the current number of virtual CPUs this domain should have.  Note
1206  * that this will only work if both the hypervisor and domain on this connection
1207  * support virtual CPU hotplug/hot-unplug.
1208  */
1209 static VALUE libvirt_dom_vcpus_set(VALUE s, VALUE nvcpus) {
1210     gen_call_void(virDomainSetVcpus, conn(s), domain_get(s), NUM2UINT(nvcpus));
1211 }
1212
1213 /*
1214  * call-seq:
1215  *   dom.pin_vcpu(vcpu, cpulist) -> nil
1216  *
1217  * Call +virDomainPinVcpu+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainPinVcpu]
1218  * to pin a particular virtual CPU to a range of physical processors.  The
1219  * cpulist should be an array of Fixnums representing the physical processors
1220  * this virtual CPU should be allowed to be scheduled on.
1221  */
1222 static VALUE libvirt_dom_pin_vcpu(VALUE s, VALUE vcpu, VALUE cpulist) {
1223     virDomainPtr dom = domain_get(s);
1224     int r, i, len, maplen;
1225     unsigned char *cpumap;
1226     virNodeInfo nodeinfo;
1227     virConnectPtr c = conn(s);
1228     unsigned int vcpunum;
1229
1230     vcpunum = NUM2UINT(vcpu);
1231     Check_Type(cpulist, T_ARRAY);
1232
1233     r = virNodeGetInfo(c, &nodeinfo);
1234     _E(r < 0, create_error(e_RetrieveError, "virNodeGetInfo", c));
1235
1236     maplen = VIR_CPU_MAPLEN(nodeinfo.cpus);
1237     cpumap = ALLOC_N(unsigned char, maplen);
1238     MEMZERO(cpumap, unsigned char, maplen);
1239
1240     len = RARRAY_LEN(cpulist);
1241     for(i = 0; i < len; i++) {
1242         VALUE e = rb_ary_entry(cpulist, i);
1243         VIR_USE_CPU(cpumap, NUM2UINT(e));
1244     }
1245
1246     r = virDomainPinVcpu(dom, vcpunum, cpumap, maplen);
1247     xfree(cpumap);
1248     _E(r < 0, create_error(e_RetrieveError, "virDomainPinVcpu", c));
1249
1250     return Qnil;
1251 }
1252
1253 /*
1254  * call-seq:
1255  *   dom.xml_desc(flags=0) -> string
1256  *
1257  * Call +virDomainGetXMLDesc+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetXMLDesc]
1258  * to retrieve the XML describing this domain.
1259  */
1260 static VALUE libvirt_dom_xml_desc(int argc, VALUE *argv, VALUE s) {
1261     VALUE flags;
1262
1263     rb_scan_args(argc, argv, "01", &flags);
1264
1265     if (NIL_P(flags))
1266         flags = INT2FIX(0);
1267
1268     gen_call_string(virDomainGetXMLDesc, conn(s), 1, domain_get(s),
1269                     NUM2INT(flags));
1270 }
1271
1272 /*
1273  * call-seq:
1274  *   dom.undefine -> nil
1275  *
1276  * Call +virDomainUndefine+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainUndefine]
1277  * to undefine the domain.  After this call, the domain object is no longer
1278  * valid.
1279  */
1280 static VALUE libvirt_dom_undefine(VALUE s) {
1281     gen_call_void(virDomainUndefine, conn(s), domain_get(s));
1282 }
1283
1284 /*
1285  * call-seq:
1286  *   dom.create(flags=0) -> nil
1287  *
1288  * Call +virDomainCreate+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainCreate]
1289  * to start an already defined domain.
1290  */
1291 static VALUE libvirt_dom_create(int argc, VALUE *argv, VALUE s) {
1292     VALUE flags;
1293
1294     rb_scan_args(argc, argv, "01", &flags);
1295
1296     if (NIL_P(flags))
1297         flags = INT2FIX(0);
1298
1299 #if HAVE_VIRDOMAINCREATEWITHFLAGS
1300     gen_call_void(virDomainCreateWithFlags, conn(s), domain_get(s), NUM2UINT(flags));
1301 #else
1302     if (NUM2UINT(flags) != 0)
1303         rb_raise(e_NoSupportError, "Non-zero flags not supported");
1304     gen_call_void(virDomainCreate, conn(s), domain_get(s));
1305 #endif
1306 }
1307
1308 /*
1309  * call-seq:
1310  *   dom.autostart -> [true|false]
1311  *
1312  * Call +virDomainGetAutostart+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetAutostart]
1313  * to find out the state of the autostart flag for a domain.
1314  */
1315 static VALUE libvirt_dom_autostart(VALUE s){
1316     virDomainPtr dom = domain_get(s);
1317     int r, autostart;
1318
1319     r = virDomainGetAutostart(dom, &autostart);
1320     _E(r < 0, create_error(e_RetrieveError, "virDomainAutostart", conn(s)));
1321
1322     return autostart ? Qtrue : Qfalse;
1323 }
1324
1325 /*
1326  * call-seq:
1327  *   dom.autostart = [true|false]
1328  *
1329  * Call +virDomainSetAutostart+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetAutostart]
1330  * to make this domain autostart when libvirtd starts up.
1331  */
1332 static VALUE libvirt_dom_autostart_set(VALUE s, VALUE autostart) {
1333     if (autostart != Qtrue && autostart != Qfalse)
1334                 rb_raise(rb_eTypeError,
1335                  "wrong argument type (expected TrueClass or FalseClass)");
1336
1337     gen_call_void(virDomainSetAutostart, conn(s),
1338                   domain_get(s), RTEST(autostart) ? 1 : 0);
1339 }
1340
1341 /*
1342  * call-seq:
1343  *   dom.attach_device(device_xml, flags=0) -> nil
1344  *
1345  * Call +virDomainAttachDevice+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainAttachDevice]
1346  * to attach the device described by the device_xml to the domain.
1347  */
1348 static VALUE libvirt_dom_attach_device(int argc, VALUE *argv, VALUE s) {
1349     VALUE xml;
1350     VALUE flags;
1351
1352     rb_scan_args(argc, argv, "11", &xml, &flags);
1353
1354     if (NIL_P(flags))
1355         flags = INT2FIX(0);
1356
1357 #if HAVE_VIRDOMAINATTACHDEVICEFLAGS
1358     gen_call_void(virDomainAttachDeviceFlags, conn(s), domain_get(s),
1359                   StringValueCStr(xml), NUM2UINT(flags));
1360 #else
1361     if (NUM2UINT(flags) != 0)
1362         rb_raise(e_NoSupportError, "Non-zero flags not supported");
1363     gen_call_void(virDomainAttachDevice, conn(s), domain_get(s),
1364                   StringValueCStr(xml));
1365 #endif
1366 }
1367
1368 /*
1369  * call-seq:
1370  *   dom.detach_device(device_xml, flags=0) -> nil
1371  *
1372  * Call +virDomainDetachDevice+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainDetachDevice]
1373  * to detach the device described the device_xml from the domain.
1374  */
1375 static VALUE libvirt_dom_detach_device(int argc, VALUE *argv, VALUE s) {
1376     VALUE xml;
1377     VALUE flags;
1378
1379     rb_scan_args(argc, argv, "11", &xml, &flags);
1380
1381     if (NIL_P(flags))
1382         flags = INT2FIX(0);
1383
1384 #if HAVE_VIRDOMAINDETACHDEVICEFLAGS
1385     gen_call_void(virDomainDetachDeviceFlags, conn(s), domain_get(s),
1386                   StringValueCStr(xml), NUM2UINT(flags));
1387 #else
1388     if (NUM2UINT(flags) != 0)
1389         rb_raise(e_NoSupportError, "Non-zero flags not supported");
1390     gen_call_void(virDomainDetachDevice, conn(s), domain_get(s),
1391                   StringValueCStr(xml));
1392 #endif
1393 }
1394
1395 #if HAVE_VIRDOMAINUPDATEDEVICEFLAGS
1396 /*
1397  * call-seq:
1398  *   dom.update_device(device_xml, flags=0) -> nil
1399  *
1400  * Call +virDomainUpdateDeviceFlags+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainUpdateDeviceFlags]
1401  * to update the device described the device_xml from the domain.
1402  */
1403 static VALUE libvirt_dom_update_device(int argc, VALUE *argv, VALUE s) {
1404     VALUE xml;
1405     VALUE flags;
1406
1407     rb_scan_args(argc, argv, "11", &xml, &flags);
1408
1409     if (NIL_P(flags))
1410         flags = INT2FIX(0);
1411
1412     gen_call_void(virDomainUpdateDeviceFlags, conn(s), domain_get(s),
1413                   StringValueCStr(xml), NUM2UINT(flags));
1414 }
1415 #endif
1416
1417 /*
1418  * call-seq:
1419  *   dom.free -> nil
1420  *
1421  * Call +virDomainFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainFree]
1422  * to free a domain object.
1423  */
1424 static VALUE libvirt_dom_free(VALUE s) {
1425     gen_call_free(Domain, s);
1426 }
1427
1428 #if HAVE_TYPE_VIRDOMAINSNAPSHOTPTR
1429 static void domain_snapshot_free(void *d) {
1430     generic_free(DomainSnapshot, d);
1431 }
1432
1433 static VALUE domain_snapshot_new(virDomainSnapshotPtr d, VALUE domain) {
1434     VALUE result;
1435     result = Data_Wrap_Struct(c_domain_snapshot, NULL, domain_snapshot_free, d);
1436     rb_iv_set(result, "@domain", domain);
1437     return result;
1438 }
1439
1440 static virDomainSnapshotPtr domain_snapshot_get(VALUE s) {
1441     generic_get(DomainSnapshot, s);
1442 }
1443
1444 /*
1445  * call-seq:
1446  *   dom.snapshot_create_xml(snapshot_xml, flags=0) -> Libvirt::Domain::Snapshot
1447  *
1448  * Call +virDomainSnapshotCreateXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotCreateXML]
1449  * to create a new snapshot based on snapshot_xml.
1450  */
1451 static VALUE libvirt_dom_snapshot_create_xml(int argc, VALUE *argv, VALUE d) {
1452     VALUE xmlDesc, flags;
1453     virDomainSnapshotPtr ret;
1454
1455     rb_scan_args(argc, argv, "11", &xmlDesc, &flags);
1456
1457     if (NIL_P(flags))
1458         flags = INT2FIX(0);
1459
1460     ret = virDomainSnapshotCreateXML(domain_get(d), StringValueCStr(xmlDesc),
1461                                      NUM2UINT(flags));
1462
1463     _E(ret == NULL, create_error(e_Error, "virDomainSnapshotCreateXML",
1464                                  conn(d)));
1465
1466     return domain_snapshot_new(ret, d);
1467 }
1468
1469 /*
1470  * call-seq:
1471  *   dom.num_of_snapshots(flags=0) -> fixnum
1472  *
1473  * Call +virDomainSnapshotNum+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotNum]
1474  * to retrieve the number of available snapshots for this domain.
1475  */
1476 static VALUE libvirt_dom_num_of_snapshots(int argc, VALUE *argv, VALUE d) {
1477     int result;
1478     virDomainPtr dom = domain_get(d);
1479     VALUE flags;
1480
1481     rb_scan_args(argc, argv, "01", &flags);
1482
1483     if (NIL_P(flags))
1484         flags = INT2FIX(0);
1485
1486     result = virDomainSnapshotNum(dom, NUM2UINT(flags));
1487     _E(result < 0, create_error(e_RetrieveError, "virDomainSnapshotNum",
1488                                 conn(d)));
1489
1490     return INT2NUM(result);
1491 }
1492
1493 /*
1494  * call-seq:
1495  *   dom.list_snapshots(flags=0) -> list
1496  *
1497  * Call +virDomainSnapshotListNames+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotListNames]
1498  * to retrieve a list of snapshot names available for this domain.
1499  */
1500 static VALUE libvirt_dom_list_snapshots(int argc, VALUE *argv, VALUE d) {
1501     VALUE flags_val;
1502     int r;
1503     int num;
1504     virDomainPtr dom = domain_get(d);
1505     char **names;
1506     unsigned int flags;
1507
1508     rb_scan_args(argc, argv, "01", &flags_val);
1509
1510     if (NIL_P(flags_val))
1511         flags = 0;
1512     else
1513         flags = NUM2UINT(flags_val);
1514
1515     num = virDomainSnapshotNum(dom, 0);
1516     _E(num < 0, create_error(e_RetrieveError, "virDomainSnapshotNum", conn(d)));
1517     if (num == 0)
1518         /* if num is 0, don't call virDomainSnapshotListNames function */
1519         return rb_ary_new2(num);
1520
1521     names = ALLOC_N(char *, num);
1522
1523     r = virDomainSnapshotListNames(domain_get(d), names, num, flags);
1524     if (r < 0) {
1525         xfree(names);
1526         rb_exc_raise(create_error(e_RetrieveError, "virDomainSnapshotListNames",
1527                                   conn(d)));
1528     }
1529
1530     return gen_list(num, &names);
1531 }
1532
1533 /*
1534  * call-seq:
1535  *   dom.lookup_snapshot_by_name(name, flags=0) -> Libvirt::Domain::Snapshot
1536  *
1537  * Call +virDomainSnapshotLookupByName+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotLookupByName]
1538  * to retrieve a snapshot object corresponding to snapshot name.
1539  */
1540 static VALUE libvirt_dom_lookup_snapshot_by_name(int argc, VALUE *argv, VALUE d) {
1541     virDomainPtr dom = domain_get(d);
1542     virDomainSnapshotPtr snap;
1543     VALUE name, flags;
1544
1545     rb_scan_args(argc, argv, "11", &name, &flags);
1546
1547     if (NIL_P(flags))
1548         flags = INT2FIX(0);
1549
1550     snap = virDomainSnapshotLookupByName(dom, StringValueCStr(name),
1551                                          NUM2UINT(flags));
1552     _E(dom == NULL, create_error(e_RetrieveError,
1553                                  "virDomainSnapshotLookupByName", conn(d)));
1554
1555     return domain_snapshot_new(snap, d);
1556 }
1557
1558 /*
1559  * call-seq:
1560  *   dom.has_current_snapshot?(flags=0) -> [true|false]
1561  *
1562  * Call +virDomainHasCurrentSnapshot+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainHasCurrentSnapshot]
1563  * to find out if this domain has a snapshot active.
1564  */
1565 static VALUE libvirt_dom_has_current_snapshot_p(int argc, VALUE *argv, VALUE d) {
1566     VALUE flags;
1567
1568     rb_scan_args(argc, argv, "01", &flags);
1569
1570     if (NIL_P(flags))
1571         flags = INT2FIX(0);
1572
1573     gen_call_truefalse(virDomainHasCurrentSnapshot, conn(d), domain_get(d),
1574                        NUM2UINT(flags));
1575 }
1576
1577 /*
1578  * call-seq:
1579  *   dom.revert_to_snapshot(snapshot_object, flags=0) -> nil
1580  *
1581  * Call +virDomainRevertToSnapshot+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainRevertToSnapshot]
1582  * to restore this domain to a previously saved snapshot.
1583  */
1584 static VALUE libvirt_dom_revert_to_snapshot(int argc, VALUE *argv, VALUE d) {
1585     VALUE snap, flags;
1586     int r;
1587
1588     rb_scan_args(argc, argv, "11", &snap, &flags);
1589
1590     if (NIL_P(flags))
1591         flags = INT2FIX(0);
1592
1593     r = virDomainRevertToSnapshot(domain_snapshot_get(snap), NUM2UINT(flags));
1594     _E(r < 0, create_error(e_RetrieveError, "virDomainRevertToSnapshot",
1595                            conn(d)));
1596
1597     return Qnil;
1598 }
1599
1600 /*
1601  * call-seq:
1602  *   dom.current_snapshot(flags=0) -> Libvirt::Domain::Snapshot
1603  *
1604  * Call +virDomainCurrentSnapshot+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainCurrentSnapshot]
1605  * to retrieve the current snapshot for this domain (if any).
1606  */
1607 static VALUE libvirt_dom_current_snapshot(int argc, VALUE *argv, VALUE d) {
1608     VALUE flags;
1609     virDomainSnapshotPtr snap;
1610
1611     rb_scan_args(argc, argv, "01", &flags);
1612
1613     if (NIL_P(flags))
1614         flags = INT2FIX(0);
1615
1616     snap = virDomainSnapshotCurrent(domain_get(d), NUM2UINT(flags));
1617     _E(snap == NULL, create_error(e_RetrieveError, "virDomainSnapshotCurrent",
1618                                   conn(d)));
1619
1620     return domain_snapshot_new(snap, d);
1621 }
1622
1623 /*
1624  * call-seq:
1625  *   snapshot.xml_desc(flags=0) -> string
1626  *
1627  * Call +virDomainSnapshotGetXMLDesc+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotGetXMLDesc]
1628  * to retrieve the xml description for this snapshot.
1629  */
1630 static VALUE libvirt_dom_snapshot_xml_desc(int argc, VALUE *argv, VALUE s) {
1631     VALUE flags;
1632
1633     rb_scan_args(argc, argv, "01", &flags);
1634
1635     if (NIL_P(flags))
1636         flags = INT2FIX(0);
1637
1638     gen_call_string(virDomainSnapshotGetXMLDesc, conn(s), 1,
1639                     domain_snapshot_get(s), NUM2UINT(flags));
1640 }
1641
1642 /*
1643  * call-seq:
1644  *   snapshot.delete(flags=0) -> nil
1645  *
1646  * Call +virDomainSnapshotDelete+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotDelete]
1647  * to delete this snapshot.
1648  */
1649 static VALUE libvirt_dom_snapshot_delete(int argc, VALUE *argv, VALUE s) {
1650     VALUE flags;
1651
1652     rb_scan_args(argc, argv, "01", &flags);
1653
1654     if (NIL_P(flags))
1655         flags = INT2FIX(0);
1656
1657     gen_call_void(virDomainSnapshotDelete, conn(s),
1658                   domain_snapshot_get(s), NUM2UINT(flags));
1659 }
1660
1661 /*
1662  * call-seq:
1663  *   snapshot.free -> nil
1664  *
1665  * Call +virDomainSnapshotFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotFree]
1666  * to free up the snapshot object.  After this call the snapshot object is
1667  * no longer valid.
1668  */
1669 static VALUE libvirt_dom_snapshot_free(VALUE s) {
1670     gen_call_free(DomainSnapshot, s);
1671 }
1672
1673 #endif
1674
1675 #if HAVE_TYPE_VIRDOMAINJOBINFOPTR
1676 /*
1677  * call-seq:
1678  *   dom.job_info -> Libvirt::Domain::JobInfo
1679  *
1680  * Call +virDomainGetJobInfo+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetJobInfo]
1681  * to retrieve the current state of the running domain job.
1682  */
1683 static VALUE libvirt_dom_job_info(VALUE d) {
1684     int r;
1685     virDomainJobInfo info;
1686     VALUE result;
1687
1688     r = virDomainGetJobInfo(domain_get(d), &info);
1689     _E(r < 0, create_error(e_RetrieveError, "virDomainGetJobInfo", conn(d)));
1690
1691     result = rb_class_new_instance(0, NULL, c_domain_job_info);
1692     rb_iv_set(result, "@type", INT2NUM(info.type));
1693     rb_iv_set(result, "@time_elapsed", ULL2NUM(info.timeElapsed));
1694     rb_iv_set(result, "@time_remaining", ULL2NUM(info.timeRemaining));
1695     rb_iv_set(result, "@data_total", ULL2NUM(info.dataTotal));
1696     rb_iv_set(result, "@data_processed", ULL2NUM(info.dataProcessed));
1697     rb_iv_set(result, "@data_remaining", ULL2NUM(info.dataRemaining));
1698     rb_iv_set(result, "@mem_total", ULL2NUM(info.memTotal));
1699     rb_iv_set(result, "@mem_processed", ULL2NUM(info.memProcessed));
1700     rb_iv_set(result, "@mem_remaining", ULL2NUM(info.memRemaining));
1701     rb_iv_set(result, "@file_total", ULL2NUM(info.fileTotal));
1702     rb_iv_set(result, "@file_processed", ULL2NUM(info.fileProcessed));
1703     rb_iv_set(result, "@file_remaining", ULL2NUM(info.fileRemaining));
1704
1705     return result;
1706 }
1707
1708 /*
1709  * call-seq:
1710  *   dom.abort_job -> nil
1711  *
1712  * Call +virDomainAbortJob+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainAbortJob]
1713  * to abort the currently running job on this domain.
1714  */
1715 static VALUE libvirt_dom_abort_job(VALUE d) {
1716     gen_call_void(virDomainAbortJob, conn(d), domain_get(d));
1717 }
1718
1719 #endif
1720
1721 /*
1722  * call-seq:
1723  *   dom.scheduler_type -> [type, #params]
1724  *
1725  * Call +virDomainGetSchedulerType+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetSchedulerType]
1726  * to retrieve the scheduler type used on this domain.
1727  */
1728 static VALUE libvirt_dom_scheduler_type(VALUE d) {
1729     int nparams;
1730     char *type;
1731     VALUE result;
1732     int exception = 0;
1733     struct rb_ary_push_arg args;
1734
1735     type = virDomainGetSchedulerType(domain_get(d), &nparams);
1736
1737     _E(type == NULL, create_error(e_RetrieveError, "virDomainGetSchedulerType",
1738                                   conn(d)));
1739
1740     result = rb_protect(rb_ary_new_wrap, (VALUE)NULL, &exception);
1741     if (exception) {
1742         free(type);
1743         rb_jump_tag(exception);
1744     }
1745
1746     args.arr = result;
1747     args.value = rb_protect(rb_str_new2_wrap, (VALUE)&type, &exception);
1748     if (exception) {
1749         free(type);
1750         rb_jump_tag(exception);
1751     }
1752     rb_protect(rb_ary_push_wrap, (VALUE)&args, &exception);
1753     if (exception) {
1754         free(type);
1755         rb_jump_tag(exception);
1756     }
1757
1758     args.arr = result;
1759     args.value = INT2FIX(nparams);
1760     rb_protect(rb_ary_push_wrap, (VALUE)&args, &exception);
1761     free(type);
1762     if (exception)
1763         rb_jump_tag(exception);
1764
1765     return result;
1766 }
1767
1768 /*
1769  * call-seq:
1770  *   dom.scheduler_parameters -> Hash
1771  *
1772  * Call +virDomainGetSchedulerParameters+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetSchedulerParameters]
1773  * to retrieve all of the scheduler parameters for this domain.  The keys and
1774  * values in the hash that is returned are hypervisor specific.
1775  */
1776 static VALUE libvirt_dom_scheduler_parameters(VALUE d) {
1777     int nparams;
1778     char *type;
1779     virSchedParameterPtr params;
1780     VALUE result;
1781     virDomainPtr dom;
1782     int r;
1783     int i;
1784     VALUE val;
1785
1786     dom = domain_get(d);
1787
1788     type = virDomainGetSchedulerType(dom, &nparams);
1789
1790     _E(type == NULL, create_error(e_RetrieveError, "virDomainGetSchedulerType",
1791                                   conn(d)));
1792
1793     xfree(type);
1794
1795     params = ALLOC_N(virSchedParameter, nparams);
1796
1797     r = virDomainGetSchedulerParameters(dom, params, &nparams);
1798     if (r < 0) {
1799         xfree(params);
1800         rb_exc_raise(create_error(e_RetrieveError,
1801                                   "virDomainGetSchedulerParameters", conn(d)));
1802     }
1803
1804     /* just to shut the compiler up */
1805     val = Qnil;
1806
1807     result = rb_hash_new();
1808     for (i = 0; i < nparams; i++) {
1809         switch(params[i].type) {
1810         case VIR_DOMAIN_SCHED_FIELD_INT:
1811             val = INT2FIX(params[i].value.i);
1812             break;
1813         case VIR_DOMAIN_SCHED_FIELD_UINT:
1814             val = UINT2NUM(params[i].value.ui);
1815             break;
1816         case VIR_DOMAIN_SCHED_FIELD_LLONG:
1817             val = LL2NUM(params[i].value.l);
1818             break;
1819         case VIR_DOMAIN_SCHED_FIELD_ULLONG:
1820             val = ULL2NUM(params[i].value.ul);
1821             break;
1822         case VIR_DOMAIN_SCHED_FIELD_DOUBLE:
1823             val = rb_float_new(params[i].value.d);
1824             break;
1825         case VIR_DOMAIN_SCHED_FIELD_BOOLEAN:
1826             val = (params[i].value.b == 0) ? Qfalse : Qtrue;
1827             break;
1828         default:
1829             xfree(params);
1830             rb_raise(rb_eArgError, "Invalid parameter type");
1831         }
1832
1833         rb_hash_aset(result, rb_str_new2(params[i].field), val);
1834     }
1835
1836     xfree(params);
1837
1838     return result;
1839 }
1840
1841 /*
1842  * call-seq:
1843  *   dom.scheduler_parameters = Hash
1844  *
1845  * Call +virDomainSetSchedulerParameters+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetSchedulerParameters]
1846  * to set the scheduler parameters for this domain.  The keys and values in
1847  * the input hash are hypervisor specific.
1848  */
1849 static VALUE libvirt_dom_scheduler_parameters_set(VALUE d, VALUE input) {
1850     int nparams;
1851     char *type;
1852     virSchedParameterPtr params;
1853     virDomainPtr dom;
1854     int r;
1855     int i;
1856     VALUE val;
1857
1858     Check_Type(input, T_HASH);
1859
1860     dom = domain_get(d);
1861
1862     type = virDomainGetSchedulerType(dom, &nparams);
1863
1864     _E(type == NULL, create_error(e_RetrieveError, "virDomainGetSchedulerType",
1865                                   conn(d)));
1866
1867     xfree(type);
1868
1869     params = ALLOC_N(virSchedParameter, nparams);
1870
1871     r = virDomainGetSchedulerParameters(dom, params, &nparams);
1872     if (r < 0) {
1873         xfree(params);
1874         rb_exc_raise(create_error(e_RetrieveError,
1875                                   "virDomainGetSchedulerParameters", conn(d)));
1876     }
1877
1878     for (i = 0; i < nparams; i++) {
1879         val = rb_hash_aref(input, rb_str_new2(params[i].field));
1880
1881         switch(params[i].type) {
1882         case VIR_DOMAIN_SCHED_FIELD_INT:
1883             params[i].value.i = NUM2INT(val);
1884             break;
1885         case VIR_DOMAIN_SCHED_FIELD_UINT:
1886             params[i].value.ui = NUM2UINT(val);
1887             break;
1888         case VIR_DOMAIN_SCHED_FIELD_LLONG:
1889             params[i].value.l = NUM2LL(val);
1890             break;
1891         case VIR_DOMAIN_SCHED_FIELD_ULLONG:
1892             params[i].value.ul = NUM2ULL(val);
1893             break;
1894         case VIR_DOMAIN_SCHED_FIELD_DOUBLE:
1895             params[i].value.d = NUM2DBL(val);
1896             break;
1897         case VIR_DOMAIN_SCHED_FIELD_BOOLEAN:
1898             params[i].value.b = (val == Qtrue) ? 1 : 0;
1899             break;
1900         default:
1901             xfree(params);
1902             rb_raise(rb_eArgError, "Invalid parameter type");
1903         }
1904     }
1905
1906     r = virDomainSetSchedulerParameters(dom, params, nparams);
1907     if (r < 0) {
1908         xfree(params);
1909         rb_exc_raise(create_error(e_RetrieveError,
1910                                   "virDomainSetSchedulerParameters", conn(d)));
1911     }
1912
1913     xfree(params);
1914
1915     return Qnil;
1916 }
1917
1918 #if HAVE_VIRDOMAINQEMUMONITORCOMMAND
1919 /*
1920  * call-seq:
1921  *   dom.qemu_monitor_command -> string
1922  *
1923  * Call virDomainQemuMonitorCommand
1924  * to send a qemu command directly to the monitor.  Note that this will only
1925  * work on qemu hypervisors, and the input and output formats are not
1926  * guaranteed to be stable.  Also note that using this command can severly
1927  * impede libvirt's ability to manage the domain; use with caution!
1928  */
1929 static VALUE libvirt_dom_qemu_monitor_command(int argc, VALUE *argv, VALUE d) {
1930     VALUE cmd, flags;
1931     virDomainPtr dom;
1932     char *result;
1933     VALUE ret;
1934     int exception;
1935     virConnectPtr c;
1936
1937     rb_scan_args(argc, argv, "11", &cmd, &flags);
1938
1939     if (NIL_P(flags))
1940         flags = INT2FIX(0);
1941
1942     c = conn(d);
1943     type = virConnectGetType(c);
1944     _E(type == NULL, create_error(e_Error, "virConnectGetType", c));
1945     if (strcmp(type, "QEMU") != 0)
1946         rb_raise(rb_TypeError, "Tried to use virDomainQemuMonitor command on %s connection", type);
1947
1948     dom = domain_get(d);
1949
1950     r = virDomainQemuMonitorCommand(dom, StringValueCStr(cmd), &result,
1951                                     NUM2UINT(flags));
1952     _E(r < 0, create_error(e_RetrieveError, "virDomainQemuMonitorCommand", c));
1953
1954     ret = rb_protect(rb_str_new2_wrap, &result, &exception);
1955     free(result);
1956     if (exception)
1957         rb_jump_tag(exception);
1958
1959     return ret;
1960 }
1961 #endif
1962
1963 /*
1964  * Class Libvirt::Domain
1965  */
1966 void init_domain()
1967 {
1968     c_domain = rb_define_class_under(m_libvirt, "Domain", rb_cObject);
1969
1970     rb_define_const(c_domain, "NOSTATE", INT2NUM(VIR_DOMAIN_NOSTATE));
1971     rb_define_const(c_domain, "RUNNING", INT2NUM(VIR_DOMAIN_RUNNING));
1972     rb_define_const(c_domain, "BLOCKED", INT2NUM(VIR_DOMAIN_BLOCKED));
1973     rb_define_const(c_domain, "PAUSED", INT2NUM(VIR_DOMAIN_PAUSED));
1974     rb_define_const(c_domain, "SHUTDOWN", INT2NUM(VIR_DOMAIN_SHUTDOWN));
1975     rb_define_const(c_domain, "SHUTOFF", INT2NUM(VIR_DOMAIN_SHUTOFF));
1976     rb_define_const(c_domain, "CRASHED", INT2NUM(VIR_DOMAIN_CRASHED));
1977
1978     /* virDomainMigrateFlags */
1979 #if HAVE_CONST_VIR_MIGRATE_LIVE
1980     rb_define_const(c_domain, "MIGRATE_LIVE", INT2NUM(VIR_MIGRATE_LIVE));
1981 #endif
1982 #if HAVE_CONST_VIR_MIGRATE_PEER2PEER
1983     rb_define_const(c_domain, "MIGRATE_PEER2PEER",
1984                     INT2NUM(VIR_MIGRATE_PEER2PEER));
1985 #endif
1986 #if HAVE_CONST_VIR_MIGRATE_TUNNELLED
1987     rb_define_const(c_domain, "MIGRATE_TUNNELLED",
1988                     INT2NUM(VIR_MIGRATE_TUNNELLED));
1989 #endif
1990 #if HAVE_CONST_VIR_MIGRATE_PERSIST_DEST
1991     rb_define_const(c_domain, "MIGRATE_PERSIST_DEST",
1992                     INT2NUM(VIR_MIGRATE_PERSIST_DEST));
1993 #endif
1994 #if HAVE_CONST_VIR_MIGRATE_UNDEFINE_SOURCE
1995     rb_define_const(c_domain, "MIGRATE_UNDEFINE_SOURCE",
1996                     INT2NUM(VIR_MIGRATE_UNDEFINE_SOURCE));
1997 #endif
1998 #if HAVE_CONST_VIR_MIGRATE_PAUSED
1999     rb_define_const(c_domain, "MIGRATE_PAUSED", INT2NUM(VIR_MIGRATE_PAUSED));
2000 #endif
2001 #if HAVE_CONST_VIR_MIGRATE_NON_SHARED_DISK
2002     rb_define_const(c_domain, "MIGRATE_NON_SHARED_DISK",
2003                     INT2NUM(VIR_MIGRATE_NON_SHARED_DISK));
2004 #endif
2005 #if HAVE_CONST_VIR_MIGRATE_NON_SHARED_INC
2006     rb_define_const(c_domain, "MIGRATE_NON_SHARED_INC",
2007                     INT2NUM(VIR_MIGRATE_NON_SHARED_INC));
2008 #endif
2009     rb_define_const(c_domain, "DOMAIN_XML_SECURE",
2010                     INT2NUM(VIR_DOMAIN_XML_SECURE));
2011     rb_define_const(c_domain, "DOMAIN_XML_INACTIVE",
2012                     INT2NUM(VIR_DOMAIN_XML_INACTIVE));
2013 #if HAVE_CONST_VIR_DOMAIN_XML_UPDATE_CPU
2014     rb_define_const(c_domain, "DOMAIN_XML_UPDATE_CPU",
2015                     INT2NUM(VIR_DOMAIN_XML_UPDATE_CPU));
2016 #endif
2017     rb_define_const(c_domain, "MEMORY_VIRTUAL", INT2NUM(VIR_MEMORY_VIRTUAL));
2018 #if HAVE_CONST_VIR_MEMORY_PHYSICAL
2019     rb_define_const(c_domain, "MEMORY_PHYSICAL", INT2NUM(VIR_MEMORY_PHYSICAL));
2020 #endif
2021
2022 #if HAVE_CONST_VIR_DOMAIN_START_PAUSED
2023     rb_define_const(c_domain, "START_PAUSED", INT2NUM(VIR_DOMAIN_START_PAUSED));
2024 #endif
2025
2026 #if HAVE_CONST_VIR_DUMP_CRASH
2027     rb_define_const(c_domain, "DUMP_CRASH", INT2NUM(VIR_DUMP_CRASH));
2028 #endif
2029 #if HAVE_CONST_VIR_DUMP_LIVE
2030     rb_define_const(c_domain, "DUMP_LIVE", INT2NUM(VIR_DUMP_LIVE));
2031 #endif
2032
2033     /* Domain creation/lookup */
2034     rb_define_method(c_connect, "num_of_domains",
2035                      libvirt_conn_num_of_domains, 0);
2036     rb_define_method(c_connect, "list_domains", libvirt_conn_list_domains, 0);
2037     rb_define_method(c_connect, "num_of_defined_domains",
2038                      libvirt_conn_num_of_defined_domains, 0);
2039     rb_define_method(c_connect, "list_defined_domains",
2040                      libvirt_conn_list_defined_domains, 0);
2041     rb_define_method(c_connect, "create_domain_linux",
2042                      libvirt_conn_create_linux, -1);
2043 #if HAVE_VIRDOMAINCREATEXML
2044     rb_define_method(c_connect, "create_domain_xml",
2045                      libvirt_conn_create_xml, -1);
2046 #endif
2047     rb_define_method(c_connect, "lookup_domain_by_name",
2048                      libvirt_conn_lookup_domain_by_name, 1);
2049     rb_define_method(c_connect, "lookup_domain_by_id",
2050                      libvirt_conn_lookup_domain_by_id, 1);
2051     rb_define_method(c_connect, "lookup_domain_by_uuid",
2052                      libvirt_conn_lookup_domain_by_uuid, 1);
2053     rb_define_method(c_connect, "define_domain_xml",
2054                      libvirt_conn_define_domain_xml, 1);
2055
2056 #if HAVE_VIRCONNECTDOMAINXMLFROMNATIVE
2057     rb_define_method(c_connect, "domain_xml_from_native",
2058                      libvirt_conn_domain_xml_from_native, -1);
2059 #endif
2060 #if HAVE_VIRCONNECTDOMAINXMLTONATIVE
2061     rb_define_method(c_connect, "domain_xml_to_native",
2062                      libvirt_conn_domain_xml_to_native, -1);
2063 #endif
2064
2065     rb_define_method(c_domain, "migrate", libvirt_dom_migrate, -1);
2066 #if HAVE_VIRDOMAINMIGRATETOURI
2067     rb_define_method(c_domain, "migrate_to_uri",
2068                      libvirt_dom_migrate_to_uri, -1);
2069 #endif
2070 #if HAVE_VIRDOMAINMIGRATESETMAXDOWNTIME
2071     rb_define_method(c_domain, "migrate_set_max_downtime",
2072                      libvirt_dom_migrate_set_max_downtime, -1);
2073 #endif
2074     rb_define_attr(c_domain, "connection", 1, 0);
2075     rb_define_method(c_domain, "shutdown", libvirt_dom_shutdown, 0);
2076     rb_define_method(c_domain, "reboot", libvirt_dom_reboot, -1);
2077     rb_define_method(c_domain, "destroy", libvirt_dom_destroy, 0);
2078     rb_define_method(c_domain, "suspend", libvirt_dom_suspend, 0);
2079     rb_define_method(c_domain, "resume", libvirt_dom_resume, 0);
2080     rb_define_method(c_domain, "save", libvirt_dom_save, 1);
2081     rb_define_singleton_method(c_domain, "restore", libvirt_dom_s_restore, 2);
2082     rb_define_method(c_domain, "restore", libvirt_dom_restore, 1);
2083     rb_define_method(c_domain, "core_dump", libvirt_dom_core_dump, -1);
2084     rb_define_method(c_domain, "info", libvirt_dom_info, 0);
2085     rb_define_method(c_domain, "ifinfo", libvirt_dom_if_stats, 1);
2086     rb_define_method(c_domain, "name", libvirt_dom_name, 0);
2087     rb_define_method(c_domain, "id", libvirt_dom_id, 0);
2088     rb_define_method(c_domain, "uuid", libvirt_dom_uuid, 0);
2089     rb_define_method(c_domain, "os_type", libvirt_dom_os_type, 0);
2090     rb_define_method(c_domain, "max_memory", libvirt_dom_max_memory, 0);
2091     rb_define_method(c_domain, "max_memory=", libvirt_dom_max_memory_set, 1);
2092     rb_define_method(c_domain, "memory=", libvirt_dom_memory_set, 1);
2093     rb_define_method(c_domain, "max_vcpus", libvirt_dom_max_vcpus, 0);
2094     rb_define_method(c_domain, "vcpus=", libvirt_dom_vcpus_set, 1);
2095     rb_define_method(c_domain, "pin_vcpu", libvirt_dom_pin_vcpu, 2);
2096     rb_define_method(c_domain, "xml_desc", libvirt_dom_xml_desc, -1);
2097     rb_define_method(c_domain, "undefine", libvirt_dom_undefine, 0);
2098     rb_define_method(c_domain, "create", libvirt_dom_create, -1);
2099     rb_define_method(c_domain, "autostart", libvirt_dom_autostart, 0);
2100     rb_define_method(c_domain, "autostart?", libvirt_dom_autostart, 0);
2101     rb_define_method(c_domain, "autostart=", libvirt_dom_autostart_set, 1);
2102     rb_define_method(c_domain, "free", libvirt_dom_free, 0);
2103
2104 #if HAVE_CONST_VIR_DOMAIN_DEVICE_MODIFY_CURRENT
2105     rb_define_const(c_domain, "DEVICE_MODIFY_CURRENT",
2106                     INT2NUM(VIR_DOMAIN_DEVICE_MODIFY_CURRENT));
2107 #endif
2108 #if HAVE_CONST_VIR_DOMAIN_DEVICE_MODIFY_LIVE
2109     rb_define_const(c_domain, "DEVICE_MODIFY_LIVE",
2110                     INT2NUM(VIR_DOMAIN_DEVICE_MODIFY_LIVE));
2111 #endif
2112 #if HAVE_CONST_VIR_DOMAIN_DEVICE_MODIFY_CONFIG
2113     rb_define_const(c_domain, "DEVICE_MODIFY_CONFIG",
2114                     INT2NUM(VIR_DOMAIN_DEVICE_MODIFY_CONFIG));
2115 #endif
2116     rb_define_method(c_domain, "attach_device", libvirt_dom_attach_device, -1);
2117     rb_define_method(c_domain, "detach_device", libvirt_dom_detach_device, -1);
2118 #if HAVE_VIRDOMAINUPDATEDEVICEFLAGS
2119     rb_define_method(c_domain, "update_device", libvirt_dom_update_device, -1);
2120 #endif
2121
2122     rb_define_method(c_domain, "scheduler_type", libvirt_dom_scheduler_type, 0);
2123     rb_define_method(c_domain, "scheduler_parameters",
2124                      libvirt_dom_scheduler_parameters, 0);
2125     rb_define_method(c_domain, "scheduler_parameters=",
2126                      libvirt_dom_scheduler_parameters_set, 1);
2127
2128 #if HAVE_VIRDOMAINMANAGEDSAVE
2129     rb_define_method(c_domain, "managed_save", libvirt_dom_managed_save, -1);
2130     rb_define_method(c_domain, "has_managed_save?",
2131                      libvirt_dom_has_managed_save, -1);
2132     rb_define_method(c_domain, "managed_save_remove",
2133                      libvirt_dom_managed_save_remove, -1);
2134 #endif
2135 #if HAVE_VIRDOMAINGETSECURITYLABEL
2136     rb_define_method(c_domain, "security_label",
2137                      libvirt_dom_security_label, 0);
2138 #endif
2139     rb_define_method(c_domain, "block_stats", libvirt_dom_block_stats, 1);
2140 #if HAVE_TYPE_VIRDOMAINMEMORYSTATPTR
2141     rb_define_method(c_domain, "memory_stats", libvirt_dom_memory_stats, -1);
2142 #endif
2143     rb_define_method(c_domain, "block_peek", libvirt_dom_block_peek, -1);
2144 #if HAVE_TYPE_VIRDOMAINBLOCKINFOPTR
2145     rb_define_method(c_domain, "blockinfo", libvirt_dom_block_info, -1);
2146 #endif
2147     rb_define_method(c_domain, "memory_peek", libvirt_dom_memory_peek, -1);
2148     rb_define_method(c_domain, "get_vcpus", libvirt_dom_get_vcpus, 0);
2149 #if HAVE_VIRDOMAINISACTIVE
2150     rb_define_method(c_domain, "active?", libvirt_dom_active_p, 0);
2151 #endif
2152 #if HAVE_VIRDOMAINISPERSISTENT
2153     rb_define_method(c_domain, "persistent?", libvirt_dom_persistent_p, 0);
2154 #endif
2155 #if HAVE_TYPE_VIRDOMAINSNAPSHOTPTR
2156     rb_define_method(c_domain, "snapshot_create_xml",
2157                      libvirt_dom_snapshot_create_xml, -1);
2158     rb_define_method(c_domain, "num_of_snapshots",
2159                      libvirt_dom_num_of_snapshots, -1);
2160     rb_define_method(c_domain, "list_snapshots",
2161                      libvirt_dom_list_snapshots, -1);
2162     rb_define_method(c_domain, "lookup_snapshot_by_name",
2163                      libvirt_dom_lookup_snapshot_by_name, -1);
2164     rb_define_method(c_domain, "has_current_snapshot?",
2165                      libvirt_dom_has_current_snapshot_p, -1);
2166     rb_define_method(c_domain, "revert_to_snapshot",
2167                      libvirt_dom_revert_to_snapshot, -1);
2168     rb_define_method(c_domain, "current_snapshot",
2169                      libvirt_dom_current_snapshot, -1);
2170 #endif
2171
2172     /*
2173      * Class Libvirt::Domain::Info
2174      */
2175     c_domain_info = rb_define_class_under(c_domain, "Info", rb_cObject);
2176     rb_define_attr(c_domain_info, "state", 1, 0);
2177     rb_define_attr(c_domain_info, "max_mem", 1, 0);
2178     rb_define_attr(c_domain_info, "memory", 1, 0);
2179     rb_define_attr(c_domain_info, "nr_virt_cpu", 1, 0);
2180     rb_define_attr(c_domain_info, "cpu_time", 1, 0);
2181
2182     /*
2183      * Class Libvirt::Domain::InterfaceInfo
2184      */
2185     c_domain_ifinfo = rb_define_class_under(c_domain, "InterfaceInfo",
2186                                             rb_cObject);
2187     rb_define_attr(c_domain_ifinfo, "rx_bytes", 1, 0);
2188     rb_define_attr(c_domain_ifinfo, "rx_packets", 1, 0);
2189     rb_define_attr(c_domain_ifinfo, "rx_errs", 1, 0);
2190     rb_define_attr(c_domain_ifinfo, "rx_drop", 1, 0);
2191     rb_define_attr(c_domain_ifinfo, "tx_bytes", 1, 0);
2192     rb_define_attr(c_domain_ifinfo, "tx_packets", 1, 0);
2193     rb_define_attr(c_domain_ifinfo, "tx_errs", 1, 0);
2194     rb_define_attr(c_domain_ifinfo, "tx_drop", 1, 0);
2195
2196     /*
2197      * Class Libvirt::Domain::SecurityLabel
2198      */
2199     c_domain_security_label = rb_define_class_under(c_domain, "SecurityLabel",
2200                                                     rb_cObject);
2201     rb_define_attr(c_domain_security_label, "label", 1, 0);
2202     rb_define_attr(c_domain_security_label, "enforcing", 1, 0);
2203
2204     /*
2205      * Class Libvirt::Domain::BlockStats
2206      */
2207     c_domain_block_stats = rb_define_class_under(c_domain, "BlockStats",
2208                                                  rb_cObject);
2209     rb_define_attr(c_domain_block_stats, "rd_req", 1, 0);
2210     rb_define_attr(c_domain_block_stats, "rd_bytes", 1, 0);
2211     rb_define_attr(c_domain_block_stats, "wr_req", 1, 0);
2212     rb_define_attr(c_domain_block_stats, "wr_bytes", 1, 0);
2213     rb_define_attr(c_domain_block_stats, "errs", 1, 0);
2214
2215 #if HAVE_TYPE_VIRDOMAINMEMORYSTATPTR
2216     /*
2217      * Class Libvirt::Domain::MemoryStats
2218      */
2219     c_domain_memory_stats = rb_define_class_under(c_domain, "MemoryStats",
2220                                                   rb_cObject);
2221     rb_define_attr(c_domain_memory_stats, "tag", 1, 0);
2222     rb_define_attr(c_domain_memory_stats, "value", 1, 0);
2223
2224     rb_define_const(c_domain_memory_stats, "SWAP_IN",
2225                     INT2NUM(VIR_DOMAIN_MEMORY_STAT_SWAP_IN));
2226     rb_define_const(c_domain_memory_stats, "SWAP_OUT",
2227                     INT2NUM(VIR_DOMAIN_MEMORY_STAT_SWAP_OUT));
2228     rb_define_const(c_domain_memory_stats, "MAJOR_FAULT",
2229                     INT2NUM(VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT));
2230     rb_define_const(c_domain_memory_stats, "MINOR_FAULT",
2231                     INT2NUM(VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT));
2232     rb_define_const(c_domain_memory_stats, "UNUSED",
2233                     INT2NUM(VIR_DOMAIN_MEMORY_STAT_UNUSED));
2234     rb_define_const(c_domain_memory_stats, "AVAILABLE",
2235                     INT2NUM(VIR_DOMAIN_MEMORY_STAT_AVAILABLE));
2236     rb_define_const(c_domain_memory_stats, "NR",
2237                     INT2NUM(VIR_DOMAIN_MEMORY_STAT_NR));
2238 #endif
2239
2240 #if HAVE_TYPE_VIRDOMAINBLOCKINFOPTR
2241     /*
2242      * Class Libvirt::Domain::BlockInfo
2243      */
2244     c_domain_block_info = rb_define_class_under(c_domain, "BlockInfo",
2245                                                 rb_cObject);
2246     rb_define_attr(c_domain_block_info, "capacity", 1, 0);
2247     rb_define_attr(c_domain_block_info, "allocation", 1, 0);
2248     rb_define_attr(c_domain_block_info, "physical", 1, 0);
2249 #endif
2250
2251 #if HAVE_TYPE_VIRDOMAINSNAPSHOTPTR
2252     /*
2253      * Class Libvirt::Domain::Snapshot
2254      */
2255     c_domain_snapshot = rb_define_class_under(c_domain, "Snapshot", rb_cObject);
2256     rb_define_const(c_domain_snapshot, "DELETE_CHILDREN",
2257                     INT2NUM(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN));
2258     rb_define_method(c_domain_snapshot, "xml_desc",
2259                      libvirt_dom_snapshot_xml_desc, -1);
2260     rb_define_method(c_domain_snapshot, "delete",
2261                      libvirt_dom_snapshot_delete, -1);
2262     rb_define_method(c_domain_snapshot, "free", libvirt_dom_snapshot_free, 0);
2263 #endif
2264
2265     /*
2266      * Class Libvirt::Domain::VCPUInfo
2267      */
2268     c_domain_vcpuinfo = rb_define_class_under(c_domain, "VCPUInfo", rb_cObject);
2269     rb_define_const(c_domain_vcpuinfo, "OFFLINE", VIR_VCPU_OFFLINE);
2270     rb_define_const(c_domain_vcpuinfo, "RUNNING", VIR_VCPU_RUNNING);
2271     rb_define_const(c_domain_vcpuinfo, "BLOCKED", VIR_VCPU_BLOCKED);
2272     rb_define_attr(c_domain_vcpuinfo, "number", 1, 0);
2273     rb_define_attr(c_domain_vcpuinfo, "state", 1, 0);
2274     rb_define_attr(c_domain_vcpuinfo, "cpu_time", 1, 0);
2275     rb_define_attr(c_domain_vcpuinfo, "cpu", 1, 0);
2276     rb_define_attr(c_domain_vcpuinfo, "cpumap", 1, 0);
2277
2278 #if HAVE_TYPE_VIRDOMAINJOBINFOPTR
2279     /*
2280      * Class Libvirt::Domain::JobInfo
2281      */
2282     c_domain_job_info = rb_define_class_under(c_domain, "JobInfo", rb_cObject);
2283     rb_define_const(c_domain_job_info, "NONE", INT2NUM(VIR_DOMAIN_JOB_NONE));
2284     rb_define_const(c_domain_job_info, "BOUNDED",
2285                     INT2NUM(VIR_DOMAIN_JOB_BOUNDED));
2286     rb_define_const(c_domain_job_info, "UNBOUNDED",
2287                     INT2NUM(VIR_DOMAIN_JOB_UNBOUNDED));
2288     rb_define_const(c_domain_job_info, "COMPLETED",
2289                     INT2NUM(VIR_DOMAIN_JOB_COMPLETED));
2290     rb_define_const(c_domain_job_info, "FAILED",
2291                     INT2NUM(VIR_DOMAIN_JOB_FAILED));
2292     rb_define_const(c_domain_job_info, "CANCELLED",
2293                     INT2NUM(VIR_DOMAIN_JOB_CANCELLED));
2294     rb_define_attr(c_domain_job_info, "type", 1, 0);
2295     rb_define_attr(c_domain_job_info, "time_elapsed", 1, 0);
2296     rb_define_attr(c_domain_job_info, "time_remaining", 1, 0);
2297     rb_define_attr(c_domain_job_info, "data_total", 1, 0);
2298     rb_define_attr(c_domain_job_info, "data_processed", 1, 0);
2299     rb_define_attr(c_domain_job_info, "data_remaining", 1, 0);
2300     rb_define_attr(c_domain_job_info, "mem_total", 1, 0);
2301     rb_define_attr(c_domain_job_info, "mem_processed", 1, 0);
2302     rb_define_attr(c_domain_job_info, "mem_remaining", 1, 0);
2303     rb_define_attr(c_domain_job_info, "file_total", 1, 0);
2304     rb_define_attr(c_domain_job_info, "file_processed", 1, 0);
2305     rb_define_attr(c_domain_job_info, "file_remaining", 1, 0);
2306
2307     rb_define_method(c_domain, "job_info", libvirt_dom_job_info, 0);
2308     rb_define_method(c_domain, "abort_job", libvirt_dom_abort_job, 0);
2309 #endif
2310
2311 #if HAVE_VIRDOMAINQEMUMONITORCOMMAND
2312     rb_define_method(c_domain, "qemu_monitor_command",
2313                      libvirt_dom_qemu_monitor_command, -1);
2314 #endif
2315 }