Sunday, December 15, 2013

Release of ruby-libvirt 0.5.1

I'm pleased to announce the release of ruby-libvirt 0.5.1. ruby-libvirt is a ruby wrapper around the libvirt API. The changelog between 0.5.0 and 0.5.1 is:
  • Fixes to compile against older libvirt
  • Fixes to compile against ruby 1.8
Version 0.5.1 is available from http://libvirt.org/ruby: Tarball: http://libvirt.org/ruby/download/ruby-libvirt-0.5.1.tgz Gem: http://libvirt.org/ruby/download/ruby-libvirt-0.5.1.gem It is also available from rubygems.org; to get the latest version, run: $ gem install ruby-libvirt As usual, if you run into questions, problems, or bugs, please feel free to mail me (clalancette@gmail.com) and/or the libvirt mailing list. Thanks to everyone who contributed patches and submitted bugs.

Monday, December 9, 2013

Release of ruby-libvirt 0.5.0

I'm pleased to announce the release of ruby-libvirt 0.5.0. ruby-libvirt is a ruby wrapper around the libvirt API. Version 0.5.0 brings new APIs, more documentation, and bugfixes:
  • Updated Network class, implementing almost all libvirt APIs
  • Updated Domain class, implementing almost all libvirt APIs
  • Updated Connection class, implementing almost all libvirt APIs
  • Updated DomainSnapshot class, implementing almost all libvirt APIs
  • Updated NodeDevice class, implementing almost all libvirt APIs
  • Updated Storage class, implementing almost all libvirt APIs
  • Add constants for almost all libvirt defines
  • Improved performance in the library by using alloca
Version 0.5.0 is available from http://libvirt.org/ruby: Tarball: http://libvirt.org/ruby/download/ruby-libvirt-0.5.0.tgz Gem: http://libvirt.org/ruby/download/ruby-libvirt-0.5.0.gem It is also available from rubygems.org; to get the latest version, run: $ gem install ruby-libvirt As usual, if you run into questions, problems, or bugs, please feel free to mail me (clalancette@gmail.com) and/or the libvirt mailing list. Thanks to everyone who contributed patches and submitted bugs.

Saturday, November 9, 2013

Writing Ruby Extensions in C - Part 13, Wrapping C data structures

This is the thirteenth in my series of posts about writing ruby extensions in C. The first post talked about the basic structure of a project, including how to set up building. The second post talked about generating documentation. The third post talked about initializing the module and setting up classes. The fourth post talked about types and return values. The fifth post focused on creating and handling exceptions. The sixth post talked about ruby catch and throw blocks. The seventh post talk about dealing with numbers. The eighth post talked about strings. The ninth post focused on arrays. The tenth post looked at hashes. The eleventh post explored blocks and callbacks. The twelfth post looked at allocating and freeing memory. This post will focus on wrapping C data structures in ruby objects.

Wrapping C data structures

When developing a ruby extension in C, it may be necessary to save an allocated C structure inside a Ruby object. For instance, in the ruby-libvirt bindings, a virConnectPtr (which points to a libvirt connection object) is saved inside of Libvirt::Connect ruby object, and that pointer is fetched from the object any time an instance method is called. Note that the pointer to the C structure is stored inside the Ruby object in a way that the ruby code can't get to; only C extensions will have access to this pointer. There are only 3 APIs that are used to manipulate these pointers:
  • Data_Wrap_Struct(VALUE klass, void (*mark)(), void (*free)(), void *ptr) - Wrap the C data structure in ptr into a class of type klass. The free argument is a function pointer to a function that will be called when the object is being garbage collected. If the C structure references other ruby objects, then the mark function pointer must also be provided and must properly mark the other objects with rb_gc_mark(). This function returns a VALUE which is an object of type klass.
  • Data_Make_Struct(VALUE klass, c-type, void (*mark)(), void (*free)(), c-type *ptr) - Similar to Data_Wrap_Struct(), but first allocates and then wraps the C structure in an object. The klass, mark, free, and ptr arguments have the same meaning as Data_Wrap_Struct(). The c-type argument is the actual name of the type that needs to be allocated (sizeof(type) will be used to allocate).
  • Data_Get_Struct(VALUE obj, c-type, c-type *ptr) - Get the C data structure of c-type out of the object obj, and put the result in ptr. Note that this pointer assignment works because this is a macro.

An example will demonstrate the use of these functions:

 1) static VALUE m_example;
 2) static VALUE c_conn;
 3)
 4) struct mystruct {
 5)     int a;
 6)     int b;
 7) };
 8)
 9) static void mystruct_free(void *s)
10) {
11)    xfree(s);
12) }
13)
14) static VALUE example_open(VALUE m)
15) {
16)     struct mystruct *conn;
17)     conn = ALLOC(struct mystruct);
18)     conn->a = 25;
19)     conn->b = 99;
20)     return Data_Wrap_Struct(c_conn, NULL, mystruct_free, conn);
21) }
22)
23) static VALUE conn_get_a(VALUE c)
24) {
25)     struct mystruct *conn;
26)     Data_Get_Struct(c, struct mystruct, conn);
27)     return INT2NUM(conn->a);
28) }
29)
30) void Init_example(void)
31) {
32)     m_example = rb_define_module("Example");
33)     rb_define_module_function(m_example, "open", example_open, 0);
34)     c_conn = rb_define_class_under(m_example, "Conn", rb_cObject);
35)     rb_define_method(c_conn, "get_a", conn_get_a, 0);
36) }

On lines 32 and 33, we define the Example module and give it a module function called "open". Lines 34 and 35 define a Conn class under the Example module, and gives the Conn class a "get_a" method. Lines 14 through 21 are where we implement the Example::open function. There, we allocate memory for our C structure, then use Data_Wrap_Struct() to wrap that C structure in a ruby object of type Example::Conn. Note that we also pass mystruct_free() as the free callback; when the object gets reaped by the garbage collector, this function on lines 9 through 12 will be called to free up any memory. Now when the user calls "get_a" on the Example::Conn ruby object, the function on lines 23 through 27 will be called. There we use Data_Get_Struct() to fetch the structure back out of the object, and then return a ruby number for the integer stored inside. Update: added links to all of the previous articles. Update Jan 27, 2014: Updated the example to fix the use of ALLOC(). Thanks to Thomas Thomassen in the comments.

Sunday, July 28, 2013

Oz 0.11.0 release

I'm pleased to announce release 0.11.0 of Oz. Oz is a program for doing automated installation of guest operating systems with limited input from the user. Release 0.11.0 is a bugfix and feature release for Oz. Some of the highlights between Oz 0.10.0 and 0.11.0 are:
  • Add support for installing Ubuntu 13.04
  • Add the ability to get user-specific ICICLE information
  • Add the ability to generate ICICLE safely, by using a disk snapshot
  • Add the ability to include extra files and directories on the installation ISO
  • Add the ability to install to alternate file types, like qcow2, etc.
  • Add support for installing Ubuntu 5.04/5.10
  • Add support for installing Fedora 19
  • Add support for installing Debian 7
  • Add support for Windows 2012 and 8
  • Add support for getting files over http for the commands/files section of the TDL
  • Add support for setting a custom MAC address to guests during installation
  • Add support for user specified disk and NIC model
  • Add support for OpenSUSE 12.3
  • Add support for URL based installs for Ubuntu
A tarball and zipfile of this release is available on the Github releases page: https://github.com/clalancette/oz/releases. Packages for Fedora-18 and Fedora-19 have been built in Koji and will eventually make their way to stable. Instructions on how to get and use Oz are available at http://github.com/clalancette/oz/wiki.

If you have questions or comments about Oz, please feel free to contact me at clalancette at gmail.com, or open up an issue on the github page: http://github.com/clalancette/oz/issues.

This was one of the most active Oz releases ever, because of the feedback and patches from the community. Thanks to everyone who contributed to this release through bug reports, patches, and suggestions for improvement.

Saturday, March 9, 2013

Oz 0.10.0 release

I'm pleased to announce release 0.10.0 of Oz. Oz is a program for doing automated installation of guest operating systems with limited input from the user. Release 0.10.0 is a bugfix and feature release for Oz. Some of the highlights between Oz 0.9.0 and 0.10.0 are:
  • Support for installing OpenSUSE 12.1 and 12.2
  • Support for python3
  • Support for Ubuntu 12.04.1, 12.04.2, and 12.10
  • Fix up ordering so that commands are run in the order they are specified in the XML
  • Updates and fixes to the documentation
  • Increase the shutdown timeout to support slower qemu guests
  • Add a default screenshot directory as /var/lib/oz/screenshots
  • Support for RHEL 5.9
  • Support for Fedora 18
  • Switch over to pycurl for header information; this allows http authentication to work
  • Switch to using the libvirt built-in screenshot mechanism. This removes the gvnc dependency and makes screenshots more reliable, but requires libvirt 0.9.7 or newer
  • Delete auto-generated ssh keys after customization
A tarball of this release is available, as well as packages for Fedora-17. Instructions on how to get and use Oz are available at http://github.com/clalancette/oz/wiki . If you have questions or comments about Oz, please feel free to contact me at clalancette@gmail.com, or open up an issue on the github page: http://github.com/clalancette/oz/issues . Thanks to everyone who contributed to this release through bug reports, patches, and suggestions for improvement.