Awesome
Erlang bindings to the libvirt virtualization API.
ALTERNATIVES
A "pure" Erlang libvirt interface is available here:
https://github.com/msantos/verx
verx uses the libvirtd remote procotol over a socket. By default, verx uses a Unix socket which depends on a library written in C but verx also supports TCP and TLS transports which do not have any external dependencies.
WARNING
The current implementation prevents the Erlang VM from being blocked
by calling all libvirt functions in a thread. If libvirt blocks,
the caller will receive an error immediately ({error, eagain}).
Only one call from Erlang into libvirt can be running at a time.
These bindings have only been lightly tested. It's still possible
that some of the functions may segfault.
HOW TO BUILD IT
sudo apt-get install libvirt-dev libvirt-bin
make
CREATING A TEST VM
If you don't have a VM ready to test, you can download a test image
by running:
bin/get_image.escript
The script will download an OpenWRT image and set up the configuration
in priv/example.xml. By default, it will set up the VM to run under
KVM using user mode networking.
You can manually modify the configuration afterwards or set these
environment variables before running the script:
VERT_QEMU_BIN : path to the qemu binary (default: /usr/bin/kvm)
VERT_BRIDGE_INTERFACE : bridge interface (default: user networking)
HOW TO USE IT
The Erlang libvirt API follows the libvirt C API. For example, if the C API has:
virConnectOpen(char *name)
virConnectGetLibVersion(virConnectPtr(conn), unsigned long *version)
To call the same functions in Erlang:
{ok, Connect} = vert:virConnectOpen("qemu:///system"),
{ok,{0,7,5}} = vert:virConnectGetLibVersion(Connect).
EXAMPLES
CREATING A DOMAIN
start(Path) ->
{ok, Connect} = vert:virConnectOpen("qemu:///system"),
{ok, XML} = file:read_file(Path),
{ok, Domain} = vert:virDomainDefineXML(Connect, XML),
ok = vert:virDomainCreate(Domain),
Active = vert:virConnectNumOfDomains(Connect),
io:format("Active Domains: ~p~n", [Active]),
{ok, Domain}.
halt(Domain) ->
ok = vert:virDomainDestroy(Domain).
DUMPING XML CONFIGURATION
This example dumps the XML of a defined (not running) domain.
1> {ok, Connect} = vert:virConnectOpen("qemu:///system").
{ok,{resource,connect,#Ref<0.0.0.30>,<<>>}}
2> {ok, [Host|_]} = vert:virConnectListDefinedDomains(Connect).
{ok, ["vm1"]}
3> {ok, Domain} = vert:virDomainLookupByName(Connect, Host).
{ok,{resource,domain,#Ref<0.0.0.56>,<<>>}}
4> {ok, XML} = vert:virDomainGetXMLDesc(Domain, 0).
5> {Doc, _} = xmerl_scan:string(XML).
6> rr(xmerl).
7> [Memory|_] = xmerl_xpath:string("/domain/memory/text()", Doc).
8> Memory#xmlText.value.
"1048576"
SUSPENDING AND RESUMING A DOMAIN
This example is the Erlang equivalent of a Python script to manipulate running domains. The example is taken from:
http://www.ibm.com/developerworks/linux/library/l-libvirt/
-module(ex6).
%% Listing 6. Sample Python script for domain control (libvtest.py)
%%
%% import libvirt
%%
%% conn = libvirt.open('qemu:///system')
%%
%% for id in conn.listDomainsID():
%%
%% dom = conn.lookupByID(id)
%%
%% print "Dom %s State %s" % ( dom.name(), dom.info()[0] )
%%
%% dom.suspend()
%% print "Dom %s State %s (after suspend)" % ( dom.name(), dom.info()[0] )
%%
%% dom.resume()
%% print "Dom %s State %s (after resume)" % ( dom.name(), dom.info()[0] )
%%
%% dom.destroy()
%%
-export([start/0]).
start() ->
{ok, Connect} = vert:virConnectOpen("qemu:///system"),
{ok, DomainIDs} = vert:virConnectListDomains(Connect),
[ states(Connect, DomainID) || DomainID <- DomainIDs ],
ok.
states(Connect, DomainID) ->
{ok, Domain} = vert:virDomainLookupByID(Connect, DomainID),
io:format("running: ~p~n", [info(Domain)]),
ok = vert:virDomainSuspend(Domain),
io:format("suspend: ~p~n", [info(Domain)]),
ok = vert:virDomainResume(Domain),
io:format("resumed: ~p~n", [info(Domain)]),
ok = vert:virDomainDestroy(Domain).
info(Domain) ->
{ok, Name} = vert:virDomainGetName(Domain),
{ok, Info} = vert:virDomainGetInfo(Domain),
[{name, Name}, {info, Info}].
TODO
-
allow caller to optionally run a libvirt operations in a new thread
-
add remaining libvirt API functions