diff -Nru ruby-libvirt-0.0.7/autobuild.sh ruby-libvirt-0.4.0/autobuild.sh --- ruby-libvirt-0.0.7/autobuild.sh 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/autobuild.sh 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,28 @@ +#!/bin/sh + +set -e +set -v + +rake clean || : + +rake build +#rake test + +rm -rf pkg +rake package + +if [ -n "$AUTOBUILD_COUNTER" ]; then + EXTRA_RELEASE=".auto$AUTOBUILD_COUNTER" +else + NOW=`date +"%s"` + EXTRA_RELEASE=".$USER$NOW" +fi + +if [ -f /usr/bin/rpmbuild ]; then + ver=`grep '^PKG_VERSION' Rakefile | sed -e "s/PKG_VERSION=//" -e "s/'//g"` + sed -e "s/\@VERSION\@/$ver/" < ruby-libvirt.spec > pkg/ruby-libvirt.spec + rpmbuild --nodeps \ + --define "extra_release $EXTRA_RELEASE" \ + --define "_sourcedir `pwd`/pkg" \ + -ba --clean pkg/ruby-libvirt.spec +fi diff -Nru ruby-libvirt-0.0.7/debian/bzr-builder.manifest ruby-libvirt-0.4.0/debian/bzr-builder.manifest --- ruby-libvirt-0.0.7/debian/bzr-builder.manifest 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/debian/bzr-builder.manifest 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,3 @@ +# bzr-builder format 0.2 deb-version 0.4.0-0ubuntu1~bb+299+30 +lp:ruby-libvirt revid:git-v1:9518e3ee9d3de879ff94d2fee07941edf04c6098 +nest packaging lp:~brightbox/ruby-libvirt/packaging debian revid:neil@aldur.co.uk-20101006065124-ipe9bncdq5ryhhpa diff -Nru ruby-libvirt-0.0.7/debian/changelog ruby-libvirt-0.4.0/debian/changelog --- ruby-libvirt-0.0.7/debian/changelog 2011-07-29 16:24:54.000000000 +0000 +++ ruby-libvirt-0.4.0/debian/changelog 2011-07-29 16:19:09.000000000 +0000 @@ -1,3 +1,9 @@ +ruby-libvirt (0.4.0-0ubuntu1~bb+299+30~oneiric1) unstable; urgency=low + + * Auto build. + + -- Neil Wilson Fri, 29 Jul 2011 16:19:09 +0000 + ruby-libvirt (0.0.7-1) unstable; urgency=low * Initial release (Closes: #501999) diff -Nru ruby-libvirt-0.0.7/debian/compat ruby-libvirt-0.4.0/debian/compat --- ruby-libvirt-0.0.7/debian/compat 2011-07-29 16:24:54.000000000 +0000 +++ ruby-libvirt-0.4.0/debian/compat 2011-07-29 16:19:09.000000000 +0000 @@ -1 +1 @@ -7 +5 diff -Nru ruby-libvirt-0.0.7/debian/control ruby-libvirt-0.4.0/debian/control --- ruby-libvirt-0.0.7/debian/control 2011-07-29 16:24:54.000000000 +0000 +++ ruby-libvirt-0.4.0/debian/control 2011-07-29 16:19:09.000000000 +0000 @@ -1,16 +1,18 @@ Source: ruby-libvirt -Section: libs +Section: ruby Priority: extra -Maintainer: Debian Libvirt Maintainers -Uploaders: Guido Günther -Build-Depends: cdbs, debhelper (>= 7), ruby-pkg-tools, rake, ruby1.8-dev, - rubygems, libvirt-dev, pkg-config -Standards-Version: 3.8.0 -Homepage: http://libvirt.org/ruby/ +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Bryan McLellan +Build-Depends: cdbs, debhelper (>= 5.0.0), ruby-pkg-tools (>= 0.14), ruby1.8-dev, ruby1.9.1-dev, libvirt-dev, pkg-config, quilt, ruby1.8, ruby1.9.1, graphviz +Vcs-Browser: http://bazaar.launchpad.net/~brightbox/ruby-libvirt/packaging/files +Vcs-Bzr: http://code.launchpad.net/~brightbox/ruby-libvirt/packaging +Standards-Version: 3.9.1 +Homepage: http://libvirt.org/ruby Package: libvirt-ruby Architecture: all -Depends: libvirt-ruby1.8 +Depends: libvirt-ruby1.8, ${misc:Depends} +Suggests: libvirt-ruby-doc Description: Ruby bindings for libvirt This library provides Ruby bindings for using libvirt. . @@ -19,13 +21,27 @@ a long term stable C API for different virtualization mechanisms. It currently supports QEMU, KVM, and XEN. . - This is a dependency package which depends on Debian's default Ruby version + This package is a dependency package, which depends on the package + containing actual Ruby libvirt libraries for the default Ruby version (currently 1.8). Package: libvirt-ruby1.8 Architecture: any -Depends: ${shlibs:Depends} -Description: Ruby bindings for libvirt +Depends: ${shlibs:Depends}, ${misc:Depends}, ruby1.8 +Description: Ruby 1.8 bindings for libvirt + This library provides Ruby bindings for using libvirt. + . + Libvirt is a toolkit to interact with the virtualization capabilities + of recent versions of Linux (and other OSes). The library aims at providing + a long term stable C API for different virtualization mechanisms. It currently + supports QEMU, KVM, and XEN. + . + This package contains libvirt libraries for Ruby 1.8. + +Package: libvirt-ruby1.9.1 +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, ruby1.9.1 +Description: Ruby 1.9.1 bindings for libvirt This library provides Ruby bindings for using libvirt. . Libvirt is a toolkit to interact with the virtualization capabilities @@ -33,4 +49,17 @@ a long term stable C API for different virtualization mechanisms. It currently supports QEMU, KVM, and XEN. . - This package is built for Ruby 1.8. + This package contains libvirt libraries for Ruby 1.9.1. + +Package: libvirt-ruby-doc +Section: doc +Architecture: all +Depends: libvirt-ruby, ${misc:Depends} +Description: Documentation for libvirt-ruby + Libvirt is a toolkit to interact with the virtualization capabilities + of recent versions of Linux (and other OSes). The library aims at providing + a long term stable C API for different virtualization mechanisms. It currently + supports QEMU, KVM, and XEN. + . + This package provides generated HTML documentation for libvirt-ruby. + diff -Nru ruby-libvirt-0.0.7/debian/docs ruby-libvirt-0.4.0/debian/docs --- ruby-libvirt-0.0.7/debian/docs 2011-07-29 16:24:54.000000000 +0000 +++ ruby-libvirt-0.4.0/debian/docs 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -NEWS -README -README.rdoc diff -Nru ruby-libvirt-0.0.7/debian/libvirt-ruby1.8.install ruby-libvirt-0.4.0/debian/libvirt-ruby1.8.install --- ruby-libvirt-0.0.7/debian/libvirt-ruby1.8.install 2011-07-29 16:24:54.000000000 +0000 +++ ruby-libvirt-0.4.0/debian/libvirt-ruby1.8.install 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -ext/libvirt/_libvirt.so /usr/lib/ruby/1.8/ -lib/libvirt.rb /usr/lib/ruby/1.8/ diff -Nru ruby-libvirt-0.0.7/debian/libvirt-ruby-doc.doc-base ruby-libvirt-0.4.0/debian/libvirt-ruby-doc.doc-base --- ruby-libvirt-0.0.7/debian/libvirt-ruby-doc.doc-base 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/debian/libvirt-ruby-doc.doc-base 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,9 @@ +Document: libvirt-ruby-doc +Title: libvirt API documentation +Author: David Lutterkort +Abstract: Rdoc-generated API documentation. +Section: Programming/Ruby + +Format: HTML +Index: /usr/share/doc/libvirt-ruby-doc/rdoc/index.html +Files: /usr/share/doc/libvirt-ruby-doc/rdoc/*.html diff -Nru ruby-libvirt-0.0.7/debian/README.debian ruby-libvirt-0.4.0/debian/README.debian --- ruby-libvirt-0.0.7/debian/README.debian 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/debian/README.debian 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,6 @@ +Ruby libvirt library for Debian +----------------------------- + +This package uses debhelper 5 (dh5) for backporting compatibility for cdbs for lenny per lucas. http://pastie.org/733947 + + -- Bryan McLellan Tue, 22 Jun 2010 18:58:11 +0000 diff -Nru ruby-libvirt-0.0.7/debian/rules ruby-libvirt-0.4.0/debian/rules --- ruby-libvirt-0.0.7/debian/rules 2011-07-29 16:24:54.000000000 +0000 +++ ruby-libvirt-0.4.0/debian/rules 2011-07-29 16:19:09.000000000 +0000 @@ -1,20 +1,5 @@ #!/usr/bin/make -f +include /usr/share/cdbs/1/rules/patchsys-quilt.mk include /usr/share/cdbs/1/rules/debhelper.mk -include /usr/share/ruby-pkg-tools/1/class/ruby-common.mk - -cdbs_pkgdir = $(CURDIR)/debian/tmp -cdbs_ruby_libdir_ver = $(cdbs_pkgdir)$(DEB_RUBY_LIBDIR) -cdbs_ruby_archdir_ver = $(cdbs_pkgdir)$(DEB_RUBY_ARCHDIR) -DEB_RUBY_INSTALL_ARGS = DESTDIR=$(cdbs_pkgdir) \ - sitelibdir=$(cdbs_ruby_libdir_ver) \ - sitearchdir=$(cdbs_ruby_archdir_ver) - -DEB_RUBY_SETUP_ARGS = --with-cflags="$(CFLAGS)" --with-ldflags="$(LDFLAGS)" - -common-build-arch:: - rake build - -clean:: - rm -f ext/libvirt/_libvirt.o ext/libvirt/_libvirt.so \ - ext/libvirt/Makefile ext/libvirt/mkmf.log +include /usr/share/ruby-pkg-tools/1/class/ruby-setup-rb.mk diff -Nru ruby-libvirt-0.0.7/debian/source/format ruby-libvirt-0.4.0/debian/source/format --- ruby-libvirt-0.0.7/debian/source/format 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/debian/source/format 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1 @@ +1.0 diff -Nru ruby-libvirt-0.0.7/doc/site/contact.html ruby-libvirt-0.4.0/doc/site/contact.html --- ruby-libvirt-0.0.7/doc/site/contact.html 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/contact.html 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,114 @@ + + + + + + + + + ruby-libvirt: News + + + + +
+ +
+

Bug reporting

+

+ The Red Hat Bugzilla Server + should be used to report bugs and request features against + ruby-libvirt. Before submitting a ticket, check the + existing tickets to see if the bug/feature is already tracked. +

+

Contacting the development team

+

Mailing lists

+

There are two mailing lists:

+
+
libvir-list@redhat.com
+
This list is a place for discussions about the + development of libvirt (including + ruby-libvirt). Topics for discussion include: +
    +
  • New features for libvirt
  • +
  • Bug fixing of libvirt
  • +
  • New hypervisor drivers
  • +
  • Development of language bindings for the libvirt + API
  • +
  • Testing and documentation of libvirt
  • +
+
+
libvirt-users@redhat.com
+
This list is a place for discussions involving libvirt + users (including ruby-libvirt + users). Topics for discussion include: +
    +
  • Usage of libvirt / virsh
  • +
  • Administration of libvirtd
  • +
  • Deployment of libvirt with hypervisors
  • +
  • Development of applications on top of / using the + libvirt API(s)
  • +
  • Any other topics along these lines
  • +
+
+
+

+ Both mailing lists require that you subscribe before posting to the list, + otherwise your posting will be delayed for manual approval by mailman. + You can subscribe at the linked webpages above. +

+

+ Patches with explanations and provided as attachments are appreciated + and should be sent to the development mailing list. + If possible generate the patches by using git format-patch in a GIT clone. +

+

IRC discussion

+

+ Some of the libvirt developers may be found on IRC on the OFTC IRC + network. Use the settings: +

+
    +
  • server: irc.oftc.net
  • +
  • port: 6667 (the usual IRC port)
  • +
  • channel: #virt
  • +
+

+ NB There is no guarantee that someone will be watching or + able to reply promptly, so use the mailing-list if you don't + get an answer on the IRC channel. +

+
+
+
+ +
+ + diff -Nru ruby-libvirt-0.0.7/doc/site/documentation.html ruby-libvirt-0.4.0/doc/site/documentation.html --- ruby-libvirt-0.0.7/doc/site/documentation.html 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/documentation.html 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,89 @@ + + + + + + + + + ruby-libvirt: News + + + + +
+ +
+

Documentation

+

This page contains documentation for application writers + using the ruby-libvirt bindings

+

RDoc API documentation

+

The API documentation for the + ruby-libvirt bindings are automatically generated out of the + source code using RDoc. +

+

Examples

+

Sometimes the easiest way to learn is by looking through + example code. The following examples each demonstrate one or + more of the methods in the library. Note that some of the + examples may not work on your particular setup, depending on + the hypervisor in use, the version of libvirt in use, and the + version of the ruby-libvirt bindings in use. +

    +
  1. Connect to a + hypervisor
  2. +
  3. Connect to a + hypervisor with authentication needed
  4. +
  5. Retrieve various + information about a hypervisor
  6. +
  7. Manipulate a domain
  8. +
  9. React to domain events
  10. +
  11. Query the connection + pointer for information
  12. +
  13. Create and retrieve a + secret
  14. +
  15. Create a + network
  16. +
  17. Create a network + filter
  18. +
  19. List information + about node (host) devices
  20. +
  21. Create an + interface
  22. +
  23. Create a storage pool + and storage volume and retrieve information
  24. +
+

+
+
+
+ +
+ + diff -Nru ruby-libvirt-0.0.7/doc/site/downloads.html ruby-libvirt-0.4.0/doc/site/downloads.html --- ruby-libvirt-0.0.7/doc/site/downloads.html 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/downloads.html 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,105 @@ + + + + + + + + + Ruby bindings for libvirt + + + + +
+ +
+

Downloads

+

The latest released version of the ruby-libvirt bindings can be + downloaded from:

+ +

Distribution Packages

+

If your distribution packages the ruby-libvirt bindings, + this is the easiest way to obtain the code and binaries. The + bindings are packaged for at least: +

+

+

GEM

+

The ruby-libvirt package is also available via + rubygems.org gem. To + install the ruby-libvirt gem, make sure you have rubygems + installed and then run: +

$ gem install ruby-libvirt

+

+

GIT source repository

+

The ruby-libvirt source code that is in development is maintained in a git repository available on + libvirt.org: +

+
+
+git clone git://libvirt.org/ruby-libvirt.git
+	
+

+ It can also be browsed at: +

+
+
+http://libvirt.org/git/?p=ruby-libvirt.git;a=summary
+	
+

Compilation

+

In order to compile ruby-libvirt, you will need to have the + development libraries for both ruby and libvirt installed. + These are typically called something like ruby-devel and + libvirt-devel. Once those are installed, the library can be + compiled using rake:

+

$ tar -zxvf ruby-libvirt-xxx.tar.gz

+

$ cd ruby-libvirt-xxx

+

$ rake build

+

If the libvirt development libraries are header files are + in a non-system location, the ruby-libvirt bindings can be + compiled against them by using:

+

$ rake build -- + --with-libvirt-include=/home/clalance/upstream/libvirt/include + --with-libvirt-lib=/home/clalance/upstream/libvirt/src/.libs

+

(due to the way that rake parses command-line arguments, + the -- immediately after the build argument is required)

+
+
+
+ +
+ + diff -Nru ruby-libvirt-0.0.7/doc/site/examples/conn.rb ruby-libvirt-0.4.0/doc/site/examples/conn.rb --- ruby-libvirt-0.0.7/doc/site/examples/conn.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/examples/conn.rb 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,174 @@ +# this program demonstrates a few of the connection methods; in particular +# it shows getting information about the connection and listing certain +# types of objects returned by libvirt + +require 'libvirt' + +# open up a connection to the qemu driver +#conn = Libvirt::open('qemu:///system') +conn = Libvirt::open('qemu+ssh://root@laforge.usersys.redhat.com/system') + +# query some basic information about the connection +puts "Connection closed?: #{conn.closed?}" +puts "Connection type: #{conn.type}" +puts "Connection hypervisor version: #{conn.version}" +puts "Connection libvirt version: #{conn.libversion}" +puts "Connection hostname: #{conn.hostname}" +puts "Connection canonical URI: #{conn.uri}" +puts "Connection Maximum VCPUs: #{conn.max_vcpus}" + +begin + # check if the connection to the remote hypervisor is encrypted + puts "Connection Encrypted: #{conn.encrypted?}" +rescue NoMethodError + # skip this completely, since this compiled version of ruby-libvirt doesn't + # support this method +rescue Libvirt::Error => e + if e.libvirt_code == 3 + # this compiled version of ruby-libvirt supports the method, but the + # libvirt that we are connecting to does not + else + raise + end +end + +begin + # check if the connection to the remove hypervisor is secure + puts "Connection Secure: #{conn.secure?}" +rescue NoMethodError + # skip this completely, since this compiled version of ruby-libvirt doesn't + # support this method +rescue Libvirt::Error => e + if e.libvirt_code == 3 + # this compiled version of ruby-libvirt supports the method, but the + # libvirt that we are connecting to does not + else + raise + end +end + +# get the number of active (running) domains and list them; the full domain +# list is available through a combination of the list returned from +# conn.list_domains and the list returned from conn.list_defined_domains +puts "Connection number of active domains: #{conn.num_of_domains}" +puts "Connection active domains:" +conn.list_domains.each do |domid| + dom = conn.lookup_domain_by_id(domid) + puts " Domain #{dom.name}" +end + +# get the number of inactive (shut off) domains and list them +puts "Connection number of inactive domains: #{conn.num_of_defined_domains}" +puts "Connection inactive domains:" +conn.list_defined_domains.each do |domname| + puts " Domain #{domname}" +end + +begin + # get the number of active and inactive interfaces and list them + puts "Connection number of active interfaces: #{conn.num_of_interfaces}" + puts "Connection number of inactive interfaces: #{conn.num_of_defined_interfaces}" + puts "Connection interfaces:" + active = conn.list_interfaces + inactive = conn.list_defined_interfaces + (active+inactive).each do |intname| + puts " Interface #{intname}" + end +rescue NoMethodError + # skip this completely, since this compiled version of ruby-libvirt doesn't + # support this method +rescue Libvirt::Error => e + if e.libvirt_code == 3 + # this compiled version of ruby-libvirt supports the method, but the + # libvirt that we are connecting to does not + else + raise + end +end + +# get the number of active and inactive networks and list them +puts "Connection number of active networks: #{conn.num_of_networks}" +puts "Connection number of inactive networks: #{conn.num_of_defined_networks}" +puts "Connection networks:" +active = conn.list_networks +inactive = conn.list_defined_networks +(active+inactive).each do |netname| + puts " Network #{netname}" +end + +begin + # get the number of node devices and list them + puts "Connection number of nodedevices: #{conn.num_of_nodedevices}" + conn.list_nodedevices.each do |nodename| + puts " Node Device #{nodename}" + end +rescue NoMethodError + # skip this completely, since this compiled version of ruby-libvirt doesn't + # support this method +rescue Libvirt::Error => e + if e.libvirt_code == 3 + # this compiled version of ruby-libvirt supports the method, but the + # libvirt that we are connecting to does not + else + raise + end +end + +begin + # get the number of network filters and list them + puts "Connection number of nwfilters: #{conn.num_of_nwfilters}" + conn.list_nwfilters.each do |nwfname| + pust " NWFilter #{nwfname}" + end +rescue NoMethodError + # skip this completely, since this compiled version of ruby-libvirt doesn't + # support this method +rescue Libvirt::Error => e + if e.libvirt_code == 3 + # this compiled version of ruby-libvirt supports the method, but the + # libvirt that we are connecting to does not + else + raise + end +end + +begin + # get the number of secrets and list them + puts "Connection number of secrets: #{conn.num_of_secrets}" + conn.list_secrets.each do |secretuuid| + puts " Secret #{secretuuid}" + end +rescue NoMethodError + # skip this completely, since this compiled version of ruby-libvirt doesn't + # support this method +rescue Libvirt::Error => e + if e.libvirt_code == 3 + # this compiled version of ruby-libvirt supports the method, but the + # libvirt that we are connecting to does not + else + raise + end +end + +begin + # get the number of active and inactive storage pools and list them + puts "Connection number of active storage pools: #{conn.num_of_storage_pools}" + puts "Connection number of inactive storage pools: #{conn.num_of_defined_storage_pools}" + active = conn.list_storage_pools + inactive = conn.list_defined_storage_pools + (active+inactive).each do |poolname| + puts " Pool #{poolname}" + end +rescue NoMethodError + # skip this completely, since this compiled version of ruby-libvirt doesn't + # support this method +rescue Libvirt::Error => e + if e.libvirt_code == 3 + # this compiled version of ruby-libvirt supports the method, but the + # libvirt that we are connecting to does not + else + raise + end +end + +conn.close diff -Nru ruby-libvirt-0.0.7/doc/site/examples/domain_create.rb ruby-libvirt-0.4.0/doc/site/examples/domain_create.rb --- ruby-libvirt-0.0.7/doc/site/examples/domain_create.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/examples/domain_create.rb 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,106 @@ +# this program demonstrates various methods that can be used to create and +# remove libvirt domains + +require 'libvirt' + +GUEST_DISK = '/var/lib/libvirt/images/example.qcow2' +# create the guest disk +`rm -f #{GUEST_DISK} ; qemu-img create -f qcow2 #{GUEST_DISK} 5G` + +UUID = "93a5c045-6457-2c09-e5ff-927cdf34e17b" + +# the XML that describes our guest; note that this is a KVM guest. For +# additional information about the guest XML, please see the libvirt +# documentation +new_dom_xml = < + ruby-libvirt-tester + #{UUID} + 1048576 + 1048576 + 1 + + hvm + + + + + + + + + destroy + restart + restart + + + + + + + + + + + + + + + + + + + + + + + +EOF + +puts "Connecting to libvirt" +conn = Libvirt::open('qemu:///system') + +# create the domain from the XML above. This actually defines the domain +# and starts it at the same time. Domains created this way are transient; +# once they are stopped, libvirt forgets about them. +puts "Creating transient domain ruby-libvirt-tester" +dom = conn.create_domain_xml(new_dom_xml) + +# stop the domain. Because this is a transient domain, libvirt will no longer +# remember this domain after this call +puts "Destroying transient domain ruby-libvirt-tester" +dom.destroy + +# define the domain from the XML above. Note that defining a domain just +# makes libvirt aware of the domain as a persistent entity; it does not start +# or otherwise change the domain +puts "Defining permanent domain ruby-libvirt-tester" +dom = conn.define_domain_xml(new_dom_xml) + +# start the domain +puts "Starting permanent domain ruby-libvirt-tester" +dom.create + +sleep 2 + +begin + # undefine the domain. Oops! This raises an exception since it is not legal + # to undefine a running domain + puts "Trying to undefine running domain ruby-libvirt-tester" + dom.undefine +rescue => e + puts e +end + +# stop the domain. Because this is a permanent domain, libvirt will stop the +# execution of the domain, but will remember the domain for next time +puts "Destroying running domain ruby-libvirt-tester" +dom.destroy + +# undefine the domain; the dom object is no longer valid after this operation +puts "Undefining permanent domain ruby-libvirt-tester" +dom.undefine + +conn.close diff -Nru ruby-libvirt-0.0.7/doc/site/examples/event_test.rb ruby-libvirt-0.4.0/doc/site/examples/event_test.rb --- ruby-libvirt-0.0.7/doc/site/examples/event_test.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/examples/event_test.rb 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,477 @@ +# this program demonstrates the use of the libvirt event APIs. This example +# is very, very complicated because: +# 1) the libvirt event APIs are complicated and +# 2) it tries to simulate a multi-threaded UI program, leading to some weirdness + +require 'libvirt' + +class VirEventLoop + class VirEventLoopHandle + # represents an event handle (usually a file descriptor). When an event + # happens to the handle, we dispatch the event to libvirt via + # Libvirt::event_invoke_handle_callback (feeding it the handleID we returned + # from add_handle, the file descriptor, the new events, and the opaque + # data that libvirt gave us earlier) + attr_accessor :handleID, :fd, :events + attr_reader :opaque + + def initialize(handleID, fd, events, opaque) + puts "PROG: VirEventLoopHandle.initialize" + @handleID = handleID + @fd = fd + @events = events + @opaque = opaque + end + + def dispatch(events) + puts "PROG: handle dispatch called with events #{events}" + Libvirt::event_invoke_handle_callback(@handleID, @fd, events, @opaque) + end + end + + class VirEventLoopTimer + # represents a timer. When a timer expires, we dispatch the event to + # libvirt via Libvirt::event_invoke_timeout_callback (feeding it the timerID + # we returned from add_timer and the opaque data that libvirt gave us + # earlier) + attr_accessor :lastfired, :interval + attr_reader :timerID, :opaque + + def initialize(timerID, interval, opaque) + puts "PROG: VirEventLoopTimer.initialize" + @timerID = timerID + @interval = interval + @opaque = opaque + @lastfired = 0 + end + + def dispatch + puts "PROG: timer dispatch" + Libvirt::event_invoke_timeout_callback(@timerID, @opaque) + end + end + + def initialize + puts "PROG: VirEventLoop.initialize" + @nextHandleID = 1 + @nextTimerID = 1 + @handles = [] + # a bit of oddness having to do with signalling. Since signals are + # unreliable in a multi-threaded program, create a "self-pipe". The read + # end of the pipe will be part of the pollin array, and will be selected + # on during "run_once". The write end of the pipe is available to the + # callbacks registered with libvirt. When libvirt does an add, update, + # or remove of either a handle or a timer, the callbacks will write a single + # byte (via the interrupt method) to the write end of the pipe. This will + # cause the select loop in "run_once" to wakeup and recalculate the + # polling arrays and timers based on the new information. + @rdpipe, @wrpipe = IO.pipe + @pending_wakeup = false + @running_poll = false + @quit = false + + @timers = [] + + @pollin = [] + @pollout = [] + @pollerr = [] + @pollhup = [] + + @pollin << @rdpipe + end + + def next_timeout + # calculate the smallest timeout of all of the registered timeouts + nexttimer = 0 + @timers.each do |t| + puts "PROG: next_timeout, timer #{t.timerID} last #{t.lastfired} interval #{t.interval}" + if t.interval < 0 + next + end + if nexttimer == 0 or (t.lastfired + t.interval) < nexttimer + nexttimer = t.lastfired + t.interval + end + end + + return nexttimer + end + + def print_pollers + # debug function to print the polling arrays + print "PROG: pollin: [" + @pollin.each{|x| print "#{x.fileno}, "} + puts "]" + print "PROG: pollout: [" + @pollin.each{|x| print "#{x.fileno}, "} + puts "]" + print "PROG: pollerr: [" + @pollin.each{|x| print "#{x.fileno}, "} + puts "]" + end + + def run_once + # the main loop of the program. This loop first calculates the smallest + # timeout value (via next_timeout). Based on that, it knows how long to + # sleep for in the select (it sleeps forever if there are no timers + # registered). It then does a select on all of the registered file + # descriptors, waking up if one of them becomes active or we hit the + # timeout. If one of the file descriptors becomes active, we properly + # dispatch the handle event to libvirt. If we woke up because of a timeout + # we dispatch the timeout callback to libvirt. + puts "PROG: VirEventLoop.run_once" + + sleep = -1 + @running_poll = true + nexttimer = next_timeout + puts "PROG: Next timeout at #{nexttimer}" + + if nexttimer > 0 + now = Time.now.to_i * 1000 + if now >= nexttimer + sleep = 0 + else + sleep = (nexttimer - now) / 1000.0 + end + end + + if sleep < 0 + events = IO.select(@pollin, @pollout, @pollerr) + else + events = IO.select(@pollin, @pollout, @pollerr, sleep) + end + + print_pollers + + if not events.nil? + puts "PROG: after poll, 0 #{events[0]}, 1 #{events[1]}, 2 #{events[2]}" + (events[0] + events[1] + events[2]).each do |io| + if io.fileno == @rdpipe.fileno + @pending_wakeup = false + pipe = @rdpipe.read(1) + next + end + + @handles.each do |handle| + if handle.fd == io.fileno + libvirt_events = 0 + if events[0].include?(io) + libvirt_events |= Libvirt::EVENT_HANDLE_READABLE + elsif events[1].include?(io) + libvirt_events |= Libvirt::EVENT_HANDLE_WRITABLE + elsif events[2].include?(io) + libvirt_events |= Libvirt::EVENT_HANDLE_ERROR + end + handle.dispatch(libvirt_events) + end + end + end + end + + now = Time.now.to_i * 1000 + @timers.each do |t| + if t.interval < 0 + next + end + + want = t.lastfired + t.interval + if now >= (want - 20) + t.lastfired = now + t.dispatch + end + end + + @running_poll = false + end + + def run_loop + # run "run_once" forever + puts "PROG: VirEventLoop.run_loop" + while true + run_once + end + end + + def interrupt + # write a byte to the internal pipe to wake up "run_once" for recalculation. + # See initialize for more information about the internal pipe + puts "PROG: VirEventLoop.interrupt" + if @running_poll and not @pending_wakeup + @pending_wakeup = true + @wrpipe.write('c') + end + end + + def register_fd(fd, events) + # given an fd and a set of libvirt events, register the fd in the + # appropriate polling arrays. These arrays are used in "run_once" to + # determine what to poll on + puts "PROG: register fd #{fd} for events #{events}" + if (events & Libvirt::EVENT_HANDLE_READABLE) != 0 + @pollin << IO.new(fd, 'r') + end + if (events & Libvirt::EVENT_HANDLE_WRITABLE) != 0 + @pollout << IO.new(fd, 'w') + end + if (events & Libvirt::EVENT_HANDLE_ERROR) != 0 + @pollerr << IO.new(fd, 'r') + end + if (events & Libvirt::EVENT_HANDLE_HANGUP) != 0 + @pollhup << IO.new(fd, 'r') + end + end + + def unregister_fd(fd) + # remove an fd from all of the poll arrays. run_once will no longer select + # on this fd + @pollin.delete_if {|x| x.fileno == fd} + @pollout.delete_if {|x| x.fileno == fd} + @pollerr.delete_if {|x| x.fileno == fd} + @pollhup.delete_if {|x| x.fileno == fd} + end + + def add_handle(fd, events, opaque) + # add a handle to be tracked by this object. The application is + # expected to maintain a list of internal handle IDs (integers); this + # callback *must* return the current handleID. This handleID is used + # both by libvirt to identify the handle (during an update or remove + # callback), and is also passed by the application into libvirt when + # dispatching an event. The application *must* also store the opaque + # data given by libvirt, and return it back to libvirt later + # (see remove_handle) + puts "PROG: VirEventLoop.add_handle" + handleID = @nextHandleID + 1 + @nextHandleID = handleID + + @handles << VirEventLoop::VirEventLoopHandle.new(handleID, fd, events, + opaque) + + register_fd(fd, events) + + interrupt + + return handleID + end + + def update_handle(handleID, events) + # update a previously registered handle. Libvirt tells us the handleID + # (which was returned to libvirt via add_handle), and the new events. It + # is our responsibility to find the correct handle and update the events + # it cares about + puts "PROG: VirEventLoop.update_handle handleID #{handleID}, events #{events}" + @handles.each do |handle| + if handle.handleID == handleID + puts "PROG: updating handle #{handleID} with fd #{handle.fd}" + handle.events = events + unregister_fd(handle.fd) + register_fd(handle.fd, events) + interrupt + end + end + end + + def remove_handle(handleID) + # remove a previously registered handle. Libvirt tells us the handleID + # (which was returned to libvirt via add_handle), and it is our + # responsibility to "forget" the handle. We must return the opaque data + # that libvirt handed us in "add_handle", otherwise we will leak memory + puts "PROG: VirEventLoop.remove_handle" + handles = [] + @handles.each do |h| + if h.handleID == handleID + unregister_fd(h.fd) + puts "PROG: Removed handle #{handleID} fd #{h.fd}" + opaque = h.opaque + else + handles << h + end + end + @handles = handles + interrupt + + return opaque + end + + def add_timer(interval, opaque) + # add a timeout to be tracked by this object. The application is + # expected to maintain a list of internal timer IDs (integers); this + # callback *must* return the current timerID. This timerID is used + # both by libvirt to identify the timeout (during an update or remove + # callback), and is also passed by the application into libvirt when + # dispatching an event. The application *must* also store the opaque + # data given by libvirt, and return it back to libvirt later + # (see remove_timer) + puts "PROG: VirEventLoop.add_timer" + timerID = @nextTimerID + 1 + @nextTimerID = timerID + + @timers << VirEventLoop::VirEventLoopTimer.new(timerID, interval, opaque) + + interrupt + + return timerID + end + + def update_timer(timerID, interval) + # update a previously registered timer. Libvirt tells us the timerID + # (which was returned to libvirt via add_timer), and the new interval. It + # is our responsibility to find the correct timer and update the timers + # it cares about + puts "PROG: VirEventLoop.update_timer ID #{timerID} interval #{interval}" + @timers.each do |timer| + if timer.timerID == timerID + puts "PROG: updating timer" + timer.interval = interval + interrupt + end + end + end + + def remove_timer(timerID) + # remove a previously registered timeout. Libvirt tells us the timerID + # (which was returned to libvirt via add_timer), and it is our + # responsibility to "forget" the timer. We must return the opaque data + # that libvirt handed us in "add_timer", otherwise we will leak memory + puts "PROG: VirEventLoop.remove_timer" + timers = [] + @timers.each do |t| + if t.timerId == timerID + opaque = t.opaque + else + timers << t + puts "PROG: Remove timer #{timerID}" + end + end + @timers = timers + interrupt + return opaque + end +end + +# allocate a global VirEventLoop object. This needs to be global because it +# will be referenced in each of the event impl callbacks +$eventLoop = VirEventLoop.new + +$virEventAddHandleImpl = lambda {|fd, events, opaque| + puts "PROG: virEventAddHandleImpl" + return $eventLoop.add_handle(fd, events, opaque) +} + +def virEventUpdateHandleImpl(watch, event) + puts "PROG: virEventUpdateHandleImpl" + return $eventLoop.update_handle(watch, event) +end + +def virEventRemoveHandleImpl(handleID) + puts "PROG: virEventRemoveHandleImpl" + return $eventLoop.remove_handle(handleID) +end + +def virEventAddTimerImpl(interval, opaque) + puts "PROG: virEventAddTimerImpl" + return $eventLoop.add_timer(interval, opaque) +end + +def virEventUpdateTimerImpl(timer, timeout) + puts "PROG: virEventUpdateTimerImpl" + return $eventLoop.update_timer(timer, timeout) +end + +def virEventRemoveTimerImpl(timerID) + puts "PROG: virEventRemoveTimerImpl" + return $eventLoop.remove_timer(timerID) +end + +def virEventLoopStart + puts "PROG: event loop start" + + # register the handle implementations with libvirt. Each callback is + # either a Symbol to a function or a Proc. + Libvirt::event_register_impl($virEventAddHandleImpl, + :virEventUpdateHandleImpl, + :virEventRemoveHandleImpl, + :virEventAddTimerImpl, + :virEventUpdateTimerImpl, + :virEventRemoveTimerImpl) + + Thread.new { + # continuously run the loop looking to dispatch callbacks + $eventLoop.run_loop() + } +end + +# the domain callbacks that will be registered below. Note that each type of +# domain callback (lifecycle, reboot, etc) need to accept a certain number +# of parameters; see the ruby-libvirt API documentation for a full list +dom_event_callback1 = lambda {|conn, dom, event, detail, opaque| + puts "PROG: dom_event_callback1: conn #{conn}, dom #{dom}, event #{event}, detail #{detail}, opaque #{opaque}" +} + +def dom_event_callback_lifecycle(conn, dom, event, detail, opaque) + puts "PROG: dom_event_callback_lifecycle: conn #{conn}, dom #{dom}, event #{event}, detail #{detail}, opaque #{opaque}" +end + +def dom_event_callback_reboot(conn, dom, opaque) + puts "PROG: dom_event_callback_reboot: conn #{conn}, dom #{dom}, opaque #{opaque}" +end + +# start the main program + +# make sure to abort the program if any of the threads throw an exception +Thread.abort_on_exception = true + +# if run with no arguments, connect to the qemu libvirt driver. Otherwise try +# to connect to the given libvirt URI. +if ARGV.length == 0 + uri = "qemu:///system" +else + uri = ARGV[0] +end + +puts "Using uri: " + uri + +# start up the event loop that will dispatch incoming events +virEventLoopStart + +# connect to libvirt +conn = Libvirt::open(uri) + +puts "PROG: Registering callbacks 1 and 2" +# register a callback for domain events using the old-style +# "domain_event_register". The first parameter is the callback (either a +# Symbol to a function or a Proc), the second (optional) parameter is user +# supplied data to pass to the callback (this can be any valid ruby object). +# Note that domain_event_register is limited to "domain" events, and is +# deprecated in favor of domain_event_register_any +conn.domain_event_register(dom_event_callback1, ["hello", "there"]) + +# register a callback for domain events using the new-style +# "domain_event_register_any". The first required parameter is which type of +# events to register for, and the second required parameters is the callback +# (either a Symbol to a function or a Proc). The third (optional) parameter +# is which domain to get events for; if nil, events for all domains will be +# sent. The fourth (optional) parameter is user supplied data to pass to the +# callback (this can be any valid ruby object). The return value from +# domain_event_register_any *must* be stored by the application; this is the +# handle used to "unregister" this callback later. +cb2 = conn.domain_event_register_any(Libvirt::Connect::DOMAIN_EVENT_ID_LIFECYCLE, + :dom_event_callback_lifecycle, nil, + "sweet") + +cb3 = conn.domain_event_register_any(Libvirt::Connect::DOMAIN_EVENT_ID_REBOOT, + :dom_event_callback_reboot) + +sleep 30 + +# after 30 seconds, unregister a couple of the callbacks to show how + +puts "PROG: Deregistering callback 1" +conn.domain_event_deregister + +puts "PROG: Deregistering reboot callback" +# deregister the reboot callback by passing the handle stored by +# domain_event_register_any +conn.domain_event_deregister_any(cb3) + +while true + sleep 1 +end diff -Nru ruby-libvirt-0.0.7/doc/site/examples/interface.rb ruby-libvirt-0.4.0/doc/site/examples/interface.rb --- ruby-libvirt-0.0.7/doc/site/examples/interface.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/examples/interface.rb 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,42 @@ +# this example program demonstrates how to create a new interface using +# the libvirt APIs + +require 'libvirt' + +# the new interface XML. This example XML creates a bridge named +# "ruby-libvirt-tester", intended to start on boot, with a bridge delay of 0. +interface_xml = < + + + + +EOF + +# open the connection to libvirt +conn = Libvirt::open('qemu:///system') + +# list the number of interfaces defined +puts "Number of interfaces: #{conn.num_of_interfaces}" + +# define (but do not start) the new interface +intf = conn.define_interface_xml(interface_xml) + +# print some information about this new interface +puts "Interface:" +puts " Name: #{intf.name}" +puts " MAC: #{intf.mac}" + +# start the new interface +intf.create + +# now there should be one more interface than there was before +puts "Number of interfaces: #{conn.num_of_interfaces}" + +# shutdown the interface +intf.destroy + +# undefine the interface +intf.undefine + +conn.close diff -Nru ruby-libvirt-0.0.7/doc/site/examples/network.rb ruby-libvirt-0.4.0/doc/site/examples/network.rb --- ruby-libvirt-0.0.7/doc/site/examples/network.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/examples/network.rb 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,53 @@ +# this example program shows how to create a new network, get information +# about it, start it, and stop it +require 'libvirt' + +# the XML describing the network. This network will be a NAT'ed network with +# host IP of 192.168.134.1, and can hand out DHCP addresses to guests between +# 192.168.134.2 and 192.168.134.254. http://libvirt.org/formatnetwork.html has +# much more information about the format of the XML. +network_xml = < + ruby-libvirt-tester + 04068860-d9a2-47c5-bc9d-9e047ae901da + + + + + + + + +EOF + +# connect to libvirt +conn = Libvirt::open('qemu:///system') + +# print out the number of networks before we do anything +puts "Number of networks: #{conn.num_of_networks}" + +# define a new network based on the XML +net = conn.define_network_xml(network_xml) + +# print out some information about our new network +puts "Network:" +puts " Name: #{net.name}" +puts " UUID: #{net.uuid}" +puts " Bridge Name: #{net.bridge_name}" +puts " Autostart?: #{net.autostart?}" + +# start the new network +net.create + +# print out the number of networks, which should be one more than earlier +puts "Number of networks: #{conn.num_of_networks}" + +sleep 2 + +# shutdown the new network +net.destroy + +# undefine the new network +net.undefine + +conn.close diff -Nru ruby-libvirt-0.0.7/doc/site/examples/nodedevices.rb ruby-libvirt-0.4.0/doc/site/examples/nodedevices.rb --- ruby-libvirt-0.0.7/doc/site/examples/nodedevices.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/examples/nodedevices.rb 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,25 @@ +# this example program goes through all of the node (aka host) devices on +# the current machine and prints some information about each device + +require 'libvirt' + +# connect to libvirt +conn = Libvirt::open('qemu:///system') + +# find out how many devices there are on this system +puts "Number of node devices: #{conn.num_of_nodedevices}" + +# look at each device. list_nodedevices returns an array of names, so it is +# necessary to look each device up by name to get a nodedevice object +conn.list_nodedevices.each do |device| + nd = conn.lookup_nodedevice_by_name(device) + + # print some information about the device + puts "Nodedevice:" + puts " Name: #{nd.name}" + puts " Parent: #{nd.parent}" + puts " Number of Capabilities: #{nd.num_of_caps}" + puts " Capabilities: #{nd.list_caps.inspect}" +end + +conn.close diff -Nru ruby-libvirt-0.0.7/doc/site/examples/node_info.rb ruby-libvirt-0.4.0/doc/site/examples/node_info.rb --- ruby-libvirt-0.0.7/doc/site/examples/node_info.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/examples/node_info.rb 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,69 @@ +# this program demonstrates getting various information about the hypervisor. +# not all of these calls work on all hypervisors. +require 'libvirt' + +conn = Libvirt::open('qemu:///system') + +# check if the connection is closed +puts "Hypervisor connection closed?: #{conn.closed?}" + +# retrieve basic information about the hypervisor. See the libvirt +# documentation for more information about what each of these fields mean. +nodeinfo = conn.node_get_info +puts "Hypervisor Nodeinfo:" +puts " Model: #{nodeinfo.model}" +puts " Memory: #{nodeinfo.memory}" +puts " CPUs: #{nodeinfo.cpus}" +puts " MHz: #{nodeinfo.mhz}" +puts " (NUMA) Nodes: #{nodeinfo.nodes}" +puts " Sockets: #{nodeinfo.sockets}" +puts " Cores: #{nodeinfo.cores}" +puts " Threads: #{nodeinfo.threads}" + +# print the amount of free memory in every NUMA node on the hypervisor +begin + cellsmem = conn.node_cells_free_memory + puts "Hypervisor NUMA node free memory:" + cellsmem.each_with_index do |cell,index| + puts " Node #{index}: #{cell}" + end +rescue + # this call may not be supported; if so, just ignore +end + +# print the type of the connection. This will be "QEMU" for qemu, "XEN" for +# xen, etc. +puts "Hypervisor Type: #{conn.type}" +# print the hypervisor version +puts "Hypervisor Version: #{conn.version}" +# print the libvirt version on the hypervisor +puts "Hypervisor Libvirt version: #{conn.libversion}" +# print the hypervisor hostname (deprecated) +puts "Hypervisor Hostname: #{conn.hostname}" +# print the URI in use on this connection. Note that this may be different +# from the one passed into Libvirt::open, since libvirt may decide to +# canonicalize the URI +puts "Hypervisor URI: #{conn.uri}" +# print the amount of free memory on the hypervisor +begin + puts "Hypervisor Free Memory: #{conn.node_free_memory}" +rescue + # this call may not be supported; if so, just ignore +end + +# print the security model in use on the hypervisor +secmodel = conn.node_get_security_model +puts "Hypervisor Security Model:" +puts " Model: #{secmodel.model}" +puts " DOI: #{secmodel.doi}" + +# print whether the connection to the hypervisor is encrypted +puts "Hypervisor connection encrypted?: #{conn.encrypted?}" +# print whether the connection to the hypervisor is secure +puts "Hypervisor connection secure?: #{conn.secure?}" +# print the capabilities XML for the hypervisor. A detailed explanation of +# the XML format can be found in the libvirt documentation. +puts "Hypervisor capabilities XML:" +puts conn.capabilities + +conn.close diff -Nru ruby-libvirt-0.0.7/doc/site/examples/nwfilter.rb ruby-libvirt-0.4.0/doc/site/examples/nwfilter.rb --- ruby-libvirt-0.0.7/doc/site/examples/nwfilter.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/examples/nwfilter.rb 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,42 @@ +# this example program shows how to define and undefine a new network filter. + +require 'libvirt' + +# the XML to describe a silly network filter. This network filter allows any +# ipv4 tcp traffic to host 255.255.255.255 from port 63000 to port 62000 to +# go out. It also allows any ipv4 tcp traffic from port 63000 to port 62000 to +# come in. There is a lot more documentation on the nwfilter XML format at +# http://libvirt.org/formatnwfilter.html +nwfilter_xml = < + bd339530-134c-6d07-441a-17fb90dad807 + + + + + + + +EOF + +# open the connection to libvirt +conn = Libvirt::open('qemu:///system') + +# print out how many filters are currently defined +puts "Number of nwfilters: #{conn.num_of_nwfilters}" + +# define our new filter +nwf = conn.define_nwfilter_xml(nwfilter_xml) + +# now there should be one more filter than before +puts "Number of nwfilters: #{conn.num_of_nwfilters}" + +# print out some information about our filter +puts "NWFilter:" +puts " Name: #{nwf.name}" +puts " UUID: #{nwf.uuid}" + +# remove the filter +nwf.undefine + +conn.close diff -Nru ruby-libvirt-0.0.7/doc/site/examples/open_auth.rb ruby-libvirt-0.4.0/doc/site/examples/open_auth.rb --- ruby-libvirt-0.0.7/doc/site/examples/open_auth.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/examples/open_auth.rb 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,42 @@ +# this program demonstrates opening a libvirt connection with the bindings +# using Libvirt::open_auth. Libvirt::open_auth has the ability to request +# additional information from the user (via a callback mechanism) to complete +# the connection. + +require 'libvirt' + +# open a connection to libvirt using Libvirt::open_auth. The first argument +# is the libvirt URI to connect to. The second argument is the list of +# credentials the block is willing to accept. The third argument is any +# user-specific data that should be passed into the block. The block itself +# receives a single parameter which is a hash containing the fields necessary +# to retrieve information from the user. The block will be called once for +# each credential that needs to be resolved to connect. The last expression of +# the block must contain the result necessary to resolve this credential. +conn = Libvirt::open_auth("qemu+tcp://localhost/system", + [Libvirt::CRED_AUTHNAME, Libvirt::CRED_PASSPHRASE], + "my data") do |cred| + puts "Credential information:" + puts " Type: #{cred["type"]}" + puts " Prompt: #{cred["prompt"]}" + puts " Challenge: #{cred["challenge"]}" + puts " Default result: #{cred["defresult"]}" + puts " User data: #{cred["userdata"]}\n\n" + + print "#{cred['prompt']}: " + + if cred["type"] == Libvirt::CRED_AUTHNAME + res = gets + # strip off the \n + res = res[0..-2] + elsif cred["type"] == Libvirt::CRED_PASSPHRASE + res = gets + res = res[0..-2] + else + raise "Unsupported credential #{cred['type']}" + end + + res +end + +conn.close diff -Nru ruby-libvirt-0.0.7/doc/site/examples/open.rb ruby-libvirt-0.4.0/doc/site/examples/open.rb --- ruby-libvirt-0.0.7/doc/site/examples/open.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/examples/open.rb 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,18 @@ +# this simple program demonstrates opening a libvirt connection with the +# bindings and then closing it out + +require 'libvirt' + +# the open method is a module method. It can take 0 or 1 parameters; with 0 +# parameters, libvirt attempts to auto-connect to a hypervisor for you (not +# recommended). If a parameter is passed, it must be a valid libvirt URI +conn = Libvirt::open("qemu:///system") + +# check to see if the connection is closed (it shouldn't be) +puts "After open, connection closed?: #{conn.closed?}" + +# close the connection +conn.close + +# after close, the closed? should return true +puts "After close, connection closed?: #{conn.closed?}" diff -Nru ruby-libvirt-0.0.7/doc/site/examples/screenshot.rb ruby-libvirt-0.4.0/doc/site/examples/screenshot.rb --- ruby-libvirt-0.0.7/doc/site/examples/screenshot.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/examples/screenshot.rb 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,46 @@ +# this simple program demonstrates taking a screenshot of a libvirt domain + +require 'libvirt' + +# make sure we get the required command-line arguments +if ARGV.length != 2 + puts "Usage: screenshot.rb " + exit 1 +end + +domname = ARGV[0] +filename = ARGV[1] + +# open the connection to libvirt +conn = Libvirt::open("qemu:///system") + +# lookup the domain object +dom = conn.lookup_domain_by_name(domname) + +# create a new stream +stream = conn.stream + +# start the screenshot +mimetype = dom.screenshot(stream, 0) + +# open up the output file +f = File.open(filename, 'w') + +# receive all of the data from the stream (the screenshot). stream.recvall +# takes one parameter, which is the opaque userdata to pass into the block. +# It then yields a bunch of data, and that userdata to the block as many times +# as necessary. The block is expected to return the number of bytes consumed +# during this iteration. +stream.recvall(f) do |data, opaque| + opaque.write(data) + data.length +end + +# close out the output file +f.close + +# close out the stream +stream.finish + +# close the connection +conn.close diff -Nru ruby-libvirt-0.0.7/doc/site/examples/secret.rb ruby-libvirt-0.4.0/doc/site/examples/secret.rb --- ruby-libvirt-0.0.7/doc/site/examples/secret.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/examples/secret.rb 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,46 @@ +# this example shows how to use the secret API to store and then retrieve +# binary data from a secret + +require 'libvirt' + +# generate some example secret XML. http://libvirt.org/formatsecret.html has +# more details about the XML format, but essentially: +# ephemeral='no' means to keep this secret on-disk +# private='no' means make this secret available to callers +# usage type of 'volume' is the only one currently defined +new_secret_xml = < + test secret + bd339530-134c-6d07-4410-17fb90dad805 + + /var/lib/libvirt/images/mail.img + + +EOF + +# open the connection to libvirt +conn = Libvirt::open('qemu:///system') + +# start out by showing how many current secrets there are +puts "Number of secrets to start: #{conn.num_of_secrets}" + +# define our new secret +secret = conn.define_secret_xml(new_secret_xml) + +# there now should be one more secret than before +puts "Number of secrets now: #{conn.num_of_secrets}" + +# set the value of the secret to a binary string. The secret can be any +# kind of string +secret.set_value("\x3a\x3c\x3b\x5a") + +# fetch the secret that we just stored, and print it out byte-by-byte +val = secret.get_value +val.unpack("c#{val.length}").each do |byte| + puts "byte is #{byte}" +end + +# undefine the secret +secret.undefine + +conn.close diff -Nru ruby-libvirt-0.0.7/doc/site/examples/storage.rb ruby-libvirt-0.4.0/doc/site/examples/storage.rb --- ruby-libvirt-0.0.7/doc/site/examples/storage.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/examples/storage.rb 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,110 @@ +# this program demonstrates the use of the libvirt storage APIs. In particular +# it demonstrates directory pool creation, volume creation, and teardown. +# libvirt supports many other kinds of storage pools, including iSCSI, NFS, +# etc. See http://libvirt.org/formatstorage.html for more details + +require 'libvirt' + +# a directory storage pool. This will be a pool with the name +# 'ruby-libvirt-tester' with the pool itself in /tmp/ruby-libvirt-tester +storage_pool_xml = < + ruby-libvirt-tester + 33a5c045-645a-2c00-e56b-927cdf34e17a + + /tmp/ruby-libvirt-tester + + +EOF + +# a storage volume. This will have name test.img, with capacity of 1GB +# and allocation of 0. The difference between allocation and capacity is the +# maximum allowed for a volume (capacity) versus how much is currently +# allocated (allocation). If allocation < capacity, then this is a +# thinly-provisioned volume (think of a sparse file) +storage_vol_xml = < + test.img + 0 + 1 + + /tmp/ruby-libvirt-tester/test.img + + +EOF + +# open up the connection to libvirt +conn = Libvirt::open('qemu:///system') + +# print out how many storage pools are currently active +puts "Number of storage pools: #{conn.num_of_storage_pools}" + +# create our new storage pool +pool = conn.define_storage_pool_xml(storage_pool_xml) + +# build the storage pool. The operation that this performs is pool-specific; +# in the case of a directory pool, it does the equivalent of mkdir to create +# the directory +pool.build + +# start up the pool +pool.create + +# print out how many active storage pools are now there; this should be one +# more than before +puts "Number of storage pools: #{conn.num_of_storage_pools}" + +# print out some information about the pool. Note that allocation can be +# much less than capacity; see the discussion for the storage volume XML for +# more details +puts "Storage Pool:" +puts " Name: #{pool.name}" +puts " UUID: #{pool.uuid}" +puts " Autostart?: #{pool.autostart?}" +poolinfo = pool.info +puts " Info:" +puts " State: #{poolinfo.state}" +puts " Capacity: #{poolinfo.capacity / 1024}kb" +puts " Allocation: #{poolinfo.allocation / 1024}kb" +puts " Available: #{poolinfo.available / 1024}kb" +puts " Number of volumes: #{pool.num_of_volumes}" + +# create a new volume in the storage pool. What happens on volume creation +# is pool-type specific. In the case of a directory pool, this creates the +# file +vol = pool.create_volume_xml(storage_vol_xml) + +# refresh the pool, which rescans the pool for any changes to the pool including +# new or deleted volumes. While this isn't strictly necessary +# (create_volume_xml already does this), it is a good habit to get into when +# making changes to a pool +pool.refresh + +# print out how many volumes are in our pool; there should now be 1 +puts " Number of volumes: #{pool.num_of_volumes}" + +# print out some information about the volume. Again, see the discussion +# for the storage volume XML to understand the differences between allocation +# and capacity +puts "Storage Volume:" +puts " Name: #{vol.name}" +puts " Key: #{vol.key}" +puts " Path: #{vol.path}" +puts " Pool: #{vol.pool.name}" +volinfo = vol.info +puts " Info:" +puts " Type: #{volinfo.type}" +puts " Capacity: #{volinfo.capacity / 1024}kb" +puts " Allocation: #{volinfo.allocation / 1024}kb" + +# delete the volume. What happens here is pool-type specific; for a directory +# pool, the file is erased +vol.delete + +# destroy the pool +pool.destroy + +# undefine the pool +pool.undefine + +conn.close diff -Nru ruby-libvirt-0.0.7/doc/site/index.html ruby-libvirt-0.4.0/doc/site/index.html --- ruby-libvirt-0.0.7/doc/site/index.html 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/index.html 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,77 @@ + + + + + + + + + Ruby bindings for libvirt + + + + +
+ +
+

What is ruby-libvirt?

+ +

ruby-libvirt provides Ruby bindings for + libvirt. With them you can use libvirt directly from your Ruby + programs:

+
+require 'libvirt'
+
+conn = Libvirt::open("qemu:///system")
+puts conn.capabilities
+
+conn.create_domain_linux(File.read("domain.xml"))
+
+dom = conn.lookup_domain_by_name("mydomain")
+dom.suspend
+dom.resume
+puts dom.xml_desc
+        
+

Please see + the documentation page for + more complete examples. +

Developers

+

The sources are available from git. To clone, run

+
git clone git://libvirt.org/ruby-libvirt.git
+ +

Please use the libvirt mailing list for questions, + comments and patches. +

+
+
+
+ +
+ + diff -Nru ruby-libvirt-0.0.7/doc/site/news.html ruby-libvirt-0.4.0/doc/site/news.html --- ruby-libvirt-0.0.7/doc/site/news.html 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/news.html 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,181 @@ + + + + + + + + + ruby-libvirt: News + + + + +
+ +
+

News

+
    +
  • July 27, 2011 - Release 0.4.0
  • +
  • December 12, 2010 - Release 0.3.0
  • +
  • November 10, 2010 - Gem for version 0.2.0 pushed to + rubygems.org
  • +
  • July 1, 2010 - Release 0.2.0
  • +
  • November 18, 2008 - Release 0.1.0
  • +
  • April 15, 2008 - Release 0.0.7
  • +
  • April 2, 2008 - Release 0.0.6
  • +
  • April 2, 2008 - Release 0.0.5
  • +
  • April 1, 2008 - Release 0.0.4
  • +
  • December 6, 2007 - Release 0.0.2
  • +
  • November 19, 2007 - Release 0.0.1
  • +
+

Releases

+

0.4.0: July 27, 2011

+
    +
  • Updated Domain class, implementing dom.memory_parameters=, + dom.memory_parameters, dom.updated?, dom.migrate2, + dom.migrate_to_uri2, dom.migrate_set_max_speed, + dom.qemu_monitor_command, dom.blkio_parameters, + dom.blkio_parameters=, dom.state, dom.open_console, dom.screenshot, + and dom.inject_nmi
  • +
  • Implementation of the Stream class, which covers the + libvirt virStream APIs
  • +
  • Add the ability to build against non-system libvirt libraries
  • +
  • Updated Error object, which now includes the libvirt + code, component and level of the error, as well as all of + the error constants from libvirt.h
  • +
  • Updated Connect class, implementing conn.sys_info, conn.stream, + conn.interface_change_begin, conn.interface_change_commit, and + conn.interface_change_rollback
  • +
  • Updated StorageVol class, implementing vol.download and vol.upload
  • +
  • Various bugfixes
  • +
+

0.3.0: Dec 12, 2010

+
    +
  • Implementation of Libvirt::open_auth, Libvirt::event_register_impl
  • +
  • Updated Connect class, implementing conn.compare_cpu, + conn.baseline_cpu, conn.domain_event_register_any, + conn.domain_event_deregister_any, + conn.domain_event_register, conn.domain_event_deregister, + and conn.create_domain_xml.
  • +
  • Updated Domain class, implementing dom.get_vcpus, + dom.update_device, dom.scheduler_type, + dom.scheduler_parameters, dom.scheduler_parameters=, + dom.num_vcpus, dom.vcpus_flags=, and dom.qemu_monitor_command.
  • +
  • Updated Interface class, implementing interface.free
  • +
  • Many potential memory leaks have been fixed.
  • +
  • Many bugfixes.
  • +
  • Documentation update of many methods, including all of + the lookup methods that were missing before.
  • +
+

0.2.0: July 1 2010

+
    +
  • Updated Storage class, implementing pool.active?, + pool.persistent?, pool.vol_create_xml_from.
  • +
  • Updated Connect class, implementing conn.node_free_memory, + conn.node_cells_free_memory, conn.node_get_security_model, + conn.encrypted?, conn.libversion, and conn.secure?
  • +
  • Updated Network class, implementing network.active? and + network.persistent?
  • +
  • Update Domain class, implementing conn.domain_xml_from_native, + conn.domain_xml_to_native, dom.migrate_to_uri, + dom.migrate_set_max_downtime, dom.managed_save, + dom.has_managed_save?, dom.managed_save_remove, + dom.security_label, dom.block_stats, dom.memory_stats, + dom.blockinfo, dom.block_peek, dom.memory_peek, + dom.active?, dom.persistent?, dom.snapshot_create_xml, + dom.num_of_snapshots, dom.list_snapshots, + dom.lookup_snapshot_by_name, dom.has_current_snapshot?, + dom.revert_to_snapshot, dom.current_snapshot, snapshot.xml_desc, + snapshot.delete, dom.job_info, and dom.abort_job.
  • +
  • Implementation of the NodeDevice class.
  • +
  • Implementation of the Secret class.
  • +
  • Implementation of the NWFilter class.
  • +
  • Implementation of the Interface class.
  • +
  • Conversion of the development tree to git.
  • +
  • New maintainer (Chris Lalancette). David Lutterkort has + agreed to transfer maintainership since he is not actively + involved in their development anymore.
  • +
+

0.1.0: November 18 2008

+
    +
  • Short-circuit calls to list functions for empty lists. + As an optimizaton (and workaround for a bug in 0.4.3), do not call + virConnectList* functions if the coresponding virConnectNumOf* call + returned 0. Return an empty list instead.
  • +
  • Add the MIGRATE_LIVE (enum virDomainMigrateFlags) + flag.
  • +
  • Fix dom_migrate: (1) allow passing nil for dname and uri, + (2) make all but the first two parameters optional.
  • +
  • Add the binding for virConnectFindStoragePoolSources.
  • +
+

0.0.7: April 15 2008

+
    +
  • Add the binding for virDomainMigrate.
  • +
+

0.0.6: April 2 2008

+
    +
  • Fix a test failure from 0.0.5
  • +
+

0.0.5: April 2 2008

+
    +
  • Add free methods to the various objects. + It is sometimes necessary to free a virXXX object + explicitly instead of waiting for the garbage collector to + come and do it. This adds explicit free methods that call + the underlying virXXXFree functions to do that.
  • +
  • More finegrained exceptions. + Errors from libvirt are now translated in not just one but + four different kinds of exceptions, and the error message + from libvirt's virError structure is returned.
  • +
+

0.0.4: April 1 2008

+
    +
  • Bindings for storage API in libvirt 0.4.1
  • +
  • Bindings for virDomainSetMemory and virDomainSetVcpus
  • +
  • Binding for virDomainPinVcpu
  • +
+

0.0.2: December 6 2007

+
    +
  • Add the virNodeGetInfo call
  • +
  • Convert Ruby API from StudlyCaps to _ separation. + Using one_two_three instead of oneTwoThree is the standard + Ruby way.
  • +
+

0.0.1: November 19 2007

+
    +
  • Initial release
  • +
+
+
+
+ +
+ + diff -Nru ruby-libvirt-0.0.7/doc/site/relatedlinks.html ruby-libvirt-0.4.0/doc/site/relatedlinks.html --- ruby-libvirt-0.0.7/doc/site/relatedlinks.html 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/relatedlinks.html 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,57 @@ + + + + + + + + + ruby-libvirt: News + + + + +
+ +
+

Related links

+

This page contains some links of interest having to do + with ruby and libvirt

+ +
+
+
+ +
+ + diff -Nru ruby-libvirt-0.0.7/doc/site/ruby-libvirt.css ruby-libvirt-0.4.0/doc/site/ruby-libvirt.css --- ruby-libvirt-0.0.7/doc/site/ruby-libvirt.css 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/doc/site/ruby-libvirt.css 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,8 @@ +#rubyHeaderLogo { + position: absolute; + top: 0px; + left: 0px; + height: 104px; + width: 400px; + background: url(ruby-libvirt-header-logo.png); +} Binary files /tmp/tmB2bEsRG5/ruby-libvirt-0.0.7/doc/site/ruby-libvirt-header-logo.png and /tmp/o77JeplPh5/ruby-libvirt-0.4.0/doc/site/ruby-libvirt-header-logo.png differ diff -Nru ruby-libvirt-0.0.7/ext/libvirt/common.c ruby-libvirt-0.4.0/ext/libvirt/common.c --- ruby-libvirt-0.0.7/ext/libvirt/common.c 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/common.c 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,203 @@ +/* + * common.c: Common utilities for the ruby libvirt bindings + * + * Copyright (C) 2007,2010 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif +#include +#include +#include +#include +#include "common.h" + +struct rb_exc_new2_arg { + VALUE error; + char *msg; +}; + +static VALUE rb_exc_new2_wrap(VALUE arg) { + struct rb_exc_new2_arg *e = (struct rb_exc_new2_arg *)arg; + + return rb_exc_new2(e->error, e->msg); +} + +VALUE rb_ary_new2_wrap(VALUE arg) { + return rb_ary_new2(*((int *)arg)); +} + +VALUE rb_ary_push_wrap(VALUE arg) { + struct rb_ary_push_arg *e = (struct rb_ary_push_arg *)arg; + + return rb_ary_push(e->arr, e->value); +} + +VALUE rb_str_new2_wrap(VALUE arg) { + char **str = (char **)arg; + + return rb_str_new2(*str); +} + +VALUE rb_ary_entry_wrap(VALUE arg) { + struct rb_ary_entry_arg *e = (struct rb_ary_entry_arg *)arg; + + return rb_ary_entry(e->arr, e->elem); +} + +VALUE rb_ary_new_wrap(VALUE arg) { + return rb_ary_new(); +} + +VALUE rb_str_new_wrap(VALUE arg) { + struct rb_str_new_arg *e = (struct rb_str_new_arg *)arg; + + return rb_str_new(e->val, e->size); +} + +VALUE rb_iv_set_wrap(VALUE arg) { + struct rb_iv_set_arg *e = (struct rb_iv_set_arg *)arg; + + return rb_iv_set(e->klass, e->member, e->value); +} + +VALUE rb_class_new_instance_wrap(VALUE arg) { + struct rb_class_new_instance_arg *e = (struct rb_class_new_instance_arg *)arg; + + return rb_class_new_instance(e->argc, e->argv, e->klass); +} + +VALUE rb_string_value_cstr_wrap(VALUE arg) { + return (VALUE)rb_string_value_cstr((VALUE *)arg); +} + +/* Error handling */ +VALUE create_error(VALUE error, const char* method, virConnectPtr conn) { + VALUE ruby_errinfo; + virErrorPtr err; + char *msg; + int rc; + struct rb_exc_new2_arg arg; + int exception = 0; + + if (conn == NULL) + err = virGetLastError(); + else + err = virConnGetLastError(conn); + + if (err != NULL && err->message != NULL) + rc = asprintf(&msg, "Call to %s failed: %s", method, err->message); + else + rc = asprintf(&msg, "Call to %s failed", method); + + if (rc < 0) { + /* there's not a whole lot we can do here; try to raise an + * out-of-memory message */ + rb_memerror(); + } + + arg.error = error; + arg.msg = msg; + ruby_errinfo = rb_protect(rb_exc_new2_wrap, (VALUE)&arg, &exception); + free(msg); + if (exception) + rb_jump_tag(exception); + + rb_iv_set(ruby_errinfo, "@libvirt_function_name", rb_str_new2(method)); + + if (err != NULL) { + rb_iv_set(ruby_errinfo, "@libvirt_code", INT2NUM(err->code)); + rb_iv_set(ruby_errinfo, "@libvirt_component", INT2NUM(err->domain)); + rb_iv_set(ruby_errinfo, "@libvirt_level", INT2NUM(err->level)); + if (err->message != NULL) + rb_iv_set(ruby_errinfo, "@libvirt_message", + rb_str_new2(err->message)); + } + + return ruby_errinfo; +}; + +char *get_string_or_nil(VALUE arg) +{ + if (TYPE(arg) == T_NIL) + return NULL; + else if (TYPE(arg) == T_STRING) + return StringValueCStr(arg); + else + rb_raise(rb_eTypeError, "wrong argument type (expected String or nil)"); return NULL; +} + +VALUE generic_new(VALUE klass, void *ptr, VALUE conn, + RUBY_DATA_FUNC free_func) { + VALUE result; + result = Data_Wrap_Struct(klass, NULL, free_func, ptr); + rb_iv_set(result, "@connection", conn); + return result; +} + +int is_symbol_or_proc(VALUE handle) { + return ((strcmp(rb_obj_classname(handle), "Symbol") == 0) || + (strcmp(rb_obj_classname(handle), "Proc") == 0)); +} + +/* this is an odd function, because it has massive side-effects. The first + * tip that something is weird here should be the triple-starred list. + * The intended usage of this function is after a list has been collected + * from a libvirt list function, and now we want to make an array out of it. + * However, it is possible that the act of creating an array causes an + * exception, which would lead to a memory leak of the values we got from + * libvirt. Therefore, this function not only wraps all of the relevant + * calls with rb_protect, it also frees every individual entry in list + * along with list itself. + */ +VALUE gen_list(int num, char ***list) { + VALUE result; + int exception = 0; + int i, j; + struct rb_ary_push_arg arg; + + result = rb_protect(rb_ary_new2_wrap, (VALUE)&num, &exception); + if (exception) { + for (i = 0; i < num; i++) + free((*list)[i]); + xfree(*list); + rb_jump_tag(exception); + } + for (i = 0; i < num; i++) { + arg.arr = result; + arg.value = rb_protect(rb_str_new2_wrap, (VALUE)&((*list)[i]), + &exception); + if (exception) { + for (j = i; j < num; j++) + xfree((*list)[j]); + xfree(*list); + rb_jump_tag(exception); + } + rb_protect(rb_ary_push_wrap, (VALUE)&arg, &exception); + if (exception) { + for (j = i; j < num; j++) + xfree((*list)[j]); + xfree(*list); + rb_jump_tag(exception); + } + xfree((*list)[i]); + } + xfree(*list); + + return result; +} diff -Nru ruby-libvirt-0.0.7/ext/libvirt/common.h ruby-libvirt-0.4.0/ext/libvirt/common.h --- ruby-libvirt-0.0.7/ext/libvirt/common.h 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/common.h 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,211 @@ +#ifndef COMMON_H +#define COMMON_H + +/* Macros to ease some of the boilerplate */ +VALUE generic_new(VALUE klass, void *ptr, VALUE conn, + RUBY_DATA_FUNC free_func); + +#define generic_get(kind, v) \ + do { \ + vir##kind##Ptr ptr; \ + Data_Get_Struct(v, vir##kind, ptr); \ + if (!ptr) \ + rb_raise(rb_eArgError, #kind " has been freed"); \ + return ptr; \ + } while (0); + +#define generic_free(kind, p) \ + do { \ + int r; \ + r = vir##kind##Free((vir##kind##Ptr) p); \ + if (r < 0) \ + rb_raise(rb_eSystemCallError, # kind " free failed"); \ + } while(0); + +VALUE create_error(VALUE error, const char* method, virConnectPtr conn); + +/* + * Code generating macros. + * + * We only generate function bodies, not the whole function + * declaration. + */ + +/* Generate a call to a function FUNC which returns a string. The Ruby + * function will return the string on success and throw an exception on + * error. The string returned by FUNC is freed if dealloc is true. + */ +#define gen_call_string(func, conn, dealloc, args...) \ + do { \ + const char *str; \ + VALUE result; \ + \ + str = func(args); \ + _E(str == NULL, create_error(e_Error, # func, conn)); \ + \ + result = rb_str_new2(str); \ + if (dealloc) \ + xfree((void *) str); \ + return result; \ + } while(0) + +/* Generate a call to vir##KIND##Free and return Qnil. Set the the embedded + * vir##KIND##Ptr to NULL. If that pointer is already NULL, do nothing. + */ +#define gen_call_free(kind, s) \ + do { \ + vir##kind##Ptr ptr; \ + Data_Get_Struct(s, vir##kind, ptr); \ + if (ptr != NULL) { \ + int r = vir##kind##Free(ptr); \ + _E(r < 0, create_error(e_Error, "vir" #kind "Free", conn(s))); \ + DATA_PTR(s) = NULL; \ + } \ + return Qnil; \ + } while (0) + +/* Generate a call to a function FUNC which returns an int error, where -1 + * indicates error and 0 success. The Ruby function will return Qnil on + * success and throw an exception on error. + */ +#define gen_call_void(func, conn, args...) \ + do { \ + int _r_##func; \ + _r_##func = func(args); \ + _E(_r_##func < 0, create_error(e_Error, #func, conn)); \ + return Qnil; \ + } while(0) + +/* + * Generate a call to a virConnectNumOf... function. C is the Ruby VALUE + * holding the connection and OBJS is a token indicating what objects to + * get the number of, e.g. 'Domains' + */ +#define gen_conn_num_of(c, objs) \ + do { \ + int result; \ + virConnectPtr conn = connect_get(c); \ + \ + result = virConnectNumOf##objs(conn); \ + _E(result < 0, create_error(e_RetrieveError, "virConnectNumOf" # objs, conn)); \ + \ + return INT2NUM(result); \ + } while(0) + + +VALUE gen_list(int num, char ***list); + +/* + * Generate a call to a virConnectList... function. S is the Ruby VALUE + * holding the connection and OBJS is a token indicating what objects to + * get the number of, e.g. 'Domains' The list function must return an array + * of strings, which is returned as a Ruby array + */ +#define gen_conn_list_names(s, objs) \ + do { \ + int r, num; \ + char **names; \ + virConnectPtr conn = connect_get(s); \ + \ + num = virConnectNumOf##objs(conn); \ + _E(num < 0, create_error(e_RetrieveError, "virConnectNumOf" # objs, conn)); \ + if (num == 0) { \ + /* if num is 0, don't call virConnectList* function */ \ + return rb_ary_new2(num); \ + } \ + names = ALLOC_N(char *, num); \ + r = virConnectList##objs(conn, names, num); \ + if (r < 0) { \ + xfree(names); \ + _E(r < 0, create_error(e_RetrieveError, "virConnectList" # objs, conn)); \ + } \ + \ + return gen_list(num, &names); \ + } while(0) + +/* Generate a call to a function FUNC which returns an int; -1 indicates + * error, 0 indicates Qfalse, and 1 indicates Qtrue. + */ +#define gen_call_truefalse(func, conn, args...) \ + do { \ + int _r_##func; \ + _r_##func = func(args); \ + _E(_r_##func < 0, create_error(e_Error, #func, conn)); \ + return _r_##func ? Qtrue : Qfalse; \ + } while(0) + +/* Generate a call to a function FUNC which returns an int error, where -1 + * indicates error and >= 0 success. The Ruby function will return the integer + * success and throw an exception on error. + */ +#define gen_call_int(func, conn, args...) \ + do { \ + int _r_##func; \ + _r_##func = func(args); \ + _E(_r_##func < 0, create_error(e_RetrieveError, #func, conn)); \ + return INT2NUM(_r_##func); \ + } while(0) + +/* Error handling */ +#define _E(cond, excep) \ + do { if (cond) rb_exc_raise(excep); } while(0) + +int is_symbol_or_proc(VALUE handle); + +extern VALUE e_RetrieveError; +extern VALUE e_Error; +extern VALUE e_DefinitionError; +extern VALUE e_NoSupportError; + +extern VALUE m_libvirt; + +char *get_string_or_nil(VALUE arg); + +struct rb_ary_entry_arg { + VALUE arr; + int elem; +}; +VALUE rb_ary_entry_wrap(VALUE arg); +VALUE rb_ary_new_wrap(VALUE arg); +struct rb_ary_push_arg { + VALUE arr; + VALUE value; +}; +VALUE rb_ary_push_wrap(VALUE arg); +VALUE rb_ary_new2_wrap(VALUE arg); + +VALUE rb_str_new2_wrap(VALUE arg); +struct rb_str_new_arg { + char *val; + size_t size; +}; +VALUE rb_str_new_wrap(VALUE arg); +VALUE rb_string_value_cstr_wrap(VALUE arg); + +struct rb_iv_set_arg { + VALUE klass; + char *member; + VALUE value; +}; +VALUE rb_iv_set_wrap(VALUE arg); + +struct rb_class_new_instance_arg { + int argc; + VALUE *argv; + VALUE klass; +}; +VALUE rb_class_new_instance_wrap(VALUE arg); + +#ifndef RARRAY_LEN +#define RARRAY_LEN(ar) (RARRAY(ar)->len) +#endif + +#ifndef RSTRING_PTR +#define RSTRING_PTR(str) (RSTRING(str)->ptr) +#endif + +#ifndef RSTRING_LEN +#define RSTRING_LEN(str) (RSTRING(str)->len) +#endif + +#endif diff -Nru ruby-libvirt-0.0.7/ext/libvirt/connect.c ruby-libvirt-0.4.0/ext/libvirt/connect.c --- ruby-libvirt-0.0.7/ext/libvirt/connect.c 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/connect.c 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,2265 @@ +/* + * connect.c: virConnect methods + * + * Copyright (C) 2007,2010 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "extconf.h" +#include "common.h" +#include "domain.h" +#include "network.h" + +static VALUE c_connect; +static VALUE c_node_security_model; +static VALUE c_node_info; + +static void connect_close(void *p) { + int r; + + if (!p) + return; + r = virConnectClose((virConnectPtr) p); + _E(r < 0, create_error(rb_eSystemCallError, "virConnectClose", p)); +} + +VALUE connect_new(virConnectPtr p) { + return Data_Wrap_Struct(c_connect, NULL, connect_close, p); +} + +virConnectPtr connect_get(VALUE s) { + generic_get(Connect, s); +} + +VALUE conn_attr(VALUE s) { + if (rb_obj_is_instance_of(s, c_connect) != Qtrue) { + s = rb_iv_get(s, "@connection"); + } + if (rb_obj_is_instance_of(s, c_connect) != Qtrue) { + rb_raise(rb_eArgError, "Expected Connection object"); + } + return s; +} + +virConnectPtr conn(VALUE s) { + virConnectPtr conn; + + s = conn_attr(s); + Data_Get_Struct(s, virConnect, conn); + if (!conn) + rb_raise(rb_eArgError, "Connection has been closed"); + return conn; +} + +/* + * call-seq: + * conn.close -> nil + * + * Call +virConnectClose+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectClose] + * to close the connection. + */ +static VALUE libvirt_conn_close(VALUE s) { + virConnectPtr conn; + Data_Get_Struct(s, virConnect, conn); + if (conn) { + connect_close(conn); + DATA_PTR(s) = NULL; + } + return Qnil; +} + +/* + * call-seq: + * conn.closed? -> [True|False] + * + * Return +true+ if the connection is closed, +false+ if it is open. + */ +static VALUE libvirt_conn_closed_p(VALUE s) { + virConnectPtr conn; + + Data_Get_Struct(s, virConnect, conn); + return (conn==NULL) ? Qtrue : Qfalse; +} + +/* + * call-seq: + * conn.type -> string + * + * Call +virConnectGetType+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectGetType] + * to retrieve the type of hypervisor for this connection. + */ +static VALUE libvirt_conn_type(VALUE s) { + gen_call_string(virConnectGetType, conn(s), 0, connect_get(s)); +} + +/* + * call-seq: + * conn.version -> fixnum + * + * Call +virConnectGetVersion+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectGetVersion] + * to retrieve the version of the hypervisor for this connection. + */ +static VALUE libvirt_conn_version(VALUE s) { + int r; + unsigned long v; + virConnectPtr conn = connect_get(s); + + r = virConnectGetVersion(conn, &v); + _E(r < 0, create_error(e_RetrieveError, "virConnectGetVersion", conn)); + + return ULONG2NUM(v); +} + +#if HAVE_VIRCONNECTGETLIBVERSION +/* + * call-seq: + * conn.libversion -> fixnum + * + * Call +virConnectGetLibVersion+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectGetLibVersion] + * to retrieve the version of the libvirt library for this connection. + */ +static VALUE libvirt_conn_libversion(VALUE s) { + int r; + unsigned long v; + virConnectPtr conn = connect_get(s); + + r = virConnectGetLibVersion(conn, &v); + _E(r < 0, create_error(e_RetrieveError, "virConnectGetLibVersion", conn)); + + return ULONG2NUM(v); +} +#endif + +/* + * call-seq: + * conn.hostname -> string + * + * Call +virConnectGetHostname+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectGetHostname] + * to retrieve the hostname of the hypervisor for this connection. + */ +static VALUE libvirt_conn_hostname(VALUE s) { + gen_call_string(virConnectGetHostname, conn(s), 1, connect_get(s)); +} + +/* + * call-seq: + * conn.uri -> string + * + * Call +virConnectGetURI+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectGetURI] + * to retrieve the canonical URI for this connection. + */ +static VALUE libvirt_conn_uri(VALUE s) { + gen_call_string(virConnectGetURI, conn(s), 1, connect_get(s)); +} + +/* + * call-seq: + * conn.max_vcpus(type=nil) -> fixnum + * + * Call +virConnectGetMaxVcpus+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectGetMaxVcpus] + * to retrieve the maximum number of virtual cpus supported by the hypervisor + * for this connection. + */ +static VALUE libvirt_conn_max_vcpus(int argc, VALUE *argv, VALUE s) { + VALUE type; + + rb_scan_args(argc, argv, "01", &type); + + gen_call_int(virConnectGetMaxVcpus, conn(s), connect_get(s), + get_string_or_nil(type)); +} + +/* + * call-seq: + * conn.node_get_info -> Libvirt::Connect::Nodeinfo + * + * Call +virNodeGetInfo+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeGetInfo] + * to retrieve information about the node for this connection. + */ +static VALUE libvirt_conn_node_get_info(VALUE s) { + int r; + virConnectPtr conn = connect_get(s); + virNodeInfo nodeinfo; + VALUE result; + + r = virNodeGetInfo(conn, &nodeinfo); + _E(r < 0, create_error(e_RetrieveError, "virNodeGetInfo", conn)); + + result = rb_class_new_instance(0, NULL, c_node_info); + rb_iv_set(result, "@model", rb_str_new2(nodeinfo.model)); + rb_iv_set(result, "@memory", ULONG2NUM(nodeinfo.memory)); + rb_iv_set(result, "@cpus", UINT2NUM(nodeinfo.cpus)); + rb_iv_set(result, "@mhz", UINT2NUM(nodeinfo.mhz)); + rb_iv_set(result, "@nodes", UINT2NUM(nodeinfo.nodes)); + rb_iv_set(result, "@sockets", UINT2NUM(nodeinfo.sockets)); + rb_iv_set(result, "@cores", UINT2NUM(nodeinfo.cores)); + rb_iv_set(result, "@threads", UINT2NUM(nodeinfo.threads)); + + return result; +} + +/* + * call-seq: + * conn.node_free_memory -> fixnum + * + * Call +virNodeGetFreeMemory+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeGetFreeMemory] + * to retrieve the amount of free memory available on the host for this + * connection. + */ +static VALUE libvirt_conn_node_free_memory(VALUE s) { + virConnectPtr conn = connect_get(s); + unsigned long long freemem; + + freemem = virNodeGetFreeMemory(conn); + + _E(freemem == 0, create_error(e_RetrieveError, "virNodeGetFreeMemory", + conn)); + + return ULL2NUM(freemem); +} + +/* + * call-seq: + * conn.node_cells_free_memory(startCell=0, maxCells=#nodeCells) -> list + * + * Call +virNodeGetCellsFreeMemory+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeGetCellsFreeMemory] + * to retrieve the amount of free memory in each NUMA cell on the host for + * this connection. + */ +static VALUE libvirt_conn_node_cells_free_memory(int argc, VALUE *argv, + VALUE s) { + int r; + virConnectPtr conn = connect_get(s); + VALUE cells; + VALUE start, max; + unsigned long long *freeMems; + virNodeInfo nodeinfo; + int i; + unsigned int startCell, maxCells; + + rb_scan_args(argc, argv, "02", &start, &max); + + if (NIL_P(start)) + startCell = 0; + else + startCell = NUM2UINT(start); + + if (NIL_P(max)) { + r = virNodeGetInfo(conn, &nodeinfo); + _E(r < 0, create_error(e_RetrieveError, "virNodeGetInfo", conn)); + maxCells = nodeinfo.nodes; + } + else + maxCells = NUM2UINT(max); + + freeMems = ALLOC_N(unsigned long long, maxCells); + + r = virNodeGetCellsFreeMemory(conn, freeMems, startCell, maxCells); + if (r < 0) { + xfree(freeMems); + rb_exc_raise(create_error(e_RetrieveError, "virNodeGetCellsFreeMemory", + conn)); + } + + cells = rb_ary_new2(r); + for (i = 0; i < r; i++) + rb_ary_push(cells, ULL2NUM(freeMems[i])); + xfree(freeMems); + + return cells; +} + +#if HAVE_VIRNODEGETSECURITYMODEL +/* + * call-seq: + * conn.node_get_security_model -> Libvirt::Connect::NodeSecurityModel + * + * Call +virNodeGetSecurityModel+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeGetSecurityModel] + * to retrieve the security model in use on the host for this connection. + */ +static VALUE libvirt_conn_node_get_security_model(VALUE s) { + virSecurityModel secmodel; + virConnectPtr conn = connect_get(s); + int r; + VALUE result; + + r = virNodeGetSecurityModel(conn, &secmodel); + _E(r < 0, create_error(e_RetrieveError, "virNodeGetSecurityModel", conn)); + + result = rb_class_new_instance(0, NULL, c_node_security_model); + rb_iv_set(result, "@model", rb_str_new2(secmodel.model)); + rb_iv_set(result, "@doi", rb_str_new2(secmodel.doi)); + + return result; +} +#endif + +#if HAVE_VIRCONNECTISENCRYPTED +/* + * call-seq: + * conn.encrypted? -> [True|False] + * + * Call +virConnectIsEncrypted+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectIsEncrypted] + * to determine if the connection is encrypted. + */ +static VALUE libvirt_conn_encrypted_p(VALUE s) { + gen_call_truefalse(virConnectIsEncrypted, conn(s), connect_get(s)); +} +#endif + +#if HAVE_VIRCONNECTISSECURE +/* + * call-seq: + * conn.secure? -> [True|False] + * + * Call +virConnectIsSecure+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectIsSecure] + * to determine if the connection is secure. + */ +static VALUE libvirt_conn_secure_p(VALUE s) { + gen_call_truefalse(virConnectIsSecure, conn(s), connect_get(s)); +} +#endif + +/* + * call-seq: + * conn.capabilities -> string + * + * Call +virConnectGetCapabilities+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectGetCapabilities] + * to retrieve the capabilities XML for this connection. + */ +static VALUE libvirt_conn_capabilities(VALUE s) { + gen_call_string(virConnectGetCapabilities, conn(s), 1, connect_get(s)); +} + +#if HAVE_VIRCONNECTCOMPARECPU +/* + * call-seq: + * conn.compare_cpu(xml, flags=0) -> compareflag + * + * Call +virConnectCompareCPU+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectCompareCPU] + * to compare the host CPU with the XML contained in xml. Returns one of + * Libvirt::CPU_COMPARE_ERROR, Libvirt::CPU_COMPARE_INCOMPATIBLE, + * Libvirt::CPU_COMPARE_IDENTICAL, or Libvirt::CPU_COMPARE_SUPERSET. + */ +static VALUE libvirt_conn_compare_cpu(int argc, VALUE *argv, VALUE s) { + VALUE xml, flags; + + rb_scan_args(argc, argv, "11", &xml, &flags); + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_int(virConnectCompareCPU, conn(s), connect_get(s), + StringValueCStr(xml), NUM2UINT(flags)); +} +#endif + + +#if HAVE_VIRCONNECTBASELINECPU +/* + * call-seq: + * conn.baseline_cpu([xml, xml2, ...], flags=0) -> XML + * + * Call +virConnectBaselineCPU+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectBaselineCPU] + * to compare the most feature-rich CPU which is compatible with all + * given host CPUs. + */ +static VALUE libvirt_conn_baseline_cpu(int argc, VALUE *argv, VALUE s) { + VALUE xmlcpus, flags_val; + virConnectPtr conn = connect_get(s); + char *r; + VALUE retval; + unsigned int ncpus, flags; + VALUE entry; + const char **xmllist; + int i; + int exception = 0; + struct rb_ary_entry_arg arg; + + rb_scan_args(argc, argv, "11", &xmlcpus, &flags_val); + /* + * We check flags up-front here so that we get a TypeError early on if + * flags is bogus. + */ + if (NIL_P(flags_val)) + flags = 0; + else + flags = NUM2UINT(flags_val); + + Check_Type(xmlcpus, T_ARRAY); + + if (RARRAY_LEN(xmlcpus) < 1) + rb_raise(rb_eArgError, "wrong number of cpu arguments (%d for 1 or more)", + RARRAY_LEN(xmlcpus)); + + ncpus = RARRAY_LEN(xmlcpus); + xmllist = ALLOC_N(const char *, ncpus); + + for (i = 0; i < ncpus; i++) { + arg.arr = xmlcpus; + arg.elem = i; + entry = rb_protect(rb_ary_entry_wrap, (VALUE)&arg, &exception); + if (exception) { + xfree(xmllist); + rb_jump_tag(exception); + } + + xmllist[i] = (char *)rb_protect(rb_string_value_cstr_wrap, + (VALUE)&entry, &exception); + if (exception) { + xfree(xmllist); + rb_jump_tag(exception); + } + } + + r = virConnectBaselineCPU(conn, xmllist, ncpus, flags); + xfree(xmllist); + _E(r == NULL, create_error(e_RetrieveError, "virConnectBaselineCPU", conn)); + + retval = rb_protect(rb_str_new2_wrap, (VALUE)&r, &exception); + if (exception) { + free(r); + rb_jump_tag(exception); + } + + free(r); + + return retval; +} +#endif + +#if HAVE_VIRCONNECTDOMAINEVENTREGISTERANY || HAVE_VIRCONNECTDOMAINEVENTREGISTER +static int domain_event_lifecycle_callback(virConnectPtr conn, + virDomainPtr dom, int event, + int detail, void *opaque) { + VALUE passthrough = (VALUE)opaque; + VALUE cb; + VALUE cb_opaque; + VALUE newc; + + if (TYPE(passthrough) != T_ARRAY) + rb_raise(rb_eTypeError, + "wrong domain event lifecycle callback argument type (expected Array)"); + + if (RARRAY_LEN(passthrough) != 2) + rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", + RARRAY_LEN(passthrough)); + + cb = rb_ary_entry(passthrough, 0); + cb_opaque = rb_ary_entry(passthrough, 1); + + newc = connect_new(conn); + if (strcmp(rb_obj_classname(cb), "Symbol") == 0) + rb_funcall(rb_class_of(cb), rb_to_id(cb), 5, newc, + domain_new(dom, newc), INT2NUM(event), INT2NUM(detail), + cb_opaque); + else if (strcmp(rb_obj_classname(cb), "Proc") == 0) + rb_funcall(cb, rb_intern("call"), 5, newc, domain_new(dom, newc), + INT2NUM(event), INT2NUM(detail), cb_opaque); + else + rb_raise(rb_eTypeError, + "wrong domain event lifecycle callback (expected Symbol or Proc)"); + + return 0; +} +#endif + +#if HAVE_VIRCONNECTDOMAINEVENTREGISTERANY +static int domain_event_reboot_callback(virConnectPtr conn, virDomainPtr dom, + void *opaque) { + VALUE passthrough = (VALUE)opaque; + VALUE cb; + VALUE cb_opaque; + VALUE newc; + + if (TYPE(passthrough) != T_ARRAY) + rb_raise(rb_eTypeError, + "wrong domain event reboot callback argument type (expected Array)"); + + if (RARRAY_LEN(passthrough) != 2) + rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", + RARRAY_LEN(passthrough)); + + cb = rb_ary_entry(passthrough, 0); + cb_opaque = rb_ary_entry(passthrough, 1); + + newc = connect_new(conn); + if (strcmp(rb_obj_classname(cb), "Symbol") == 0) + rb_funcall(rb_class_of(cb), rb_to_id(cb), 3, newc, + domain_new(dom, newc), cb_opaque); + else if (strcmp(rb_obj_classname(cb), "Proc") == 0) + rb_funcall(cb, rb_intern("call"), 3, newc, domain_new(dom, newc), + cb_opaque); + else + rb_raise(rb_eTypeError, + "wrong domain event reboot callback (expected Symbol or Proc)"); + + return 0; +} + +static int domain_event_rtc_callback(virConnectPtr conn, virDomainPtr dom, + long long utc_offset, void *opaque) { + VALUE passthrough = (VALUE)opaque; + VALUE cb; + VALUE cb_opaque; + VALUE newc; + + if (TYPE(passthrough) != T_ARRAY) + rb_raise(rb_eTypeError, + "wrong domain event rtc callback argument type (expected Array)"); + + if (RARRAY_LEN(passthrough) != 2) + rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", + RARRAY_LEN(passthrough)); + + cb = rb_ary_entry(passthrough, 0); + cb_opaque = rb_ary_entry(passthrough, 1); + + newc = connect_new(conn); + if (strcmp(rb_obj_classname(cb), "Symbol") == 0) + rb_funcall(rb_class_of(cb), rb_to_id(cb), 4, newc, + domain_new(dom, newc), LL2NUM(utc_offset), cb_opaque); + else if (strcmp(rb_obj_classname(cb), "Proc") == 0) + rb_funcall(cb, rb_intern("call"), 4, newc, domain_new(dom, newc), + LL2NUM(utc_offset), cb_opaque); + else + rb_raise(rb_eTypeError, + "wrong domain event rtc callback (expected Symbol or Proc)"); + + return 0; +} + +static int domain_event_watchdog_callback(virConnectPtr conn, virDomainPtr dom, + int action, void *opaque) { + VALUE passthrough = (VALUE)opaque; + VALUE cb; + VALUE cb_opaque; + VALUE newc; + + if (TYPE(passthrough) != T_ARRAY) + rb_raise(rb_eTypeError, + "wrong domain event watchdog callback argument type (expected Array)"); + + if (RARRAY_LEN(passthrough) != 2) + rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", + RARRAY_LEN(passthrough)); + + cb = rb_ary_entry(passthrough, 0); + cb_opaque = rb_ary_entry(passthrough, 1); + + newc = connect_new(conn); + if (strcmp(rb_obj_classname(cb), "Symbol") == 0) + rb_funcall(rb_class_of(cb), rb_to_id(cb), 4, newc, + domain_new(dom, newc), INT2NUM(action), cb_opaque); + else if (strcmp(rb_obj_classname(cb), "Proc") == 0) + rb_funcall(cb, rb_intern("call"), 4, newc, domain_new(dom, newc), + INT2NUM(action), cb_opaque); + else + rb_raise(rb_eTypeError, + "wrong domain event watchdog callback (expected Symbol or Proc)"); + + return 0; +} + +static int domain_event_io_error_callback(virConnectPtr conn, virDomainPtr dom, + const char *src_path, + const char *dev_alias, + int action, + void *opaque) { + VALUE passthrough = (VALUE)opaque; + VALUE cb; + VALUE cb_opaque; + VALUE newc; + + if (TYPE(passthrough) != T_ARRAY) + rb_raise(rb_eTypeError, + "wrong domain event IO error callback argument type (expected Array)"); + + if (RARRAY_LEN(passthrough) != 2) + rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", + RARRAY_LEN(passthrough)); + + cb = rb_ary_entry(passthrough, 0); + cb_opaque = rb_ary_entry(passthrough, 1); + + newc = connect_new(conn); + if (strcmp(rb_obj_classname(cb), "Symbol") == 0) + rb_funcall(rb_class_of(cb), rb_to_id(cb), 6, newc, + domain_new(dom, newc), rb_str_new2(src_path), + rb_str_new2(dev_alias), INT2NUM(action), cb_opaque); + else if (strcmp(rb_obj_classname(cb), "Proc") == 0) + rb_funcall(cb, rb_intern("call"), 6, newc, domain_new(dom, newc), + rb_str_new2(src_path), rb_str_new2(dev_alias), + INT2NUM(action), cb_opaque); + else + rb_raise(rb_eTypeError, + "wrong domain event IO error callback (expected Symbol or Proc)"); + + return 0; +} + +static int domain_event_io_error_reason_callback(virConnectPtr conn, + virDomainPtr dom, + const char *src_path, + const char *dev_alias, + int action, + const char *reason, + void *opaque) { + VALUE passthrough = (VALUE)opaque; + VALUE cb; + VALUE cb_opaque; + VALUE newc; + + if (TYPE(passthrough) != T_ARRAY) + rb_raise(rb_eTypeError, + "wrong domain event IO error reason callback argument type (expected Array)"); + + if (RARRAY_LEN(passthrough) != 2) + rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", + RARRAY_LEN(passthrough)); + + cb = rb_ary_entry(passthrough, 0); + cb_opaque = rb_ary_entry(passthrough, 1); + + newc = connect_new(conn); + if (strcmp(rb_obj_classname(cb), "Symbol") == 0) + rb_funcall(rb_class_of(cb), rb_to_id(cb), 7, newc, + domain_new(dom, newc), rb_str_new2(src_path), + rb_str_new2(dev_alias), INT2NUM(action), + rb_str_new2(reason), cb_opaque); + else if (strcmp(rb_obj_classname(cb), "Proc") == 0) + rb_funcall(cb, rb_intern("call"), 7, newc, domain_new(dom, newc), + rb_str_new2(src_path), rb_str_new2(dev_alias), + INT2NUM(action), rb_str_new2(reason), cb_opaque); + else + rb_raise(rb_eTypeError, + "wrong domain event IO error reason callback (expected Symbol or Proc)"); + + return 0; +} + +static int domain_event_graphics_callback(virConnectPtr conn, virDomainPtr dom, + int phase, + virDomainEventGraphicsAddressPtr local, + virDomainEventGraphicsAddressPtr remote, + const char *authScheme, + virDomainEventGraphicsSubjectPtr subject, + void *opaque) { + VALUE passthrough = (VALUE)opaque; + VALUE cb; + VALUE cb_opaque; + VALUE newc; + VALUE local_hash; + VALUE remote_hash; + VALUE subject_array; + VALUE pair; + int i; + + if (TYPE(passthrough) != T_ARRAY) + rb_raise(rb_eTypeError, + "wrong domain event graphics callback argument type (expected Array)"); + + if (RARRAY_LEN(passthrough) != 2) + rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", + RARRAY_LEN(passthrough)); + + cb = rb_ary_entry(passthrough, 0); + cb_opaque = rb_ary_entry(passthrough, 1); + + local_hash = rb_hash_new(); + rb_hash_aset(local_hash, rb_str_new2("family"), INT2NUM(local->family)); + rb_hash_aset(local_hash, rb_str_new2("node"), rb_str_new2(local->node)); + rb_hash_aset(local_hash, rb_str_new2("service"), + rb_str_new2(local->service)); + + remote_hash = rb_hash_new(); + rb_hash_aset(remote_hash, rb_str_new2("family"), INT2NUM(remote->family)); + rb_hash_aset(remote_hash, rb_str_new2("node"), rb_str_new2(remote->node)); + rb_hash_aset(remote_hash, rb_str_new2("service"), + rb_str_new2(remote->service)); + + subject_array = rb_ary_new(); + for (i = 0; i < subject->nidentity; i++) { + pair = rb_ary_new(); + rb_ary_store(pair, 0, rb_str_new2(subject->identities[i].type)); + rb_ary_store(pair, 1, rb_str_new2(subject->identities[i].name)); + + rb_ary_store(subject_array, i, pair); + } + + newc = connect_new(conn); + if (strcmp(rb_obj_classname(cb), "Symbol") == 0) + rb_funcall(rb_class_of(cb), rb_to_id(cb), 8, newc, + domain_new(dom, newc), INT2NUM(phase), local_hash, + remote_hash, rb_str_new2(authScheme), subject_array, + cb_opaque); + else if (strcmp(rb_obj_classname(cb), "Proc") == 0) + rb_funcall(cb, rb_intern("call"), 8, newc, domain_new(dom, newc), + INT2NUM(phase), local_hash, remote_hash, + rb_str_new2(authScheme), subject_array, cb_opaque); + else + rb_raise(rb_eTypeError, + "wrong domain event graphics callback (expected Symbol or Proc)"); + + return 0; +} + +/* + * call-seq: + * conn.domain_event_register_any(eventID, callback, dom=nil, opaque=nil) -> fixnum + * + * Call +virConnectDomainEventRegisterAny+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventRegisterAny] + * to register callback for eventID with libvirt. The eventID must be one of + * the Libvirt::Connect::DOMAIN_EVENT_ID_* constants. The callback can either + * be a Symbol (that is the name of a method to callback) or a Proc. Note that + * the callback must accept different numbers of arguments depending on the + * eventID passed in. The arguments are as follows: + * + * - DOMAIN_EVENT_ID_LIFECYCLE: Libvirt::Connect, Libvirt::Domain, event, detail, opaque + * - DOMAIN_EVENT_ID_REBOOT: Libvirt::Connect, Libvirt::Domain, opaque + * - DOMAIN_EVENT_ID_RTC_CHANGE: Libvirt::Connect, Libvirt::Domain, utc_offset, opaque + * - DOMAIN_EVENT_ID_WATCHDOG: Libvirt::Connect, Libvirt::Domain, action, opaque + * - DOMAIN_EVENT_ID_IO_ERROR: Libvirt::Connect, Libvirt::Domain, src_path, dev_alias, action, opaque + * - DOMAIN_EVENT_ID_IO_ERROR_REASON: Libvirt::Connect, Libvirt::Domain, src_path, dev_alias, action, reason, opaque + * - DOMAIN_EVENT_ID_GRAPHICS: Libvirt::Connect, Libvirt::Domain, phase, local, remote, auth_scheme, subject, opaque + + * If dom is a valid Libvirt::Domain object, then only events from that + * domain will be seen. The opaque parameter can be any valid ruby type, and + * will be passed into callback as "opaque". This method returns a + * libvirt-specific handle, which must be used by the application to + * deregister the callback later (see domain_event_deregister_any). + */ +static VALUE libvirt_conn_domain_event_register_any(int argc, VALUE *argv, + VALUE c) { + VALUE eventID, cb, dom, opaque; + virDomainPtr domain; + virConnectDomainEventGenericCallback internalcb = NULL; + VALUE passthrough; + + rb_scan_args(argc, argv, "22", &eventID, &cb, &dom, &opaque); + + if (!is_symbol_or_proc(cb)) + rb_raise(rb_eTypeError, "wrong argument type (expected Symbol or Proc)"); + + if (NIL_P(dom)) + domain = NULL; + else + domain = domain_get(dom); + + switch(NUM2INT(eventID)) { + case VIR_DOMAIN_EVENT_ID_LIFECYCLE: + internalcb = VIR_DOMAIN_EVENT_CALLBACK(domain_event_lifecycle_callback); + break; + case VIR_DOMAIN_EVENT_ID_REBOOT: + internalcb = VIR_DOMAIN_EVENT_CALLBACK(domain_event_reboot_callback); + break; + case VIR_DOMAIN_EVENT_ID_RTC_CHANGE: + internalcb = VIR_DOMAIN_EVENT_CALLBACK(domain_event_rtc_callback); + break; + case VIR_DOMAIN_EVENT_ID_WATCHDOG: + internalcb = VIR_DOMAIN_EVENT_CALLBACK(domain_event_watchdog_callback); + break; + case VIR_DOMAIN_EVENT_ID_IO_ERROR: + internalcb = VIR_DOMAIN_EVENT_CALLBACK(domain_event_io_error_callback); + break; + case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON: + internalcb = VIR_DOMAIN_EVENT_CALLBACK(domain_event_io_error_reason_callback); + break; + case VIR_DOMAIN_EVENT_ID_GRAPHICS: + internalcb = VIR_DOMAIN_EVENT_CALLBACK(domain_event_graphics_callback); + break; + default: + rb_raise(rb_eArgError, "invalid eventID argument %d", + NUM2INT(eventID)); + break; + } + + passthrough = rb_ary_new(); + rb_ary_store(passthrough, 0, cb); + rb_ary_store(passthrough, 1, opaque); + + gen_call_int(virConnectDomainEventRegisterAny, conn(c), connect_get(c), + domain, NUM2INT(eventID), internalcb, (void *)passthrough, + NULL); +} + +/* + * call-seq: + * conn.domain_event_deregister_any(callbackID) -> nil + * + * Call +virConnectDomainEventDeregisterAny+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventDeregisterAny] + * to deregister a callback from libvirt. The callbackID must be a + * libvirt-specific handle returned by domain_event_register_any. + */ +static VALUE libvirt_conn_domain_event_deregister_any(VALUE c, + VALUE callbackID) { + gen_call_void(virConnectDomainEventDeregisterAny, conn(c), connect_get(c), + NUM2INT(callbackID)); +} +#endif + +#if HAVE_VIRCONNECTDOMAINEVENTREGISTER +/* + * this is a bit of silliness. Because libvirt internals track the address + * of the function pointer, trying to use domain_event_lifecycle_callback + * for both register and register_any would mean that we could only register + * one or the other for lifecycle callbacks. Instead we do a simple wrapper + * so that the addresses are different + */ +static int domain_event_callback(virConnectPtr conn, + virDomainPtr dom, int event, + int detail, void *opaque) { + return domain_event_lifecycle_callback(conn, dom, event, detail, opaque); +} +/* + * call-seq: + * conn.domain_event_register(callback, opaque=nil) -> nil + * + * Call +virConnectDomainEventRegister+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventRegister] + * to register callback for domain lifecycle events with libvirt. The + * callback can either be a Symbol (that is the name of a method to callback) + * or a Proc. The callback must accept 5 parameters: Libvirt::Connect, + * Libvirt::Domain, event, detail, opaque. The opaque parameter to + * domain_event_register can be any valid ruby type, and will be passed into + * callback as "opaque". This method is deprecated in favor of + * domain_event_register_any. + */ +static VALUE libvirt_conn_domain_event_register(int argc, VALUE *argv, + VALUE c) { + VALUE cb, opaque; + VALUE passthrough; + + rb_scan_args(argc, argv, "11", &cb, &opaque); + + if (!is_symbol_or_proc(cb)) + rb_raise(rb_eTypeError, "wrong argument type (expected Symbol or Proc)"); + + passthrough = rb_ary_new(); + rb_ary_store(passthrough, 0, cb); + rb_ary_store(passthrough, 1, opaque); + + gen_call_void(virConnectDomainEventRegister, conn(c), connect_get(c), + domain_event_callback, (void *)passthrough, NULL); +} + +/* + * call-seq: + * conn.domain_event_deregister(callback) -> nil + * + * Call +virConnectDomainEventDeregister+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventDeregister] + * to deregister the event callback from libvirt. This method is deprecated + * in favor of domain_event_deregister_any (though they cannot be mixed; if + * the callback was registered with domain_event_register, it must be + * deregistered with domain_event_deregister). + */ +static VALUE libvirt_conn_domain_event_deregister(VALUE c) { + gen_call_void(virConnectDomainEventDeregister, conn(c), connect_get(c), + domain_event_callback); +} +#endif + +/* + * call-seq: + * conn.num_of_domains -> fixnum + * + * Call +virConnectNumOfDomains+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfDomains] + * to retrieve the number of active domains on this connection. + */ +static VALUE libvirt_conn_num_of_domains(VALUE s) { + gen_conn_num_of(s, Domains); +} + +/* + * call-seq: + * conn.list_domains -> list + * + * Call +virConnectListDomains+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListDomains] + * to retrieve a list of active domain IDs on this connection. + */ +static VALUE libvirt_conn_list_domains(VALUE s) { + int i, r, num, *ids; + virConnectPtr conn = connect_get(s); + VALUE result; + int exception = 0; + struct rb_ary_push_arg args; + + num = virConnectNumOfDomains(conn); + _E(num < 0, create_error(e_RetrieveError, "virConnectNumOfDomains", conn)); + if (num == 0) { + result = rb_ary_new2(num); + return result; + } + + ids = ALLOC_N(int, num); + r = virConnectListDomains(conn, ids, num); + if (r < 0) { + xfree(ids); + rb_exc_raise(create_error(e_RetrieveError, "virConnectListDomains", + conn)); + } + + result = rb_protect(rb_ary_new2_wrap, (VALUE)&num, &exception); + if (exception) { + xfree(ids); + rb_jump_tag(exception); + } + + for (i = 0; i < num; i++) { + args.arr = result; + args. value = INT2NUM(ids[i]); + rb_protect(rb_ary_push_wrap, (VALUE)&args, &exception); + if (exception) { + xfree(ids); + rb_jump_tag(exception); + } + } + xfree(ids); + return result; +} + +/* + * call-seq: + * conn.num_of_defined_domains -> fixnum + * + * Call +virConnectNumOfDefinedDomains+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfDefinedDomains] + * to retrieve the number of inactive domains on this connection. + */ +static VALUE libvirt_conn_num_of_defined_domains(VALUE s) { + gen_conn_num_of(s, DefinedDomains); +} + +/* + * call-seq: + * conn.list_defined_domains -> list + * + * Call +virConnectListDefinedDomains+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListDefinedDomains] + * to retrieve a list of inactive domain names on this connection. + */ +static VALUE libvirt_conn_list_defined_domains(VALUE s) { + gen_conn_list_names(s, DefinedDomains); +} + +/* + * call-seq: + * conn.create_domain_linux(xml, flags=0) -> Libvirt::Domain + * + * Call +virDomainCreateLinux+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainCreateLinux] + * to start a transient domain from the given XML. Deprecated; use + * conn.create_domain_xml instead. + */ +static VALUE libvirt_conn_create_linux(int argc, VALUE *argv, VALUE c) { + virDomainPtr dom; + virConnectPtr conn = connect_get(c); + VALUE flags, xml; + + rb_scan_args(argc, argv, "11", &xml, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + dom = virDomainCreateLinux(conn, StringValueCStr(xml), NUM2UINT(flags)); + _E(dom == NULL, create_error(e_Error, "virDomainCreateLinux", conn)); + + return domain_new(dom, c); +} + +#if HAVE_VIRDOMAINCREATEXML +/* + * call-seq: + * conn.create_domain_xml(xml, flags=0) -> Libvirt::Domain + * + * Call +virDomainCreateXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainCreateXML] + * to start a transient domain from the given XML. + */ +static VALUE libvirt_conn_create_xml(int argc, VALUE *argv, VALUE c) { + virDomainPtr dom; + virConnectPtr conn = connect_get(c); + VALUE flags, xml; + + rb_scan_args(argc, argv, "11", &xml, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + dom = virDomainCreateXML(conn, StringValueCStr(xml), NUM2UINT(flags)); + _E(dom == NULL, create_error(e_Error, "virDomainCreateXML", conn)); + + return domain_new(dom, c); +} +#endif + +/* + * call-seq: + * conn.lookup_domain_by_name(name) -> Libvirt::Domain + * + * Call +virDomainLookupByName+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainLookupByName] + * to retrieve a domain object for name. + */ +static VALUE libvirt_conn_lookup_domain_by_name(VALUE c, VALUE name) { + virDomainPtr dom; + virConnectPtr conn = connect_get(c); + + dom = virDomainLookupByName(conn, StringValueCStr(name)); + _E(dom == NULL, create_error(e_RetrieveError, "virDomainLookupByName", + conn)); + + return domain_new(dom, c); +} + +/* + * call-seq: + * conn.lookup_domain_by_id(id) -> Libvirt::Domain + * + * Call +virDomainLookupByID+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainLookupByID] + * to retrieve a domain object for id. + */ +static VALUE libvirt_conn_lookup_domain_by_id(VALUE c, VALUE id) { + virDomainPtr dom; + virConnectPtr conn = connect_get(c); + + dom = virDomainLookupByID(conn, NUM2INT(id)); + _E(dom == NULL, create_error(e_RetrieveError, "virDomainLookupByID", + conn)); + + return domain_new(dom, c); +} + +/* + * call-seq: + * conn.lookup_domain_by_uuid(uuid) -> Libvirt::Domain + * + * Call +virDomainLookupByUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainLookupByUUIDString] + * to retrieve a domain object for uuid. + */ +static VALUE libvirt_conn_lookup_domain_by_uuid(VALUE c, VALUE uuid) { + virDomainPtr dom; + virConnectPtr conn = connect_get(c); + + dom = virDomainLookupByUUIDString(conn, StringValueCStr(uuid)); + _E(dom == NULL, create_error(e_RetrieveError, "virDomainLookupByUUID", + conn)); + + return domain_new(dom, c); +} + +/* + * call-seq: + * conn.define_domain_xml(xml) -> Libvirt::Domain + * + * Call +virDomainDefineXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainDefineXML] + * to define a permanent domain on this connection. + */ +static VALUE libvirt_conn_define_domain_xml(VALUE c, VALUE xml) { + virDomainPtr dom; + virConnectPtr conn = connect_get(c); + + dom = virDomainDefineXML(conn, StringValueCStr(xml)); + _E(dom == NULL, create_error(e_DefinitionError, "virDomainDefineXML", + conn)); + + return domain_new(dom, c); +} + +#if HAVE_VIRCONNECTDOMAINXMLFROMNATIVE +/* + * call-seq: + * conn.domain_xml_from_native(nativeFormat, xml, flags=0) -> string + * + * Call +virConnectDomainXMLFromNative+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainXMLFromNative] + * to convert a native hypervisor domain representation to libvirt XML. + */ +static VALUE libvirt_conn_domain_xml_from_native(int argc, VALUE *argv, + VALUE s) { + VALUE nativeFormat, xml, flags; + char *ret; + VALUE result; + + rb_scan_args(argc, argv, "21", &nativeFormat, &xml, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + ret = virConnectDomainXMLFromNative(conn(s), StringValueCStr(nativeFormat), + StringValueCStr(xml), NUM2UINT(flags)); + _E(ret == NULL, create_error(e_Error, "virConnectDomainXMLFromNative", + conn(s))); + + result = rb_str_new2(ret); + + free(ret); + + return result; +} +#endif + +#if HAVE_VIRCONNECTDOMAINXMLTONATIVE +/* + * call-seq: + * conn.domain_xml_to_native(nativeFormat, xml, flags=0) -> string + * + * Call +virConnectDomainXMLToNative+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainXMLToNative] + * to convert libvirt XML to a native domain hypervisor representation. + */ +static VALUE libvirt_conn_domain_xml_to_native(int argc, VALUE *argv, VALUE s) { + VALUE nativeFormat, xml, flags; + char *ret; + VALUE result; + + rb_scan_args(argc, argv, "21", &nativeFormat, &xml, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + ret = virConnectDomainXMLToNative(conn(s), StringValueCStr(nativeFormat), + StringValueCStr(xml), NUM2UINT(flags)); + _E(ret == NULL, create_error(e_Error, "virConnectDomainXMLToNative", + conn(s))); + + result = rb_str_new2(ret); + + free(ret); + + return result; +} +#endif + +#if HAVE_TYPE_VIRINTERFACEPTR +/* + * call-seq: + * conn.num_of_interfaces -> fixnum + * + * Call +virConnectNumOfInterfaces+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfInterfaces] + * to retrieve the number of active interfaces on this connection. + */ +static VALUE libvirt_conn_num_of_interfaces(VALUE s) { + gen_conn_num_of(s, Interfaces); +} + +/* + * call-seq: + * conn.list_interfaces -> list + * + * Call +virConnectListInterfaces+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListInterfaces] + * to retrieve a list of active interface names on this connection. + */ +static VALUE libvirt_conn_list_interfaces(VALUE s) { + gen_conn_list_names(s, Interfaces); +} + +/* + * call-seq: + * conn.num_of_defined_interfaces -> fixnum + * + * Call +virConnectNumOfDefinedInterfaces+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfDefinedInterfaces] + * to retrieve the number of inactive interfaces on this connection. + */ +static VALUE libvirt_conn_num_of_defined_interfaces(VALUE s) { + gen_conn_num_of(s, DefinedInterfaces); +} + +/* + * call-seq: + * conn.list_defined_interfaces -> list + * + * Call +virConnectListDefinedInterfaces+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListDefinedInterfaces] + * to retrieve a list of inactive interface names on this connection. + */ +static VALUE libvirt_conn_list_defined_interfaces(VALUE s) { + gen_conn_list_names(s, DefinedInterfaces); +} + +extern VALUE interface_new(virInterfacePtr i, VALUE conn); +/* + * call-seq: + * conn.lookup_interface_by_name(name) -> Libvirt::Interface + * + * Call +virInterfaceLookupByName+[http://www.libvirt.org/html/libvirt-libvirt.html#virInterfaceLookupByName] + * to retrieve an interface object by name. + */ +static VALUE libvirt_conn_lookup_interface_by_name(VALUE c, VALUE name) { + virInterfacePtr iface; + virConnectPtr conn = connect_get(c); + + iface = virInterfaceLookupByName(conn, StringValueCStr(name)); + _E(iface == NULL, create_error(e_RetrieveError, "virInterfaceLookupByName", + conn)); + + return interface_new(iface, c); +} + +/* + * call-seq: + * conn.lookup_interface_by_mac(mac) -> Libvirt::Interface + * + * Call +virInterfaceLookupByMACString+[http://www.libvirt.org/html/libvirt-libvirt.html#virInterfaceLookupByMACString] + * to retrieve an interface object by MAC address. + */ +static VALUE libvirt_conn_lookup_interface_by_mac(VALUE c, VALUE mac) { + virInterfacePtr iface; + virConnectPtr conn = connect_get(c); + + iface = virInterfaceLookupByMACString(conn, StringValueCStr(mac)); + _E(iface == NULL, create_error(e_RetrieveError, + "virInterfaceLookupByMACString", conn)); + + return interface_new(iface, c); +} + +/* + * call-seq: + * conn.define_interface_xml(xml, flags=0) -> Libvirt::Interface + * + * Call +virInterfaceDefineXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virInterfaceDefineXML] + * to define a new interface from xml. + */ +static VALUE libvirt_conn_define_interface_xml(int argc, VALUE *argv, VALUE c) { + virInterfacePtr iface; + virConnectPtr conn = connect_get(c); + VALUE xml, flags; + + rb_scan_args(argc, argv, "11", &xml, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + iface = virInterfaceDefineXML(conn, StringValueCStr(xml), NUM2UINT(flags)); + _E(iface == NULL, create_error(e_DefinitionError, "virInterfaceDefineXML", + conn)); + + return interface_new(iface, c); +} +#endif + +/* + * call-seq: + * conn.num_of_networks -> fixnum + * + * Call +virConnectNumOfNetworks+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfNetworks] + * to retrieve the number of active networks on this connection. + */ +static VALUE libvirt_conn_num_of_networks(VALUE s) { + gen_conn_num_of(s, Networks); +} + +/* + * call-seq: + * conn.list_networks -> list + * + * Call +virConnectListNetworks+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListNetworks] + * to retrieve a list of active network names on this connection. + */ +static VALUE libvirt_conn_list_networks(VALUE s) { + gen_conn_list_names(s, Networks); +} + +/* + * call-seq: + * conn.num_of_defined_networks -> fixnum + * + * Call +virConnectNumOfDefinedNetworks+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfDefinedNetworks] + * to retrieve the number of inactive networks on this connection. + */ +static VALUE libvirt_conn_num_of_defined_networks(VALUE s) { + gen_conn_num_of(s, DefinedNetworks); +} + +/* + * call-seq: + * conn.list_of_defined_networks -> list + * + * Call +virConnectListDefinedNetworks+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListDefinedNetworks] + * to retrieve a list of inactive network names on this connection. + */ +static VALUE libvirt_conn_list_defined_networks(VALUE s) { + gen_conn_list_names(s, DefinedNetworks); +} + +/* + * call-seq: + * conn.lookup_network_by_name(name) -> Libvirt::Network + * + * Call +virNetworkLookupByName+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkLookupByName] + * to retrieve a network object by name. + */ +static VALUE libvirt_conn_lookup_network_by_name(VALUE c, VALUE name) { + virNetworkPtr netw; + virConnectPtr conn = connect_get(c); + + netw = virNetworkLookupByName(conn, StringValueCStr(name)); + _E(netw == NULL, create_error(e_RetrieveError, "virNetworkLookupByName", + conn)); + + return network_new(netw, c); +} + +/* + * call-seq: + * conn.lookup_network_by_uuid(uuid) -> Libvirt::Network + * + * Call +virNetworkLookupByUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkLookupByUUIDString] + * to retrieve a network object by UUID. + */ +static VALUE libvirt_conn_lookup_network_by_uuid(VALUE c, VALUE uuid) { + virNetworkPtr netw; + virConnectPtr conn = connect_get(c); + + netw = virNetworkLookupByUUIDString(conn, StringValueCStr(uuid)); + _E(netw == NULL, create_error(e_RetrieveError, "virNetworkLookupByUUID", + conn)); + + return network_new(netw, c); +} + +/* + * call-seq: + * conn.create_network_xml(xml) -> Libvirt::Network + * + * Call +virNetworkCreateXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkCreateXML] + * to start a new transient network from xml. + */ +static VALUE libvirt_conn_create_network_xml(VALUE c, VALUE xml) { + virNetworkPtr netw; + virConnectPtr conn = connect_get(c); + + netw = virNetworkCreateXML(conn, StringValueCStr(xml)); + _E(netw == NULL, create_error(e_Error, "virNetworkCreateXML", conn)); + + return network_new(netw, c); +} + +/* + * call-seq: + * conn.define_network_xml(xml) -> Libvirt::Network + * + * Call +virNetworkDefineXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkDefineXML] + * to define a new permanent network from xml. + */ +static VALUE libvirt_conn_define_network_xml(VALUE c, VALUE xml) { + virNetworkPtr netw; + virConnectPtr conn = connect_get(c); + + netw = virNetworkDefineXML(conn, StringValueCStr(xml)); + _E(netw == NULL, create_error(e_DefinitionError, "virNetworkDefineXML", + conn)); + + return network_new(netw, c); +} + +#if HAVE_TYPE_VIRNODEDEVICEPTR +extern VALUE nodedevice_new(virNodeDevicePtr s, VALUE conn); + +/* + * call-seq: + * conn.num_of_nodedevices(cap=nil, flags=0) -> fixnum + * + * Call +virNodeNumOfDevices+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeNumOfDevices] + * to retrieve the number of node devices on this connection. + */ +static VALUE libvirt_conn_num_of_nodedevices(int argc, VALUE *argv, VALUE c) { + int result; + virConnectPtr conn = connect_get(c); + VALUE cap, flags; + + rb_scan_args(argc, argv, "02", &cap, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + result = virNodeNumOfDevices(conn, get_string_or_nil(cap), NUM2UINT(flags)); + _E(result < 0, create_error(e_RetrieveError, "virNodeNumOfDevices", conn)); + + return INT2NUM(result); +} + +/* + * call-seq: + * conn.list_nodedevices(cap=nil, flags=0) -> list + * + * Call +virNodeListDevices+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeListDevices] + * to retrieve a list of node device names on this connection. + */ +static VALUE libvirt_conn_list_nodedevices(int argc, VALUE *argv, VALUE c) { + int r, num; + virConnectPtr conn = connect_get(c); + VALUE cap, flags_val; + char *capstr; + char **names; + unsigned int flags; + + rb_scan_args(argc, argv, "02", &cap, &flags_val); + + if (NIL_P(flags_val)) + flags = 0; + else + flags = NUM2UINT(flags_val); + + capstr = get_string_or_nil(cap); + + num = virNodeNumOfDevices(conn, capstr, 0); + _E(num < 0, create_error(e_RetrieveError, "virNodeNumOfDevices", conn)); + if (num == 0) + /* if num is 0, don't call virNodeListDevices function */ + return rb_ary_new2(num); + + names = ALLOC_N(char *, num); + r = virNodeListDevices(conn, capstr, names, num, flags); + if (r < 0) { + xfree(names); + rb_exc_raise(create_error(e_RetrieveError, "virNodeListDevices", conn)); + } + + return gen_list(num, &names); +} + +/* + * call-seq: + * conn.lookup_nodedevice_by_name(name) -> Libvirt::NodeDevice + * + * Call +virNodeDeviceLookupByName+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeDeviceLookupByName] + * to retrieve a nodedevice object by name. + */ +static VALUE libvirt_conn_lookup_nodedevice_by_name(VALUE c, VALUE name) { + virNodeDevicePtr nodedev; + virConnectPtr conn = connect_get(c); + + nodedev = virNodeDeviceLookupByName(conn, StringValueCStr(name)); + _E(nodedev == NULL, create_error(e_RetrieveError, + "virNodeDeviceLookupByName", conn)); + + return nodedevice_new(nodedev, c); + +} + +#if HAVE_VIRNODEDEVICECREATEXML +/* + * call-seq: + * conn.create_nodedevice_xml(xml, flags=0) -> Libvirt::NodeDevice + * + * Call +virNodeDeviceCreateXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeDeviceCreateXML] + * to create a new node device from xml. + */ +static VALUE libvirt_conn_create_nodedevice_xml(int argc, VALUE *argv, + VALUE c) { + virNodeDevicePtr nodedev; + virConnectPtr conn = connect_get(c); + VALUE xml, flags; + + rb_scan_args(argc, argv, "11", &xml, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + nodedev = virNodeDeviceCreateXML(conn, StringValueCStr(xml), + NUM2UINT(flags)); + _E(nodedev == NULL, create_error(e_Error, "virNodeDeviceCreateXML", conn)); + + return nodedevice_new(nodedev, c); +} +#endif +#endif + +#if HAVE_TYPE_VIRNWFILTERPTR +extern VALUE nwfilter_new(virNWFilterPtr nw, VALUE conn); + +/* + * call-seq: + * conn.num_of_nwfilters -> fixnum + * + * Call +virConnectNumOfNWFilters+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfNWFilters] + * to retrieve the number of network filters on this connection. + */ +static VALUE libvirt_conn_num_of_nwfilters(VALUE s) { + gen_conn_num_of(s, NWFilters); +} + +/* + * call-seq: + * conn.list_nwfilters -> list + * + * Call +virConnectListNWFilters+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListNWFilters] + * to retrieve a list of network filter names on this connection. + */ +static VALUE libvirt_conn_list_nwfilters(VALUE s) { + gen_conn_list_names(s, NWFilters); +} + +/* + * call-seq: + * conn.lookup_nwfilter_by_name(name) -> Libvirt::NWFilter + * + * Call +virNWFilterLookupByName+[http://www.libvirt.org/html/libvirt-libvirt.html#virNWFilterLookupByName] + * to retrieve a network filter object by name. + */ +static VALUE libvirt_conn_lookup_nwfilter_by_name(VALUE c, VALUE name) { + virNWFilterPtr nwfilter; + virConnectPtr conn = connect_get(c); + + nwfilter = virNWFilterLookupByName(conn, StringValueCStr(name)); + _E(nwfilter == NULL, create_error(e_RetrieveError, + "virNWFilterLookupByName", conn)); + + return nwfilter_new(nwfilter, c); +} + +/* + * call-seq: + * conn.lookup_nwfilter_by_uuid(uuid) -> Libvirt::NWFilter + * + * Call +virNWFilterLookupByUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virNWFilterLookupByUUIDString] + * to retrieve a network filter object by UUID. + */ +static VALUE libvirt_conn_lookup_nwfilter_by_uuid(VALUE c, VALUE uuid) { + virNWFilterPtr nwfilter; + virConnectPtr conn = connect_get(c); + + nwfilter = virNWFilterLookupByUUIDString(conn, StringValueCStr(uuid)); + _E(nwfilter == NULL, create_error(e_RetrieveError, + "virNWFilterLookupByUUIDString", conn)); + + return nwfilter_new(nwfilter, c); +} + +/* + * call-seq: + * conn.define_nwfilter_xml(xml) -> Libvirt::NWFilter + * + * Call +virNWFilterDefineXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virNWFilterDefineXML] + * to define a new network filter from xml. + */ +static VALUE libvirt_conn_define_nwfilter_xml(VALUE c, VALUE xml) { + virNWFilterPtr nwfilter; + virConnectPtr conn = connect_get(c); + + nwfilter = virNWFilterDefineXML(conn, StringValueCStr(xml)); + _E(nwfilter == NULL, create_error(e_DefinitionError, "virNWFilterDefineXML", + conn)); + + return nwfilter_new(nwfilter, c); +} +#endif + +#if HAVE_TYPE_VIRSECRETPTR +extern VALUE secret_new(virSecretPtr s, VALUE conn); + +/* + * call-seq: + * conn.num_of_secrets -> fixnum + * + * Call +virConnectNumOfSecrets+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfSecrets] + * to retrieve the number of secrets on this connection. + */ +static VALUE libvirt_conn_num_of_secrets(VALUE s) { + gen_conn_num_of(s, Secrets); +} + +/* + * call-seq: + * conn.list_secrets -> list + * + * Call +virConnectListSecrets+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListSecrets] + * to retrieve a list of secret UUIDs on this connection. + */ +static VALUE libvirt_conn_list_secrets(VALUE s) { + gen_conn_list_names(s, Secrets); +} + +/* + * call-seq: + * conn.lookup_secret_by_uuid(uuid) -> Libvirt::Secret + * + * Call +virSecretLookupByUUID+[http://www.libvirt.org/html/libvirt-libvirt.html#virSecretLookupByUUID] + * to retrieve a network object from uuid. + */ +static VALUE libvirt_conn_lookup_secret_by_uuid(VALUE c, VALUE uuid) { + virSecretPtr secret; + virConnectPtr conn = connect_get(c); + + secret = virSecretLookupByUUIDString(conn, StringValueCStr(uuid)); + _E(secret == NULL, create_error(e_RetrieveError, "virSecretLookupByUUID", + conn)); + + return secret_new(secret, c); +} + +/* + * call-seq: + * conn.lookup_secret_by_usage(usagetype, usageID) -> Libvirt::Secret + * + * Call +virSecretLookupByUsage+[http://www.libvirt.org/html/libvirt-libvirt.html#virSecretLookupByUsage] + * to retrieve a secret by usagetype. + */ +static VALUE libvirt_conn_lookup_secret_by_usage(VALUE c, VALUE usagetype, + VALUE usageID) { + virSecretPtr secret; + virConnectPtr conn = connect_get(c); + + secret = virSecretLookupByUsage(conn, NUM2UINT(usagetype), + StringValueCStr(usageID)); + _E(secret == NULL, create_error(e_RetrieveError, "virSecretLookupByUsage", + conn)); + + return secret_new(secret, c); +} + +/* + * call-seq: + * conn.define_secret_xml(xml, flags=0) -> Libvirt::Secret + * + * Call +virSecretDefineXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virSecretDefineXML] + * to define a new secret from xml. + */ +static VALUE libvirt_conn_define_secret_xml(int argc, VALUE *argv, VALUE c) { + virSecretPtr secret; + virConnectPtr conn = connect_get(c); + VALUE xml, flags; + + rb_scan_args(argc, argv, "11", &xml, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + secret = virSecretDefineXML(conn, StringValueCStr(xml), NUM2UINT(flags)); + _E(secret == NULL, create_error(e_DefinitionError, "virSecretDefineXML", + conn)); + + return secret_new(secret, c); +} +#endif + +#if HAVE_TYPE_VIRSTORAGEPOOLPTR + +VALUE pool_new(virStoragePoolPtr n, VALUE conn); + +/* + * call-seq: + * conn.list_storage_pools -> list + * + * Call +virConnectListStoragePools+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListStoragePools] + * to retrieve a list of active storage pool names on this connection. + */ +static VALUE libvirt_conn_list_storage_pools(VALUE s) { + gen_conn_list_names(s, StoragePools); +} + +/* + * call-seq: + * conn.num_of_storage_pools -> fixnum + * + * Call +virConnectNumOfStoragePools+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfStoragePools] + * to retrieve the number of active storage pools on this connection. + */ +static VALUE libvirt_conn_num_of_storage_pools(VALUE s) { + gen_conn_num_of(s, StoragePools); +} + +/* + * call-seq: + * conn.list_defined_storage_pools -> list + * + * Call +virConnectListDefinedStoragePools+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListDefinedStoragePools] + * to retrieve a list of inactive storage pool names on this connection. + */ +static VALUE libvirt_conn_list_defined_storage_pools(VALUE s) { + gen_conn_list_names(s, DefinedStoragePools); +} + +/* + * call-seq: + * conn.num_of_defined_storage_pools -> fixnum + * + * Call +virConnectNumOfDefinedStoragePools+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfDefinedStoragePools] + * to retrieve the number of inactive storage pools on this connection. + */ +static VALUE libvirt_conn_num_of_defined_storage_pools(VALUE s) { + gen_conn_num_of(s, DefinedStoragePools); +} + +/* + * call-seq: + * conn.lookup_storage_pool_by_name(name) -> Libvirt::StoragePool + * + * Call +virStoragePoolLookupByName+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolLookupByName] + * to retrieve a storage pool object by name. + */ +static VALUE libvirt_conn_lookup_pool_by_name(VALUE c, VALUE name) { + virStoragePoolPtr pool; + virConnectPtr conn = connect_get(c); + + pool = virStoragePoolLookupByName(conn, StringValueCStr(name)); + _E(pool == NULL, create_error(e_RetrieveError, "virStoragePoolLookupByName", + conn)); + + return pool_new(pool, c); +} + +/* + * call-seq: + * conn.lookup_storage_pool_by_uuid(uuid) -> Libvirt::StoragePool + * + * Call +virStoragePoolLookupByUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolLookupByUUIDString] + * to retrieve a storage pool object by uuid. + */ +static VALUE libvirt_conn_lookup_pool_by_uuid(VALUE c, VALUE uuid) { + virStoragePoolPtr pool; + virConnectPtr conn = connect_get(c); + + pool = virStoragePoolLookupByUUIDString(conn, StringValueCStr(uuid)); + _E(pool == NULL, create_error(e_RetrieveError, "virStoragePoolLookupByUUID", + conn)); + + return pool_new(pool, c); +} + +/* + * call-seq: + * conn.create_storage_pool_xml(xml, flags=0) -> Libvirt::StoragePool + * + * Call +virStoragePoolCreateXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolCreateXML] + * to start a new transient storage pool from xml. + */ +static VALUE libvirt_conn_create_pool_xml(int argc, VALUE *argv, VALUE c) { + virStoragePoolPtr pool; + virConnectPtr conn = connect_get(c); + VALUE xml, flags; + + rb_scan_args(argc, argv, "11", &xml, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + pool = virStoragePoolCreateXML(conn, StringValueCStr(xml), NUM2UINT(flags)); + _E(pool == NULL, create_error(e_Error, "virStoragePoolCreateXML", conn)); + + return pool_new(pool, c); +} + +/* + * call-seq: + * conn.define_storage_pool_xml(xml, flags=0) -> Libvirt::StoragePool + * + * Call +virStoragePoolDefineXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolDefineXML] + * to define a permanent storage pool from xml. + */ +static VALUE libvirt_conn_define_pool_xml(int argc, VALUE *argv, VALUE c) { + virStoragePoolPtr pool; + virConnectPtr conn = connect_get(c); + VALUE xml, flags; + + rb_scan_args(argc, argv, "11", &xml, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + pool = virStoragePoolDefineXML(conn, StringValueCStr(xml), NUM2UINT(flags)); + _E(pool == NULL, create_error(e_DefinitionError, "virStoragePoolDefineXML", + conn)); + + return pool_new(pool, c); +} + +/* + * call-seq: + * conn.discover_storage_pool_sources(type, srcSpec=nil, flags=0) -> string + * + * Call +virConnectFindStoragePoolSources+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectFindStoragePoolSources] + * to find the storage pool sources corresponding to type. + */ +static VALUE libvirt_conn_find_storage_pool_sources(int argc, VALUE *argv, + VALUE c) { + VALUE type, srcSpec_val, flags; + + rb_scan_args(argc, argv, "12", &type, &srcSpec_val, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_string(virConnectFindStoragePoolSources, conn(c), 1, + connect_get(c), StringValueCStr(type), + get_string_or_nil(srcSpec_val), NUM2UINT(flags)); +} +#endif + +#if HAVE_VIRCONNECTGETSYSINFO +/* + * call-seq: + * conn.sys_info(flags=0) -> string + * + * Call +virConnectGetSysinfo+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectGetSysinfo] + * to get machine-specific information about the hypervisor. This may include + * data such as the host UUID, the BIOS version, etc. + */ +static VALUE libvirt_conn_get_sys_info(int argc, VALUE *argv, VALUE c) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_string(virConnectGetSysinfo, conn(c), 1, connect_get(c), + NUM2UINT(flags)); +} +#endif + +#if HAVE_TYPE_VIRSTREAMPTR +extern VALUE stream_new(virStreamPtr s, VALUE conn); + +/* + * call-seq: + * conn.stream(flags=0) -> Libvirt::Stream + * + * Call +virStreamNew+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamNew] + * to create a new stream. + */ +static VALUE libvirt_conn_stream(int argc, VALUE *argv, VALUE c) { + VALUE flags; + virStreamPtr stream; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + stream = virStreamNew(connect_get(c), NUM2UINT(flags)); + + _E(stream == NULL, create_error(e_RetrieveError, "virStreamNew", conn(c))); + + return stream_new(stream, c); +} +#endif + +#if HAVE_VIRINTERFACECHANGEBEGIN +/* + * call-seq: + * conn.interface_change_begin(flags=0) -> nil + * + * Call +virInterfaceChangeBegin+[http://www.libvirt.org/html/libvirt-libvirt.html#virInterfaceChangeBegin] + * to create a restore point for interface changes. Once changes have been + * made, conn.interface_change_commit can be used to commit the result or + * conn.interface_change_rollback can be used to rollback to this restore point. + */ +static VALUE libvirt_conn_interface_change_begin(int argc, VALUE *argv, + VALUE c) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + gen_call_void(virInterfaceChangeBegin, conn(c), connect_get(c), + NUM2UINT(flags)); +} + +/* + * call-seq: + * conn.interface_change_commit(flags=0) -> nil + * + * Call +virInterfaceChangeCommit+[http://www.libvirt.org/html/libvirt-libvirt.html#virInterfaceChangeCommit] + * to commit the interface changes since the last conn.interface_change_begin. + */ +static VALUE libvirt_conn_interface_change_commit(int argc, VALUE *argv, + VALUE c) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + gen_call_void(virInterfaceChangeCommit, conn(c), connect_get(c), + NUM2UINT(flags)); +} + +/* + * call-seq: + * conn.interface_change_rollback(flags=0) -> nil + * + * Call +virInterfaceChangeRollback+[http://www.libvirt.org/html/libvirt-libvirt.html#virInterfaceChangeRollback] + * to rollback to the restore point saved by conn.interface_change_begin. + */ +static VALUE libvirt_conn_interface_change_rollback(int argc, VALUE *argv, + VALUE c) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + gen_call_void(virInterfaceChangeRollback, conn(c), connect_get(c), + NUM2UINT(flags)); +} +#endif + +/* + * Class Libvirt::Connect + */ +void init_connect() +{ + c_connect = rb_define_class_under(m_libvirt, "Connect", rb_cObject); + + /* + * Class Libvirt::Connect::Nodeinfo + */ + c_node_info = rb_define_class_under(c_connect, "Nodeinfo", rb_cObject); + rb_define_attr(c_node_info, "model", 1, 0); + rb_define_attr(c_node_info, "memory", 1, 0); + rb_define_attr(c_node_info, "cpus", 1, 0); + rb_define_attr(c_node_info, "mhz", 1, 0); + rb_define_attr(c_node_info, "nodes", 1, 0); + rb_define_attr(c_node_info, "sockets", 1, 0); + rb_define_attr(c_node_info, "cores", 1, 0); + rb_define_attr(c_node_info, "threads", 1, 0); + + /* + * Class Libvirt::Connect::NodeSecurityModel + */ + c_node_security_model = rb_define_class_under(c_connect, + "NodeSecurityModel", + rb_cObject); + rb_define_attr(c_node_security_model, "model", 1, 0); + rb_define_attr(c_node_security_model, "doi", 1, 0); + + rb_define_method(c_connect, "close", libvirt_conn_close, 0); + rb_define_method(c_connect, "closed?", libvirt_conn_closed_p, 0); + rb_define_method(c_connect, "type", libvirt_conn_type, 0); + rb_define_method(c_connect, "version", libvirt_conn_version, 0); +#if HAVE_VIRCONNECTGETLIBVERSION + rb_define_method(c_connect, "libversion", libvirt_conn_libversion, 0); +#endif + rb_define_method(c_connect, "hostname", libvirt_conn_hostname, 0); + rb_define_method(c_connect, "uri", libvirt_conn_uri, 0); + rb_define_method(c_connect, "max_vcpus", libvirt_conn_max_vcpus, -1); + rb_define_method(c_connect, "node_get_info", libvirt_conn_node_get_info, 0); + rb_define_method(c_connect, "node_free_memory", + libvirt_conn_node_free_memory, 0); + rb_define_method(c_connect, "node_cells_free_memory", + libvirt_conn_node_cells_free_memory, -1); +#if HAVE_VIRNODEGETSECURITYMODEL + rb_define_method(c_connect, "node_get_security_model", + libvirt_conn_node_get_security_model, 0); +#endif +#if HAVE_VIRCONNECTISENCRYPTED + rb_define_method(c_connect, "encrypted?", libvirt_conn_encrypted_p, 0); +#endif +#if HAVE_VIRCONNECTISSECURE + rb_define_method(c_connect, "secure?", libvirt_conn_secure_p, 0); +#endif + rb_define_method(c_connect, "capabilities", libvirt_conn_capabilities, 0); + +#if HAVE_VIRCONNECTCOMPARECPU + rb_define_const(c_connect, "CPU_COMPARE_ERROR", + INT2NUM(VIR_CPU_COMPARE_ERROR)); + rb_define_const(c_connect, "CPU_COMPARE_INCOMPATIBLE", + INT2NUM(VIR_CPU_COMPARE_INCOMPATIBLE)); + rb_define_const(c_connect, "CPU_COMPARE_IDENTICAL", + INT2NUM(VIR_CPU_COMPARE_IDENTICAL)); + rb_define_const(c_connect, "CPU_COMPARE_SUPERSET", + INT2NUM(VIR_CPU_COMPARE_SUPERSET)); + + rb_define_method(c_connect, "compare_cpu", libvirt_conn_compare_cpu, -1); +#endif + +#if HAVE_VIRCONNECTBASELINECPU + rb_define_method(c_connect, "baseline_cpu", libvirt_conn_baseline_cpu, -1); +#endif + + /* In the libvirt development history, the events were + * first defined in commit 1509b8027fd0b73c30aeab443f81dd5a18d80544, + * then ADDED and REMOVED were renamed to DEFINED and UNDEFINED at + * the same time that the details were added + * (d3d54d2fc92e350f250eda26cee5d0342416a9cf). What this means is that + * we have to check for HAVE_CONST_VIR_DOMAIN_EVENT_DEFINED and + * HAVE_CONST_VIR_DOMAIN_EVENT_STARTED to untangle these, and then we + * can make a decision for many of the events based on that. + */ +#if HAVE_CONST_VIR_DOMAIN_EVENT_DEFINED + rb_define_const(c_connect, "DOMAIN_EVENT_DEFINED", + INT2NUM(VIR_DOMAIN_EVENT_DEFINED)); + rb_define_const(c_connect, "DOMAIN_EVENT_DEFINED_ADDED", + INT2NUM(VIR_DOMAIN_EVENT_DEFINED_ADDED)); + rb_define_const(c_connect, "DOMAIN_EVENT_DEFINED_UPDATED", + INT2NUM(VIR_DOMAIN_EVENT_DEFINED_UPDATED)); + rb_define_const(c_connect, "DOMAIN_EVENT_UNDEFINED", + INT2NUM(VIR_DOMAIN_EVENT_UNDEFINED)); + rb_define_const(c_connect, "DOMAIN_EVENT_UNDEFINED_REMOVED", + INT2NUM(VIR_DOMAIN_EVENT_UNDEFINED_REMOVED)); + rb_define_const(c_connect, "DOMAIN_EVENT_STARTED_BOOTED", + INT2NUM(VIR_DOMAIN_EVENT_STARTED_BOOTED)); + rb_define_const(c_connect, "DOMAIN_EVENT_STARTED_MIGRATED", + INT2NUM(VIR_DOMAIN_EVENT_STARTED_MIGRATED)); + rb_define_const(c_connect, "DOMAIN_EVENT_STARTED_RESTORED", + INT2NUM(VIR_DOMAIN_EVENT_STARTED_RESTORED)); + rb_define_const(c_connect, "DOMAIN_EVENT_SUSPENDED_PAUSED", + INT2NUM(VIR_DOMAIN_EVENT_SUSPENDED_PAUSED)); + rb_define_const(c_connect, "DOMAIN_EVENT_SUSPENDED_MIGRATED", + INT2NUM(VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED)); + rb_define_const(c_connect, "DOMAIN_EVENT_RESUMED_UNPAUSED", + INT2NUM(VIR_DOMAIN_EVENT_RESUMED_UNPAUSED)); + rb_define_const(c_connect, "DOMAIN_EVENT_RESUMED_MIGRATED", + INT2NUM(VIR_DOMAIN_EVENT_RESUMED_MIGRATED)); + rb_define_const(c_connect, "DOMAIN_EVENT_STOPPED_SHUTDOWN", + INT2NUM(VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN)); + rb_define_const(c_connect, "DOMAIN_EVENT_STOPPED_DESTROYED", + INT2NUM(VIR_DOMAIN_EVENT_STOPPED_DESTROYED)); + rb_define_const(c_connect, "DOMAIN_EVENT_STOPPED_CRASHED", + INT2NUM(VIR_DOMAIN_EVENT_STOPPED_CRASHED)); + rb_define_const(c_connect, "DOMAIN_EVENT_STOPPED_MIGRATED", + INT2NUM(VIR_DOMAIN_EVENT_STOPPED_MIGRATED)); + rb_define_const(c_connect, "DOMAIN_EVENT_STOPPED_SAVED", + INT2NUM(VIR_DOMAIN_EVENT_STOPPED_SAVED)); + rb_define_const(c_connect, "DOMAIN_EVENT_STOPPED_FAILED", + INT2NUM(VIR_DOMAIN_EVENT_STOPPED_FAILED)); +#endif +#if HAVE_CONST_VIR_DOMAIN_EVENT_STARTED + rb_define_const(c_connect, "DOMAIN_EVENT_STARTED", + INT2NUM(VIR_DOMAIN_EVENT_STARTED)); + rb_define_const(c_connect, "DOMAIN_EVENT_SUSPENDED", + INT2NUM(VIR_DOMAIN_EVENT_SUSPENDED)); + rb_define_const(c_connect, "DOMAIN_EVENT_RESUMED", + INT2NUM(VIR_DOMAIN_EVENT_RESUMED)); + rb_define_const(c_connect, "DOMAIN_EVENT_STOPPED", + INT2NUM(VIR_DOMAIN_EVENT_STOPPED)); +#endif +#if HAVE_TYPE_VIRDOMAINSNAPSHOTPTR + rb_define_const(c_connect, "DOMAIN_EVENT_STARTED_FROM_SNAPSHOT", + INT2NUM(VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT)); + rb_define_const(c_connect, "DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT", + INT2NUM(VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT)); +#endif +#if HAVE_CONST_VIR_DOMAIN_EVENT_SUSPENDED_IOERROR + rb_define_const(c_connect, "DOMAIN_EVENT_SUSPENDED_IOERROR", + INT2NUM(VIR_DOMAIN_EVENT_SUSPENDED_IOERROR)); + rb_define_const(c_connect, "DOMAIN_EVENT_SUSPENDED_WATCHDOG", + INT2NUM(VIR_DOMAIN_EVENT_SUSPENDED_WATCHDOG)); +#endif +#if HAVE_CONST_VIR_DOMAIN_EVENT_ID_WATCHDOG + rb_define_const(c_connect, "DOMAIN_EVENT_ID_WATCHDOG", + INT2NUM(VIR_DOMAIN_EVENT_ID_WATCHDOG)); + rb_define_const(c_connect, "DOMAIN_EVENT_WATCHDOG_NONE", + INT2NUM(VIR_DOMAIN_EVENT_WATCHDOG_NONE)); + rb_define_const(c_connect, "DOMAIN_EVENT_WATCHDOG_PAUSE", + INT2NUM(VIR_DOMAIN_EVENT_WATCHDOG_PAUSE)); + rb_define_const(c_connect, "DOMAIN_EVENT_WATCHDOG_RESET", + INT2NUM(VIR_DOMAIN_EVENT_WATCHDOG_RESET)); + rb_define_const(c_connect, "DOMAIN_EVENT_WATCHDOG_POWEROFF", + INT2NUM(VIR_DOMAIN_EVENT_WATCHDOG_POWEROFF)); + rb_define_const(c_connect, "DOMAIN_EVENT_WATCHDOG_SHUTDOWN", + INT2NUM(VIR_DOMAIN_EVENT_WATCHDOG_SHUTDOWN)); + rb_define_const(c_connect, "DOMAIN_EVENT_WATCHDOG_DEBUG", + INT2NUM(VIR_DOMAIN_EVENT_WATCHDOG_DEBUG)); +#endif +#if HAVE_CONST_VIR_DOMAIN_EVENT_ID_IO_ERROR + rb_define_const(c_connect, "DOMAIN_EVENT_ID_IO_ERROR", + INT2NUM(VIR_DOMAIN_EVENT_ID_IO_ERROR)); + rb_define_const(c_connect, "DOMAIN_EVENT_IO_ERROR_NONE", + INT2NUM(VIR_DOMAIN_EVENT_IO_ERROR_NONE)); + rb_define_const(c_connect, "DOMAIN_EVENT_IO_ERROR_PAUSE", + INT2NUM(VIR_DOMAIN_EVENT_IO_ERROR_PAUSE)); + rb_define_const(c_connect, "DOMAIN_EVENT_IO_ERROR_REPORT", + INT2NUM(VIR_DOMAIN_EVENT_IO_ERROR_REPORT)); +#endif +#if HAVE_CONST_VIR_DOMAIN_EVENT_ID_GRAPHICS + rb_define_const(c_connect, "DOMAIN_EVENT_ID_GRAPHICS", + INT2NUM(VIR_DOMAIN_EVENT_ID_GRAPHICS)); + rb_define_const(c_connect, "DOMAIN_EVENT_GRAPHICS_CONNECT", + INT2NUM(VIR_DOMAIN_EVENT_GRAPHICS_CONNECT)); + rb_define_const(c_connect, "DOMAIN_EVENT_GRAPHICS_INITIALIZE", + INT2NUM(VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE)); + rb_define_const(c_connect, "DOMAIN_EVENT_GRAPHICS_DISCONNECT", + INT2NUM(VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT)); + rb_define_const(c_connect, "DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4", + INT2NUM(VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4)); + rb_define_const(c_connect, "DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6", + INT2NUM(VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6)); +#endif +#if HAVE_VIRCONNECTDOMAINEVENTREGISTERANY + rb_define_const(c_connect, "DOMAIN_EVENT_ID_LIFECYCLE", + INT2NUM(VIR_DOMAIN_EVENT_ID_LIFECYCLE)); +#endif +#if HAVE_CONST_VIR_DOMAIN_EVENT_ID_REBOOT + rb_define_const(c_connect, "DOMAIN_EVENT_ID_REBOOT", + INT2NUM(VIR_DOMAIN_EVENT_ID_REBOOT)); +#endif +#if HAVE_CONST_VIR_DOMAIN_EVENT_ID_RTC_CHANGE + rb_define_const(c_connect, "DOMAIN_EVENT_ID_RTC_CHANGE", + INT2NUM(VIR_DOMAIN_EVENT_ID_RTC_CHANGE)); +#endif +#if HAVE_CONST_VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON + rb_define_const(c_connect, "DOMAIN_EVENT_ID_IO_ERROR_REASON", + INT2NUM(VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON)); +#endif + +#if HAVE_CONST_VIR_DOMAIN_EVENT_ID_CONTROL_ERROR + rb_define_const(c_connect, "DOMAIN_EVENT_ID_CONTROL_ERROR", + INT2NUM(VIR_DOMAIN_EVENT_ID_CONTROL_ERROR)); +#endif + +#if HAVE_VIRCONNECTDOMAINEVENTREGISTER + rb_define_method(c_connect, "domain_event_register", + libvirt_conn_domain_event_register, -1); + rb_define_method(c_connect, "domain_event_deregister", + libvirt_conn_domain_event_deregister, 0); +#endif + +#if HAVE_VIRCONNECTDOMAINEVENTREGISTERANY + rb_define_method(c_connect, "domain_event_register_any", + libvirt_conn_domain_event_register_any, -1); + rb_define_method(c_connect, "domain_event_deregister_any", + libvirt_conn_domain_event_deregister_any, 1); +#endif + + /* Domain creation/lookup */ + rb_define_method(c_connect, "num_of_domains", + libvirt_conn_num_of_domains, 0); + rb_define_method(c_connect, "list_domains", libvirt_conn_list_domains, 0); + rb_define_method(c_connect, "num_of_defined_domains", + libvirt_conn_num_of_defined_domains, 0); + rb_define_method(c_connect, "list_defined_domains", + libvirt_conn_list_defined_domains, 0); + rb_define_method(c_connect, "create_domain_linux", + libvirt_conn_create_linux, -1); +#if HAVE_VIRDOMAINCREATEXML + rb_define_method(c_connect, "create_domain_xml", + libvirt_conn_create_xml, -1); +#endif + rb_define_method(c_connect, "lookup_domain_by_name", + libvirt_conn_lookup_domain_by_name, 1); + rb_define_method(c_connect, "lookup_domain_by_id", + libvirt_conn_lookup_domain_by_id, 1); + rb_define_method(c_connect, "lookup_domain_by_uuid", + libvirt_conn_lookup_domain_by_uuid, 1); + rb_define_method(c_connect, "define_domain_xml", + libvirt_conn_define_domain_xml, 1); + +#if HAVE_VIRCONNECTDOMAINXMLFROMNATIVE + rb_define_method(c_connect, "domain_xml_from_native", + libvirt_conn_domain_xml_from_native, -1); +#endif +#if HAVE_VIRCONNECTDOMAINXMLTONATIVE + rb_define_method(c_connect, "domain_xml_to_native", + libvirt_conn_domain_xml_to_native, -1); +#endif + +#if HAVE_TYPE_VIRINTERFACEPTR + /* Interface lookup/creation methods */ + rb_define_method(c_connect, "num_of_interfaces", + libvirt_conn_num_of_interfaces, 0); + rb_define_method(c_connect, "list_interfaces", + libvirt_conn_list_interfaces, 0); + rb_define_method(c_connect, "num_of_defined_interfaces", + libvirt_conn_num_of_defined_interfaces, 0); + rb_define_method(c_connect, "list_defined_interfaces", + libvirt_conn_list_defined_interfaces, 0); + rb_define_method(c_connect, "lookup_interface_by_name", + libvirt_conn_lookup_interface_by_name, 1); + rb_define_method(c_connect, "lookup_interface_by_mac", + libvirt_conn_lookup_interface_by_mac, 1); + rb_define_method(c_connect, "define_interface_xml", + libvirt_conn_define_interface_xml, -1); +#endif + + /* Network lookup/creation methods */ + rb_define_method(c_connect, "num_of_networks", + libvirt_conn_num_of_networks, 0); + rb_define_method(c_connect, "list_networks", libvirt_conn_list_networks, 0); + rb_define_method(c_connect, "num_of_defined_networks", + libvirt_conn_num_of_defined_networks, 0); + rb_define_method(c_connect, "list_defined_networks", + libvirt_conn_list_defined_networks, 0); + rb_define_method(c_connect, "lookup_network_by_name", + libvirt_conn_lookup_network_by_name, 1); + rb_define_method(c_connect, "lookup_network_by_uuid", + libvirt_conn_lookup_network_by_uuid, 1); + rb_define_method(c_connect, "create_network_xml", + libvirt_conn_create_network_xml, 1); + rb_define_method(c_connect, "define_network_xml", + libvirt_conn_define_network_xml, 1); + + /* Node device lookup/creation methods */ +#if HAVE_TYPE_VIRNODEDEVICEPTR + rb_define_method(c_connect, "num_of_nodedevices", + libvirt_conn_num_of_nodedevices, -1); + rb_define_method(c_connect, "list_nodedevices", + libvirt_conn_list_nodedevices, -1); + rb_define_method(c_connect, "lookup_nodedevice_by_name", + libvirt_conn_lookup_nodedevice_by_name, 1); +#if HAVE_VIRNODEDEVICECREATEXML + rb_define_method(c_connect, "create_nodedevice_xml", + libvirt_conn_create_nodedevice_xml, -1); +#endif +#endif + +#if HAVE_TYPE_VIRNWFILTERPTR + /* NWFilter lookup/creation methods */ + rb_define_method(c_connect, "num_of_nwfilters", + libvirt_conn_num_of_nwfilters, 0); + rb_define_method(c_connect, "list_nwfilters", + libvirt_conn_list_nwfilters, 0); + rb_define_method(c_connect, "lookup_nwfilter_by_name", + libvirt_conn_lookup_nwfilter_by_name, 1); + rb_define_method(c_connect, "lookup_nwfilter_by_uuid", + libvirt_conn_lookup_nwfilter_by_uuid, 1); + rb_define_method(c_connect, "define_nwfilter_xml", + libvirt_conn_define_nwfilter_xml, 1); +#endif + +#if HAVE_TYPE_VIRSECRETPTR + /* Secret lookup/creation methods */ + rb_define_method(c_connect, "num_of_secrets", + libvirt_conn_num_of_secrets, 0); + rb_define_method(c_connect, "list_secrets", + libvirt_conn_list_secrets, 0); + rb_define_method(c_connect, "lookup_secret_by_uuid", + libvirt_conn_lookup_secret_by_uuid, 1); + rb_define_method(c_connect, "lookup_secret_by_usage", + libvirt_conn_lookup_secret_by_usage, 2); + rb_define_method(c_connect, "define_secret_xml", + libvirt_conn_define_secret_xml, -1); +#endif + +#if HAVE_TYPE_VIRSTORAGEPOOLPTR + /* StoragePool lookup/creation methods */ + rb_define_method(c_connect, "num_of_storage_pools", + libvirt_conn_num_of_storage_pools, 0); + rb_define_method(c_connect, "list_storage_pools", + libvirt_conn_list_storage_pools, 0); + rb_define_method(c_connect, "num_of_defined_storage_pools", + libvirt_conn_num_of_defined_storage_pools, 0); + rb_define_method(c_connect, "list_defined_storage_pools", + libvirt_conn_list_defined_storage_pools, 0); + rb_define_method(c_connect, "lookup_storage_pool_by_name", + libvirt_conn_lookup_pool_by_name, 1); + rb_define_method(c_connect, "lookup_storage_pool_by_uuid", + libvirt_conn_lookup_pool_by_uuid, 1); + rb_define_method(c_connect, "create_storage_pool_xml", + libvirt_conn_create_pool_xml, -1); + rb_define_method(c_connect, "define_storage_pool_xml", + libvirt_conn_define_pool_xml, -1); + rb_define_method(c_connect, "discover_storage_pool_sources", + libvirt_conn_find_storage_pool_sources, -1); +#endif + +#if HAVE_VIRCONNECTGETSYSINFO + rb_define_method(c_connect, "sys_info", libvirt_conn_get_sys_info, -1); +#endif +#if HAVE_TYPE_VIRSTREAMPTR + rb_define_method(c_connect, "stream", libvirt_conn_stream, -1); +#endif + +#if HAVE_VIRINTERFACECHANGEBEGIN + rb_define_method(c_connect, "interface_change_begin", + libvirt_conn_interface_change_begin, -1); + rb_define_method(c_connect, "interface_change_commit", + libvirt_conn_interface_change_commit, -1); + rb_define_method(c_connect, "interface_change_rollback", + libvirt_conn_interface_change_rollback, -1); +#endif +} diff -Nru ruby-libvirt-0.0.7/ext/libvirt/connect.h ruby-libvirt-0.4.0/ext/libvirt/connect.h --- ruby-libvirt-0.0.7/ext/libvirt/connect.h 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/connect.h 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,11 @@ +#ifndef CONNECT_H +#define CONNECT_H + +void init_connect(); + +virConnectPtr conn(VALUE s); +VALUE connect_new(virConnectPtr p); +virConnectPtr connect_get(VALUE s); +VALUE conn_attr(VALUE s); + +#endif diff -Nru ruby-libvirt-0.0.7/ext/libvirt/domain.c ruby-libvirt-0.4.0/ext/libvirt/domain.c --- ruby-libvirt-0.0.7/ext/libvirt/domain.c 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/domain.c 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,2651 @@ +/* + * domain.c: virDomain methods + * + * Copyright (C) 2007,2010 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#if HAVE_VIRDOMAINQEMUMONITORCOMMAND +#include +#endif +#include +#include "common.h" +#include "connect.h" +#include "extconf.h" +#include "stream.h" + +#ifndef HAVE_TYPE_VIRTYPEDPARAMETERPTR +#define VIR_TYPED_PARAM_INT VIR_DOMAIN_SCHED_FIELD_INT +#define VIR_TYPED_PARAM_UINT VIR_DOMAIN_SCHED_FIELD_UINT +#define VIR_TYPED_PARAM_LLONG VIR_DOMAIN_SCHED_FIELD_LLONG +#define VIR_TYPED_PARAM_ULLONG VIR_DOMAIN_SCHED_FIELD_ULLONG +#define VIR_TYPED_PARAM_DOUBLE VIR_DOMAIN_SCHED_FIELD_DOUBLE +#define VIR_TYPED_PARAM_BOOLEAN VIR_DOMAIN_SCHED_FIELD_BOOLEAN + +#define VIR_TYPED_PARAM_FIELD_LENGTH 80 +typedef struct _virTypedParameter virTypedParameter; +struct _virTypedParameter { + char field[VIR_TYPED_PARAM_FIELD_LENGTH]; /* parameter name */ + int type; /* parameter type, virTypedParameterType */ + union { + int i; /* type is INT */ + unsigned int ui; /* type is UINT */ + long long int l; /* type is LLONG */ + unsigned long long int ul; /* type is ULLONG */ + double d; /* type is DOUBLE */ + char b; /* type is BOOLEAN */ + } value; /* parameter value */ +}; +typedef virTypedParameter *virTypedParameterPtr; + +#endif + +static VALUE c_domain; +static VALUE c_domain_info; +static VALUE c_domain_ifinfo; +static VALUE c_domain_security_label; +static VALUE c_domain_block_stats; +#if HAVE_TYPE_VIRDOMAINBLOCKINFOPTR +static VALUE c_domain_block_info; +#endif +#if HAVE_TYPE_VIRDOMAINMEMORYSTATPTR +static VALUE c_domain_memory_stats; +#endif +#if HAVE_TYPE_VIRDOMAINSNAPSHOTPTR +static VALUE c_domain_snapshot; +#endif +#if HAVE_TYPE_VIRDOMAINJOBINFOPTR +static VALUE c_domain_job_info; +#endif +static VALUE c_domain_vcpuinfo; + +static void domain_free(void *d) { + generic_free(Domain, d); +} + +VALUE domain_new(virDomainPtr d, VALUE conn) { + return generic_new(c_domain, d, conn, domain_free); +} + +virDomainPtr domain_get(VALUE s) { + generic_get(Domain, s); +} + +/* + * call-seq: + * dom.migrate(dconn, flags=0, dname=nil, uri=nil, bandwidth=0) -> Libvirt::Domain + * + * Call +virDomainMigrate+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainMigrate] + * to migrate a domain from the host on this connection to the connection + * referenced in dconn. + */ +static VALUE libvirt_dom_migrate(int argc, VALUE *argv, VALUE s) { + VALUE dconn, flags, dname_val, uri_val, bandwidth; + virDomainPtr ddom = NULL; + + rb_scan_args(argc, argv, "14", &dconn, &flags, &dname_val, &uri_val, + &bandwidth); + + if (NIL_P(bandwidth)) + bandwidth = INT2NUM(0); + if (NIL_P(flags)) + flags = INT2NUM(0); + + ddom = virDomainMigrate(domain_get(s), conn(dconn), NUM2ULONG(flags), + get_string_or_nil(dname_val), + get_string_or_nil(uri_val), NUM2ULONG(bandwidth)); + + _E(ddom == NULL, create_error(e_Error, "virDomainMigrate", conn(s))); + + return domain_new(ddom, dconn); +} + +#if HAVE_VIRDOMAINMIGRATETOURI +/* + * call-seq: + * dom.migrate_to_uri(duri, flags=0, dname=nil, bandwidth=0) -> nil + * + * Call +virDomainMigrateToURI+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainMigrateToURI] + * to migrate a domain from the host on this connection to the host whose + * libvirt URI is duri. + */ +static VALUE libvirt_dom_migrate_to_uri(int argc, VALUE *argv, VALUE s) { + VALUE duri, flags, dname, bandwidth; + + rb_scan_args(argc, argv, "13", &duri, &flags, &dname, &bandwidth); + + if (NIL_P(bandwidth)) + bandwidth = INT2NUM(0); + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virDomainMigrateToURI, conn(s), domain_get(s), + StringValueCStr(duri), NUM2ULONG(flags), + get_string_or_nil(dname), NUM2ULONG(bandwidth)); +} +#endif + +#if HAVE_VIRDOMAINMIGRATESETMAXDOWNTIME +/* + * call-seq: + * dom.migrate_set_max_downtime(downtime, flags=0) -> nil + * + * Call +virDomainMigrateSetMaxDowntime+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainMigrateSetMaxDowntime] + * to set the maximum downtime desired for live migration. + */ +static VALUE libvirt_dom_migrate_set_max_downtime(int argc, VALUE *argv, + VALUE s) { + VALUE downtime, flags; + + rb_scan_args(argc, argv, "11", &downtime, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virDomainMigrateSetMaxDowntime, conn(s), domain_get(s), + NUM2ULL(downtime), NUM2UINT(flags)); +} +#endif + +#if HAVE_VIRDOMAINMIGRATE2 +/* + * call-seq: + * dom.migrate2(dconn, dxml=nil, flags=0, dname=nil, uri=nil, bandwidth=0) -> Libvirt::Domain + * + * Call +virDomainMigrate2+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainMigrate2] + * to migrate a domain from the host on this connection to the connection + * referenced in dconn. + */ +static VALUE libvirt_dom_migrate2(int argc, VALUE *argv, VALUE s) { + VALUE dconn, dxml, flags, dname_val, uri_val, bandwidth; + virDomainPtr ddom = NULL; + + rb_scan_args(argc, argv, "15", &dconn, &dxml, &flags, &dname_val, &uri_val, + &bandwidth); + + if (NIL_P(bandwidth)) + bandwidth = INT2NUM(0); + if (NIL_P(flags)) + flags = INT2NUM(0); + + ddom = virDomainMigrate2(domain_get(s), conn(dconn), + get_string_or_nil(dxml), NUM2ULONG(flags), + get_string_or_nil(dname_val), + get_string_or_nil(uri_val), NUM2ULONG(bandwidth)); + + _E(ddom == NULL, create_error(e_Error, "virDomainMigrate2", conn(s))); + + return domain_new(ddom, dconn); +} + +/* + * call-seq: + * dom.migrate_to_uri2(duri=nil, migrate_uri=nil, dxml=nil, flags=0, dname=nil, bandwidth=0) -> nil + * + * Call +virDomainMigrateToURI2+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainMigrateToURI2] + * to migrate a domain from the host on this connection to the host whose + * libvirt URI is duri. + */ +static VALUE libvirt_dom_migrate_to_uri2(int argc, VALUE *argv, VALUE s) { + VALUE duri, migrate_uri, dxml, flags, dname, bandwidth; + + rb_scan_args(argc, argv, "06", &duri, &migrate_uri, &dxml, &flags, &dname, + &bandwidth); + + if (NIL_P(bandwidth)) + bandwidth = INT2NUM(0); + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virDomainMigrateToURI2, conn(s), domain_get(s), + get_string_or_nil(duri), get_string_or_nil(migrate_uri), + get_string_or_nil(dxml), NUM2ULONG(flags), + get_string_or_nil(dname), NUM2ULONG(bandwidth)); +} + +/* + * call-seq: + * dom.migrate_set_max_speed(bandwidth, flags=0) -> nil + * + * Call +virDomainMigrateSetMaxSpeed+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainMigrateSetMaxSpeed] + * to set the maximum bandwidth allowed for live migration. + */ +static VALUE libvirt_dom_migrate_set_max_speed(int argc, VALUE *argv, VALUE s) { + VALUE bandwidth, flags; + + rb_scan_args(argc, argv, "11", &bandwidth, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virDomainMigrateSetMaxSpeed, conn(s), domain_get(s), + NUM2ULONG(bandwidth), NUM2UINT(flags)); +} +#endif + +/* + * call-seq: + * dom.shutdown -> nil + * + * Call +virDomainShutdown+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainShutdown] + * to do a soft shutdown of the domain. The mechanism for doing the shutdown + * is hypervisor specific, and may require software running inside the domain + * to succeed. + */ +static VALUE libvirt_dom_shutdown(VALUE s) { + gen_call_void(virDomainShutdown, conn(s), domain_get(s)); +} + +/* + * call-seq: + * dom.reboot(flags=0) -> nil + * + * Call +virDomainReboot+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainReboot] + * to do a reboot of the domain. + */ +static VALUE libvirt_dom_reboot(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virDomainReboot, conn(s), domain_get(s), NUM2UINT(flags)); +} + +/* + * call-seq: + * dom.destroy -> nil + * + * Call +virDomainDestroy+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainDestroy] + * to do a hard power-off of the domain. + */ +static VALUE libvirt_dom_destroy(VALUE s) { + gen_call_void(virDomainDestroy, conn(s), domain_get(s)); +} + +/* + * call-seq: + * dom.suspend -> nil + * + * Call +virDomainSuspend+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSuspend] + * to stop the domain from executing. The domain will still continue to + * consume memory, but will not take any CPU time. + */ +static VALUE libvirt_dom_suspend(VALUE s) { + gen_call_void(virDomainSuspend, conn(s), domain_get(s)); +} + +/* + * call-seq: + * dom.resume -> nil + * + * Call +virDomainResume+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainResume] + * to resume a suspended domain. After this call the domain will start + * consuming CPU resources again. + */ +static VALUE libvirt_dom_resume(VALUE s) { + gen_call_void(virDomainResume, conn(s), domain_get(s)); +} + +/* + * call-seq: + * dom.save(filename) -> nil + * + * Call +virDomainSave+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSave] + * to save the domain state to filename. After this call, the domain will no + * longer be consuming any resources. + */ +static VALUE libvirt_dom_save(VALUE s, VALUE to) { + gen_call_void(virDomainSave, conn(s), domain_get(s), StringValueCStr(to)); +} + +#if HAVE_VIRDOMAINMANAGEDSAVE +/* + * call-seq: + * dom.managed_save(flags=0) -> nil + * + * Call +virDomainManagedSave+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainManagedSave] + * to do a managed save of the domain. The domain will be saved to a place + * of libvirt's choosing. + */ +static VALUE libvirt_dom_managed_save(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virDomainManagedSave, conn(s), domain_get(s), + NUM2UINT(flags)); +} + +/* + * call-seq: + * dom.has_managed_save?(flags=0) -> [True|False] + * + * Call +virDomainHasManagedSaveImage+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainHasManagedSaveImage] + * to determine if a particular domain has a managed save image. + */ +static VALUE libvirt_dom_has_managed_save(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_truefalse(virDomainHasManagedSaveImage, conn(s), domain_get(s), + NUM2UINT(flags)); +} + +/* + * call-seq: + * dom.managed_save_remove(flags=0) -> nil + * + * Call +virDomainManagedSaveRemove+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainManagedSaveRemove] + * to remove the managed save image for a domain. + */ +static VALUE libvirt_dom_managed_save_remove(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virDomainManagedSaveRemove, conn(s), domain_get(s), + NUM2UINT(flags)); +} +#endif + +/* + * call-seq: + * dom.core_dump(filename, flags=0) -> nil + * + * Call +virDomainCoreDump+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainCoreDump] + * to do a full memory dump of the domain to filename. + */ +static VALUE libvirt_dom_core_dump(int argc, VALUE *argv, VALUE s) { + VALUE to, flags; + + rb_scan_args(argc, argv, "11", &to, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virDomainCoreDump, conn(s), domain_get(s), + StringValueCStr(to), NUM2INT(flags)); +} + +/* + * call-seq: + * dom.restore(filename) -> nil + * + * Call +virDomainRestore+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainRestore] + * to restore the domain from the filename. + */ +static VALUE libvirt_dom_restore(VALUE s, VALUE from) { + gen_call_void(virDomainRestore, conn(s), connect_get(s), + StringValueCStr(from)); +} + +/* + * call-seq: + * Libvirt::Domain::restore(conn, filename) -> nil + * + * Call +virDomainRestore+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainRestore] + * to restore the domain from the filename. + */ +static VALUE libvirt_dom_s_restore(VALUE klass, VALUE c, VALUE from) { + gen_call_void(virDomainRestore, conn(c), connect_get(c), + StringValueCStr(from)); +} + +/* + * call-seq: + * dom.info -> Libvirt::Domain::Info + * + * Call +virDomainGetInfo+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetInfo] + * to retrieve domain information. + */ +static VALUE libvirt_dom_info(VALUE s) { + virDomainPtr dom = domain_get(s); + virDomainInfo info; + int r; + VALUE result; + + r = virDomainGetInfo(dom, &info); + _E(r < 0, create_error(e_RetrieveError, "virDomainGetInfo", conn(s))); + + result = rb_class_new_instance(0, NULL, c_domain_info); + rb_iv_set(result, "@state", CHR2FIX(info.state)); + rb_iv_set(result, "@max_mem", ULONG2NUM(info.maxMem)); + rb_iv_set(result, "@memory", ULONG2NUM(info.memory)); + rb_iv_set(result, "@nr_virt_cpu", INT2NUM((int) info.nrVirtCpu)); + rb_iv_set(result, "@cpu_time", ULL2NUM(info.cpuTime)); + + return result; +} + +#if HAVE_VIRDOMAINGETSECURITYLABEL +/* + * call-seq: + * dom.security_label -> Libvirt::Domain::SecurityLabel + * + * Call +virDomainGetSecurityLabel+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetSecurityLabel] + * to retrieve the security label applied to this domain. + */ +static VALUE libvirt_dom_security_label(VALUE s) { + virDomainPtr dom = domain_get(s); + virSecurityLabel seclabel; + int r; + VALUE result; + + r = virDomainGetSecurityLabel(dom, &seclabel); + _E(r < 0, create_error(e_RetrieveError, "virDomainGetSecurityLabel", + conn(s))); + + result = rb_class_new_instance(0, NULL, c_domain_security_label); + rb_iv_set(result, "@label", rb_str_new2(seclabel.label)); + rb_iv_set(result, "@enforcing", INT2NUM(seclabel.enforcing)); + + return result; +} +#endif + +/* + * call-seq: + * dom.block_stats(path) -> Libvirt::Domain::BlockStats + * + * Call +virDomainBlockStats+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainBlockStats] + * to retrieve statistics about domain block device path. + */ +static VALUE libvirt_dom_block_stats(VALUE s, VALUE path) { + virDomainPtr dom = domain_get(s); + virDomainBlockStatsStruct stats; + int r; + VALUE result; + + r = virDomainBlockStats(dom, StringValueCStr(path), &stats, sizeof(stats)); + _E(r < 0, create_error(e_RetrieveError, "virDomainBlockStats", conn(s))); + + result = rb_class_new_instance(0, NULL, c_domain_block_stats); + rb_iv_set(result, "@rd_req", LL2NUM(stats.rd_req)); + rb_iv_set(result, "@rd_bytes", LL2NUM(stats.rd_bytes)); + rb_iv_set(result, "@wr_req", LL2NUM(stats.wr_req)); + rb_iv_set(result, "@wr_bytes", LL2NUM(stats.wr_bytes)); + rb_iv_set(result, "@errs", LL2NUM(stats.errs)); + + return result; +} + +#if HAVE_TYPE_VIRDOMAINMEMORYSTATPTR +/* + * call-seq: + * dom.memory_stats(flags=0) -> [ Libvirt::Domain::MemoryStats ] + * + * Call +virDomainMemoryStats+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainMemoryStats] + * to retrieve statistics about the amount of memory consumed by a domain. + */ +static VALUE libvirt_dom_memory_stats(int argc, VALUE *argv, VALUE s) { + virDomainPtr dom = domain_get(s); + virDomainMemoryStatStruct stats[6]; + int r; + VALUE result; + VALUE flags; + VALUE tmp; + int i; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + r = virDomainMemoryStats(dom, stats, 6, NUM2UINT(flags)); + _E(r < 0, create_error(e_RetrieveError, "virDomainMemoryStats", conn(s))); + + /* FIXME: the right rubyish way to have done this would have been to + * create a hash with the values, something like: + * + * { 'SWAP_IN' => 0, 'SWAP_OUT' => 98, 'MAJOR_FAULT' => 45, + * 'MINOR_FAULT' => 55, 'UNUSED' => 455, 'AVAILABLE' => 98 } + * + * Unfortunately this has already been released with the array version + * so we have to maintain compatibility with that. We should probably add + * a new memory_stats-like call that properly creates the hash. + */ + result = rb_ary_new2(r); + for (i=0; i Libvirt::Domain::BlockInfo + * + * Call +virDomainGetBlockInfo+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetBlockInfo] + * to retrieve information about the backing file path for the domain. + */ +static VALUE libvirt_dom_block_info(int argc, VALUE *argv, VALUE s) { + virDomainPtr dom = domain_get(s); + virDomainBlockInfo info; + int r; + VALUE result; + VALUE flags; + VALUE path; + + rb_scan_args(argc, argv, "11", &path, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + r = virDomainGetBlockInfo(dom, StringValueCStr(path), &info, + NUM2UINT(flags)); + _E(r < 0, create_error(e_RetrieveError, "virDomainGetBlockInfo", conn(s))); + + result = rb_class_new_instance(0, NULL, c_domain_block_info); + rb_iv_set(result, "@capacity", ULL2NUM(info.capacity)); + rb_iv_set(result, "@allocation", ULL2NUM(info.allocation)); + rb_iv_set(result, "@physical", ULL2NUM(info.physical)); + + return result; +} +#endif + +#if HAVE_VIRDOMAINBLOCKPEEK +/* + * call-seq: + * dom.block_peek(path, offset, size, flags=0) -> string + * + * Call +virDomainBlockPeek+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainBlockPeek] + * to read size number of bytes, starting at offset offset from domain backing + * file path. Due to limitations of the libvirt remote protocol, the user + * should never request more than 64k bytes. + */ +static VALUE libvirt_dom_block_peek(int argc, VALUE *argv, VALUE s) { + virDomainPtr dom = domain_get(s); + VALUE path_val, offset_val, size_val, flags_val; + char *buffer; + int r; + VALUE ret; + char *path; + unsigned int size, flags; + unsigned long long offset; + struct rb_str_new_arg args; + int exception = 0; + + rb_scan_args(argc, argv, "31", &path_val, &offset_val, &size_val, + &flags_val); + + if (NIL_P(flags_val)) + flags_val = INT2NUM(0); + + path = StringValueCStr(path_val); + offset = NUM2ULL(offset_val); + size = NUM2UINT(size_val); + flags = NUM2UINT(flags_val); + + buffer = ALLOC_N(char, size); + + r = virDomainBlockPeek(dom, path, offset, size, buffer, flags); + + if (r < 0) { + xfree(buffer); + rb_exc_raise(create_error(e_RetrieveError, "virDomainBlockPeek", + conn(s))); + } + + args.val = buffer; + args.size = size; + ret = rb_protect(rb_str_new_wrap, (VALUE)&args, &exception); + xfree(buffer); + if (exception) + rb_jump_tag(exception); + + return ret; +} +#endif + +#if HAVE_VIRDOMAINMEMORYPEEK +/* + * call-seq: + * dom.memory_peek(start, size, flags=Libvirt::Domain::MEMORY_VIRTUAL) -> string + * + * Call +virDomainMemoryPeek+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainMemoryPeek] + * to read size number of bytes from offset start from the domain memory. + * Due to limitations of the libvirt remote protocol, the user + * should never request more than 64k bytes. + */ +static VALUE libvirt_dom_memory_peek(int argc, VALUE *argv, VALUE s) { + virDomainPtr dom = domain_get(s); + VALUE start_val, size_val, flags_val; + char *buffer; + int r; + VALUE ret; + unsigned int size, flags; + unsigned long long start; + struct rb_str_new_arg args; + int exception = 0; + + rb_scan_args(argc, argv, "21", &start_val, &size_val, &flags_val); + + if (NIL_P(flags_val)) + flags_val = INT2NUM(VIR_MEMORY_VIRTUAL); + + start = NUM2UINT(start_val); + size = NUM2UINT(size_val); + flags = NUM2UINT(flags_val); + + buffer = ALLOC_N(char, size); + + r = virDomainMemoryPeek(dom, start, size, buffer, flags); + + if (r < 0) { + xfree(buffer); + rb_exc_raise(create_error(e_RetrieveError, "virDomainMemoryPeek", + conn(s))); + } + + args.val = buffer; + args.size = size; + ret = rb_protect(rb_str_new_wrap, (VALUE)&args, &exception); + xfree(buffer); + if (exception) + rb_jump_tag(exception); + + return ret; +} +#endif + +struct create_vcpu_array_args { + virVcpuInfoPtr cpuinfo; + unsigned char *cpumap; + int nr_virt_cpu; + int maxcpus; +}; + +static VALUE create_vcpu_array(VALUE input) { + struct create_vcpu_array_args *args; + VALUE result; + int i; + VALUE vcpuinfo; + VALUE p2vcpumap; + int j; + + args = (struct create_vcpu_array_args *)input; + + result = rb_ary_new(); + + for (i = 0; i < args->nr_virt_cpu; i++) { + vcpuinfo = rb_class_new_instance(0, NULL, c_domain_vcpuinfo); + rb_iv_set(vcpuinfo, "@number", UINT2NUM((args->cpuinfo)[i].number)); + rb_iv_set(vcpuinfo, "@state", INT2NUM((args->cpuinfo)[i].state)); + rb_iv_set(vcpuinfo, "@cpu_time", ULL2NUM((args->cpuinfo)[i].cpuTime)); + rb_iv_set(vcpuinfo, "@cpu", INT2NUM((args->cpuinfo)[i].cpu)); + + p2vcpumap = rb_ary_new(); + + for (j = 0; j < args->maxcpus; j++) + rb_ary_push(p2vcpumap, + (VIR_CPU_USABLE(args->cpumap, + VIR_CPU_MAPLEN(args->maxcpus), i, j)) ? Qtrue : Qfalse); + rb_iv_set(vcpuinfo, "@cpumap", p2vcpumap); + + rb_ary_push(result, vcpuinfo); + } + + return result; +} + +/* call-seq: + * dom.get_vcpus -> [ Libvirt::Domain::VCPUInfo ] + * + * Call +virDomainGetVcpus+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetVcpus] + * to retrieve detailed information about the state of a domain's virtual CPUs. + */ +static VALUE libvirt_dom_get_vcpus(VALUE s) { + virDomainPtr dom = domain_get(s); + virNodeInfo nodeinfo; + virDomainInfo dominfo; + virVcpuInfoPtr cpuinfo; + unsigned char *cpumap; + int cpumaplen; + int r; + VALUE result; + int exception = 0; + struct create_vcpu_array_args args; + + r = virNodeGetInfo(conn(s), &nodeinfo); + _E(r < 0, create_error(e_RetrieveError, "virNodeGetInfo", conn(s))); + + r = virDomainGetInfo(dom, &dominfo); + _E(r < 0, create_error(e_RetrieveError, "virDomainGetInfo", conn(s))); + + cpuinfo = ALLOC_N(virVcpuInfo, dominfo.nrVirtCpu); + + cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo)); + + /* we use malloc instead of ruby_xmalloc here to avoid a memory leak + * if ruby_xmalloc raises an exception + */ + cpumap = malloc(dominfo.nrVirtCpu * cpumaplen); + if (cpumap == NULL) { + xfree(cpuinfo); + rb_memerror(); + } + + r = virDomainGetVcpus(dom, cpuinfo, dominfo.nrVirtCpu, cpumap, cpumaplen); + if (r < 0) { + xfree(cpuinfo); + free(cpumap); + rb_exc_raise(create_error(e_RetrieveError, "virDomainGetVcpus", + conn(s))); + } + + args.cpuinfo = cpuinfo; + args.cpumap = cpumap; + args.nr_virt_cpu = dominfo.nrVirtCpu; + args.maxcpus = VIR_NODEINFO_MAXCPUS(nodeinfo); + result = rb_protect(create_vcpu_array, (VALUE)&args, &exception); + if (exception) { + xfree(cpuinfo); + free(cpumap); + rb_jump_tag(exception); + } + + free(cpumap); + xfree(cpuinfo); + + return result; +} + +#if HAVE_VIRDOMAINISACTIVE +/* + * call-seq: + * dom.active? -> [true|false] + * + * Call +virDomainIsActive+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainIsActive] + * to determine if this domain is currently active. + */ +static VALUE libvirt_dom_active_p(VALUE d) { + gen_call_truefalse(virDomainIsActive, conn(d), domain_get(d)); +} +#endif + +#if HAVE_VIRDOMAINISPERSISTENT +/* + * call-seq: + * dom.persistent? -> [true|false] + * + * Call +virDomainIsPersistent+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainIsPersistent] + * to determine if this is a persistent domain. + */ +static VALUE libvirt_dom_persistent_p(VALUE d) { + gen_call_truefalse(virDomainIsPersistent, conn(d), domain_get(d)); +} +#endif + +/* + * call-seq: + * dom.ifinfo(if) -> Libvirt::Domain::IfInfo + * + * Call +virDomainInterfaceStats+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainInterfaceStats] + * to retrieve statistics about domain interface if. + */ +static VALUE libvirt_dom_if_stats(VALUE s, VALUE sif) { + virDomainPtr dom = domain_get(s); + char *ifname = get_string_or_nil(sif); + virDomainInterfaceStatsStruct ifinfo; + int r; + VALUE result = Qnil; + + if (ifname) { + r = virDomainInterfaceStats(dom, ifname, &ifinfo, + sizeof(virDomainInterfaceStatsStruct)); + _E(r < 0, create_error(e_RetrieveError, "virDomainInterfaceStats", + conn(s))); + + result = rb_class_new_instance(0, NULL, c_domain_ifinfo); + rb_iv_set(result, "@rx_bytes", LL2NUM(ifinfo.rx_bytes)); + rb_iv_set(result, "@rx_packets", LL2NUM(ifinfo.rx_packets)); + rb_iv_set(result, "@rx_errs", LL2NUM(ifinfo.rx_errs)); + rb_iv_set(result, "@rx_drop", LL2NUM(ifinfo.rx_drop)); + rb_iv_set(result, "@tx_bytes", LL2NUM(ifinfo.tx_bytes)); + rb_iv_set(result, "@tx_packets", LL2NUM(ifinfo.tx_packets)); + rb_iv_set(result, "@tx_errs", LL2NUM(ifinfo.tx_errs)); + rb_iv_set(result, "@tx_drop", LL2NUM(ifinfo.tx_drop)); + } + return result; +} + +/* + * call-seq: + * dom.name -> string + * + * Call +virDomainGetName+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetName] + * to retrieve the name of this domain. + */ +static VALUE libvirt_dom_name(VALUE s) { + gen_call_string(virDomainGetName, conn(s), 0, domain_get(s)); +} + +/* + * call-seq: + * dom.id -> fixnum + * + * Call +virDomainGetID+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetID] + * to retrieve the ID of this domain. If the domain isn't running, this will + * be -1. + */ +static VALUE libvirt_dom_id(VALUE s) { + virDomainPtr dom = domain_get(s); + unsigned int id; + int out; + + id = virDomainGetID(dom); + + /* we need to cast the unsigned int id to a signed int out to handle the + * -1 case + */ + out = id; + _E(out == -1, create_error(e_RetrieveError, "virDomainGetID", conn(s))); + + return INT2NUM(out); +} + +/* + * call-seq: + * dom.uuid -> string + * + * Call +virDomainGetUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetUUIDString] + * to retrieve the UUID of this domain. + */ +static VALUE libvirt_dom_uuid(VALUE s) { + virDomainPtr dom = domain_get(s); + char uuid[VIR_UUID_STRING_BUFLEN]; + int r; + + r = virDomainGetUUIDString(dom, uuid); + _E(r < 0, create_error(e_RetrieveError, "virDomainGetUUIDString", conn(s))); + + return rb_str_new2((char *) uuid); +} + +/* + * call-seq: + * dom.os_type -> string + * + * Call +virDomainGetOSType+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetOSType] + * to retrieve the os_type of this domain. In libvirt terms, os_type determines + * whether this domain is fully virtualized, paravirtualized, or a container. + */ +static VALUE libvirt_dom_os_type(VALUE s) { + gen_call_string(virDomainGetOSType, conn(s), 1, domain_get(s)); +} + +/* + * call-seq: + * dom.max_memory -> fixnum + * + * Call +virDomainGetMaxMemory+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetMaxMemory] + * to retrieve the maximum amount of memory this domain is allowed to access. + * Note that the current amount of memory this domain is allowed to access may + * be different (see dom.memory_set). + */ +static VALUE libvirt_dom_max_memory(VALUE s) { + virDomainPtr dom = domain_get(s); + unsigned long max_memory; + + max_memory = virDomainGetMaxMemory(dom); + _E(max_memory == 0, create_error(e_RetrieveError, "virDomainGetMaxMemory", + conn(s))); + + return ULONG2NUM(max_memory); +} + +/* + * call-seq: + * dom.max_memory = Fixnum + * + * Call +virDomainSetMaxMemory+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetMaxMemory] + * to set the maximum amount of memory (in kilobytes) this domain should be + * allowed to access. + */ +static VALUE libvirt_dom_max_memory_set(VALUE s, VALUE max_memory) { + virDomainPtr dom = domain_get(s); + int r; + + r = virDomainSetMaxMemory(dom, NUM2ULONG(max_memory)); + _E(r < 0, create_error(e_DefinitionError, "virDomainSetMaxMemory", + conn(s))); + + return ULONG2NUM(max_memory); +} + +/* + * call-seq: + * dom.memory = Fixnum,flags=0 + * + * Call +virDomainSetMemory+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetMemory] + * to set the amount of memory (in kilobytes) this domain should currently + * have. Note this will only succeed if both the hypervisor and the domain on + * this connection support ballooning. + */ +static VALUE libvirt_dom_memory_set(VALUE s, VALUE in) { + VALUE memory; + VALUE flags; + virDomainPtr dom = domain_get(s); + int r; + + if (TYPE(in) == T_FIXNUM) { + memory = in; + flags = INT2NUM(0); + } + else if (TYPE(in) == T_ARRAY) { + if (RARRAY_LEN(in) != 2) + rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", + RARRAY_LEN(in)); + memory = rb_ary_entry(in, 0); + flags = rb_ary_entry(in, 1); + } + else + rb_raise(rb_eTypeError, + "wrong argument type (expected Number or Array)"); + +#if HAVE_VIRDOMAINSETMEMORYFLAGS + r = virDomainSetMemoryFlags(dom, NUM2ULONG(memory), NUM2UINT(flags)); + _E(r < 0, create_error(e_DefinitionError, "virDomainSetMemoryFlags", + conn(s))); +#else + if (NUM2UINT(flags) != 0) + rb_raise(e_NoSupportError, "Non-zero flags not supported"); + r = virDomainSetMemory(dom, NUM2ULONG(memory)); + _E(r < 0, create_error(e_DefinitionError, "virDomainSetMemory", conn(s))); +#endif + + return ULONG2NUM(memory); +} + +/* + * call-seq: + * dom.max_vcpus -> fixnum + * + * Call +virDomainGetMaxVcpus+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetMaxVcpus] + * to retrieve the maximum number of virtual CPUs this domain can use. + */ +static VALUE libvirt_dom_max_vcpus(VALUE s) { + gen_call_int(virDomainGetMaxVcpus, conn(s), domain_get(s)); +} + +#if HAVE_VIRDOMAINGETVCPUSFLAGS +/* call-seq: + * dom.num_vcpus(flags) -> fixnum + * + * Call +virDomainGetVcpusFlags+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetVcpusFlags] + * to retrieve the number of virtual CPUs assigned to this domain. + */ +static VALUE libvirt_dom_num_vcpus(VALUE d, VALUE flags) { + gen_call_int(virDomainGetVcpusFlags, conn(d), domain_get(d), + NUM2UINT(flags)); +} +#endif + +/* + * call-seq: + * dom.vcpus = Fixnum + * + * Call +virDomainSetVcpus+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetVcpus] + * to set the current number of virtual CPUs this domain should have. Note + * that this will only work if both the hypervisor and domain on this + * connection support virtual CPU hotplug/hot-unplug. + */ +static VALUE libvirt_dom_vcpus_set(VALUE s, VALUE nvcpus) { + gen_call_void(virDomainSetVcpus, conn(s), domain_get(s), NUM2UINT(nvcpus)); +} + +#if HAVE_VIRDOMAINSETVCPUSFLAGS +/* + * call-seq: + * dom.vcpus_flags = Fixnum,flags + * + * Call +virDomainSetVcpusFlags+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetVcpusFlags] + * to set the current number of virtual CPUs this domain should have. The + * flags parameter controls whether the change is made to the running domain + * the domain configuration, or both, and must not be 0. + */ +static VALUE libvirt_dom_vcpus_set_flags(VALUE s, VALUE vcpus) { + VALUE nvcpus; + VALUE flags; + + Check_Type(vcpus, T_ARRAY); + + if (RARRAY_LEN(vcpus) != 2) + rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", + RARRAY_LEN(vcpus)); + + nvcpus = rb_ary_entry(vcpus, 0); + flags = rb_ary_entry(vcpus, 1); + + gen_call_void(virDomainSetVcpusFlags, conn(s), domain_get(s), + NUM2UINT(nvcpus), NUM2UINT(flags)); +} +#endif + +/* + * call-seq: + * dom.pin_vcpu(vcpu, cpulist) -> nil + * + * Call +virDomainPinVcpu+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainPinVcpu] + * to pin a particular virtual CPU to a range of physical processors. The + * cpulist should be an array of Fixnums representing the physical processors + * this virtual CPU should be allowed to be scheduled on. + */ +static VALUE libvirt_dom_pin_vcpu(VALUE s, VALUE vcpu, VALUE cpulist) { + virDomainPtr dom = domain_get(s); + int r, i, len, maplen; + unsigned char *cpumap; + virNodeInfo nodeinfo; + virConnectPtr c = conn(s); + unsigned int vcpunum; + + vcpunum = NUM2UINT(vcpu); + Check_Type(cpulist, T_ARRAY); + + r = virNodeGetInfo(c, &nodeinfo); + _E(r < 0, create_error(e_RetrieveError, "virNodeGetInfo", c)); + + maplen = VIR_CPU_MAPLEN(nodeinfo.cpus); + cpumap = ALLOC_N(unsigned char, maplen); + MEMZERO(cpumap, unsigned char, maplen); + + len = RARRAY_LEN(cpulist); + for(i = 0; i < len; i++) { + VALUE e = rb_ary_entry(cpulist, i); + VIR_USE_CPU(cpumap, NUM2UINT(e)); + } + + r = virDomainPinVcpu(dom, vcpunum, cpumap, maplen); + xfree(cpumap); + _E(r < 0, create_error(e_RetrieveError, "virDomainPinVcpu", c)); + + return Qnil; +} + +/* + * call-seq: + * dom.xml_desc(flags=0) -> string + * + * Call +virDomainGetXMLDesc+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetXMLDesc] + * to retrieve the XML describing this domain. + */ +static VALUE libvirt_dom_xml_desc(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_string(virDomainGetXMLDesc, conn(s), 1, domain_get(s), + NUM2INT(flags)); +} + +/* + * call-seq: + * dom.undefine -> nil + * + * Call +virDomainUndefine+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainUndefine] + * to undefine the domain. After this call, the domain object is no longer + * valid. + */ +static VALUE libvirt_dom_undefine(VALUE s) { + gen_call_void(virDomainUndefine, conn(s), domain_get(s)); +} + +/* + * call-seq: + * dom.create(flags=0) -> nil + * + * Call +virDomainCreate+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainCreate] + * to start an already defined domain. + */ +static VALUE libvirt_dom_create(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + +#if HAVE_VIRDOMAINCREATEWITHFLAGS + gen_call_void(virDomainCreateWithFlags, conn(s), domain_get(s), + NUM2UINT(flags)); +#else + if (NUM2UINT(flags) != 0) + rb_raise(e_NoSupportError, "Non-zero flags not supported"); + gen_call_void(virDomainCreate, conn(s), domain_get(s)); +#endif +} + +/* + * call-seq: + * dom.autostart -> [true|false] + * + * Call +virDomainGetAutostart+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetAutostart] + * to find out the state of the autostart flag for a domain. + */ +static VALUE libvirt_dom_autostart(VALUE s){ + virDomainPtr dom = domain_get(s); + int r, autostart; + + r = virDomainGetAutostart(dom, &autostart); + _E(r < 0, create_error(e_RetrieveError, "virDomainAutostart", conn(s))); + + return autostart ? Qtrue : Qfalse; +} + +/* + * call-seq: + * dom.autostart = [true|false] + * + * Call +virDomainSetAutostart+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetAutostart] + * to make this domain autostart when libvirtd starts up. + */ +static VALUE libvirt_dom_autostart_set(VALUE s, VALUE autostart) { + if (autostart != Qtrue && autostart != Qfalse) + rb_raise(rb_eTypeError, + "wrong argument type (expected TrueClass or FalseClass)"); + + gen_call_void(virDomainSetAutostart, conn(s), + domain_get(s), RTEST(autostart) ? 1 : 0); +} + +/* + * call-seq: + * dom.attach_device(device_xml, flags=0) -> nil + * + * Call +virDomainAttachDevice+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainAttachDevice] + * to attach the device described by the device_xml to the domain. + */ +static VALUE libvirt_dom_attach_device(int argc, VALUE *argv, VALUE s) { + VALUE xml; + VALUE flags; + + rb_scan_args(argc, argv, "11", &xml, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + +#if HAVE_VIRDOMAINATTACHDEVICEFLAGS + gen_call_void(virDomainAttachDeviceFlags, conn(s), domain_get(s), + StringValueCStr(xml), NUM2UINT(flags)); +#else + if (NUM2UINT(flags) != 0) + rb_raise(e_NoSupportError, "Non-zero flags not supported"); + gen_call_void(virDomainAttachDevice, conn(s), domain_get(s), + StringValueCStr(xml)); +#endif +} + +/* + * call-seq: + * dom.detach_device(device_xml, flags=0) -> nil + * + * Call +virDomainDetachDevice+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainDetachDevice] + * to detach the device described by the device_xml from the domain. + */ +static VALUE libvirt_dom_detach_device(int argc, VALUE *argv, VALUE s) { + VALUE xml; + VALUE flags; + + rb_scan_args(argc, argv, "11", &xml, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + +#if HAVE_VIRDOMAINDETACHDEVICEFLAGS + gen_call_void(virDomainDetachDeviceFlags, conn(s), domain_get(s), + StringValueCStr(xml), NUM2UINT(flags)); +#else + if (NUM2UINT(flags) != 0) + rb_raise(e_NoSupportError, "Non-zero flags not supported"); + gen_call_void(virDomainDetachDevice, conn(s), domain_get(s), + StringValueCStr(xml)); +#endif +} + +#if HAVE_VIRDOMAINUPDATEDEVICEFLAGS +/* + * call-seq: + * dom.update_device(device_xml, flags=0) -> nil + * + * Call +virDomainUpdateDeviceFlags+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainUpdateDeviceFlags] + * to update the device described by the device_xml. + */ +static VALUE libvirt_dom_update_device(int argc, VALUE *argv, VALUE s) { + VALUE xml; + VALUE flags; + + rb_scan_args(argc, argv, "11", &xml, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virDomainUpdateDeviceFlags, conn(s), domain_get(s), + StringValueCStr(xml), NUM2UINT(flags)); +} +#endif + +/* + * call-seq: + * dom.free -> nil + * + * Call +virDomainFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainFree] + * to free a domain object. + */ +static VALUE libvirt_dom_free(VALUE s) { + gen_call_free(Domain, s); +} + +#if HAVE_TYPE_VIRDOMAINSNAPSHOTPTR +static void domain_snapshot_free(void *d) { + generic_free(DomainSnapshot, d); +} + +static VALUE domain_snapshot_new(virDomainSnapshotPtr d, VALUE domain) { + VALUE result; + result = Data_Wrap_Struct(c_domain_snapshot, NULL, domain_snapshot_free, d); + rb_iv_set(result, "@domain", domain); + return result; +} + +static virDomainSnapshotPtr domain_snapshot_get(VALUE s) { + generic_get(DomainSnapshot, s); +} + +/* + * call-seq: + * dom.snapshot_create_xml(snapshot_xml, flags=0) -> Libvirt::Domain::Snapshot + * + * Call +virDomainSnapshotCreateXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotCreateXML] + * to create a new snapshot based on snapshot_xml. + */ +static VALUE libvirt_dom_snapshot_create_xml(int argc, VALUE *argv, VALUE d) { + VALUE xmlDesc, flags; + virDomainSnapshotPtr ret; + + rb_scan_args(argc, argv, "11", &xmlDesc, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + ret = virDomainSnapshotCreateXML(domain_get(d), StringValueCStr(xmlDesc), + NUM2UINT(flags)); + + _E(ret == NULL, create_error(e_Error, "virDomainSnapshotCreateXML", + conn(d))); + + return domain_snapshot_new(ret, d); +} + +/* + * call-seq: + * dom.num_of_snapshots(flags=0) -> fixnum + * + * Call +virDomainSnapshotNum+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotNum] + * to retrieve the number of available snapshots for this domain. + */ +static VALUE libvirt_dom_num_of_snapshots(int argc, VALUE *argv, VALUE d) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_int(virDomainSnapshotNum, conn(d), domain_get(d), + NUM2UINT(flags)); +} + +/* + * call-seq: + * dom.list_snapshots(flags=0) -> list + * + * Call +virDomainSnapshotListNames+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotListNames] + * to retrieve a list of snapshot names available for this domain. + */ +static VALUE libvirt_dom_list_snapshots(int argc, VALUE *argv, VALUE d) { + VALUE flags_val; + int r; + int num; + virDomainPtr dom = domain_get(d); + char **names; + unsigned int flags; + + rb_scan_args(argc, argv, "01", &flags_val); + + if (NIL_P(flags_val)) + flags = 0; + else + flags = NUM2UINT(flags_val); + + num = virDomainSnapshotNum(dom, 0); + _E(num < 0, create_error(e_RetrieveError, "virDomainSnapshotNum", conn(d))); + if (num == 0) + /* if num is 0, don't call virDomainSnapshotListNames function */ + return rb_ary_new2(num); + + names = ALLOC_N(char *, num); + + r = virDomainSnapshotListNames(domain_get(d), names, num, flags); + if (r < 0) { + xfree(names); + rb_exc_raise(create_error(e_RetrieveError, "virDomainSnapshotListNames", + conn(d))); + } + + return gen_list(num, &names); +} + +/* + * call-seq: + * dom.lookup_snapshot_by_name(name, flags=0) -> Libvirt::Domain::Snapshot + * + * Call +virDomainSnapshotLookupByName+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotLookupByName] + * to retrieve a snapshot object corresponding to snapshot name. + */ +static VALUE libvirt_dom_lookup_snapshot_by_name(int argc, VALUE *argv, VALUE d) { + virDomainPtr dom = domain_get(d); + virDomainSnapshotPtr snap; + VALUE name, flags; + + rb_scan_args(argc, argv, "11", &name, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + snap = virDomainSnapshotLookupByName(dom, StringValueCStr(name), + NUM2UINT(flags)); + _E(dom == NULL, create_error(e_RetrieveError, + "virDomainSnapshotLookupByName", conn(d))); + + return domain_snapshot_new(snap, d); +} + +/* + * call-seq: + * dom.has_current_snapshot?(flags=0) -> [true|false] + * + * Call +virDomainHasCurrentSnapshot+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainHasCurrentSnapshot] + * to find out if this domain has a snapshot active. + */ +static VALUE libvirt_dom_has_current_snapshot_p(int argc, VALUE *argv, VALUE d) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_truefalse(virDomainHasCurrentSnapshot, conn(d), domain_get(d), + NUM2UINT(flags)); +} + +/* + * call-seq: + * dom.revert_to_snapshot(snapshot_object, flags=0) -> nil + * + * Call +virDomainRevertToSnapshot+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainRevertToSnapshot] + * to restore this domain to a previously saved snapshot. + */ +static VALUE libvirt_dom_revert_to_snapshot(int argc, VALUE *argv, VALUE d) { + VALUE snap, flags; + + rb_scan_args(argc, argv, "11", &snap, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virDomainRevertToSnapshot, conn(d), + domain_snapshot_get(snap), NUM2UINT(flags)); +} + +/* + * call-seq: + * dom.current_snapshot(flags=0) -> Libvirt::Domain::Snapshot + * + * Call +virDomainCurrentSnapshot+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainCurrentSnapshot] + * to retrieve the current snapshot for this domain (if any). + */ +static VALUE libvirt_dom_current_snapshot(int argc, VALUE *argv, VALUE d) { + VALUE flags; + virDomainSnapshotPtr snap; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + snap = virDomainSnapshotCurrent(domain_get(d), NUM2UINT(flags)); + _E(snap == NULL, create_error(e_RetrieveError, "virDomainSnapshotCurrent", + conn(d))); + + return domain_snapshot_new(snap, d); +} + +/* + * call-seq: + * snapshot.xml_desc(flags=0) -> string + * + * Call +virDomainSnapshotGetXMLDesc+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotGetXMLDesc] + * to retrieve the xml description for this snapshot. + */ +static VALUE libvirt_dom_snapshot_xml_desc(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_string(virDomainSnapshotGetXMLDesc, conn(s), 1, + domain_snapshot_get(s), NUM2UINT(flags)); +} + +/* + * call-seq: + * snapshot.delete(flags=0) -> nil + * + * Call +virDomainSnapshotDelete+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotDelete] + * to delete this snapshot. + */ +static VALUE libvirt_dom_snapshot_delete(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virDomainSnapshotDelete, conn(s), + domain_snapshot_get(s), NUM2UINT(flags)); +} + +/* + * call-seq: + * snapshot.free -> nil + * + * Call +virDomainSnapshotFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotFree] + * to free up the snapshot object. After this call the snapshot object is + * no longer valid. + */ +static VALUE libvirt_dom_snapshot_free(VALUE s) { + gen_call_free(DomainSnapshot, s); +} + +#endif + +#if HAVE_TYPE_VIRDOMAINJOBINFOPTR +/* + * call-seq: + * dom.job_info -> Libvirt::Domain::JobInfo + * + * Call +virDomainGetJobInfo+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetJobInfo] + * to retrieve the current state of the running domain job. + */ +static VALUE libvirt_dom_job_info(VALUE d) { + int r; + virDomainJobInfo info; + VALUE result; + + r = virDomainGetJobInfo(domain_get(d), &info); + _E(r < 0, create_error(e_RetrieveError, "virDomainGetJobInfo", conn(d))); + + result = rb_class_new_instance(0, NULL, c_domain_job_info); + rb_iv_set(result, "@type", INT2NUM(info.type)); + rb_iv_set(result, "@time_elapsed", ULL2NUM(info.timeElapsed)); + rb_iv_set(result, "@time_remaining", ULL2NUM(info.timeRemaining)); + rb_iv_set(result, "@data_total", ULL2NUM(info.dataTotal)); + rb_iv_set(result, "@data_processed", ULL2NUM(info.dataProcessed)); + rb_iv_set(result, "@data_remaining", ULL2NUM(info.dataRemaining)); + rb_iv_set(result, "@mem_total", ULL2NUM(info.memTotal)); + rb_iv_set(result, "@mem_processed", ULL2NUM(info.memProcessed)); + rb_iv_set(result, "@mem_remaining", ULL2NUM(info.memRemaining)); + rb_iv_set(result, "@file_total", ULL2NUM(info.fileTotal)); + rb_iv_set(result, "@file_processed", ULL2NUM(info.fileProcessed)); + rb_iv_set(result, "@file_remaining", ULL2NUM(info.fileRemaining)); + + return result; +} + +/* + * call-seq: + * dom.abort_job -> nil + * + * Call +virDomainAbortJob+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainAbortJob] + * to abort the currently running job on this domain. + */ +static VALUE libvirt_dom_abort_job(VALUE d) { + gen_call_void(virDomainAbortJob, conn(d), domain_get(d)); +} + +#endif + +struct create_sched_type_args { + char *type; + int nparams; +}; + +static VALUE create_sched_type_array(VALUE input) { + struct create_sched_type_args *args; + VALUE result; + + args = (struct create_sched_type_args *)input; + + result = rb_ary_new(); + rb_ary_push(result, rb_str_new2(args->type)); + rb_ary_push(result, INT2NUM(args->nparams)); + + return result; +} + +/* + * call-seq: + * dom.scheduler_type -> [type, #params] + * + * Call +virDomainGetSchedulerType+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetSchedulerType] + * to retrieve the scheduler type used on this domain. + */ +static VALUE libvirt_dom_scheduler_type(VALUE d) { + int nparams; + char *type; + VALUE result; + int exception = 0; + struct create_sched_type_args args; + + type = virDomainGetSchedulerType(domain_get(d), &nparams); + + _E(type == NULL, create_error(e_RetrieveError, "virDomainGetSchedulerType", + conn(d))); + + args.type = type; + args.nparams = nparams; + result = rb_protect(create_sched_type_array, (VALUE)&args, &exception); + if (exception) { + free(type); + rb_jump_tag(exception); + } + + return result; +} + +#if HAVE_VIRDOMAINQEMUMONITORCOMMAND +/* + * call-seq: + * dom.qemu_monitor_command(cmd, flags=0) -> string + * + * Call virDomainQemuMonitorCommand + * to send a qemu command directly to the monitor. Note that this will only + * work on qemu hypervisors, and the input and output formats are not + * guaranteed to be stable. Also note that using this command can severly + * impede libvirt's ability to manage the domain; use with caution! + */ +static VALUE libvirt_dom_qemu_monitor_command(int argc, VALUE *argv, VALUE d) { + VALUE cmd, flags; + char *result; + VALUE ret; + int exception; + virConnectPtr c; + const char *type; + int r; + + rb_scan_args(argc, argv, "11", &cmd, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + c = conn(d); + type = virConnectGetType(c); + _E(type == NULL, create_error(e_Error, "virConnectGetType", c)); + if (strcmp(type, "QEMU") != 0) + rb_raise(rb_eTypeError, + "Tried to use virDomainQemuMonitor command on %s connection", + type); + + r = virDomainQemuMonitorCommand(domain_get(d), StringValueCStr(cmd), + &result, NUM2UINT(flags)); + _E(r < 0, create_error(e_RetrieveError, "virDomainQemuMonitorCommand", c)); + + ret = rb_protect(rb_str_new2_wrap, (VALUE)&result, &exception); + free(result); + if (exception) + rb_jump_tag(exception); + + return ret; +} +#endif + +#if HAVE_VIRDOMAINISUPDATED +/* + * call-seq: + * dom.updated? -> [True|False] + * Call +virDomainIsUpdated+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainIsUpdated] + * to determine whether the definition for this domain has been updated. + */ +static VALUE libvirt_dom_is_updated(VALUE d) { + gen_call_truefalse(virDomainIsUpdated, conn(d), domain_get(d)); +} +#endif + +struct field_to_value { + VALUE result; + virTypedParameterPtr param; +}; + +static VALUE typed_field_to_value(VALUE input) { + struct field_to_value *ftv = (struct field_to_value *)input; + VALUE val; + + switch(ftv->param->type) { + case VIR_TYPED_PARAM_INT: + val = INT2NUM(ftv->param->value.i); + break; + case VIR_TYPED_PARAM_UINT: + val = UINT2NUM(ftv->param->value.ui); + break; + case VIR_TYPED_PARAM_LLONG: + val = LL2NUM(ftv->param->value.l); + break; + case VIR_TYPED_PARAM_ULLONG: + val = ULL2NUM(ftv->param->value.ul); + break; + case VIR_TYPED_PARAM_DOUBLE: + val = rb_float_new(ftv->param->value.d); + break; + case VIR_TYPED_PARAM_BOOLEAN: + val = (ftv->param->value.b == 0) ? Qfalse : Qtrue; + break; + default: + rb_raise(rb_eArgError, "Invalid parameter type"); + } + + rb_hash_aset(ftv->result, rb_str_new2(ftv->param->field), val); + + return Qnil; +} + +static VALUE internal_get_parameters(int argc, VALUE *argv, VALUE d, + int (*nparams_cb)(VALUE d, + unsigned int flags), + char *(*get_cb)(VALUE d, + unsigned int flags, + virTypedParameterPtr params, + int *nparams)) { + int nparams; + virTypedParameterPtr params; + VALUE result; + int i; + int exception; + char *errname; + struct field_to_value ftv; + unsigned int flags; + VALUE flags_val; + + rb_scan_args(argc, argv, "01", &flags_val); + + if (NIL_P(flags_val)) + flags = 0; + else + flags = NUM2UINT(flags_val); + + nparams = nparams_cb(d, flags); + + result = rb_hash_new(); + + if (nparams == 0) + return result; + + params = ALLOC_N(virTypedParameter, nparams); + + errname = get_cb(d, flags, params, &nparams); + if (errname != NULL) { + xfree(params); + rb_exc_raise(create_error(e_RetrieveError, errname, conn(d))); + } + + for (i = 0; i < nparams; i++) { + ftv.result = result; + ftv.param = ¶ms[i]; + rb_protect(typed_field_to_value, (VALUE)&ftv, &exception); + if (exception) { + xfree(params); + rb_jump_tag(exception); + } + } + + xfree(params); + + return result; +} + +struct value_to_field { + virTypedParameterPtr param; + VALUE input; +}; + +static VALUE typed_value_to_field(VALUE in) { + struct value_to_field *vtf = (struct value_to_field *)in; + VALUE val; + + val = rb_hash_aref(vtf->input, rb_str_new2(vtf->param->field)); + if (NIL_P(val)) + return Qnil; + + switch(vtf->param->type) { + case VIR_TYPED_PARAM_INT: + vtf->param->value.i = NUM2INT(val); + break; + case VIR_TYPED_PARAM_UINT: + vtf->param->value.ui = NUM2UINT(val); + break; + case VIR_TYPED_PARAM_LLONG: + vtf->param->value.l = NUM2LL(val); + break; + case VIR_TYPED_PARAM_ULLONG: + vtf->param->value.ul = NUM2ULL(val); + break; + case VIR_TYPED_PARAM_DOUBLE: + vtf->param->value.d = NUM2DBL(val); + break; + case VIR_TYPED_PARAM_BOOLEAN: + vtf->param->value.b = (val == Qtrue) ? 1 : 0; + break; + default: + rb_raise(rb_eArgError, "Invalid parameter type"); + } + + return Qnil; +} + +static VALUE internal_set_parameters(VALUE d, VALUE in, + int (*nparams_cb)(VALUE d, + unsigned int flags), + char *(*get_cb)(VALUE d, + unsigned int flags, + virTypedParameterPtr params, + int *nparams), + char *(*set_cb)(VALUE d, + unsigned int flags, + virTypedParameterPtr params, + int nparams)) { + int nparams; + virTypedParameterPtr params; + int exception; + int i; + char *errname; + struct value_to_field vtf; + VALUE input; + VALUE flags_val; + unsigned int flags; + + if (TYPE(in) == T_HASH) { + input = in; + flags_val = INT2NUM(0); + } + else if (TYPE(in) == T_ARRAY) { + if (RARRAY_LEN(in) != 2) + rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", + RARRAY_LEN(in)); + input = rb_ary_entry(in, 0); + flags_val = rb_ary_entry(in, 1); + } + else + rb_raise(rb_eTypeError, "wrong argument type (expected Hash or Array)"); + + Check_Type(input, T_HASH); + + /* we do this up-front for proper argument error checking */ + flags = NUM2UINT(flags_val); + + if (RHASH_SIZE(input) == 0) + return Qnil; + + /* Complicated. The below all stems from the fact that we have no way to + * have no way to discover what type each parameter should be based on the + * be based on the input. Instead, we ask libvirt to give us the current + * us the current parameters and types, and then we replace the values with + * the values with the new values. That way we find out what the old types + * what the old types were, and if the new types don't match, libvirt will + * throw an error. + */ + + nparams = nparams_cb(d, flags); + + params = ALLOC_N(virTypedParameter, nparams); + + errname = get_cb(d, flags, params, &nparams); + if (errname != NULL) { + xfree(params); + rb_exc_raise(create_error(e_RetrieveError, errname, conn(d))); + } + + for (i = 0; i < nparams; i++) { + vtf.param = ¶ms[i]; + vtf.input = input; + rb_protect(typed_value_to_field, (VALUE)&vtf, &exception); + if (exception) { + xfree(params); + rb_jump_tag(exception); + } + } + + errname = set_cb(d, flags, params, nparams); + if (errname != NULL) { + xfree(params); + rb_exc_raise(create_error(e_RetrieveError, errname, conn(d))); + } + + xfree(params); + + return Qnil; +} + +static int scheduler_nparams(VALUE d, unsigned int flags) { + int nparams; + char *type; + + type = virDomainGetSchedulerType(domain_get(d), &nparams); + _E(type == NULL, create_error(e_RetrieveError, "virDomainGetSchedulerType", + conn(d))); + xfree(type); + + return nparams; +} + +static char *scheduler_get(VALUE d, unsigned int flags, + virTypedParameterPtr params, int *nparams) { +#ifdef HAVE_TYPE_VIRTYPEDPARAMETERPTR + if (virDomainGetSchedulerParametersFlags(domain_get(d), params, nparams, + flags) < 0) + return "virDomainGetSchedulerParameters"; +#else + if (flags != 0) + rb_raise(e_NoSupportError, "Non-zero flags not supported"); + if (virDomainGetSchedulerParameters(domain_get(d), + (virSchedParameterPtr)params, + nparams) < 0) + return "virDomainGetSchedulerParameters"; +#endif + + return NULL; +} + +static char *scheduler_set(VALUE d, unsigned int flags, + virTypedParameterPtr params, int nparams) { +#if HAVE_TYPE_VIRTYPEDPARAMETERPTR + if (virDomainSetSchedulerParametersFlags(domain_get(d), params, nparams, + flags) < 0) + return "virDomainSetSchedulerParameters"; +#else + if (flags != 0) + rb_raise(e_NoSupportError, "Non-zero flags not supported"); + if (virDomainSetSchedulerParameters(domain_get(d), + (virSchedParameterPtr)params, + nparams) < 0) + return "virDomainSetSchedulerParameters"; +#endif + + return NULL; +} + +/* + * call-seq: + * dom.scheduler_parameters(flags=0) -> Hash + * + * Call +virDomainGetSchedulerParameters+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetSchedulerParameters] + * to retrieve all of the scheduler parameters for this domain. The keys and + * values in the hash that is returned are hypervisor specific. + */ +static VALUE libvirt_dom_get_scheduler_parameters(int argc, VALUE *argv, + VALUE d) { + return internal_get_parameters(argc, argv, d, scheduler_nparams, + scheduler_get); +} + +/* + * call-seq: + * dom.scheduler_parameters = Hash,flags=0 + * + * Call +virDomainSetSchedulerParameters+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetSchedulerParameters] + * to set the scheduler parameters for this domain. The keys and values in + * the input hash are hypervisor specific. If an empty hash is given, no + * changes are made (and no error is raised). + */ +static VALUE libvirt_dom_set_scheduler_parameters(VALUE d, VALUE input) { + return internal_set_parameters(d, input, scheduler_nparams, scheduler_get, + scheduler_set); +} + +#if HAVE_VIRDOMAINSETMEMORYPARAMETERS +static int memory_nparams(VALUE d, unsigned int flags) { + int nparams = 0; + int ret; + + ret = virDomainGetMemoryParameters(domain_get(d), NULL, &nparams, flags); + _E(ret < 0, create_error(e_RetrieveError, "virDomainGetMemoryParameters", + conn(d))); + + return nparams; +} + +static char *memory_get(VALUE d, unsigned int flags, + virTypedParameterPtr params, int *nparams) { +#ifdef HAVE_TYPE_VIRTYPEDPARAMETERPTR + if (virDomainGetMemoryParameters(domain_get(d), params, nparams, flags) < 0) +#else + if (virDomainGetMemoryParameters(domain_get(d), + (virMemoryParameterPtr)params, nparams, + flags) < 0) +#endif + return "virDomainGetMemoryParameters"; + + return NULL; +} + +static char *memory_set(VALUE d, unsigned int flags, + virTypedParameterPtr params, int nparams) { +#ifdef HAVE_TYPE_VIRTYPEDPARAMETERPTR + if (virDomainSetMemoryParameters(domain_get(d), params, nparams, flags) < 0) +#else + if (virDomainSetMemoryParameters(domain_get(d), + (virMemoryParameterPtr)params, nparams, + flags) < 0) +#endif + return "virDomainSetMemoryParameters"; + + return NULL; +} + +/* + * call-seq: + * dom.memory_parameters(flags=0) -> Hash + * + * Call +virDomainGetMemoryParameters+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetMemoryParameters] + * to retrieve all of the memory parameters for this domain. The keys and + * values in the hash that is returned are hypervisor specific. + */ +static VALUE libvirt_dom_get_memory_parameters(int argc, VALUE *argv, VALUE d) { + return internal_get_parameters(argc, argv, d, memory_nparams, memory_get); +} + +/* + * call-seq: + * dom.memory_parameters = Hash,flags=0 + * + * Call +virDomainSetMemoryParameters+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetMemoryParameters] + * to set the memory parameters for this domain. The keys and values in + * the input hash are hypervisor specific. + */ +static VALUE libvirt_dom_set_memory_parameters(VALUE d, VALUE in) { + return internal_set_parameters(d, in, memory_nparams, memory_get, + memory_set); +} +#endif + +#if HAVE_VIRDOMAINSETBLKIOPARAMETERS +static int blkio_nparams(VALUE d, unsigned int flags) { + int nparams = 0; + int ret; + + ret = virDomainGetBlkioParameters(domain_get(d), NULL, &nparams, flags); + _E(ret < 0, create_error(e_RetrieveError, "virDomainGetBlkioParameters", + conn(d))); + + return nparams; +} + +static char *blkio_get(VALUE d, unsigned int flags, virTypedParameterPtr params, + int *nparams) { +#ifdef HAVE_TYPE_VIRTYPEDPARAMETERPTR + if (virDomainGetBlkioParameters(domain_get(d), params, nparams, flags) < 0) +#else + if (virDomainGetBlkioParameters(domain_get(d), + (virBlkioParameterPtr)params, nparams, + flags) < 0) +#endif + return "virDomainGetBlkioParameters"; + + return NULL; +} + +static char *blkio_set(VALUE d, unsigned int flags, virTypedParameterPtr params, + int nparams) { +#ifdef HAVE_TYPE_VIRTYPEDPARAMETERPTR + if (virDomainSetBlkioParameters(domain_get(d), params, nparams, flags) < 0) +#else + if (virDomainSetBlkioParameters(domain_get(d), + (virBlkioParameterPtr)params, nparams, + flags) < 0) +#endif + return "virDomainSetBlkioParameters"; + + return NULL; +} + +/* + * call-seq: + * dom.blkio_parameters(flags=0) -> Hash + * + * Call +virDomainGetBlkioParameters+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetBlkioParameters] + * to retrieve all of the blkio parameters for this domain. The keys and + * values in the hash that is returned are hypervisor specific. + */ +static VALUE libvirt_dom_get_blkio_parameters(int argc, VALUE *argv, VALUE d) { + return internal_get_parameters(argc, argv, d, blkio_nparams, blkio_get); +} + +/* + * call-seq: + * dom.memory_parameters = Hash,flags=0 + * + * Call +virDomainSetBlkioParameters+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetBlkioParameters] + * to set the blkio parameters for this domain. The keys and values in + * the input hash are hypervisor specific. + */ +static VALUE libvirt_dom_set_blkio_parameters(VALUE d, VALUE in) { + return internal_set_parameters(d, in, blkio_nparams, blkio_get, blkio_set); +} +#endif + +#if HAVE_VIRDOMAINGETSTATE +/* + * call-seq: + * dom.state(flags=0) -> state, reason + * + * Call +virDomainGetState+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetState] + * to get the current state of the domain. + */ +static VALUE libvirt_dom_get_state(int argc, VALUE *argv, VALUE d) { + VALUE flags; + int state, reason; + VALUE result; + int retval; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + retval = virDomainGetState(domain_get(d), &state, &reason, NUM2INT(flags)); + _E(retval < 0, create_error(e_Error, "virDomainGetState", conn(d))); + + result = rb_ary_new(); + + rb_ary_push(result, INT2NUM(state)); + rb_ary_push(result, INT2NUM(reason)); + + return result; +} +#endif + +#if HAVE_VIRDOMAINOPENCONSOLE +/* + * call-seq: + * dom.open_console(device, stream, flags=0) -> nil + * + * Call +virDomainOpenConsole+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainOpenConsole] + * to open up a console to device over stream. + */ +static VALUE libvirt_dom_open_console(int argc, VALUE *argv, VALUE d) { + VALUE dev, st, flags; + + rb_scan_args(argc, argv, "21", &dev, &st, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virDomainOpenConsole, conn(d), domain_get(d), + StringValueCStr(dev), stream_get(st), NUM2INT(flags)); +} +#endif + +#if HAVE_VIRDOMAINSCREENSHOT +/* + * call-seq: + * dom.screenshot(stream, screen, flags=0) -> nil + * + * Call +virDomainScreenshot+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainScreenshot] + * to take a screenshot of the domain console as a stream. + */ +static VALUE libvirt_dom_screenshot(int argc, VALUE *argv, VALUE d) { + VALUE st, screen, flags; + + rb_scan_args(argc, argv, "21", &st, &screen, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_string(virDomainScreenshot, conn(d), 1, domain_get(d), + stream_get(st), NUM2UINT(screen), NUM2UINT(flags)); +} +#endif + +#if HAVE_VIRDOMAININJECTNMI +/* + * call-seq: + * dom.inject_nmi(flags=0) -> nil + * + * Call +virDomainInjectNMI+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainInjectNMI] + * to send an NMI to the guest. + */ +static VALUE libvirt_dom_inject_nmi(int argc, VALUE *argv, VALUE d) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virDomainInjectNMI, conn(d), domain_get(d), NUM2UINT(flags)); +} +#endif + +/* + * Class Libvirt::Domain + */ +void init_domain() +{ + c_domain = rb_define_class_under(m_libvirt, "Domain", rb_cObject); + + rb_define_const(c_domain, "NOSTATE", INT2NUM(VIR_DOMAIN_NOSTATE)); + rb_define_const(c_domain, "RUNNING", INT2NUM(VIR_DOMAIN_RUNNING)); + rb_define_const(c_domain, "BLOCKED", INT2NUM(VIR_DOMAIN_BLOCKED)); + rb_define_const(c_domain, "PAUSED", INT2NUM(VIR_DOMAIN_PAUSED)); + rb_define_const(c_domain, "SHUTDOWN", INT2NUM(VIR_DOMAIN_SHUTDOWN)); + rb_define_const(c_domain, "SHUTOFF", INT2NUM(VIR_DOMAIN_SHUTOFF)); + rb_define_const(c_domain, "CRASHED", INT2NUM(VIR_DOMAIN_CRASHED)); + + /* virDomainMigrateFlags */ +#if HAVE_CONST_VIR_MIGRATE_LIVE + rb_define_const(c_domain, "MIGRATE_LIVE", INT2NUM(VIR_MIGRATE_LIVE)); +#endif +#if HAVE_CONST_VIR_MIGRATE_PEER2PEER + rb_define_const(c_domain, "MIGRATE_PEER2PEER", + INT2NUM(VIR_MIGRATE_PEER2PEER)); +#endif +#if HAVE_CONST_VIR_MIGRATE_TUNNELLED + rb_define_const(c_domain, "MIGRATE_TUNNELLED", + INT2NUM(VIR_MIGRATE_TUNNELLED)); +#endif +#if HAVE_CONST_VIR_MIGRATE_PERSIST_DEST + rb_define_const(c_domain, "MIGRATE_PERSIST_DEST", + INT2NUM(VIR_MIGRATE_PERSIST_DEST)); +#endif +#if HAVE_CONST_VIR_MIGRATE_UNDEFINE_SOURCE + rb_define_const(c_domain, "MIGRATE_UNDEFINE_SOURCE", + INT2NUM(VIR_MIGRATE_UNDEFINE_SOURCE)); +#endif +#if HAVE_CONST_VIR_MIGRATE_PAUSED + rb_define_const(c_domain, "MIGRATE_PAUSED", INT2NUM(VIR_MIGRATE_PAUSED)); +#endif +#if HAVE_CONST_VIR_MIGRATE_NON_SHARED_DISK + rb_define_const(c_domain, "MIGRATE_NON_SHARED_DISK", + INT2NUM(VIR_MIGRATE_NON_SHARED_DISK)); +#endif +#if HAVE_CONST_VIR_MIGRATE_NON_SHARED_INC + rb_define_const(c_domain, "MIGRATE_NON_SHARED_INC", + INT2NUM(VIR_MIGRATE_NON_SHARED_INC)); +#endif + rb_define_const(c_domain, "DOMAIN_XML_SECURE", + INT2NUM(VIR_DOMAIN_XML_SECURE)); + rb_define_const(c_domain, "DOMAIN_XML_INACTIVE", + INT2NUM(VIR_DOMAIN_XML_INACTIVE)); +#if HAVE_CONST_VIR_DOMAIN_XML_UPDATE_CPU + rb_define_const(c_domain, "DOMAIN_XML_UPDATE_CPU", + INT2NUM(VIR_DOMAIN_XML_UPDATE_CPU)); +#endif +#if HAVE_VIRDOMAINMEMORYPEEK + rb_define_const(c_domain, "MEMORY_VIRTUAL", INT2NUM(VIR_MEMORY_VIRTUAL)); +#endif +#if HAVE_CONST_VIR_MEMORY_PHYSICAL + rb_define_const(c_domain, "MEMORY_PHYSICAL", INT2NUM(VIR_MEMORY_PHYSICAL)); +#endif + +#if HAVE_CONST_VIR_DOMAIN_START_PAUSED + rb_define_const(c_domain, "START_PAUSED", INT2NUM(VIR_DOMAIN_START_PAUSED)); +#endif + +#if HAVE_CONST_VIR_DUMP_CRASH + rb_define_const(c_domain, "DUMP_CRASH", INT2NUM(VIR_DUMP_CRASH)); +#endif +#if HAVE_CONST_VIR_DUMP_LIVE + rb_define_const(c_domain, "DUMP_LIVE", INT2NUM(VIR_DUMP_LIVE)); +#endif + +#if HAVE_VIRDOMAINGETVCPUSFLAGS + rb_define_const(c_domain, "VCPU_LIVE", INT2NUM(VIR_DOMAIN_VCPU_LIVE)); + rb_define_const(c_domain, "VCPU_CONFIG", INT2NUM(VIR_DOMAIN_VCPU_CONFIG)); + rb_define_const(c_domain, "VCPU_MAXIMUM", INT2NUM(VIR_DOMAIN_VCPU_MAXIMUM)); +#endif + + rb_define_method(c_domain, "migrate", libvirt_dom_migrate, -1); +#if HAVE_VIRDOMAINMIGRATETOURI + rb_define_method(c_domain, "migrate_to_uri", + libvirt_dom_migrate_to_uri, -1); +#endif +#if HAVE_VIRDOMAINMIGRATESETMAXDOWNTIME + rb_define_method(c_domain, "migrate_set_max_downtime", + libvirt_dom_migrate_set_max_downtime, -1); +#endif +#if HAVE_VIRDOMAINMIGRATE2 + rb_define_method(c_domain, "migrate2", libvirt_dom_migrate2, -1); + rb_define_method(c_domain, "migrate_to_uri2", + libvirt_dom_migrate_to_uri2, -1); + rb_define_method(c_domain, "migrate_set_max_speed", + libvirt_dom_migrate_set_max_speed, -1); +#endif + + rb_define_attr(c_domain, "connection", 1, 0); + rb_define_method(c_domain, "shutdown", libvirt_dom_shutdown, 0); + rb_define_method(c_domain, "reboot", libvirt_dom_reboot, -1); + rb_define_method(c_domain, "destroy", libvirt_dom_destroy, 0); + rb_define_method(c_domain, "suspend", libvirt_dom_suspend, 0); + rb_define_method(c_domain, "resume", libvirt_dom_resume, 0); + rb_define_method(c_domain, "save", libvirt_dom_save, 1); + rb_define_singleton_method(c_domain, "restore", libvirt_dom_s_restore, 2); + rb_define_method(c_domain, "restore", libvirt_dom_restore, 1); + rb_define_method(c_domain, "core_dump", libvirt_dom_core_dump, -1); + rb_define_method(c_domain, "info", libvirt_dom_info, 0); + rb_define_method(c_domain, "ifinfo", libvirt_dom_if_stats, 1); + rb_define_method(c_domain, "name", libvirt_dom_name, 0); + rb_define_method(c_domain, "id", libvirt_dom_id, 0); + rb_define_method(c_domain, "uuid", libvirt_dom_uuid, 0); + rb_define_method(c_domain, "os_type", libvirt_dom_os_type, 0); + rb_define_method(c_domain, "max_memory", libvirt_dom_max_memory, 0); + rb_define_method(c_domain, "max_memory=", libvirt_dom_max_memory_set, 1); + rb_define_method(c_domain, "memory=", libvirt_dom_memory_set, 1); + rb_define_method(c_domain, "max_vcpus", libvirt_dom_max_vcpus, 0); + rb_define_method(c_domain, "vcpus=", libvirt_dom_vcpus_set, 1); +#if HAVE_VIRDOMAINSETVCPUSFLAGS + rb_define_method(c_domain, "vcpus_flags=", libvirt_dom_vcpus_set_flags, 1); +#endif + rb_define_method(c_domain, "pin_vcpu", libvirt_dom_pin_vcpu, 2); + rb_define_method(c_domain, "xml_desc", libvirt_dom_xml_desc, -1); + rb_define_method(c_domain, "undefine", libvirt_dom_undefine, 0); + rb_define_method(c_domain, "create", libvirt_dom_create, -1); + rb_define_method(c_domain, "autostart", libvirt_dom_autostart, 0); + rb_define_method(c_domain, "autostart?", libvirt_dom_autostart, 0); + rb_define_method(c_domain, "autostart=", libvirt_dom_autostart_set, 1); + rb_define_method(c_domain, "free", libvirt_dom_free, 0); + +#if HAVE_CONST_VIR_DOMAIN_DEVICE_MODIFY_CURRENT + rb_define_const(c_domain, "DEVICE_MODIFY_CURRENT", + INT2NUM(VIR_DOMAIN_DEVICE_MODIFY_CURRENT)); +#endif +#if HAVE_CONST_VIR_DOMAIN_DEVICE_MODIFY_LIVE + rb_define_const(c_domain, "DEVICE_MODIFY_LIVE", + INT2NUM(VIR_DOMAIN_DEVICE_MODIFY_LIVE)); +#endif +#if HAVE_CONST_VIR_DOMAIN_DEVICE_MODIFY_CONFIG + rb_define_const(c_domain, "DEVICE_MODIFY_CONFIG", + INT2NUM(VIR_DOMAIN_DEVICE_MODIFY_CONFIG)); +#endif +#if HAVE_CONST_VIR_DOMAIN_DEVICE_MODIFY_FORCE + rb_define_const(c_domain, "DEVICE_MODIFY_FORCE", + INT2NUM(VIR_DOMAIN_DEVICE_MODIFY_FORCE)); +#endif + rb_define_method(c_domain, "attach_device", libvirt_dom_attach_device, -1); + rb_define_method(c_domain, "detach_device", libvirt_dom_detach_device, -1); +#if HAVE_VIRDOMAINUPDATEDEVICEFLAGS + rb_define_method(c_domain, "update_device", libvirt_dom_update_device, -1); +#endif + + rb_define_method(c_domain, "scheduler_type", libvirt_dom_scheduler_type, 0); + +#if HAVE_VIRDOMAINMANAGEDSAVE + rb_define_method(c_domain, "managed_save", libvirt_dom_managed_save, -1); + rb_define_method(c_domain, "has_managed_save?", + libvirt_dom_has_managed_save, -1); + rb_define_method(c_domain, "managed_save_remove", + libvirt_dom_managed_save_remove, -1); +#endif +#if HAVE_VIRDOMAINGETSECURITYLABEL + rb_define_method(c_domain, "security_label", + libvirt_dom_security_label, 0); +#endif + rb_define_method(c_domain, "block_stats", libvirt_dom_block_stats, 1); +#if HAVE_TYPE_VIRDOMAINMEMORYSTATPTR + rb_define_method(c_domain, "memory_stats", libvirt_dom_memory_stats, -1); +#endif +#if HAVE_VIRDOMAINBLOCKPEEK + rb_define_method(c_domain, "block_peek", libvirt_dom_block_peek, -1); +#endif +#if HAVE_TYPE_VIRDOMAINBLOCKINFOPTR + rb_define_method(c_domain, "blockinfo", libvirt_dom_block_info, -1); +#endif +#if HAVE_VIRDOMAINMEMORYPEEK + rb_define_method(c_domain, "memory_peek", libvirt_dom_memory_peek, -1); +#endif + rb_define_method(c_domain, "get_vcpus", libvirt_dom_get_vcpus, 0); +#if HAVE_VIRDOMAINISACTIVE + rb_define_method(c_domain, "active?", libvirt_dom_active_p, 0); +#endif +#if HAVE_VIRDOMAINISPERSISTENT + rb_define_method(c_domain, "persistent?", libvirt_dom_persistent_p, 0); +#endif +#if HAVE_TYPE_VIRDOMAINSNAPSHOTPTR + rb_define_method(c_domain, "snapshot_create_xml", + libvirt_dom_snapshot_create_xml, -1); + rb_define_method(c_domain, "num_of_snapshots", + libvirt_dom_num_of_snapshots, -1); + rb_define_method(c_domain, "list_snapshots", + libvirt_dom_list_snapshots, -1); + rb_define_method(c_domain, "lookup_snapshot_by_name", + libvirt_dom_lookup_snapshot_by_name, -1); + rb_define_method(c_domain, "has_current_snapshot?", + libvirt_dom_has_current_snapshot_p, -1); + rb_define_method(c_domain, "revert_to_snapshot", + libvirt_dom_revert_to_snapshot, -1); + rb_define_method(c_domain, "current_snapshot", + libvirt_dom_current_snapshot, -1); +#endif + + /* + * Class Libvirt::Domain::Info + */ + c_domain_info = rb_define_class_under(c_domain, "Info", rb_cObject); + rb_define_attr(c_domain_info, "state", 1, 0); + rb_define_attr(c_domain_info, "max_mem", 1, 0); + rb_define_attr(c_domain_info, "memory", 1, 0); + rb_define_attr(c_domain_info, "nr_virt_cpu", 1, 0); + rb_define_attr(c_domain_info, "cpu_time", 1, 0); + + /* + * Class Libvirt::Domain::InterfaceInfo + */ + c_domain_ifinfo = rb_define_class_under(c_domain, "InterfaceInfo", + rb_cObject); + rb_define_attr(c_domain_ifinfo, "rx_bytes", 1, 0); + rb_define_attr(c_domain_ifinfo, "rx_packets", 1, 0); + rb_define_attr(c_domain_ifinfo, "rx_errs", 1, 0); + rb_define_attr(c_domain_ifinfo, "rx_drop", 1, 0); + rb_define_attr(c_domain_ifinfo, "tx_bytes", 1, 0); + rb_define_attr(c_domain_ifinfo, "tx_packets", 1, 0); + rb_define_attr(c_domain_ifinfo, "tx_errs", 1, 0); + rb_define_attr(c_domain_ifinfo, "tx_drop", 1, 0); + + /* + * Class Libvirt::Domain::SecurityLabel + */ + c_domain_security_label = rb_define_class_under(c_domain, "SecurityLabel", + rb_cObject); + rb_define_attr(c_domain_security_label, "label", 1, 0); + rb_define_attr(c_domain_security_label, "enforcing", 1, 0); + + /* + * Class Libvirt::Domain::BlockStats + */ + c_domain_block_stats = rb_define_class_under(c_domain, "BlockStats", + rb_cObject); + rb_define_attr(c_domain_block_stats, "rd_req", 1, 0); + rb_define_attr(c_domain_block_stats, "rd_bytes", 1, 0); + rb_define_attr(c_domain_block_stats, "wr_req", 1, 0); + rb_define_attr(c_domain_block_stats, "wr_bytes", 1, 0); + rb_define_attr(c_domain_block_stats, "errs", 1, 0); + +#if HAVE_TYPE_VIRDOMAINMEMORYSTATPTR + /* + * Class Libvirt::Domain::MemoryStats + */ + c_domain_memory_stats = rb_define_class_under(c_domain, "MemoryStats", + rb_cObject); + rb_define_attr(c_domain_memory_stats, "tag", 1, 0); + rb_define_attr(c_domain_memory_stats, "value", 1, 0); + + rb_define_const(c_domain_memory_stats, "SWAP_IN", + INT2NUM(VIR_DOMAIN_MEMORY_STAT_SWAP_IN)); + rb_define_const(c_domain_memory_stats, "SWAP_OUT", + INT2NUM(VIR_DOMAIN_MEMORY_STAT_SWAP_OUT)); + rb_define_const(c_domain_memory_stats, "MAJOR_FAULT", + INT2NUM(VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT)); + rb_define_const(c_domain_memory_stats, "MINOR_FAULT", + INT2NUM(VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT)); + rb_define_const(c_domain_memory_stats, "UNUSED", + INT2NUM(VIR_DOMAIN_MEMORY_STAT_UNUSED)); + rb_define_const(c_domain_memory_stats, "AVAILABLE", + INT2NUM(VIR_DOMAIN_MEMORY_STAT_AVAILABLE)); + rb_define_const(c_domain_memory_stats, "NR", + INT2NUM(VIR_DOMAIN_MEMORY_STAT_NR)); +#endif + +#if HAVE_TYPE_VIRDOMAINBLOCKINFOPTR + /* + * Class Libvirt::Domain::BlockInfo + */ + c_domain_block_info = rb_define_class_under(c_domain, "BlockInfo", + rb_cObject); + rb_define_attr(c_domain_block_info, "capacity", 1, 0); + rb_define_attr(c_domain_block_info, "allocation", 1, 0); + rb_define_attr(c_domain_block_info, "physical", 1, 0); +#endif + +#if HAVE_TYPE_VIRDOMAINSNAPSHOTPTR + /* + * Class Libvirt::Domain::Snapshot + */ + c_domain_snapshot = rb_define_class_under(c_domain, "Snapshot", rb_cObject); + rb_define_const(c_domain_snapshot, "DELETE_CHILDREN", + INT2NUM(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN)); + rb_define_method(c_domain_snapshot, "xml_desc", + libvirt_dom_snapshot_xml_desc, -1); + rb_define_method(c_domain_snapshot, "delete", + libvirt_dom_snapshot_delete, -1); + rb_define_method(c_domain_snapshot, "free", libvirt_dom_snapshot_free, 0); +#endif + + /* + * Class Libvirt::Domain::VCPUInfo + */ + c_domain_vcpuinfo = rb_define_class_under(c_domain, "VCPUInfo", rb_cObject); + rb_define_const(c_domain_vcpuinfo, "OFFLINE", VIR_VCPU_OFFLINE); + rb_define_const(c_domain_vcpuinfo, "RUNNING", VIR_VCPU_RUNNING); + rb_define_const(c_domain_vcpuinfo, "BLOCKED", VIR_VCPU_BLOCKED); + rb_define_attr(c_domain_vcpuinfo, "number", 1, 0); + rb_define_attr(c_domain_vcpuinfo, "state", 1, 0); + rb_define_attr(c_domain_vcpuinfo, "cpu_time", 1, 0); + rb_define_attr(c_domain_vcpuinfo, "cpu", 1, 0); + rb_define_attr(c_domain_vcpuinfo, "cpumap", 1, 0); + +#if HAVE_TYPE_VIRDOMAINJOBINFOPTR + /* + * Class Libvirt::Domain::JobInfo + */ + c_domain_job_info = rb_define_class_under(c_domain, "JobInfo", rb_cObject); + rb_define_const(c_domain_job_info, "NONE", INT2NUM(VIR_DOMAIN_JOB_NONE)); + rb_define_const(c_domain_job_info, "BOUNDED", + INT2NUM(VIR_DOMAIN_JOB_BOUNDED)); + rb_define_const(c_domain_job_info, "UNBOUNDED", + INT2NUM(VIR_DOMAIN_JOB_UNBOUNDED)); + rb_define_const(c_domain_job_info, "COMPLETED", + INT2NUM(VIR_DOMAIN_JOB_COMPLETED)); + rb_define_const(c_domain_job_info, "FAILED", + INT2NUM(VIR_DOMAIN_JOB_FAILED)); + rb_define_const(c_domain_job_info, "CANCELLED", + INT2NUM(VIR_DOMAIN_JOB_CANCELLED)); + rb_define_attr(c_domain_job_info, "type", 1, 0); + rb_define_attr(c_domain_job_info, "time_elapsed", 1, 0); + rb_define_attr(c_domain_job_info, "time_remaining", 1, 0); + rb_define_attr(c_domain_job_info, "data_total", 1, 0); + rb_define_attr(c_domain_job_info, "data_processed", 1, 0); + rb_define_attr(c_domain_job_info, "data_remaining", 1, 0); + rb_define_attr(c_domain_job_info, "mem_total", 1, 0); + rb_define_attr(c_domain_job_info, "mem_processed", 1, 0); + rb_define_attr(c_domain_job_info, "mem_remaining", 1, 0); + rb_define_attr(c_domain_job_info, "file_total", 1, 0); + rb_define_attr(c_domain_job_info, "file_processed", 1, 0); + rb_define_attr(c_domain_job_info, "file_remaining", 1, 0); + + rb_define_method(c_domain, "job_info", libvirt_dom_job_info, 0); + rb_define_method(c_domain, "abort_job", libvirt_dom_abort_job, 0); +#endif + +#if HAVE_VIRDOMAINQEMUMONITORCOMMAND + rb_define_method(c_domain, "qemu_monitor_command", + libvirt_dom_qemu_monitor_command, -1); +#endif + +#if HAVE_VIRDOMAINGETVCPUSFLAGS + rb_define_method(c_domain, "num_vcpus", libvirt_dom_num_vcpus, 1); +#endif + +#if HAVE_VIRDOMAINISUPDATED + rb_define_method(c_domain, "updated?", libvirt_dom_is_updated, 0); +#endif + +#ifdef VIR_DOMAIN_MEMORY_PARAM_UNLIMITED + rb_define_const(c_domain, "MEMORY_PARAM_UNLIMITED", + VIR_DOMAIN_MEMORY_PARAM_UNLIMITED); +#endif + +#if HAVE_VIRDOMAINSETMEMORYFLAGS + rb_define_const(c_domain, "DOMAIN_MEM_LIVE", INT2NUM(VIR_DOMAIN_MEM_LIVE)); + rb_define_const(c_domain, "DOMAIN_MEM_CONFIG", + INT2NUM(VIR_DOMAIN_MEM_CONFIG)); +#endif +#if HAVE_CONST_VIR_DOMAIN_MEM_CURRENT + rb_define_const(c_domain, "DOMAIN_MEM_CURRENT", + INT2NUM(VIR_DOMAIN_MEM_CURRENT)); + rb_define_const(c_domain, "DOMAIN_MEM_MAXIMUM", + INT2NUM(VIR_DOMAIN_MEM_MAXIMUM)); +#endif + + rb_define_method(c_domain, "scheduler_parameters", + libvirt_dom_get_scheduler_parameters, -1); + rb_define_method(c_domain, "scheduler_parameters=", + libvirt_dom_set_scheduler_parameters, 1); + +#if HAVE_VIRDOMAINSETMEMORYPARAMETERS + rb_define_method(c_domain, "memory_parameters", + libvirt_dom_get_memory_parameters, -1); + rb_define_method(c_domain, "memory_parameters=", + libvirt_dom_set_memory_parameters, 1); +#endif + +#if HAVE_VIRDOMAINSETBLKIOPARAMETERS + rb_define_method(c_domain, "blkio_parameters", + libvirt_dom_get_blkio_parameters, -1); + rb_define_method(c_domain, "blkio_parameters=", + libvirt_dom_set_blkio_parameters, 1); +#endif + +#if HAVE_VIRDOMAINGETSTATE + rb_define_const(c_domain, "DOMAIN_RUNNING_UNKNOWN", + INT2NUM(VIR_DOMAIN_RUNNING_UNKNOWN)); + rb_define_const(c_domain, "DOMAIN_RUNNING_BOOTED", + INT2NUM(VIR_DOMAIN_RUNNING_BOOTED)); + rb_define_const(c_domain, "DOMAIN_RUNNING_MIGRATED", + INT2NUM(VIR_DOMAIN_RUNNING_MIGRATED)); + rb_define_const(c_domain, "DOMAIN_RUNNING_RESTORED", + INT2NUM(VIR_DOMAIN_RUNNING_RESTORED)); + rb_define_const(c_domain, "DOMAIN_RUNNING_FROM_SNAPSHOT", + INT2NUM(VIR_DOMAIN_RUNNING_FROM_SNAPSHOT)); + rb_define_const(c_domain, "DOMAIN_RUNNING_UNPAUSED", + INT2NUM(VIR_DOMAIN_RUNNING_UNPAUSED)); + rb_define_const(c_domain, "DOMAIN_RUNNING_MIGRATION_CANCELED", + INT2NUM(VIR_DOMAIN_RUNNING_MIGRATION_CANCELED)); + rb_define_const(c_domain, "DOMAIN_RUNNING_SAVE_CANCELED", + INT2NUM(VIR_DOMAIN_RUNNING_SAVE_CANCELED)); + rb_define_const(c_domain, "DOMAIN_BLOCKED_UNKNOWN", + INT2NUM(VIR_DOMAIN_BLOCKED_UNKNOWN)); + rb_define_const(c_domain, "DOMAIN_PAUSED_UNKNOWN", + INT2NUM(VIR_DOMAIN_PAUSED_UNKNOWN)); + rb_define_const(c_domain, "DOMAIN_PAUSED_USER", + INT2NUM(VIR_DOMAIN_PAUSED_USER)); + rb_define_const(c_domain, "DOMAIN_PAUSED_MIGRATION", + INT2NUM(VIR_DOMAIN_PAUSED_MIGRATION)); + rb_define_const(c_domain, "DOMAIN_PAUSED_SAVE", + INT2NUM(VIR_DOMAIN_PAUSED_SAVE)); + rb_define_const(c_domain, "DOMAIN_PAUSED_DUMP", + INT2NUM(VIR_DOMAIN_PAUSED_DUMP)); + rb_define_const(c_domain, "DOMAIN_PAUSED_IOERROR", + INT2NUM(VIR_DOMAIN_PAUSED_IOERROR)); + rb_define_const(c_domain, "DOMAIN_PAUSED_WATCHDOG", + INT2NUM(VIR_DOMAIN_PAUSED_WATCHDOG)); + rb_define_const(c_domain, "DOMAIN_PAUSED_FROM_SNAPSHOT", + INT2NUM(VIR_DOMAIN_PAUSED_FROM_SNAPSHOT)); + rb_define_const(c_domain, "DOMAIN_SHUTDOWN_UNKNOWN", + INT2NUM(VIR_DOMAIN_SHUTDOWN_UNKNOWN)); + rb_define_const(c_domain, "DOMAIN_SHUTDOWN_USER", + INT2NUM(VIR_DOMAIN_SHUTDOWN_USER)); + rb_define_const(c_domain, "DOMAIN_SHUTOFF_UNKNOWN", + INT2NUM(VIR_DOMAIN_SHUTOFF_UNKNOWN)); + rb_define_const(c_domain, "DOMAIN_SHUTOFF_SHUTDOWN", + INT2NUM(VIR_DOMAIN_SHUTOFF_SHUTDOWN)); + rb_define_const(c_domain, "DOMAIN_SHUTOFF_DESTROYED", + INT2NUM(VIR_DOMAIN_SHUTOFF_DESTROYED)); + rb_define_const(c_domain, "DOMAIN_SHUTOFF_CRASHED", + INT2NUM(VIR_DOMAIN_SHUTOFF_CRASHED)); + rb_define_const(c_domain, "DOMAIN_SHUTOFF_MIGRATED", + INT2NUM(VIR_DOMAIN_SHUTOFF_MIGRATED)); + rb_define_const(c_domain, "DOMAIN_SHUTOFF_SAVED", + INT2NUM(VIR_DOMAIN_SHUTOFF_SAVED)); + rb_define_const(c_domain, "DOMAIN_SHUTOFF_FAILED", + INT2NUM(VIR_DOMAIN_SHUTOFF_FAILED)); + rb_define_const(c_domain, "DOMAIN_SHUTOFF_FROM_SNAPSHOT", + INT2NUM(VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT)); + rb_define_const(c_domain, "DOMAIN_CRASHED_UNKNOWN", + INT2NUM(VIR_DOMAIN_CRASHED_UNKNOWN)); + + rb_define_method(c_domain, "state", libvirt_dom_get_state, -1); +#endif + +#if HAVE_CONST_VIR_DOMAIN_AFFECT_CURRENT + rb_define_const(c_domain, "DOMAIN_AFFECT_CURRENT", + INT2NUM(VIR_DOMAIN_AFFECT_CURRENT)); + rb_define_const(c_domain, "DOMAIN_AFFECT_LIVE", + INT2NUM(VIR_DOMAIN_AFFECT_LIVE)); + rb_define_const(c_domain, "DOMAIN_AFFECT_CONFIG", + INT2NUM(VIR_DOMAIN_AFFECT_CONFIG)); +#endif + +#if HAVE_VIRDOMAINOPENCONSOLE + rb_define_method(c_domain, "open_console", libvirt_dom_open_console, -1); +#endif + +#if HAVE_VIRDOMAINSCREENSHOT + rb_define_method(c_domain, "screenshot", libvirt_dom_screenshot, -1); +#endif + +#if HAVE_VIRDOMAININJECTNMI + rb_define_method(c_domain, "inject_nmi", libvirt_dom_inject_nmi, -1); +#endif +} diff -Nru ruby-libvirt-0.0.7/ext/libvirt/domain.h ruby-libvirt-0.4.0/ext/libvirt/domain.h --- ruby-libvirt-0.0.7/ext/libvirt/domain.h 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/domain.h 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,9 @@ +#ifndef DOMAIN_H +#define DOMAIN_H + +VALUE domain_new(virDomainPtr d, VALUE conn); +virDomainPtr domain_get(VALUE s); + +void init_domain(); + +#endif diff -Nru ruby-libvirt-0.0.7/ext/libvirt/extconf.h ruby-libvirt-0.4.0/ext/libvirt/extconf.h --- ruby-libvirt-0.0.7/ext/libvirt/extconf.h 2008-04-02 17:39:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/extconf.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#ifndef EXTCONF_H -#define EXTCONF_H -#define HAVE_TYPE_VIRNETWORKPTR 1 -#define HAVE_TYPE_VIRSTORAGEPOOLPTR 1 -#define HAVE_TYPE_VIRSTORAGEVOLPTR 1 -#endif diff -Nru ruby-libvirt-0.0.7/ext/libvirt/extconf.rb ruby-libvirt-0.4.0/ext/libvirt/extconf.rb --- ruby-libvirt-0.0.7/ext/libvirt/extconf.rb 2008-03-27 18:18:51.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/extconf.rb 2011-07-29 16:19:09.000000000 +0000 @@ -1,5 +1,7 @@ require 'mkmf' +RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC'] + def have_libvirt_funcs(funcs) funcs.each { |f| have_func(f, "libvirt/libvirt.h") } end @@ -8,19 +10,212 @@ types.each { |t| have_type(t, "libvirt/libvirt.h") } end -extension_name = '_libvirt' +# older mkmf does not have checking_message, so implement our own here +def libvirt_checking_message(target, place = nil, opt = nil) + [["in", place], ["with", opt]].inject("#{target}") do |msg, (pre, noun)| + if noun + [[:to_str], [:join, ","], [:to_s]].each do |meth, *args| + if noun.respond_to?(meth) + break noun = noun.send(meth, *args) + end + end + msg << " #{pre} #{noun}" unless noun.empty? + end + msg + end +end -dir_config(extension_name) +def have_const(const, headers = nil, opt = "", &b) + checking_for libvirt_checking_message(const, headers, opt) do + headers = cpp_include(headers) + if try_compile(<<"SRC", opt, &b) +#{COMMON_HEADERS} +#{headers} +/*top*/ +static int t = #{const}; +SRC + $defs.push(format("-DHAVE_CONST_%s", const.strip.upcase.tr_s("^A-Z0-9_", "_"))) + true + else + false + end + end +end -unless pkg_config("libvirt") - raise "libvirt not found" +def have_libvirt_consts(consts) + consts.each { |c| have_const(c, ["libvirt/libvirt.h", "libvirt/virterror.h"]) } end +extension_name = '_libvirt' + +# this is a poor-man's dir_config, but is a bit more flexible. In particular, +# it allows you to specify the exact location of the libvirt.so, as opposed +# to requiring a lib/ subdirectory. Note that due to the way include files +# are done within ruby-libvirt, the libvirt header file(s) must be in a libvirt/ +# subdirectory. Also note that if specifying the include directory, the +# location of the library must also be specified. Finally, note that if neither +# the include nor the library are specified, the build will attempt to use +# pkg-config to discover this information. +# +# Taking all of the above rules into account, the valid options are either: +# $ ruby extconf.rb --with-libvirt-include=/home/clalance/libvirt/include \ +# --with-libvirt-lib=/home/clalance/libvirt/src/.libs +# +# To specify the location of the include files and the library, or: +# $ ruby extconf.rb +# +# to attempt to use pkg-config to do it automatically from the system files. +include = with_config("libvirt-include") +lib = with_config("libvirt-lib") +if include and lib + $LIBPATH = [lib] | $LIBPATH + $CPPFLAGS += "-I" + include + have_library("virt", "virConnectOpen", "libvirt/libvirt.h") + + # if we are using custom libvirt libraries, we have to suppress the default + # library path so have_func() only picks up the custom ones, not the installed + # ones + $DEFLIBPATH = [] +elsif (include and not lib) or (not include and lib) + raise "Must specify both --with-libvirt-include and --with-libvirt-lib, or neither" +else + unless pkg_config("libvirt") + raise "libvirt library not found in default locations" + end +end + + libvirt_types = [ 'virNetworkPtr', 'virStoragePoolPtr', - 'virStorageVolPtr' ] + 'virStorageVolPtr', + 'virSecretPtr', + 'virNWFilterPtr', + 'virInterfacePtr', + 'virDomainBlockInfoPtr', + 'virDomainMemoryStatPtr', + 'virDomainSnapshotPtr', + 'virDomainJobInfoPtr', + 'virNodeDevicePtr', + 'virStreamPtr', + 'virTypedParameterPtr', + ] + +libvirt_funcs = [ 'virStorageVolWipe', + 'virStoragePoolIsActive', + 'virStoragePoolIsPersistent', + 'virStorageVolCreateXMLFrom', + 'virConnectGetLibVersion', + 'virConnectIsEncrypted', + 'virConnectIsSecure', + 'virNetworkIsActive', + 'virNetworkIsPersistent', + 'virNodeDeviceCreateXML', + 'virNodeDeviceDestroy', + 'virInterfaceIsActive', + 'virDomainMigrateToURI', + 'virDomainMigrateSetMaxDowntime', + 'virDomainManagedSave', + 'virDomainIsActive', + 'virDomainIsPersistent', + 'virConnectDomainXMLFromNative', + 'virConnectDomainXMLToNative', + 'virDomainCreateWithFlags', + 'virDomainAttachDeviceFlags', + 'virDomainDetachDeviceFlags', + 'virDomainUpdateDeviceFlags', + 'virNodeGetSecurityModel', + 'virDomainCreateXML', + 'virDomainGetSecurityLabel', + 'virConnectCompareCPU', + 'virConnectBaselineCPU', + 'virDomainSetVcpusFlags', + 'virDomainGetVcpusFlags', + 'virConnectDomainEventRegisterAny', + 'virConnectDomainEventRegister', + 'virDomainBlockPeek', + 'virDomainMemoryPeek', + 'virConnectOpenAuth', + 'virEventRegisterImpl', + 'virDomainIsUpdated', + 'virDomainSetMemoryParameters', + 'virConnectGetSysinfo', + 'virDomainSetBlkioParameters', + 'virDomainSetMemoryFlags', + 'virDomainGetState', + 'virDomainOpenConsole', + 'virDomainMigrate2', + 'virDomainScreenshot', + 'virInterfaceChangeBegin', + 'virStorageVolDownload', + 'virDomainInjectNMI', + ] + +libvirt_consts = [ 'VIR_MIGRATE_LIVE', + 'VIR_MIGRATE_PEER2PEER', + 'VIR_MIGRATE_TUNNELLED', + 'VIR_MIGRATE_PERSIST_DEST', + 'VIR_MIGRATE_UNDEFINE_SOURCE', + 'VIR_MIGRATE_PAUSED', + 'VIR_MIGRATE_NON_SHARED_DISK', + 'VIR_MIGRATE_NON_SHARED_INC', + 'VIR_DOMAIN_XML_UPDATE_CPU', + 'VIR_MEMORY_PHYSICAL', + 'VIR_DOMAIN_START_PAUSED', + 'VIR_DUMP_CRASH', + 'VIR_DUMP_LIVE', + 'VIR_DOMAIN_DEVICE_MODIFY_CURRENT', + 'VIR_DOMAIN_DEVICE_MODIFY_LIVE', + 'VIR_DOMAIN_DEVICE_MODIFY_CONFIG', + 'VIR_DOMAIN_DEVICE_MODIFY_FORCE', + 'VIR_INTERFACE_XML_INACTIVE', + 'VIR_STORAGE_POOL_INACCESSIBLE', + 'VIR_DOMAIN_EVENT_DEFINED', + 'VIR_DOMAIN_EVENT_STARTED', + 'VIR_DOMAIN_EVENT_SUSPENDED_IOERROR', + 'VIR_DOMAIN_EVENT_ID_WATCHDOG', + 'VIR_DOMAIN_EVENT_ID_IO_ERROR', + 'VIR_DOMAIN_EVENT_ID_GRAPHICS', + 'VIR_DOMAIN_EVENT_ID_REBOOT', + 'VIR_DOMAIN_EVENT_ID_RTC_CHANGE', + 'VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON', + 'VIR_FROM_VMWARE', + 'VIR_FROM_AUDIT', + 'VIR_FROM_SYSINFO', + 'VIR_FROM_STREAMS', + 'VIR_FROM_XENAPI', + 'VIR_FROM_HOOK', + 'VIR_ERR_HOOK_SCRIPT_FAILED', + 'VIR_ERR_MIGRATE_PERSIST_FAILED', + 'VIR_ERR_OPERATION_TIMEOUT', + 'VIR_ERR_CONFIG_UNSUPPORTED', + 'VIR_FROM_XENXM', + 'VIR_ERR_OPERATION_INVALID', + 'VIR_ERR_NO_SECURITY_MODEL', + 'VIR_ERR_AUTH_FAILED', + 'VIR_FROM_PHYP', + 'VIR_FROM_ESX', + 'VIR_FROM_ONE', + 'VIR_FROM_VBOX', + 'VIR_FROM_LXC', + 'VIR_FROM_UML', + 'VIR_FROM_NETWORK', + 'VIR_FROM_DOMAIN', + 'VIR_FROM_STATS_LINUX', + 'VIR_FROM_XEN_INOTIFY', + 'VIR_FROM_SECURITY', + 'VIR_DOMAIN_AFFECT_CURRENT', + 'VIR_DOMAIN_MEM_CURRENT', + 'VIR_DOMAIN_EVENT_ID_CONTROL_ERROR', + ] have_libvirt_types(libvirt_types) +have_libvirt_funcs(libvirt_funcs) +if find_header("libvirt/libvirt-qemu.h") + have_library("virt-qemu", "virDomainQemuMonitorCommand") + have_func("virDomainQemuMonitorCommand", "libvirt/libvirt-qemu.h") +end + +have_libvirt_consts(libvirt_consts) create_header create_makefile(extension_name) diff -Nru ruby-libvirt-0.0.7/ext/libvirt/interface.c ruby-libvirt-0.4.0/ext/libvirt/interface.c --- ruby-libvirt-0.0.7/ext/libvirt/interface.c 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/interface.c 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,181 @@ +/* + * interface.c: virInterface methods + * + * Copyright (C) 2010 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "common.h" +#include "connect.h" +#include "extconf.h" + +#if HAVE_TYPE_VIRINTERFACEPTR +static VALUE c_interface; + +static void interface_free(void *i) { + generic_free(Interface, i); +} + +static virInterfacePtr interface_get(VALUE s) { + generic_get(Interface, s); +} + +VALUE interface_new(virInterfacePtr i, VALUE conn) { + return generic_new(c_interface, i, conn, interface_free); +} + +/* + * call-seq: + * interface.undefine -> nil + * + * Call +virInterfaceUndefine+[http://www.libvirt.org/html/libvirt-libvirt.html#virInterfaceUndefine] + * to undefine this interface. + */ +static VALUE libvirt_interface_undefine(VALUE s) { + gen_call_void(virInterfaceUndefine, conn(s), interface_get(s)); +} + +/* + * call-seq: + * interface.create(flags=0) -> nil + * + * Call +virInterfaceCreate+[http://www.libvirt.org/html/libvirt-libvirt.html#virInterfaceCreate] + * to start this interface. + */ +static VALUE libvirt_interface_create(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virInterfaceCreate, conn(s), interface_get(s), + NUM2UINT(flags)); +} + +/* + * call-seq: + * interface.destroy(flags=0) -> nil + * + * Call +virInterfaceDestroy+[http://www.libvirt.org/html/libvirt-libvirt.html#virInterfaceDestroy] + * to shutdown this interface. + */ +static VALUE libvirt_interface_destroy(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virInterfaceDestroy, conn(s), interface_get(s), + NUM2UINT(flags)); +} + +#if HAVE_VIRINTERFACEISACTIVE +/* + * call-seq: + * interface.active? -> [true|false] + * + * Call +virInterfaceIsActive+[http://www.libvirt.org/html/libvirt-libvirt.html#virInterfaceIsActive] + * to determine if this interface is currently active. + */ +static VALUE libvirt_interface_active_p(VALUE p) { + gen_call_truefalse(virInterfaceIsActive, conn(p), interface_get(p)); +} +#endif + +/* + * call-seq: + * interface.name -> string + * + * Call +virInterfaceGetName+[http://www.libvirt.org/html/libvirt-libvirt.html#virInterfaceGetName] + * to retrieve the name of this interface. + */ +static VALUE libvirt_interface_name(VALUE s) { + gen_call_string(virInterfaceGetName, conn(s), 0, interface_get(s)); +} + +/* + * call-seq: + * interface.mac -> string + * + * Call +virInterfaceGetMACString+[http://www.libvirt.org/html/libvirt-libvirt.html#virInterfaceGetMACString] + * to retrieve the MAC address of this interface. + */ +static VALUE libvirt_interface_mac(VALUE s) { + gen_call_string(virInterfaceGetMACString, conn(s), 0, interface_get(s)); +} + +/* + * call-seq: + * interface.xml_desc -> string + * + * Call +virInterfaceGetXMLDesc+[http://www.libvirt.org/html/libvirt-libvirt.html#virInterfaceGetXMLDesc] + * to retrieve the XML of this interface. + */ +static VALUE libvirt_interface_xml_desc(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_string(virInterfaceGetXMLDesc, conn(s), 1, interface_get(s), + NUM2UINT(flags)); +} + +/* + * call-seq: + * interface.free -> nil + * + * Call +virInterfaceFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virInterfaceFree] + * to free this interface. The object will no longer be valid after this call. + */ +static VALUE libvirt_interface_free(VALUE s) { + gen_call_free(Interface, s); +} +#endif + +/* + * Class Libvirt::Interface + */ +void init_interface() +{ +#if HAVE_TYPE_VIRINTERFACEPTR + c_interface = rb_define_class_under(m_libvirt, "Interface", rb_cObject); +#if HAVE_CONST_VIR_INTERFACE_XML_INACTIVE + rb_define_const(c_interface, "XML_INACTIVE", + INT2NUM(VIR_INTERFACE_XML_INACTIVE)); +#endif + rb_define_attr(c_interface, "connection", 1, 0); + + /* Interface object methods */ + rb_define_method(c_interface, "name", libvirt_interface_name, 0); + rb_define_method(c_interface, "mac", libvirt_interface_mac, 0); + rb_define_method(c_interface, "xml_desc", libvirt_interface_xml_desc, -1); + rb_define_method(c_interface, "undefine", libvirt_interface_undefine, 0); + rb_define_method(c_interface, "create", libvirt_interface_create, -1); + rb_define_method(c_interface, "destroy", libvirt_interface_destroy, -1); + rb_define_method(c_interface, "free", libvirt_interface_free, 0); +#if HAVE_VIRINTERFACEISACTIVE + rb_define_method(c_interface, "active?", libvirt_interface_active_p, 0); +#endif +#endif +} diff -Nru ruby-libvirt-0.0.7/ext/libvirt/interface.h ruby-libvirt-0.4.0/ext/libvirt/interface.h --- ruby-libvirt-0.0.7/ext/libvirt/interface.h 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/interface.h 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,6 @@ +#ifndef INTERFACE_H +#define INTERFACE_H + +void init_interface(); + +#endif diff -Nru ruby-libvirt-0.0.7/ext/libvirt/_libvirt.c ruby-libvirt-0.4.0/ext/libvirt/_libvirt.c --- ruby-libvirt-0.0.7/ext/libvirt/_libvirt.c 2008-04-14 20:03:21.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/_libvirt.c 2011-07-29 16:19:09.000000000 +0000 @@ -1,7 +1,7 @@ /* * libvirt.c: Ruby bindings for libvirt * - * Copyright (C) 2007 Red Hat Inc. + * Copyright (C) 2007,2010 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,1888 +24,987 @@ #include #include #include "extconf.h" +#include "common.h" +#include "storage.h" +#include "connect.h" +#include "network.h" +#include "nodedevice.h" +#include "secret.h" +#include "nwfilter.h" +#include "interface.h" +#include "domain.h" +#include "stream.h" -static VALUE m_libvirt; -static VALUE c_connect; -static VALUE c_domain; -static VALUE c_domain_info; -#if HAVE_TYPE_VIRNETWORKPTR -static VALUE c_network; -#endif -static VALUE c_libvirt_version; -static VALUE c_node_info; -#if HAVE_TYPE_VIRSTORAGEPOOLPTR -static VALUE c_storage_pool; -static VALUE c_storage_pool_info; -#endif -#if HAVE_TYPE_VIRSTORAGEVOLPTR -static VALUE c_storage_vol; -static VALUE c_storage_vol_info; -#endif - - -// define additional errors here -static VALUE e_Error; // Error - generic error -static VALUE e_ConnectionError; // ConnectionError - error durring connection establishment -static VALUE e_DefinitionError; // DefinitionError - error during data definition -static VALUE e_RetrieveError; // RetrievalError - error during data retrieval - -/* - * Internal helpers - */ - -/* Macros to ease some of the boilerplate */ - -#define generic_free(kind, p) \ - do { \ - int r; \ - r = vir##kind##Free((vir##kind##Ptr) p); \ - if (r < 0) \ - rb_raise(rb_eSystemCallError, # kind " free failed"); \ - } while(0); - -#define generic_get(kind, v) \ - do { \ - vir##kind##Ptr ptr; \ - Data_Get_Struct(v, vir##kind, ptr); \ - if (!ptr) \ - rb_raise(rb_eArgError, #kind " has been freed"); \ - return ptr; \ - } while (0); - -static VALUE generic_new(VALUE klass, void *ptr, VALUE conn, - RUBY_DATA_FUNC free_func) { - VALUE result; - result = Data_Wrap_Struct(klass, NULL, free_func, ptr); - rb_iv_set(result, "@connection", conn); - return result; -} - -/* Error handling */ -#define _E(cond, excep) \ - do { if (cond) vir_error(excep); } while(0) - -NORETURN(static void vir_error(VALUE exception)); - -static void vir_error(VALUE exception) { - rb_exc_raise(exception); -} - -static VALUE create_error(VALUE error, const char* method, const char* msg, - virConnectPtr conn) { - VALUE ruby_errinfo; - virErrorPtr err; - - if (msg == NULL || strlen(msg) == 0) { - char *defmsg; - size_t len; - len = snprintf(NULL, 0, "Call to function %s failed", method) + 1; - defmsg = ALLOC_N(char, len); - snprintf(defmsg, len, "Call to function %s failed", method); - ruby_errinfo = rb_exc_new2(error, defmsg); - free(defmsg); - } else { - ruby_errinfo = rb_exc_new2(error, msg); - } - rb_iv_set(ruby_errinfo, "@libvirt_function_name", rb_str_new2(method)); - - if (conn == NULL) - err = virGetLastError(); - else - err = virConnGetLastError(conn); - - if (err != NULL && err->message != NULL) { - rb_iv_set(ruby_errinfo, "@libvirt_message", rb_str_new2(err->message)); - } - - return ruby_errinfo; -}; - - -/* Connections */ -static void connect_close(void *p) { - int r; - - if (!p) - return; - r = virConnectClose((virConnectPtr) p); - _E(r < 0, create_error(rb_eSystemCallError, "connect_close", - "Connection close failed", p)); -} - -static VALUE connect_new(virConnectPtr p) { - return Data_Wrap_Struct(c_connect, NULL, connect_close, p); -} - -static virConnectPtr connect_get(VALUE s) { - generic_get(Connect, s); -} - -static VALUE conn_attr(VALUE s) { - if (rb_obj_is_instance_of(s, c_connect) != Qtrue) { - s = rb_iv_get(s, "@connection"); - } - if (rb_obj_is_instance_of(s, c_connect) != Qtrue) { - rb_raise(rb_eArgError, "Expected Connection object"); - } - return s; -} - -static virConnectPtr conn(VALUE s) { - s = conn_attr(s); - virConnectPtr conn; - Data_Get_Struct(s, virConnect, conn); - if (!conn) - rb_raise(rb_eArgError, "Connection has been closed"); - return conn; -} - -/* Domains */ -static void domain_free(void *d) { - generic_free(Domain, d); -} - -static virDomainPtr domain_get(VALUE s) { - generic_get(Domain, s); -} - -static VALUE domain_new(virDomainPtr d, VALUE conn) { - return generic_new(c_domain, d, conn, domain_free); -} - -/* Network */ -#if HAVE_TYPE_VIRNETWORKPTR -static void network_free(void *d) { - generic_free(Network, d); -} - -static virNetworkPtr network_get(VALUE s) { - generic_get(Network, s); -} - -static VALUE network_new(virNetworkPtr n, VALUE conn) { - return generic_new(c_network, n, conn, network_free); -} -#endif - -#if HAVE_TYPE_VIRSTORAGEPOOLPTR -/* StoragePool */ -static void pool_free(void *d) { - generic_free(StoragePool, d); -} - -static virStoragePoolPtr pool_get(VALUE s) { - generic_get(StoragePool, s); -} - -static VALUE pool_new(virStoragePoolPtr n, VALUE conn) { - return generic_new(c_storage_pool, n, conn, pool_free); -} -#endif - -/* StorageVol */ -#if HAVE_TYPE_VIRSTORAGEVOLPTR -static void vol_free(void *d) { - generic_free(StorageVol, d); -} - -static virStorageVolPtr vol_get(VALUE s) { - generic_get(StorageVol, s); -} - -static VALUE vol_new(virStorageVolPtr n, VALUE conn) { - return generic_new(c_storage_vol, n, conn, vol_free); -} -#endif - -/* - * Code generating macros. - * - * We only generate function bodies, not the whole function - * declaration. - */ - -/* - * Generate a call to a virConnectNumOf... function. C is the Ruby VALUE - * holding the connection and OBJS is a token indicating what objects to - * get the number of, e.g. 'Domains' - */ -#define gen_conn_num_of(c, objs) \ - do { \ - int result; \ - virConnectPtr conn = connect_get(c); \ - \ - result = virConnectNumOf##objs(conn); \ - _E(result < 0, create_error(e_RetrieveError, "virConnectNumOf" # objs, "", conn)); \ - \ - return INT2NUM(result); \ - } while(0) - -/* - * Generate a call to a virConnectList... function. S is the Ruby VALUE - * holding the connection and OBJS is a token indicating what objects to - * get the number of, e.g. 'Domains' The list function must return an array - * of strings, which is returned as a Ruby array - */ -#define gen_conn_list_names(s, objs) \ - do { \ - int i, r, num; \ - char **names; \ - virConnectPtr conn = connect_get(s); \ - VALUE result; \ - \ - num = virConnectNumOf##objs(conn); \ - _E(num < 0, create_error(e_RetrieveError, "virConnectNumOf" # objs, "", conn)); \ - \ - names = ALLOC_N(char *, num); \ - r = virConnectList##objs(conn, names, num); \ - if (r < 0) { \ - free(names); \ - _E(r < 0, create_error(e_RetrieveError, "virConnectList" # objs, "", conn)); \ - } \ - \ - result = rb_ary_new2(num); \ - for (i=0; i [ libvirt_version, type_version ] - * - * Call - * +virGetVersion+[http://www.libvirt.org/html/libvirt-libvirt.html#virGetVersion] - * to get the version of libvirt and of the hypervisor TYPE. Returns an - * array with two entries of type Libvirt::Version. - * - */ -VALUE libvirt_version(VALUE m, VALUE t) { - unsigned long libVer; - const char *type = NULL; - unsigned long typeVer; - int r; - VALUE result, argv[2]; - - type = StringValueCStr(t); - r = virGetVersion(&libVer, type, &typeVer); - if (r < 0) - rb_raise(rb_eArgError, "Failed to get version for %s", type); - - result = rb_ary_new2(2); - argv[0] = rb_str_new2("libvirt"); - argv[1] = ULONG2NUM(libVer); - rb_ary_push(result, rb_class_new_instance(2, argv, c_libvirt_version)); - argv[0] = t; - argv[1] = ULONG2NUM(typeVer); - rb_ary_push(result, rb_class_new_instance(2, argv, c_libvirt_version)); - return result; -} - -/* - * call-seq: - * Libvirt::open(url) -> Libvirt::Connect - * - * Open a connection to URL with virConnectOpen[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectOpen] - */ -VALUE libvirt_open(VALUE m, VALUE url) { - char *str = NULL; - - if (url) { - str = StringValueCStr(url); - if (!str) - rb_raise(rb_eTypeError, "expected string"); - } - virConnectPtr ptr = virConnectOpen(str); - if (!ptr) - rb_raise(e_ConnectionError, "Failed to open %s", str); - return connect_new(ptr); -} - -/* - * call-seq: - * Libvirt::openReadOnly(url) -> Libvirt::Connect - * - * Open a read-only connection to URL with - * virConnectOpenReadOnly[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectOpenReadOnly] - */ -VALUE libvirt_open_read_only(VALUE m, VALUE url) { - char *str = NULL; - - if (url) { - str = StringValueCStr(url); - if (!str) - rb_raise(rb_eTypeError, "expected string"); - } - virConnectPtr ptr = virConnectOpenReadOnly(str); - if (!ptr) - rb_raise(e_ConnectionError, "Failed to open %s readonly", str); - return connect_new(ptr); -} - -/* - * Class Libvirt::Connect - */ - -/* - * call-seq: - * conn.close - * - * Close the connection - */ -VALUE libvirt_conn_close(VALUE s) { - virConnectPtr conn; - Data_Get_Struct(s, virConnect, conn); - if (conn) { - connect_close(conn); - DATA_PTR(s) = NULL; - } - return Qnil; -} - -/* - * call-seq: - * conn.closed? - * - * Return +true+ if the connection is closed, +false+ if it is open - */ -VALUE libvirt_conn_closed_p(VALUE s) { - virConnectPtr conn; - Data_Get_Struct(s, virConnect, conn); - return (conn==NULL) ? Qtrue : Qfalse; -} - -/* - * call-seq: - * conn.type -> string - * - * Call +virConnectGetType+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectGetType] - */ -VALUE libvirt_conn_type(VALUE s) { - gen_call_string(virConnectGetType, connect_get(s), 0, - connect_get(s)); -} - -/* - * call-seq: - * conn.version -> fixnum - * - * Call +virConnectGetVersion+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectGetVersion] - */ -VALUE libvirt_conn_version(VALUE s) { - int r; - unsigned long v; - virConnectPtr conn = connect_get(s); - - r = virConnectGetVersion(conn, &v); - _E(r < 0, create_error(e_RetrieveError, "virConnectGetVersion", "", conn)); - - return ULONG2NUM(v); -} - -/* - * call-seq: - * conn.hostname -> string - * - * Call +virConnectGetHostname+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectGetHostname] - */ -VALUE libvirt_conn_hostname(VALUE s) { - gen_call_string(virConnectGetHostname, connect_get(s), 1, - connect_get(s)); -} - -/* - * Call +virConnectGetURI+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectGetURI] - */ -VALUE libvirt_conn_uri(VALUE s) { - virConnectPtr conn = connect_get(s); - gen_call_string(virConnectGetURI, conn, 1, - conn); -} - -/* - * Call +virConnectGetMaxVcpus+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectGetMaxVcpus] - */ -VALUE libvirt_conn_max_vcpus(VALUE s, VALUE type) { - int result; - virConnectPtr conn = connect_get(s); - - result = virConnectGetMaxVcpus(conn, StringValueCStr(type)); - _E(result < 0, create_error(e_RetrieveError, "virConnectGetMaxVcpus", "", conn)); - - return INT2NUM(result); -} - -/* - * Call +virNodeInfo+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeGetInfo] - */ -VALUE libvirt_conn_node_get_info(VALUE s){ - int r; - virConnectPtr conn = connect_get(s); - virNodeInfo nodeinfo; - VALUE result; - VALUE modelstr; - - r = virNodeGetInfo(conn, &nodeinfo); - _E(r < 0, create_error(e_RetrieveError, "virNodeGetInfo", "", conn)); - - modelstr = rb_str_new2(nodeinfo.model); - - result = rb_class_new_instance(0, NULL, c_node_info); - rb_iv_set(result, "@model", modelstr); - rb_iv_set(result, "@memory", ULONG2NUM(nodeinfo.memory)); - rb_iv_set(result, "@cpus", UINT2NUM(nodeinfo.cpus)); - rb_iv_set(result, "@mhz", UINT2NUM(nodeinfo.mhz)); - rb_iv_set(result, "@nodes", UINT2NUM(nodeinfo.nodes)); - rb_iv_set(result, "@sockets", UINT2NUM(nodeinfo.sockets)); - rb_iv_set(result, "@cores", UINT2NUM(nodeinfo.cores)); - rb_iv_set(result, "@threads", UINT2NUM(nodeinfo.threads)); - return result; -} - -/* - * Call +virConnectGetCapabilities+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectGetCapabilities] - */ -VALUE libvirt_conn_capabilities(VALUE s) { - virConnectPtr conn = connect_get(s); - gen_call_string(virConnectGetCapabilities, conn, 1, - conn); -} - -/* - * Call +virConnectNumOfDomains+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfDomains] - */ -VALUE libvirt_conn_num_of_domains(VALUE s) { - gen_conn_num_of(s, Domains); -} - -/* - * Call +virConnectListDomains+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListDomains] - */ -VALUE libvirt_conn_list_domains(VALUE s) { - int i, r, num, *ids; - virConnectPtr conn = connect_get(s); - VALUE result; - - num = virConnectNumOfDomains(conn); - _E(num < 0, create_error(e_RetrieveError, "virConnectNumOfDomains", "", conn)); - - ids = ALLOC_N(int, num); - r = virConnectListDomains(conn, ids, num); - if (r < 0) { - free(ids); - _E(r < 0, create_error(e_RetrieveError, "virConnectListDomains", "", conn)); - } - - result = rb_ary_new2(num); - for (i=0; i Libvirt::Domain::Info - * - * Call +virDomainGetInfo+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetInfo] - */ -VALUE libvirt_dom_info(VALUE s) { - virDomainPtr dom = domain_get(s); - virDomainInfo info; - int r; - VALUE result; - - r = virDomainGetInfo(dom, &info); - _E(r < 0, create_error(e_RetrieveError, "virDomainGetInfo", "", conn(s))); - - result = rb_class_new_instance(0, NULL, c_domain_info); - rb_iv_set(result, "@state", CHR2FIX(info.state)); - rb_iv_set(result, "@max_mem", ULONG2NUM(info.maxMem)); - rb_iv_set(result, "@memory", ULONG2NUM(info.memory)); - rb_iv_set(result, "@nr_virt_cpu", INT2FIX((int) info.nrVirtCpu)); - rb_iv_set(result, "@cpu_time", ULL2NUM(info.cpuTime)); - return result; -} - - -/* - * Call +virDomainGetName+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetName] - */ -VALUE libvirt_dom_name(VALUE s) { - gen_call_string(virDomainGetName, conn(s), 0, - domain_get(s)); -} - -/* - * Call +virDomainGetID+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetID] - */ -VALUE libvirt_dom_id(VALUE s) { - virDomainPtr dom = domain_get(s); - unsigned int id; - - id = virDomainGetID(dom); - _E(id < 0, create_error(e_RetrieveError, "virDomainGetID", "", conn(s))); - - return UINT2NUM(id); -} - -/* - * Call +virDomainGetUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetUUIDString] - */ -VALUE libvirt_dom_uuid(VALUE s) { - virDomainPtr dom = domain_get(s); - char uuid[VIR_UUID_STRING_BUFLEN]; - int r; - - r = virDomainGetUUIDString(dom, uuid); - _E(r < 0, create_error(e_RetrieveError, "virDomainGetUUIDString", "", conn(s))); - - return rb_str_new2((char *) uuid); -} - -/* - * Call +virDomainGetOSType+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetOSType] - */ -VALUE libvirt_dom_os_type(VALUE s) { - gen_call_string(virDomainGetOSType, conn(s), 1, - domain_get(s)); -} - -/* - * Call +virDomainGetMaxMemory+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetMaxMemory] - */ -VALUE libvirt_dom_max_memory(VALUE s) { - virDomainPtr dom = domain_get(s); - unsigned long max_memory; - - max_memory = virDomainGetMaxMemory(dom); - _E(max_memory == 0, create_error(e_RetrieveError, "virDomainGetMaxMemory", "", conn(s))); - - return ULONG2NUM(max_memory); -} - -/* - * Call +virDomainSetMaxMemory+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetMaxMemory] - */ -VALUE libvirt_dom_max_memory_set(VALUE s, VALUE max_memory) { - virDomainPtr dom = domain_get(s); - int r; - - r = virDomainSetMaxMemory(dom, NUM2ULONG(max_memory)); - _E(r < 0, create_error(e_DefinitionError, "virDomainSetMaxMemory", "", conn(s))); - - return ULONG2NUM(max_memory); -} - -/* - * Call +virDomainSetMemory+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetMemory] - */ -VALUE libvirt_dom_memory_set(VALUE s, VALUE memory) { - virDomainPtr dom = domain_get(s); - int r; - - r = virDomainSetMemory(dom, NUM2ULONG(memory)); - _E(r < 0, create_error(e_DefinitionError, "virDomainSetMemory", "", conn(s))); - - return ULONG2NUM(memory); -} - -/* - * Call +virDomainGetMaxVcpus+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetMaxVcpus] - */ -VALUE libvirt_dom_max_vcpus(VALUE s) { - virDomainPtr dom = domain_get(s); - int vcpus; - - vcpus = virDomainGetMaxVcpus(dom); - _E(vcpus < 0, create_error(e_RetrieveError, "virDomainGetMaxVcpus", "", conn(s))); - - return INT2NUM(vcpus); -} - - -/* - * Call +virDomainSetVcpus+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetVcpus] - */ -VALUE libvirt_dom_vcpus_set(VALUE s, VALUE nvcpus) { - virDomainPtr dom = domain_get(s); - int r; - - r = virDomainSetVcpus(dom, NUM2UINT(nvcpus)); - _E(r < 0, create_error(e_DefinitionError, "virDomainSetVcpus", "", conn(s))); - - return r; -} - -/* - * Call +virDomainPinVcpu+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainPinVcpu] - */ -VALUE libvirt_dom_pin_vcpu(VALUE s, VALUE vcpu, VALUE cpulist) { - virDomainPtr dom = domain_get(s); - int r, i, len, maplen; - unsigned char *cpumap; - virNodeInfo nodeinfo; - virConnectPtr c = conn(s); - - r = virNodeGetInfo(c, &nodeinfo); - _E(r < 0, create_error(e_RetrieveError, "virNodeGetInfo", "", c)); - - maplen = VIR_CPU_MAPLEN(nodeinfo.cpus); - cpumap = ALLOC_N(unsigned char, maplen); - MEMZERO(cpumap, unsigned char, maplen); - - len = RARRAY(cpulist)->len; - for(i = 0; i < len; i++) { - VALUE e = rb_ary_entry(cpulist, i); - VIR_USE_CPU(cpumap, NUM2UINT(e)); - } - - r = virDomainPinVcpu(dom, NUM2UINT(vcpu), cpumap, maplen); - free(cpumap); - _E(r < 0, create_error(e_RetrieveError, "virDomainPinVcpu", "", c)); - - return r; -} - - -/* - * Call +virDomainGetXMLDesc+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetXMLDesc] - */ -VALUE libvirt_dom_xml_desc(int argc, VALUE *argv, VALUE s) { - VALUE flags; - - rb_scan_args(argc, argv, "01", &flags); - - if (NIL_P(flags)) - flags = INT2FIX(0); - - gen_call_string(virDomainGetXMLDesc, conn(s), 1, - domain_get(s), 0); -} - -/* - * Call +virDomainUndefine+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainUndefine] - */ -VALUE libvirt_dom_undefine(VALUE s) { - gen_call_void(virDomainUndefine, conn(s), - domain_get(s)); -} - -/* - * Call +virDomainCreate+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainCreate] - */ -VALUE libvirt_dom_create(VALUE s) { - gen_call_void(virDomainCreate, conn(s), - domain_get(s)); -} - -/* - * Call +virDomainGetAutostart+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainGetAutostart] - */ -VALUE libvirt_dom_autostart(VALUE s){ - virDomainPtr dom = domain_get(s); - int r, autostart; - - r = virDomainGetAutostart(dom, &autostart); - _E(r < 0, create_error(e_RetrieveError, "virDomainAutostart", "", conn(s))); - - return autostart ? Qtrue : Qfalse; -} - -/* - * Call +virDomainSetAutostart+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSetAutostart] - */ -VALUE libvirt_dom_autostart_set(VALUE s, VALUE autostart) { - gen_call_void(virDomainSetAutostart, conn(s), - domain_get(s), RTEST(autostart) ? 1 : 0); -} - -/* - * Call +virDomainCreateLinux+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainCreateLinux] - */ -VALUE libvirt_conn_create_linux(int argc, VALUE *argv, VALUE c) { - virDomainPtr dom; - virConnectPtr conn = connect_get(c); - char *xmlDesc; - VALUE flags, xml; - - rb_scan_args(argc, argv, "11", &xml, &flags); - - if (NIL_P(flags)) - flags = INT2FIX(0); - - xmlDesc = StringValueCStr(xml); - - dom = virDomainCreateLinux(conn, xmlDesc, NUM2UINT(flags)); - _E(dom == NULL, create_error(e_Error, "virDomainCreateLinux", "", conn)); - - return domain_new(dom, c); -} - -/* - * Call +virDomainLookupByName+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainLookupByName] - */ -VALUE libvirt_conn_lookup_domain_by_name(VALUE c, VALUE name) { - virDomainPtr dom; - virConnectPtr conn = connect_get(c); - - dom = virDomainLookupByName(conn, StringValueCStr(name)); - _E(dom == NULL, create_error(e_RetrieveError, "virDomainLookupByName", "", conn)); - - return domain_new(dom, c); -} - -/* - * Call +virDomainLookupByID+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainLookupByID] - */ -VALUE libvirt_conn_lookup_domain_by_id(VALUE c, VALUE id) { - virDomainPtr dom; - virConnectPtr conn = connect_get(c); - - dom = virDomainLookupByID(conn, NUM2INT(id)); - _E(dom == NULL, create_error(e_RetrieveError, "virDomainLookupByID", "", conn)); - - return domain_new(dom, c); -} - -/* - * Call +virDomainLookupByUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainLookupByUUIDString] - */ -VALUE libvirt_conn_lookup_domain_by_uuid(VALUE c, VALUE uuid) { - virDomainPtr dom; - virConnectPtr conn = connect_get(c); - - dom = virDomainLookupByUUIDString(conn, StringValueCStr(uuid)); - _E(dom == NULL, create_error(e_RetrieveError, "virDomainLookupByUUID", "", conn)); - - return domain_new(dom, c); -} - -/* - * Call +virDomainDefineXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainDefineXML] - */ -VALUE libvirt_conn_define_domain_xml(VALUE c, VALUE xml) { - virDomainPtr dom; - virConnectPtr conn = connect_get(c); - - dom = virDomainDefineXML(conn, StringValueCStr(xml)); - _E(dom == NULL, create_error(e_DefinitionError, "virDomainDefineXML", "", conn)); - - return domain_new(dom, c); -} - -/* - * Call +virDomainFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainFree] - */ -VALUE libvirt_dom_free(VALUE s) { - gen_call_free(Domain, s); -} - -/* - * Class Libvirt::Network - */ - -#if HAVE_TYPE_VIRNETWORKPTR -/* - * Call +virNetworkLookupByName+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkLookupByName] - */ -VALUE libvirt_conn_lookup_network_by_name(VALUE c, VALUE name) { - virNetworkPtr netw; - virConnectPtr conn = connect_get(c); - - netw = virNetworkLookupByName(conn, StringValueCStr(name)); - _E(netw == NULL, create_error(e_RetrieveError, "virNetworkLookupByName", "", conn)); - - return network_new(netw, c); -} - -/* - * Call +virNetworkLookupByUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkLookupByUUIDString] - */ -VALUE libvirt_conn_lookup_network_by_uuid(VALUE c, VALUE uuid) { - virNetworkPtr netw; - virConnectPtr conn = connect_get(c); - - netw = virNetworkLookupByUUIDString(conn, StringValueCStr(uuid)); - _E(netw == NULL, create_error(e_RetrieveError, "virNetworkLookupByUUID", "", conn)); - - return network_new(netw, c); -} - -/* - * Call +virNetworkCreateXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkCreateXML] - */ -VALUE libvirt_conn_create_network_xml(VALUE c, VALUE xml) { - virNetworkPtr netw; - virConnectPtr conn = connect_get(c); - char *xmlDesc; - - xmlDesc = StringValueCStr(xml); - - netw = virNetworkCreateXML(conn, xmlDesc); - _E(netw == NULL, create_error(e_Error, "virNetworkCreateXML", "", conn)); - - return network_new(netw, c); -} - -/* - * Call +virNetworkDefineXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkDefineXML] - */ -VALUE libvirt_conn_define_network_xml(VALUE c, VALUE xml) { - virNetworkPtr netw; - virConnectPtr conn = connect_get(c); - - netw = virNetworkDefineXML(conn, StringValueCStr(xml)); - _E(netw == NULL, create_error(e_DefinitionError, "virNetworkDefineXML", "", conn)); - - return network_new(netw, c); -} -#endif - -#if HAVE_TYPE_VIRNETWORKPTR -/* - * Call +virNetworkUndefine+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkUndefine] - */ -VALUE libvirt_netw_undefine(VALUE s) { - gen_call_void(virNetworkUndefine, conn(s), - network_get(s)); -} - -/* - * Call +virNetworkCreate+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkCreate] - */ -VALUE libvirt_netw_create(VALUE s) { - gen_call_void(virNetworkCreate, conn(s), - network_get(s)); -} - -/* - * Call +virNetworkDestroy+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkDestroy] - */ -VALUE libvirt_netw_destroy(VALUE s) { - gen_call_void(virNetworkDestroy, conn(s), - network_get(s)); -} - -/* - * Call +virNetworkGetName+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkGetName] - */ -VALUE libvirt_netw_name(VALUE s) { - gen_call_string(virNetworkGetName, conn(s), 0, - network_get(s)); -} - -/* - * Call +virNetworkGetUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkGetUUIDString] - */ -VALUE libvirt_netw_uuid(VALUE s) { - virNetworkPtr netw = network_get(s); - char uuid[VIR_UUID_STRING_BUFLEN]; - int r; - - r = virNetworkGetUUIDString(netw, uuid); - _E(r < 0, create_error(e_RetrieveError, "virNetworkGetUUIDString", "", conn(s))); - - return rb_str_new2((char *) uuid); -} - -/* - * Call +virNetworkGetXMLDesc+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkGetXMLDesc] - */ -VALUE libvirt_netw_xml_desc(int argc, VALUE *argv, VALUE s) { - VALUE flags; - - rb_scan_args(argc, argv, "01", &flags); - - if (NIL_P(flags)) - flags = INT2FIX(0); - - gen_call_string(virNetworkGetXMLDesc, conn(s), 1, - network_get(s), NUM2UINT(flags)); -} - -/* - * Call +virNetworkGetBridgeName+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkGetBridgeName] - */ -VALUE libvirt_netw_bridge_name(VALUE s) { - gen_call_string(virNetworkGetBridgeName, conn(s), 1, - network_get(s)); -} - -/* - * Call +virNetworkGetAutostart+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkGetAutostart] - */ -VALUE libvirt_netw_autostart(VALUE s){ - virNetworkPtr netw = network_get(s); - int r, autostart; - - r = virNetworkGetAutostart(netw, &autostart); - _E(r < 0, create_error(e_RetrieveError, "virNetworkAutostart", "", conn(s))); - - return autostart ? Qtrue : Qfalse; -} - -/* - * Call +virNetworkSetAutostart+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkSetAutostart] - */ -VALUE libvirt_netw_autostart_set(VALUE s, VALUE autostart) { - gen_call_void(virNetworkSetAutostart, conn(s), - network_get(s), RTEST(autostart) ? 1 : 0); -} - -/* - * Call +virNetworkFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkFree] - */ -VALUE libvirt_netw_free(VALUE s) { - gen_call_free(Network, s); -} -#endif - -/* - * Libvirt::StoragePool - */ - -#if HAVE_TYPE_VIRSTORAGEPOOLPTR -/* - * Call +virStoragePoolLookupByName+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolLookupByName] - */ -VALUE libvirt_conn_lookup_pool_by_name(VALUE c, VALUE name) { - virStoragePoolPtr pool; - virConnectPtr conn = connect_get(c); - - pool = virStoragePoolLookupByName(conn, StringValueCStr(name)); - _E(pool == NULL, create_error(e_RetrieveError, "virStoragePoolLookupByName", "", conn)); - - return pool_new(pool, c); -} - -/* - * Call +virStoragePoolLookupByUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolLookupByUUIDString] - */ -VALUE libvirt_conn_lookup_pool_by_uuid(VALUE c, VALUE uuid) { - virStoragePoolPtr pool; - virConnectPtr conn = connect_get(c); - - pool = virStoragePoolLookupByUUIDString(conn, StringValueCStr(uuid)); - _E(pool == NULL, create_error(e_RetrieveError, "virStoragePoolLookupByUUID", "", conn)); - - return pool_new(pool, c); -} - -/* - * Call +virStoragePoolLookupByVolume+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolLookupByVolume] - */ -VALUE libvirt_vol_get_pool(VALUE v) { - virStoragePoolPtr pool; - - pool = virStoragePoolLookupByVolume(vol_get(v)); - _E(pool == NULL, create_error(e_RetrieveError, "virStoragePoolLookupByVolume", "", conn(v))); - - return pool_new(pool, conn_attr(v)); -} - -/* - * Call +virStoragePoolCreateXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolCreateXML] - */ -VALUE libvirt_conn_create_pool_xml(int argc, VALUE *argv, VALUE c) { - virStoragePoolPtr pool; - virConnectPtr conn = connect_get(c); - char *xmlDesc; - VALUE xml, flags; - - rb_scan_args(argc, argv, "11", &xml, &flags); - - if (NIL_P(flags)) - flags = INT2FIX(0); - - xmlDesc = StringValueCStr(xml); - - pool = virStoragePoolCreateXML(conn, xmlDesc, NUM2UINT(flags)); - _E(pool == NULL, create_error(e_Error, "virStoragePoolCreateXML", "", conn)); - - return pool_new(pool, c); -} - -/* - * Call +virStoragePoolDefineXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolDefineXML] - */ -VALUE libvirt_conn_define_pool_xml(int argc, VALUE *argv, VALUE c) { - virStoragePoolPtr pool; - virConnectPtr conn = connect_get(c); - VALUE xml, flags; - - rb_scan_args(argc, argv, "11", &xml, &flags); - - if (NIL_P(flags)) - flags = INT2FIX(0); - - pool = virStoragePoolDefineXML(conn, StringValueCStr(xml), NUM2UINT(flags)); - _E(pool == NULL, create_error(e_DefinitionError, "virStoragePoolDefineXML", "", conn)); - - return pool_new(pool, c); -} - -/* - * Call +virStoragePoolBuild+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolBuild] - */ -VALUE libvirt_pool_build(int argc, VALUE *argv, VALUE p) { - VALUE flags; - - rb_scan_args(argc, argv, "01", &flags); +static VALUE c_libvirt_version; - if (NIL_P(flags)) - flags = INT2FIX(0); +VALUE m_libvirt; - gen_call_void(virStoragePoolBuild, conn(p), - pool_get(p), NUM2UINT(flags)); -} +/* define additional errors here */ +static VALUE e_ConnectionError; /* ConnectionError - error during connection establishment */ +VALUE e_DefinitionError; +VALUE e_RetrieveError; +VALUE e_Error; +VALUE e_NoSupportError; -/* - * Call +virStoragePoolUndefine+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolUndefine] - */ -VALUE libvirt_pool_undefine(VALUE p) { - gen_call_void(virStoragePoolUndefine, conn(p), - pool_get(p)); +/* custom error function to suppress libvirt printing to stderr */ +static void rubyLibvirtErrorFunc(void *userdata, virErrorPtr err){ } /* - * Call +virStoragePoolCreate+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolCreate] + * call-seq: + * Libvirt::version(type=nil) -> [ libvirt_version, type_version ] + * + * Call + * +virGetVersion+[http://www.libvirt.org/html/libvirt-libvirt.html#virGetVersion] + * to get the version of libvirt and of the hypervisor TYPE. */ -VALUE libvirt_pool_create(int argc, VALUE *argv, VALUE p) { - VALUE flags; - - rb_scan_args(argc, argv, "01", &flags); +static VALUE libvirt_version(int argc, VALUE *argv, VALUE m) { + unsigned long libVer; + VALUE type; + unsigned long typeVer; + int r; + VALUE result, rargv[2]; - if (NIL_P(flags)) - flags = INT2FIX(0); + rb_scan_args(argc, argv, "01", &type); - gen_call_void(virStoragePoolCreate, conn(p), - pool_get(p), NUM2UINT(flags)); -} + r = virGetVersion(&libVer, get_string_or_nil(type), &typeVer); + _E(r < 0, create_error(rb_eArgError, "virGetVersion", NULL)); -/* - * Call +virStoragePoolDestroy+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolDestroy] - */ -VALUE libvirt_pool_destroy(VALUE p) { - gen_call_void(virStoragePoolDestroy, conn(p), - pool_get(p)); + result = rb_ary_new2(2); + rargv[0] = rb_str_new2("libvirt"); + rargv[1] = ULONG2NUM(libVer); + rb_ary_push(result, rb_class_new_instance(2, rargv, c_libvirt_version)); + rargv[0] = type; + rargv[1] = ULONG2NUM(typeVer); + rb_ary_push(result, rb_class_new_instance(2, rargv, c_libvirt_version)); + return result; } -/* - * Call +virStoragePoolDelete+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolDelete] - */ -VALUE libvirt_pool_delete(int argc, VALUE *argv, VALUE p) { - VALUE flags; - - rb_scan_args(argc, argv, "01", &flags); - - if (NIL_P(flags)) - flags = INT2FIX(0); +static VALUE internal_open(int argc, VALUE *argv, VALUE m, int readonly) +{ + VALUE uri; + char *uri_c; + virConnectPtr conn; - gen_call_void(virStoragePoolDelete, conn(p), - pool_get(p), NUM2UINT(flags)); -} + rb_scan_args(argc, argv, "01", &uri); -/* - * Call +virStoragePoolRefresh+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolRefresh] - */ -VALUE libvirt_pool_refresh(int argc, VALUE *argv, VALUE p) { - VALUE flags; + uri_c = get_string_or_nil(uri); - rb_scan_args(argc, argv, "01", &flags); + if (readonly) + conn = virConnectOpenReadOnly(uri_c); + else + conn = virConnectOpen(uri_c); - if (NIL_P(flags)) - flags = INT2FIX(0); + _E(conn == NULL, create_error(e_ConnectionError, + readonly ? "virConnectOpenReadOnly" : "virConnectOpen", + NULL)); - gen_call_void(virStoragePoolRefresh, conn(p), - pool_get(p), NUM2UINT(flags)); + return connect_new(conn); } /* - * Call +virStoragePoolGetName+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolGetName] + * call-seq: + * Libvirt::open(uri=nil) -> Libvirt::Connect + * + * Call + * +virConnectOpen+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectOpen] + * to open a connection to a URL. */ -VALUE libvirt_pool_name(VALUE s) { - const char *name; - - name = virStoragePoolGetName(pool_get(s)); - _E(name == NULL, create_error(e_RetrieveError, "virStoragePoolGetName", "", conn(s))); - - return rb_str_new2(name); +static VALUE libvirt_open(int argc, VALUE *argv, VALUE m) { + return internal_open(argc, argv, m, 0); } /* - * Call +virStoragePoolGetUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolGetUUIDString] + * call-seq: + * Libvirt::open_read_only(uri=nil) -> Libvirt::Connect + * + * Call + * +virConnectOpenReadOnly+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectOpenReadOnly] + * to open a read-only connection to a URL. */ -VALUE libvirt_pool_uuid(VALUE s) { - char uuid[VIR_UUID_STRING_BUFLEN]; - int r; - - r = virStoragePoolGetUUIDString(pool_get(s), uuid); - _E(r < 0, create_error(e_RetrieveError, "virStoragePoolGetUUIDString", "", conn(s))); - - return rb_str_new2((char *) uuid); +static VALUE libvirt_open_read_only(int argc, VALUE *argv, VALUE m) { + return internal_open(argc, argv, m, 1); } -/* - * Call +virStoragePoolGetInfo+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolGetInfo] - */ -VALUE libvirt_pool_info(VALUE s) { - virStoragePoolInfo info; - int r; +#if HAVE_VIRCONNECTOPENAUTH +static int libvirt_auth_callback_wrapper(virConnectCredentialPtr cred, + unsigned int ncred, void *cbdata) { + VALUE userdata; + VALUE newcred; + int i; VALUE result; - r = virStoragePoolGetInfo(pool_get(s), &info); - _E(r < 0, create_error(e_RetrieveError, "virStoragePoolGetInfo", "", conn(s))); + userdata = (VALUE)cbdata; - result = rb_class_new_instance(0, NULL, c_storage_pool_info); - rb_iv_set(result, "@state", INT2FIX(info.state)); - rb_iv_set(result, "@capacity", ULL2NUM(info.capacity)); - rb_iv_set(result, "@allocation", ULL2NUM(info.allocation)); - rb_iv_set(result, "@available", ULL2NUM(info.available)); + if (!rb_block_given_p()) + rb_raise(rb_eRuntimeError, "No block given, this should never happen!\n"); - return result; -} - -/* - * Call +virStoragePoolGetXMLDesc+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolGetXMLDesc] - */ -VALUE libvirt_pool_xml_desc(int argc, VALUE *argv, VALUE s) { - VALUE flags; - - rb_scan_args(argc, argv, "01", &flags); + for (i = 0; i < ncred; i++) { + newcred = rb_hash_new(); - if (NIL_P(flags)) - flags = INT2FIX(0); - - gen_call_string(virStoragePoolGetXMLDesc, conn(s), 1, - pool_get(s), NUM2UINT(flags)); + rb_hash_aset(newcred, rb_str_new2("type"), INT2NUM(cred[i].type)); + rb_hash_aset(newcred, rb_str_new2("prompt"), + rb_str_new2(cred[i].prompt)); + if (cred[i].challenge) + rb_hash_aset(newcred, rb_str_new2("challenge"), + rb_str_new2(cred[i].challenge)); + else + rb_hash_aset(newcred, rb_str_new2("challenge"), Qnil); + if (cred[i].defresult) + rb_hash_aset(newcred, rb_str_new2("defresult"), + rb_str_new2(cred[i].defresult)); + else + rb_hash_aset(newcred, rb_str_new2("defresult"), Qnil); + rb_hash_aset(newcred, rb_str_new2("result"), Qnil); + rb_hash_aset(newcred, rb_str_new2("userdata"), userdata); + + result = rb_yield(newcred); + if (NIL_P(result)) { + cred[i].result = NULL; + cred[i].resultlen = 0; + } + else { + cred[i].result = strdup(StringValueCStr(result)); + cred[i].resultlen = strlen(cred[i].result); + } + } + + return 0; } -/* - * Call +virStoragePoolGetAutostart+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolGetAutostart] - */ -VALUE libvirt_pool_autostart(VALUE s){ - int r, autostart; - r = virStoragePoolGetAutostart(pool_get(s), &autostart); - _E(r < 0, create_error(e_RetrieveError, "virStoragePoolGetAutostart", "", conn(s))); +struct wrap_callout { + char *uri; + virConnectAuthPtr auth; + unsigned int flags; +}; - return autostart ? Qtrue : Qfalse; -} +static VALUE rb_open_auth_wrap(VALUE arg) { + struct wrap_callout *e = (struct wrap_callout *)arg; -/* - * Call +virStoragePoolSetAutostart+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolSetAutostart] - */ -VALUE libvirt_pool_autostart_set(VALUE s, VALUE autostart) { - gen_call_void(virStoragePoolSetAutostart, conn(s), - pool_get(s), RTEST(autostart) ? 1 : 0); + return (VALUE)virConnectOpenAuth(e->uri, e->auth, e->flags); } -/* - * Call +virStoragePoolNumOfVolumes+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolNumOfVolumes] - */ -VALUE libvirt_pool_num_of_volumes(VALUE s) { - int n = virStoragePoolNumOfVolumes(pool_get(s)); - _E(n < 0, create_error(e_RetrieveError, "virStoragePoolNumOfVolumes", "", conn(s))); - - return INT2FIX(n); +static VALUE rb_num2int_wrap(VALUE arg) { + return NUM2INT(arg); } /* - * Call +virStoragePoolListVolumes+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolListVolumes] - */ -VALUE libvirt_pool_list_volumes(VALUE s) { - int i, r, num; - char **names; - virStoragePoolPtr pool = pool_get(s); - VALUE result; - - num = virStoragePoolNumOfVolumes(pool); - _E(num < 0, create_error(e_RetrieveError, "virStoragePoolNumOfVolumes", "", conn(s))); - - names = ALLOC_N(char *, num); - r = virStoragePoolListVolumes(pool, names, num); - if (r < 0) { - free(names); - _E(r < 0, create_error(e_RetrieveError, "virStoragePoolListVolumes", "", conn(s))); - } - - result = rb_ary_new2(num); - for (i=0; i Libvirt::Connect + * + * Call + * +virConnectOpenAuth+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectOpenAuth] + * to open a connection to a libvirt URI, with a possible authentication block. + * If an authentication block is desired, then credlist should be an array that + * specifies which credentials the authentication block is willing to support; + * the full list is available at http://libvirt.org/html/libvirt-libvirt.html#virConnectCredentialType. + * If userdata is not nil and an authentication block is given, userdata will + * be passed unaltered into the authentication block. The flags parameter + * controls how to open connection. The only options currently available for + * flags are 0 for a read/write connection and Libvirt::CONNECT_RO for a + * read-only connection. + * + * If the credlist is not empty, and an authentication block is given, the + * authentication block will be called once for each credential necessary + * to complete the authentication. The authentication block will be passed a + * single parameter, which is a hash of values containing information necessary + * to complete authentication. This hash contains 5 elements: + * + * type - the type of credential to be examined + * + * prompt - a suggested prompt to show to the user + * + * challenge - any additional challenge information + * + * defresult - a default result to use if credentials could not be obtained + * + * userdata - the userdata passed into open_auth initially + * + * The authentication block should return the result of collecting the + * information; these results will then be sent to libvirt for authentication. + */ +static VALUE libvirt_open_auth(int argc, VALUE *argv, VALUE m) { + virConnectAuthPtr auth; + VALUE uri; + VALUE credlist; + VALUE userdata; + VALUE flags_val; + char *uri_c; + virConnectPtr conn = NULL; + unsigned int flags; + int auth_alloc; + int i; + VALUE tmp; + int exception = 0; + struct rb_ary_entry_arg args; + struct wrap_callout callargs; + + rb_scan_args(argc, argv, "04", &uri, &credlist, &userdata, &flags_val); + + /* handle the optional URI */ + uri_c = get_string_or_nil(uri); + + /* handle the optional flags */ + if (NIL_P(flags_val)) + flags = 0; + else + flags = NUM2UINT(flags_val); -/* - * Call +virStoragePoolFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolFree] - */ -VALUE libvirt_pool_free(VALUE s) { - gen_call_free(StoragePool, s); -} -#endif + if (rb_block_given_p()) { + auth = ALLOC(virConnectAuth); + auth_alloc = 1; + + if (TYPE(credlist) == T_NIL) + auth->ncredtype = 0; + else if (TYPE(credlist) == T_ARRAY) + auth->ncredtype = RARRAY_LEN(credlist); + else + rb_raise(rb_eTypeError, "wrong argument type (expected Array or nil)"); + auth->credtype = NULL; + if (auth->ncredtype > 0) { + /* we don't use ALLOC_N here because that can throw an exception, + * and leak the auth pointer. Instead we use normal malloc + * (which has a slightly higher chance of returning NULL), and + * then properly cleanup if it fails + */ + auth->credtype = malloc(sizeof(int) * auth->ncredtype); + if (auth->credtype == NULL) { + xfree(auth); + rb_memerror(); + } + for (i = 0; i < auth->ncredtype; i++) { + args.arr = credlist; + args.elem = i; + tmp = rb_protect(rb_ary_entry_wrap, (VALUE)&args, &exception); + if (exception) + goto do_cleanup; + + auth->credtype[i] = rb_protect(rb_num2int_wrap, tmp, + &exception); + if (exception) + goto do_cleanup; + } + } + + auth->cb = libvirt_auth_callback_wrapper; + auth->cbdata = (void *)userdata; + } + else { + auth = virConnectAuthPtrDefault; + auth_alloc = 0; + } + + callargs.uri = uri_c; + callargs.auth = auth; + callargs.flags = flags; + + conn = (virConnectPtr)rb_protect(rb_open_auth_wrap, (VALUE)&callargs, + &exception); + +do_cleanup: + if (auth_alloc) { + free(auth->credtype); + xfree(auth); + } + + if (exception) + rb_jump_tag(exception); + + _E(conn == NULL, create_error(e_ConnectionError, "virConnectOpenAuth", + NULL)); + + return connect_new(conn); +} +#endif + +#if HAVE_VIREVENTREGISTERIMPL +static VALUE add_handle, update_handle, remove_handle; +static VALUE add_timeout, update_timeout, remove_timeout; /* - * Libvirt::StorageVol - */ -#if HAVE_TYPE_VIRSTORAGEVOLPTR -/* - * Call +virStorageVolLookupByName+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolLookupByName] - */ -VALUE libvirt_pool_lookup_vol_by_name(VALUE p, VALUE name) { - virStorageVolPtr vol; - - vol = virStorageVolLookupByName(pool_get(p), StringValueCStr(name)); - _E(vol == NULL, create_error(e_RetrieveError, "virStorageVolLookupByName", "", conn(p))); + * call-seq: + * Libvirt::event_invoke_handle_callback(handle, fd, events, opaque) -> Qnil + * + * Unlike most of the other functions in the ruby-libvirt bindings, this one + * does not directly correspond to a libvirt API function. Instead, this + * module method (and event_invoke_timeout_callback) are meant to be called + * when there is an event of interest to libvirt on one of the file descriptors + * that libvirt uses. The application is notified of the file descriptors + * that libvirt uses via the callbacks from Libvirt::event_register_impl. When + * there is an event of interest, the application must call + * event_invoke_timeout_callback to ensure proper operation. + * + * Libvirt::event_invoke_handle_callback takes 4 arguments: + * + * handle + * an application specific handle ID. This can be any integer, but + * must be unique from all other libvirt handles in the application. + * fd + * the file descriptor of interest. This was given to the application + * as a callback to add_handle of Libvirt::event_register_impl + * events + * the events that have occured on the fd. Note that the events are + * libvirt specific, and are some combination of + * Libvirt::EVENT_HANDLE_READABLE, Libvirt::EVENT_HANDLE_WRITABLE, + * Libvirt::EVENT_HANDLE_ERROR, Libvirt::EVENT_HANDLE_HANGUP. To + * notify libvirt of more than one event at a time, these values should + * be logically OR'ed together. + * opaque + * the opaque data passed from libvirt during the + * Libvirt::event_register_impl add_handle callback. To ensure proper + * operation this data must be passed through to + * event_invoke_handle_callback without modification. + */ +static VALUE libvirt_event_invoke_handle_callback(VALUE m, VALUE handle, + VALUE fd, VALUE events, + VALUE opaque) { + virEventHandleCallback cb; + void *op; + VALUE libvirt_cb; + VALUE libvirt_opaque; + + if (TYPE(opaque) != T_HASH) + rb_raise(rb_eTypeError, + "wrong event callback argument type (expected Hash)"); - return vol_new(vol, conn_attr(p)); -} + libvirt_cb = rb_hash_aref(opaque, rb_str_new2("libvirt_cb")); -/* - * Call +virStorageVolLookupByKey+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolLookupByKey] - */ -VALUE libvirt_pool_lookup_vol_by_key(VALUE p, VALUE key) { - virStorageVolPtr vol; + /* This is equivalent to Data_Get_Struct; I reproduce it here because + * I don't want the additional type-cast that Data_Get_Struct does + */ + Check_Type(libvirt_cb, T_DATA); + cb = DATA_PTR(libvirt_cb); - // FIXME: Why does this take a connection, not a pool ? - vol = virStorageVolLookupByKey(conn(p), StringValueCStr(key)); - _E(vol == NULL, create_error(e_RetrieveError, "virStorageVolLookupByKey", "", conn(p))); + if (cb) { + libvirt_opaque = rb_hash_aref(opaque, rb_str_new2("opaque")); + Data_Get_Struct(libvirt_opaque, void *, op); + cb(NUM2INT(handle), NUM2INT(fd), NUM2INT(events), op); + } - return vol_new(vol, conn_attr(p)); + return Qnil; } /* - * Call +virStorageVolLookupByPath+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolLookupByPath] - */ -VALUE libvirt_pool_lookup_vol_by_path(VALUE p, VALUE path) { - virStorageVolPtr vol; + * call-seq: + * Libvirt::event_invoke_timeout_callback(timer, opaque) -> Qnil + * + * Unlike most of the other functions in the ruby-libvirt bindings, this one + * does not directly correspond to a libvirt API function. Instead, this + * module method (and event_invoke_handle_callback) are meant to be called + * when there is a timeout of interest to libvirt. The application is + * notified of the timers that libvirt uses via the callbacks from + * Libvirt::event_register_impl. When a timeout expires, the application must + * call event_invoke_timeout_callback to ensure proper operation. + * + * Libvirt::event_invoke_timeout_callback takes 2 arguments: + * + * handle + * an application specific timer ID. This can be any integer, but + * must be unique from all other libvirt timers in the application. + * opaque + * the opaque data passed from libvirt during the + * Libvirt::event_register_impl add_handle callback. To ensure proper + * operation this data must be passed through to + * event_invoke_handle_callback without modification. + */ +static VALUE libvirt_event_invoke_timeout_callback(VALUE m, VALUE timer, + VALUE opaque) { + virEventTimeoutCallback cb; + void *op; + VALUE libvirt_cb; + VALUE libvirt_opaque; + + if (TYPE(opaque) != T_HASH) + rb_raise(rb_eTypeError, + "wrong event callback argument type (expected Hash)"); - // FIXME: Why does this take a connection, not a pool ? - vol = virStorageVolLookupByPath(conn(p), StringValueCStr(path)); - _E(vol == NULL, create_error(e_RetrieveError, "virStorageVolLookupByPath", "", conn(p))); + libvirt_cb = rb_hash_aref(opaque, rb_str_new2("libvirt_cb")); - return vol_new(vol, conn_attr(p)); -} + /* This is equivalent to Data_Get_Struct; I reproduce it here because + * I don't want the additional type-cast that Data_Get_Struct does + */ + Check_Type(libvirt_cb, T_DATA); + cb = DATA_PTR(libvirt_cb); -/* - * Call +virStorageVolGetName+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolGetName] - */ -VALUE libvirt_vol_name(VALUE v) { - gen_call_string(virStorageVolGetName, conn(v), 0, - vol_get(v)); -} + if (cb) { + libvirt_opaque = rb_hash_aref(opaque, rb_str_new2("opaque")); + Data_Get_Struct(libvirt_opaque, void *, op); + cb(NUM2INT(timer), op); + } -/* - * Call +virStorageVolGetKey+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolGetKey] - */ -VALUE libvirt_vol_key(VALUE v) { - gen_call_string(virStorageVolGetKey, conn(v), 0, - vol_get(v)); + return Qnil; } -/* - * Call +virStorageVolCreateXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolCreateXML] - */ -VALUE libvirt_pool_vol_create_xml(int argc, VALUE *argv, VALUE p) { - virStorageVolPtr vol; - virConnectPtr c = conn(p); - char *xmlDesc; - VALUE xml, flags; - - rb_scan_args(argc, argv, "11", &xml, &flags); - - if (NIL_P(flags)) - flags = INT2FIX(0); - - xmlDesc = StringValueCStr(xml); - - vol = virStorageVolCreateXML(pool_get(p), xmlDesc, NUM2UINT(flags)); - _E(vol == NULL, create_error(e_Error, "virNetworkCreateXML", "", c)); +static int internal_add_handle_func(int fd, int events, + virEventHandleCallback cb, void *opaque, + virFreeCallback ff) { + VALUE rubyargs; + VALUE res; + + rubyargs = rb_hash_new(); + rb_hash_aset(rubyargs, rb_str_new2("libvirt_cb"), + Data_Wrap_Struct(rb_class_of(add_handle), NULL, NULL, cb)); + rb_hash_aset(rubyargs, rb_str_new2("opaque"), + Data_Wrap_Struct(rb_class_of(add_handle), NULL, NULL, opaque)); + rb_hash_aset(rubyargs, rb_str_new2("free_func"), + Data_Wrap_Struct(rb_class_of(add_handle), NULL, NULL, ff)); + + /* call out to the ruby object */ + if (strcmp(rb_obj_classname(add_handle), "Symbol") == 0) + res = rb_funcall(rb_class_of(add_handle), rb_to_id(add_handle), 3, + INT2NUM(fd), INT2NUM(events), rubyargs); + else if (strcmp(rb_obj_classname(add_handle), "Proc") == 0) + res = rb_funcall(add_handle, rb_intern("call"), 3, INT2NUM(fd), + INT2NUM(events), rubyargs); + else + rb_raise(rb_eTypeError, + "wrong add handle callback argument type (expected Symbol or Proc)"); - return vol_new(vol, conn_attr(p)); + if (TYPE(res) != T_FIXNUM) + rb_raise(rb_eTypeError, + "expected integer return from add_handle callback"); + + return NUM2INT(res); +} + +static void internal_update_handle_func(int watch, int event) { + /* call out to the ruby object */ + if (strcmp(rb_obj_classname(update_handle), "Symbol") == 0) + rb_funcall(rb_class_of(update_handle), rb_to_id(update_handle), 2, + INT2NUM(watch), INT2NUM(event)); + else if (strcmp(rb_obj_classname(update_handle), "Proc") == 0) + rb_funcall(update_handle, rb_intern("call"), 2, INT2NUM(watch), + INT2NUM(event)); + else + rb_raise(rb_eTypeError, + "wrong update handle callback argument type (expected Symbol or Proc)"); } -/* - * Call +virStorageVolDelete+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolDelete] - */ -VALUE libvirt_vol_delete(int argc, VALUE *argv, VALUE v) { - VALUE flags; - - rb_scan_args(argc, argv, "01", &flags); +static int internal_remove_handle_func(int watch) { + VALUE res; + virFreeCallback ff_cb; + void *op; + VALUE libvirt_opaque; + VALUE ff; + + /* call out to the ruby object */ + if (strcmp(rb_obj_classname(remove_handle), "Symbol") == 0) + res = rb_funcall(rb_class_of(remove_handle), rb_to_id(remove_handle), + 1, INT2NUM(watch)); + else if (strcmp(rb_obj_classname(remove_handle), "Proc") == 0) + res = rb_funcall(remove_handle, rb_intern("call"), 1, INT2NUM(watch)); + else + rb_raise(rb_eTypeError, + "wrong remove handle callback argument type (expected Symbol or Proc)"); - if (NIL_P(flags)) - flags = INT2FIX(0); + if (TYPE(res) != T_HASH) + rb_raise(rb_eTypeError, + "expected opaque hash returned from remove_handle callback"); + + ff = rb_hash_aref(res, rb_str_new2("free_func")); + if (!NIL_P(ff)) { + /* This is equivalent to Data_Get_Struct; I reproduce it here because + * I don't want the additional type-cast that Data_Get_Struct does + */ + Check_Type(ff, T_DATA); + ff_cb = DATA_PTR(ff); + if (ff_cb) { + libvirt_opaque = rb_hash_aref(res, rb_str_new2("opaque")); + Data_Get_Struct(libvirt_opaque, void *, op); + + (*ff_cb)(op); + } + } + + return 0; +} + +static int internal_add_timeout_func(int interval, virEventTimeoutCallback cb, + void *opaque, virFreeCallback ff) { + VALUE rubyargs; + VALUE res; + + rubyargs = rb_hash_new(); + + rb_hash_aset(rubyargs, rb_str_new2("libvirt_cb"), + Data_Wrap_Struct(rb_class_of(add_timeout), NULL, NULL, cb)); + rb_hash_aset(rubyargs, rb_str_new2("opaque"), + Data_Wrap_Struct(rb_class_of(add_timeout), NULL, NULL, + opaque)); + rb_hash_aset(rubyargs, rb_str_new2("free_func"), + Data_Wrap_Struct(rb_class_of(add_timeout), NULL, NULL, ff)); + + /* call out to the ruby object */ + if (strcmp(rb_obj_classname(add_timeout), "Symbol") == 0) + res = rb_funcall(rb_class_of(add_timeout), rb_to_id(add_timeout), 2, + INT2NUM(interval), rubyargs); + else if (strcmp(rb_obj_classname(add_timeout), "Proc") == 0) + res = rb_funcall(add_timeout, rb_intern("call"), 2, INT2NUM(interval), + rubyargs); + else + rb_raise(rb_eTypeError, + "wrong add timeout callback argument type (expected Symbol or Proc)"); - gen_call_void(virStorageVolDelete, conn(v), - vol_get(v), NUM2UINT(flags)); + if (TYPE(res) != T_FIXNUM) + rb_raise(rb_eTypeError, + "expected integer return from add_timeout callback"); + + return NUM2INT(res); +} + +static void internal_update_timeout_func(int timer, int timeout) { + /* call out to the ruby object */ + if (strcmp(rb_obj_classname(update_timeout), "Symbol") == 0) + rb_funcall(rb_class_of(update_timeout), rb_to_id(update_timeout), 2, + INT2NUM(timer), INT2NUM(timeout)); + else if (strcmp(rb_obj_classname(update_timeout), "Proc") == 0) + rb_funcall(update_timeout, rb_intern("call"), 2, INT2NUM(timer), + INT2NUM(timeout)); + else + rb_raise(rb_eTypeError, + "wrong update timeout callback argument type (expected Symbol or Proc)"); } -/* - * Call +virStorageVolGetInfo+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolGetInfo] - */ -VALUE libvirt_vol_info(VALUE v) { - virStorageVolInfo info; - int r; - VALUE result; - - r = virStorageVolGetInfo(vol_get(v), &info); - _E(r < 0, create_error(e_RetrieveError, "virStorageVolGetInfo", "", conn(v))); +static int internal_remove_timeout_func(int timer) { + VALUE res; + virFreeCallback ff_cb; + void *op; + VALUE libvirt_opaque; + VALUE ff; + + /* call out to the ruby object */ + if (strcmp(rb_obj_classname(remove_timeout), "Symbol") == 0) + res = rb_funcall(rb_class_of(remove_timeout), rb_to_id(remove_timeout), + 1, INT2NUM(timer)); + else if (strcmp(rb_obj_classname(remove_timeout), "Proc") == 0) + res = rb_funcall(remove_timeout, rb_intern("call"), 1, INT2NUM(timer)); + else + rb_raise(rb_eTypeError, + "wrong remove timeout callback argument type (expected Symbol or Proc)"); - result = rb_class_new_instance(0, NULL, c_storage_vol_info); - rb_iv_set(result, "@type", INT2NUM(info.type)); - rb_iv_set(result, "@capacity", ULL2NUM(info.capacity)); - rb_iv_set(result, "@allocation", ULL2NUM(info.allocation)); + if (TYPE(res) != T_HASH) + rb_raise(rb_eTypeError, + "expected opaque hash returned from remove_timeout callback"); + + ff = rb_hash_aref(res, rb_str_new2("free_func")); + if (!NIL_P(ff)) { + /* This is equivalent to Data_Get_Struct; I reproduce it here because + * I don't want the additional type-cast that Data_Get_Struct does + */ + Check_Type(ff, T_DATA); + ff_cb = DATA_PTR(ff); + if (ff_cb) { + libvirt_opaque = rb_hash_aref(res, rb_str_new2("opaque")); + Data_Get_Struct(libvirt_opaque, void *, op); + + (*ff_cb)(op); + } + } + + return 0; +} + +#define set_event_func_or_null(type) \ + do { \ + if (NIL_P(type)) \ + type##_temp = NULL; \ + else \ + type##_temp = internal_##type##_func; \ + } while(0) - return result; +static int is_symbol_proc_or_nil(VALUE handle) { + if (NIL_P(handle)) + return 1; + return is_symbol_or_proc(handle); } /* - * Call +virStorageVolGetXMLDesc+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolGetXMLDesc] - */ -VALUE libvirt_vol_xml_desc(int argc, VALUE *argv, VALUE v) { - VALUE flags; - - rb_scan_args(argc, argv, "01", &flags); + * call-seq: + * Libvirt::event_register_impl(add_handle=nil, update_handle=nil, remove_handle=nil, add_timeout=nil, update_timeout=nil, remove_timeout=nil) -> Qnil + * + * Call + * +virEventRegisterImpl+[http://www.libvirt.org/html/libvirt-libvirt.html#virEventRegisterImpl] + * to register callback handlers for handles and timeouts. These handles and + * timeouts are used as part of the libvirt infrastructure for generating + * domain events. Each callback must be a Symbol (that is the name of a + * method to callback), a Proc, or nil (to disable the callback). In the + * end-user application program, these callbacks are typically used to track + * the file descriptors or timers that libvirt is interested in (and is intended + * to be integrated into the "main loop" of a UI program). The individual + * callbacks will be given a certain number of arguments, and must return + * certain values. Those arguments and return types are: + * + * add_handle(fd, events, opaque) => Fixnum + * + * update_handle(handleID, event) => nil + * + * remove_handle(handleID) => opaque data from add_handle + * + * add_timeout(interval, opaque) => Fixnum + * + * update_timeout(timerID, timeout) => nil + * + * remove_timeout(timerID) => opaque data from add_timeout + * + * Any arguments marked as "opaque" must be accepted from the library and saved + * without modification. The values passed to the callbacks are meant to be + * passed to the event_invoke_handle_callback and event_invoke_timeout_callback + * module methods; see the documentation for those methods for more details. + */ +static VALUE libvirt_conn_event_register_impl(int argc, VALUE *argv, VALUE c) { + virEventAddHandleFunc add_handle_temp; + virEventUpdateHandleFunc update_handle_temp; + virEventRemoveHandleFunc remove_handle_temp; + virEventAddTimeoutFunc add_timeout_temp; + virEventUpdateTimeoutFunc update_timeout_temp; + virEventRemoveTimeoutFunc remove_timeout_temp; - if (NIL_P(flags)) - flags = INT2FIX(0); + /* + * subtle; we put the arguments (callbacks) directly into the global + * add_handle, update_handle, etc. variables. Then we register the + * internal functions as the callbacks with virEventRegisterImpl + */ + rb_scan_args(argc, argv, "06", &add_handle, &update_handle, &remove_handle, + &add_timeout, &update_timeout, &remove_timeout); - gen_call_string(virStorageVolGetXMLDesc, conn(v), 1, - vol_get(v), NUM2UINT(flags)); -} + if (!is_symbol_proc_or_nil(add_handle) || + !is_symbol_proc_or_nil(update_handle) || + !is_symbol_proc_or_nil(remove_handle) || + !is_symbol_proc_or_nil(add_timeout) || + !is_symbol_proc_or_nil(update_timeout) || + !is_symbol_proc_or_nil(remove_timeout)) + rb_raise(rb_eTypeError, + "wrong argument type (expected Symbol, Proc, or nil)"); + + set_event_func_or_null(add_handle); + set_event_func_or_null(update_handle); + set_event_func_or_null(remove_handle); + set_event_func_or_null(add_timeout); + set_event_func_or_null(update_timeout); + set_event_func_or_null(remove_timeout); + + /* virEventRegisterImpl returns void, so no error checking here */ + virEventRegisterImpl(add_handle_temp, update_handle_temp, + remove_handle_temp, add_timeout_temp, + update_timeout_temp, remove_timeout_temp); -/* - * Call +virStorageVolGetPath+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolGetPath] - */ -VALUE libvirt_vol_path(VALUE v) { - gen_call_string(virStorageVolGetPath, conn(v), 1, - vol_get(v)); + return Qnil; } +#endif /* - * Call +virStorageVolFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolFree] + * Module Libvirt */ -VALUE libvirt_vol_free(VALUE s) { - gen_call_free(StorageVol, s); -} -#endif - -static void init_storage(void) { - /* - * Class Libvirt::StoragePool and Libvirt::StoragePoolInfo - */ -#if HAVE_TYPE_VIRSTORAGEPOOLPTR - c_storage_pool_info = rb_define_class_under(m_libvirt, "StoragePoolInfo", - rb_cObject); - rb_define_attr(c_storage_pool_info, "state", 1, 0); - rb_define_attr(c_storage_pool_info, "capacity", 1, 0); - rb_define_attr(c_storage_pool_info, "allocation", 1, 0); - rb_define_attr(c_storage_pool_info, "available", 1, 0); - - c_storage_pool = rb_define_class_under(m_libvirt, "StoragePool", - rb_cObject); -#define DEF_POOLCONST(name) \ - rb_define_const(c_storage_pool, #name, INT2NUM(VIR_STORAGE_POOL_##name)) - /* virStoragePoolState */ - DEF_POOLCONST(INACTIVE); - DEF_POOLCONST(BUILDING); - DEF_POOLCONST(RUNNING); - DEF_POOLCONST(DEGRADED); - /* virStoragePoolBuildFlags */ - DEF_POOLCONST(BUILD_NEW); - DEF_POOLCONST(BUILD_REPAIR); - DEF_POOLCONST(BUILD_RESIZE); - /* virStoragePoolDeleteFlags */ - DEF_POOLCONST(DELETE_NORMAL); - DEF_POOLCONST(DELETE_ZEROED); -#undef DEF_POOLCONST - /* Creating/destroying pools */ - rb_define_method(c_storage_pool, "build", libvirt_pool_build, -1); - rb_define_method(c_storage_pool, "undefine", libvirt_pool_undefine, 0); - rb_define_method(c_storage_pool, "create", libvirt_pool_create, -1); - rb_define_method(c_storage_pool, "destroy", libvirt_pool_destroy, 0); - rb_define_method(c_storage_pool, "delete", libvirt_pool_delete, -1); - rb_define_method(c_storage_pool, "refresh", libvirt_pool_refresh, -1); - /* StoragePool information */ - rb_define_method(c_storage_pool, "name", libvirt_pool_name, 0); - rb_define_method(c_storage_pool, "uuid", libvirt_pool_uuid, 0); - rb_define_method(c_storage_pool, "info", libvirt_pool_info, 0); - rb_define_method(c_storage_pool, "xml_desc", libvirt_pool_xml_desc, -1); - rb_define_method(c_storage_pool, "autostart", libvirt_pool_autostart, 0); - rb_define_method(c_storage_pool, "autostart=", - libvirt_pool_autostart_set, 1); - /* List/lookup storage volumes within a pool */ - rb_define_method(c_storage_pool, "num_of_volumes", - libvirt_pool_num_of_volumes, 0); - rb_define_method(c_storage_pool, "list_volumes", - libvirt_pool_list_volumes, 0); - /* Lookup volumes based on various attributes */ - rb_define_method(c_storage_pool, "lookup_volume_by_name", - libvirt_pool_lookup_vol_by_name, 1); - rb_define_method(c_storage_pool, "lookup_volume_by_key", - libvirt_pool_lookup_vol_by_key, 1); - rb_define_method(c_storage_pool, "lookup_volume_by_path", - libvirt_pool_lookup_vol_by_path, 1); - rb_define_method(c_storage_pool, "free", libvirt_pool_free, 0); - rb_define_method(c_storage_pool, "create_vol_xml", libvirt_pool_vol_create_xml, -1); -#endif - -#if HAVE_TYPE_VIRSTORAGEVOLPTR - /* - * Class Libvirt::StorageVol and Libvirt::StorageVolInfo - */ - c_storage_vol_info = rb_define_class_under(m_libvirt, "StorageVolInfo", - rb_cObject); - rb_define_attr(c_storage_vol_info, "type", 1, 0); - rb_define_attr(c_storage_vol_info, "capacity", 1, 0); - rb_define_attr(c_storage_vol_info, "allocation", 1, 0); - - c_storage_vol = rb_define_class_under(m_libvirt, "StorageVol", - rb_cObject); -#define DEF_VOLCONST(name) \ - rb_define_const(c_storage_vol, #name, INT2NUM(VIR_STORAGE_VOL_##name)) - /* virStorageVolType */ - DEF_VOLCONST(FILE); - DEF_VOLCONST(BLOCK); - /* virStorageVolDeleteFlags */ - DEF_VOLCONST(DELETE_NORMAL); - DEF_VOLCONST(DELETE_ZEROED); -#undef DEF_VOLCONST - - rb_define_method(c_storage_vol, "pool", libvirt_vol_get_pool, 0); - rb_define_method(c_storage_vol, "name", libvirt_vol_name, 0); - rb_define_method(c_storage_vol, "key", libvirt_vol_key, 0); - rb_define_method(c_storage_vol, "delete", libvirt_vol_delete, -1); - rb_define_method(c_storage_vol, "info", libvirt_vol_info, 0); - rb_define_method(c_storage_vol, "xml_desc", libvirt_vol_xml_desc, -1); - rb_define_method(c_storage_vol, "path", libvirt_vol_path, 0); - rb_define_method(c_storage_vol, "free", libvirt_vol_free, 0); -#endif -} - void Init__libvirt() { - int r; - m_libvirt = rb_define_module("Libvirt"); c_libvirt_version = rb_define_class_under(m_libvirt, "Version", rb_cObject); +#if HAVE_VIRCONNECTOPENAUTH + rb_define_const(m_libvirt, "CONNECT_RO", INT2NUM(VIR_CONNECT_RO)); + + rb_define_const(m_libvirt, "CRED_USERNAME", INT2NUM(VIR_CRED_USERNAME)); + rb_define_const(m_libvirt, "CRED_AUTHNAME", INT2NUM(VIR_CRED_AUTHNAME)); + rb_define_const(m_libvirt, "CRED_LANGUAGE", INT2NUM(VIR_CRED_LANGUAGE)); + rb_define_const(m_libvirt, "CRED_CNONCE", INT2NUM(VIR_CRED_CNONCE)); + rb_define_const(m_libvirt, "CRED_PASSPHRASE", INT2NUM(VIR_CRED_PASSPHRASE)); + rb_define_const(m_libvirt, "CRED_ECHOPROMPT", INT2NUM(VIR_CRED_ECHOPROMPT)); + rb_define_const(m_libvirt, "CRED_NOECHOPROMPT", INT2NUM(VIR_CRED_NOECHOPROMPT)); + rb_define_const(m_libvirt, "CRED_REALM", INT2NUM(VIR_CRED_REALM)); + rb_define_const(m_libvirt, "CRED_EXTERNAL", INT2NUM(VIR_CRED_EXTERNAL)); +#endif /* * Libvirt Errors */ - e_Error = rb_define_class_under(m_libvirt, "Error", - rb_eStandardError); - e_ConnectionError = rb_define_class_under(m_libvirt, "ConnectionError", - e_Error); - e_DefinitionError = rb_define_class_under(m_libvirt, "DefinitionError", - e_Error); - e_RetrieveError = rb_define_class_under(m_libvirt, "RetrieveError", - e_Error); + e_Error = rb_define_class_under(m_libvirt, "Error", + rb_eStandardError); + e_ConnectionError = rb_define_class_under(m_libvirt, "ConnectionError", + e_Error); + e_DefinitionError = rb_define_class_under(m_libvirt, "DefinitionError", + e_Error); + e_RetrieveError = rb_define_class_under(m_libvirt, "RetrieveError", + e_Error); + e_NoSupportError = rb_define_class_under(m_libvirt, "NoSupportError", + e_Error); - // create 'libvirt_function_name' and 'vir_connect_ptr' attributes on e_Error class rb_define_attr(e_Error, "libvirt_function_name", 1, 0); rb_define_attr(e_Error, "libvirt_message", 1, 0); - - /* - * Class Libvirt::Connect - */ - c_connect = rb_define_class_under(m_libvirt, "Connect", rb_cObject); - - rb_define_module_function(m_libvirt, "version", libvirt_version, 1); - rb_define_module_function(m_libvirt, "open", libvirt_open, 1); - rb_define_module_function(m_libvirt, "open_read_only", - libvirt_open_read_only, 1); - - rb_define_method(c_connect, "close", libvirt_conn_close, 0); - rb_define_method(c_connect, "closed?", libvirt_conn_closed_p, 0); - rb_define_method(c_connect, "type", libvirt_conn_type, 0); - rb_define_method(c_connect, "version", libvirt_conn_version, 0); - rb_define_method(c_connect, "hostname", libvirt_conn_hostname, 0); - rb_define_method(c_connect, "uri", libvirt_conn_uri, 0); - rb_define_method(c_connect, "max_vcpus", libvirt_conn_max_vcpus, 1); - rb_define_method(c_connect, "node_get_info", libvirt_conn_node_get_info, 0); - rb_define_method(c_connect, "capabilities", libvirt_conn_capabilities, 0); - rb_define_method(c_connect, "num_of_domains", libvirt_conn_num_of_domains, 0); - rb_define_method(c_connect, "list_domains", libvirt_conn_list_domains, 0); - rb_define_method(c_connect, "num_of_defined_domains", - libvirt_conn_num_of_defined_domains, 0); - rb_define_method(c_connect, "list_defined_domains", - libvirt_conn_list_defined_domains, 0); -#if HAVE_TYPE_VIRNETWORKPTR - rb_define_method(c_connect, "num_of_networks", - libvirt_conn_num_of_networks, 0); - rb_define_method(c_connect, "list_networks", libvirt_conn_list_networks, 0); - rb_define_method(c_connect, "num_of_defined_networks", - libvirt_conn_num_of_defined_networks, 0); - rb_define_method(c_connect, "list_defined_networks", - libvirt_conn_list_defined_networks, 0); + rb_define_attr(e_Error, "libvirt_code", 1, 0); + rb_define_attr(e_Error, "libvirt_component", 1, 0); + rb_define_attr(e_Error, "libvirt_level", 1, 0); + + /* libvirt error components (domains) */ + rb_define_const(e_Error, "FROM_NONE", INT2NUM(VIR_FROM_NONE)); + rb_define_const(e_Error, "FROM_XEN", INT2NUM(VIR_FROM_XEN)); + rb_define_const(e_Error, "FROM_XEND", INT2NUM(VIR_FROM_XEND)); + rb_define_const(e_Error, "FROM_XENSTORE", INT2NUM(VIR_FROM_XENSTORE)); + rb_define_const(e_Error, "FROM_SEXPR", INT2NUM(VIR_FROM_SEXPR)); + rb_define_const(e_Error, "FROM_XML", INT2NUM(VIR_FROM_XML)); + rb_define_const(e_Error, "FROM_DOM", INT2NUM(VIR_FROM_DOM)); + rb_define_const(e_Error, "FROM_RPC", INT2NUM(VIR_FROM_RPC)); + rb_define_const(e_Error, "FROM_PROXY", INT2NUM(VIR_FROM_PROXY)); + rb_define_const(e_Error, "FROM_CONF", INT2NUM(VIR_FROM_CONF)); + rb_define_const(e_Error, "FROM_QEMU", INT2NUM(VIR_FROM_QEMU)); + rb_define_const(e_Error, "FROM_NET", INT2NUM(VIR_FROM_NET)); + rb_define_const(e_Error, "FROM_TEST", INT2NUM(VIR_FROM_TEST)); + rb_define_const(e_Error, "FROM_REMOTE", INT2NUM(VIR_FROM_REMOTE)); + rb_define_const(e_Error, "FROM_OPENVZ", INT2NUM(VIR_FROM_OPENVZ)); +#if HAVE_CONST_VIR_FROM_VMWARE + rb_define_const(e_Error, "FROM_VMWARE", INT2NUM(VIR_FROM_VMWARE)); #endif -#if HAVE_TYPE_VIRSTORAGEPOOLPTR - rb_define_method(c_connect, "num_of_storage_pools", - libvirt_conn_num_of_storage_pools, 0); - rb_define_method(c_connect, "list_storage_pools", - libvirt_conn_list_storage_pools, 0); - rb_define_method(c_connect, "num_of_defined_storage_pools", - libvirt_conn_num_of_defined_storage_pools, 0); - rb_define_method(c_connect, "list_defined_storage_pools", - libvirt_conn_list_defined_storage_pools, 0); -#endif - // Domain creation/lookup - rb_define_method(c_connect, "create_domain_linux", - libvirt_conn_create_linux, -1); - rb_define_method(c_connect, "lookup_domain_by_name", - libvirt_conn_lookup_domain_by_name, 1); - rb_define_method(c_connect, "lookup_domain_by_id", - libvirt_conn_lookup_domain_by_id, 1); - rb_define_method(c_connect, "lookup_domain_by_uuid", - libvirt_conn_lookup_domain_by_uuid, 1); - rb_define_method(c_connect, "define_domain_xml", - libvirt_conn_define_domain_xml, 1); - // Network creation/lookup -#if HAVE_TYPE_VIRNETWORKPTR - rb_define_method(c_connect, "lookup_network_by_name", - libvirt_conn_lookup_network_by_name, 1); - rb_define_method(c_connect, "lookup_network_by_uuid", - libvirt_conn_lookup_network_by_uuid, 1); - rb_define_method(c_connect, "create_network_xml", - libvirt_conn_create_network_xml, 1); - rb_define_method(c_connect, "define_network_xml", - libvirt_conn_define_network_xml, 1); +#if HAVE_CONST_VIR_FROM_XENXM + rb_define_const(e_Error, "FROM_XENXM", INT2NUM(VIR_FROM_XENXM)); +#endif +#if HAVE_CONST_VIR_FROM_STATS_LINUX + rb_define_const(e_Error, "FROM_STATS_LINUX", INT2NUM(VIR_FROM_STATS_LINUX)); +#endif +#if HAVE_TYPE_VIR_FROM_LXC + rb_define_const(e_Error, "FROM_LXC", INT2NUM(VIR_FROM_LXC)); #endif - // Storage pool creation/lookup #if HAVE_TYPE_VIRSTORAGEPOOLPTR - rb_define_method(c_connect, "lookup_storage_pool_by_name", - libvirt_conn_lookup_pool_by_name, 1); - rb_define_method(c_connect, "lookup_storage_pool_by_uuid", - libvirt_conn_lookup_pool_by_uuid, 1); - rb_define_method(c_connect, "create_storage_pool_xml", - libvirt_conn_create_pool_xml, -1); - rb_define_method(c_connect, "define_storage_pool_xml", - libvirt_conn_define_pool_xml, -1); + rb_define_const(e_Error, "FROM_STORAGE", INT2NUM(VIR_FROM_STORAGE)); #endif - - /* - * Class Libvirt::Connect::Nodeinfo - */ - c_node_info = rb_define_class_under(c_connect, "Nodeinfo", rb_cObject); - rb_define_attr(c_node_info, "model", 1, 0); - rb_define_attr(c_node_info, "memory", 1, 0); - rb_define_attr(c_node_info, "cpus", 1, 0); - rb_define_attr(c_node_info, "mhz", 1, 0); - rb_define_attr(c_node_info, "nodes", 1, 0); - rb_define_attr(c_node_info, "sockets", 1, 0); - rb_define_attr(c_node_info, "cores", 1, 0); - rb_define_attr(c_node_info, "threads", 1, 0); - - /* - * Class Libvirt::Domain - */ - c_domain = rb_define_class_under(m_libvirt, "Domain", rb_cObject); -#define DEF_DOMSTATE(name) \ - rb_define_const(c_domain, #name, INT2NUM(VIR_DOMAIN_##name)) - /* virDomainState */ - DEF_DOMSTATE(NOSTATE); - DEF_DOMSTATE(RUNNING); - DEF_DOMSTATE(BLOCKED); - DEF_DOMSTATE(PAUSED); - DEF_DOMSTATE(SHUTDOWN); - DEF_DOMSTATE(SHUTOFF); - DEF_DOMSTATE(CRASHED); -#undef DEF_DOMSTATE - - rb_define_method(c_domain, "migrate", libvirt_dom_migrate, 5); - rb_define_attr(c_domain, "connection", 1, 0); - rb_define_method(c_domain, "shutdown", libvirt_dom_shutdown, 0); - rb_define_method(c_domain, "reboot", libvirt_dom_reboot, -1); - rb_define_method(c_domain, "destroy", libvirt_dom_destroy, 0); - rb_define_method(c_domain, "suspend", libvirt_dom_suspend, 0); - rb_define_method(c_domain, "resume", libvirt_dom_resume, 0); - rb_define_method(c_domain, "save", libvirt_dom_save, 1); - rb_define_singleton_method(c_domain, "restore", libvirt_dom_s_restore, 2); - rb_define_method(c_domain, "core_dump", libvirt_dom_core_dump, -1); - rb_define_method(c_domain, "info", libvirt_dom_info, 0); - rb_define_method(c_domain, "name", libvirt_dom_name, 0); - rb_define_method(c_domain, "id", libvirt_dom_id, 0); - rb_define_method(c_domain, "uuid", libvirt_dom_uuid, 0); - rb_define_method(c_domain, "os_type", libvirt_dom_os_type, 0); - rb_define_method(c_domain, "max_memory", libvirt_dom_max_memory, 0); - rb_define_method(c_domain, "max_memory=", libvirt_dom_max_memory_set, 1); - rb_define_method(c_domain, "memory=", libvirt_dom_memory_set, 1); - rb_define_method(c_domain, "max_vcpus", libvirt_dom_max_vcpus, 0); - rb_define_method(c_domain, "vcpus=", libvirt_dom_vcpus_set, 1); - rb_define_method(c_domain, "pin_vcpu", libvirt_dom_pin_vcpu, 2); - rb_define_method(c_domain, "xml_desc", libvirt_dom_xml_desc, -1); - rb_define_method(c_domain, "undefine", libvirt_dom_undefine, 0); - rb_define_method(c_domain, "create", libvirt_dom_create, 0); - rb_define_method(c_domain, "autostart", libvirt_dom_autostart, 0); - rb_define_method(c_domain, "autostart=", libvirt_dom_autostart_set, 1); - rb_define_method(c_domain, "free", libvirt_dom_free, 0); - - /* - * Class Libvirt::Domain::Info - */ - c_domain_info = rb_define_class_under(c_domain, "Info", rb_cObject); - rb_define_attr(c_domain_info, "state", 1, 0); - rb_define_attr(c_domain_info, "max_mem", 1, 0); - rb_define_attr(c_domain_info, "memory", 1, 0); - rb_define_attr(c_domain_info, "nr_virt_cpu", 1, 0); - rb_define_attr(c_domain_info, "cpu_time", 1, 0); - - /* - * Class Libvirt::Network - */ -#if HAVE_TYPE_VIRNETWORKPTR - c_network = rb_define_class_under(m_libvirt, "Network", rb_cObject); - rb_define_attr(c_network, "connection", 1, 0); - rb_define_method(c_network, "undefine", libvirt_netw_undefine, 0); - rb_define_method(c_network, "create", libvirt_netw_create, 0); - rb_define_method(c_network, "destroy", libvirt_netw_destroy, 0); - rb_define_method(c_network, "name", libvirt_netw_name, 0); - rb_define_method(c_network, "uuid", libvirt_netw_uuid, 0); - rb_define_method(c_network, "xml_desc", libvirt_netw_xml_desc, -1); - rb_define_method(c_network, "bridge_name", libvirt_netw_bridge_name, 0); - rb_define_method(c_network, "autostart", libvirt_netw_autostart, 0); - rb_define_method(c_network, "autostart=", libvirt_netw_autostart_set, 1); - rb_define_method(c_network, "free", libvirt_netw_free, 0); +#if HAVE_CONST_VIR_FROM_NETWORK + rb_define_const(e_Error, "FROM_NETWORK", INT2NUM(VIR_FROM_NETWORK)); +#endif +#if HAVE_CONST_VIR_FROM_DOMAIN + rb_define_const(e_Error, "FROM_DOMAIN", INT2NUM(VIR_FROM_DOMAIN)); +#endif +#if HAVE_CONST_VIR_FROM_UML + rb_define_const(e_Error, "FROM_UML", INT2NUM(VIR_FROM_UML)); +#endif +#if HAVE_TYPE_VIRNODEDEVICEPTR + rb_define_const(e_Error, "FROM_NODEDEV", INT2NUM(VIR_FROM_NODEDEV)); +#endif +#if HAVE_CONST_VIR_FROM_XEN_INOTIFY + rb_define_const(e_Error, "FROM_XEN_INOTIFY", INT2NUM(VIR_FROM_XEN_INOTIFY)); +#endif +#if HAVE_CONST_VIR_FROM_SECURITY + rb_define_const(e_Error, "FROM_SECURITY", INT2NUM(VIR_FROM_SECURITY)); +#endif +#if HAVE_CONST_VIR_FROM_VBOX + rb_define_const(e_Error, "FROM_VBOX", INT2NUM(VIR_FROM_VBOX)); +#endif +#if HAVE_TYPE_VIRINTERFACEPTR + rb_define_const(e_Error, "FROM_INTERFACE", INT2NUM(VIR_FROM_INTERFACE)); +#endif +#if HAVE_CONST_VIR_FROM_ONE + rb_define_const(e_Error, "FROM_ONE", INT2NUM(VIR_FROM_ONE)); +#endif +#if HAVE_CONST_VIR_FROM_ESX + rb_define_const(e_Error, "FROM_ESX", INT2NUM(VIR_FROM_ESX)); +#endif +#if HAVE_CONST_VIR_FROM_PHYP + rb_define_const(e_Error, "FROM_PHYP", INT2NUM(VIR_FROM_PHYP)); +#endif +#if HAVE_TYPE_VIRSECRETPTR + rb_define_const(e_Error, "FROM_SECRET", INT2NUM(VIR_FROM_SECRET)); +#endif +#if HAVE_VIRCONNECTCOMPARECPU + rb_define_const(e_Error, "FROM_CPU", INT2NUM(VIR_FROM_CPU)); +#endif +#if HAVE_CONST_VIR_FROM_XENAPI + rb_define_const(e_Error, "FROM_XENAPI", INT2NUM(VIR_FROM_XENAPI)); +#endif +#if HAVE_TYPE_VIRNWFILTERPTR + rb_define_const(e_Error, "FROM_NWFILTER", INT2NUM(VIR_FROM_NWFILTER)); +#endif +#if HAVE_CONST_VIR_FROM_HOOK + rb_define_const(e_Error, "FROM_HOOK", INT2NUM(VIR_FROM_HOOK)); +#endif +#if HAVE_TYPE_VIRDOMAINSNAPSHOTPTR + rb_define_const(e_Error, "FROM_DOMAIN_SNAPSHOT", + INT2NUM(VIR_FROM_DOMAIN_SNAPSHOT)); +#endif +#if HAVE_CONST_VIR_FROM_AUDIT + rb_define_const(e_Error, "FROM_AUDIT", INT2NUM(VIR_FROM_AUDIT)); +#endif +#if HAVE_CONST_VIR_FROM_SYSINFO + rb_define_const(e_Error, "FROM_SYSINFO", INT2NUM(VIR_FROM_SYSINFO)); +#endif +#if HAVE_CONST_VIR_FROM_STREAMS + rb_define_const(e_Error, "FROM_STREAMS", INT2NUM(VIR_FROM_STREAMS)); +#endif + + /* libvirt error codes */ + rb_define_const(e_Error, "ERR_OK", INT2NUM(VIR_ERR_OK)); + rb_define_const(e_Error, "ERR_INTERNAL_ERROR", + INT2NUM(VIR_ERR_INTERNAL_ERROR)); + rb_define_const(e_Error, "ERR_NO_MEMORY", INT2NUM(VIR_ERR_NO_MEMORY)); + rb_define_const(e_Error, "ERR_NO_SUPPORT", INT2NUM(VIR_ERR_NO_SUPPORT)); + rb_define_const(e_Error, "ERR_UNKNOWN_HOST", INT2NUM(VIR_ERR_UNKNOWN_HOST)); + rb_define_const(e_Error, "ERR_NO_CONNECT", INT2NUM(VIR_ERR_NO_CONNECT)); + rb_define_const(e_Error, "ERR_INVALID_CONN", INT2NUM(VIR_ERR_INVALID_CONN)); + rb_define_const(e_Error, "ERR_INVALID_DOMAIN", + INT2NUM(VIR_ERR_INVALID_DOMAIN)); + rb_define_const(e_Error, "ERR_INVALID_ARG", INT2NUM(VIR_ERR_INVALID_ARG)); + rb_define_const(e_Error, "ERR_OPERATION_FAILED", + INT2NUM(VIR_ERR_OPERATION_FAILED)); + rb_define_const(e_Error, "ERR_GET_FAILED", INT2NUM(VIR_ERR_GET_FAILED)); + rb_define_const(e_Error, "ERR_POST_FAILED", INT2NUM(VIR_ERR_POST_FAILED)); + rb_define_const(e_Error, "ERR_HTTP_ERROR", INT2NUM(VIR_ERR_HTTP_ERROR)); + rb_define_const(e_Error, "ERR_SEXPR_SERIAL", INT2NUM(VIR_ERR_SEXPR_SERIAL)); + rb_define_const(e_Error, "ERR_NO_XEN", INT2NUM(VIR_ERR_NO_XEN)); + rb_define_const(e_Error, "ERR_XEN_CALL", INT2NUM(VIR_ERR_XEN_CALL)); + rb_define_const(e_Error, "ERR_OS_TYPE", INT2NUM(VIR_ERR_OS_TYPE)); + rb_define_const(e_Error, "ERR_NO_KERNEL", INT2NUM(VIR_ERR_NO_KERNEL)); + rb_define_const(e_Error, "ERR_NO_ROOT", INT2NUM(VIR_ERR_NO_ROOT)); + rb_define_const(e_Error, "ERR_NO_SOURCE", INT2NUM(VIR_ERR_NO_SOURCE)); + rb_define_const(e_Error, "ERR_NO_TARGET", INT2NUM(VIR_ERR_NO_TARGET)); + rb_define_const(e_Error, "ERR_NO_NAME", INT2NUM(VIR_ERR_NO_NAME)); + rb_define_const(e_Error, "ERR_NO_OS", INT2NUM(VIR_ERR_NO_OS)); + rb_define_const(e_Error, "ERR_NO_DEVICE", INT2NUM(VIR_ERR_NO_DEVICE)); + rb_define_const(e_Error, "ERR_NO_XENSTORE", INT2NUM(VIR_ERR_NO_XENSTORE)); + rb_define_const(e_Error, "ERR_DRIVER_FULL", INT2NUM(VIR_ERR_DRIVER_FULL)); + rb_define_const(e_Error, "ERR_CALL_FAILED", INT2NUM(VIR_ERR_CALL_FAILED)); + rb_define_const(e_Error, "ERR_XML_ERROR", INT2NUM(VIR_ERR_XML_ERROR)); + rb_define_const(e_Error, "ERR_DOM_EXIST", INT2NUM(VIR_ERR_DOM_EXIST)); + rb_define_const(e_Error, "ERR_OPERATION_DENIED", + INT2NUM(VIR_ERR_OPERATION_DENIED)); + rb_define_const(e_Error, "ERR_OPEN_FAILED", INT2NUM(VIR_ERR_OPEN_FAILED)); + rb_define_const(e_Error, "ERR_READ_FAILED", INT2NUM(VIR_ERR_READ_FAILED)); + rb_define_const(e_Error, "ERR_PARSE_FAILED", INT2NUM(VIR_ERR_PARSE_FAILED)); + rb_define_const(e_Error, "ERR_CONF_SYNTAX", INT2NUM(VIR_ERR_CONF_SYNTAX)); + rb_define_const(e_Error, "ERR_WRITE_FAILED", INT2NUM(VIR_ERR_WRITE_FAILED)); + rb_define_const(e_Error, "ERR_XML_DETAIL", INT2NUM(VIR_ERR_XML_DETAIL)); + rb_define_const(e_Error, "ERR_INVALID_NETWORK", + INT2NUM(VIR_ERR_INVALID_NETWORK)); + rb_define_const(e_Error, "ERR_NETWORK_EXIST", + INT2NUM(VIR_ERR_NETWORK_EXIST)); + rb_define_const(e_Error, "ERR_SYSTEM_ERROR", INT2NUM(VIR_ERR_SYSTEM_ERROR)); + rb_define_const(e_Error, "ERR_RPC", INT2NUM(VIR_ERR_RPC)); + rb_define_const(e_Error, "ERR_GNUTLS_ERROR", INT2NUM(VIR_ERR_GNUTLS_ERROR)); + rb_define_const(e_Error, "WAR_NO_NETWORK", INT2NUM(VIR_WAR_NO_NETWORK)); + rb_define_const(e_Error, "ERR_NO_DOMAIN", INT2NUM(VIR_ERR_NO_DOMAIN)); + rb_define_const(e_Error, "ERR_NO_NETWORK", INT2NUM(VIR_ERR_NO_NETWORK)); + rb_define_const(e_Error, "ERR_INVALID_MAC", INT2NUM(VIR_ERR_INVALID_MAC)); +#if HAVE_CONST_VIR_ERR_AUTH_FAILED + rb_define_const(e_Error, "ERR_AUTH_FAILED", INT2NUM(VIR_ERR_AUTH_FAILED)); +#endif +#if HAVE_TYPE_VIRSTORAGEPOOLPTR + rb_define_const(e_Error, "ERR_INVALID_STORAGE_POOL", + INT2NUM(VIR_ERR_INVALID_STORAGE_POOL)); + rb_define_const(e_Error, "ERR_INVALID_STORAGE_VOL", + INT2NUM(VIR_ERR_INVALID_STORAGE_VOL)); + rb_define_const(e_Error, "WAR_NO_STORAGE", INT2NUM(VIR_WAR_NO_STORAGE)); + rb_define_const(e_Error, "ERR_NO_STORAGE_POOL", + INT2NUM(VIR_ERR_NO_STORAGE_POOL)); + rb_define_const(e_Error, "ERR_NO_STORAGE_VOL", + INT2NUM(VIR_ERR_NO_STORAGE_VOL)); +#endif +#if HAVE_TYPE_VIRNODEDEVICEPTR + rb_define_const(e_Error, "WAR_NO_NODE", INT2NUM(VIR_WAR_NO_NODE)); + rb_define_const(e_Error, "ERR_INVALID_NODE_DEVICE", + INT2NUM(VIR_ERR_INVALID_NODE_DEVICE)); + rb_define_const(e_Error, "ERR_NO_NODE_DEVICE", + INT2NUM(VIR_ERR_NO_NODE_DEVICE)); +#endif +#if HAVE_CONST_VIR_ERR_NO_SECURITY_MODEL + rb_define_const(e_Error, "ERR_NO_SECURITY_MODEL", + INT2NUM(VIR_ERR_NO_SECURITY_MODEL)); +#endif +#if HAVE_CONST_VIR_ERR_OPERATION_INVALID + rb_define_const(e_Error, "ERR_OPERATION_INVALID", + INT2NUM(VIR_ERR_OPERATION_INVALID)); +#endif +#if HAVE_TYPE_VIRINTERFACEPTR + rb_define_const(e_Error, "WAR_NO_INTERFACE", INT2NUM(VIR_WAR_NO_INTERFACE)); + rb_define_const(e_Error, "ERR_NO_INTERFACE", INT2NUM(VIR_ERR_NO_INTERFACE)); + rb_define_const(e_Error, "ERR_INVALID_INTERFACE", + INT2NUM(VIR_ERR_INVALID_INTERFACE)); + rb_define_const(e_Error, "ERR_MULTIPLE_INTERFACES", + INT2NUM(VIR_ERR_MULTIPLE_INTERFACES)); +#endif +#if HAVE_TYPE_VIRNWFILTERPTR + rb_define_const(e_Error, "WAR_NO_NWFILTER", INT2NUM(VIR_WAR_NO_NWFILTER)); + rb_define_const(e_Error, "ERR_INVALID_NWFILTER", + INT2NUM(VIR_ERR_INVALID_NWFILTER)); + rb_define_const(e_Error, "ERR_NO_NWFILTER", INT2NUM(VIR_ERR_NO_NWFILTER)); + rb_define_const(e_Error, "ERR_BUILD_FIREWALL", + INT2NUM(VIR_ERR_BUILD_FIREWALL)); +#endif +#if HAVE_TYPE_VIRSECRETPTR + rb_define_const(e_Error, "WAR_NO_SECRET", INT2NUM(VIR_WAR_NO_SECRET)); + rb_define_const(e_Error, "ERR_INVALID_SECRET", + INT2NUM(VIR_ERR_INVALID_SECRET)); + rb_define_const(e_Error, "ERR_NO_SECRET", INT2NUM(VIR_ERR_NO_SECRET)); +#endif +#if HAVE_CONST_VIR_ERR_CONFIG_UNSUPPORTED + rb_define_const(e_Error, "ERR_CONFIG_UNSUPPORTED", + INT2NUM(VIR_ERR_CONFIG_UNSUPPORTED)); +#endif +#if HAVE_CONST_VIR_ERR_OPERATION_TIMEOUT + rb_define_const(e_Error, "ERR_OPERATION_TIMEOUT", + INT2NUM(VIR_ERR_OPERATION_TIMEOUT)); +#endif +#if HAVE_CONST_VIR_ERR_MIGRATE_PERSIST_FAILED + rb_define_const(e_Error, "ERR_MIGRATE_PERSIST_FAILED", + INT2NUM(VIR_ERR_MIGRATE_PERSIST_FAILED)); +#endif +#if HAVE_CONST_VIR_ERR_HOOK_SCRIPT_FAILED + rb_define_const(e_Error, "ERR_HOOK_SCRIPT_FAILED", + INT2NUM(VIR_ERR_HOOK_SCRIPT_FAILED)); +#endif +#if HAVE_TYPE_VIRDOMAINSNAPSHOTPTR + rb_define_const(e_Error, "ERR_INVALID_DOMAIN_SNAPSHOT", + INT2NUM(VIR_ERR_INVALID_DOMAIN_SNAPSHOT)); + rb_define_const(e_Error, "ERR_NO_DOMAIN_SNAPSHOT", + INT2NUM(VIR_ERR_NO_DOMAIN_SNAPSHOT)); +#endif + + /* libvirt levels */ + rb_define_const(e_Error, "LEVEL_NONE", INT2NUM(VIR_ERR_NONE)); + rb_define_const(e_Error, "LEVEL_WARNING", INT2NUM(VIR_ERR_WARNING)); + rb_define_const(e_Error, "LEVEL_ERROR", INT2NUM(VIR_ERR_ERROR)); + + rb_define_module_function(m_libvirt, "version", libvirt_version, -1); + rb_define_module_function(m_libvirt, "open", libvirt_open, -1); + rb_define_module_function(m_libvirt, "open_read_only", + libvirt_open_read_only, -1); +#if HAVE_VIRCONNECTOPENAUTH + rb_define_module_function(m_libvirt, "open_auth", libvirt_open_auth, -1); +#endif + +#if HAVE_VIREVENTREGISTERIMPL + rb_define_const(m_libvirt, "EVENT_HANDLE_READABLE", + INT2NUM(VIR_EVENT_HANDLE_READABLE)); + rb_define_const(m_libvirt, "EVENT_HANDLE_WRITABLE", + INT2NUM(VIR_EVENT_HANDLE_WRITABLE)); + rb_define_const(m_libvirt, "EVENT_HANDLE_ERROR", + INT2NUM(VIR_EVENT_HANDLE_ERROR)); + rb_define_const(m_libvirt, "EVENT_HANDLE_HANGUP", + INT2NUM(VIR_EVENT_HANDLE_HANGUP)); + + /* since we are using globals, we have to register with the gc */ + rb_global_variable(&add_handle); + rb_global_variable(&update_handle); + rb_global_variable(&remove_handle); + rb_global_variable(&add_timeout); + rb_global_variable(&update_timeout); + rb_global_variable(&remove_timeout); + + rb_define_module_function(m_libvirt, "event_register_impl", + libvirt_conn_event_register_impl, -1); + rb_define_module_function(m_libvirt, "event_invoke_handle_callback", + libvirt_event_invoke_handle_callback, 4); + rb_define_module_function(m_libvirt, "event_invoke_timeout_callback", + libvirt_event_invoke_timeout_callback, 2); #endif + init_connect(); init_storage(); + init_network(); + init_nodedevice(); + init_secret(); + init_nwfilter(); + init_interface(); + init_domain(); + init_stream(); - r = virInitialize(); - if (r < 0) + virSetErrorFunc(NULL, rubyLibvirtErrorFunc); + + if (virInitialize() < 0) rb_raise(rb_eSystemCallError, "virInitialize failed"); } - -/* - * Local variables: - * indent-tabs-mode: nil - * c-indent-level: 4 - * c-basic-offset: 4 - * tab-width: 4 - * End: - */ diff -Nru ruby-libvirt-0.0.7/ext/libvirt/network.c ruby-libvirt-0.4.0/ext/libvirt/network.c --- ruby-libvirt-0.0.7/ext/libvirt/network.c 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/network.c 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,235 @@ +/* + * network.c: virNetwork methods + * + * Copyright (C) 2007,2010 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "common.h" +#include "connect.h" +#include "extconf.h" + +#if HAVE_TYPE_VIRNETWORKPTR +static VALUE c_network; + +static void network_free(void *d) { + generic_free(Network, d); +} + +static virNetworkPtr network_get(VALUE s) { + generic_get(Network, s); +} + +VALUE network_new(virNetworkPtr n, VALUE conn) { + return generic_new(c_network, n, conn, network_free); +} + +/* + * call-seq: + * net.undefine -> nil + * + * Call +virNetworkUndefine+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkUndefine] + * to undefine this network. + */ +static VALUE libvirt_netw_undefine(VALUE s) { + gen_call_void(virNetworkUndefine, conn(s), network_get(s)); +} + +/* + * call-seq: + * net.create -> nil + * + * Call +virNetworkCreate+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkCreate] + * to start this network. + */ +static VALUE libvirt_netw_create(VALUE s) { + gen_call_void(virNetworkCreate, conn(s), network_get(s)); +} + +/* + * call-seq: + * net.destroy -> nil + * + * Call +virNetworkDestroy+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkDestroy] + * to shutdown this network. + */ +static VALUE libvirt_netw_destroy(VALUE s) { + gen_call_void(virNetworkDestroy, conn(s), network_get(s)); +} + +/* + * call-seq: + * net.name -> string + * + * Call +virNetworkGetName+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkGetName] + * to retrieve the name of this network. + */ +static VALUE libvirt_netw_name(VALUE s) { + gen_call_string(virNetworkGetName, conn(s), 0, network_get(s)); +} + +/* + * call-seq: + * net.uuid -> string + * + * Call +virNetworkGetUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkGetUUIDString] + * to retrieve the UUID of this network. + */ +static VALUE libvirt_netw_uuid(VALUE s) { + virNetworkPtr netw = network_get(s); + char uuid[VIR_UUID_STRING_BUFLEN]; + int r; + + r = virNetworkGetUUIDString(netw, uuid); + _E(r < 0, create_error(e_RetrieveError, "virNetworkGetUUIDString", + conn(s))); + + return rb_str_new2((char *) uuid); +} + +/* + * call-seq: + * net.xml_desc(flags=0) -> string + * + * Call +virNetworkGetXMLDesc+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkGetXMLDesc] + * to retrieve the XML for this network. + */ +static VALUE libvirt_netw_xml_desc(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_string(virNetworkGetXMLDesc, conn(s), 1, network_get(s), + NUM2UINT(flags)); +} + +/* + * call-seq: + * net.bridge_name -> string + * + * Call +virNetworkGetBridgeName+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkGetBridgeName] + * to retrieve the bridge name for this network. + */ +static VALUE libvirt_netw_bridge_name(VALUE s) { + gen_call_string(virNetworkGetBridgeName, conn(s), 1, network_get(s)); +} + +/* + * call-seq: + * net.autostart? -> [true|false] + * + * Call +virNetworkGetAutostart+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkGetAutostart] + * to determine if this network will be autostarted when libvirtd starts. + */ +static VALUE libvirt_netw_autostart(VALUE s){ + virNetworkPtr netw = network_get(s); + int r, autostart; + + r = virNetworkGetAutostart(netw, &autostart); + _E(r < 0, create_error(e_RetrieveError, "virNetworkAutostart", conn(s))); + + return autostart ? Qtrue : Qfalse; +} + +/* + * call-seq: + * net.autostart = [true|false] + * + * Call +virNetworkSetAutostart+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkSetAutostart] + * to set this network to be autostarted when libvirtd starts. + */ +static VALUE libvirt_netw_autostart_set(VALUE s, VALUE autostart) { + if (autostart != Qtrue && autostart != Qfalse) + rb_raise(rb_eTypeError, + "wrong argument type (expected TrueClass or FalseClass)"); + + gen_call_void(virNetworkSetAutostart, conn(s), network_get(s), + RTEST(autostart) ? 1 : 0); +} + +/* + * call-seq: + * net.free -> nil + * + * Call +virNetworkFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkFree] + * to free this network. The object will no longer be valid after this call. + */ +static VALUE libvirt_netw_free(VALUE s) { + gen_call_free(Network, s); +} + +#if HAVE_VIRNETWORKISACTIVE +/* + * call-seq: + * net.active? -> [true|false] + * + * Call +virNetworkIsActive+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkIsActive] + * to determine if this network is currently active. + */ +static VALUE libvirt_netw_active_p(VALUE s) { + gen_call_truefalse(virNetworkIsActive, conn(s), network_get(s)); +} +#endif + +#if HAVE_VIRNETWORKISPERSISTENT +/* + * call-seq: + * net.persistent? -> [true|false] + * + * Call +virNetworkIsPersistent+[http://www.libvirt.org/html/libvirt-libvirt.html#virNetworkIsPersistent] + * to determine if this network is persistent. + */ +static VALUE libvirt_netw_persistent_p(VALUE s) { + gen_call_truefalse(virNetworkIsPersistent, conn(s), network_get(s)); +} +#endif + +#endif + +/* + * Class Libvirt::Network + */ +void init_network() +{ +#if HAVE_TYPE_VIRNETWORKPTR + c_network = rb_define_class_under(m_libvirt, "Network", rb_cObject); + rb_define_attr(c_network, "connection", 1, 0); + + rb_define_method(c_network, "undefine", libvirt_netw_undefine, 0); + rb_define_method(c_network, "create", libvirt_netw_create, 0); + rb_define_method(c_network, "destroy", libvirt_netw_destroy, 0); + rb_define_method(c_network, "name", libvirt_netw_name, 0); + rb_define_method(c_network, "uuid", libvirt_netw_uuid, 0); + rb_define_method(c_network, "xml_desc", libvirt_netw_xml_desc, -1); + rb_define_method(c_network, "bridge_name", libvirt_netw_bridge_name, 0); + rb_define_method(c_network, "autostart", libvirt_netw_autostart, 0); + rb_define_method(c_network, "autostart?", libvirt_netw_autostart, 0); + rb_define_method(c_network, "autostart=", libvirt_netw_autostart_set, 1); + rb_define_method(c_network, "free", libvirt_netw_free, 0); +#if HAVE_VIRNETWORKISACTIVE + rb_define_method(c_network, "active?", libvirt_netw_active_p, 0); +#endif +#if HAVE_VIRNETWORKISPERSISTENT + rb_define_method(c_network, "persistent?", libvirt_netw_persistent_p, 0); +#endif +#endif +} diff -Nru ruby-libvirt-0.0.7/ext/libvirt/network.h ruby-libvirt-0.4.0/ext/libvirt/network.h --- ruby-libvirt-0.0.7/ext/libvirt/network.h 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/network.h 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,7 @@ +#ifndef NETWORK_H +#define NETWORK_H + +VALUE network_new(virNetworkPtr n, VALUE conn); +void init_network(); + +#endif diff -Nru ruby-libvirt-0.0.7/ext/libvirt/nodedevice.c ruby-libvirt-0.4.0/ext/libvirt/nodedevice.c --- ruby-libvirt-0.0.7/ext/libvirt/nodedevice.c 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/nodedevice.c 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,220 @@ +/* + * nodedevice.c: virNodeDevice methods + * + * Copyright (C) 2010 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "common.h" +#include "connect.h" +#include "extconf.h" + +#if HAVE_TYPE_VIRNODEDEVICEPTR +static VALUE c_nodedevice; + +static void nodedevice_free(void *s) { + generic_free(NodeDevice, s); +} + +static virNodeDevicePtr nodedevice_get(VALUE s) { + generic_get(NodeDevice, s); +} + +VALUE nodedevice_new(virNodeDevicePtr s, VALUE conn) { + return generic_new(c_nodedevice, s, conn, nodedevice_free); +} + +/* + * call-seq: + * nodedevice.name -> string + * + * Call +virNodeDeviceGetName+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeDeviceGetName] + * to retrieve the name of the node device. + */ +static VALUE libvirt_nodedevice_name(VALUE c) { + gen_call_string(virNodeDeviceGetName, conn(c), 0, nodedevice_get(c)); +} + +/* + * call-seq: + * nodedevice.parent -> string + * + * Call +virNodeDeviceGetParent+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeDeviceGetParent] + * to retrieve the parent of the node device. + */ +static VALUE libvirt_nodedevice_parent(VALUE c) { + /* unfortunately we can't use gen_call_string() here because + * virNodeDeviceGetParent() returns NULL as a valid value (when this + * device has no parent. Hand-code it instead + */ + + const char *str; + + str = virNodeDeviceGetParent(nodedevice_get(c)); + if (str == NULL) + return Qnil; + else + return rb_str_new2(str); +} + +/* + * call-seq: + * nodedevice.num_of_caps -> fixnum + * + * Call +virNodeDeviceNumOfCaps+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeDeviceNumOfCaps] + * to retrieve the number of capabilities of the node device. + */ +static VALUE libvirt_nodedevice_num_of_caps(VALUE c) { + gen_call_int(virNodeDeviceNumOfCaps, conn(c), nodedevice_get(c)); +} + +/* + * call-seq: + * nodedevice.list_caps -> list + * + * Call +virNodeDeviceListCaps+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeDeviceListCaps] + * to retrieve a list of capabilities of the node device. + */ +static VALUE libvirt_nodedevice_list_caps(VALUE c) { + int r, num; + virConnectPtr conn = connect_get(c); + virNodeDevicePtr nodedev = nodedevice_get(c); + char **names; + + num = virNodeDeviceNumOfCaps(nodedev); + _E(num < 0, create_error(e_RetrieveError, "virNodeDeviceNumOfCaps", conn)); + if (num == 0) + /* if num is 0, don't call virNodeDeviceListCaps function */ + return rb_ary_new2(num); + + names = ALLOC_N(char *, num); + r = virNodeDeviceListCaps(nodedev, names, num); + if (r < 0) { + xfree(names); + rb_exc_raise(create_error(e_RetrieveError, "virNodeDeviceListCaps", + conn)); + } + + return gen_list(num, &names); +} + +/* + * call-seq: + * nodedevice.xml_desc(flags=0) -> string + * + * Call +virNodeDeviceGetXMLDesc+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeDeviceGetXMLDesc] + * to retrieve the XML for the node device. + */ +static VALUE libvirt_nodedevice_xml_desc(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_string(virNodeDeviceGetXMLDesc, conn(s), 1, + nodedevice_get(s), NUM2UINT(flags)); +} + +/* + * call-seq: + * nodedevice.detach -> nil + * + * Call +virNodeDeviceDettach+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeDeviceDettach] + * to detach the node device from the node. + */ +static VALUE libvirt_nodedevice_detach(VALUE s) { + gen_call_void(virNodeDeviceDettach, conn(s), nodedevice_get(s)); +} + +/* + * call-seq: + * nodedevice.reattach -> nil + * + * Call +virNodeDeviceReAttach+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeDeviceReAttach] + * to reattach the node device to the node. + */ +static VALUE libvirt_nodedevice_reattach(VALUE s) { + gen_call_void(virNodeDeviceReAttach, conn(s), nodedevice_get(s)); +} + +/* + * call-seq: + * nodedevice.reset -> nil + * + * Call +virNodeDeviceReset+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeDeviceReset] + * to reset the node device. + */ +static VALUE libvirt_nodedevice_reset(VALUE s) { + gen_call_void(virNodeDeviceReset, conn(s), nodedevice_get(s)); +} + +#if HAVE_VIRNODEDEVICEDESTROY +/* + * call-seq: + * nodedevice.destroy -> nil + * + * Call +virNodeDeviceDestroy+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeDeviceDestroy] + * to shutdown the node device. + */ +static VALUE libvirt_nodedevice_destroy(VALUE s) { + gen_call_void(virNodeDeviceDestroy, conn(s), nodedevice_get(s)); +} +#endif + +/* + * call-seq: + * nodedevice.free -> nil + * + * Call +virNodeDeviceFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virNodeDeviceFree] + * to free the node device object. After this call the node device object is + * no longer valid. + */ +static VALUE libvirt_nodedevice_free(VALUE s) { + gen_call_free(NodeDevice, s); +} +#endif + +/* + * Class Libvirt::NodeDevice + */ +void init_nodedevice() +{ +#if HAVE_TYPE_VIRNODEDEVICEPTR + c_nodedevice = rb_define_class_under(m_libvirt, "NodeDevice", rb_cObject); + + rb_define_attr(c_nodedevice, "connection", 1, 0); + + rb_define_method(c_nodedevice, "name", libvirt_nodedevice_name, 0); + rb_define_method(c_nodedevice, "parent", libvirt_nodedevice_parent, 0); + rb_define_method(c_nodedevice, "num_of_caps", + libvirt_nodedevice_num_of_caps, 0); + rb_define_method(c_nodedevice, "list_caps", + libvirt_nodedevice_list_caps, 0); + rb_define_method(c_nodedevice, "xml_desc", libvirt_nodedevice_xml_desc, -1); + rb_define_method(c_nodedevice, "detach", libvirt_nodedevice_detach, 0); + rb_define_method(c_nodedevice, "reattach", libvirt_nodedevice_reattach, 0); + rb_define_method(c_nodedevice, "reset", libvirt_nodedevice_reset, 0); +#if HAVE_VIRNODEDEVICEDESTROY + rb_define_method(c_nodedevice, "destroy", libvirt_nodedevice_destroy, 0); +#endif + rb_define_method(c_nodedevice, "free", libvirt_nodedevice_free, 0); +#endif +} diff -Nru ruby-libvirt-0.0.7/ext/libvirt/nodedevice.h ruby-libvirt-0.4.0/ext/libvirt/nodedevice.h --- ruby-libvirt-0.0.7/ext/libvirt/nodedevice.h 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/nodedevice.h 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,6 @@ +#ifndef NODEDEVICE_H +#define NODEDEVICE_H + +void init_nodedevice(); + +#endif diff -Nru ruby-libvirt-0.0.7/ext/libvirt/nwfilter.c ruby-libvirt-0.4.0/ext/libvirt/nwfilter.c --- ruby-libvirt-0.0.7/ext/libvirt/nwfilter.c 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/nwfilter.c 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,133 @@ +/* + * nwfilter.c: virNWFilter methods + * + * Copyright (C) 2010 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "common.h" +#include "connect.h" +#include "extconf.h" + +#if HAVE_TYPE_VIRNWFILTERPTR +static VALUE c_nwfilter; + +static void nwfilter_free(void *nw) { + generic_free(NWFilter, nw); +} + +static virNWFilterPtr nwfilter_get(VALUE nw) { + generic_get(NWFilter, nw); +} + +VALUE nwfilter_new(virNWFilterPtr nw, VALUE conn) { + return generic_new(c_nwfilter, nw, conn, nwfilter_free); +} + +/* + * call-seq: + * nwfilter.undefine -> nil + * + * Call +virNWFilterUndefine+[http://www.libvirt.org/html/libvirt-libvirt.html#virNWFilterUndefine] + * to undefine the network filter. + */ +static VALUE libvirt_nwfilter_undefine(VALUE s) { + gen_call_void(virNWFilterUndefine, conn(s), nwfilter_get(s)); +} + +/* + * call-seq: + * nwfilter.name -> string + * + * Call +virNWFilterGetName+[http://www.libvirt.org/html/libvirt-libvirt.html#virNWFilterGetName] + * to retrieve the network filter name. + */ +static VALUE libvirt_nwfilter_name(VALUE s) { + gen_call_string(virNWFilterGetName, conn(s), 0, nwfilter_get(s)); +} + +/* + * call-seq: + * nwfilter.uuid -> string + * + * Call +virNWFilterGetUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virNWFilterGetUUIDString] + * to retrieve the network filter UUID. + */ +static VALUE libvirt_nwfilter_uuid(VALUE s) { + virNWFilterPtr nwfilter = nwfilter_get(s); + int r; + char uuid[VIR_UUID_STRING_BUFLEN]; + + r = virNWFilterGetUUIDString(nwfilter, uuid); + _E(r < 0, create_error(e_RetrieveError, "virNWFilterGetUUIDString", + conn(s))); + + return rb_str_new2((char *)uuid); +} + +/* + * call-seq: + * nwfilter.xml_desc(flags=0) -> string + * + * Call +virNWFilterGetXMLDesc+[http://www.libvirt.org/html/libvirt-libvirt.html#virNWFilterGetXMLDesc] + * to retrieve the XML for this network filter. + */ +static VALUE libvirt_nwfilter_xml_desc(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_string(virNWFilterGetXMLDesc, conn(s), 1, nwfilter_get(s), + NUM2UINT(flags)); +} + +/* + * call-seq: + * nwfilter.free -> nil + * + * Call +virNWFilterFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virNWFilterFree] + * to free this network filter. After this call the network filter object is + * no longer valid. + */ +static VALUE libvirt_nwfilter_free(VALUE s) { + gen_call_free(NWFilter, s); +} + +#endif + +/* + * Class Libvirt::NWFilter + */ +void init_nwfilter() +{ +#if HAVE_TYPE_VIRNWFILTERPTR + c_nwfilter = rb_define_class_under(m_libvirt, "NWFilter", rb_cObject); + rb_define_attr(c_nwfilter, "connection", 1, 0); + + /* NWFilter object methods */ + rb_define_method(c_nwfilter, "undefine", libvirt_nwfilter_undefine, 0); + rb_define_method(c_nwfilter, "name", libvirt_nwfilter_name, 0); + rb_define_method(c_nwfilter, "uuid", libvirt_nwfilter_uuid, 0); + rb_define_method(c_nwfilter, "xml_desc", libvirt_nwfilter_xml_desc, -1); + rb_define_method(c_nwfilter, "free", libvirt_nwfilter_free, 0); +#endif +} diff -Nru ruby-libvirt-0.0.7/ext/libvirt/nwfilter.h ruby-libvirt-0.4.0/ext/libvirt/nwfilter.h --- ruby-libvirt-0.0.7/ext/libvirt/nwfilter.h 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/nwfilter.h 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,6 @@ +#ifndef NWFILTER_H +#define NWFILTER_H + +void init_nwfilter(); + +#endif diff -Nru ruby-libvirt-0.0.7/ext/libvirt/secret.c ruby-libvirt-0.4.0/ext/libvirt/secret.c --- ruby-libvirt-0.0.7/ext/libvirt/secret.c 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/secret.c 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,210 @@ +/* + * secret.c: virSecret methods + * + * Copyright (C) 2010 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "common.h" +#include "connect.h" +#include "extconf.h" + +#if HAVE_TYPE_VIRSECRETPTR +static VALUE c_secret; + +static void secret_free(void *s) { + generic_free(Secret, s); +} + +static virSecretPtr secret_get(VALUE s) { + generic_get(Secret, s); +} + +VALUE secret_new(virSecretPtr s, VALUE conn) { + return generic_new(c_secret, s, conn, secret_free); +} + +/* + * call-seq: + * secret.uuid -> string + * + * Call +virSecretGetUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virSecretGetUUIDString] + * to retrieve the UUID for this secret. + */ +static VALUE libvirt_secret_uuid(VALUE s) { + virSecretPtr secret = secret_get(s); + int r; + char uuid[VIR_UUID_STRING_BUFLEN]; + + r = virSecretGetUUIDString(secret, uuid); + _E(r < 0, create_error(e_RetrieveError, "virSecretGetUUIDString", conn(s))); + + return rb_str_new2((char *)uuid); +} + +/* + * call-seq: + * secret.usagetype -> fixnum + * + * Call +virSecretGetUsageType+[http://www.libvirt.org/html/libvirt-libvirt.html#virSecretGetUsageType] + * to retrieve the usagetype for this secret. + */ +static VALUE libvirt_secret_usagetype(VALUE s) { + gen_call_int(virSecretGetUsageType, conn(s), secret_get(s)); +} + +/* + * call-seq: + * secret.usageid -> string + * + * Call +virSecretGetUsageID+[http://www.libvirt.org/html/libvirt-libvirt.html#virSecretGetUsageID] + * to retrieve the usageid for this secret. + */ +static VALUE libvirt_secret_usageid(VALUE s) { + gen_call_string(virSecretGetUsageID, conn(s), 0, secret_get(s)); +} + +/* + * call-seq: + * secret.xml_desc(flags=0) -> string + * + * Call +virSecretGetXMLDesc+[http://www.libvirt.org/html/libvirt-libvirt.html#virSecretGetXMLDesc] + * to retrieve the XML for this secret. + */ +static VALUE libvirt_secret_xml_desc(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_string(virSecretGetXMLDesc, conn(s), 1, secret_get(s), + NUM2UINT(flags)); +} + +/* + * call-seq: + * secret.set_value(value, flags=0) -> nil + * + * Call +virSecretSetValue+[http://www.libvirt.org/html/libvirt-libvirt.html#virSecretSetValue] + * to set a new value in this secret. + */ +static VALUE libvirt_secret_set_value(int argc, VALUE *argv, VALUE s) { + VALUE flags; + VALUE value; + + rb_scan_args(argc, argv, "11", &value, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + StringValue(value); + + gen_call_void(virSecretSetValue, conn(s), secret_get(s), + (unsigned char *)RSTRING_PTR(value), RSTRING_LEN(value), + NUM2UINT(flags)); +} + +/* + * call-seq: + * secret.get_value(flags=0) -> string + * + * Call +virSecretGetValue+[http://www.libvirt.org/html/libvirt-libvirt.html#virSecretGetValue] + * to retrieve the value from this secret. + */ +static VALUE libvirt_secret_get_value(int argc, VALUE *argv, VALUE s) { + virSecretPtr secret = secret_get(s); + VALUE flags; + unsigned char *val; + size_t value_size; + VALUE ret; + int exception = 0; + struct rb_str_new_arg args; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + val = virSecretGetValue(secret, &value_size, NUM2UINT(flags)); + + _E(val == NULL, create_error(e_RetrieveError, "virSecretGetValue", + conn(s))); + + args.val = (char *)val; + args.size = value_size; + ret = rb_protect(rb_str_new_wrap, (VALUE)&args, &exception); + if (exception) { + free(val); + rb_jump_tag(exception); + } + + free(val); + + return ret; +} + +/* + * call-seq: + * secret.undefine -> nil + * + * Call +virSecretUndefine+[http://www.libvirt.org/html/libvirt-libvirt.html#virSecretUndefine] + * to undefine this secret. + */ +static VALUE libvirt_secret_undefine(VALUE s) { + gen_call_void(virSecretUndefine, conn(s), secret_get(s)); +} + +/* + * call-seq: + * secret.free -> nil + * + * Call +virSecretFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virSecretFree] + * to free this secret. After this call the secret object is no longer valid. + */ +static VALUE libvirt_secret_free(VALUE s) { + gen_call_free(Secret, s); +} + +#endif + +/* + * Class Libvirt::Secret + */ +void init_secret() +{ +#if HAVE_TYPE_VIRSECRETPTR + c_secret = rb_define_class_under(m_libvirt, "Secret", rb_cObject); + + rb_define_const(c_secret, "USAGE_TYPE_VOLUME", + INT2NUM(VIR_SECRET_USAGE_TYPE_VOLUME)); + rb_define_attr(c_secret, "connection", 1, 0); + + /* Secret object methods */ + rb_define_method(c_secret, "uuid", libvirt_secret_uuid, 0); + rb_define_method(c_secret, "usagetype", libvirt_secret_usagetype, 0); + rb_define_method(c_secret, "usageid", libvirt_secret_usageid, 0); + rb_define_method(c_secret, "xml_desc", libvirt_secret_xml_desc, -1); + rb_define_method(c_secret, "set_value", libvirt_secret_set_value, -1); + rb_define_method(c_secret, "get_value", libvirt_secret_get_value, -1); + rb_define_method(c_secret, "undefine", libvirt_secret_undefine, 0); + rb_define_method(c_secret, "free", libvirt_secret_free, 0); +#endif +} diff -Nru ruby-libvirt-0.0.7/ext/libvirt/secret.h ruby-libvirt-0.4.0/ext/libvirt/secret.h --- ruby-libvirt-0.0.7/ext/libvirt/secret.h 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/secret.h 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,6 @@ +#ifndef SECRET_H +#define SECRET_H + +void init_secret(); + +#endif diff -Nru ruby-libvirt-0.0.7/ext/libvirt/storage.c ruby-libvirt-0.4.0/ext/libvirt/storage.c --- ruby-libvirt-0.0.7/ext/libvirt/storage.c 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/storage.c 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,776 @@ +/* + * storage.c: virStoragePool and virStorageVolume methods + * + * Copyright (C) 2007,2010 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "common.h" +#include "connect.h" +#include "extconf.h" +#include "stream.h" + +#if HAVE_TYPE_VIRSTORAGEVOLPTR +/* this has to be here (as opposed to below with the rest of the volume + * stuff) because libvirt_vol_get_pool() relies on it + */ +static virStorageVolPtr vol_get(VALUE s) { + generic_get(StorageVol, s); +} +#endif + +#if HAVE_TYPE_VIRSTORAGEPOOLPTR +static VALUE c_storage_pool; +static VALUE c_storage_pool_info; + +/* + * Class Libvirt::StoragePool + */ + +static void pool_free(void *d) { + generic_free(StoragePool, d); +} + +static virStoragePoolPtr pool_get(VALUE s) { + generic_get(StoragePool, s); +} + +VALUE pool_new(virStoragePoolPtr n, VALUE conn) { + return generic_new(c_storage_pool, n, conn, pool_free); +} + +/* + * call-seq: + * vol.pool -> Libvirt::StoragePool + * + * Call +virStoragePoolLookupByVolume+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolLookupByVolume] + * to retrieve the storage pool for this volume. + */ +static VALUE libvirt_vol_get_pool(VALUE v) { + virStoragePoolPtr pool; + + pool = virStoragePoolLookupByVolume(vol_get(v)); + _E(pool == NULL, create_error(e_RetrieveError, + "virStoragePoolLookupByVolume", conn(v))); + + return pool_new(pool, conn_attr(v)); +} + +/* + * call-seq: + * pool.build(flags=0) -> nil + * + * Call +virStoragePoolBuild+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolBuild] + * to build this storage pool. + */ +static VALUE libvirt_pool_build(int argc, VALUE *argv, VALUE p) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virStoragePoolBuild, conn(p), pool_get(p), NUM2UINT(flags)); +} + +/* + * call-seq: + * pool.undefine -> nil + * + * Call +virStoragePoolUndefine+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolUndefine] + * to undefine this storage pool. + */ +static VALUE libvirt_pool_undefine(VALUE p) { + gen_call_void(virStoragePoolUndefine, conn(p), pool_get(p)); +} + +/* + * call-seq: + * pool.create(flags=0) -> nil + * + * Call +virStoragePoolCreate+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolCreate] + * to start this storage pool. + */ +static VALUE libvirt_pool_create(int argc, VALUE *argv, VALUE p) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virStoragePoolCreate, conn(p), pool_get(p), NUM2UINT(flags)); +} + +/* + * call-seq: + * pool.destroy -> nil + * + * Call +virStoragePoolDestroy+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolDestroy] + * to shutdown this storage pool. + */ +static VALUE libvirt_pool_destroy(VALUE p) { + gen_call_void(virStoragePoolDestroy, conn(p), pool_get(p)); +} + +/* + * call-seq: + * pool.delete(flags=0) -> nil + * + * Call +virStoragePoolDelete+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolDelete] + * to delete the data corresponding to this data pool. This is a destructive + * operation. + */ +static VALUE libvirt_pool_delete(int argc, VALUE *argv, VALUE p) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virStoragePoolDelete, conn(p), pool_get(p), NUM2UINT(flags)); +} + +/* + * call-seq: + * pool.refresh(flags=0) -> nil + * + * Call +virStoragePoolRefresh+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolRefresh] + * to refresh the list of volumes in this storage pool. + */ +static VALUE libvirt_pool_refresh(int argc, VALUE *argv, VALUE p) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virStoragePoolRefresh, conn(p), pool_get(p), NUM2UINT(flags)); +} + +/* + * call-seq: + * pool.name -> string + * + * Call +virStoragePoolGetName+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolGetName] + * to retrieve the name of this storage pool. + */ +static VALUE libvirt_pool_name(VALUE s) { + gen_call_string(virStoragePoolGetName, conn(s), 0, pool_get(s)); +} + +/* + * call-seq: + * pool.uuid -> string + * + * Call +virStoragePoolGetUUIDString+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolGetUUIDString] + * to retrieve the UUID of this storage pool. + */ +static VALUE libvirt_pool_uuid(VALUE s) { + char uuid[VIR_UUID_STRING_BUFLEN]; + int r; + + r = virStoragePoolGetUUIDString(pool_get(s), uuid); + _E(r < 0, create_error(e_RetrieveError, "virStoragePoolGetUUIDString", + conn(s))); + + return rb_str_new2((char *) uuid); +} + +/* + * call-seq: + * pool.info -> Libvirt::StoragePoolInfo + * + * Call +virStoragePoolGetInfo+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolGetInfo] + * to retrieve information about this storage pool. + */ +static VALUE libvirt_pool_info(VALUE s) { + virStoragePoolInfo info; + int r; + VALUE result; + + r = virStoragePoolGetInfo(pool_get(s), &info); + _E(r < 0, create_error(e_RetrieveError, "virStoragePoolGetInfo", conn(s))); + + result = rb_class_new_instance(0, NULL, c_storage_pool_info); + rb_iv_set(result, "@state", INT2NUM(info.state)); + rb_iv_set(result, "@capacity", ULL2NUM(info.capacity)); + rb_iv_set(result, "@allocation", ULL2NUM(info.allocation)); + rb_iv_set(result, "@available", ULL2NUM(info.available)); + + return result; +} + +/* + * call-seq: + * pool.xml_desc(flags=0) -> string + * + * Call +virStoragePoolGetXMLDesc+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolGetXMLDesc] + * to retrieve the XML for this storage pool. + */ +static VALUE libvirt_pool_xml_desc(int argc, VALUE *argv, VALUE s) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_string(virStoragePoolGetXMLDesc, conn(s), 1, pool_get(s), + NUM2UINT(flags)); +} + +/* + * call-seq: + * pool.autostart? -> [true|false] + * + * Call +virStoragePoolGetAutostart+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolGetAutostart] + * to determine whether this storage pool will autostart when libvirtd starts. + */ +static VALUE libvirt_pool_autostart(VALUE s){ + int r, autostart; + + r = virStoragePoolGetAutostart(pool_get(s), &autostart); + _E(r < 0, create_error(e_RetrieveError, "virStoragePoolGetAutostart", + conn(s))); + + return autostart ? Qtrue : Qfalse; +} + +/* + * call-seq: + * pool.autostart = [true|false] + * + * Call +virStoragePoolSetAutostart+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolSetAutostart] + * to make this storage pool start when libvirtd starts. + */ +static VALUE libvirt_pool_autostart_set(VALUE s, VALUE autostart) { + if (autostart != Qtrue && autostart != Qfalse) + rb_raise(rb_eTypeError, + "wrong argument type (expected TrueClass or FalseClass)"); + + gen_call_void(virStoragePoolSetAutostart, conn(s), pool_get(s), + RTEST(autostart) ? 1 : 0); +} + +/* + * call-seq: + * pool.num_of_volumes -> fixnum + * + * Call +virStoragePoolNumOfVolumes+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolNumOfVolumes] + * to retrieve the number of volumes in this storage pool. + */ +static VALUE libvirt_pool_num_of_volumes(VALUE s) { + int n = virStoragePoolNumOfVolumes(pool_get(s)); + _E(n < 0, create_error(e_RetrieveError, "virStoragePoolNumOfVolumes", + conn(s))); + + return INT2NUM(n); +} + +/* + * call-seq: + * pool.list_volumes -> list + * + * Call +virStoragePoolListVolumes+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolListVolumes] + * to retrieve a list of volume names in this storage pools. + */ +static VALUE libvirt_pool_list_volumes(VALUE s) { + int r, num; + char **names; + virStoragePoolPtr pool = pool_get(s); + + num = virStoragePoolNumOfVolumes(pool); + _E(num < 0, create_error(e_RetrieveError, "virStoragePoolNumOfVolumes", + conn(s))); + if (num == 0) + return rb_ary_new2(num); + + names = ALLOC_N(char *, num); + r = virStoragePoolListVolumes(pool, names, num); + if (r < 0) { + xfree(names); + rb_exc_raise(create_error(e_RetrieveError, "virStoragePoolListVolumes", + conn(s))); + } + + return gen_list(num, &names); +} + +/* + * call-seq: + * pool.free -> nil + * + * Call +virStoragePoolFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolFree] + * to free this storage pool object. After this call the storage pool object + * is no longer valid. + */ +static VALUE libvirt_pool_free(VALUE s) { + gen_call_free(StoragePool, s); +} +#endif + +#if HAVE_TYPE_VIRSTORAGEVOLPTR +/* + * Libvirt::StorageVol + */ +static VALUE c_storage_vol; +static VALUE c_storage_vol_info; + +static void vol_free(void *d) { + generic_free(StorageVol, d); +} + +static VALUE vol_new(virStorageVolPtr n, VALUE conn) { + return generic_new(c_storage_vol, n, conn, vol_free); +} + +/* + * call-seq: + * pool.lookup_volume_by_name(name) -> Libvirt::StorageVol + * + * Call +virStorageVolLookupByName+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolLookupByName] + * to retrieve a storage volume object by name. + */ +static VALUE libvirt_pool_lookup_vol_by_name(VALUE p, VALUE name) { + virStorageVolPtr vol; + + vol = virStorageVolLookupByName(pool_get(p), StringValueCStr(name)); + _E(vol == NULL, create_error(e_RetrieveError, "virStorageVolLookupByName", + conn(p))); + + return vol_new(vol, conn_attr(p)); +} + +/* + * call-seq: + * pool.lookup_volume_by_key(key) -> Libvirt::StorageVol + * + * Call +virStorageVolLookupByKey+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolLookupByKey] + * to retrieve a storage volume object by key. + */ +static VALUE libvirt_pool_lookup_vol_by_key(VALUE p, VALUE key) { + virStorageVolPtr vol; + + /* FIXME: Why does this take a connection, not a pool? */ + vol = virStorageVolLookupByKey(conn(p), StringValueCStr(key)); + _E(vol == NULL, create_error(e_RetrieveError, "virStorageVolLookupByKey", + conn(p))); + + return vol_new(vol, conn_attr(p)); +} + +/* + * call-seq: + * pool.lookup_volume_by_path(path) -> Libvirt::StorageVol + * + * Call +virStorageVolLookupByPath+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolLookupByPath] + * to retrieve a storage volume object by path. + */ +static VALUE libvirt_pool_lookup_vol_by_path(VALUE p, VALUE path) { + virStorageVolPtr vol; + + /* FIXME: Why does this take a connection, not a pool? */ + vol = virStorageVolLookupByPath(conn(p), StringValueCStr(path)); + _E(vol == NULL, create_error(e_RetrieveError, "virStorageVolLookupByPath", + conn(p))); + + return vol_new(vol, conn_attr(p)); +} + +/* + * call-seq: + * vol.name -> string + * + * Call +virStorageVolGetName+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolGetName] + * to retrieve the name of this storage volume. + */ +static VALUE libvirt_vol_name(VALUE v) { + gen_call_string(virStorageVolGetName, conn(v), 0, vol_get(v)); +} + +/* + * call-seq: + * vol.key -> string + * + * Call +virStorageVolGetKey+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolGetKey] + * to retrieve the key for this storage volume. + */ +static VALUE libvirt_vol_key(VALUE v) { + gen_call_string(virStorageVolGetKey, conn(v), 0, vol_get(v)); +} + +/* + * call-seq: + * pool.create_volume_xml(xml, flags=0) -> Libvirt::StorageVol + * + * Call +virStorageVolCreateXML+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolCreateXML] + * to create a new storage volume from xml. + */ +static VALUE libvirt_pool_vol_create_xml(int argc, VALUE *argv, VALUE p) { + virStorageVolPtr vol; + virConnectPtr c = conn(p); + VALUE xml, flags; + + rb_scan_args(argc, argv, "11", &xml, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + vol = virStorageVolCreateXML(pool_get(p), StringValueCStr(xml), + NUM2UINT(flags)); + _E(vol == NULL, create_error(e_Error, "virNetworkCreateXML", c)); + + return vol_new(vol, conn_attr(p)); +} + +#if HAVE_VIRSTORAGEVOLCREATEXMLFROM +/* + * call-seq: + * pool.create_volume_xml_from(xml, clonevol, flags=0) -> Libvirt::StorageVol + * + * Call +virStorageVolCreateXMLFrom+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolCreateXMLFrom] + * to clone a volume from an existing volume with the properties specified in + * xml. + */ +static VALUE libvirt_pool_vol_create_xml_from(int argc, VALUE *argv, VALUE p) { + virStorageVolPtr vol; + virConnectPtr c = conn(p); + VALUE xml, flags, cloneval; + + rb_scan_args(argc, argv, "21", &xml, &cloneval, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + vol = virStorageVolCreateXMLFrom(pool_get(p), StringValueCStr(xml), + vol_get(cloneval), NUM2UINT(flags)); + _E(vol == NULL, create_error(e_Error, "virNetworkCreateXMLFrom", c)); + + return vol_new(vol, conn_attr(p)); +} +#endif + +#if HAVE_VIRSTORAGEPOOLISACTIVE +/* + * call-seq: + * pool.active? -> [true|false] + * + * Call +virStoragePoolIsActive+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolIsActive] + * to determine if this storage pool is active. + */ +static VALUE libvirt_pool_active_p(VALUE p) { + gen_call_truefalse(virStoragePoolIsActive, conn(p), pool_get(p)); +} +#endif + +#if HAVE_VIRSTORAGEPOOLISPERSISTENT +/* + * call-seq: + * pool.persistent? -> [true|false] + * + * Call +virStoragePoolIsPersistent+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolIsPersistent] + * to determine if this storage pool is persistent. + */ +static VALUE libvirt_pool_persistent_p(VALUE p) { + gen_call_truefalse(virStoragePoolIsPersistent, conn(p), pool_get(p)); +} +#endif + +/* + * call-seq: + * vol.delete(flags=0) -> nil + * + * Call +virStorageVolDelete+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolDelete] + * to delete this volume. This is a destructive operation. + */ +static VALUE libvirt_vol_delete(int argc, VALUE *argv, VALUE v) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virStorageVolDelete, conn(v), vol_get(v), NUM2UINT(flags)); +} + +#if HAVE_VIRSTORAGEVOLWIPE +/* + * call-seq: + * vol.wipe(flags=0) -> nil + * + * Call +virStorageVolWipe+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolWipe] + * to wipe the data from this storage volume. This is a destructive operation. + */ +static VALUE libvirt_vol_wipe(int argc, VALUE *argv, VALUE v) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virStorageVolWipe, conn(v), vol_get(v), NUM2UINT(flags)); +} +#endif + +/* + * call-seq: + * vol.info -> Libvirt::StorageVolInfo + * + * Call +virStorageVolGetInfo+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolGetInfo] + * to retrieve information about this storage volume. + */ +static VALUE libvirt_vol_info(VALUE v) { + virStorageVolInfo info; + int r; + VALUE result; + + r = virStorageVolGetInfo(vol_get(v), &info); + _E(r < 0, create_error(e_RetrieveError, "virStorageVolGetInfo", conn(v))); + + result = rb_class_new_instance(0, NULL, c_storage_vol_info); + rb_iv_set(result, "@type", INT2NUM(info.type)); + rb_iv_set(result, "@capacity", ULL2NUM(info.capacity)); + rb_iv_set(result, "@allocation", ULL2NUM(info.allocation)); + + return result; +} + +/* + * call-seq: + * vol.xml_desc(flags=0) -> string + * + * Call +virStorageVolGetXMLDesc+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolGetXMLDesc] + * to retrieve the xml for this storage volume. + */ +static VALUE libvirt_vol_xml_desc(int argc, VALUE *argv, VALUE v) { + VALUE flags; + + rb_scan_args(argc, argv, "01", &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_string(virStorageVolGetXMLDesc, conn(v), 1, vol_get(v), + NUM2UINT(flags)); +} + +/* + * call-seq: + * vol.path -> string + * + * Call +virStorageVolGetPath+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolGetPath] + * to retrieve the path for this storage volume. + */ +static VALUE libvirt_vol_path(VALUE v) { + gen_call_string(virStorageVolGetPath, conn(v), 1, vol_get(v)); +} + +/* + * call-seq: + * vol.free -> nil + * + * Call +virStorageVolFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolFree] + * to free the storage volume object. After this call the storage volume object + * is no longer valid. + */ +static VALUE libvirt_vol_free(VALUE s) { + gen_call_free(StorageVol, s); +} +#endif + +#if HAVE_VIRSTORAGEVOLDOWNLOAD +/* + * call-seq: + * vol.download(stream, offset, length, flags=0) -> nil + * + * Call +virStorageVolDownload+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolDownload] + * to download the content of a volume as a stream. + */ +static VALUE libvirt_vol_download(int argc, VALUE *argv, VALUE v) { + VALUE st, offset, length, flags; + + rb_scan_args(argc, argv, "31", &st, &offset, &length, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virStorageVolDownload, conn(v), vol_get(v), stream_get(st), + NUM2ULL(offset), NUM2ULL(length), NUM2UINT(flags)); +} + +/* + * call-seq: + * vol.upload(stream, offset, length, flags=0) -> nil + * + * Call +virStorageVolUpload+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolUpload] + * to upload new content to a volume from a stream. + */ +static VALUE libvirt_vol_upload(int argc, VALUE *argv, VALUE v) { + VALUE st, offset, length, flags; + + rb_scan_args(argc, argv, "31", &st, &offset, &length, &flags); + + if (NIL_P(flags)) + flags = INT2NUM(0); + + gen_call_void(virStorageVolUpload, conn(v), vol_get(v), stream_get(st), + NUM2ULL(offset), NUM2ULL(length), NUM2UINT(flags)); +} +#endif + +void init_storage(void) { + /* + * Class Libvirt::StoragePool and Libvirt::StoragePoolInfo + */ +#if HAVE_TYPE_VIRSTORAGEPOOLPTR + c_storage_pool_info = rb_define_class_under(m_libvirt, "StoragePoolInfo", + rb_cObject); + rb_define_attr(c_storage_pool_info, "state", 1, 0); + rb_define_attr(c_storage_pool_info, "capacity", 1, 0); + rb_define_attr(c_storage_pool_info, "allocation", 1, 0); + rb_define_attr(c_storage_pool_info, "available", 1, 0); + + c_storage_pool = rb_define_class_under(m_libvirt, "StoragePool", + rb_cObject); + + rb_define_attr(c_storage_pool, "connection", 1, 0); + + /* virStoragePoolState */ + rb_define_const(c_storage_pool, "INACTIVE", + INT2NUM(VIR_STORAGE_POOL_INACTIVE)); + rb_define_const(c_storage_pool, "BUILDING", + INT2NUM(VIR_STORAGE_POOL_BUILDING)); + rb_define_const(c_storage_pool, "RUNNING", + INT2NUM(VIR_STORAGE_POOL_RUNNING)); + rb_define_const(c_storage_pool, "DEGRADED", + INT2NUM(VIR_STORAGE_POOL_DEGRADED)); +#if HAVE_CONST_VIR_STORAGE_POOL_INACCESSIBLE + rb_define_const(c_storage_pool, "INACCESSIBLE", + INT2NUM(VIR_STORAGE_POOL_INACCESSIBLE)); +#endif + + /* virStoragePoolBuildFlags */ + rb_define_const(c_storage_pool, "BUILD_NEW", + INT2NUM(VIR_STORAGE_POOL_BUILD_NEW)); + rb_define_const(c_storage_pool, "BUILD_REPAIR", + INT2NUM(VIR_STORAGE_POOL_BUILD_REPAIR)); + rb_define_const(c_storage_pool, "BUILD_RESIZE", + INT2NUM(VIR_STORAGE_POOL_BUILD_RESIZE)); + + /* virStoragePoolDeleteFlags */ + rb_define_const(c_storage_pool, "DELETE_NORMAL", + INT2NUM(VIR_STORAGE_POOL_DELETE_NORMAL)); + rb_define_const(c_storage_pool, "DELETE_ZEROED", + INT2NUM(VIR_STORAGE_POOL_DELETE_ZEROED)); + + /* Creating/destroying pools */ + rb_define_method(c_storage_pool, "build", libvirt_pool_build, -1); + rb_define_method(c_storage_pool, "undefine", libvirt_pool_undefine, 0); + rb_define_method(c_storage_pool, "create", libvirt_pool_create, -1); + rb_define_method(c_storage_pool, "destroy", libvirt_pool_destroy, 0); + rb_define_method(c_storage_pool, "delete", libvirt_pool_delete, -1); + rb_define_method(c_storage_pool, "refresh", libvirt_pool_refresh, -1); + /* StoragePool information */ + rb_define_method(c_storage_pool, "name", libvirt_pool_name, 0); + rb_define_method(c_storage_pool, "uuid", libvirt_pool_uuid, 0); + rb_define_method(c_storage_pool, "info", libvirt_pool_info, 0); + rb_define_method(c_storage_pool, "xml_desc", libvirt_pool_xml_desc, -1); + rb_define_method(c_storage_pool, "autostart", libvirt_pool_autostart, 0); + rb_define_method(c_storage_pool, "autostart?", libvirt_pool_autostart, 0); + rb_define_method(c_storage_pool, "autostart=", + libvirt_pool_autostart_set, 1); + /* List/lookup storage volumes within a pool */ + rb_define_method(c_storage_pool, "num_of_volumes", + libvirt_pool_num_of_volumes, 0); + rb_define_method(c_storage_pool, "list_volumes", + libvirt_pool_list_volumes, 0); + /* Lookup volumes based on various attributes */ + rb_define_method(c_storage_pool, "lookup_volume_by_name", + libvirt_pool_lookup_vol_by_name, 1); + rb_define_method(c_storage_pool, "lookup_volume_by_key", + libvirt_pool_lookup_vol_by_key, 1); + rb_define_method(c_storage_pool, "lookup_volume_by_path", + libvirt_pool_lookup_vol_by_path, 1); + rb_define_method(c_storage_pool, "free", libvirt_pool_free, 0); + rb_define_method(c_storage_pool, "create_vol_xml", + libvirt_pool_vol_create_xml, -1); + rb_define_alias(c_storage_pool, "create_volume_xml", "create_vol_xml"); +#if HAVE_VIRSTORAGEVOLCREATEXMLFROM + rb_define_method(c_storage_pool, "create_vol_xml_from", + libvirt_pool_vol_create_xml_from, -1); + rb_define_alias(c_storage_pool, "create_volume_xml_from", + "create_vol_xml_from"); +#endif +#if HAVE_VIRSTORAGEPOOLISACTIVE + rb_define_method(c_storage_pool, "active?", libvirt_pool_active_p, 0); +#endif +#if HAVE_VIRSTORAGEPOOLISPERSISTENT + rb_define_method(c_storage_pool, "persistent?", + libvirt_pool_persistent_p, 0); +#endif +#endif + +#if HAVE_TYPE_VIRSTORAGEVOLPTR + /* + * Class Libvirt::StorageVol and Libvirt::StorageVolInfo + */ + c_storage_vol_info = rb_define_class_under(m_libvirt, "StorageVolInfo", + rb_cObject); + rb_define_attr(c_storage_vol_info, "type", 1, 0); + rb_define_attr(c_storage_vol_info, "capacity", 1, 0); + rb_define_attr(c_storage_vol_info, "allocation", 1, 0); + + c_storage_vol = rb_define_class_under(m_libvirt, "StorageVol", + rb_cObject); + + /* virStorageVolType */ + rb_define_const(c_storage_vol, "FILE", INT2NUM(VIR_STORAGE_VOL_FILE)); + rb_define_const(c_storage_vol, "BLOCK", INT2NUM(VIR_STORAGE_VOL_BLOCK)); + + /* virStorageVolDeleteFlags */ + rb_define_const(c_storage_vol, "DELETE_NORMAL", + INT2NUM(VIR_STORAGE_VOL_DELETE_NORMAL)); + rb_define_const(c_storage_vol, "DELETE_ZEROED", + INT2NUM(VIR_STORAGE_VOL_DELETE_ZEROED)); + + rb_define_method(c_storage_vol, "pool", libvirt_vol_get_pool, 0); + rb_define_method(c_storage_vol, "name", libvirt_vol_name, 0); + rb_define_method(c_storage_vol, "key", libvirt_vol_key, 0); + rb_define_method(c_storage_vol, "delete", libvirt_vol_delete, -1); +#if HAVE_VIRSTORAGEVOLWIPE + rb_define_method(c_storage_vol, "wipe", libvirt_vol_wipe, -1); +#endif + rb_define_method(c_storage_vol, "info", libvirt_vol_info, 0); + rb_define_method(c_storage_vol, "xml_desc", libvirt_vol_xml_desc, -1); + rb_define_method(c_storage_vol, "path", libvirt_vol_path, 0); + rb_define_method(c_storage_vol, "free", libvirt_vol_free, 0); + +#if HAVE_VIRSTORAGEVOLDOWNLOAD + rb_define_method(c_storage_vol, "download", libvirt_vol_download, -1); + rb_define_method(c_storage_vol, "upload", libvirt_vol_upload, -1); +#endif + +#endif +} diff -Nru ruby-libvirt-0.0.7/ext/libvirt/storage.h ruby-libvirt-0.4.0/ext/libvirt/storage.h --- ruby-libvirt-0.0.7/ext/libvirt/storage.h 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/storage.h 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,6 @@ +#ifndef STORAGE_H +#define STORAGE_H + +void init_storage(); + +#endif diff -Nru ruby-libvirt-0.0.7/ext/libvirt/stream.c ruby-libvirt-0.4.0/ext/libvirt/stream.c --- ruby-libvirt-0.0.7/ext/libvirt/stream.c 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/stream.c 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,394 @@ +/* + * stream.c: virStream methods + * + * Copyright (C) 2007,2010 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "common.h" +#include "connect.h" +#include "extconf.h" + +#if HAVE_TYPE_VIRSTREAMPTR +static VALUE c_stream; + +static void stream_free(void *s) { + generic_free(Stream, s); +} + +virStreamPtr stream_get(VALUE s) { + generic_get(Stream, s); +} + +VALUE stream_new(virStreamPtr s, VALUE conn) { + return generic_new(c_stream, s, conn, stream_free); +} + +/* + * call-seq: + * stream.send(buffer) -> Fixnum + * + * Call +virStreamSend+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamSend] + * to send the data in buffer out to the stream. The return value is the + * number of bytes sent, which may be less than the size of the buffer. If + * an error occurred, -1 is returned. If the transmit buffers are full and the + * stream is marked non-blocking, returns -2. + */ +static VALUE libvirt_stream_send(VALUE s, VALUE buffer) { + int ret; + + StringValue(buffer); + + ret = virStreamSend(stream_get(s), RSTRING_PTR(buffer), + RSTRING_LEN(buffer)); + _E(ret == -1, create_error(e_RetrieveError, "virStreamSend", conn(s))); + + return INT2NUM(ret); +} + +struct stream_recv_args { + int ret; + char *data; +}; + +static VALUE stream_recv_array(VALUE input) { + VALUE result; + struct stream_recv_args *args = (struct stream_recv_args *)input; + + result = rb_ary_new(); + + rb_ary_push(result, INT2NUM(args->ret)); + rb_ary_push(result, rb_str_new(args->data, args->ret)); + + return result; +} + +/* + * call-seq: + * stream.recv(bytes) -> [return_value, data] + * + * Call +virStreamRecv+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamRecv] + * to receive up to bytes amount of data from the stream. The return is an + * array with two elements; the return code from the virStreamRecv call and + * the data (as a String) read from the stream. If an error occurred, the + * return_value is set to -1. If there is no data pending and the stream is + * marked as non-blocking, return_value is set to -2. + */ +static VALUE libvirt_stream_recv(VALUE s, VALUE bytes) { + char *data; + int ret; + int exception = 0; + VALUE result; + struct stream_recv_args args; + + data = ALLOC_N(char, NUM2INT(bytes)); + + ret = virStreamRecv(stream_get(s), data, NUM2INT(bytes)); + if (ret == -1) { + xfree(data); + rb_exc_raise(create_error(e_RetrieveError, "virStreamRecv", conn(s))); + } + + args.ret = ret; + args.data = data; + result = rb_protect(stream_recv_array, (VALUE)&args, &exception); + if (exception) { + xfree(data); + rb_jump_tag(exception); + } + + xfree(data); + return result; +} + +static int internal_sendall(virStreamPtr st, char *data, size_t nbytes, + void *opaque) { + VALUE result; + VALUE retcode, buffer; + + result = rb_yield_values(2, (VALUE)opaque, INT2NUM(nbytes)); + + if (TYPE(result) != T_ARRAY) + rb_raise(rb_eTypeError, "wrong type (expected Array)"); + + if (RARRAY_LEN(result) != 2) + rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", + RARRAY_LEN(result)); + + retcode = rb_ary_entry(result, 0); + buffer = rb_ary_entry(result, 1); + + if (NUM2INT(retcode) < 0) + return NUM2INT(retcode); + + StringValue(buffer); + + if (RSTRING_LEN(buffer) > nbytes) + rb_raise(rb_eArgError, "asked for %d bytes, block returned %d", nbytes, + RSTRING_LEN(buffer)); + + memcpy(data, RSTRING_PTR(buffer), RSTRING_LEN(buffer)); + + return NUM2INT(retcode); +} + +/* + * call-seq: + * stream.sendall(opaque=nil){|opaque, nbytes| send block} -> nil + * + * Call +virStreamSendAll+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamSendAll] + * to send the entire data stream. The send block is required and is executed + * one or more times to send data. Each invocation of the send block yields + * the opaque data passed into the initial call and the number of bytes this + * iteration is prepared to handle. The send block should return an array of + * 2 elements; the first element should be the return code from the block + * (-1 for error, 0 otherwise), and the second element should be the data + * that the block prepared to send. + */ +static VALUE libvirt_stream_sendall(int argc, VALUE *argv, VALUE s) { + VALUE opaque; + int ret; + + if (!rb_block_given_p()) + rb_raise(rb_eRuntimeError, "A block must be provided"); + + rb_scan_args(argc, argv, "01", &opaque); + + ret = virStreamSendAll(stream_get(s), internal_sendall, (void *)opaque); + _E(ret < 0, create_error(e_RetrieveError, "virStreamSendAll", conn(s))); + + return Qnil; +} + +static int internal_recvall(virStreamPtr st, const char *buf, size_t nbytes, + void *opaque) { + VALUE result; + + result = rb_yield_values(2, rb_str_new(buf, nbytes), (VALUE)opaque); + + if (TYPE(result) != T_FIXNUM) + rb_raise(rb_eArgError, "wrong type (expected an integer)"); + + return NUM2INT(result); +} + +/* + * call-seq: + * stream.recvall(opaque){|data, opaque| receive block} -> nil + * + * Call +virStreamRecvAll+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamRecvAll] + * to receive the entire data stream. The receive block is required and is + * called one or more times to receive data. Each invocation of the receive + * block yields the data received and the opaque data passed into the initial + * call. The block should return -1 if an error occurred and 0 otherwise. + */ +static VALUE libvirt_stream_recvall(int argc, VALUE *argv, VALUE s) { + VALUE opaque; + int ret; + + if (!rb_block_given_p()) + rb_raise(rb_eRuntimeError, "A block must be provided"); + + rb_scan_args(argc, argv, "01", &opaque); + + ret = virStreamRecvAll(stream_get(s), internal_recvall, (void *)opaque); + _E(ret < 0, create_error(e_RetrieveError, "virStreamRecvAll", conn(s))); + + return Qnil; +} + +static void stream_event_callback(virStreamPtr st, int events, void *opaque) { + VALUE passthrough = (VALUE)opaque; + VALUE cb; + VALUE cb_opaque; + VALUE news; + VALUE s; + + if (TYPE(passthrough) != T_ARRAY) + rb_raise(rb_eTypeError, + "wrong domain event lifecycle callback argument type (expected Array)"); + + if (RARRAY_LEN(passthrough) != 3) + rb_raise(rb_eArgError, "wrong number of arguments (%d for 3)", + RARRAY_LEN(passthrough)); + + cb = rb_ary_entry(passthrough, 0); + cb_opaque = rb_ary_entry(passthrough, 1); + s = rb_ary_entry(passthrough, 2); + + news = stream_new(st, conn_attr(s)); + if (strcmp(rb_obj_classname(cb), "Symbol") == 0) + rb_funcall(rb_class_of(cb), rb_to_id(cb), 3, news, INT2NUM(events), + cb_opaque); + else if (strcmp(rb_obj_classname(cb), "Proc") == 0) + rb_funcall(cb, rb_intern("call"), 3, news, INT2NUM(events), cb_opaque); + else + rb_raise(rb_eTypeError, + "wrong stream event callback (expected Symbol or Proc)"); +} + +/* + * call-seq: + * stream.event_add_callback(events, callback, opaque=nil) -> nil + * + * Call +virStreamEventAddCallback+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamEventAddCallback] + * to register a callback to be notified when a stream becomes readable or + * writeable. The events parameter is an integer representing the events the + * user is interested in; it should be one or more of EVENT_READABLE, + * EVENT_WRITABLE, EVENT_ERROR, and EVENT_HANGUP, ORed together. The callback + * can either be a Symbol (that is the name of a method to callback) or a Proc. + * The callback should accept 3 parameters: a pointer to the Stream object + * itself, the integer that represents the events that actually occurred, and + * an opaque pointer that was (optionally) passed into + * stream.event_add_callback to begin with. + */ +static VALUE libvirt_stream_event_add_callback(int argc, VALUE *argv, VALUE s) { + VALUE events; + VALUE callback; + VALUE opaque; + VALUE passthrough; + int ret; + + rb_scan_args(argc, argv, "21", &events, &callback, &opaque); + + if (!is_symbol_or_proc(callback)) + rb_raise(rb_eTypeError, "wrong argument type (expected Symbol or Proc)"); + + passthrough = rb_ary_new(); + rb_ary_store(passthrough, 0, callback); + rb_ary_store(passthrough, 1, opaque); + rb_ary_store(passthrough, 2, s); + + ret = virStreamEventAddCallback(stream_get(s), NUM2INT(events), + stream_event_callback, (void *)passthrough, + NULL); + _E(ret < 0, create_error(e_RetrieveError, "virStreamEventAddCallback", + conn(s))); + + return Qnil; +} + +/* + * call-seq: + * stream.event_update_callback(events) -> nil + * + * Call +virStreamEventUpdateCallback+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamEventUpdateCallback] + * to change the events that the event callback is looking for. The events + * parameter is an integer representing the events the user is interested in; + * it should be one or more of EVENT_READABLE, EVENT_WRITABLE, EVENT_ERROR, + * and EVENT_HANGUP, ORed together. + */ +static VALUE libvirt_stream_event_update_callback(VALUE s, VALUE events) { + int ret; + + ret = virStreamEventUpdateCallback(stream_get(s), NUM2INT(events)); + _E(ret < 0, create_error(e_RetrieveError, "virStreamEventUpdateCallback", + conn(s))); + + return Qnil; +} + +/* + * call-seq: + * stream.event_remove_callback -> nil + * + * Call +virStreamEventRemoveCallback+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamEventRemoveCallback] + * to remove the event callback currently registered to this stream. + */ +static VALUE libvirt_stream_event_remove_callback(VALUE s) { + int ret; + + ret = virStreamEventRemoveCallback(stream_get(s)); + _E(ret < 0, create_error(e_RetrieveError, "virStreamEventRemoveCallback", + conn(s))); + + return Qnil; +} + +/* + * call-seq: + * stream.finish -> nil + * + * Call +virStreamFinish+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamFinish] + * to finish this stream. Finish is typically used when the stream is no + * longer needed and needs to be cleaned up. + */ +static VALUE libvirt_stream_finish(VALUE s) { + gen_call_void(virStreamFinish, conn(s), stream_get(s)); +} + +/* + * call-seq: + * stream.abort -> nil + * + * Call +virStreamAbort+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamAbort] + * to abort this stream. Abort is typically used when something on the stream + * has failed, and the stream needs to be cleaned up. + */ +static VALUE libvirt_stream_abort(VALUE s) { + gen_call_void(virStreamAbort, conn(s), stream_get(s)); +} + +/* + * call-seq: + * stream.free -> nil + * + * Call +virStreamFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamFree] + * to free this stream. The object will no longer be valid after this call. + */ +static VALUE libvirt_stream_free(VALUE s) { + gen_call_free(Stream, s); +} +#endif + +/* + * Class Libvirt::Domain + */ +void init_stream() +{ +#if HAVE_TYPE_VIRSTREAMPTR + c_stream = rb_define_class_under(m_libvirt, "Stream", rb_cObject); + + rb_define_attr(c_stream, "connection", 1, 0); + + rb_define_const(c_stream, "NONBLOCK", INT2NUM(VIR_STREAM_NONBLOCK)); + + rb_define_const(c_stream, "EVENT_READABLE", + INT2NUM(VIR_STREAM_EVENT_READABLE)); + rb_define_const(c_stream, "EVENT_WRITABLE", + INT2NUM(VIR_STREAM_EVENT_WRITABLE)); + rb_define_const(c_stream, "EVENT_ERROR", INT2NUM(VIR_STREAM_EVENT_ERROR)); + rb_define_const(c_stream, "EVENT_HANGUP", INT2NUM(VIR_STREAM_EVENT_HANGUP)); + + rb_define_method(c_stream, "send", libvirt_stream_send, 1); + rb_define_method(c_stream, "recv", libvirt_stream_recv, 2); + rb_define_method(c_stream, "sendall", libvirt_stream_sendall, -1); + rb_define_method(c_stream, "recvall", libvirt_stream_recvall, -1); + + rb_define_method(c_stream, "event_add_callback", + libvirt_stream_event_add_callback, -1); + rb_define_method(c_stream, "event_update_callback", + libvirt_stream_event_update_callback, 1); + rb_define_method(c_stream, "event_remove_callback", + libvirt_stream_event_remove_callback, 0); + rb_define_method(c_stream, "finish", libvirt_stream_finish, 0); + rb_define_method(c_stream, "abort", libvirt_stream_abort, 0); + rb_define_method(c_stream, "free", libvirt_stream_free, 0); +#endif +} diff -Nru ruby-libvirt-0.0.7/ext/libvirt/stream.h ruby-libvirt-0.4.0/ext/libvirt/stream.h --- ruby-libvirt-0.0.7/ext/libvirt/stream.h 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ext/libvirt/stream.h 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,7 @@ +#ifndef STREAM_H +#define STREAM_H + +virStreamPtr stream_get(VALUE s); +void init_stream(); + +#endif diff -Nru ruby-libvirt-0.0.7/NEWS ruby-libvirt-0.4.0/NEWS --- ruby-libvirt-0.0.7/NEWS 2008-04-15 20:15:41.000000000 +0000 +++ ruby-libvirt-0.4.0/NEWS 2011-07-29 16:19:09.000000000 +0000 @@ -1,3 +1,68 @@ +2011-07-27 0.4.0 + * Updated Domain class, implementing dom.memory_parameters=, + dom.memory_parameters, dom.updated?, dom.migrate2, dom.migrate_to_uri2, + dom.migrate_set_max_speed, dom.qemu_monitor_command, dom.blkio_parameters, + dom.blkio_parameters=, dom.state, dom.open_console, dom.screenshot, and + dom.inject_nmi + * Implementation of the Stream class, which covers the libvirt virStream APIs + * Add the ability to build against non-system libvirt libraries + * Updated Error object, which now includes the libvirt code, component and + level of the error, as well as all of the error constants from libvirt.h + * Updated Connect class, implementing conn.sys_info, conn.stream, + conn.interface_change_begin, conn.interface_change_commit, and + conn.interface_change_rollback + * Updated StorageVol class, implementing vol.download and vol.upload + * Various bugfixes + +2010-12-12 0.3.0 + * Implementation of Libvirt::open_auth, Libvirt::event_register_impl + * Updated Connect class, implementing conn.compare_cpu, conn.baseline_cpu, + conn.domain_event_register_any, conn.domain_event_deregister_any, + conn.domain_event_register, conn.domain_event_deregister, and + conn.create_domain_xml. + * Updated Domain class, implementing dom.get_vcpus, dom.update_device, + dom.scheduler_type, dom.scheduler_parameters, dom.scheduler_parameters=, + dom.num_vcpus, dom.vcpus_flags=, and dom.qemu_monitor_command. + * Updated Interface class, implementing interface.free + * Many potential memory leaks have been fixed. + * Many bugfixes. + * Documentation update of many methods, including all of the lookup methods + that were missing before. + +2010-11-10 + * Gem for version 0.2.0 pushed to rubygems.org + +2010-07-01 0.2.0 + * Updated Storage class, implementing pool.active?, pool.persistent?, + pool.vol_create_xml_from. + * Updated Connect class, implementing conn.node_free_memory, + conn.node_cells_free_memory, conn.node_get_security_model, conn.encrypted?, + conn.libversion, and conn.secure? + * Updated Network class, implementing network.active? and network.persistent? + * Update Domain class, implementing conn.domain_xml_from_native, + conn.domain_xml_to_native, dom.migrate_to_uri, + dom.migrate_set_max_downtime, dom.managed_save, dom.has_managed_save?, + dom.managed_save_remove, dom.security_label, dom.block_stats, + dom.memory_stats, dom.blockinfo, dom.block_peek, dom.memory_peek, + dom.active?, dom.persistent?, dom.snapshot_create_xml, + dom.num_of_snapshots, dom.list_snapshots, dom.lookup_snapshot_by_name, + dom.has_current_snapshot?, dom.revert_to_snapshot, dom.current_snapshot, + snapshot.xml_desc, snapshot.delete, dom.job_info, and dom.abort_job. + * Implementation of the NodeDevice class. + * Implementation of the Secret class. + * Implementation of the NWFilter class. + * Implementation of the Interface class. + * Conversion of the development tree to git. + * New maintainer (Chris Lalancette). David Lutterkort has agreed to transfer + maintainership since he is not actively involved in their development + anymore. + +2008-11-18 0.1.0 + * Add binding for virConnectFindStoragePoolSources (clalance) + * Fix dom_migrate (clalance) + * Add the MIGRATE_LIVE (enum virDomainMigrateFlags) flag + * Slight improvements of the unit tests + 2008-04-15 0.0.7 * Binding for virDomainMigrate * Fix crash caused by using virResetError diff -Nru ruby-libvirt-0.0.7/Rakefile ruby-libvirt-0.4.0/Rakefile --- ruby-libvirt-0.0.7/Rakefile 2008-04-15 20:14:47.000000000 +0000 +++ ruby-libvirt-0.4.0/Rakefile 2011-07-29 16:19:09.000000000 +0000 @@ -1,7 +1,7 @@ # -*- ruby -*- # Rakefile: build ruby libvirt bindings # -# Copyright (C) 2007 Red Hat, Inc. +# Copyright (C) 2007,2010 Red Hat, Inc. # # Distributed under the GNU Lesser General Public License v2.1 or later. # See COPYING for details @@ -13,78 +13,119 @@ require 'rake/rdoctask' require 'rake/testtask' require 'rake/gempackagetask' +require 'rbconfig' PKG_NAME='ruby-libvirt' -PKG_VERSION='0.0.7' +PKG_VERSION='0.4.0' EXT_CONF='ext/libvirt/extconf.rb' MAKEFILE="ext/libvirt/Makefile" LIBVIRT_MODULE="ext/libvirt/_libvirt.so" SPEC_FILE="ruby-libvirt.spec" -LIBVIRT_SRC=LIBVIRT_MODULE.gsub(/.so$/, ".c") +LIBVIRT_SRC=Dir.glob("ext/libvirt/*.c") +LIBVIRT_SRC << MAKEFILE # # Additional files for clean/clobber # -CLEAN.include "**/*~" +CLEAN.include [ "ext/**/*.o", LIBVIRT_MODULE, + "ext/**/depend" ] -CLOBBER.include [ "config.save", - "ext/**/*.o", LIBVIRT_MODULE, - "ext/**/depend", "ext/**/mkmf.log", +CLOBBER.include [ "config.save", "ext/**/mkmf.log", "ext/**/extconf.h", MAKEFILE ] # # Build locally # -# FIXME: We can't get rid of install.rb yet, since there's no way -# to pass config options to extconf.rb file MAKEFILE => EXT_CONF do |t| Dir::chdir(File::dirname(EXT_CONF)) do - unless sh "ruby #{File::basename(EXT_CONF)}" - $stderr.puts "Failed to run extconf" - break - end + extra = "" + args = ARGV.grep(/^--with-libvirt-include=/) + extra += args[0].chomp unless args.empty? + args = ARGV.grep(/^--with-libvirt-lib=/) + extra += " " + args[0].chomp unless args.empty? + + unless sh "ruby #{File::basename(EXT_CONF)} #{extra}" + $stderr.puts "Failed to run extconf" + break + end end end -file LIBVIRT_MODULE => [ MAKEFILE, LIBVIRT_SRC ] do |t| +file LIBVIRT_MODULE => LIBVIRT_SRC do |t| Dir::chdir(File::dirname(EXT_CONF)) do - unless sh "make" - $stderr.puts "make failed" - break - end + unless sh "make" + $stderr.puts "make failed" + break + end end end desc "Build the native library" task :build => LIBVIRT_MODULE +# +# Test task +# + Rake::TestTask.new(:test) do |t| - t.test_files = FileList['tests/tc_*.rb'] + t.test_files = [ 'tests/test_conn.rb', 'tests/test_domain.rb', + 'tests/test_interface.rb', 'tests/test_network.rb', + 'tests/test_nodedevice.rb', 'tests/test_nwfilter.rb', + 'tests/test_open.rb', 'tests/test_secret.rb', + 'tests/test_storage.rb' ] t.libs = [ 'lib', 'ext/libvirt' ] end task :test => :build +# +# Documentation tasks +# + +RDOC_FILES = FileList[ "README.rdoc", "lib/libvirt.rb", + "ext/libvirt/_libvirt.c", "ext/libvirt/connect.c", + "ext/libvirt/domain.c", "ext/libvirt/interface.c", + "ext/libvirt/network.c", "ext/libvirt/nodedevice.c", + "ext/libvirt/nwfilter.c", "ext/libvirt/secret.c", + "ext/libvirt/storage.c", "ext/libvirt/stream.c" ] + Rake::RDocTask.new do |rd| rd.main = "README.rdoc" rd.rdoc_dir = "doc/site/api" - rd.rdoc_files.include("README.rdoc", "lib/**/*.rb", "ext/**/*.[ch]") + rd.rdoc_files.include(RDOC_FILES) +end + +Rake::RDocTask.new(:ri) do |rd| + rd.main = "README.rdoc" + rd.rdoc_dir = "doc/ri" + rd.options << "--ri-system" + rd.rdoc_files.include(RDOC_FILES) +end + +# +# Splint task +# + +task :splint => [ MAKEFILE ] do |t| + Dir::chdir(File::dirname(EXT_CONF)) do + unless sh "splint -I" + Config::CONFIG['vendorarchdir'] + " *.c" + $stderr.puts "Failed to run splint" + break + end + end end # # Package tasks # -PKG_FILES = FileList[ - "Rakefile", "COPYING", "README", "NEWS", "README.rdoc", - "lib/**/*.rb", - "ext/**/*.[ch]", "ext/**/MANIFEST", "ext/**/extconf.rb", - "tests/**/*", - "spec/**/*" -] - -DIST_FILES = FileList[ - "pkg/*.src.rpm", "pkg/*.gem", "pkg/*.zip", "pkg/*.tgz" -] +PKG_FILES = FileList[ "Rakefile", "COPYING", "README", "NEWS", "README.rdoc", + "lib/**/*.rb", + "ext/**/*.[ch]", "ext/**/MANIFEST", "ext/**/extconf.rb", + "tests/**/*", + "spec/**/*" ] + +DIST_FILES = FileList[ "pkg/*.src.rpm", "pkg/*.gem", "pkg/*.zip", + "pkg/*.tgz" ] SPEC = Gem::Specification.new do |s| s.name = PKG_NAME @@ -93,12 +134,11 @@ s.homepage = "http://libvirt.org/ruby/" s.summary = "Ruby bindings for LIBVIRT" s.files = PKG_FILES - s.autorequire = "libvirt" s.required_ruby_version = '>= 1.8.1' s.extensions = "ext/libvirt/extconf.rb" - s.description = < [ :rdoc ] do |t| - system("rsync -av doc/site/ libvirt:/data/www/libvirt.org/ruby/") - if $? != 0 - raise "rsync failed: #{$?}" - end -end - desc "Build (S)RPM for #{PKG_NAME}" task :rpm => [ :package ] do |t| system("sed -e 's/@VERSION@/#{PKG_VERSION}/' #{SPEC_FILE} > pkg/#{SPEC_FILE}") @@ -125,15 +157,3 @@ end end end - -desc "Release a version to the site" -task :dist => [ :rpm ] do |t| - puts "Copying files" - unless sh "scp -p #{DIST_FILES.to_s} libvirt:/data/www/libvirt.org/ruby/download" - $stderr.puts "Copy to libvirt failed" - break - end - puts "Commit and tag #{PKG_VERSION}" - system "hg commit -m 'Released version #{PKG_VERSION}'" - system "hg tag -m 'Tag release #{PKG_VERSION}' #{PKG_NAME}-#{PKG_VERSION}" -end diff -Nru ruby-libvirt-0.0.7/README ruby-libvirt-0.4.0/README --- ruby-libvirt-0.0.7/README 2007-11-19 20:43:52.000000000 +0000 +++ ruby-libvirt-0.4.0/README 2011-07-29 16:19:09.000000000 +0000 @@ -7,7 +7,7 @@ ----- In your ruby code, do a "require 'libvirt'"; to obtain a connection, use -'Libvirt::open' or 'Libvirt::openReadOnly'. See tests/*.rb for more +'Libvirt::open' or 'Libvirt::open_read_only'. See tests/*.rb for more examples. Hacking @@ -23,4 +23,30 @@ toplevel of your source checkout): export RUBYLIB=$dir/lib:$dir/ext/libvirt - ruby -rlibvirt -e 'puts Libvirt::version("xen")[0]' + ruby -rlibvirt -e 'puts Libvirt::version[0]' + +Notes +----- +As of June 24, 2011, the ruby-libvirt bindings support all of the libvirt +APIs up to libvirt commit hash 2c5ded6e8269463d2daab3dfa0ecae1477730ee2 +with the following exceptions: + +- virConnectRef +- virDomainGetConnect +- virDomainRef +- virDomainOpenConsole +- virNetworkGetConnect +- virNetworkRef +- virInterfaceGetConnect +- virInterfaceRef +- virStoragePoolGetConnect +- virStoragePoolRef +- virStorageVolGetConnect +- virStorageVolRef +- virNodeDeviceRef +- virSecretGetConnect +- virSecretRef +- virStreamRef +- virNWFilterRef +- virEventRegisterDefaultImpl +- virEventRunDefaultImpl diff -Nru ruby-libvirt-0.0.7/README.rdoc ruby-libvirt-0.4.0/README.rdoc --- ruby-libvirt-0.0.7/README.rdoc 2007-11-12 22:19:29.000000000 +0000 +++ ruby-libvirt-0.4.0/README.rdoc 2011-07-29 16:19:09.000000000 +0000 @@ -2,10 +2,27 @@ The module Libvirt provides bindings to libvirt[http://libvirt.org] -The various +*Ptr+ types in Libvirt map loosely to the following Ruby classes: +The various *Ptr types in Libvirt map loosely to the following Ruby classes: [virConnectPtr] Libvirt::Connect +[virNodeInfoPtr] Libvirt::Connect::Nodeinfo +[virSecurityModelPtr] Libvirt::Connect::NodeSecurityModel [virDomainPtr] Libvirt::Domain [virDomainInfoPtr] Libvirt::Domain::Info +[virDomainInterfaceStatsPtr] Libvirt::Domain::InterfaceInfo +[virSecurityLabelPtr] Libvirt::Domain::SecurityLabel +[virDomainBlockStatsPtr] Libvirt::Domain::BlockStats +[virDomainMemoryStatPtr] Libvirt::Domain::MemoryStats +[virDomainBlockInfoPtr] Libvirt::Domain::BlockInfo +[virDomainSnapshotPtr] Libvirt::Domain::Snapshot +[virDomainJobInfoPtr] Libvirt::Domain::JobInfo [virNetworkPtr] Libvirt::Network - +[virNWFilterPtr] Libvirt::NWFilter +[virNodeDevicePtr] Libvirt::NodeDevice +[virStoragePoolPtr] Libvirt::StoragePool +[virStoragePoolInfoPtr] Libvirt::StoragePoolInfo +[virStorageVolPtr] Libvirt::StorageVol +[virStorageVolInfoPtr] Libvirt::StorageVolInfo +[virSecretPtr] Libvirt::Secret +[virInterfacePtr] Libvirt::Interface +[virStreamPtr] Libvirt::Stream diff -Nru ruby-libvirt-0.0.7/ruby-libvirt.spec ruby-libvirt-0.4.0/ruby-libvirt.spec --- ruby-libvirt-0.0.7/ruby-libvirt.spec 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/ruby-libvirt.spec 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,91 @@ +%{!?ruby_sitelib: %define ruby_sitelib %(ruby -rrbconfig -e "puts Config::CONFIG['sitelibdir']")} +%{!?ruby_sitearch: %define ruby_sitearch %(ruby -rrbconfig -e "puts Config::CONFIG['sitearchdir']")} + +Name: ruby-libvirt +Version: @VERSION@ +Release: 1%{?dist}%{?extra_release} +Summary: Ruby bindings for libvirt +Group: Development/Languages + +License: LGPLv2+ +URL: http://libvirt.org/ruby/ +Source0: http://libvirt.org/ruby/download/ruby-libvirt-@VERSION@.tgz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + +BuildRequires: ruby ruby-devel rubygem(rake) +BuildRequires: libvirt-devel >= 0.4.0 +Requires: ruby(abi) = 1.8 +Provides: ruby(libvirt) = %{version} + +%description +Ruby bindings for libvirt. + +%prep +%setup -q + + +%build +export CFLAGS="$RPM_OPT_FLAGS" +rake build + +%install +rm -rf %{buildroot} +install -d -m0755 %{buildroot}%{ruby_sitelib} +install -d -m0755 %{buildroot}%{ruby_sitearch} +install -p -m0644 lib/libvirt.rb %{buildroot}%{ruby_sitelib} +install -p -m0755 ext/libvirt/_libvirt.so %{buildroot}%{ruby_sitearch} + +%clean +rm -rf $RPM_BUILD_ROOT + + +%files +%defattr(-,root,root,-) +%doc COPYING NEWS README +%{ruby_sitelib}/libvirt.rb +%{ruby_sitearch}/_libvirt.so + + +%changelog +* Sun Dec 12 2010 Chris Lalancette - 0.3.0-1 +- Updated bindings to implement most libvirt methods up to 0.8.6 +- Updated rdoc documentation +- Bumped package version to 0.3.0 + +* Fri Jun 25 2010 Chris Lalancette - 0.2.0-1 +- Updated bindings to have many of the new libvirt methods implemented +- Bumped package version to 0.2.0 + +* Tue Nov 18 2008 David Lutterkort - 0.1.0-1 +- Remove no-capabilities-test.patch, since it's upstream now + +* Tue Apr 15 2008 David Lutterkort - 0.0.7-2 +- Added no-capabilities-test.patch to suppress a fragile test + +* Tue Apr 15 2008 David Lutterkort - 0.0.7-1 +- New version + +* Wed Apr 2 2008 David Lutterkort - 0.0.6-1 +- New version + +* Wed Apr 2 2008 David Lutterkort - 0.0.5-1 +- Remove explicit xen-devel dependency + +* Tue Apr 1 2008 David Lutterkort - 0.0.4-1 +- New version + +* Thu Mar 6 2008 David Lutterkort - 0.0.3-1 +- Updated for libvirt 0.4.1 + +* Wed Jan 2 2008 David Lutterkort - 0.0.2-3 +- Make _libvirt.so strippable by changing permissions to +x + +* Wed Dec 19 2007 David Lutterkort - 0.0.2-2 +- Replace use of RPM_BUILD_ROOT by buildroot macro +- Fix URL + +* Thu Dec 6 2007 David Lutterkort - 0.0.2-1 +- New version + +* Mon Nov 19 2007 David Lutterkort - 0.0.1-1 +- Initial specfile diff -Nru ruby-libvirt-0.0.7/tests/tc_connect.rb ruby-libvirt-0.4.0/tests/tc_connect.rb --- ruby-libvirt-0.0.7/tests/tc_connect.rb 2008-04-14 20:09:48.000000000 +0000 +++ ruby-libvirt-0.4.0/tests/tc_connect.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,164 +0,0 @@ -require 'test/unit' - -$:.unshift(File::join(File::dirname(__FILE__), "..", "lib")) -$:.unshift(File::join(File::dirname(__FILE__), "..", "ext", "libvirt")) -require 'libvirt' - -class TestConnect < Test::Unit::TestCase - - LIBVIRT_VERSION = Libvirt::version("Test")[0] - - TEST_CAPS_OLD = "\n \n \n i686\n \n \n \n \n \n \n\n \n linux\n \n 32\n \n \n \n \n \n \n \n\n" - - TEST_CAPS_0_40_1 = "\n\n \n \n i686\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n linux\n \n 32\n \n \n \n \n \n \n \n \n\n\n" - - if LIBVIRT_VERSION.major >= 0 && - LIBVIRT_VERSION.minor >= 4 && - LIBVIRT_VERSION.release >= 1 - TEST_CAPS = TEST_CAPS_0_40_1 - else - TEST_CAPS = TEST_CAPS_OLD - end - - UUID = "004b96e1-2d78-c30f-5aa5-f03c87d21e69" - - NETWORK_XML = " - local - 9b562b27-0969-4b39-8c96-ef7858152ccc - - - - - - - - -" - - def connect_default - c = Libvirt::open("test:///default") - assert_not_nil(c) - assert(! c.closed?) - return c - end - - def test_open - c = connect_default - assert_nothing_raised { - c.close - } - assert(c.closed?) - assert_nothing_raised { - c.close - } - assert(c.closed?) - end - - def test_node_info - ni = connect_default.node_get_info - assert_equal(2, ni.nodes) - assert_equal(16, ni.cpus) - assert_equal(2, ni.threads) - assert_equal(2, ni.sockets) - assert_equal(1400, ni.mhz) - assert_equal(2, ni.cores) - assert_equal("i686", ni.model) - end - - def test_misc - c = connect_default - assert_equal("Test", c.type) - assert_equal(2, c.version) - hostname=`hostname`.chomp - assert_equal(hostname, c.hostname) - assert_equal("test:///default", c.uri) - assert_equal(32, c.max_vcpus("bogus")) - assert_equal(TEST_CAPS, c.capabilities) - assert_equal(1, c.num_of_domains) - assert_equal([1], c.list_domains) - assert_equal(0, c.num_of_defined_domains) - assert_equal([], c.list_defined_domains) - assert_equal(1, c.num_of_networks) - assert_equal(["default"], c.list_networks) - assert_equal(0, c.num_of_defined_networks) - assert_equal([], c.list_defined_networks) - - v = Libvirt::version("Test") - assert_equal("libvirt", v[0].type) - assert_equal("Test", v[1].type) - end - - def test_domain - c = connect_default; - - dom = c.lookup_domain_by_id(1) - assert_equal("test", dom.name) - assert_equal("linux", dom.os_type) - assert_equal(UUID, dom.uuid) - assert_equal(UUID, c.lookup_domain_by_uuid(UUID).uuid) - assert_equal(UUID, c.lookup_domain_by_name("test").uuid) - - info = dom.info - assert_equal(8388608, info.max_mem) - assert_equal(2097152, info.memory) - assert_equal(2, info.nr_virt_cpu) - assert_equal(Libvirt::Domain::RUNNING, info.state) - - dom.memory = info.memory/2 - dom.vcpus = 1 - info = dom.info - assert_equal(2097152/2, info.memory) - assert_equal(1, info.nr_virt_cpu) - - # pin_vcpu is not implemented in the test driver - # enable this once it becomes available - # dom.pin_vcpu(0,[0]) - - dom.free() - assert_raise ArgumentError do - dom.name - end - end - - def test_error - c = connect_default; - raised = false; - begin - c.lookup_domain_by_id(42) - rescue Libvirt::RetrieveError => e - raised = true - assert(e.message.size > 0) - assert_equal("virDomainLookupByID", e.libvirt_function_name) - assert_not_nil e.libvirt_message - end - assert(raised) - end - - def test_network - c = connect_default; - - netw = c.lookup_network_by_name("default") - assert_equal("default", netw.name) - assert_equal("default", netw.bridge_name) - assert_equal(UUID, netw.uuid) - assert_equal(UUID, c.lookup_network_by_uuid(UUID).uuid) - assert_equal(UUID, c.lookup_network_by_name("default").uuid) - assert_equal(false, netw.autostart) - netw.autostart = true - assert_equal(true, netw.autostart) - netw.autostart = false - assert_equal(false, netw.autostart) - - netw = c.define_network_xml(NETWORK_XML) - assert_equal(NETWORK_XML, netw.xml_desc(nil)) - assert_equal(c, netw.connection) - - assert_equal(2, c.num_of_networks) - assert_equal(["default", "local"], c.list_networks) - - netw.free - assert_raise ArgumentError do - netw.name - end - end -end diff -Nru ruby-libvirt-0.0.7/tests/test_conn.rb ruby-libvirt-0.4.0/tests/test_conn.rb --- ruby-libvirt-0.0.7/tests/test_conn.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/tests/test_conn.rb 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,673 @@ +#!/usr/bin/ruby + +# Test the conn methods the bindings support + +$: << File.dirname(__FILE__) + +require 'libvirt' +require 'test_utils.rb' + +# test setup +begin + `rm -f /etc/sysconfig/network-scripts/ifcfg-ruby-libvirt-tester` + `brctl delbr ruby-libvirt-tester >& /dev/null` +rescue +end +`rm -f #{$GUEST_DISK} ; qemu-img create -f qcow2 #{$GUEST_DISK} 5G` +`rm -f /var/lib/libvirt/images/ruby-libvirt-test.save` +`rm -rf #{$POOL_PATH}; mkdir #{$POOL_PATH} ; echo $?` + +conn = Libvirt::open("qemu:///system") + +cpu_xml = < + x86_64 + athlon + +EOF + +# TESTGROUP: conn.close +conn2 = Libvirt::open("qemu:///system") +expect_too_many_args(conn2, "close", 1) +expect_success(conn2, "no args", "close") + +# TESTGROUP: conn.closed? +conn2 = Libvirt::open("qemu:///system") + +expect_too_many_args(conn2, "closed?", 1) +expect_success(conn2, "no args", "closed?") {|x| x == false } +conn2.close +expect_success(conn2, "no args", "closed?") {|x| x == true } + +# TESTGROUP: conn.type +expect_too_many_args(conn, "type", 1) + +expect_success(conn, "no args", "type") {|x| x == "QEMU"} + +# TESTGROUP: conn.version +expect_too_many_args(conn, "version", 1) + +expect_success(conn, "no args", "version") + +# TESTGROUP: conn.libversion +expect_too_many_args(conn, "libversion", 1) + +expect_success(conn, "no args", "libversion") + +# TESTGROUP: conn.hostname +expect_too_many_args(conn, "hostname", 1) + +expect_success(conn, "no args", "hostname") + +# TESTGROUP: conn.uri +expect_too_many_args(conn, "uri", 1) + +expect_success(conn, "no args", "uri") {|x| x == "qemu:///system" } + +# TESTGROUP: conn.max_vcpus +expect_too_many_args(conn, "max_vcpus", 'kvm', 1) +expect_fail(conn, Libvirt::RetrieveError, "invalid arg", "max_vcpus", "foo") + +expect_success(conn, "no args", "max_vcpus") +expect_success(conn, "nil arg", "max_vcpus") +expect_success(conn, "kvm arg", "max_vcpus") +expect_success(conn, "qemu arg", "max_vcpus") + +# TESTGROUP: conn.node_get_info +expect_too_many_args(conn, "node_get_info", 1) + +expect_success(conn, "no args", "node_get_info") + +begin + # TESTGROUP: conn.node_free_memory + expect_too_many_args(conn, "node_free_memory", 1) + + conn.node_free_memory + puts_ok "conn.node_free_memory no args" +rescue Libvirt::RetrieveError + puts_skipped "conn.node_free_memory not supported on this host" +rescue NoMethodError + puts_skipped "conn.node_free_memory does not exist" +end + +begin + # TESTGROUP: conn.node_cells_free_memory + expect_too_many_args(conn, "node_cells_free_memory", 1, 2, 3) + expect_invalid_arg_type(conn, "node_cells_free_memory", 'start') + expect_invalid_arg_type(conn, "node_cells_free_memory", 0, 'end') + + cell_mem = conn.node_cells_free_memory + puts_ok "conn.node_cells_free_memory no args = " + cell_mem = conn.node_cells_free_memory(0) + puts_ok "conn.node_cells_free_memory(0) = " + cell_mem = conn.node_cells_free_memory(0, 1) + puts_ok "conn.node_cells_free_memory(0, 1) = " +rescue Libvirt::RetrieveError + puts_skipped "conn.node_cells_free_memory not supported on this host" +rescue NoMethodError + puts_skipped "conn.node_cells_free_memory does not exist" +end + +# TESTGROUP: conn.node_get_security_model +expect_too_many_args(conn, "node_get_security_model", 1) +expect_success(conn, "no args", "node_get_security_model") + +# TESTGROUP: conn.encrypted? +expect_too_many_args(conn, "encrypted?", 1) +expect_success(conn, "no args", "encrypted?") + +# TESTGROUP: conn.secure? +expect_too_many_args(conn, "secure?", 1) +expect_success(conn, "no args", "secure?") {|x| x == true} + +# TESTGROUP: conn.capabilities +expect_too_many_args(conn, "capabilities", 1) +expect_success(conn, "no args", "capabilities") + +# TESTGROUP: conn.compare_cpu +expect_too_many_args(conn, "compare_cpu", 1, 2, 3) +expect_too_few_args(conn, "compare_cpu") +expect_invalid_arg_type(conn, "compare_cpu", 1) +expect_invalid_arg_type(conn, "compare_cpu", "hello", 'bar') +expect_fail(conn, Libvirt::RetrieveError, "invalid XML", "compare_cpu", "hello") +expect_success(conn, "CPU XML", "compare_cpu", cpu_xml) + +# TESTGROUP: conn.baseline_cpu +expect_too_many_args(conn, "baseline_cpu", 1, 2, 3) +expect_too_few_args(conn, "baseline_cpu") +expect_invalid_arg_type(conn, "baseline_cpu", 1) +expect_invalid_arg_type(conn, "baseline_cpu", [], "foo") +expect_fail(conn, ArgumentError, "empty array", "baseline_cpu", []) +expect_success(conn, "CPU XML", "baseline_cpu", [cpu_xml]) + +# TESTGROUP: conn.domain_event_register_any +dom_event_callback_proc = lambda {|conn, dom, event, detail, opaque| +} + +def dom_event_callback_symbol(conn, dom, event, detail, opaque) +end + +expect_too_many_args(conn, "domain_event_register_any", 1, 2, 3, 4, 5) +expect_too_few_args(conn, "domain_event_register_any") +expect_too_few_args(conn, "domain_event_register_any", 1) +expect_invalid_arg_type(conn, "domain_event_register_any", "hello", 1) +expect_invalid_arg_type(conn, "domain_event_register_any", Libvirt::Connect::DOMAIN_EVENT_ID_LIFECYCLE, 1) +expect_invalid_arg_type(conn, "domain_event_register_any", Libvirt::Connect::DOMAIN_EVENT_ID_LIFECYCLE, dom_event_callback_proc, 1) +expect_fail(conn, ArgumentError, "invalid event ID", "domain_event_register_any", 456789, dom_event_callback_proc) + +callbackID = expect_success(conn, "eventID and proc", "domain_event_register_any", Libvirt::Connect::DOMAIN_EVENT_ID_LIFECYCLE, dom_event_callback_proc) +conn.domain_event_deregister_any(callbackID) + +callbackID = expect_success(conn, "eventID and symbol", "domain_event_register_any", Libvirt::Connect::DOMAIN_EVENT_ID_LIFECYCLE, :dom_event_callback_symbol) +conn.domain_event_deregister_any(callbackID) + +callbackID = expect_success(conn, "eventID, proc, nil domain", "domain_event_register_any", Libvirt::Connect::DOMAIN_EVENT_ID_LIFECYCLE, dom_event_callback_proc, nil) +conn.domain_event_deregister_any(callbackID) + +callbackID = expect_success(conn, "eventID, proc, nil domain, opaque", "domain_event_register_any", Libvirt::Connect::DOMAIN_EVENT_ID_LIFECYCLE, dom_event_callback_proc, nil, "opaque user data") +conn.domain_event_deregister_any(callbackID) + +# TESTGROUP: conn.domain_event_deregister_any +dom_event_callback_proc = lambda {|conn, dom, event, detail, opaque| +} + +callbackID = conn.domain_event_register_any(Libvirt::Connect::DOMAIN_EVENT_ID_LIFECYCLE, dom_event_callback_proc) + +expect_too_many_args(conn, "domain_event_deregister_any", 1, 2) +expect_too_few_args(conn, "domain_event_deregister_any") +expect_invalid_arg_type(conn, "domain_event_deregister_any", "hello") + +expect_success(conn, "callbackID", "domain_event_deregister_any", callbackID) + +# TESTGROUP: conn.domain_event_register +dom_event_callback_proc = lambda {|conn, dom, event, detail, opaque| +} + +def dom_event_callback_symbol(conn, dom, event, detail, opaque) +end + +expect_too_many_args(conn, "domain_event_register", 1, 2, 3) +expect_too_few_args(conn, "domain_event_register") +expect_invalid_arg_type(conn, "domain_event_register", "hello") + +expect_success(conn, "proc", "domain_event_register", dom_event_callback_proc) +conn.domain_event_deregister + +expect_success(conn, "symbol", "domain_event_register", :dom_event_callback_symbol) +conn.domain_event_deregister + +expect_success(conn, "proc and opaque", "domain_event_register", dom_event_callback_proc, "opaque user data") +conn.domain_event_deregister + +# TESTGROUP: conn.domain_event_deregister +dom_event_callback_proc = lambda {|conn, dom, event, detail, opaque| +} + +conn.domain_event_register(dom_event_callback_proc) + +expect_too_many_args(conn, "domain_event_deregister", 1) +expect_success(conn, "no args", "domain_event_deregister") + +# TESTGROUP: conn.num_of_domains +expect_too_many_args(conn, "num_of_domains", 1) +expect_success(conn, "no args", "num_of_domains") + +# TESTGROUP: conn.list_domains +expect_too_many_args(conn, "list_domains", 1) +expect_success(conn, "no args", "list_domains") + +# TESTGROUP: conn.num_of_defined_domains +expect_too_many_args(conn, "num_of_defined_domains", 1) +expect_success(conn, "no args", "num_of_defined_domains") + +# TESTGROUP: conn.list_defined_domains +expect_too_many_args(conn, "list_defined_domains", 1) +expect_success(conn, "no args", "list_defined_domains") + +# TESTGROUP: conn.create_domain_linux +expect_too_many_args(conn, "create_domain_linux", $new_dom_xml, 0, 1) +expect_too_few_args(conn, "create_domain_linux") +expect_invalid_arg_type(conn, "create_domain_linux", nil) +expect_invalid_arg_type(conn, "create_domain_linux", 1) +expect_invalid_arg_type(conn, "create_domain_linux", $new_dom_xml, "foo") +expect_fail(conn, Libvirt::Error, "invalid xml", "create_domain_linux", "hello") +newdom = expect_success(conn, "domain xml", "create_domain_linux", $new_dom_xml) {|x| x.class == Libvirt::Domain} +sleep 1 + +expect_fail(conn, Libvirt::Error, "already existing domain", "create_domain_linux", $new_dom_xml) + +newdom.destroy + +# TESTGROUP: conn.create_domain_xml +expect_too_many_args(conn, "create_domain_xml", $new_dom_xml, 0, 1) +expect_too_few_args(conn, "create_domain_xml") +expect_invalid_arg_type(conn, "create_domain_xml", nil) +expect_invalid_arg_type(conn, "create_domain_xml", 1) +expect_invalid_arg_type(conn, "create_domain_xml", $new_dom_xml, "foo") +expect_fail(conn, Libvirt::Error, "invalid xml", "create_domain_xml", "hello") +newdom = expect_success(conn, "domain xml", "create_domain_xml", $new_dom_xml) {|x| x.class == Libvirt::Domain} +sleep 1 + +expect_fail(conn, Libvirt::Error, "already existing domain", "create_domain_xml", $new_dom_xml) + +newdom.destroy + +# TESTGROUP: conn.lookup_domain_by_name +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(conn, "lookup_domain_by_name", 1, 2) +expect_too_few_args(conn, "lookup_domain_by_name") +expect_invalid_arg_type(conn, "lookup_domain_by_name", 1) +expect_fail(conn, Libvirt::RetrieveError, "non-existent name arg", "lookup_domain_by_name", "foobarbazsucker") + +expect_success(conn, "name arg for running domain", "lookup_domain_by_name", "ruby-libvirt-tester") {|x| x.name == "ruby-libvirt-tester"} +newdom.destroy + +newdom = conn.define_domain_xml($new_dom_xml) +expect_success(conn, "name arg for defined domain", "lookup_domain_by_name", "ruby-libvirt-tester") {|x| x.name == "ruby-libvirt-tester"} +newdom.undefine + +# TESTGROUP: conn.lookup_domain_by_id +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(conn, "lookup_domain_by_id", 1, 2) +expect_too_few_args(conn, "lookup_domain_by_id") +expect_invalid_arg_type(conn, "lookup_domain_by_id", "foo") +expect_fail(conn, Libvirt::Error, "with negative value", "lookup_domain_by_id", -1) + +expect_success(conn, "id arg for running domain", "lookup_domain_by_id", newdom.id) +newdom.destroy + +# TESTGROUP: conn.lookup_domain_by_uuid +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(conn, "lookup_domain_by_uuid", 1, 2) +expect_too_few_args(conn, "lookup_domain_by_uuid") +expect_invalid_arg_type(conn, "lookup_domain_by_uuid", 1) +expect_fail(conn, Libvirt::RetrieveError, "invalid UUID", "lookup_domain_by_uuid", "abcd") + +expect_success(conn, "UUID arg for running domain", "lookup_domain_by_uuid", newdom.uuid) {|x| x.uuid == $GUEST_UUID} +newdom.destroy + +newdom = conn.define_domain_xml($new_dom_xml) +expect_success(conn, "UUID arg for defined domain", "lookup_domain_by_uuid", newdom.uuid) {|x| x.uuid == $GUEST_UUID} +newdom.undefine + +# TESTGROUP: conn.define_domain_xml +expect_too_many_args(conn, "define_domain_xml", 1, 2) +expect_too_few_args(conn, "define_domain_xml") +expect_invalid_arg_type(conn, "define_domain_xml", 1) +expect_invalid_arg_type(conn, "define_domain_xml", nil) +expect_fail(conn, Libvirt::DefinitionError, "invalid XML", "define_domain_xml", "hello") + +newdom = expect_success(conn, "domain xml arg", "define_domain_xml", $new_dom_xml) +newdom.undefine + +# TESTGROUP: conn.domain_xml_from_native +expect_too_many_args(conn, "domain_xml_from_native", 1, 2, 3, 4) +expect_too_few_args(conn, "domain_xml_from_native") +expect_too_few_args(conn, "domain_xml_from_native", 1) +expect_invalid_arg_type(conn, "domain_xml_from_native", 1, 2) +expect_invalid_arg_type(conn, "domain_xml_from_native", nil, 2) +expect_invalid_arg_type(conn, "domain_xml_from_native", "qemu-argv", 2) +expect_invalid_arg_type(conn, "domain_xml_from_native", "qemu-argv", nil) +expect_invalid_arg_type(conn, "domain_xml_from_native", "qemu-argv", "foo", "bar") +expect_fail(conn, Libvirt::Error, "unsupported first arg", "domain_xml_from_native", "foo", "bar") + +expect_success(conn, "qemu-argv and qemu_cmd_line", "domain_xml_from_native", "qemu-argv", $qemu_cmd_line) + +# TESTGROUP: conn.domain_xml_to_native +expect_too_many_args(conn, "domain_xml_to_native", 1, 2, 3, 4) +expect_too_few_args(conn, "domain_xml_to_native") +expect_too_few_args(conn, "domain_xml_to_native", 1) +expect_invalid_arg_type(conn, "domain_xml_to_native", 1, 2) +expect_invalid_arg_type(conn, "domain_xml_to_native", nil, 2) +expect_invalid_arg_type(conn, "domain_xml_to_native", "qemu-argv", 2) +expect_invalid_arg_type(conn, "domain_xml_to_native", "qemu-argv", nil) +expect_invalid_arg_type(conn, "domain_xml_to_native", "qemu-argv", "foo", "bar") +expect_fail(conn, Libvirt::Error, "unsupported first arg", "domain_xml_to_native", "foo", "bar") + +expect_success(conn, "qemu-argv and domain XML", "domain_xml_to_native", "qemu-argv", $new_dom_xml) + +# TESTGROUP: conn.num_of_interfaces +expect_too_many_args(conn, "num_of_interfaces", 1) +expect_success(conn, "no args", "num_of_interfaces") + +# TESTGROUP: conn.list_interfaces +expect_too_many_args(conn, "list_interfaces", 1) +expect_success(conn, "no args", "list_interfaces") + +# TESTGROUP: conn.num_of_defined_interfaces +expect_too_many_args(conn, "num_of_defined_interfaces", 1) +expect_success(conn, "no args", "num_of_defined_interfaces") + +# TESTGROUP: conn.list_defined_interfaces +expect_too_many_args(conn, "list_defined_interfaces", 1) +expect_success(conn, "no args", "list_defined_interfaces") + +# TESTGROUP: conn.lookup_interface_by_name +newiface = conn.define_interface_xml($new_interface_xml) + +expect_too_many_args(conn, "lookup_interface_by_name", 1, 2) +expect_too_few_args(conn, "lookup_interface_by_name") +expect_invalid_arg_type(conn, "lookup_interface_by_name", 1) +expect_fail(conn, Libvirt::RetrieveError, "non-existent name arg", "lookup_interface_by_name", "foobarbazsucker") + +expect_success(conn, "name arg", "lookup_interface_by_name", "ruby-libvirt-tester") + +newiface.destroy + +expect_success(conn, "name arg", "lookup_interface_by_name", "ruby-libvirt-tester") + +newiface.undefine + +# TESTGROUP: conn.lookup_interface_by_mac +newiface = conn.define_interface_xml($new_interface_xml) + +expect_too_many_args(conn, "lookup_interface_by_mac", 1, 2) +expect_too_few_args(conn, "lookup_interface_by_mac") +expect_invalid_arg_type(conn, "lookup_interface_by_mac", 1) +expect_fail(conn, Libvirt::RetrieveError, "non-existent mac arg", "lookup_interface_by_mac", "foobarbazsucker") + +testiface = find_valid_iface(conn) +if not testiface.nil? + expect_success(conn, "name arg", "lookup_interface_by_mac", testiface.mac) {|x| x.mac == testiface.mac} +end + +newiface.undefine + +# TESTGROUP: conn.define_interface_xml +expect_too_many_args(conn, "define_interface_xml", 1, 2, 3) +expect_too_few_args(conn, "define_interface_xml") +expect_invalid_arg_type(conn, "define_interface_xml", 1) +expect_invalid_arg_type(conn, "define_interface_xml", nil) +expect_invalid_arg_type(conn, "define_interface_xml", "hello", 'foo') +expect_fail(conn, Libvirt::DefinitionError, "invalid XML", "define_interface_xml", "hello") + +expect_success(conn, "interface XML", "define_interface_xml", $new_interface_xml) +newiface.undefine + +# TESTGROUP: conn.num_of_networks +expect_too_many_args(conn, "num_of_networks", 1) +expect_success(conn, "no args", "num_of_networks") + +# TESTGROUP: conn.list_networks +expect_too_many_args(conn, "list_networks", 1) +expect_success(conn, "no args", "list_networks") + +# TESTGROUP: conn.num_of_defined_networks +expect_too_many_args(conn, "num_of_defined_networks", 1) +expect_success(conn, "no args", "num_of_defined_networks") + +# TESTGROUP: conn.list_defined_networks +expect_too_many_args(conn, "list_defined_networks", 1) +expect_success(conn, "no args", "list_defined_networks") + +# TESTGROUP: conn.lookup_network_by_name +newnet = conn.create_network_xml($new_net_xml) + +expect_too_many_args(conn, "lookup_network_by_name", 1, 2) +expect_too_few_args(conn, "lookup_network_by_name") +expect_invalid_arg_type(conn, "lookup_network_by_name", 1) +expect_fail(conn, Libvirt::RetrieveError, "non-existent name arg", "lookup_network_by_name", "foobarbazsucker") + +expect_success(conn, "name arg", "lookup_network_by_name", "ruby-libvirt-tester") +newnet.destroy + +newnet = conn.define_network_xml($new_net_xml) +expect_success(conn, "name arg", "lookup_network_by_name", "ruby-libvirt-tester") +newnet.undefine + +# TESTGROUP: conn.lookup_network_by_uuid +newnet = conn.create_network_xml($new_net_xml) + +expect_too_many_args(conn, "lookup_network_by_uuid", 1, 2) +expect_too_few_args(conn, "lookup_network_by_uuid") +expect_invalid_arg_type(conn, "lookup_network_by_uuid", 1) +expect_fail(conn, Libvirt::RetrieveError, "non-existent uuid arg", "lookup_network_by_uuid", "foobarbazsucker") + +expect_success(conn, "uuid arg", "lookup_network_by_uuid", $NETWORK_UUID) +newnet.destroy + +newnet = conn.define_network_xml($new_net_xml) +expect_success(conn, "uuid arg", "lookup_network_by_uuid", $NETWORK_UUID) +newnet.undefine + +# TESTGROUP: conn.create_network_xml +expect_too_many_args(conn, "create_network_xml", $new_net_xml, 0) +expect_too_few_args(conn, "create_network_xml") +expect_invalid_arg_type(conn, "create_network_xml", nil) +expect_invalid_arg_type(conn, "create_network_xml", 1) +expect_fail(conn, Libvirt::Error, "invalid xml", "create_network_xml", "hello") + +newnet = expect_success(conn, "network XML", "create_network_xml", $new_net_xml) + +expect_fail(conn, Libvirt::Error, "already existing network", "create_network_xml", $new_net_xml) + +newnet.destroy + +# TESTGROUP: conn.define_network_xml +expect_too_many_args(conn, "define_network_xml", 1, 2) +expect_too_few_args(conn, "define_network_xml") +expect_invalid_arg_type(conn, "define_network_xml", 1) +expect_invalid_arg_type(conn, "define_network_xml", nil) +expect_fail(conn, Libvirt::DefinitionError, "invalid XML", "define_network_xml", "hello") + +newnet = expect_success(conn, "network XML", "define_network_xml", $new_net_xml) +newnet.undefine + +# TESTGROUP: conn.num_of_nodedevices +expect_too_many_args(conn, "num_of_nodedevices", 1, 2, 3) +expect_invalid_arg_type(conn, "num_of_nodedevices", 1) +expect_invalid_arg_type(conn, "num_of_nodedevices", 'foo', 'bar') +expect_success(conn, "no args", "num_of_nodedevices") + +# TESTGROUP: conn.list_nodedevices +expect_too_many_args(conn, "list_nodedevices", 1, 2, 3) +expect_invalid_arg_type(conn, "list_nodedevices", 1) +expect_invalid_arg_type(conn, "list_nodedevices", 'foo', 'bar') +expect_success(conn, "no args", "list_nodedevices") + +# TESTGROUP: conn.lookup_nodedevice_by_name +testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0]) + +expect_too_many_args(conn, "lookup_nodedevice_by_name", 1, 2) +expect_too_few_args(conn, "lookup_nodedevice_by_name") +expect_invalid_arg_type(conn, "lookup_nodedevice_by_name", 1) +expect_fail(conn, Libvirt::RetrieveError, "non-existent name arg", "lookup_nodedevice_by_name", "foobarbazsucker") + +expect_success(conn, "name arg", "lookup_nodedevice_by_name", testnode.name) + +# TESTGROUP: conn.create_nodedevice_xml +expect_too_many_args(conn, "create_nodedevice_xml", 1, 2, 3) +expect_too_few_args(conn, "create_nodedevice_xml") +expect_invalid_arg_type(conn, "create_nodedevice_xml", 1) +expect_invalid_arg_type(conn, "create_nodedevice_xml", "foo", 'bar') +expect_fail(conn, Libvirt::Error, "invalid XML", "create_nodedevice_xml", "hello") + +#expect_success(conn, "nodedevice XML", "create_nodedevice_xml", "") + +# TESTGROUP: conn.num_of_nwfilters +expect_too_many_args(conn, "num_of_nwfilters", 1) +expect_success(conn, "no args", "num_of_nwfilters") + +# TESTGROUP: conn.list_nwfilters +expect_too_many_args(conn, "list_nwfilters", 1) +expect_success(conn, "no args", "list_nwfilters") + +# TESTGROUP: conn.lookup_nwfilter_by_name +newnw = conn.define_nwfilter_xml($new_nwfilter_xml) + +expect_too_many_args(conn, "lookup_nwfilter_by_name", 1, 2) +expect_too_few_args(conn, "lookup_nwfilter_by_name") +expect_invalid_arg_type(conn, "lookup_nwfilter_by_name", 1) + +expect_success(conn, "name arg", "lookup_nwfilter_by_name", "ruby-libvirt-tester") + +newnw.undefine + +# TESTGROUP: conn.lookup_nwfilter_by_uuid +newnw = conn.define_nwfilter_xml($new_nwfilter_xml) + +expect_too_many_args(conn, "lookup_nwfilter_by_uuid", 1, 2) +expect_too_few_args(conn, "lookup_nwfilter_by_uuid") +expect_invalid_arg_type(conn, "lookup_nwfilter_by_uuid", 1) + +expect_success(conn, "uuid arg", "lookup_nwfilter_by_uuid", $NWFILTER_UUID) {|x| x.uuid == $NWFILTER_UUID} + +newnw.undefine + +# TESTGROUP: conn.define_nwfilter_xml +expect_too_many_args(conn, "define_nwfilter_xml", 1, 2) +expect_too_few_args(conn, "define_nwfilter_xml") +expect_invalid_arg_type(conn, "define_nwfilter_xml", 1) +expect_invalid_arg_type(conn, "define_nwfilter_xml", nil) +expect_fail(conn, Libvirt::DefinitionError, "invalid XML", "define_nwfilter_xml", "hello") + +newnw = expect_success(conn, "nwfilter XML", "define_nwfilter_xml", $new_nwfilter_xml) + +newnw.undefine + +# TESTGROUP: conn.num_of_secrets +expect_too_many_args(conn, "num_of_secrets", 1) +expect_success(conn, "no args", "num_of_secrets") + +# TESTGROUP: conn.list_secrets +expect_too_many_args(conn, "list_secrets", 1) +expect_success(conn, "no args", "list_secrets") + +# TESTGROUP: conn.lookup_secret_by_uuid +newsecret = conn.define_secret_xml($new_secret_xml) + +expect_too_many_args(conn, "lookup_secret_by_uuid", 1, 2) +expect_too_few_args(conn, "lookup_secret_by_uuid") +expect_invalid_arg_type(conn, "lookup_secret_by_uuid", 1) + +expect_success(conn, "uuid arg", "lookup_secret_by_uuid", $SECRET_UUID) {|x| x.uuid == $SECRET_UUID} + +newsecret.undefine + +# TESTGROUP: conn.lookup_secret_by_usage +newsecret = conn.define_secret_xml($new_secret_xml) + +expect_too_many_args(conn, "lookup_secret_by_usage", 1, 2, 3) +expect_too_few_args(conn, "lookup_secret_by_usage") +expect_invalid_arg_type(conn, "lookup_secret_by_usage", 'foo', 1) +expect_invalid_arg_type(conn, "lookup_secret_by_usage", 1, 2) +expect_fail(conn, Libvirt::RetrieveError, "invalid secret", "lookup_secret_by_usage", Libvirt::Secret::USAGE_TYPE_VOLUME, "foo") + +expect_success(conn, "usage type and key", "lookup_secret_by_usage", Libvirt::Secret::USAGE_TYPE_VOLUME, "/var/lib/libvirt/images/mail.img") + +newsecret.undefine + +# TESTGROUP: conn.define_secret_xml +expect_too_many_args(conn, "define_secret_xml", 1, 2, 3) +expect_too_few_args(conn, "define_secret_xml") +expect_invalid_arg_type(conn, "define_secret_xml", 1) +expect_invalid_arg_type(conn, "define_secret_xml", nil) +expect_invalid_arg_type(conn, "define_secret_xml", "hello", 'foo') +expect_fail(conn, Libvirt::DefinitionError, "invalid XML", "define_secret_xml", "hello") + +expect_success(conn, "secret XML", "define_secret_xml", $new_secret_xml) + +newsecret.undefine + +# TESTGROUP: conn.list_storage_pools +expect_too_many_args(conn, "list_storage_pools", 1) +expect_success(conn, "no args", "list_storage_pools") + +# TESTGROUP: conn.num_of_storage_pools +expect_too_many_args(conn, "num_of_storage_pools", 1) +expect_success(conn, "no args", "num_of_storage_pools") + +# TESTGROUP: conn.list_defined_storage_pools +expect_too_many_args(conn, "list_defined_storage_pools", 1) +expect_success(conn, "no args", "list_defined_storage_pools") + +# TESTGROUP: conn.num_of_defined_storage_pools +expect_too_many_args(conn, "num_of_defined_storage_pools", 1) +expect_success(conn, "no args", "num_of_defined_storage_pools") + +# TESTGROUP: conn.lookup_storage_pool_by_name +newpool = conn.create_storage_pool_xml($new_storage_pool_xml) + +expect_too_many_args(conn, "lookup_storage_pool_by_name", 1, 2) +expect_too_few_args(conn, "lookup_storage_pool_by_name") +expect_invalid_arg_type(conn, "lookup_storage_pool_by_name", 1) +expect_fail(conn, Libvirt::RetrieveError, "non-existent name arg", "lookup_storage_pool_by_name", "foobarbazsucker") + +expect_success(conn, "name arg", "lookup_storage_pool_by_name", "ruby-libvirt-tester") + +newpool.destroy + +newpool = conn.define_storage_pool_xml($new_storage_pool_xml) +expect_success(conn, "name arg", "lookup_storage_pool_by_name", "ruby-libvirt-tester") +newpool.undefine + +# TESTGROUP: conn.lookup_storage_pool_by_uuid +newpool = conn.create_storage_pool_xml($new_storage_pool_xml) + +expect_too_many_args(conn, "lookup_storage_pool_by_uuid", 1, 2) +expect_too_few_args(conn, "lookup_storage_pool_by_uuid") +expect_invalid_arg_type(conn, "lookup_storage_pool_by_uuid", 1) +expect_fail(conn, Libvirt::RetrieveError, "non-existent uuid arg", "lookup_storage_pool_by_uuid", "foobarbazsucker") + +expect_success(conn, "uuid arg", "lookup_storage_pool_by_uuid", $POOL_UUID) + +newpool.destroy + +newpool = conn.define_storage_pool_xml($new_storage_pool_xml) + +expect_success(conn, "uuid arg", "lookup_storage_pool_by_uuid", $POOL_UUID) + +newpool.undefine + +# TESTGROUP: conn.create_storage_pool_xml +expect_too_many_args(conn, "create_storage_pool_xml", $new_storage_pool_xml, 0, 1) +expect_too_few_args(conn, "create_storage_pool_xml") +expect_invalid_arg_type(conn, "create_storage_pool_xml", nil) +expect_invalid_arg_type(conn, "create_storage_pool_xml", 1) +expect_invalid_arg_type(conn, "create_storage_pool_xml", $new_storage_pool_xml, "foo") +expect_fail(conn, Libvirt::Error, "invalid xml", "create_storage_pool_xml", "hello") + +expect_success(conn, "storage pool XML", "create_storage_pool_xml", $new_storage_pool_xml) + +expect_fail(conn, Libvirt::Error, "already existing domain", "create_storage_pool_xml", $new_storage_pool_xml) + +newpool.destroy + +# TESTGROUP: conn.define_storage_pool_xml +expect_too_many_args(conn, "define_storage_pool_xml", $new_storage_pool_xml, 0, 1) +expect_too_few_args(conn, "define_storage_pool_xml") +expect_invalid_arg_type(conn, "define_storage_pool_xml", nil) +expect_invalid_arg_type(conn, "define_storage_pool_xml", 1) +expect_invalid_arg_type(conn, "define_storage_pool_xml", $new_storage_pool_xml, "foo") +expect_fail(conn, Libvirt::Error, "invalid xml", "define_storage_pool_xml", "hello") + +expect_success(conn, "storage pool XML", "define_storage_pool_xml", $new_storage_pool_xml) + +newpool.undefine + +# TESTGROUP: conn.discover_storage_pool_sources +expect_too_many_args(conn, "discover_storage_pool_sources", 1, 2, 3, 4) +expect_too_few_args(conn, "discover_storage_pool_sources") +expect_invalid_arg_type(conn, "discover_storage_pool_sources", 1) +expect_invalid_arg_type(conn, "discover_storage_pool_sources", "foo", 1) +expect_invalid_arg_type(conn, "discover_storage_pool_sources", "foo", "bar", "baz") + +expect_fail(conn, Libvirt::Error, "invalid pool type", "discover_storage_pool_sources", "foo") + +expect_success(conn, "pool type", "discover_storage_pool_sources", "logical") + +# TESTGROUP: conn.sys_info +expect_too_many_args(conn, "sys_info", 1, 2) +expect_invalid_arg_type(conn, "sys_info", "foo") + +expect_success(conn, "system info", "sys_info") + +conn.close + +finish_tests diff -Nru ruby-libvirt-0.0.7/tests/test_domain.rb ruby-libvirt-0.4.0/tests/test_domain.rb --- ruby-libvirt-0.0.7/tests/test_domain.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-libvirt-0.4.0/tests/test_domain.rb 2011-07-29 16:19:09.000000000 +0000 @@ -0,0 +1,1096 @@ +#!/usr/bin/ruby + +# Test the domain methods the bindings support. Note that this tester requires +# the qemu driver to be enabled and available for use. + +# Note that the order of the TESTGROUPs below match the order that the +# functions are defined in the ext/libvirt/domain.c file + +$: << File.dirname(__FILE__) + +require 'libvirt' +require 'test_utils.rb' + +conn = Libvirt::open("qemu:///system") + +# initial cleanup for previous runs +begin + olddom = conn.lookup_domain_by_name("ruby-libvirt-tester") + olddom.destroy + olddom.undefine +rescue + # in case we didn't find it, don't do anything +end + +# setup for later tests +`rm -f #{$GUEST_DISK} ; qemu-img create -f qcow2 #{$GUEST_DISK} 5G` +`rm -f /var/lib/libvirt/images/ruby-libvirt-test.save` + +new_hostdev_xml = < + +
+ + +EOF + +# start tests + +# TESTGROUP: dom.migrate +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +dconn = Libvirt::open("qemu:///system") + +expect_too_many_args(newdom, "migrate", 1, 2, 3, 4, 5, 6) +expect_too_few_args(newdom, "migrate") +expect_fail(newdom, ArgumentError, "invalid connection object", "migrate", "foo") +expect_invalid_arg_type(newdom, "migrate", dconn, 'foo') +expect_invalid_arg_type(newdom, "migrate", dconn, 0, 1) +expect_invalid_arg_type(newdom, "migrate", dconn, 0, 'foo', 1) +expect_invalid_arg_type(newdom, "migrate", dconn, 0, 'foo', 'bar', 'baz') + +# FIXME: how can we make this work? +#expect_success(newdom, "conn arg", "migrate", dconn) + +dconn.close + +newdom.destroy + +# TESTGROUP: dom.migrate_to_uri +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "migrate_to_uri", 1, 2, 3, 4, 5) +expect_too_few_args(newdom, "migrate_to_uri") +expect_invalid_arg_type(newdom, "migrate_to_uri", 1) +expect_invalid_arg_type(newdom, "migrate_to_uri", "qemu:///system", 'foo') +expect_invalid_arg_type(newdom, "migrate_to_uri", "qemu:///system", 0, 1) +expect_invalid_arg_type(newdom, "migrate_to_uri", "qemu:///system", 0, 'foo', 'bar') + +#expect_success(newdom, "URI arg", "migrate_to_uri", "qemu://remote/system") + +dconn.close + +newdom.destroy + +# TESTGROUP: dom.migrate_set_max_downtime +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "migrate_set_max_downtime", 1, 2, 3) +expect_too_few_args(newdom, "migrate_set_max_downtime") +expect_invalid_arg_type(newdom, "migrate_set_max_downtime", 'foo') +expect_invalid_arg_type(newdom, "migrate_set_max_downtime", 10, 'foo') +expect_fail(newdom, Libvirt::Error, "on off domain", "migrate_set_max_downtime", 10) + +newdom.undefine + +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 +expect_fail(newdom, Libvirt::Error, "while no migration in progress", "migrate_set_max_downtime", 10) + +#newdom.migrate_to_uri("qemu://remote/system") +#expect_success(newdom, "10 second downtime", "migrate_set_max_downtime", 10) + +newdom.destroy + +# TESTGROUP: dom.shutdown +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "shutdown", 1) +expect_success(newdom, "no args", "shutdown") +sleep 1 +newdom.destroy + +# TESTGROUP: dom.reboot +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 +expect_too_many_args(newdom, "reboot", 1, 2) +expect_invalid_arg_type(newdom, "reboot", "hello") + +# Qemu driver doesn't currently support reboot, so this is going to fail +begin + newdom.reboot + puts_ok "dom.reboot succeeded" +rescue Libvirt::Error => e + puts_skipped "dom.reboot not supported, skipped" +end + +sleep 1 +newdom.destroy + +# TESTGROUP: dom.destroy +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "destroy", 1) +expect_success(newdom, "no args", "destroy") + +# TESTGROUP: dom.suspend +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "suspend", 1) +expect_success(newdom, "no args", "suspend") +newdom.destroy + +# TESTGROUP: dom.resume +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_success(newdom, "no args running domain", "resume") + +newdom.suspend +expect_too_many_args(newdom, "resume", 1) +expect_success(newdom, "no args suspended domain", "resume") +newdom.destroy + +# TESTGROUP: dom.save +newdom = conn.define_domain_xml($new_dom_xml) +newdom.create +sleep 1 + +expect_too_many_args(newdom, "save", 1, 2) +expect_too_few_args(newdom, "save") +expect_invalid_arg_type(newdom, "save", 1) +expect_invalid_arg_type(newdom, "save", nil) +expect_fail(newdom, Libvirt::Error, "non-existent path", "save", "/this/path/does/not/exist") + +expect_success(newdom, "path arg", "save", "/var/lib/libvirt/images/ruby-libvirt-test.save") + +`rm -f /var/lib/libvirt/images/ruby-libvirt-test.save` +newdom.undefine + +# TESTGROUP: dom.managed_save +newdom = conn.define_domain_xml($new_dom_xml) +newdom.create +sleep 1 + +expect_too_many_args(newdom, "managed_save", 1, 2) +expect_invalid_arg_type(newdom, "managed_save", "hello") +expect_success(newdom, "no args", "managed_save") +newdom.undefine + +# TESTGROUP: dom.has_managed_save? +newdom = conn.define_domain_xml($new_dom_xml) +newdom.create +sleep 1 + +expect_too_many_args(newdom, "has_managed_save?", 1, 2) +expect_invalid_arg_type(newdom, "has_managed_save?", "hello") + +if newdom.has_managed_save? + puts_fail "dom.has_managed_save? reports true on a new domain" +else + puts_ok "dom.has_managed_save? not true on new domain" +end + +newdom.managed_save + +if not newdom.has_managed_save? + puts_fail "dom.has_managed_save? reports false after a managed save" +else + puts_ok "dom.has_managed_save? reports true after a managed save" +end + +newdom.undefine + +# TESTGROUP: dom.managed_save_remove +newdom = conn.define_domain_xml($new_dom_xml) +newdom.create +sleep 1 +newdom.managed_save + +expect_too_many_args(newdom, "managed_save_remove", 1, 2) +expect_invalid_arg_type(newdom, "managed_save_remove", "hello") + +if not newdom.has_managed_save? + puts_fail "prior to dom.managed_save_remove, no managed save file" +end +expect_success(newdom, "no args", "managed_save_remove") +if newdom.has_managed_save? + puts_fail "after dom.managed_save_remove, managed save file still exists" +else + puts_ok "after dom.managed_save_remove, managed save file no longer exists" +end + +newdom.undefine + +# TESTGROUP: dom.core_dump +newdom = conn.define_domain_xml($new_dom_xml) +newdom.create +sleep 1 + +expect_too_many_args(newdom, "core_dump", 1, 2, 3) +expect_too_few_args(newdom, "core_dump") +expect_invalid_arg_type(newdom, "core_dump", 1, 2) +expect_invalid_arg_type(newdom, "core_dump", "/path", "foo") +expect_fail(newdom, Libvirt::Error, "invalid path", "core_dump", "/this/path/does/not/exist") + +expect_success(newdom, "live with path arg", "core_dump", "/var/lib/libvirt/images/ruby-libvirt-test.core") + +`rm -f /var/lib/libvirt/images/ruby-libvirt-test.core` + +expect_success(newdom, "crash with path arg", "core_dump", "/var/lib/libvirt/images/ruby-libvirt-test.core", Libvirt::Domain::DUMP_CRASH) + +expect_fail(newdom, Libvirt::Error, "of shut-off domain", "core_dump", "/var/lib/libvirt/images/ruby-libvirt-test.core", Libvirt::Domain::DUMP_CRASH) + +`rm -f /var/lib/libvirt/images/ruby-libvirt-test.core` + +newdom.undefine + +# TESTGROUP: Libvirt::Domain::restore +newdom = conn.define_domain_xml($new_dom_xml) +newdom.create +sleep 1 +newdom.save("/var/lib/libvirt/images/ruby-libvirt-test.save") + +expect_too_many_args(Libvirt::Domain, "restore", 1, 2, 3) +expect_too_few_args(Libvirt::Domain, "restore") +expect_invalid_arg_type(Libvirt::Domain, "restore", 1, 2) +expect_invalid_arg_type(Libvirt::Domain, "restore", conn, 2) +expect_fail(Libvirt::Domain, Libvirt::Error, "invalid path", "restore", conn, "/this/path/does/not/exist") +`touch /tmp/foo` +expect_fail(Libvirt::Domain, Libvirt::Error, "invalid save file", "restore", conn, "/tmp/foo") +`rm -f /tmp/foo` + +expect_success(Libvirt::Domain, "2 args", "restore", conn, "/var/lib/libvirt/images/ruby-libvirt-test.save") + +`rm -f /var/lib/libvirt/images/ruby-libvirt-test.save` + +newdom.destroy +newdom.undefine + +# TESTGROUP: dom.info +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "info", 1) + +expect_success(newdom, "no args", "info") {|x| x.state == Libvirt::Domain::RUNNING and x.max_mem == 1048576 and x.memory == 1048576 and x.nr_virt_cpu == 2} + +newdom.destroy + +# TESTGROUP: dom.security_label +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "security_label", 1) + +expect_success(newdom, "no args", "security_label") + +newdom.destroy + +# TESTGROUP: dom.block_stats +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "block_stats", 1, 2) +expect_too_few_args(newdom, "block_stats") +expect_invalid_arg_type(newdom, "block_stats", 1) +expect_fail(newdom, Libvirt::RetrieveError, "invalid path", "block_stats", "foo") + +expect_success(newdom, "block device arg", "block_stats", "vda") + +newdom.destroy + +# TESTGROUP: dom.memory_stats +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "memory_stats", 1, 2) +expect_invalid_arg_type(newdom, "memory_stats", "foo") + +expect_success(newdom, "no args", "memory_stats") + +newdom.destroy + +# TESTGROUP: dom.blockinfo +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "blockinfo", 1, 2, 3) +expect_too_few_args(newdom, "blockinfo") +expect_invalid_arg_type(newdom, "blockinfo", 1) +expect_invalid_arg_type(newdom, "blockinfo", "foo", "bar") +expect_fail(newdom, Libvirt::RetrieveError, "invalid path", "blockinfo", "foo") + +expect_success(newdom, "path arg", "blockinfo", $GUEST_DISK) + +newdom.destroy + +# TESTGROUP: dom.block_peek +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "block_peek", 1, 2, 3, 4, 5) +expect_too_few_args(newdom, "block_peek") +expect_too_few_args(newdom, "block_peek", 1) +expect_too_few_args(newdom, "block_peek", 1, 2) +expect_invalid_arg_type(newdom, "block_peek", 1, 2, 3) +expect_invalid_arg_type(newdom, "block_peek", "foo", "bar", 3) +expect_invalid_arg_type(newdom, "block_peek", "foo", 0, "bar") +expect_invalid_arg_type(newdom, "block_peek", "foo", 0, 512, "baz") +expect_fail(newdom, Libvirt::RetrieveError, "invalid path", "block_peek", "foo", 0, 512) + +blockpeek = newdom.block_peek($GUEST_DISK, 0, 512) + +# 51 46 49 fb are the first 4 bytes of a qcow2 image +if blockpeek[0] != 0x51 or blockpeek[1] != 0x46 or blockpeek[2] != 0x49 or + blockpeek[3] != 0xfb + puts_fail "dom.block_peek read did not return valid data" +else + puts_ok "dom.block_peek read valid data" +end + +newdom.destroy + +# TESTGROUP: dom.memory_peek +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "memory_peek", 1, 2, 3, 4) +expect_too_few_args(newdom, "memory_peek") +expect_too_few_args(newdom, "memory_peek", 1) +expect_invalid_arg_type(newdom, "memory_peek", "foo", 2) +expect_invalid_arg_type(newdom, "memory_peek", 0, "bar") +expect_invalid_arg_type(newdom, "memory_peek", 0, 512, "baz") + +expect_success(newdom, "offset and size args", "memory_peek", 0, 512) + +newdom.destroy + +# TESTGROUP: dom.get_vcpus +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "get_vcpus", 1) + +expect_success(newdom, "no args", "get_vcpus") {|x| x.length == 2} + +newdom.destroy + +# TESTGROUP: dom.active? +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "active?", 1) + +expect_success(newdom, "no args", "active?") {|x| x == true} + +newdom.destroy + +newdom = conn.define_domain_xml($new_dom_xml) + +expect_success(newdom, "no args", "active?") {|x| x == false} + +newdom.create +sleep 1 + +expect_success(newdom, "no args", "active?") {|x| x == true} + +newdom.destroy +newdom.undefine + +# TESTGROUP: dom.persistent? +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "persistent?", 1) + +expect_success(newdom, "no args", "persistent?") {|x| x == false} + +newdom.destroy + +newdom = conn.define_domain_xml($new_dom_xml) + +expect_success(newdom, "no args", "persistent?") {|x| x == true} + +newdom.undefine + +# TESTGROUP: dom.ifinfo +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "ifinfo", 1, 2) +expect_too_few_args(newdom, "ifinfo") +expect_invalid_arg_type(newdom, "ifinfo", 1) +expect_fail(newdom, Libvirt::RetrieveError, "invalid arg", "ifinfo", "foo") + +expect_success(newdom, "interface arg", "ifinfo", "rl556") + +newdom.destroy + +# TESTGROUP: dom.name +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "name", 1) + +expect_success(newdom, "no args", "name") {|x| x == "ruby-libvirt-tester"} + +newdom.destroy + +# TESTGROUP: dom.id +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "id", 1) + +expect_success(newdom, "no args", "id") + +newdom.destroy + +# TESTGROUP: dom.uuid +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "uuid", 1) + +expect_success(newdom, "no args", "uuid") {|x| x == $GUEST_UUID} + +newdom.destroy + +# TESTGROUP: dom.os_type +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "os_type", 1) + +expect_success(newdom, "no args", "os_type") {|x| x == "hvm"} + +newdom.destroy + +# TESTGROUP: dom.max_memory +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "max_memory", 1) + +expect_success(newdom, "no args", "max_memory") {|x| x == 1048576} + +newdom.destroy + +# TESTGROUP: dom.max_memory= +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "max_memory=", 1, 2) +expect_too_few_args(newdom, "max_memory=") +expect_invalid_arg_type(newdom, "max_memory=", 'foo') + +begin + newdom.max_memory = 200000 + puts_ok "dom.max_memory= succeded" +rescue NoMethodError + puts_skipped "dom.max_memory does not exist" +rescue Libvirt::DefinitionError => e + # dom.max_memory is not supported by Qemu; skip + puts_skipped "dom.max_memory not supported by connection driver" +end + +newdom.undefine + +# TESTGROUP: dom.memory= +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "memory=", 1, 2) +expect_too_few_args(newdom, "memory=") +expect_invalid_arg_type(newdom, "memory=", 'foo') + +expect_fail(newdom, Libvirt::Error, "shutoff domain", "memory=", 2) + +newdom.undefine + +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_success(newdom, "number arg", "memory=", 200000) + +newdom.destroy + +# TESTGROUP: dom.max_vcpus +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "max_vcpus", 1) + +expect_success(newdom, "no args", "max_vcpus") + +newdom.destroy + +# TESTGROUP: dom.vcpus= +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "vcpus=", 1, 2) +expect_too_few_args(newdom, "vcpus=") +expect_invalid_arg_type(newdom, "vcpus=", 'foo') + +expect_fail(newdom, Libvirt::Error, "shutoff domain", "vcpus=", 2) + +newdom.undefine + +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +# FIXME: this kills the domain for some reason +#expect_success(newdom, "number arg", "vcpus=", 2) + +newdom.destroy + +# TESTGROUP: dom.pin_vcpu +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "pin_vcpu", 1, 2, 3) +expect_too_few_args(newdom, "pin_vcpu") +expect_invalid_arg_type(newdom, "pin_vcpu", 'foo', [0]) +expect_invalid_arg_type(newdom, "pin_vcpu", 0, 1) + +expect_success(newdom, "cpu args", "pin_vcpu", 0, [0]) + +newdom.destroy + +# TESTGROUP: dom.xml_desc +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_too_many_args(newdom, "xml_desc", 1, 2) +expect_invalid_arg_type(newdom, "xml_desc", "foo") + +expect_success(newdom, "no args", "xml_desc") + +newdom.destroy + +# TESTGROUP: dom.undefine +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "undefine", 1) + +expect_success(newdom, "no args", "undefine") + +# TESTGROUP: dom.create +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "create", 1, 2) +expect_invalid_arg_type(newdom, "create", "foo") + +expect_success(newdom, "no args", "create") + +expect_fail(newdom, Libvirt::Error, "on already running domain", "create") + +newdom.destroy +newdom.undefine + +# TESTGROUP: dom.autostart? +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "autostart?", 1) + +expect_success(newdom, "no args", "autostart?") {|x| x == false} + +newdom.autostart = true + +expect_success(newdom, "no args", "autostart?") {|x| x == true} + +newdom.undefine + +# TESTGROUP: dom.autostart= +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "autostart=", 1, 2) +expect_invalid_arg_type(newdom, "autostart=", 'foo') +expect_invalid_arg_type(newdom, "autostart=", nil) +expect_invalid_arg_type(newdom, "autostart=", 1234) + +expect_success(newdom, "true arg", "autostart=", true) +if not newdom.autostart? + puts_fail "dom.autostart= did not set autostart to true" +else + puts_ok "dom.autostart= set autostart to true" +end + +expect_success(newdom, "false arg", "autostart=", false) +if newdom.autostart? + puts_fail "dom.autostart= did not set autostart to false" +else + puts_ok "dom.autostart= set autostart to false" +end + +newdom.undefine + +# TESTGROUP: dom.attach_device +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "attach_device", 1, 2, 3) +expect_too_few_args(newdom, "attach_device") +expect_invalid_arg_type(newdom, "attach_device", 1) +expect_invalid_arg_type(newdom, "attach_device", 'foo', 'bar') +expect_fail(newdom, Libvirt::Error, "invalid XML", "attach_device", "hello") +expect_fail(newdom, Libvirt::Error, "shut off domain", "attach_device", new_hostdev_xml) + +newdom.undefine + +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +#expect_success(newdom, "hostdev XML", "attach_device", new_hostdev_xml) + +newdom.destroy + +# TESTGROUP: dom.detach_device +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "detach_device", 1, 2, 3) +expect_too_few_args(newdom, "detach_device") +expect_invalid_arg_type(newdom, "detach_device", 1) +expect_invalid_arg_type(newdom, "detach_device", 'foo', 'bar') +expect_fail(newdom, Libvirt::Error, "invalid XML", "detach_device", "hello") +expect_fail(newdom, Libvirt::Error, "shut off domain", "detach_device", new_hostdev_xml) + +newdom.undefine + +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +#expect_success(newdom, "hostdev XML", "detach_device", new_hostdev_xml) + +newdom.destroy + +# TESTGROUP: dom.update_device +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "update_device", 1, 2, 3) +expect_too_few_args(newdom, "update_device") +expect_invalid_arg_type(newdom, "update_device", 1) +expect_invalid_arg_type(newdom, "update_device", 'foo', 'bar') +expect_fail(newdom, Libvirt::Error, "invalid XML", "update_device", "hello") +expect_fail(newdom, Libvirt::Error, "shut off domain", "update_device", new_hostdev_xml) + +newdom.undefine + +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +#expect_success(newdom, "hostdev XML", "update_device", new_hostdev_xml) + +newdom.destroy + +# TESTGROUP: dom.free +newdom = conn.define_domain_xml($new_dom_xml) +newdom.undefine +expect_too_many_args(newdom, "free", 1) + +newdom.free +puts_ok "dom.free succeeded" + +# TESTGROUP: dom.snapshot_create_xml +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "snapshot_create_xml", 1, 2, 3) +expect_too_few_args(newdom, "snapshot_create_xml") +expect_invalid_arg_type(newdom, "snapshot_create_xml", 1) +expect_invalid_arg_type(newdom, "snapshot_create_xml", nil) +expect_invalid_arg_type(newdom, "snapshot_create_xml", 'foo', 'bar') + +expect_success(newdom, "simple XML arg", "snapshot_create_xml", "") + +snaps = newdom.num_of_snapshots +if snaps != 1 + puts_fail "dom.snapshot_create_xml after one snapshot has #{snaps} snapshots" +else + puts_ok "dom.snapshot_create_xml after one snapshot has 1 snapshot" +end + +newdom.undefine + +# TESTGROUP: dom.num_of_snapshots +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "num_of_snapshots", 1, 2) +expect_invalid_arg_type(newdom, "num_of_snapshots", 'foo') + +expect_success(newdom, "no args", "num_of_snapshots") {|x| x == 0} + +newdom.snapshot_create_xml("") + +expect_success(newdom, "no args", "num_of_snapshots") {|x| x == 1} + +newdom.undefine + +# TESTGROUP: dom.list_snapshots +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "list_snapshots", 1, 2) +expect_invalid_arg_type(newdom, "list_snapshots", 'foo') + +expect_success(newdom, "no args", "list_snapshots") {|x| x.length == 0} + +newdom.snapshot_create_xml("") + +expect_success(newdom, "no args", "list_snapshots") {|x| x.length == 1} + +newdom.undefine + +# TESTGROUP: dom.lookup_snapshot_by_name +newdom = conn.define_domain_xml($new_dom_xml) +newdom.snapshot_create_xml("foo") + +expect_too_many_args(newdom, "lookup_snapshot_by_name", 1, 2, 3) +expect_too_few_args(newdom, "lookup_snapshot_by_name") +expect_invalid_arg_type(newdom, "lookup_snapshot_by_name", 1) +expect_invalid_arg_type(newdom, "lookup_snapshot_by_name", 'foo', 'bar') + +expect_success(newdom, "name arg", "lookup_snapshot_by_name", "foo") + +newdom.undefine + +# TESTGROUP: dom.has_current_snapshot? +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "has_current_snapshot?", 1, 2) +expect_invalid_arg_type(newdom, "has_current_snapshot?", 'foo') + +expect_success(newdom, "no args", "has_current_snapshot?") {|x| x == false} + +newdom.snapshot_create_xml("foo") + +expect_success(newdom, "no args", "has_current_snapshot?") {|x| x == true} + +newdom.undefine + +# TESTGROUP: dom.revert_to_snapshot +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "revert_to_snapshot", 1, 2, 3) +expect_too_few_args(newdom, "revert_to_snapshot") +expect_invalid_arg_type(newdom, "revert_to_snapshot", 1) +expect_invalid_arg_type(newdom, "revert_to_snapshot", nil) +expect_invalid_arg_type(newdom, "revert_to_snapshot", 'foo') + +snap = newdom.snapshot_create_xml("foo") +sleep 1 + +expect_invalid_arg_type(newdom, "revert_to_snapshot", snap, 'foo') + +expect_success(newdom, "snapshot arg", "revert_to_snapshot", snap) + +newdom.undefine + +# TESTGROUP: dom.current_snapshot +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "current_snapshot", 1, 2) +expect_invalid_arg_type(newdom, "current_snapshot", 'foo') +expect_fail(newdom, Libvirt::RetrieveError, "with no snapshots", "current_snapshot") + +newdom.snapshot_create_xml("foo") + +expect_success(newdom, "no args", "current_snapshot") + +newdom.undefine + +# TESTGROUP: snapshot.xml_desc +newdom = conn.define_domain_xml($new_dom_xml) +snap = newdom.snapshot_create_xml("") + +expect_too_many_args(snap, "xml_desc", 1, 2) +expect_invalid_arg_type(snap, "xml_desc", 'foo') + +expect_success(newdom, "no args", "xml_desc") + +newdom.undefine + +# TESTGROUP: snapshot.delete +newdom = conn.define_domain_xml($new_dom_xml) +snap = newdom.snapshot_create_xml("") + +expect_too_many_args(snap, "delete", 1, 2) +expect_invalid_arg_type(snap, "delete", 'foo') + +expect_success(snap, "no args", "delete") + +newdom.undefine + +# TESTGROUP: snapshot.free +newdom = conn.define_domain_xml($new_dom_xml) +newdom.undefine +expect_too_many_args(newdom, "free", 1) + +expect_success(newdom, "no args", "free") + +# TESTGROUP: dom.job_info +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "job_info", 1) + +expect_fail(newdom, Libvirt::RetrieveError, "shutoff domain", "job_info") + +newdom.undefine + +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_success(newdom, "no args", "job_info") + +newdom.destroy + +# TESTGROUP: dom.abort_job +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "abort_job", 1) + +expect_fail(newdom, Libvirt::Error, "not running domain", "abort_job") + +newdom.undefine + +newdom = conn.create_domain_xml($new_dom_xml) +sleep 1 + +expect_fail(newdom, Libvirt::Error, "no active job", "abort_job") + +# FIXME: need to start long running job here +#expect_success(newdom, "no args", "abort_job") + +newdom.destroy + +# TESTGROUP: dom.scheduler_type +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "scheduler_type", 1) + +begin + newdom.scheduler_type + puts_ok "dom.scheduler_type succeeded" +rescue NoMethodError + puts_skipped "dom.scheduler_type does not exist" +rescue Libvirt::RetrieveError + # this may not be supported (if cgroups aren't configured), so skip it + puts_skipped "dom.scheduler_type not supported" +end + +newdom.undefine + +# TESTGROUP: dom.scheduler_parameters +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "scheduler_parameters", 1) + +begin + newdom.scheduler_parameters + puts_ok "dom.scheduler_parameters succeeded" +rescue NoMethodError + puts_skipped "dom.scheduler_parameters does not exist" +rescue Libvirt::RetrieveError + # this may not be supported (if cgroups aren't configured), so skip it + puts_ok "dom.scheduler_parameters not supported" +end + +newdom.undefine + +# TESTGROUP: dom.scheduler_parameters= +newdom = conn.define_domain_xml($new_dom_xml) + +expect_too_many_args(newdom, "scheduler_parameters=", 1, 2) +expect_too_few_args(newdom, "scheduler_parameters=") +expect_invalid_arg_type(newdom, "scheduler_parameters=", 0) + +begin + newdom.scheduler_parameters={"cpu_shares"=>512} +rescue NoMethodError + puts_skipped "dom.scheduler_parameters= does not exist" +rescue Libvirt::RetrieveError + # this may not be supported (if cgroups aren't configured), so skip it + puts_ok "dom.scheduler_parameters= not supported" +end + +newdom.undefine + +# TESTGROUP: dom.qemu_monitor_command +new_test_xml = < + fc4 + EF86180145B911CB88E3AFBFE5370493 + + xen + /boot/vmlinuz-2.6.15-1.43_FC5guest + /boot/initrd-2.6.15-1.43_FC5guest.img + /dev/sda1 + ro selinux=0 3 + + 261072 + 131072 + 1 + + + + + + + + +