[Pkg-libvirt-commits] [SCM] libvirt ruby bindinds packaging branch, master, updated. debian/0.4.0-1
Guido Günther
agx at sigxcpu.org
Tue Feb 7 21:11:44 UTC 2012
The following commit has been merged in the master branch:
commit 7bf70bab8c51e2eec9f44a4515ddab7e8f5dfcd9
Author: Guido Günther <agx at sigxcpu.org>
Date: Tue Feb 7 19:40:38 2012 +0100
New upstream version 0.4.0
diff --git a/NEWS b/NEWS
index f607975..c26c071 100644
--- a/NEWS
+++ b/NEWS
@@ -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 --git a/README b/README
index 1c7ed49..011ea22 100644
--- a/README
+++ b/README
@@ -7,7 +7,7 @@ Usage
-----
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 @@ To run against the checkout, make sure you set RUBYLIB (assuming DIR is the
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 --git a/README.rdoc b/README.rdoc
index eb37a7e..3514843 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -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 --git a/Rakefile b/Rakefile
index 62f3ae2..8996716 100644
--- a/Rakefile
+++ b/Rakefile
@@ -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/clean'
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/**/*"
-]
+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"
-]
+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 @@ SPEC = Gem::Specification.new do |s|
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 = <<EOF
-Provides bindings for libvirt.
-EOF
+ s.author = "David Lutterkort, Chris Lalancette"
+ s.rubyforge_project = "None"
+ s.description = "Ruby bindings for libvirt."
end
Rake::GemPackageTask.new(SPEC) do |pkg|
@@ -106,14 +146,6 @@ Rake::GemPackageTask.new(SPEC) do |pkg|
pkg.need_zip = true
end
-desc "Update the ruby-libvirt site"
-task :site => [ :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 @@ task :rpm => [ :package ] do |t|
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 --git a/ext/libvirt/_libvirt.c b/ext/libvirt/_libvirt.c
index a1b6fae..0e7e0df 100644
--- a/ext/libvirt/_libvirt.c
+++ b/ext/libvirt/_libvirt.c
@@ -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 <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#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<num; i++) { \
- rb_ary_push(result, rb_str_new2(names[i])); \
- free(names[i]); \
- } \
- free(names); \
- return result; \
- } 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 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) \
- free((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)
-
-/*
- * Module Libvirt
- */
-
-/*
- * call-seq:
- * Libvirt::version(type) -> [ 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<num; i++) {
- rb_ary_push(result, INT2NUM(ids[i]));
- }
- free(ids);
- return result;
-}
-
-/*
- * Call +virConnectNumOfDefinedDomains+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfDefinedDomains]
- */
-VALUE libvirt_conn_num_of_defined_domains(VALUE s) {
- gen_conn_num_of(s, DefinedDomains);
-}
-
-/*
- * Call +virConnectListDefinedDomains+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListDefinedDomains]
- */
-VALUE libvirt_conn_list_defined_domains(VALUE s) {
- gen_conn_list_names(s, DefinedDomains);
-}
-
-/*
- * Call +virConnectNumOfNetworks+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfNetworks]
- */
-VALUE libvirt_conn_num_of_networks(VALUE s) {
- gen_conn_num_of(s, Networks);
-}
-
-/*
- * Call +virConnectListNetworks+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListNetworks]
- */
-VALUE libvirt_conn_list_networks(VALUE s) {
- gen_conn_list_names(s, Networks);
-}
-
-/*
- * Call +virConnectNumOfDefinedNetworks+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfDefinedNetworks]
- */
-VALUE libvirt_conn_num_of_defined_networks(VALUE s) {
- gen_conn_num_of(s, DefinedNetworks);
-}
-
-/*
- * Call +virConnectListDefinedNetworks+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListDefinedNetworks]
- */
-VALUE libvirt_conn_list_defined_networks(VALUE s) {
- gen_conn_list_names(s, DefinedNetworks);
-}
-
-#if HAVE_TYPE_VIRSTORAGEPOOLPTR
-/*
- * Call +virConnectListStoragePools+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListStoragePools]
- */
-VALUE libvirt_conn_list_storage_pools(VALUE s) {
- gen_conn_list_names(s, StoragePools);
-}
-
-/*
- * Call +virConnectNumOfStoragePools+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfStoragePools]
- */
-VALUE libvirt_conn_num_of_storage_pools(VALUE s) {
- gen_conn_num_of(s, StoragePools);
-}
-
-/*
- * Call +virConnectListDefinedStoragePools+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectListDefinedStoragePools]
- */
-VALUE libvirt_conn_list_defined_storage_pools(VALUE s) {
- gen_conn_list_names(s, DefinedStoragePools);
-}
-
-/*
- * Call +virConnectNumOfDefinedStoragePools+[http://www.libvirt.org/html/libvirt-libvirt.html#virConnectNumOfDefinedStoragePools]
- */
-VALUE libvirt_conn_num_of_defined_storage_pools(VALUE s) {
- gen_conn_num_of(s, DefinedStoragePools);
-}
-#endif
-
-/*
- * Class Libvirt::Domain
- */
-VALUE libvirt_dom_migrate(VALUE s, VALUE dconn, VALUE flags,
- VALUE dname, VALUE uri, VALUE bandwidth) {
- virDomainPtr ddom = NULL;
-
- ddom = virDomainMigrate(domain_get(s), conn(dconn), NUM2UINT(flags),
- StringValueCStr(dname), StringValueCStr(uri),
- NUM2UINT(bandwidth));
-
- _E(ddom == NULL,
- create_error(e_Error, "virDomainMigrate", "", conn(dconn)));
-
- return domain_new(ddom, dconn);
-}
-
-/*
- * Call +virDomainShutdown+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainShutdown]
- */
-VALUE libvirt_dom_shutdown(VALUE s) {
- gen_call_void(virDomainShutdown, conn(s),
- domain_get(s));
-}
-
-/*
- * Call +virDomainReboot+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainReboot]
- */
-VALUE libvirt_dom_reboot(int argc, VALUE *argv, VALUE s) {
- VALUE flags;
-
- rb_scan_args(argc, argv, "01", &flags);
-
- if (NIL_P(flags))
- flags = INT2FIX(0);
-
- gen_call_void(virDomainReboot, conn(s),
- domain_get(s), NUM2UINT(flags));
-}
-
-/*
- * Call +virDomainDestroy+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainDestroy]
- */
-VALUE libvirt_dom_destroy(VALUE s) {
- gen_call_void(virDomainDestroy, conn(s),
- domain_get(s));
-}
-
-/*
- * Call +virDomainSuspend+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSuspend]
- */
-VALUE libvirt_dom_suspend(VALUE s) {
- gen_call_void(virDomainSuspend, conn(s),
- domain_get(s));
-}
-
-/*
- * Call +virDomainResume+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainResume]
- */
-VALUE libvirt_dom_resume(VALUE s) {
- gen_call_void(virDomainResume, conn(s),
- domain_get(s));
-}
-
-/*
- * Call +virDomainSave+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSave]
- */
-VALUE libvirt_dom_save(VALUE s, VALUE to) {
- gen_call_void(virDomainSave, conn(s),
- domain_get(s), StringValueCStr(to));
-}
-
-/*
- * Call +virDomainCoreDump+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainCoreDump]
- */
-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 = INT2FIX(0);
-
- gen_call_void(virDomainCoreDump, conn(s),
- domain_get(s), StringValueCStr(to), NUM2UINT(flags));
-}
-
-/*
- * Call +virDomainRestore+[http://www.libvirt.org/html/libvirt-libvirt.html#virDomainRestore]
- */
-VALUE libvirt_dom_s_restore(VALUE klass, VALUE c, VALUE from) {
- gen_call_void(virDomainRestore, connect_get(c),
- connect_get(c), StringValueCStr(from));
-}
-
-/*
- * call-seq:
- * domain.info -> 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)));
-
- 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));
+ userdata = (VALUE)cbdata;
+
+ if (!rb_block_given_p())
+ rb_raise(rb_eRuntimeError, "No block given, this should never happen!\n");
+
+ for (i = 0; i < ncred; i++) {
+ newcred = rb_hash_new();
+
+ 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 result;
+ return 0;
}
-/*
- * 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);
- if (NIL_P(flags))
- flags = INT2FIX(0);
-
- gen_call_string(virStoragePoolGetXMLDesc, conn(s), 1,
- pool_get(s), NUM2UINT(flags));
-}
-
-/*
- * Call +virStoragePoolGetAutostart+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolGetAutostart]
- */
-VALUE libvirt_pool_autostart(VALUE s){
- int r, autostart;
+struct wrap_callout {
+ char *uri;
+ virConnectAuthPtr auth;
+ unsigned int flags;
+};
- r = virStoragePoolGetAutostart(pool_get(s), &autostart);
- _E(r < 0, create_error(e_RetrieveError, "virStoragePoolGetAutostart", "", conn(s)));
+static VALUE rb_open_auth_wrap(VALUE arg) {
+ struct wrap_callout *e = (struct wrap_callout *)arg;
- return autostart ? Qtrue : Qfalse;
+ return (VALUE)virConnectOpenAuth(e->uri, e->auth, e->flags);
}
-/*
- * 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);
+static VALUE rb_num2int_wrap(VALUE arg) {
+ return NUM2INT(arg);
}
/*
- * 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);
-}
+ * call-seq:
+ * Libvirt::open_auth(uri=nil, credlist=nil, userdata=nil, flags=0) {|...| authentication block} -> 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);
+
+ 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;
+ }
-/*
- * 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;
+ callargs.uri = uri_c;
+ callargs.auth = auth;
+ callargs.flags = flags;
- num = virStoragePoolNumOfVolumes(pool);
- _E(num < 0, create_error(e_RetrieveError, "virStoragePoolNumOfVolumes", "", conn(s)));
+ conn = (virConnectPtr)rb_protect(rb_open_auth_wrap, (VALUE)&callargs,
+ &exception);
- 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)));
+do_cleanup:
+ if (auth_alloc) {
+ free(auth->credtype);
+ xfree(auth);
}
- result = rb_ary_new2(num);
- for (i=0; i<num; i++) {
- rb_ary_push(result, rb_str_new2(names[i]));
- // FIXME: Should these really be freed ?
- free(names[i]);
- }
- free(names);
- return result;
-}
+ if (exception)
+ rb_jump_tag(exception);
-/*
- * Call +virStoragePoolFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virStoragePoolFree]
- */
-VALUE libvirt_pool_free(VALUE s) {
- gen_call_free(StoragePool, s);
+ _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;
+ * 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)");
+
+ libvirt_cb = rb_hash_aref(opaque, rb_str_new2("libvirt_cb"));
+
+ /* 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);
- vol = virStorageVolLookupByName(pool_get(p), StringValueCStr(name));
- _E(vol == NULL, create_error(e_RetrieveError, "virStorageVolLookupByName", "", 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 +virStorageVolLookupByKey+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolLookupByKey]
- */
-VALUE libvirt_pool_lookup_vol_by_key(VALUE p, VALUE key) {
- 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)");
+
+ libvirt_cb = rb_hash_aref(opaque, rb_str_new2("libvirt_cb"));
+
+ /* 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(timer), 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;
+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)");
- // 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)));
+ if (TYPE(res) != T_FIXNUM)
+ rb_raise(rb_eTypeError,
+ "expected integer return from add_handle callback");
- return vol_new(vol, conn_attr(p));
+ return NUM2INT(res);
}
-/*
- * 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));
-}
+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)");
+}
+
+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 (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);
+ }
+ }
-/*
- * 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 0;
}
-/*
- * 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);
+static int internal_add_timeout_func(int interval, virEventTimeoutCallback cb,
+ void *opaque, virFreeCallback ff) {
+ VALUE rubyargs;
+ VALUE res;
- vol = virStorageVolCreateXML(pool_get(p), xmlDesc, NUM2UINT(flags));
- _E(vol == NULL, create_error(e_Error, "virNetworkCreateXML", "", c));
+ rubyargs = rb_hash_new();
- return vol_new(vol, conn_attr(p));
-}
-
-/*
- * Call +virStorageVolDelete+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolDelete]
- */
-VALUE libvirt_vol_delete(int argc, VALUE *argv, VALUE v) {
- VALUE flags;
+ 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));
- rb_scan_args(argc, argv, "01", &flags);
+ /* 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)");
- if (NIL_P(flags))
- flags = INT2FIX(0);
+ if (TYPE(res) != T_FIXNUM)
+ rb_raise(rb_eTypeError,
+ "expected integer return from add_timeout callback");
- gen_call_void(virStorageVolDelete, conn(v),
- vol_get(v), NUM2UINT(flags));
+ return NUM2INT(res);
}
-/*
- * 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)));
-
- 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));
+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)");
+}
+
+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)");
+
+ 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 result;
+ return 0;
}
-/*
- * 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);
-
- if (NIL_P(flags))
- flags = INT2FIX(0);
-
- gen_call_string(virStorageVolGetXMLDesc, conn(v), 1,
- vol_get(v), NUM2UINT(flags));
-}
+#define set_event_func_or_null(type) \
+ do { \
+ if (NIL_P(type)) \
+ type##_temp = NULL; \
+ else \
+ type##_temp = internal_##type##_func; \
+ } while(0)
-/*
- * 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));
+static int is_symbol_proc_or_nil(VALUE handle) {
+ if (NIL_P(handle))
+ return 1;
+ return is_symbol_or_proc(handle);
}
/*
- * Call +virStorageVolFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolFree]
- */
-VALUE libvirt_vol_free(VALUE s) {
- gen_call_free(StorageVol, s);
-}
-#endif
+ * 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;
-static void init_storage(void) {
/*
- * Class Libvirt::StoragePool and Libvirt::StoragePoolInfo
+ * 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
*/
-#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
+ rb_scan_args(argc, argv, "06", &add_handle, &update_handle, &remove_handle,
+ &add_timeout, &update_timeout, &remove_timeout);
+
+ 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);
-#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
+ return Qnil;
}
+#endif
+/*
+ * Module Libvirt
+ */
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);
-
- // create 'libvirt_function_name' and 'vir_connect_ptr' attributes on e_Error class
+ 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);
+
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);
+#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
- // 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_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
+#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
- /*
- * 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);
+ /* 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
- /*
- * 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);
+ /* 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
- /*
- * 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_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 --git a/ext/libvirt/common.c b/ext/libvirt/common.c
new file mode 100644
index 0000000..fa61056
--- /dev/null
+++ b/ext/libvirt/common.c
@@ -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 <stdio.h>
+#include <ruby.h>
+#include <libvirt/libvirt.h>
+#include <libvirt/virterror.h>
+#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 --git a/ext/libvirt/common.h b/ext/libvirt/common.h
new file mode 100644
index 0000000..d68e3c1
--- /dev/null
+++ b/ext/libvirt/common.h
@@ -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 --git a/ext/libvirt/connect.c b/ext/libvirt/connect.c
new file mode 100644
index 0000000..8f511d6
--- /dev/null
+++ b/ext/libvirt/connect.c
@@ -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 <ruby.h>
+#include <libvirt/libvirt.h>
+#include <libvirt/virterror.h>
+#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 --git a/ext/libvirt/connect.h b/ext/libvirt/connect.h
new file mode 100644
index 0000000..c64428c
--- /dev/null
+++ b/ext/libvirt/connect.h
@@ -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 --git a/ext/libvirt/domain.c b/ext/libvirt/domain.c
new file mode 100644
index 0000000..d4a9236
--- /dev/null
+++ b/ext/libvirt/domain.c
@@ -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 <stdint.h>
+#include <ruby.h>
+#include <st.h>
+#include <libvirt/libvirt.h>
+#if HAVE_VIRDOMAINQEMUMONITORCOMMAND
+#include <libvirt/libvirt-qemu.h>
+#endif
+#include <libvirt/virterror.h>
+#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<r; i++) {
+ tmp = rb_class_new_instance(0, NULL, c_domain_memory_stats);
+ rb_iv_set(tmp, "@tag", INT2NUM(stats[i].tag));
+ rb_iv_set(tmp, "@val", ULL2NUM(stats[i].val));
+
+ rb_ary_push(result, tmp);
+ } \
+
+ return result;
+}
+#endif
+
+#if HAVE_TYPE_VIRDOMAINBLOCKINFOPTR
+/*
+ * call-seq:
+ * dom.blockinfo(path, flags=0) -> 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 --git a/ext/libvirt/domain.h b/ext/libvirt/domain.h
new file mode 100644
index 0000000..dfca6ec
--- /dev/null
+++ b/ext/libvirt/domain.h
@@ -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 --git a/ext/libvirt/extconf.h b/ext/libvirt/extconf.h
deleted file mode 100644
index 29a7f7c..0000000
--- a/ext/libvirt/extconf.h
+++ /dev/null
@@ -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 --git a/ext/libvirt/extconf.rb b/ext/libvirt/extconf.rb
index 331eb21..6d0f6bc 100644
--- a/ext/libvirt/extconf.rb
+++ b/ext/libvirt/extconf.rb
@@ -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 @@ def have_libvirt_types(types)
types.each { |t| have_type(t, "libvirt/libvirt.h") }
end
+# 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
+
+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
+
+def have_libvirt_consts(consts)
+ consts.each { |c| have_const(c, ["libvirt/libvirt.h", "libvirt/virterror.h"]) }
+end
+
extension_name = '_libvirt'
-dir_config(extension_name)
+# 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")
-unless pkg_config("libvirt")
- raise "libvirt not found"
+ # 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 --git a/ext/libvirt/interface.c b/ext/libvirt/interface.c
new file mode 100644
index 0000000..6af2fea
--- /dev/null
+++ b/ext/libvirt/interface.c
@@ -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 <ruby.h>
+#include <libvirt/libvirt.h>
+#include <libvirt/virterror.h>
+#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 --git a/ext/libvirt/interface.h b/ext/libvirt/interface.h
new file mode 100644
index 0000000..a313625
--- /dev/null
+++ b/ext/libvirt/interface.h
@@ -0,0 +1,6 @@
+#ifndef INTERFACE_H
+#define INTERFACE_H
+
+void init_interface();
+
+#endif
diff --git a/ext/libvirt/network.c b/ext/libvirt/network.c
new file mode 100644
index 0000000..75eefce
--- /dev/null
+++ b/ext/libvirt/network.c
@@ -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 <ruby.h>
+#include <libvirt/libvirt.h>
+#include <libvirt/virterror.h>
+#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 --git a/ext/libvirt/network.h b/ext/libvirt/network.h
new file mode 100644
index 0000000..1d2c07b
--- /dev/null
+++ b/ext/libvirt/network.h
@@ -0,0 +1,7 @@
+#ifndef NETWORK_H
+#define NETWORK_H
+
+VALUE network_new(virNetworkPtr n, VALUE conn);
+void init_network();
+
+#endif
diff --git a/ext/libvirt/nodedevice.c b/ext/libvirt/nodedevice.c
new file mode 100644
index 0000000..22b2ff4
--- /dev/null
+++ b/ext/libvirt/nodedevice.c
@@ -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 <ruby.h>
+#include <libvirt/libvirt.h>
+#include <libvirt/virterror.h>
+#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 --git a/ext/libvirt/nodedevice.h b/ext/libvirt/nodedevice.h
new file mode 100644
index 0000000..387ff3d
--- /dev/null
+++ b/ext/libvirt/nodedevice.h
@@ -0,0 +1,6 @@
+#ifndef NODEDEVICE_H
+#define NODEDEVICE_H
+
+void init_nodedevice();
+
+#endif
diff --git a/ext/libvirt/nwfilter.c b/ext/libvirt/nwfilter.c
new file mode 100644
index 0000000..4ab2d17
--- /dev/null
+++ b/ext/libvirt/nwfilter.c
@@ -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 <ruby.h>
+#include <libvirt/libvirt.h>
+#include <libvirt/virterror.h>
+#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 --git a/ext/libvirt/nwfilter.h b/ext/libvirt/nwfilter.h
new file mode 100644
index 0000000..fc4bc0c
--- /dev/null
+++ b/ext/libvirt/nwfilter.h
@@ -0,0 +1,6 @@
+#ifndef NWFILTER_H
+#define NWFILTER_H
+
+void init_nwfilter();
+
+#endif
diff --git a/ext/libvirt/secret.c b/ext/libvirt/secret.c
new file mode 100644
index 0000000..e62c335
--- /dev/null
+++ b/ext/libvirt/secret.c
@@ -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 <ruby.h>
+#include <libvirt/libvirt.h>
+#include <libvirt/virterror.h>
+#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 --git a/ext/libvirt/secret.h b/ext/libvirt/secret.h
new file mode 100644
index 0000000..e2bce35
--- /dev/null
+++ b/ext/libvirt/secret.h
@@ -0,0 +1,6 @@
+#ifndef SECRET_H
+#define SECRET_H
+
+void init_secret();
+
+#endif
diff --git a/ext/libvirt/storage.c b/ext/libvirt/storage.c
new file mode 100644
index 0000000..f3c8487
--- /dev/null
+++ b/ext/libvirt/storage.c
@@ -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 <ruby.h>
+#include <libvirt/libvirt.h>
+#include <libvirt/virterror.h>
+#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 --git a/ext/libvirt/storage.h b/ext/libvirt/storage.h
new file mode 100644
index 0000000..2cfd34a
--- /dev/null
+++ b/ext/libvirt/storage.h
@@ -0,0 +1,6 @@
+#ifndef STORAGE_H
+#define STORAGE_H
+
+void init_storage();
+
+#endif
diff --git a/ext/libvirt/stream.c b/ext/libvirt/stream.c
new file mode 100644
index 0000000..3d120be
--- /dev/null
+++ b/ext/libvirt/stream.c
@@ -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 <ruby.h>
+#include <libvirt/libvirt.h>
+#include <libvirt/virterror.h>
+#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 --git a/ext/libvirt/stream.h b/ext/libvirt/stream.h
new file mode 100644
index 0000000..094c6e9
--- /dev/null
+++ b/ext/libvirt/stream.h
@@ -0,0 +1,7 @@
+#ifndef STREAM_H
+#define STREAM_H
+
+virStreamPtr stream_get(VALUE s);
+void init_stream();
+
+#endif
diff --git a/tests/tc_connect.rb b/tests/tc_connect.rb
deleted file mode 100644
index 81bb208..0000000
--- a/tests/tc_connect.rb
+++ /dev/null
@@ -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 = "<capabilities>\n <host>\n <cpu>\n <arch>i686</arch>\n <features>\n <pae/>\n <nonpae/>\n </features>\n </cpu>\n </host>\n\n <guest>\n <os_type>linux</os_type>\n <arch name=\"i686\">\n <wordsize>32</wordsize>\n <domain type=\"test\"/>\n </arch>\n <features>\n <pae/>\n <nonpae/>\n </features>\n </guest>\n</capabilities>\n"
-
- TEST_CAPS_0_40_1 = "<capabilities>\n\n <host>\n <cpu>\n <arch>i686</arch>\n <features>\n <pae/>\n <nonpae/>\n </features>\n </cpu>\n <topology>\n <cells num='2'>\n <cell id='0'>\n <cpus num='8'>\n <cpu id='0'>\n <cpu id='2'>\n <cpu id='4'>\n <cpu id='6'>\n <cpu id='8'>\n <cpu id='10'>\n <cpu id='12'>\n <cpu id='14'>\n </cpus>\n </cell>\n <cell id='1'>\n <cpus num='8'>\n <cpu id='1'>\n <cpu id='3'>\n <cpu id='5'>\n <cpu id='7'>\n <cpu id='9'>\n <cpu id='11'>\n <cpu id='13'>\n <cpu id='15'>\n </cpus>\n </cell>\n </cells>\n </topology>\n </host>\n\n <guest>\n <os_type>linux</os_type>\n <arch name='i686'>\n <wordsize>32</wordsize>\n <domain type='test'>\n </domain>\n </arch>\n <features>\n <pae/>\n <nonpae/>\n </features>\n </guest>\n\n</capabilities>\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 = "<network>
- <name>local</name>
- <uuid>9b562b27-0969-4b39-8c96-ef7858152ccc</uuid>
- <bridge name='virbr0'/>
- <forward/>
- <ip address='172.31.122.1' netmask='255.255.255.0'>
- <dhcp>
- <range start='172.31.122.2' end='172.31.122.254'/>
- </dhcp>
- </ip>
-</network>
-"
-
- 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 --git a/tests/test_conn.rb b/tests/test_conn.rb
new file mode 100644
index 0000000..65c1a75
--- /dev/null
+++ b/tests/test_conn.rb
@@ -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 = <<EOF
+<cpu>
+ <arch>x86_64</arch>
+ <model>athlon</model>
+</cpu>
+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", "<nodedevice/>")
+
+# 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 --git a/tests/test_domain.rb b/tests/test_domain.rb
new file mode 100644
index 0000000..f3976be
--- /dev/null
+++ b/tests/test_domain.rb
@@ -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
+<hostdev mode='subsystem' type='pci' managed='yes'>
+ <source>
+ <address bus='0x45' slot='0x55' function='0x33'/>
+ </source>
+</hostdev>
+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", "<domainsnapshot/>")
+
+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("<domainsnapshot/>")
+
+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("<domainsnapshot/>")
+
+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("<domainsnapshot><name>foo</name></domainsnapshot>")
+
+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("<domainsnapshot><name>foo</name></domainsnapshot>")
+
+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("<domainsnapshot><name>foo</name></domainsnapshot>")
+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("<domainsnapshot><name>foo</name></domainsnapshot>")
+
+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("<domainsnapshot/>")
+
+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("<domainsnapshot/>")
+
+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 = <<EOF
+<domain type='test'>
+ <name>fc4</name>
+ <uuid>EF86180145B911CB88E3AFBFE5370493</uuid>
+ <os>
+ <type>xen</type>
+ <kernel>/boot/vmlinuz-2.6.15-1.43_FC5guest</kernel>
+ <initrd>/boot/initrd-2.6.15-1.43_FC5guest.img</initrd>
+ <root>/dev/sda1</root>
+ <cmdline> ro selinux=0 3</cmdline>
+ </os>
+ <memory>261072</memory>
+ <currentMemory>131072</currentMemory>
+ <vcpu>1</vcpu>
+ <devices>
+ <disk type='file'>
+ <source file='/u/fc4.img'/>
+ <target dev='sda1'/>
+ </disk>
+ <interface type='bridge'>
+ <source bridge='xenbr0'/>
+ <mac address='aa:00:00:00:00:11'/>
+ <script path='/etc/xen/scripts/vif-bridge'/>
+ </interface>
+ <console tty='/dev/pts/5'/>
+ </devices>
+</domain>
+EOF
+
+newdom = conn.create_domain_xml($new_dom_xml)
+
+expect_too_many_args(newdom, "qemu_monitor_command", 1, 2, 3)
+expect_too_few_args(newdom, "qemu_monitor_command")
+expect_invalid_arg_type(newdom, "qemu_monitor_command", 1)
+expect_invalid_arg_type(newdom, "qemu_monitor_command", "foo", "bar")
+testconn = Libvirt::open("test:///default")
+fakedom = testconn.create_domain_xml(new_test_xml)
+expect_invalid_arg_type(fakedom, "qemu_monitor_command", "foo")
+fakedom.destroy
+testconn.close
+expect_fail(newdom, Libvirt::RetrieveError, "invalid command", "qemu_monitor_command", "foo")
+
+expect_success(newdom, "monitor command", "qemu_monitor_command", '{"execute":"query-cpus"}')
+
+newdom.destroy
+
+# TESTGROUP: dom.num_vcpus
+newdom = conn.define_domain_xml($new_dom_xml)
+
+expect_too_many_args(newdom, "num_vcpus", 1, 2)
+expect_too_few_args(newdom, "num_vcpus")
+expect_invalid_arg_type(newdom, "num_vcpus", 'foo')
+expect_fail(newdom, Libvirt::Error, "zero flags", "num_vcpus", 0)
+expect_fail(newdom, Libvirt::Error, "active flag on shutoff domain", "num_vcpus", Libvirt::Domain::VCPU_LIVE)
+expect_fail(newdom, Libvirt::Error, "live and config flags", "num_vcpus", Libvirt::Domain::VCPU_LIVE | Libvirt::Domain::VCPU_CONFIG)
+expect_success(newdom, "config flag", "num_vcpus", Libvirt::Domain::VCPU_CONFIG) {|x| x == 2}
+
+newdom.undefine
+
+newdom = conn.create_domain_xml($new_dom_xml)
+sleep 1
+
+expect_success(newdom, "config flag on transient domain", "num_vcpus", Libvirt::Domain::VCPU_CONFIG)
+expect_success(newdom, "live flag on transient domain", "num_vcpus", Libvirt::Domain::VCPU_LIVE)
+
+newdom.destroy
+
+# TESTGROUP: dom.vcpus_flags=
+newdom = conn.define_domain_xml($new_dom_xml)
+
+expect_too_many_args(newdom, "vcpus_flags=", 1, 2, 3)
+expect_too_few_args(newdom, "vcpus_flags=")
+expect_invalid_arg_type(newdom, "vcpus_flags=", 1)
+expect_invalid_arg_type(newdom, "vcpus_flags=", ['foo', 2])
+expect_invalid_arg_type(newdom, "vcpus_flags=", [2, 'foo'])
+expect_fail(newdom, Libvirt::Error, "zero flags", "vcpus_flags=", [2, 0])
+expect_fail(newdom, Libvirt::Error, "zero vcpus", "vcpus_flags=", [0, Libvirt::Domain::VCPU_CONFIG])
+expect_fail(newdom, Libvirt::Error, "live vcpu on shutoff domain", "vcpus_flags=", [2, Libvirt::Domain::VCPU_LIVE])
+expect_success(newdom, "2 vcpu config", "vcpus_flags=", [2, Libvirt::Domain::VCPU_CONFIG])
+
+newdom.undefine
+
+newdom = conn.create_domain_xml($new_dom_xml)
+sleep 1
+
+expect_fail(newdom, Libvirt::Error, "vcpu config on transient domain", "vcpus_flags=", [2, Libvirt::Domain::VCPU_CONFIG])
+expect_fail(newdom, Libvirt::Error, "too many vcpus", "vcpus_flags=", [4, Libvirt::Domain::VCPU_LIVE])
+
+# FIXME: this doesn't work for some reason
+#expect_success(newdom, "vcpus to 1", "vcpus_flags=", [1, Libvirt::Domain::VCPU_LIVE])
+
+newdom.destroy
+
+# TESTGROUP: dom.memory_parameters=
+newdom = conn.define_domain_xml($new_dom_xml)
+
+expect_too_many_args(newdom, "memory_parameters=", 1, 2, 3)
+expect_too_few_args(newdom, "memory_parameters=")
+expect_invalid_arg_type(newdom, "memory_parameters=", 0)
+expect_fail(newdom, ArgumentError, "empty array", "memory_parameters=", [])
+expect_invalid_arg_type(newdom, "memory_parameters=", [1, 0])
+expect_invalid_arg_type(newdom, "memory_parameters=", [{}, "foo"])
+
+begin
+ newdom.memory_parameters={"soft_limit" => 9007199254740999, "swap_hard_limit" => 9007199254740999}
+rescue NoMethodError
+ puts_skipped "dom.memory_parameters= does not exist"
+rescue Libvirt::RetrieveError
+ # this may not be supported (if cgroups aren't configured), so skip it
+ puts_skipped "memory_parameters= not supported"
+end
+
+newdom.undefine
+
+# TESTGROUP: dom.memory_parameters
+newdom = conn.define_domain_xml($new_dom_xml)
+
+expect_too_many_args(newdom, "memory_parameters", 1, 2)
+
+begin
+ newdom.memory_parameters
+ puts_ok "dom.memory_parameters succeeded"
+rescue NoMethodError
+ puts_skipped "memory_parameters does not exist"
+rescue Libvirt::RetrieveError
+ # this may not be supported (if cgroups aren't configured), so skip it
+ puts_skipped "memory_parameters not supported"
+end
+
+newdom.undefine
+
+# TESTGROUP: dom.blkio_parameters=
+newdom = conn.define_domain_xml($new_dom_xml)
+
+expect_too_many_args(newdom, "blkio_parameters=", 1, 2, 3)
+expect_too_few_args(newdom, "blkio_parameters=")
+expect_invalid_arg_type(newdom, "blkio_parameters=", 0)
+expect_fail(newdom, ArgumentError, "empty array", "blkio_parameters=", [])
+expect_invalid_arg_type(newdom, "blkio_parameters=", [1, 0])
+expect_invalid_arg_type(newdom, "blkio_parameters=", [{}, "foo"])
+
+begin
+ newdom.blkio_parameters={"weight" => 1}
+rescue NoMethodError
+ puts_skipped "blkio_parameters= does not exist"
+rescue Libvirt::RetrieveError
+ # this may not be supported (if cgroups aren't configured), so skip it
+ puts_skipped "blkio_parameters= not supported"
+end
+
+newdom.undefine
+
+# TESTGROUP: dom.blkio_parameters
+newdom = conn.define_domain_xml($new_dom_xml)
+
+expect_too_many_args(newdom, "blkio_parameters", 1, 2)
+
+begin
+ newdom.blkio_parameters
+ puts_ok "dom.blkio_parameters succeeded"
+rescue NoMethodError
+ puts_skipped "blkio_parameters does not exist"
+rescue Libvirt::RetrieveError
+ # this may not be supported (if cgroups aren't configured), so skip it
+ puts_skipped "blkio_parameters not supported"
+end
+
+newdom.undefine
+
+# TESTGROUP: dom.open_console
+newdom = conn.create_domain_xml(new_dom_xml)
+stream = conn.stream
+
+expect_too_many_args(newdom, "open_console", 1, 2, 3, 4)
+expect_too_few_args(newdom, "open_console")
+expect_too_few_args(newdom, "open_console", 1)
+expect_invalid_arg_type(newdom, "open_console", 1, stream)
+expect_invalid_arg_type(newdom, "open_console", "pty", 1)
+expect_invalid_arg_type(newdom, "open_console", "pty", stream, "wow")
+
+expect_success(newdom, "device and stream args", "open_console", "pty", stream)
+
+newdom.destroy
+
+conn.close
+
+finish_tests
diff --git a/tests/test_interface.rb b/tests/test_interface.rb
new file mode 100644
index 0000000..b921042
--- /dev/null
+++ b/tests/test_interface.rb
@@ -0,0 +1,106 @@
+#!/usr/bin/ruby
+
+# Test the interface methods the bindings support
+
+$: << File.dirname(__FILE__)
+
+require 'libvirt'
+require 'test_utils.rb'
+
+def find_valid_iface(conn)
+ conn.list_interfaces.each do |ifname|
+ iface = conn.lookup_interface_by_name(ifname)
+ if iface.mac == "00:00:00:00:00:00"
+ next
+ end
+ return iface
+ end
+end
+
+conn = Libvirt::open("qemu:///system")
+
+# test setup
+begin
+ `rm -f /etc/sysconfig/network-scripts/ifcfg-ruby-libvirt-tester`
+ `brctl delbr ruby-libvirt-tester >& /dev/null`
+rescue
+end
+
+# TESTGROUP: iface.undefine
+newiface = conn.define_interface_xml($new_interface_xml)
+
+expect_too_many_args(newiface, "undefine", 1)
+
+expect_success(newiface, "no args", "undefine")
+
+# TESTGROUP: iface.create
+newiface = conn.define_interface_xml($new_interface_xml)
+
+expect_too_many_args(newiface, "create", 1, 2)
+expect_invalid_arg_type(newiface, "create", 'foo')
+
+#expect_success(newiface, "no args", "create")
+
+#expect_fail(newiface, Libvirt::Error, "on already running interface", "create")
+
+#newiface.destroy
+newiface.undefine
+
+# TESTGROUP: iface.destroy
+newiface = conn.define_interface_xml($new_interface_xml)
+
+expect_too_many_args(newiface, "destroy", 1, 2)
+expect_invalid_arg_type(newiface, "destroy", 'foo')
+
+expect_success(newiface, "no args", "destroy")
+
+newiface.undefine
+
+# TESTGROUP: iface.active?
+newiface = conn.define_interface_xml($new_interface_xml)
+
+expect_too_many_args(newiface, "active?", 1)
+
+expect_success(newiface, "no args", "active?") {|x| x == false}
+
+#newiface.create
+#expect_success(newiface, "no args", "active?") {|x| x == true}
+
+#newiface.destroy
+newiface.undefine
+
+# TESTGROUP: iface.name
+newiface = conn.define_interface_xml($new_interface_xml)
+
+expect_too_many_args(newiface, "name", 1)
+
+expect_success(newiface, "no args", "name") {|x| x == "ruby-libvirt-tester"}
+
+newiface.undefine
+
+# TESTGROUP: iface.mac
+testiface = find_valid_iface(conn)
+if not testiface.nil?
+ expect_too_many_args(testiface, "mac", 1)
+
+ expect_success(testiface, "no args", "mac") {|x| x == testiface.mac}
+end
+
+# TESTGROUP: iface.xml_desc
+testiface = find_valid_iface(conn)
+if not testiface.nil?
+ expect_too_many_args(testiface, "xml_desc", 1, 2)
+ expect_invalid_arg_type(testiface, "xml_desc", "foo")
+ expect_success(testiface, "no args", "xml_desc")
+end
+
+# TESTGROUP: iface.free
+newiface = conn.define_interface_xml($new_interface_xml)
+newiface.undefine
+expect_too_many_args(newiface, "free", 1)
+
+expect_success(newiface, "no args", "free")
+
+conn.close
+
+finish_tests
diff --git a/tests/test_network.rb b/tests/test_network.rb
new file mode 100644
index 0000000..dbe6a0e
--- /dev/null
+++ b/tests/test_network.rb
@@ -0,0 +1,166 @@
+#!/usr/bin/ruby
+
+# Test the network methods the bindings support
+
+$: << File.dirname(__FILE__)
+
+require 'libvirt'
+require 'test_utils.rb'
+
+conn = Libvirt::open("qemu:///system")
+
+# initial cleanup for previous run
+begin
+ oldnet = conn.lookup_network_by_name("ruby-libvirt-tester")
+ oldnet.destroy
+ oldnet.undefine
+rescue
+ # in case we didn't find it, don't do anything
+end
+
+# TESTGROUP: net.undefine
+newnet = conn.define_network_xml($new_net_xml)
+
+expect_too_many_args(newnet, "undefine", 1)
+
+expect_success(newnet, "no args", "undefine")
+
+# TESTGROUP: net.create
+newnet = conn.define_network_xml($new_net_xml)
+
+expect_too_many_args(newnet, "create", 1)
+
+expect_success(newnet, "no args", "create")
+
+expect_fail(newnet, Libvirt::Error, "on already running network", "create")
+
+newnet.destroy
+newnet.undefine
+
+# TESTGROUP: net.destroy
+newnet = conn.create_network_xml($new_net_xml)
+
+expect_too_many_args(newnet, "destroy", 1)
+
+expect_success(newnet, "no args", "destroy")
+
+# TESTGROUP: net.name
+newnet = conn.create_network_xml($new_net_xml)
+
+expect_too_many_args(newnet, "name", 1)
+
+expect_success(newnet, "no args", "name") {|x| x == "ruby-libvirt-tester"}
+
+newnet.destroy
+
+# TESTGROUP: net.uuid
+newnet = conn.create_network_xml($new_net_xml)
+
+expect_too_many_args(newnet, "uuid", 1)
+
+expect_success(newnet, "no args", "uuid") {|x| x == $NETWORK_UUID}
+
+newnet.destroy
+
+# TESTGROUP: net.xml_desc
+newnet = conn.create_network_xml($new_net_xml)
+
+expect_too_many_args(newnet, "xml_desc", 1, 2)
+expect_invalid_arg_type(newnet, "xml_desc", "foo")
+
+expect_success(newnet, "no args", "xml_desc")
+
+newnet.destroy
+
+# TESTGROUP: net.bridge_name
+newnet = conn.create_network_xml($new_net_xml)
+
+expect_too_many_args(newnet, "bridge_name", 1)
+
+expect_success(newnet, "no args", "bridge_name") {|x| x == "rubybr0"}
+
+newnet.destroy
+
+# TESTGROUP: net.autostart?
+newnet = conn.define_network_xml($new_net_xml)
+
+expect_too_many_args(newnet, "autostart?", 1)
+
+expect_success(newnet, "no args", "autostart?") {|x| x == false}
+
+newnet.autostart = true
+
+expect_success(newnet, "no args", "autostart?") {|x| x == true}
+
+newnet.undefine
+
+# TESTGROUP: net.autostart=
+newnet = conn.define_network_xml($new_net_xml)
+
+expect_too_many_args(newnet, "autostart=", 1, 2)
+expect_invalid_arg_type(newnet, "autostart=", 'foo')
+expect_invalid_arg_type(newnet, "autostart=", nil)
+expect_invalid_arg_type(newnet, "autostart=", 1234)
+
+expect_success(newnet, "boolean arg", "autostart=", true)
+if not newnet.autostart?
+ puts_fail "net.autostart= did not set autostart to true"
+else
+ puts_ok "net.autostart= set autostart to true"
+end
+
+expect_success(newnet, "boolean arg", "autostart=", false)
+if newnet.autostart?
+ puts_fail "net.autostart= did not set autostart to false"
+else
+ puts_ok "net.autostart= set autostart to false"
+end
+
+newnet.undefine
+
+# TESTGROUP: net.free
+newnet = conn.define_network_xml($new_net_xml)
+newnet.undefine
+expect_too_many_args(newnet, "free", 1)
+
+expect_success(newnet, "no args", "free")
+
+# TESTGROUP: net.active?
+newnet = conn.create_network_xml($new_net_xml)
+
+expect_too_many_args(newnet, "active?", 1)
+
+expect_success(newnet, "no args", "active?") {|x| x == true}
+
+newnet.destroy
+
+newnet = conn.define_network_xml($new_net_xml)
+
+expect_success(newnet, "no args", "active?") {|x| x == false}
+
+newnet.create
+
+expect_success(newnet, "no args", "active?") {|x| x == true}
+
+newnet.destroy
+newnet.undefine
+
+# TESTGROUP: net.persistent?
+newnet = conn.create_network_xml($new_net_xml)
+
+expect_too_many_args(newnet, "persistent?", 1)
+
+expect_success(newnet, "no args", "persistent?") {|x| x == false}
+
+newnet.destroy
+
+newnet = conn.define_network_xml($new_net_xml)
+
+expect_success(newnet, "no args", "persistent?") {|x| x == true}
+
+newnet.undefine
+
+
+conn.close
+
+finish_tests
diff --git a/tests/test_nodedevice.rb b/tests/test_nodedevice.rb
new file mode 100644
index 0000000..bd05cbb
--- /dev/null
+++ b/tests/test_nodedevice.rb
@@ -0,0 +1,80 @@
+#!/usr/bin/ruby
+
+# Test the nodedevice methods the bindings support
+
+$: << File.dirname(__FILE__)
+
+require 'libvirt'
+require 'test_utils.rb'
+
+conn = Libvirt::open("qemu:///system")
+
+# TESTGROUP: nodedevice.name
+testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
+
+expect_too_many_args(testnode, "name", 1)
+expect_success(testnode, "no args", "name")
+
+# TESTGROUP: nodedevice.parent
+testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
+
+expect_too_many_args(testnode, "parent", 1)
+expect_success(testnode, "no args", "parent")
+
+# TESTGROUP: nodedevice.num_of_caps
+testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
+
+expect_too_many_args(testnode, "num_of_caps", 1)
+expect_success(testnode, "no args", "num_of_caps")
+
+# TESTGROUP: nodedevice.list_caps
+testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
+
+expect_too_many_args(testnode, "list_caps", 1)
+expect_success(testnode, "no args", "list_caps")
+
+# TESTGROUP: nodedevice.xml_desc
+testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
+
+expect_too_many_args(testnode, "xml_desc", 1, 2)
+expect_invalid_arg_type(testnode, "xml_desc", 'foo')
+expect_success(testnode, "no args", "xml_desc")
+
+# TESTGROUP: nodedevice.detach
+testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
+
+expect_too_many_args(testnode, "detach", 1)
+
+#expect_success(testnode, "no args", "detach")
+
+# TESTGROUP: nodedevice.reattach
+testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
+
+expect_too_many_args(testnode, "reattach", 1)
+
+#expect_success(testnode, "no args", "reattach")
+
+# TESTGROUP: nodedevice.reset
+testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
+
+expect_too_many_args(testnode, "reset", 1)
+
+#expect_success(testnode, "no args", "reset")
+
+# TESTGROUP: nodedevice.destroy
+testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
+
+expect_too_many_args(testnode, "destroy", 1)
+
+#expect_success(testnode, "no args", "destroy")
+
+# TESTGROUP: nodedevice.free
+testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
+
+expect_too_many_args(testnode, "free", 1)
+
+expect_success(testnode, "no args", "free")
+
+conn.close
+
+finish_tests
diff --git a/tests/test_nwfilter.rb b/tests/test_nwfilter.rb
new file mode 100644
index 0000000..a059aee
--- /dev/null
+++ b/tests/test_nwfilter.rb
@@ -0,0 +1,56 @@
+#!/usr/bin/ruby
+
+# Test the nwfilter methods the bindings support
+
+$: << File.dirname(__FILE__)
+
+require 'libvirt'
+require 'test_utils.rb'
+
+conn = Libvirt::open("qemu:///system")
+
+# TESTGROUP: nwfilter.undefine
+newnw = conn.define_nwfilter_xml($new_nwfilter_xml)
+
+expect_too_many_args(newnw, "undefine", 1)
+
+expect_success(newnw, "no args", "undefine")
+
+# TESTGROUP: nwfilter.name
+newnw = conn.define_nwfilter_xml($new_nwfilter_xml)
+
+expect_too_many_args(newnw, "name", 1)
+
+expect_success(newnw, "no args", "name") {|x| x == "ruby-libvirt-tester"}
+
+newnw.undefine
+
+# TESTGROUP: nwfilter.uuid
+newnw = conn.define_nwfilter_xml($new_nwfilter_xml)
+
+expect_too_many_args(newnw, "uuid", 1)
+
+expect_success(newnw, "no args", "uuid") {|x| x == $NWFILTER_UUID}
+
+newnw.undefine
+
+# TESTGROUP: nwfilter.xml_desc
+newnw = conn.define_nwfilter_xml($new_nwfilter_xml)
+
+expect_too_many_args(newnw, "xml_desc", 1, 2)
+expect_invalid_arg_type(newnw, "xml_desc", "foo")
+
+expect_success(newnw, "no args", "xml_desc")
+
+newnw.undefine
+
+# TESTGROUP: nwfilter.free
+newnw = conn.define_nwfilter_xml($new_nwfilter_xml)
+newnw.undefine
+expect_too_many_args(newnw, "free", 1)
+
+expect_success(newnw, "no args", "free")
+
+conn.close
+
+finish_tests
diff --git a/tests/test_open.rb b/tests/test_open.rb
new file mode 100644
index 0000000..6b57ada
--- /dev/null
+++ b/tests/test_open.rb
@@ -0,0 +1,197 @@
+#!/usr/bin/ruby
+
+# Test the open calls that the bindings support
+
+$: << File.dirname(__FILE__)
+
+require 'libvirt'
+require 'test_utils.rb'
+
+def expect_connect_error(func, args)
+ expect_fail(Libvirt, Libvirt::ConnectionError, "invalid driver", func, *args)
+end
+
+# TESTGROUP: Libvirt::version
+expect_too_many_args(Libvirt, "version", "test", 1)
+expect_invalid_arg_type(Libvirt, "version", 1)
+expect_success(Libvirt, "no args", "version") {|x| x.class == Array and x.length == 2}
+expect_success(Libvirt, "nil arg", "version", nil) {|x| x.class == Array and x.length == 2}
+expect_success(Libvirt, "Test arg", "version", "Test") {|x| x.class == Array and x.length == 2}
+
+# TESTGROUP: Libvirt::open
+expect_too_many_args(Libvirt, "open", "qemu:///system", 1)
+expect_connect_error("open", "foo:///system")
+conn = expect_success(Libvirt, "no args", "open") {|x| x.class == Libvirt::Connect }
+conn.close
+conn = expect_success(Libvirt, "qemu:///system", "open", "qemu:///system") {|x| x.class == Libvirt::Connect }
+conn.close
+conn = expect_success(Libvirt, "nil arg", "open", nil) {|x| x.class == Libvirt::Connect }
+conn.close
+
+# TESTGROUP: Libvirt::open_read_only
+expect_too_many_args(Libvirt, "open_read_only", "qemu:///system", 1)
+expect_connect_error("open_read_only", "foo:///system")
+conn = expect_success(Libvirt, "no args", "open_read_only") {|x| x.class == Libvirt::Connect }
+conn.close
+conn = expect_success(Libvirt, "qemu:///system", "open_read_only", "qemu:///system") {|x| x.class == Libvirt::Connect }
+conn.close
+conn = expect_success(Libvirt, "nil arg", "open_read_only", nil) {|x| x.class == Libvirt::Connect }
+conn.close
+
+# TESTGROUP: Libvirt::open_auth
+expect_too_many_args(Libvirt, "open_auth", "qemu:///system", [], "hello there", 1, 2)
+expect_connect_error("open_auth", "foo:///system")
+expect_invalid_arg_type(Libvirt, "open_auth", 1)
+expect_invalid_arg_type(Libvirt, "open_auth", "qemu:///system", [], "hello", "foo")
+
+conn = expect_success(Libvirt, "no args", "open_auth") {|x| x.class == Libvirt::Connect }
+conn.close
+
+conn = expect_success(Libvirt, "uri arg", "open_auth", "qemu:///system") {|x| x.class == Libvirt::Connect }
+conn.close
+
+conn = expect_success(Libvirt, "uri and empty cred args", "open_auth", "qemu:///system", []) {|x| x.class == Libvirt::Connect }
+conn.close
+
+conn = expect_success(Libvirt, "uri and full cred args", "open_auth", "qemu:///system", [Libvirt::CRED_AUTHNAME, Libvirt::CRED_PASSPHRASE]) {|x| x.class == Libvirt::Connect }
+conn.close
+
+conn = expect_success(Libvirt, "uri, full cred, and user args", "open_auth", "qemu:///system", [Libvirt::CRED_AUTHNAME, Libvirt::CRED_PASSPHRASE], "hello") {|x| x.class == Libvirt::Connect }
+conn.close
+
+# equivalent to "expect_success"
+begin
+ conn = Libvirt::open_auth("qemu:///system", [Libvirt::CRED_AUTHNAME, Libvirt::CRED_PASSPHRASE], "hello") do |cred|
+ if not cred["userdata"].nil?
+ puts "userdata is #{cred["userdata"]}"
+ end
+ if cred["type"] == Libvirt::CRED_AUTHNAME
+ print "#{cred['prompt']}: "
+ res = gets
+ # strip off the \n
+ res = res[0..-2]
+ elsif cred["type"] == Libvirt::CRED_PASSPHRASE
+ print "#{cred['prompt']}: "
+ res = gets
+ res = res[0..-2]
+ else
+ raise "Unsupported credential #{cred['type']}"
+ end
+ res
+ end
+
+ puts_ok "open_auth uri, creds, userdata, auth block succeeded"
+ conn.close
+rescue NoMethodError
+ puts_skipped "open_auth does not exist"
+rescue => e
+ puts_fail "open_auth uri, creds, userdata, auth block expected to succeed, threw #{e.class.to_s}: #{e.to_s}"
+end
+
+# equivalent to "expect_success"
+begin
+ conn = Libvirt::open_auth("qemu:///system", [Libvirt::CRED_AUTHNAME, Libvirt::CRED_PASSPHRASE], "hello", Libvirt::CONNECT_RO) do |cred|
+ if not cred["userdata"].nil?
+ puts "userdata is #{cred["userdata"]}"
+ end
+ if cred["type"] == Libvirt::CRED_AUTHNAME
+ print "#{cred['prompt']}: "
+ res = gets
+ # strip off the \n
+ res = res[0..-2]
+ elsif cred["type"] == Libvirt::CRED_PASSPHRASE
+ print "#{cred['prompt']}: "
+ res = gets
+ res = res[0..-2]
+ else
+ raise "Unsupported credential #{cred['type']}"
+ end
+ res
+ end
+
+ puts_ok "open_auth uri, creds, userdata, R/O flag, auth block succeeded"
+ conn.close
+rescue NoMethodError
+ puts_skipped "open_auth does not exist"
+rescue => e
+ puts_fail "open_auth uri, creds, userdata, R/O flag, auth block expected to succeed, threw #{e.class.to_s}: #{e.to_s}"
+end
+
+# TESTGROUP: Libvirt::event_invoke_handle_callback
+conn = Libvirt::open("qemu:///system")
+
+expect_too_many_args(Libvirt, "event_invoke_handle_callback", 1, 2, 3, 4, 5)
+expect_too_few_args(Libvirt, "event_invoke_handle_callback")
+expect_too_few_args(Libvirt, "event_invoke_handle_callback", 1)
+expect_too_few_args(Libvirt, "event_invoke_handle_callback", 1, 2)
+expect_too_few_args(Libvirt, "event_invoke_handle_callback", 1, 2, 3)
+# this is a bit bizarre; I am constructing a bogus hash to pass as the 4th
+# parameter to event_invoke_handle_callback. In a real situation, I would
+# have been given this hash from libvirt earlier, and just pass it on. I
+# don't want all of that complexity here, though, so I create the bogus hash.
+# One caveat; the data inside the hash *must* be of type T_DATA, so I pass in
+# a fake conn object just to appease the type checker (so I can test out the
+# other arguments properly)
+expect_invalid_arg_type(Libvirt, "event_invoke_handle_callback", "hello", 1, 1, { "libvirt_cb" => conn, "opaque" => conn })
+expect_invalid_arg_type(Libvirt, "event_invoke_handle_callback", 1, "hello", 1, { "libvirt_cb" => conn, "opaque" => conn })
+expect_invalid_arg_type(Libvirt, "event_invoke_handle_callback", 1, 1, "hello", { "libvirt_cb" => conn, "opaque" => conn })
+expect_invalid_arg_type(Libvirt, "event_invoke_handle_callback", 1, 1, 1, { "libvirt_cb" => "hello", "opaque" => conn })
+expect_invalid_arg_type(Libvirt, "event_invoke_handle_callback", 1, 1, 1, { "libvirt_cb" => conn, "opaque" => "hello" })
+conn.close
+
+# TESTGROUP: Libvirt::event_invoke_timeout_callback
+conn = Libvirt::open("qemu:///system")
+
+expect_too_many_args(Libvirt, "event_invoke_timeout_callback", 1, 2, 3)
+expect_too_few_args(Libvirt, "event_invoke_timeout_callback")
+expect_too_few_args(Libvirt, "event_invoke_timeout_callback", 1)
+# this is a bit bizarre; I am constructing a bogus hash to pass as the 4th
+# parameter to event_invoke_handle_callback. In a real situation, I would
+# have been given this hash from libvirt earlier, and just pass it on. I
+# don't want all of that complexity here, though, so I create the bogus hash.
+# One caveat; the data inside the hash *must* be of type T_DATA, so I pass in
+# a fake conn object just to appease the type checker (so I can test out the
+# other arguments properly)
+expect_invalid_arg_type(Libvirt, "event_invoke_timeout_callback", "hello", { "libvirt_cb" => conn, "opaque" => conn })
+expect_invalid_arg_type(Libvirt, "event_invoke_timeout_callback", 1, { "libvirt_cb" => "hello", "opaque" => conn })
+expect_invalid_arg_type(Libvirt, "event_invoke_timeout_callback", 1, { "libvirt_cb" => conn, "opaque" => "hello" })
+conn.close
+
+# TESTGROUP: Libvirt::event_register_impl
+expect_too_many_args(Libvirt, "event_register_impl", 1, 2, 3, 4, 5, 6, 7)
+expect_invalid_arg_type(Libvirt, "event_register_impl", 1)
+
+# symbol callbacks
+def virEventAddHandleImpl(fd, events, opaque)
+end
+def virEventUpdateHandleImpl(watch, event)
+end
+def virEventRemoveHandleImpl(handleID)
+end
+def virEventAddTimerImpl(interval, opaque)
+end
+def virEventUpdateTimerImpl(timer, timeout)
+end
+def virEventRemoveTimerImpl(timerID)
+end
+
+# proc callbacks
+virEventAddHandleProc = lambda {|fd, events, opaque|
+}
+virEventUpdateHandleProc = lambda {|watch, event|
+}
+virEventRemoveHandleProc = lambda {|handleID|
+}
+virEventAddTimerProc = lambda {|interval, opaque|
+}
+virEventUpdateTimerProc = lambda {|timer, timeout|
+}
+virEventRemoveTimerProc = lambda {|timerID|
+}
+
+expect_success(Libvirt, "all Symbol callbacks", "event_register_impl", :virEventAddHandleImpl, :virEventUpdateHandleImpl, :virEventRemoveHandleImpl, :virEventAddTimerImpl, :virEventUpdateTimerImpl, :virEventRemoveTimerImpl)
+expect_success(Libvirt, "unregister all callbacks", "event_register_impl", nil, nil, nil, nil, nil, nil)
+expect_success(Libvirt, "all Proc callbacks", "event_register_impl", virEventAddHandleProc, virEventUpdateHandleProc, virEventRemoveHandleProc, virEventAddTimerProc, virEventUpdateTimerProc, virEventRemoveTimerProc)
+expect_success(Libvirt, "unregister all callbacks", "event_register_impl")
+
+finish_tests
diff --git a/tests/test_secret.rb b/tests/test_secret.rb
new file mode 100644
index 0000000..aac2446
--- /dev/null
+++ b/tests/test_secret.rb
@@ -0,0 +1,89 @@
+#!/usr/bin/ruby
+
+# Test the secret methods the bindings support
+
+$: << File.dirname(__FILE__)
+
+require 'libvirt'
+require 'test_utils.rb'
+
+conn = Libvirt::open("qemu:///system")
+
+# TESTGROUP: secret.uuid
+newsecret = conn.define_secret_xml($new_secret_xml)
+
+expect_too_many_args(newsecret, "uuid", 1)
+
+expect_success(newsecret, "no args", "uuid") {|x| x == $SECRET_UUID}
+
+newsecret.undefine
+
+# TESTGROUP: secret.usagetype
+newsecret = conn.define_secret_xml($new_secret_xml)
+
+expect_too_many_args(newsecret, "usagetype", 1)
+
+expect_success(newsecret, "no args", "usagetype") {|x| x == Libvirt::Secret::USAGE_TYPE_VOLUME}
+
+newsecret.undefine
+
+# TESTGROUP: secret.usageid
+newsecret = conn.define_secret_xml($new_secret_xml)
+
+expect_too_many_args(newsecret, "usageid", 1)
+
+expect_success(newsecret, "no args", "usageid")
+
+newsecret.undefine
+
+# TESTGROUP: secret.xml_desc
+newsecret = conn.define_secret_xml($new_secret_xml)
+
+expect_too_many_args(newsecret, "xml_desc", 1, 2)
+expect_invalid_arg_type(newsecret, "xml_desc", "foo")
+
+expect_success(newsecret, "no args", "xml_desc")
+
+newsecret.undefine
+
+# TESTGROUP: secret.set_value
+newsecret = conn.define_secret_xml($new_secret_xml)
+
+expect_too_many_args(newsecret, "set_value", 1, 2, 3)
+expect_too_few_args(newsecret, "set_value")
+expect_invalid_arg_type(newsecret, "set_value", 1)
+expect_invalid_arg_type(newsecret, "set_value", "foo", "bar")
+
+expect_success(newsecret, "value arg", "set_value", "foo")
+
+newsecret.undefine
+
+# TESTGROUP: secret.get_value
+newsecret = conn.define_secret_xml($new_secret_xml)
+newsecret.set_value("foo")
+
+expect_too_many_args(newsecret, "get_value", 1, 2)
+expect_invalid_arg_type(newsecret, "get_value", 'foo')
+
+expect_success(newsecret, "no args", "get_value") {|x| x == 'foo'}
+
+newsecret.undefine
+
+# TESTGROUP: secret.undefine
+newsecret = conn.define_secret_xml($new_secret_xml)
+
+expect_too_many_args(newsecret, "undefine", 1)
+
+expect_success(newsecret, "no args", "undefine")
+
+# TESTGROUP: secret.free
+newsecret = conn.define_secret_xml($new_secret_xml)
+newsecret.undefine
+
+expect_too_many_args(newsecret, "free", 1)
+
+expect_success(newsecret, "no args", "free")
+
+conn.close
+
+finish_tests
diff --git a/tests/test_storage.rb b/tests/test_storage.rb
new file mode 100644
index 0000000..63fdcbe
--- /dev/null
+++ b/tests/test_storage.rb
@@ -0,0 +1,423 @@
+#!/usr/bin/ruby
+
+# Test the storage methods the bindings support
+
+$: << File.dirname(__FILE__)
+
+require 'libvirt'
+require 'test_utils.rb'
+
+conn = Libvirt::open("qemu:///system")
+
+begin
+ oldpool = conn.lookup_storage_pool_by_name("ruby-libvirt-tester")
+ oldpool.destroy
+ oldpool.undefine
+rescue
+ # in case we didn't find it, don't do anything
+end
+
+# test setup
+`rm -rf #{$POOL_PATH}; mkdir #{$POOL_PATH} ; echo $?`
+
+new_storage_vol_xml = <<EOF
+<volume>
+ <name>test.img</name>
+ <allocation>0</allocation>
+ <capacity unit="G">1</capacity>
+ <target>
+ <path>/tmp/ruby-libvirt-tester/test.img</path>
+ </target>
+</volume>
+EOF
+
+new_storage_vol_xml_2 = <<EOF
+<volume>
+ <name>test2.img</name>
+ <allocation>0</allocation>
+ <capacity unit="G">5</capacity>
+ <target>
+ <path>/tmp/ruby-libvirt-tester/test2.img</path>
+ </target>
+</volume>
+EOF
+
+# TESTGROUP: vol.pool
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+
+newvol = newpool.create_volume_xml(new_storage_vol_xml)
+
+expect_too_many_args(newvol, "pool", 1)
+
+expect_success(newvol, "no args", "pool")
+
+newvol.delete
+
+newpool.destroy
+
+# TESTGROUP: pool.build
+newpool = conn.define_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "build", 1, 2)
+expect_invalid_arg_type(newpool, "build", 'foo')
+
+expect_success(newpool, "no args", "build")
+
+newpool.undefine
+
+# TESTGROUP: pool.undefine
+newpool = conn.define_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "undefine", 1)
+
+expect_success(newpool, "no args", "undefine")
+
+# TESTGROUP: pool.create
+newpool = conn.define_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "create", 1, 2)
+expect_invalid_arg_type(newpool, "create", 'foo')
+
+expect_success(newpool, "no args", "create")
+
+newpool.destroy
+newpool.undefine
+
+# TESTGROUP: pool.destroy
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "destroy", 1)
+
+expect_success(newpool, "no args", "destroy")
+
+# TESTGROUP: pool.delete
+newpool = conn.define_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "delete", 1, 2)
+expect_invalid_arg_type(newpool, "delete", 'foo')
+
+expect_success(newpool, "no args", "delete")
+
+`mkdir /tmp/ruby-libvirt-tester`
+
+newpool.undefine
+
+# TESTGROUP: pool.refresh
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "refresh", 1, 2)
+expect_invalid_arg_type(newpool, "refresh", 'foo')
+
+expect_success(newpool, "no args", "refresh")
+
+newpool.destroy
+
+# TESTGROUP: pool.name
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "name", 1)
+
+expect_success(newpool, "no args", "name") {|x| x == "ruby-libvirt-tester"}
+
+newpool.destroy
+
+# TESTGROUP: pool.uuid
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "uuid", 1)
+
+expect_success(newpool, "no args", "uuid") {|x| x == $POOL_UUID}
+
+newpool.destroy
+
+# TESTGROUP: pool.info
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "info", 1)
+
+expect_success(newpool, "no args", "info")
+
+newpool.destroy
+
+# TESTGROUP: pool.xml_desc
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "xml_desc", 1, 2)
+expect_invalid_arg_type(newpool, "xml_desc", "foo")
+
+expect_success(newpool, "no args", "xml_desc")
+
+newpool.destroy
+
+# TESTGROUP: pool.autostart?
+newpool = conn.define_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "autostart?", 1)
+
+expect_success(newpool, "no args", "autostart?") {|x| x == false}
+
+newpool.autostart = true
+
+expect_success(newpool, "no args", "autostart?") {|x| x == true}
+
+newpool.undefine
+
+# TESTGROUP: pool.autostart=
+newpool = conn.define_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "autostart=", 1, 2)
+expect_invalid_arg_type(newpool, "autostart=", 'foo')
+expect_invalid_arg_type(newpool, "autostart=", nil)
+expect_invalid_arg_type(newpool, "autostart=", 1234)
+
+expect_success(newpool, "no args", "autostart=", true)
+if not newpool.autostart?
+ puts_fail "pool.autostart= did not set autostart to true"
+else
+ puts_ok "pool.autostart= set autostart to true"
+end
+
+expect_success(newpool, "no args", "autostart=", false)
+if newpool.autostart?
+ puts_fail "pool.autostart= did not set autostart to false"
+else
+ puts_ok "pool.autostart= set autostart to false"
+end
+
+newpool.undefine
+
+# TESTGROUP: pool.num_of_volumes
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "num_of_volumes", 1)
+
+expect_success(newpool, "no args", "num_of_volumes") {|x| x == 0}
+
+newpool.destroy
+
+# TESTGROUP: pool.list_volumes
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "list_volumes", 1)
+
+expect_success(newpool, "no args", "list_volumes")
+
+newpool.destroy
+
+# TESTGROUP: pool.free
+newpool = conn.define_storage_pool_xml($new_storage_pool_xml)
+newpool.undefine
+expect_too_many_args(newpool, "free", 1)
+
+expect_success(newpool, "no args", "free")
+
+# TESTGROUP: pool.lookup_volume_by_name
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+newvol = newpool.create_volume_xml(new_storage_vol_xml)
+
+expect_too_many_args(newpool, "lookup_volume_by_name", 1, 2)
+expect_too_few_args(newpool, "lookup_volume_by_name")
+expect_invalid_arg_type(newpool, "lookup_volume_by_name", 1);
+expect_invalid_arg_type(newpool, "lookup_volume_by_name", nil);
+expect_fail(newpool, Libvirt::RetrieveError, "non-existent name arg", "lookup_volume_by_name", "foobarbazsucker")
+
+expect_success(newpool, "name arg", "lookup_volume_by_name", "test.img")
+
+newvol.delete
+newpool.destroy
+
+# TESTGROUP: pool.lookup_volume_by_key
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+newvol = newpool.create_volume_xml(new_storage_vol_xml)
+
+expect_too_many_args(newpool, "lookup_volume_by_key", 1, 2)
+expect_too_few_args(newpool, "lookup_volume_by_key")
+expect_invalid_arg_type(newpool, "lookup_volume_by_key", 1);
+expect_invalid_arg_type(newpool, "lookup_volume_by_key", nil);
+expect_fail(newpool, Libvirt::RetrieveError, "non-existent key arg", "lookup_volume_by_key", "foobarbazsucker")
+
+expect_success(newpool, "name arg", "lookup_volume_by_key", newvol.key)
+
+newvol.delete
+newpool.destroy
+
+# TESTGROUP: pool.lookup_volume_by_path
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+newvol = newpool.create_volume_xml(new_storage_vol_xml)
+
+expect_too_many_args(newpool, "lookup_volume_by_path", 1, 2)
+expect_too_few_args(newpool, "lookup_volume_by_path")
+expect_invalid_arg_type(newpool, "lookup_volume_by_path", 1);
+expect_invalid_arg_type(newpool, "lookup_volume_by_path", nil);
+expect_fail(newpool, Libvirt::RetrieveError, "non-existent path arg", "lookup_volume_by_path", "foobarbazsucker")
+
+expect_success(newpool, "name arg", "lookup_volume_by_path", newvol.path)
+
+newvol.delete
+newpool.destroy
+
+# TESTGROUP: vol.name
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+newvol = newpool.create_volume_xml(new_storage_vol_xml)
+
+expect_too_many_args(newvol, "name", 1)
+
+expect_success(newvol, "no args", "name")
+
+newvol.delete
+newpool.destroy
+
+# TESTGROUP: vol.key
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+newvol = newpool.create_volume_xml(new_storage_vol_xml)
+
+expect_too_many_args(newvol, "key", 1)
+
+expect_success(newvol, "no args", "key")
+
+newvol.delete
+newpool.destroy
+
+# TESTGROUP: pool.create_volume_xml
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "create_volume_xml", new_storage_vol_xml, 0, 1)
+expect_too_few_args(newpool, "create_volume_xml")
+expect_invalid_arg_type(newpool, "create_volume_xml", nil)
+expect_invalid_arg_type(newpool, "create_volume_xml", 1)
+expect_invalid_arg_type(newpool, "create_volume_xml", new_storage_vol_xml, "foo")
+expect_fail(newpool, Libvirt::Error, "invalid xml", "create_volume_xml", "hello")
+
+expect_success(newpool, "storage volume XML", "create_volume_xml", new_storage_vol_xml)
+
+expect_fail(newpool, Libvirt::Error, "already existing domain", "create_volume_xml", new_storage_vol_xml)
+
+newvol.delete
+newpool.destroy
+
+# TESTGROUP: pool.create_volume_xml_from
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+newvol = newpool.create_volume_xml(new_storage_vol_xml)
+
+expect_too_many_args(newpool, "create_volume_xml_from", new_storage_vol_xml_2, 0, 1, 2)
+expect_too_few_args(newpool, "create_volume_xml_from")
+expect_invalid_arg_type(newpool, "create_volume_xml_from", 1, 2)
+expect_invalid_arg_type(newpool, "create_volume_xml_from", "foo", 2)
+expect_invalid_arg_type(newpool, "create_volume_xml_from", "foo", newvol, "bar")
+expect_fail(newpool, Libvirt::Error, "invalid xml", "create_volume_xml_from", "hello", newvol)
+
+newvol2 = expect_success(newpool, "storage volume XML", "create_volume_xml_from", new_storage_vol_xml_2, newvol)
+
+expect_fail(newpool, Libvirt::Error, "already existing domain", "create_volume_xml_from", new_storage_vol_xml_2, newvol)
+
+newvol2.delete
+newvol.delete
+newpool.destroy
+
+# TESTGROUP: pool.active?
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+
+expect_too_many_args(newpool, "active?", 1)
+
+expect_success(newpool, "no args", "active?") {|x| x == true}
+
+newpool.destroy
+
+newpool = conn.define_storage_pool_xml($new_storage_pool_xml)
+
+expect_success(newpool, "no args", "active?") {|x| x == false}
+
+newpool.create
+
+expect_success(newpool, "no args", "active?") {|x| x == true}
+
+newpool.destroy
+newpool.undefine
+
+# TESTGROUP: pool.persistent?
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+sleep 1
+
+expect_too_many_args(newpool, "persistent?", 1)
+
+expect_success(newpool, "no args", "persistent?") {|x| x == false}
+
+newpool.destroy
+
+newpool = conn.define_storage_pool_xml($new_storage_pool_xml)
+
+expect_success(newpool, "no args", "persistent?") {|x| x == true}
+
+newpool.undefine
+
+# TESTGROUP: vol.delete
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+newvol = newpool.create_volume_xml(new_storage_vol_xml)
+
+expect_too_many_args(newvol, "delete", 1, 2)
+expect_invalid_arg_type(newvol, "delete", 'foo')
+
+expect_success(newvol, "no args", "delete")
+
+newpool.destroy
+
+# TESTGROUP: vol.wipe
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+newvol = newpool.create_volume_xml(new_storage_vol_xml)
+
+expect_too_many_args(newvol, "wipe", 1, 2)
+expect_invalid_arg_type(newvol, "wipe", 'foo')
+
+expect_success(newvol, "no args", "wipe")
+
+newvol.delete
+newpool.destroy
+
+# TESTGROUP: vol.info
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+newvol = newpool.create_volume_xml(new_storage_vol_xml)
+
+expect_too_many_args(newvol, "info", 1)
+
+expect_success(newvol, "no args", "info")
+
+newvol.delete
+newpool.destroy
+
+# TESTGROUP: vol.xml_desc
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+newvol = newpool.create_volume_xml(new_storage_vol_xml)
+
+expect_too_many_args(newvol, "xml_desc", 1, 2)
+expect_invalid_arg_type(newvol, "xml_desc", "foo")
+
+expect_success(newvol, "no args", "xml_desc")
+
+newvol.delete
+newpool.destroy
+
+# TESTGROUP: vol.path
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+newvol = newpool.create_volume_xml(new_storage_vol_xml)
+
+expect_too_many_args(newvol, "path", 1)
+
+expect_success(newvol, "no args", "path")
+
+newvol.delete
+newpool.destroy
+
+# TESTGROUP: vol.free
+newpool = conn.create_storage_pool_xml($new_storage_pool_xml)
+newvol = newpool.create_volume_xml(new_storage_vol_xml)
+newvol.delete
+
+expect_too_many_args(newvol, "free", 1)
+
+expect_success(newvol, "no args", "free")
+
+newpool.destroy
+
+conn.close
+
+finish_tests
diff --git a/tests/test_utils.rb b/tests/test_utils.rb
new file mode 100644
index 0000000..cc0c856
--- /dev/null
+++ b/tests/test_utils.rb
@@ -0,0 +1,180 @@
+$FAIL = 0
+$SUCCESS = 0
+$SKIPPED = 0
+
+$GUEST_DISK = '/var/lib/libvirt/images/ruby-libvirt-tester.qcow2'
+$GUEST_UUID = "93a5c045-6457-2c09-e56f-927cdf34e17a"
+
+# XML data for later tests
+$new_dom_xml = <<EOF
+<domain type='kvm'>
+ <name>ruby-libvirt-tester</name>
+ <uuid>#{$GUEST_UUID}</uuid>
+ <memory>1048576</memory>
+ <currentMemory>1048576</currentMemory>
+ <vcpu>2</vcpu>
+ <os>
+ <type arch='x86_64'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <acpi/>
+ <apic/>
+ <pae/>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2'/>
+ <source file='#{$GUEST_DISK}'/>
+ <target dev='vda' bus='virtio'/>
+ </disk>
+ <interface type='bridge'>
+ <mac address='52:54:00:60:3c:95'/>
+ <source bridge='virbr0'/>
+ <model type='virtio'/>
+ <target dev='rl556'/>
+ </interface>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <target port='0'/>
+ </console>
+ <input type='mouse' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes' keymap='en-us'/>
+ <video>
+ <model type='cirrus' vram='9216' heads='1'/>
+ </video>
+ </devices>
+</domain>
+EOF
+
+# qemu command-line that roughly corresponds to the above XML
+$qemu_cmd_line = "/usr/bin/qemu-kvm -S -M pc-0.13 -enable-kvm -m 1024 -smp 1,sockets=1,cores=1,threads=1 -name ruby-libvirt-tester -uuid #{$GUEST_UUID} -nodefconfig -nodefaults -chardev socket,id=monitor,path=/var/lib/libvirt/qemu/ruby-libvirt-tester.monitor,server,nowait -mon chardev=monitor,mode=readline -rtc base=utc -boot c -chardev pty,id=serial0 -device isa-serial,chardev=serial0 -usb -vnc 127.0.0.1:0 -k en-us -vga cirrus -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5"
+
+$new_interface_xml = <<EOF
+<interface type="bridge" name="ruby-libvirt-tester">
+ <start mode="onboot"/>
+ <bridge delay="0">
+ </bridge>
+</interface>
+EOF
+
+$NETWORK_UUID = "04068860-d9a2-47c5-bc9d-9e047ae901da"
+$new_net_xml = <<EOF
+<network>
+ <name>ruby-libvirt-tester</name>
+ <uuid>#{$NETWORK_UUID}</uuid>
+ <forward mode='nat'/>
+ <bridge name='rubybr0' stp='on' delay='0' />
+ <ip address='192.168.134.1' netmask='255.255.255.0'>
+ <dhcp>
+ <range start='192.168.134.2' end='192.168.134.254' />
+ </dhcp>
+ </ip>
+</network>
+EOF
+
+$NWFILTER_UUID = "bd339530-134c-6d07-441a-17fb90dad807"
+$new_nwfilter_xml = <<EOF
+<filter name='ruby-libvirt-tester' chain='ipv4'>
+ <uuid>#{$NWFILTER_UUID}</uuid>
+ <rule action='accept' direction='out' priority='100'>
+ <ip srcipaddr='0.0.0.0' dstipaddr='255.255.255.255' protocol='tcp' srcportstart='63000' dstportstart='62000'/>
+ </rule>
+ <rule action='accept' direction='in' priority='100'>
+ <ip protocol='tcp' srcportstart='63000' dstportstart='62000'/>
+ </rule>
+</filter>
+EOF
+
+$SECRET_UUID = "bd339530-134c-6d07-4410-17fb90dad805"
+$new_secret_xml = <<EOF
+<secret ephemeral='no' private='no'>
+ <description>test secret</description>
+ <uuid>#{$SECRET_UUID}</uuid>
+ <usage type='volume'>
+ <volume>/var/lib/libvirt/images/mail.img</volume>
+ </usage>
+</secret>
+EOF
+
+$POOL_UUID = "33a5c045-645a-2c00-e56b-927cdf34e17a"
+$POOL_PATH = "/var/lib/libvirt/images/ruby-libvirt-tester"
+$new_storage_pool_xml = <<EOF
+<pool type="dir">
+ <name>ruby-libvirt-tester</name>
+ <uuid>#{$POOL_UUID}</uuid>
+ <target>
+ <path>#{$POOL_PATH}</path>
+ </target>
+</pool>
+EOF
+
+def expect_success(object, msg, func, *args)
+ begin
+ x = object.send(func, *args)
+ if block_given?
+ res = yield x
+ if not res
+ # FIXME: generate a proper error here
+ raise "Failed"
+ end
+ end
+ puts_ok "#{func} #{msg} succeeded"
+ x
+ rescue NoMethodError
+ puts_skipped "#{func} does not exist"
+ rescue => e
+ puts_fail "#{func} #{msg} expected to succeed, threw #{e.class.to_s}: #{e.to_s}"
+ end
+end
+
+def expect_fail(object, errtype, errmsg, func, *args)
+ begin
+ object.send(func, *args)
+ rescue NoMethodError
+ puts_skipped "#{func} does not exist"
+ rescue errtype => e
+ puts_ok "#{func} #{errmsg} threw #{errtype.to_s}"
+ rescue => e
+ puts_fail "#{func} #{errmsg} expected to throw #{errtype.to_s}, but instead threw #{e.class.to_s}: #{e.to_s}"
+ else
+ puts_fail "#{func} #{errmsg} expected to throw #{errtype.to_s}, but threw nothing"
+ end
+end
+
+def expect_too_many_args(object, func, *args)
+ expect_fail(object, ArgumentError, "too many args", func, *args)
+end
+
+def expect_too_few_args(object, func, *args)
+ expect_fail(object, ArgumentError, "too few args", func, *args)
+end
+
+def expect_invalid_arg_type(object, func, *args)
+ expect_fail(object, TypeError, "invalid arg type", func, *args)
+end
+
+def puts_ok(str)
+ puts "OK: " + str
+ $SUCCESS = $SUCCESS + 1
+end
+
+def puts_fail(str)
+ puts "FAIL: " + str
+ $FAIL = $FAIL + 1
+end
+
+def puts_skipped(str)
+ puts "SKIPPED: " + str
+ $SKIPPED = $SKIPPED + 1
+end
+
+def finish_tests
+ puts "Successfully finished #{$SUCCESS} tests, failed #{$FAIL} tests, skipped #{$SKIPPED} tests"
+end
--
libvirt ruby bindinds packaging
More information about the Pkg-libvirt-commits
mailing list