Re: [libvirt] blkio cgroup
by Vivek Goyal
On Fri, Feb 18, 2011 at 03:42:45PM +0100, Dominik Klein wrote:
> Hi Vivek
>
> I don't know whether you follow the libvirt list, I assume you don't. So
> I thought I'd forward you an E-Mail involving the blkio controller and a
> terrible situation arising from using it (maybe in a wrong way).
>
> I'd truely appreciate it if you read it and commented on it. Maybe I did
> something wrong, but maybe also I found a bug in some way.
Hi Dominik,
Thanks for forwarding me this mail. Yes, I am not on libvir-list. I have
just now subscribed.
Few questions inline.
> -------- Original Message --------
> Subject: Re: [libvirt] [PATCH 0/6 v3] Add blkio cgroup support
> Date: Fri, 18 Feb 2011 14:42:51 +0100
> From: Dominik Klein <dk(a)in-telegence.net>
> To: libvir-list(a)redhat.com
>
> Hi
>
> back with some testing results.
>
> >> how about the start Guest with option "cache=none" to bypass pagecache?
> >> This should help i think.
> >
> > I will read up on where to set that and give it a try. Thanks for the hint.
>
> So here's what I did and found out:
>
> The host system has 2 12 core CPUs and 128 GB of Ram.
>
> I have 8 test VMs named kernel1 to kernel8. Each VM has 4 VCPUs, 2 GB of
> RAm and one disk, which is an lv on the host. Cache mode is "none":
So you have only one root SATA disk and setup a linear logical volume on
that? I not, can you give more info about the storage configuration?
- I am assuming you are using CFQ on your underlying physical disk.
- What kernel version are you testing with.
- Cache=none mode is good which should make all the IO O_DIRECT on host
and should show up as SYNC IO on CFQ without losing io context info.
The onlly probelm is intermediate dm layer and if it is changing the
io context somehow. I am not sure at this point of time.
- Is it possible to capture 10-15 second blktrace on your underlying
physical device. That should give me some idea what's happening.
- Can you also try setting /sys/block/<disk>/queue/iosched/group_isolation=1
on your underlying physical device where CFQ is running and see if it makes
any difference.
>
> for vm in kernel1 kernel2 kernel3 kernel4 kernel5 kernel6 kernel7
> kernel8; do virsh dumpxml $vm|grep cache; done
> <driver name='qemu' type='raw' cache='none'/>
> <driver name='qemu' type='raw' cache='none'/>
> <driver name='qemu' type='raw' cache='none'/>
> <driver name='qemu' type='raw' cache='none'/>
> <driver name='qemu' type='raw' cache='none'/>
> <driver name='qemu' type='raw' cache='none'/>
> <driver name='qemu' type='raw' cache='none'/>
> <driver name='qemu' type='raw' cache='none'/>
>
> My goal is to give more I/O time to kernel1 and kernel2 than to the rest
> of the VMs.
>
> mount -t cgroup -o blkio none /mnt
> cd /mnt
> mkdir important
> mkdir notimportant
>
> echo 1000 > important/blkio.weight
> echo 100 > notimportant/blkio.weight
> for vm in kernel3 kernel4 kernel5 kernel6 kernel7 kernel8; do
> cd /proc/$(pgrep -f "qemu-kvm.*$vm")/task
> for task in *; do
> /bin/echo $task > /mnt/notimportant/tasks
> done
> done
>
> for vm in kernel1 kernel2; do
> cd /proc/$(pgrep -f "qemu-kvm.*$vm")/task
> for task in *; do
> /bin/echo $task > /mnt/important/tasks
> done
> done
>
> Then I used cssh to connect to all 8 VMs and execute
> dd if=/dev/zero of=testfile bs=1M count=1500
> in all VMs simultaneously.
>
> Results are:
> kernel1: 47.5593 s, 33.1 MB/s
> kernel2: 60.1464 s, 26.2 MB/s
> kernel3: 74.204 s, 21.2 MB/s
> kernel4: 77.0759 s, 20.4 MB/s
> kernel5: 65.6309 s, 24.0 MB/s
> kernel6: 81.1402 s, 19.4 MB/s
> kernel7: 70.3881 s, 22.3 MB/s
> kernel8: 77.4475 s, 20.3 MB/s
>
> Results vary a little bit from run to run, but it is nothing
> spectacular, as weights of 1000 vs. 100 would suggest.
>
> So I went and tried to throttle I/O of kernel3-8 to 10MB/s instead of
> weighing I/O. First I rebooted everything so that no old configuration
> of cgroup was left in place and then setup everything except the 100 and
> 1000 weight configuration.
>
> quote from blkio.txt:
> ------------
> - blkio.throttle.write_bps_device
> - Specifies upper limit on WRITE rate to the device. IO rate is
> specified in bytes per second. Rules are per deivce. Following is
> the format.
>
> echo "<major>:<minor> <rate_bytes_per_second>" >
> /cgrp/blkio.write_bps_device
> -------------
>
> for vm in kernel1 kernel2 kernel3 kernel4 kernel5 kernel6 kernel7
> kernel8; do ls -lH /dev/vdisks/$vm; done
> brw-rw---- 1 root root 254, 23 Feb 18 13:45 /dev/vdisks/kernel1
> brw-rw---- 1 root root 254, 24 Feb 18 13:45 /dev/vdisks/kernel2
> brw-rw---- 1 root root 254, 25 Feb 18 13:45 /dev/vdisks/kernel3
> brw-rw---- 1 root root 254, 26 Feb 18 13:45 /dev/vdisks/kernel4
> brw-rw---- 1 root root 254, 27 Feb 18 13:45 /dev/vdisks/kernel5
> brw-rw---- 1 root root 254, 28 Feb 18 13:45 /dev/vdisks/kernel6
> brw-rw---- 1 root root 254, 29 Feb 18 13:45 /dev/vdisks/kernel7
> brw-rw---- 1 root root 254, 30 Feb 18 13:45 /dev/vdisks/kernel8
>
> /bin/echo 254:25 10000000 >
> /mnt/notimportant/blkio.throttle.write_bps_device
> /bin/echo 254:26 10000000 >
> /mnt/notimportant/blkio.throttle.write_bps_device
> /bin/echo 254:27 10000000 >
> /mnt/notimportant/blkio.throttle.write_bps_device
> /bin/echo 254:28 10000000 >
> /mnt/notimportant/blkio.throttle.write_bps_device
> /bin/echo 254:29 10000000 >
> /mnt/notimportant/blkio.throttle.write_bps_device
> /bin/echo 254:30 10000000 >
> /mnt/notimportant/blkio.throttle.write_bps_device
> /bin/echo 254:30 10000000 >
> /mnt/notimportant/blkio.throttle.write_bps_device
>
> Then I ran the previous test again. This resulted in an ever increasing
> load (last I checked was ~ 300) on the host system. (This is perfectly
> reproducible).
>
> uptime
> Fri Feb 18 14:42:17 2011
> 14:42:17 up 12 min, 9 users, load average: 286.51, 142.22, 56.71
Have you run top or something to figure out why load average is shooting
up. I suspect that because of throttling limit, IO threads have been
blocked and qemu is forking more IO threads. Can you just run top/ps
and figure out what's happening.
Again, is it some kind of linear volume group from which you have carved
out logical volumes for each virtual machine?
For throttling to begin with, can we do a simple test first. That is
run a single virtual machine, put some throttling limit on logical volume
and try to do READs. Once READs work, lets test WRITES and check why
does system load go up.
Thanks
Vivek
13 years, 9 months
[libvirt] questions about libvirtd and virsh
by fengzi.gg
hello, everyone
I am now reading the souce code of libvirtd and virsh, and got some
questions:
1. Is libvirtd necessary when I use some tools(based on libvirt)
to control domains?
2. It seems that virsh use remote driver to comunicate to libvirtd (the hypervisor is qemu),
why doesn't it call libvirt directly?
3. In the souce code, there is "server" and "client" functions, so what is a
"client", and what is a "server"?
4. libvirtd has 7 threads, what are these threads doing?
thanks
fengzihuachuan
2011-02-25
--
libvir-list mailing list
libvir-list(a)redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
13 years, 9 months
[libvirt] [BUG, ½PATCH] domain.rng vs. formatdomain.html#elementsUSB
by Philipp Hahn
Hello,
I just tried to validate the minimal <hostdev>-example from
<http://libvirt.org/formatdomain.html#elementsUSB>, which failed.
<domain type='xen'>
<name>N</name>
<memory>123456</memory>
<bootloader>/usr/bin/pygrub</bootloader>
<os>
<type arch='x86_64' machine='xenpv'>linux</type>
</os>
<devices>
<hostdev mode='subsystem' type='pci'>
<source>
<address bus='0x06' slot='0x00' function='0x0'/>
</source>
</hostdev>
</devices>
</domain>
This is caused by domain.rng requiring either all three attributes
("mode", "type", and the undocumented "managed") to be defined or non of
them; just a subset of them is not allowed because the all reside in the same
<optional>-section.
Since I don't know, which of the three attributes must be defined in concert,
and which is optional, I just post a patch to make all three self-standing.
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 8b215f3..11a987e 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -1731,12 +1731,16 @@
<value>capabilities</value>
</choice>
</attribute>
+ </optional>
+ <optional>
<attribute name="type">
<choice>
<value>usb</value>
<value>pci</value>
</choice>
</attribute>
+ </optional>
+ <optional>
<attribute name="managed">
<choice>
<value>yes</value>
Also the "managed" attribute should be documented on that page. Any internal
documentation (read: code) for that?
Sincerely
Philipp
--
Philipp Hahn Open Source Software Engineer hahn(a)univention.de
Univention GmbH Linux for Your Business fon: +49 421 22 232- 0
Mary-Somerville-Str.1 28359 Bremen fax: +49 421 22 232-99
http://www.univention.de/
** Besuchen Sie uns auf der CeBIT in Hannover **
** Auf dem Univention Stand D36 in Halle 2 **
** Vom 01. bis 05. März 2011 **
13 years, 9 months
[libvirt] [PATCH V2] Add libxenlight driver
by Jim Fehlig
Add a new xen driver based on libxenlight [1], which is the primary
toolstack starting with Xen 4.1.0. The driver is stateful, runs
privileged only, and is accessed with libxl:/// URI.
V2:
- Update to Xen 4.1 RC6-pre (c/s 22940:5a4710640f81)
- Rebased to current master
- Plug memory leaks found by Stefano Stabellini and valgrind
- Handle SHUTDOWN_crash domain death event
[1] http://lists.xensource.com/archives/html/xen-devel/2009-11/msg00436.html
---
cfg.mk | 1 +
configure.ac | 48 ++
daemon/Makefile.am | 4 +
daemon/libvirtd.c | 6 +
docs/drivers.html.in | 3 +-
docs/drvxen.html.in | 6 +-
docs/drvxenlight.html.in | 53 ++
docs/sitemap.html.in | 6 +-
include/libvirt/virterror.h | 1 +
po/POTFILES.in | 2 +
src/Makefile.am | 32 ++
src/driver.h | 3 +-
src/libvirt.c | 4 +
src/libxl/libxl_conf.c | 894 ++++++++++++++++++++++++++++++
src/libxl/libxl_conf.h | 88 +++
src/libxl/libxl_driver.c | 1281 +++++++++++++++++++++++++++++++++++++++++++
src/libxl/libxl_driver.h | 27 +
src/util/virterror.c | 3 +
18 files changed, 2458 insertions(+), 4 deletions(-)
diff --git a/cfg.mk b/cfg.mk
index 1bb9cbb..f155ce3 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -401,6 +401,7 @@ msg_gen_function += virXenStoreError
msg_gen_function += virXendError
msg_gen_function += vmwareError
msg_gen_function += xenapiSessionErrorHandler
+msg_gen_function += libxlError
msg_gen_function += xenUnifiedError
msg_gen_function += xenXMError
msg_gen_function += VIR_ERROR
diff --git a/configure.ac b/configure.ac
index bd509f3..9658a68 100644
--- a/configure.ac
+++ b/configure.ac
@@ -263,6 +263,8 @@ AC_ARG_WITH([phyp],
AC_HELP_STRING([--with-phyp], [add PHYP support @<:@default=check@:>@]),[],[with_phyp=check])
AC_ARG_WITH([xenapi],
AC_HELP_STRING([--with-xenapi], [add XenAPI support @<:@default=check@:>@]),[],[with_xenapi=check])
+AC_ARG_WITH([libxl],
+ AC_HELP_STRING([--with-libxl], [add libxenlight support @<:@default=check@:>@]),[],[with_libxl=check])
AC_ARG_WITH([vbox],
AC_HELP_STRING([--with-vbox=@<:@PFX@:>@],
[VirtualBox XPCOMC location @<:@default=yes@:>@]),[],
@@ -497,6 +499,46 @@ fi
AC_SUBST([LIBXENSERVER_CFLAGS])
AC_SUBST([LIBXENSERVER_LIBS])
+old_LIBS="$LIBS"
+old_CFLAGS="$CFLAGS"
+LIBXL_LIBS=""
+LIBXL_CFLAGS=""
+dnl search for libxl, aka libxenlight
+fail=0
+if test "$with_libxl" != "no" ; then
+ if test "$with_libxl" != "yes" && test "$with_libxl" != "check" ; then
+ LIBXL_CFLAGS="-I$with_libxl/include"
+ LIBXL_LIBS="-L$with_libxl"
+ fi
+ CFLAGS="$CFLAGS $LIBXL_CFLAGS"
+ LIBS="$LIBS $LIBXL_LIBS"
+ AC_CHECK_LIB([xenlight], [libxl_ctx_init], [
+ with_libxl=yes
+ LIBXL_LIBS="$LIBXL_LIBS -lxenlight -lxenstore -lxenctrl -lxenguest -luuid -lutil -lblktapctl"
+ ],[
+ if test "$with_libxl" = "yes"; then
+ fail=1
+ fi
+ with_libxl=no
+ ],[
+ -lxenstore -lxenctrl -lxenguest -luuid -lutil -lblktapctl
+ ])
+fi
+
+LIBS="$old_LIBS"
+CFLAGS="$old_CFLAGS"
+
+if test $fail = 1; then
+ AC_MSG_ERROR([You must install the libxl Library to compile libxenlight driver with -lxl])
+fi
+
+if test "$with_libxl" = "yes"; then
+ AC_DEFINE_UNQUOTED([WITH_LIBXL], 1, [whether libxenlight driver is enabled])
+fi
+AM_CONDITIONAL([WITH_LIBXL], [test "$with_libxl" = "yes"])
+
+AC_SUBST([LIBXL_CFLAGS])
+AC_SUBST([LIBXL_LIBS])
old_LIBS="$LIBS"
old_CFLAGS="$CFLAGS"
@@ -2370,6 +2412,7 @@ AC_MSG_NOTICE([ OpenVZ: $with_openvz])
AC_MSG_NOTICE([ VMware: $with_vmware])
AC_MSG_NOTICE([ VBox: $with_vbox])
AC_MSG_NOTICE([ XenAPI: $with_xenapi])
+AC_MSG_NOTICE([libxenlight: $with_libxl])
AC_MSG_NOTICE([ LXC: $with_lxc])
AC_MSG_NOTICE([ PHYP: $with_phyp])
AC_MSG_NOTICE([ ONE: $with_one])
@@ -2479,6 +2522,11 @@ AC_MSG_NOTICE([ xenapi: $LIBXENSERVER_CFLAGS $LIBXENSERVER_LIBS])
else
AC_MSG_NOTICE([ xenapi: no])
fi
+if test "$with_libxl" = "yes" ; then
+AC_MSG_NOTICE([ libxenlight: $LIBXL_CFLAGS $LIBXL_LIBS])
+else
+AC_MSG_NOTICE([ libxenlight: no])
+fi
if test "$with_hal" = "yes" ; then
AC_MSG_NOTICE([ hal: $HAL_CFLAGS $HAL_LIBS])
else
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 86f024f..1a215f3 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -112,6 +112,10 @@ if WITH_LXC
libvirtd_LDADD += ../src/libvirt_driver_lxc.la
endif
+if WITH_LIBXL
+ libvirtd_LDADD += ../src/libvirt_driver_libxl.la
+endif
+
if WITH_UML
libvirtd_LDADD += ../src/libvirt_driver_uml.la
endif
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index b2e5e20..6e552f2 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -80,6 +80,9 @@
# ifdef WITH_LXC
# include "lxc/lxc_driver.h"
# endif
+# ifdef WITH_LIBXL
+# include "libxl/libxl_driver.h"
+# endif
# ifdef WITH_UML
# include "uml/uml_driver.h"
# endif
@@ -928,6 +931,9 @@ static struct qemud_server *qemudInitialize(void) {
# ifdef WITH_LXC
lxcRegister();
# endif
+# ifdef WITH_LIBXL
+ libxlRegister();
+# endif
# ifdef WITH_UML
umlRegister();
# endif
diff --git a/docs/drivers.html.in b/docs/drivers.html.in
index ecad03a..368664e 100644
--- a/docs/drivers.html.in
+++ b/docs/drivers.html.in
@@ -28,7 +28,8 @@
<li><strong><a href="drvvbox.html">VirtualBox</a></strong></li>
<li><strong><a href="drvesx.html">VMware ESX</a></strong></li>
<li><strong><a href="drvvmware.html">VMware Workstation/Player</a></strong></li>
- <li><strong><a href="drvxen.html">Xen</a></strong></li>
+ <li><strong><a href="drvxen.html">Xen 3.0.1 - 4.0.x</a></strong></li>
+ <li><strong><a href="drvxenlight.html">Xen 4.1.0 onwards</a></strong></li>
</ul>
<h2><a name="stroage">Storage drivers</a></h2>
diff --git a/docs/drvxen.html.in b/docs/drvxen.html.in
index 4e35afa..4b88a7d 100644
--- a/docs/drvxen.html.in
+++ b/docs/drvxen.html.in
@@ -6,7 +6,11 @@
<p>
The libvirt Xen driver provides the ability to manage virtual machines
- on any Xen release from 3.0.1 onwards.
+ on any Xen release from 3.0.1 to 4.0.x. Starting with Xen 4.1.0,
+ the traditional xm/xend toolstack is replaced with a new toolstack
+ based on libxenlight. Consult the
+ <a href="drvxenlight.html">libxenlight driver</a> if your Xen host is
+ configured to use the new toolstack.
</p>
<h2><a name="prereq">Deployment pre-requisites</a></h2>
diff --git a/docs/drvxenlight.html.in b/docs/drvxenlight.html.in
new file mode 100644
index 0000000..fe60786
--- /dev/null
+++ b/docs/drvxenlight.html.in
@@ -0,0 +1,53 @@
+<html>
+ <body>
+ <h1>libxenlight hypervisor driver</h1>
+
+ <ul id="toc"></ul>
+
+ <p>
+ The libvirt libxenlight driver provides the ability to manage virtual
+ machines on any Xen release from 4.1.0 onwards.
+ </p>
+
+ <h2><a name="prereq">Deployment pre-requisites</a></h2>
+
+ <p>
+ This driver uses Xen's libxenlight toolstack, which is the default
+ toolstack configuration starting with Xen 4.1.0. The traditional
+ xm/xend toolstack is still provided, but it is no longer maintained
+ and may be removed in a future Xen release.
+ </p>
+
+ <p>
+ The libxenlight toolstack uses xenstored and blktap2. Ensure
+ xenstored is running, or use the xencommons init script provided.
+ Ensure your kernel supports the blktap2 module and it is loaded.
+ </p>
+
+ <h2><a name="uri">Connections to libxenlight driver</a></h2>
+
+ <p>
+ The libvirt libxenlight driver is a stateful, privileged driver,
+ with a driver name of 'libxl'. Some example conection URIs for
+ the libxenlight driver are:
+ </p>
+
+<pre>
+libxl:/// (local access, direct)
+libxl://example.com/ (remote access, TLS/x509)
+libxl+tcp://example.com/ (remote access, SASl/Kerberos)
+libxl+ssh://root@example.com/ (remote access, SSH tunnelled)
+</pre>
+
+ <h2><a name="xmlconfig">Example domain XML config</a></h2>
+
+ <p>
+ The libxenlight toolstack attempts to be compatible with the
+ legacy xm/xend toolstack, supporting the traditional python
+ configuration files (xen-xm). Fortunately, the libvirt XML
+ syntax is unchanged with the libxenlight driver. Consult
+ the <a href="drvxen.html#xmlconfig">Xen driver examples</a>.
+ </p>
+
+ </body>
+</html>
diff --git a/docs/sitemap.html.in b/docs/sitemap.html.in
index ac0af71..538f227 100644
--- a/docs/sitemap.html.in
+++ b/docs/sitemap.html.in
@@ -156,7 +156,11 @@
<ul>
<li>
<a href="drvxen.html">Xen</a>
- <span>Driver the Xen hypervisor</span>
+ <span>Driver the Xen hypervisor, versions 3.0.1 - 4.0.x</span>
+ </li>
+ <li>
+ <a href="drvxenlight.html">libxenlight</a>
+ <span>Driver the Xen hypervisor, version 4.1.0 onwards</span>
</li>
<li>
<a href="drvqemu.html">QEMU / KVM</a>
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index 5962dbf..9f263d2 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -79,6 +79,7 @@ typedef enum {
VIR_FROM_SYSINFO = 37, /* Error from sysinfo/SMBIOS */
VIR_FROM_STREAMS = 38, /* Error from I/O streams */
VIR_FROM_VMWARE = 39, /* Error from VMware driver */
+ VIR_FROM_LIBXL = 40, /* Error from libxenlight driver */
} virErrorDomain;
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9852f97..64be591 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -34,6 +34,8 @@ src/lxc/lxc_conf.c
src/lxc/lxc_controller.c
src/lxc/lxc_driver.c
src/lxc/veth.c
+src/libxl/libxl_driver.c
+src/libxl/libxl_conf.c
src/network/bridge_driver.c
src/node_device/node_device_driver.c
src/node_device/node_device_hal.c
diff --git a/src/Makefile.am b/src/Makefile.am
index bd25b38..2b1f9fc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -297,6 +297,10 @@ XENAPI_DRIVER_SOURCES = \
xenapi/xenapi_driver_private.h \
xenapi/xenapi_utils.c xenapi/xenapi_utils.h
+LIBXL_DRIVER_SOURCES = \
+ libxl/libxl_conf.c libxl/libxl_conf.h \
+ libxl/libxl_driver.c libxl/libxl_driver.h
+
UML_DRIVER_SOURCES = \
uml/uml_conf.c uml/uml_conf.h \
uml/uml_driver.c uml/uml_driver.h
@@ -691,6 +695,25 @@ endif
libvirt_driver_xenapi_la_SOURCES = $(XENAPI_DRIVER_SOURCES)
endif
+if WITH_LIBXL
+if WITH_DRIVER_MODULES
+mod_LTLIBRARIES += libvirt_driver_libxl.la
+else
+noinst_LTLIBRARIES += libvirt_driver_libxl.la
+# Stateful, so linked to daemon instead
+#libvirt_la_BUILT_LIBADD += libvirt_driver_libxl.la
+endif
+libvirt_driver_libxl_la_CFLAGS = $(LIBXL_CFLAGS) \
+ -I@top_srcdir@/src/conf $(AM_CFLAGS)
+libvirt_driver_libxl_la_LDFLAGS = $(AM_LDFLAGS)
+libvirt_driver_libxl_la_LIBADD = $(LIBXL_LIBS)
+if WITH_DRIVER_MODULES
+libvirt_driver_libxl_la_LIBADD += ../gnulib/lib/libgnu.la
+libvirt_driver_libxl_la_LDFLAGS += -module -avoid-version
+endif
+libvirt_driver_libxl_la_SOURCES = $(LIBXL_DRIVER_SOURCES)
+endif
+
if WITH_QEMU
if WITH_DRIVER_MODULES
mod_LTLIBRARIES += libvirt_driver_qemu.la
@@ -990,6 +1013,7 @@ EXTRA_DIST += \
$(PHYP_DRIVER_SOURCES) \
$(VBOX_DRIVER_SOURCES) \
$(XENAPI_DRIVER_SOURCES) \
+ $(LIBXL_DRIVER_SOURCES) \
$(ESX_DRIVER_SOURCES) \
$(ESX_DRIVER_EXTRA_DIST) \
$(NETWORK_DRIVER_SOURCES) \
@@ -1244,6 +1268,10 @@ if WITH_LXC
$(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/lxc"
$(MKDIR_P) "$(DESTDIR)$(localstatedir)/run/libvirt/lxc"
endif
+if WITH_LIBXL
+ $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/libxl"
+ $(MKDIR_P) "$(DESTDIR)$(localstatedir)/run/libvirt/libxl"
+endif
if WITH_UML
$(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/uml"
$(MKDIR_P) "$(DESTDIR)$(localstatedir)/run/libvirt/uml"
@@ -1281,6 +1309,10 @@ if WITH_LXC
rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/lxc" ||:
rmdir "$(DESTDIR)$(localstatedir)/run/libvirt/lxc" ||:
endif
+if WITH_LIBXL
+ rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/libxl" ||:
+ rmdir "$(DESTDIR)$(localstatedir)/run/libvirt/libxl" ||:
+endif
if WITH_UML
rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/uml" ||:
rmdir "$(DESTDIR)$(localstatedir)/run/libvirt/uml" ||:
diff --git a/src/driver.h b/src/driver.h
index 7451004..b2d9814 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -28,7 +28,8 @@ typedef enum {
VIR_DRV_ESX = 10,
VIR_DRV_PHYP = 11,
VIR_DRV_XENAPI = 12,
- VIR_DRV_VMWARE = 13
+ VIR_DRV_VMWARE = 13,
+ VIR_DRV_LIBXL = 14,
} virDrvNo;
diff --git a/src/libvirt.c b/src/libvirt.c
index e4b451e..5e2876b 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -912,6 +912,10 @@ virGetVersion(unsigned long *libVer, const char *type,
if (STRCASEEQ(type, "LXC"))
*typeVer = LIBVIR_VERSION_NUMBER;
# endif
+# if WITH_LIBXL
+ if (STRCASEEQ(type, "libxl"))
+ *typeVer = LIBVIR_VERSION_NUMBER;
+# endif
# if WITH_PHYP
if (STRCASEEQ(type, "phyp"))
*typeVer = LIBVIR_VERSION_NUMBER;
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
new file mode 100644
index 0000000..dacb82b
--- /dev/null
+++ b/src/libxl/libxl_conf.c
@@ -0,0 +1,894 @@
+/*---------------------------------------------------------------------------*/
+/* Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * 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 <config.h>
+
+#include <regex.h>
+#include <libxl.h>
+#include <sys/utsname.h>
+
+#include "internal.h"
+#include "logging.h"
+#include "virterror_internal.h"
+#include "datatypes.h"
+#include "files.h"
+#include "memory.h"
+#include "uuid.h"
+#include "capabilities.h"
+#include "libxl_driver.h"
+#include "libxl_conf.h"
+
+
+#define VIR_FROM_THIS VIR_FROM_LIBXL
+
+
+struct guest_arch {
+ const char *model;
+ int bits;
+ int hvm;
+ int pae;
+ int nonpae;
+ int ia64_be;
+};
+
+static const char *xen_cap_re = "(xen|hvm)-[[:digit:]]+\\.[[:digit:]]+-(x86_32|x86_64|ia64|powerpc64)(p|be)?";
+static regex_t xen_cap_rec;
+
+static virCapsPtr
+libxlBuildCapabilities(const char *hostmachine,
+ int host_pae,
+ struct guest_arch *guest_archs,
+ int nr_guest_archs)
+{
+ virCapsPtr caps;
+ int i;
+
+ if ((caps = virCapabilitiesNew(hostmachine, 1, 1)) == NULL)
+ goto no_memory;
+
+ virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x00, 0x16, 0x3e });
+
+ if (host_pae &&
+ virCapabilitiesAddHostFeature(caps, "pae") < 0)
+ goto no_memory;
+
+ for (i = 0; i < nr_guest_archs; ++i) {
+ virCapsGuestPtr guest;
+ char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" : "xenpv"};
+ virCapsGuestMachinePtr *machines;
+
+ if ((machines = virCapabilitiesAllocMachines(xen_machines, 1)) == NULL)
+ goto no_memory;
+
+ if ((guest = virCapabilitiesAddGuest(caps,
+ guest_archs[i].hvm ? "hvm" : "xen",
+ guest_archs[i].model,
+ guest_archs[i].bits,
+ (STREQ(hostmachine, "x86_64") ?
+ "/usr/lib64/xen/bin/qemu-dm" :
+ "/usr/lib/xen/bin/qemu-dm"),
+ (guest_archs[i].hvm ?
+ "/usr/lib/xen/boot/hvmloader" :
+ NULL),
+ 1,
+ machines)) == NULL) {
+ virCapabilitiesFreeMachines(machines, 1);
+ goto no_memory;
+ }
+ machines = NULL;
+
+ if (virCapabilitiesAddGuestDomain(guest,
+ "xen",
+ NULL,
+ NULL,
+ 0,
+ NULL) == NULL)
+ goto no_memory;
+
+ if (guest_archs[i].pae &&
+ virCapabilitiesAddGuestFeature(guest,
+ "pae",
+ 1,
+ 0) == NULL)
+ goto no_memory;
+
+ if (guest_archs[i].nonpae &&
+ virCapabilitiesAddGuestFeature(guest,
+ "nonpae",
+ 1,
+ 0) == NULL)
+ goto no_memory;
+
+ if (guest_archs[i].ia64_be &&
+ virCapabilitiesAddGuestFeature(guest,
+ "ia64_be",
+ 1,
+ 0) == NULL)
+ goto no_memory;
+
+ if (guest_archs[i].hvm) {
+ if (virCapabilitiesAddGuestFeature(guest,
+ "acpi",
+ 1,
+ 1) == NULL)
+ goto no_memory;
+
+ if (virCapabilitiesAddGuestFeature(guest, "apic",
+ 1,
+ 0) == NULL)
+ goto no_memory;
+
+ if (virCapabilitiesAddGuestFeature(guest,
+ "hap",
+ 0,
+ 1) == NULL)
+ goto no_memory;
+ }
+ }
+
+ caps->defaultConsoleTargetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
+
+ return caps;
+
+ no_memory:
+ virCapabilitiesFree(caps);
+ return NULL;
+}
+
+static virCapsPtr
+libxlMakeCapabilitiesInternal(const char *hostmachine,
+ libxl_physinfo *phy_info,
+ char *capabilities)
+{
+ char *str, *token;
+ regmatch_t subs[4];
+ char *saveptr = NULL;
+ int i;
+
+ int host_pae = 0;
+ struct guest_arch guest_archs[32];
+ int nr_guest_archs = 0;
+ virCapsPtr caps = NULL;
+
+ memset(guest_archs, 0, sizeof(guest_archs));
+
+ // TODO: extract pae from phy_info->phys_cap
+ // for now, better default is 1
+ (void)phy_info;
+ host_pae = 1;
+
+ /* Format of capabilities string is documented in the code in
+ * xen-unstable.hg/xen/arch/.../setup.c.
+ *
+ * It is a space-separated list of supported guest architectures.
+ *
+ * For x86:
+ * TYP-VER-ARCH[p]
+ * ^ ^ ^ ^
+ * | | | +-- PAE supported
+ * | | +------- x86_32 or x86_64
+ * | +----------- the version of Xen, eg. "3.0"
+ * +--------------- "xen" or "hvm" for para or full virt respectively
+ *
+ * For IA64:
+ * TYP-VER-ARCH[be]
+ * ^ ^ ^ ^
+ * | | | +-- Big-endian supported
+ * | | +------- always "ia64"
+ * | +----------- the version of Xen, eg. "3.0"
+ * +--------------- "xen" or "hvm" for para or full virt respectively
+ */
+
+ /* Split capabilities string into tokens. strtok_r is OK here because
+ * we "own" the buffer. Parse out the features from each token.
+ */
+ for (str = capabilities, nr_guest_archs = 0;
+ nr_guest_archs < sizeof guest_archs / sizeof guest_archs[0]
+ && (token = strtok_r (str, " ", &saveptr)) != NULL;
+ str = NULL) {
+ if (regexec(&xen_cap_rec, token, sizeof subs / sizeof subs[0],
+ subs, 0) == 0) {
+ int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm");
+ const char *model;
+ int bits, pae = 0, nonpae = 0, ia64_be = 0;
+
+ if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) {
+ model = "i686";
+ bits = 32;
+ if (subs[3].rm_so != -1 &&
+ STRPREFIX(&token[subs[3].rm_so], "p"))
+ pae = 1;
+ else
+ nonpae = 1;
+ }
+ else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) {
+ model = "x86_64";
+ bits = 64;
+ }
+ else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) {
+ model = "ia64";
+ bits = 64;
+ if (subs[3].rm_so != -1 &&
+ STRPREFIX(&token[subs[3].rm_so], "be"))
+ ia64_be = 1;
+ }
+ else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) {
+ model = "ppc64";
+ bits = 64;
+ } else {
+ continue;
+ }
+
+ /* Search for existing matching (model,hvm) tuple */
+ for (i = 0 ; i < nr_guest_archs ; i++) {
+ if (STREQ(guest_archs[i].model, model) &&
+ guest_archs[i].hvm == hvm) {
+ break;
+ }
+ }
+
+ /* Too many arch flavours - highly unlikely ! */
+ if (i >= ARRAY_CARDINALITY(guest_archs))
+ continue;
+ /* Didn't find a match, so create a new one */
+ if (i == nr_guest_archs)
+ nr_guest_archs++;
+
+ guest_archs[i].model = model;
+ guest_archs[i].bits = bits;
+ guest_archs[i].hvm = hvm;
+
+ /* Careful not to overwrite a previous positive
+ setting with a negative one here - some archs
+ can do both pae & non-pae, but Xen reports
+ separately capabilities so we're merging archs */
+ if (pae)
+ guest_archs[i].pae = pae;
+ if (nonpae)
+ guest_archs[i].nonpae = nonpae;
+ if (ia64_be)
+ guest_archs[i].ia64_be = ia64_be;
+ }
+ }
+
+ if ((caps = libxlBuildCapabilities(hostmachine,
+ host_pae,
+ guest_archs,
+ nr_guest_archs)) == NULL)
+ goto no_memory;
+
+ return caps;
+
+ no_memory:
+ virReportOOMError();
+ virCapabilitiesFree(caps);
+ return NULL;
+}
+
+static int
+libxlMakeDomCreateInfo(virDomainDefPtr def, libxl_domain_create_info *c_info)
+{
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+ libxl_init_create_info(c_info);
+
+ c_info->hvm = STREQ(def->os.type, "hvm");
+ if ((c_info->name = strdup(def->name)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+
+ virUUIDFormat(def->uuid, uuidstr);
+ if (libxl_uuid_from_string(&c_info->uuid, uuidstr) ) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("libxenlight failed to parse UUID '%s'"), uuidstr);
+ goto error;
+ }
+
+ return 0;
+
+error:
+ libxl_domain_create_info_destroy(c_info);
+ return -1;
+}
+
+static int
+libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_domain_config *d_config)
+{
+ libxl_domain_build_info *b_info = &d_config->b_info;
+ int hvm = STREQ(def->os.type, "hvm");
+
+ libxl_init_build_info(b_info, &d_config->c_info);
+
+ b_info->hvm = hvm;
+ b_info->max_vcpus = def->maxvcpus;
+ b_info->cur_vcpus = def->vcpus;
+ if (def->clock.ntimers > 0 &&
+ def->clock.timers[0]->name == VIR_DOMAIN_TIMER_NAME_TSC) {
+ switch (def->clock.timers[0]->mode) {
+ case VIR_DOMAIN_TIMER_MODE_NATIVE:
+ b_info->tsc_mode = 2;
+ break;
+ case VIR_DOMAIN_TIMER_MODE_PARAVIRT:
+ b_info->tsc_mode = 3;
+ break;
+ default:
+ b_info->tsc_mode = 1;
+ }
+ }
+ b_info->max_memkb = def->mem.max_balloon;
+ b_info->target_memkb = def->mem.cur_balloon;
+ if (hvm) {
+ b_info->u.hvm.pae = def->features & (1 << VIR_DOMAIN_FEATURE_PAE);
+ b_info->u.hvm.apic = def->features & (1 << VIR_DOMAIN_FEATURE_APIC);
+ b_info->u.hvm.acpi = def->features & (1 << VIR_DOMAIN_FEATURE_ACPI);
+ /* 256 pages (1MB) per vcpu,
+ plus 1 page per MiB of RAM for the P2M map,
+ plus 1 page per MiB of RAM to shadow the resident processes.
+ This is higher than the minimum that Xen would allocate if no value
+ were given (but the Xen minimum is for safety, not performance).
+ */
+ b_info->shadow_memkb = 4 * (256 * b_info->cur_vcpus +
+ 2 * (b_info->max_memkb / 1024));
+ } else {
+ if (def->os.bootloader) {
+ if ((b_info->u.pv.bootloader = strdup(def->os.bootloader)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ }
+ if (def->os.bootloaderArgs) {
+ if ((b_info->u.pv.bootloader_args = strdup(def->os.bootloaderArgs)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ }
+ if (def->os.cmdline) {
+ if ((b_info->u.pv.cmdline = strdup(def->os.cmdline)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ }
+ if (def->os.kernel) {
+ /* libxl_init_build_info() sets kernel.path = strdup("hvmloader") */
+ free(b_info->kernel.path);
+ if ((b_info->kernel.path = strdup(def->os.kernel)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ }
+ if (def->os.initrd) {
+ if ((b_info->u.pv.ramdisk.path = strdup(def->os.initrd)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ }
+ }
+
+ return 0;
+
+error:
+ libxl_domain_build_info_destroy(b_info);
+ return -1;
+}
+
+static int
+libxlMakeDiskList(virDomainDefPtr def, libxl_domain_config *d_config)
+{
+ virDomainDiskDefPtr *l_disks = def->disks;
+ int ndisks = def->ndisks;
+ libxl_device_disk *x_disks;
+ int i;
+
+ if (VIR_ALLOC_N(x_disks, ndisks) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ for (i = 0; i < ndisks; i++) {
+ if (l_disks[i]->src &&
+ (x_disks[i].pdev_path = strdup(l_disks[i]->src)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+
+ if (l_disks[i]->dst &&
+ (x_disks[i].vdev = strdup(l_disks[i]->dst)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+
+ if (l_disks[i]->driverName) {
+ if (STREQ(l_disks[i]->driverName, "tap") ||
+ STREQ(l_disks[i]->driverName, "tap2")) {
+ if (l_disks[i]->driverType) {
+ if (STREQ(l_disks[i]->driverType, "qcow")) {
+ x_disks[i].format = DISK_FORMAT_QCOW;
+ x_disks[i].backend = DISK_BACKEND_QDISK;
+ } else if (STREQ(l_disks[i]->driverType, "qcow2")) {
+ x_disks[i].format = DISK_FORMAT_QCOW2;
+ x_disks[i].backend = DISK_BACKEND_QDISK;
+ } else if (STREQ(l_disks[i]->driverType, "vhd")) {
+ x_disks[i].format = DISK_FORMAT_VHD;
+ x_disks[i].backend = DISK_BACKEND_TAP;
+ } else if (STREQ(l_disks[i]->driverType, "aio") ||
+ STREQ(l_disks[i]->driverType, "raw")) {
+ x_disks[i].format = DISK_FORMAT_RAW;
+ x_disks[i].backend = DISK_BACKEND_TAP;
+ }
+ } else {
+ /* No subtype specified, default to raw/tap */
+ x_disks[i].format = DISK_FORMAT_RAW;
+ x_disks[i].backend = DISK_BACKEND_TAP;
+ }
+ } else if (STREQ(l_disks[i]->driverName, "file")) {
+ x_disks[i].format = DISK_FORMAT_RAW;
+ x_disks[i].backend = DISK_BACKEND_TAP;
+ } else if (STREQ(l_disks[i]->driverName, "phy")) {
+ x_disks[i].format = DISK_FORMAT_RAW;
+ x_disks[i].backend = DISK_BACKEND_PHY;
+ } else {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("libxenlight does not support disk driver %s"),
+ l_disks[i]->driverName);
+ goto error;
+ }
+ } else {
+ /* No driverName - default to raw/tap?? */
+ x_disks[i].format = DISK_FORMAT_RAW;
+ x_disks[i].backend = DISK_BACKEND_TAP;
+ }
+
+ /* How to set unpluggable? */
+ x_disks[i].unpluggable = 1;
+ x_disks[i].readwrite = !l_disks[i]->readonly;
+ x_disks[i].is_cdrom =
+ l_disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM ? 1 : 0;
+ }
+
+ d_config->disks = x_disks;
+ d_config->num_disks = ndisks;
+
+ return 0;
+
+error:
+ for (i = 0; i < ndisks; i++)
+ libxl_device_disk_destroy(&x_disks[i]);
+ VIR_FREE(x_disks);
+ return -1;
+}
+
+static int
+libxlMakeNicList(virDomainDefPtr def, libxl_domain_config *d_config)
+{
+ virDomainNetDefPtr *l_nics = def->nets;
+ int nnics = def->nnets;
+ libxl_device_nic *x_nics;
+ int i;
+
+ if (VIR_ALLOC_N(x_nics, nnics) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ for (i = 0; i < nnics; i++) {
+ x_nics[i].devid = i;
+
+ // TODO: Where is mtu stored?
+ x_nics[i].mtu = 1492;
+
+ memcpy(x_nics[i].mac, l_nics[i]->mac, sizeof(libxl_mac));
+
+ if (l_nics[i]->model && !STREQ(l_nics[i]->model, "netfront")) {
+ if ((x_nics[i].model = strdup(l_nics[i]->model)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ x_nics[i].nictype = NICTYPE_IOEMU;
+ } else {
+ x_nics[i].nictype = NICTYPE_VIF;
+ }
+
+ if (l_nics[i]->ifname &&
+ (x_nics[i].ifname = strdup(l_nics[i]->ifname)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+
+ if (l_nics[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+ if (l_nics[i]->data.bridge.brname &&
+ (x_nics[i].bridge =
+ strdup(l_nics[i]->data.bridge.brname)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ if (l_nics[i]->data.bridge.script &&
+ (x_nics[i].script =
+ strdup(l_nics[i]->data.bridge.script)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ }
+
+ //TODO
+ //x_nics[i].ip = ;
+ }
+
+ d_config->vifs = x_nics;
+ d_config->num_vifs = nnics;
+
+ return 0;
+
+error:
+ for (i = 0; i < nnics; i++)
+ libxl_device_nic_destroy(&x_nics[i]);
+ VIR_FREE(x_nics);
+ return -1;
+}
+
+static int
+libxlMakeVfbList(virDomainDefPtr def, libxl_domain_config *d_config)
+{
+ virDomainGraphicsDefPtr *l_vfbs = def->graphics;
+ int nvfbs = def->ngraphics;
+ libxl_device_vfb *x_vfbs;
+ libxl_device_vkb *x_vkbs;
+ int i;
+
+ if (VIR_ALLOC_N(x_vfbs, nvfbs) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+ if (VIR_ALLOC_N(x_vkbs, nvfbs) < 0) {
+ virReportOOMError();
+ VIR_FREE(x_vfbs);
+ return -1;
+ }
+
+ for (i = 0; i < nvfbs; i++) {
+ libxl_device_vfb_init(&x_vfbs[i], i);
+ libxl_device_vkb_init(&x_vkbs[i], i);
+
+ switch (l_vfbs[i]->type) {
+ case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
+ x_vfbs[i].sdl = 1;
+ if (l_vfbs[i]->data.sdl.display &&
+ (x_vfbs[i].display =
+ strdup(l_vfbs[i]->data.sdl.display)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ if (l_vfbs[i]->data.sdl.xauth &&
+ (x_vfbs[i].xauthority =
+ strdup(l_vfbs[i]->data.sdl.xauth)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ break;
+ case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
+ x_vfbs[i].vnc = 1;
+ if (l_vfbs[i]->data.vnc.autoport)
+ x_vfbs[i].vncunused = 1;
+ else
+ x_vfbs[i].vncdisplay = l_vfbs[i]->data.vnc.port;
+
+ if (l_vfbs[i]->data.vnc.listenAddr) {
+ /* libxl_device_vfb_init() does strdup("127.0.0.1") */
+ free(x_vfbs[i].vnclisten);
+ if ((x_vfbs[i].vnclisten =
+ strdup(l_vfbs[i]->data.vnc.listenAddr)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ }
+ if (l_vfbs[i]->data.vnc.keymap &&
+ (x_vfbs[i].keymap =
+ strdup(l_vfbs[i]->data.vnc.keymap)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ break;
+ }
+ }
+
+ d_config->vfbs = x_vfbs;
+ d_config->vkbs = x_vkbs;
+ d_config->num_vfbs = d_config->num_vkbs = nvfbs;
+
+ return 0;
+
+error:
+ for (i = 0; i < nvfbs; i++) {
+ libxl_device_vfb_destroy(&x_vfbs[i]);
+ libxl_device_vkb_destroy(&x_vkbs[i]);
+ }
+ VIR_FREE(x_vfbs);
+ VIR_FREE(x_vkbs);
+ return -1;
+}
+
+static int
+libxlMakeChrdevStr(virDomainChrDefPtr def, char **buf)
+{
+ const char *type = virDomainChrTypeToString(def->source.type);
+
+ if (!type) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("unexpected chr device type"));
+ return -1;
+ }
+
+ switch (def->source.type) {
+ case VIR_DOMAIN_CHR_TYPE_NULL:
+ case VIR_DOMAIN_CHR_TYPE_STDIO:
+ case VIR_DOMAIN_CHR_TYPE_VC:
+ case VIR_DOMAIN_CHR_TYPE_PTY:
+ if (virAsprintf(buf, "%s", type) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_FILE:
+ case VIR_DOMAIN_CHR_TYPE_PIPE:
+ if (virAsprintf(buf, "%s:%s", type,
+ def->source.data.file.path) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_DEV:
+ if (virAsprintf(buf, "%s", def->source.data.file.path) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int
+libxlMakeDeviceModelInfo(virDomainDefPtr def, libxl_domain_config *d_config)
+{
+ libxl_device_model_info *dm_info = &d_config->dm_info;
+ int i;
+ char b_order[VIR_DOMAIN_BOOT_LAST+1];
+
+ libxl_init_dm_info(dm_info, &d_config->c_info, &d_config->b_info);
+
+ if (d_config->b_info.hvm) {
+ /* HVM-specific device model info */
+ dm_info->type = XENFV;
+ if (def->os.nBootDevs > 0) {
+ free(dm_info->boot);
+ for (i = 0; i < def->os.nBootDevs; i++) {
+ switch (def->os.bootDevs[i]) {
+ case VIR_DOMAIN_BOOT_FLOPPY:
+ b_order[i] = 'a';
+ break;
+ default:
+ case VIR_DOMAIN_BOOT_DISK:
+ b_order[i] = 'c';
+ break;
+ case VIR_DOMAIN_BOOT_CDROM:
+ b_order[i] = 'd';
+ break;
+ case VIR_DOMAIN_BOOT_NET:
+ b_order[i] = 'n';
+ break;
+ }
+ }
+ b_order[def->os.nBootDevs] = '\0';
+ if ((dm_info->boot = strdup(b_order)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ }
+ if (def->serials &&
+ (libxlMakeChrdevStr(def->serials[0], &dm_info->serial) < 0))
+ goto error;
+ } else {
+ /* PV-specific device model info */
+ dm_info->type = XENPV;
+ }
+
+ if (def->ngraphics > 0) {
+ if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+ dm_info->vnc = 1;
+ if (def->graphics[0]->data.vnc.listenAddr) {
+ free(dm_info->vnclisten);
+ if ((dm_info->vnclisten =
+ strdup(def->graphics[0]->data.vnc.listenAddr)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ }
+ if (def->graphics[0]->data.vnc.keymap &&
+ (dm_info->keymap =
+ strdup(def->graphics[0]->data.vnc.keymap)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ if (def->graphics[0]->data.vnc.autoport)
+ dm_info->vncunused = 1;
+ else
+ dm_info->vncdisplay = def->graphics[0]->data.vnc.port;
+ if (def->graphics[0]->data.vnc.auth.passwd &&
+ (dm_info->vncpasswd =
+ strdup(def->graphics[0]->data.vnc.auth.passwd)) == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+ } else if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+ dm_info->sdl = 1;
+ dm_info->vnc = 0;
+ }
+ } else if (def->ngraphics == 0) {
+ dm_info->nographic = 1;
+ dm_info->vnc = 0;
+ }
+
+ // TODO
+ //dm_info->usb = ;
+ //dm_info->usbdevice = ;
+ //dm_info->soundhw = ;
+
+ return 0;
+
+error:
+ libxl_device_model_info_destroy(dm_info);
+ return -1;
+}
+
+virCapsPtr
+libxlMakeCapabilities(libxl_ctx *ctx)
+{
+ libxl_physinfo phy_info;
+ const libxl_version_info *ver_info;
+ struct utsname utsname;
+
+ regcomp (&xen_cap_rec, xen_cap_re, REG_EXTENDED);
+
+ if (libxl_get_physinfo(ctx, &phy_info) != 0) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to get node physical info from libxenlight"));
+ return NULL;
+ }
+
+ if ((ver_info = libxl_get_version_info(ctx)) == NULL) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to get version info from libxenlight"));
+ return NULL;
+ }
+
+ uname(&utsname);
+
+ return libxlMakeCapabilitiesInternal(utsname.machine,
+ &phy_info,
+ ver_info->capabilities);
+}
+
+int
+libxlLoadRunningDomains(libxlDriverPrivatePtr driver)
+{
+ libxl_dominfo *domains;
+ int n_domains;
+ int i;
+ int ret = -1;
+ int len;
+ uint8_t *data = NULL;
+ virDomainDefPtr def = NULL;
+ virDomainObjPtr vm = NULL;
+
+ if (!(domains = libxl_list_domain(&driver->ctx, &n_domains))) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to retrieve domain list from libxenlight"));
+ return -1;
+ }
+
+ for (i = 0; i < n_domains; i++) {
+ /* ignore dom0?? */
+ if (domains[i].domid == 0)
+ continue;
+
+ /* Ignore domains that don't contain libvirtXML */
+ if (libxl_userdata_retrieve(&driver->ctx, domains[i].domid,
+ "libvirt-xml", &data, &len)) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to retrieve domain userdata from libxenlight"));
+ continue;
+ }
+ /* Ensure userdata_retrieve gave us some data */
+ if (len == 0)
+ continue;
+
+ if (!(def = virDomainDefParseString(driver->caps, (char *)data, 0))) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to parse userdata from libxenlight"));
+ goto cleanup;
+ }
+
+ if (!(vm = virDomainAssignDef(driver->caps,
+ &driver->domains, def, false)))
+ goto cleanup;
+
+ def = NULL;
+ free(data);
+ data = NULL;
+ vm->persistent = 1;
+
+ if (virDomainSaveConfig(driver->configDir,
+ vm->newDef ? vm->newDef : vm->def) < 0) {
+ virDomainRemoveInactive(&driver->domains, vm);
+ vm = NULL;
+ goto cleanup;
+ }
+ virDomainObjUnlock(vm);
+ vm = NULL;
+ }
+ ret = 0;
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ virDomainDefFree(def);
+ free(data);
+ free(domains);
+ return ret;
+}
+
+int
+libxlBuildDomainConfig(virDomainDefPtr def, libxl_domain_config *d_config)
+{
+
+ if (libxlMakeDomCreateInfo(def, &d_config->c_info) < 0)
+ return -1;
+
+ if (libxlMakeDomBuildInfo(def, d_config) < 0) {
+ goto error;
+ }
+
+ if (libxlMakeDiskList(def, d_config) < 0) {
+ goto error;
+ }
+
+ if (libxlMakeNicList(def, d_config) < 0) {
+ goto error;
+ }
+
+ if (libxlMakeVfbList(def, d_config) < 0) {
+ goto error;
+ }
+
+ if (libxlMakeDeviceModelInfo(def, d_config) < 0) {
+ goto error;
+ }
+
+ d_config->on_reboot = def->onReboot;
+ d_config->on_poweroff = def->onPoweroff;
+ d_config->on_crash = def->onCrash;
+
+ return 0;
+
+error:
+ libxl_domain_config_destroy(d_config);
+ return -1;
+}
diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h
new file mode 100644
index 0000000..1c4eff3
--- /dev/null
+++ b/src/libxl/libxl_conf.h
@@ -0,0 +1,88 @@
+/*---------------------------------------------------------------------------*/
+/* Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * 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 LIBXL_CONF_H
+# define LIBXL_CONF_H
+
+# include <config.h>
+
+# include <libxl.h>
+
+# include "internal.h"
+# include "domain_conf.h"
+# include "capabilities.h"
+# include "configmake.h"
+
+
+# define LIBXL_CONFIG_DIR SYSCONFDIR "/libvirt/libxl"
+# define LIBXL_AUTOSTART_DIR LIBXL_CONFIG_DIR "/autostart"
+# define LIBXL_STATE_DIR LOCALSTATEDIR "/run/libvirt/libxl"
+# define LIBXL_LOG_DIR LOCALSTATEDIR "/log/libvirt/libxl"
+# define LIBXL_LIB_DIR LOCALSTATEDIR "/lib/libvirt/libxl"
+# define LIBXL_SAVE_DIR LIBXL_LIB_DIR "/save"
+
+
+typedef struct _libxlDriverPrivate libxlDriverPrivate;
+typedef libxlDriverPrivate *libxlDriverPrivatePtr;
+struct _libxlDriverPrivate {
+ virMutex lock;
+ virCapsPtr caps;
+ unsigned int version;
+
+ FILE *logger_file;
+ xentoollog_logger *logger;
+ /* libxl ctx for driver wide ops; getVersion, getNodeInfo, ... */
+ libxl_ctx ctx;
+
+ virDomainObjList domains;
+
+ char *configDir;
+ char *autostartDir;
+ char *logDir;
+ char *stateDir;
+ char *libDir;
+ char *saveDir;
+};
+
+typedef struct _libxlDomainObjPrivate libxlDomainObjPrivate;
+typedef libxlDomainObjPrivate *libxlDomainObjPrivatePtr;
+struct _libxlDomainObjPrivate {
+ /* per domain libxl ctx */
+ libxl_ctx ctx;
+ libxl_waiter *dWaiter;
+ int waiterFD;
+ int eventHdl;
+};
+
+
+# define libxlError(code, ...) \
+ virReportErrorHelper(NULL, VIR_FROM_LIBXL, code, __FILE__, \
+ __FUNCTION__, __LINE__, __VA_ARGS__)
+
+virCapsPtr
+libxlMakeCapabilities(libxl_ctx *ctx);
+
+int
+libxlLoadRunningDomains(libxlDriverPrivatePtr driver);
+
+int
+libxlBuildDomainConfig(virDomainDefPtr def, libxl_domain_config *d_config);
+
+
+#endif /* LIBXL_CONF_H */
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
new file mode 100644
index 0000000..d38f5a0
--- /dev/null
+++ b/src/libxl/libxl_driver.c
@@ -0,0 +1,1281 @@
+/*---------------------------------------------------------------------------*/
+/* Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ * Copyright (C) 2011 Univention GmbH.
+ *
+ * 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 <config.h>
+
+#include <sys/utsname.h>
+#include <libxl.h>
+
+#include "internal.h"
+#include "logging.h"
+#include "virterror_internal.h"
+#include "datatypes.h"
+#include "files.h"
+#include "memory.h"
+#include "event.h"
+#include "uuid.h"
+#include "libxl_driver.h"
+#include "libxl_conf.h"
+
+
+#define VIR_FROM_THIS VIR_FROM_LIBXL
+
+#define LIBXL_DOM_REQ_POWEROFF 0
+#define LIBXL_DOM_REQ_REBOOT 1
+#define LIBXL_DOM_REQ_SUSPEND 2
+#define LIBXL_DOM_REQ_CRASH 3
+#define LIBXL_DOM_REQ_HALT 4
+
+static libxlDriverPrivatePtr libxl_driver = NULL;
+
+
+/* Function declarations */
+static int
+libxlVmStart(virDomainObjPtr vm, bool start_paused);
+
+
+/* Function definitions */
+static void
+libxlDriverLock(libxlDriverPrivatePtr driver)
+{
+ virMutexLock(&driver->lock);
+}
+
+static void
+libxlDriverUnlock(libxlDriverPrivatePtr driver)
+{
+ virMutexUnlock(&driver->lock);
+}
+
+static void *libxlDomainObjPrivateAlloc(void)
+{
+ libxlDomainObjPrivatePtr priv;
+
+ if (VIR_ALLOC(priv) < 0)
+ return NULL;
+
+ libxl_ctx_init(&priv->ctx, LIBXL_VERSION, libxl_driver->logger);
+ priv->waiterFD = -1;
+ priv->eventHdl = -1;
+
+ return priv;
+}
+
+static void libxlDomainObjPrivateFree(void *data)
+{
+ libxlDomainObjPrivatePtr priv = data;
+
+ if (priv->dWaiter) {
+ libxl_free_waiter(priv->dWaiter);
+ VIR_FREE(priv->dWaiter);
+ }
+ libxl_ctx_free(&priv->ctx);
+ VIR_FREE(priv);
+}
+
+static void libxlEventHandler(int watch,
+ int fd,
+ int events,
+ void *data)
+{
+ libxlDriverPrivatePtr driver = libxl_driver;
+ virDomainObjPtr vm = data;
+ libxlDomainObjPrivatePtr priv;
+ libxl_event event;
+ libxl_dominfo info;
+
+ libxlDriverLock(driver);
+ virDomainObjLock(vm);
+ libxlDriverUnlock(driver);
+
+ priv = vm->privateData;
+
+ memset(&event, 0, sizeof(event));
+ memset(&info, 0, sizeof(info));
+
+ if (priv->waiterFD != fd || priv->eventHdl != watch) {
+ virEventRemoveHandle(watch);
+ goto cleanup;
+ }
+
+ if (!(events & VIR_EVENT_HANDLE_READABLE))
+ goto cleanup;
+
+ if (libxl_get_event(&priv->ctx, &event))
+ goto cleanup;
+
+ if (event.type == LIBXL_EVENT_DOMAIN_DEATH) {
+ /* libxl_event_get_domain_death_info returns 1 if death
+ * event was for this domid */
+ if (libxl_event_get_domain_death_info(&priv->ctx,
+ vm->def->id,
+ &event,
+ &info) != 1)
+ goto cleanup;
+
+ virEventRemoveHandle(watch);
+ switch (info.shutdown_reason) {
+ case SHUTDOWN_poweroff:
+ case SHUTDOWN_crash:
+ libxl_domain_destroy(&priv->ctx, vm->def->id, 0);
+ if (vm->persistent) {
+ vm->def->id = -1;
+ vm->state = VIR_DOMAIN_SHUTOFF;
+ } else {
+ libxl_free_waiter(priv->dWaiter);
+ VIR_FREE(priv->dWaiter);
+ virDomainRemoveInactive(&driver->domains, vm);
+ vm = NULL;
+ }
+ break;
+ case SHUTDOWN_reboot:
+ libxl_domain_destroy(&priv->ctx, vm->def->id, 0);
+ vm->def->id = -1;
+ vm->state = VIR_DOMAIN_SHUTOFF;
+ libxlVmStart(vm, 0);
+ break;
+ default:
+ VIR_INFO("Unhandled shutdown_reason %d", info.shutdown_reason);
+ break;
+ }
+ }
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ libxl_free_event(&event);
+}
+
+static int
+libxlCreateDomEvents(virDomainObjPtr vm)
+{
+ libxlDomainObjPrivatePtr priv = vm->privateData;
+ int fd;
+
+ /* Do we already have a waiter for this domain? */
+ if (priv->dWaiter == NULL) {
+ if (VIR_ALLOC(priv->dWaiter) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ if (libxl_wait_for_domain_death(&priv->ctx,
+ vm->def->id,
+ priv->dWaiter))
+ goto error;
+ }
+
+ libxl_get_wait_fd(&priv->ctx, &fd);
+ if (fd < 0)
+ goto error;
+
+ priv->waiterFD = fd;
+ if ((priv->eventHdl = virEventAddHandle(
+ fd,
+ VIR_EVENT_HANDLE_READABLE | VIR_EVENT_HANDLE_ERROR,
+ libxlEventHandler,
+ vm, NULL)) < 0)
+ goto error;
+
+ return 0;
+
+error:
+ libxl_free_waiter(priv->dWaiter);
+ VIR_FREE(priv->dWaiter);
+ return -1;
+}
+
+static int
+libxlVmStart(virDomainObjPtr vm, bool start_paused)
+{
+ libxl_domain_config d_config;
+ virDomainDefPtr def = vm->def;
+ int ret;
+ uint32_t domid = 0;
+ char *dom_xml = NULL;
+ pid_t child_console_pid = -1;
+ libxlDomainObjPrivatePtr priv = vm->privateData;
+
+ memset(&d_config, 0, sizeof(d_config));
+
+ if (libxlBuildDomainConfig(def, &d_config) < 0 )
+ return -1;
+
+ //TODO: Balloon dom0 ??
+ //ret = freemem(&d_config->b_info, &d_config->dm_info);
+
+ ret = libxl_domain_create_new(&priv->ctx, &d_config,
+ NULL, &child_console_pid, &domid);
+ if (ret) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("libxenlight failed to create new domain '%s'"),
+ d_config.c_info.name);
+ goto error;
+ }
+
+ def->id = domid;
+ if ((dom_xml = virDomainDefFormat(def, 0)) == NULL)
+ goto error;
+
+ if(libxl_userdata_store(&priv->ctx, domid, "libvirt-xml",
+ (uint8_t *)dom_xml, strlen(dom_xml) + 1)) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("libxenlight failed to store userdata"));
+ goto error;
+ }
+
+ if (libxlCreateDomEvents(vm) < 0)
+ goto error;
+
+ if (!start_paused) {
+ libxl_domain_unpause(&priv->ctx, domid);
+ vm->state = VIR_DOMAIN_RUNNING;
+ } else {
+ vm->state = VIR_DOMAIN_PAUSED;
+ }
+
+ libxl_domain_config_destroy(&d_config);
+ VIR_FREE(dom_xml);
+ return 0;
+
+error:
+ if (domid > 0) {
+ libxl_domain_destroy(&priv->ctx, domid, 0);
+ def->id = -1;
+ }
+ libxl_domain_config_destroy(&d_config);
+ VIR_FREE(dom_xml);
+ return -1;
+}
+
+static int
+libxlShutdown(void)
+{
+ if (!libxl_driver)
+ return -1;
+
+ libxlDriverLock(libxl_driver);
+ virCapabilitiesFree(libxl_driver->caps);
+ libxl_ctx_free(&libxl_driver->ctx);
+ xtl_logger_destroy(libxl_driver->logger);
+ if (libxl_driver->logger_file)
+ VIR_FORCE_FCLOSE(libxl_driver->logger_file);
+
+ virDomainObjListDeinit(&libxl_driver->domains);
+
+ VIR_FREE(libxl_driver->configDir);
+ VIR_FREE(libxl_driver->autostartDir);
+ VIR_FREE(libxl_driver->logDir);
+ VIR_FREE(libxl_driver->stateDir);
+ VIR_FREE(libxl_driver->libDir);
+ VIR_FREE(libxl_driver->saveDir);
+
+ libxlDriverUnlock(libxl_driver);
+ virMutexDestroy(&libxl_driver->lock);
+ VIR_FREE(libxl_driver);
+
+ return 0;
+}
+
+static int
+libxlStartup(int privileged) {
+ const libxl_version_info *ver_info;
+ char *log_file = NULL;
+
+ /* Check that the user is root, silently disable if not */
+ if (!privileged) {
+ VIR_INFO0("Not running privileged, disabling libxenlight driver");
+ return 0;
+ }
+
+ if (VIR_ALLOC(libxl_driver) < 0)
+ return -1;
+
+ if (virMutexInit(&libxl_driver->lock) < 0) {
+ VIR_ERROR0(_("cannot initialize mutex"));
+ VIR_FREE(libxl_driver);
+ return -1;
+ }
+ libxlDriverLock(libxl_driver);
+
+ if (virDomainObjListInit(&libxl_driver->domains) < 0)
+ goto out_of_memory;
+
+ if (virAsprintf(&libxl_driver->configDir,
+ "%s", LIBXL_CONFIG_DIR) == -1)
+ goto out_of_memory;
+
+ if (virAsprintf(&libxl_driver->autostartDir,
+ "%s", LIBXL_AUTOSTART_DIR) == -1)
+ goto out_of_memory;
+
+ if (virAsprintf(&libxl_driver->logDir,
+ "%s", LIBXL_LOG_DIR) == -1)
+ goto out_of_memory;
+
+ if (virAsprintf(&libxl_driver->stateDir,
+ "%s", LIBXL_STATE_DIR) == -1)
+ goto out_of_memory;
+
+ if (virAsprintf(&libxl_driver->libDir,
+ "%s", LIBXL_LIB_DIR) == -1)
+ goto out_of_memory;
+
+ if (virAsprintf(&libxl_driver->saveDir,
+ "%s", LIBXL_SAVE_DIR) == -1)
+ goto out_of_memory;
+
+ if (virFileMakePath(libxl_driver->logDir) != 0) {
+ char ebuf[1024];
+ VIR_ERROR(_("Failed to create log dir '%s': %s"),
+ libxl_driver->logDir, virStrerror(errno, ebuf, sizeof ebuf));
+ goto error;
+ }
+ if (virFileMakePath(libxl_driver->stateDir) != 0) {
+ char ebuf[1024];
+ VIR_ERROR(_("Failed to create state dir '%s': %s"),
+ libxl_driver->stateDir, virStrerror(errno, ebuf, sizeof ebuf));
+ goto error;
+ }
+ if (virFileMakePath(libxl_driver->libDir) != 0) {
+ char ebuf[1024];
+ VIR_ERROR(_("Failed to create lib dir '%s': %s"),
+ libxl_driver->libDir, virStrerror(errno, ebuf, sizeof ebuf));
+ goto error;
+ }
+ if (virFileMakePath(libxl_driver->saveDir) != 0) {
+ char ebuf[1024];
+ VIR_ERROR(_("Failed to create save dir '%s': %s"),
+ libxl_driver->saveDir, virStrerror(errno, ebuf, sizeof ebuf));
+ goto error;
+ }
+
+ if (virAsprintf(&log_file, "%s/libxl.log", libxl_driver->logDir) < 0) {
+ goto out_of_memory;
+ }
+
+ if ((libxl_driver->logger_file = fopen(log_file, "a")) == NULL) {
+ virReportSystemError(errno,
+ _("failed to create logfile %s"),
+ log_file);
+ goto error;
+ }
+ VIR_FREE(log_file);
+
+ libxl_driver->logger =
+ (xentoollog_logger *)xtl_createlogger_stdiostream(libxl_driver->logger_file, XTL_DEBUG, 0);
+ if (!libxl_driver->logger) {
+ VIR_ERROR0(_("cannot create logger for libxenlight"));
+ goto error;
+ }
+
+ if (libxl_ctx_init(&libxl_driver->ctx,
+ LIBXL_VERSION,
+ libxl_driver->logger)) {
+ VIR_ERROR0(_("cannot initialize libxenlight context"));
+ goto error;
+ }
+
+ if ((ver_info = libxl_get_version_info(&libxl_driver->ctx)) == NULL) {
+ VIR_ERROR0(_("cannot version information from libxenlight"));
+ goto error;
+ }
+ libxl_driver->version = (ver_info->xen_version_major * 1000000) +
+ (ver_info->xen_version_minor * 1000);
+
+ if ((libxl_driver->caps =
+ libxlMakeCapabilities(&libxl_driver->ctx)) == NULL) {
+ VIR_ERROR0(_("cannot create capabilities for libxenlight"));
+ goto error;
+ }
+
+ libxl_driver->caps->privateDataAllocFunc = libxlDomainObjPrivateAlloc;
+ libxl_driver->caps->privateDataFreeFunc = libxlDomainObjPrivateFree;
+
+ /* Get running domains from libxenlight */
+ if (libxlLoadRunningDomains(libxl_driver) < 0)
+ goto error;
+
+ /* Then inactive persistent configs */
+ if (virDomainLoadAllConfigs(libxl_driver->caps,
+ &libxl_driver->domains,
+ libxl_driver->configDir,
+ libxl_driver->autostartDir,
+ 0, NULL, NULL) < 0)
+ goto error;
+
+ libxlDriverUnlock(libxl_driver);
+
+ // TODO: autostart domains
+ //libxlAutostartConfigs(libxl_driver);
+
+ return 0;
+
+out_of_memory:
+ virReportOOMError();
+error:
+ VIR_FREE(log_file);
+ if (libxl_driver)
+ libxlDriverUnlock(libxl_driver);
+ libxlShutdown();
+ return -1;
+}
+
+/**
+ * libxlReload:
+ *
+ * Function to restart the libxenligt driver. Configuration files
+ * will be reloaded and driver state updated.
+ */
+static int
+libxlReload(void)
+{
+ if (!libxl_driver)
+ return 0;
+
+ libxlDriverLock(libxl_driver);
+ virDomainLoadAllConfigs(libxl_driver->caps,
+ &libxl_driver->domains,
+ libxl_driver->configDir,
+ libxl_driver->autostartDir,
+ 0, NULL, libxl_driver);
+ libxlDriverUnlock(libxl_driver);
+
+ // TODO
+ //libxlAutostartConfigs(libxl_driver);
+
+ return 0;
+}
+
+static int
+libxlActive(void)
+{
+ if (!libxl_driver)
+ return 0;
+
+ return 1;
+}
+
+static virDrvOpenStatus
+libxlOpen(virConnectPtr conn,
+ virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED)
+{
+ if (conn->uri == NULL) {
+ if (libxl_driver == NULL)
+ return VIR_DRV_OPEN_DECLINED;
+
+ conn->uri = xmlParseURI("libxl:///");
+ if (!conn->uri) {
+ virReportOOMError();
+ return VIR_DRV_OPEN_ERROR;
+ }
+ } else {
+ if (conn->uri->scheme == NULL || STRNEQ(conn->uri->scheme, "libxl"))
+ return VIR_DRV_OPEN_DECLINED;
+
+ /* If server name is given, its for remote driver */
+ if (conn->uri->server != NULL)
+ return VIR_DRV_OPEN_DECLINED;
+
+ if (libxl_driver == NULL) {
+ libxlError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("libxenlight state driver is not active"));
+ return VIR_DRV_OPEN_ERROR;
+ }
+
+ /* /session isn't supported in libxenlight */
+ if (conn->uri->path &&
+ STRNEQ(conn->uri->path, "") &&
+ STRNEQ(conn->uri->path, "/") &&
+ STRNEQ(conn->uri->path, "/system")) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected Xen URI path '%s', try libxl:///"),
+ NULLSTR(conn->uri->path));
+ return VIR_DRV_OPEN_ERROR;
+ }
+ }
+
+ conn->privateData = libxl_driver;
+
+ return VIR_DRV_OPEN_SUCCESS;
+};
+
+static int
+libxlClose(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+ conn->privateData = NULL;
+ return 0;
+}
+
+static const char *
+libxlGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+ return "libxl";
+}
+
+static int
+libxlGetVersion(virConnectPtr conn, unsigned long *version)
+{
+ libxlDriverPrivatePtr driver = conn->privateData;
+
+ libxlDriverLock(driver);
+ *version = driver->version;
+ libxlDriverUnlock(driver);
+ return 0;
+}
+
+static int
+libxlGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED)
+{
+ int ret;
+ libxlDriverPrivatePtr driver = conn->privateData;
+
+ ret = libxl_get_max_cpus(&driver->ctx);
+ /* libxl_get_max_cpus() will return 0 if there were any failures,
+ e.g. xc_physinfo() failing */
+ if (ret == 0)
+ return -1;
+
+ return ret;
+}
+
+static int
+libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
+{
+ libxl_physinfo phy_info;
+ const libxl_version_info* ver_info;
+ libxlDriverPrivatePtr driver = conn->privateData;
+ struct utsname utsname;
+
+ if (libxl_get_physinfo(&driver->ctx, &phy_info)) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("libxl_get_physinfo_info failed"));
+ return -1;
+ }
+
+ if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("libxl_get_version_info failed"));
+ return -1;
+ }
+
+ uname(&utsname);
+ if (virStrncpy(info->model,
+ utsname.machine,
+ strlen(utsname.machine),
+ sizeof(info->model)) == NULL) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("machine type %s too big for destination"),
+ utsname.machine);
+ return -1;
+ }
+
+ info->memory = phy_info.total_pages * (ver_info->pagesize / 1024);
+ info->cpus = phy_info.nr_cpus;
+ info->nodes = phy_info.nr_nodes;
+ info->cores = phy_info.cores_per_socket;
+ info->threads = phy_info.threads_per_core;
+ info->sockets = 1;
+ info->mhz = phy_info.cpu_khz / 1000;
+ return 0;
+}
+
+static char *
+libxlGetCapabilities(virConnectPtr conn)
+{
+ libxlDriverPrivatePtr driver = conn->privateData;
+ char *xml;
+
+ libxlDriverLock(driver);
+ if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
+ virReportOOMError();
+ libxlDriverUnlock(driver);
+
+ return xml;
+}
+
+static int
+libxlListDomains(virConnectPtr conn, int *ids, int nids)
+{
+ libxlDriverPrivatePtr driver = conn->privateData;
+ int n;
+
+ libxlDriverLock(driver);
+ n = virDomainObjListGetActiveIDs(&driver->domains, ids, nids);
+ libxlDriverUnlock(driver);
+
+ return n;
+}
+
+static int
+libxlNumDomains(virConnectPtr conn)
+{
+ libxlDriverPrivatePtr driver = conn->privateData;
+ int n;
+
+ libxlDriverLock(driver);
+ n = virDomainObjListNumOfDomains(&driver->domains, 1);
+ libxlDriverUnlock(driver);
+
+ return n;
+}
+
+static virDomainPtr
+libxlDomainCreateXML(virConnectPtr conn, const char *xml,
+ unsigned int flags)
+{
+ libxlDriverPrivatePtr driver = conn->privateData;
+ virDomainDefPtr def;
+ virDomainObjPtr vm = NULL;
+ virDomainPtr dom = NULL;
+
+ virCheckFlags(VIR_DOMAIN_START_PAUSED, NULL);
+
+ libxlDriverLock(driver);
+ if (!(def = virDomainDefParseString(driver->caps, xml,
+ VIR_DOMAIN_XML_INACTIVE)))
+ goto cleanup;
+
+ if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
+ goto cleanup;
+
+ if (!(vm = virDomainAssignDef(driver->caps,
+ &driver->domains, def, false)))
+ goto cleanup;
+ def = NULL;
+
+ if (libxlVmStart(vm, (flags & VIR_DOMAIN_START_PAUSED) != 0) < 0) {
+ virDomainRemoveInactive(&driver->domains, vm);
+ vm = NULL;
+ goto cleanup;
+ }
+
+ dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
+ if (dom)
+ dom->id = vm->def->id;
+
+cleanup:
+ virDomainDefFree(def);
+ if (vm)
+ virDomainObjUnlock(vm);
+ libxlDriverUnlock(driver);
+ return dom;
+}
+
+static virDomainPtr
+libxlDomainLookupByID(virConnectPtr conn, int id)
+{
+ libxlDriverPrivatePtr driver = conn->privateData;
+ virDomainObjPtr vm;
+ virDomainPtr dom = NULL;
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByID(&driver->domains, id);
+ libxlDriverUnlock(driver);
+
+ if (!vm) {
+ libxlError(VIR_ERR_NO_DOMAIN, NULL);
+ goto cleanup;
+ }
+
+ dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
+ if (dom)
+ dom->id = vm->def->id;
+
+ cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ return dom;
+}
+
+static virDomainPtr
+libxlDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
+{
+ libxlDriverPrivatePtr driver = conn->privateData;
+ virDomainObjPtr vm;
+ virDomainPtr dom = NULL;
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, uuid);
+ libxlDriverUnlock(driver);
+
+ if (!vm) {
+ libxlError(VIR_ERR_NO_DOMAIN, NULL);
+ goto cleanup;
+ }
+
+ dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
+ if (dom)
+ dom->id = vm->def->id;
+
+ cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ return dom;
+}
+
+static virDomainPtr
+libxlDomainLookupByName(virConnectPtr conn, const char *name)
+{
+ libxlDriverPrivatePtr driver = conn->privateData;
+ virDomainObjPtr vm;
+ virDomainPtr dom = NULL;
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByName(&driver->domains, name);
+ libxlDriverUnlock(driver);
+
+ if (!vm) {
+ libxlError(VIR_ERR_NO_DOMAIN, NULL);
+ goto cleanup;
+ }
+
+ dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
+ if (dom)
+ dom->id = vm->def->id;
+
+ cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ return dom;
+}
+
+static int
+libxlDomainShutdown(virDomainPtr dom)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ virDomainObjPtr vm;
+ int ret = -1;
+ libxlDomainObjPrivatePtr priv;
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ libxlError(VIR_ERR_NO_DOMAIN,
+ _("No domain with matching uuid '%s'"), uuidstr);
+ goto cleanup;
+ }
+
+ if (!virDomainObjIsActive(vm)) {
+ libxlError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("Domain is not running"));
+ goto cleanup;
+ }
+
+ priv = vm->privateData;
+ if (libxl_domain_shutdown(&priv->ctx, dom->id, LIBXL_DOM_REQ_POWEROFF) != 0) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to shutdown domain '%d' with libxenlight"),
+ dom->id);
+ goto cleanup;
+ }
+
+ /* vm is marked shutoff (or removed from domains list if not persistent)
+ * in shutdown event handler.
+ */
+ ret = 0;
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ libxlDriverUnlock(driver);
+ return ret;
+}
+
+static int
+libxlDomainReboot(virDomainPtr dom, unsigned int flags ATTRIBUTE_UNUSED)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ virDomainObjPtr vm;
+ int ret = -1;
+ libxlDomainObjPrivatePtr priv;
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ libxlError(VIR_ERR_NO_DOMAIN,
+ _("No domain with matching uuid '%s'"), uuidstr);
+ goto cleanup;
+ }
+
+ if (!virDomainObjIsActive(vm)) {
+ libxlError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("Domain is not running"));
+ goto cleanup;
+ }
+
+ priv = vm->privateData;
+ if (libxl_domain_shutdown(&priv->ctx, dom->id, LIBXL_DOM_REQ_REBOOT) != 0) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to reboot domain '%d' with libxenlight"),
+ dom->id);
+ goto cleanup;
+ }
+ ret = 0;
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ libxlDriverUnlock(driver);
+ return ret;
+}
+
+static int
+libxlDomainDestroy(virDomainPtr dom)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ virDomainObjPtr vm;
+ int ret = -1;
+ libxlDomainObjPrivatePtr priv;
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ libxlError(VIR_ERR_NO_DOMAIN,
+ _("No domain with matching uuid '%s'"), uuidstr);
+ goto cleanup;
+ }
+
+ if (!virDomainObjIsActive(vm)) {
+ libxlError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("Domain is not running"));
+ goto cleanup;
+ }
+
+ priv = vm->privateData;
+ if (libxl_domain_destroy(&priv->ctx, dom->id, 1) != 0) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to destroy domain '%d' with libxenlight"),
+ dom->id);
+ goto cleanup;
+ }
+
+ /* Direct kill of domain wont be handled in event callback.
+ * Cleanup here. */
+ if (vm->persistent) {
+ vm->def->id = -1;
+ vm->state = VIR_DOMAIN_SHUTOFF;
+ } else {
+ libxl_free_waiter(priv->dWaiter);
+ VIR_FREE(priv->dWaiter);
+ virDomainRemoveInactive(&driver->domains, vm);
+ vm = NULL;
+ }
+
+ ret = 0;
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ libxlDriverUnlock(driver);
+ return ret;
+}
+
+static int
+libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ virDomainObjPtr vm;
+ int ret = -1;
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ libxlDriverUnlock(driver);
+
+ if (!vm) {
+ libxlError(VIR_ERR_NO_DOMAIN, "%s",
+ _("no domain with matching uuid"));
+ goto cleanup;
+ }
+
+ info->state = vm->state;
+ info->cpuTime = 0;
+ info->maxMem = vm->def->mem.max_balloon;
+ info->memory = vm->def->mem.cur_balloon;
+ info->nrVirtCpu = vm->def->vcpus;
+ ret = 0;
+
+ cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ return ret;
+}
+
+static char *
+libxlDomainDumpXML(virDomainPtr dom, int flags)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ virDomainObjPtr vm;
+ char *ret = NULL;
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ libxlDriverUnlock(driver);
+
+ if (!vm) {
+ libxlError(VIR_ERR_NO_DOMAIN, "%s",
+ _("no domain with matching uuid"));
+ goto cleanup;
+ }
+
+ ret = virDomainDefFormat(vm->def, flags);
+
+ cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ return ret;
+}
+
+static int
+libxlListDefinedDomains(virConnectPtr conn,
+ char **const names, int nnames)
+{
+ libxlDriverPrivatePtr driver = conn->privateData;
+ int n;
+
+ libxlDriverLock(driver);
+ n = virDomainObjListGetInactiveNames(&driver->domains, names, nnames);
+ libxlDriverUnlock(driver);
+ return n;
+}
+
+static int
+libxlNumDefinedDomains(virConnectPtr conn)
+{
+ libxlDriverPrivatePtr driver = conn->privateData;
+ int n;
+
+ libxlDriverLock(driver);
+ n = virDomainObjListNumOfDomains(&driver->domains, 0);
+ libxlDriverUnlock(driver);
+
+ return n;
+}
+
+static int
+libxlDomainCreateWithFlags(virDomainPtr dom,
+ unsigned int flags ATTRIBUTE_UNUSED)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ virDomainObjPtr vm;
+ int ret = -1;
+
+ virCheckFlags(VIR_DOMAIN_START_PAUSED, -1);
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ libxlError(VIR_ERR_NO_DOMAIN,
+ _("No domain with matching uuid '%s'"), uuidstr);
+ goto cleanup;
+ }
+
+ if (virDomainObjIsActive(vm)) {
+ libxlError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("Domain is already running"));
+ goto cleanup;
+ }
+
+ ret = libxlVmStart(vm, (flags & VIR_DOMAIN_START_PAUSED) != 0);
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ libxlDriverUnlock(driver);
+ return ret;
+}
+
+static int
+libxlDomainCreate(virDomainPtr dom)
+{
+ return libxlDomainCreateWithFlags(dom, 0);
+}
+
+static virDomainPtr
+libxlDomainDefineXML(virConnectPtr conn, const char *xml)
+{
+ libxlDriverPrivatePtr driver = conn->privateData;
+ virDomainDefPtr def = NULL;
+ virDomainObjPtr vm = NULL;
+ virDomainPtr dom = NULL;
+ int dupVM;
+
+ libxlDriverLock(driver);
+ if (!(def = virDomainDefParseString(driver->caps, xml,
+ VIR_DOMAIN_XML_INACTIVE)))
+ goto cleanup;
+
+ if ((dupVM = virDomainObjIsDuplicate(&driver->domains, def, 0)) < 0)
+ goto cleanup;
+
+ if (!(vm = virDomainAssignDef(driver->caps,
+ &driver->domains, def, false)))
+ goto cleanup;
+ def = NULL;
+ vm->persistent = 1;
+
+ if (virDomainSaveConfig(driver->configDir,
+ vm->newDef ? vm->newDef : vm->def) < 0) {
+ virDomainRemoveInactive(&driver->domains, vm);
+ vm = NULL;
+ goto cleanup;
+ }
+
+ dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
+ if (dom)
+ dom->id = vm->def->id;
+
+cleanup:
+ virDomainDefFree(def);
+ if (vm)
+ virDomainObjUnlock(vm);
+ libxlDriverUnlock(driver);
+ return dom;
+}
+
+static int
+libxlDomainUndefine(virDomainPtr dom)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ virDomainObjPtr vm;
+ int ret = -1;
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+ virUUIDFormat(dom->uuid, uuidstr);
+ libxlError(VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
+ goto cleanup;
+ }
+
+ if (virDomainObjIsActive(vm)) {
+ libxlError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("cannot undefine active domain"));
+ goto cleanup;
+ }
+
+ if (!vm->persistent) {
+ libxlError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("cannot undefine transient domain"));
+ goto cleanup;
+ }
+
+ if (virDomainDeleteConfig(driver->configDir,
+ driver->autostartDir,
+ vm) < 0)
+ goto cleanup;
+
+ virDomainRemoveInactive(&driver->domains, vm);
+ vm = NULL;
+ ret = 0;
+
+ cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ libxlDriverUnlock(driver);
+ return ret;
+}
+
+static int
+libxlDomainIsActive(virDomainPtr dom)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ virDomainObjPtr obj;
+ int ret = -1;
+
+ libxlDriverLock(driver);
+ obj = virDomainFindByUUID(&driver->domains, dom->uuid);
+ libxlDriverUnlock(driver);
+ if (!obj) {
+ libxlError(VIR_ERR_NO_DOMAIN, NULL);
+ goto cleanup;
+ }
+ ret = virDomainObjIsActive(obj);
+
+ cleanup:
+ if (obj)
+ virDomainObjUnlock(obj);
+ return ret;
+}
+
+static int
+libxlDomainIsPersistent(virDomainPtr dom)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ virDomainObjPtr obj;
+ int ret = -1;
+
+ libxlDriverLock(driver);
+ obj = virDomainFindByUUID(&driver->domains, dom->uuid);
+ libxlDriverUnlock(driver);
+ if (!obj) {
+ libxlError(VIR_ERR_NO_DOMAIN, NULL);
+ goto cleanup;
+ }
+ ret = obj->persistent;
+
+ cleanup:
+ if (obj)
+ virDomainObjUnlock(obj);
+ return ret;
+}
+
+
+static virDriver libxlDriver = {
+ VIR_DRV_LIBXL,
+ "libxenlight",
+ libxlOpen, /* open */
+ libxlClose, /* close */
+ NULL, /* supports_feature */
+ libxlGetType, /* type */
+ libxlGetVersion, /* version */
+ NULL, /* libvirtVersion (impl. in libvirt.c) */
+ virGetHostname, /* getHostname */
+ NULL, /* getSysinfo */
+ libxlGetMaxVcpus, /* getMaxVcpus */
+ libxlNodeGetInfo, /* nodeGetInfo */
+ libxlGetCapabilities, /* getCapabilities */
+ libxlListDomains, /* listDomains */
+ libxlNumDomains, /* numOfDomains */
+ libxlDomainCreateXML, /* domainCreateXML */
+ libxlDomainLookupByID, /* domainLookupByID */
+ libxlDomainLookupByUUID, /* domainLookupByUUID */
+ libxlDomainLookupByName, /* domainLookupByName */
+ NULL, /* domainSuspend */
+ NULL, /* domainResume */
+ libxlDomainShutdown, /* domainShutdown */
+ libxlDomainReboot, /* domainReboot */
+ libxlDomainDestroy, /* domainDestroy */
+ NULL, /* domainGetOSType */
+ NULL, /* domainGetMaxMemory */
+ NULL, /* domainSetMaxMemory */
+ NULL, /* domainSetMemory */
+ libxlDomainGetInfo, /* domainGetInfo */
+ NULL, /* domainSave */
+ NULL, /* domainRestore */
+ NULL, /* domainCoreDump */
+ NULL, /* domainSetVcpus */
+ NULL, /* domainSetVcpusFlags */
+ NULL, /* domainGetVcpusFlags */
+ NULL, /* domainPinVcpu */
+ NULL, /* domainGetVcpus */
+ NULL, /* domainGetMaxVcpus */
+ NULL, /* domainGetSecurityLabel */
+ NULL, /* nodeGetSecurityModel */
+ libxlDomainDumpXML, /* domainDumpXML */
+ NULL, /* domainXmlFromNative */
+ NULL, /* domainXmlToNative */
+ libxlListDefinedDomains, /* listDefinedDomains */
+ libxlNumDefinedDomains, /* numOfDefinedDomains */
+ libxlDomainCreate, /* domainCreate */
+ libxlDomainCreateWithFlags, /* domainCreateWithFlags */
+ libxlDomainDefineXML, /* domainDefineXML */
+ libxlDomainUndefine, /* domainUndefine */
+ NULL, /* domainAttachDevice */
+ NULL, /* domainAttachDeviceFlags */
+ NULL, /* domainDetachDevice */
+ NULL, /* domainDetachDeviceFlags */
+ NULL, /* domainUpdateDeviceFlags */
+ NULL, /* domainGetAutostart */
+ NULL, /* domainSetAutostart */
+ NULL, /* domainGetSchedulerType */
+ NULL, /* domainGetSchedulerParameters */
+ NULL, /* domainSetSchedulerParameters */
+ NULL, /* domainMigratePrepare */
+ NULL, /* domainMigratePerform */
+ NULL, /* domainMigrateFinish */
+ NULL, /* domainBlockStats */
+ NULL, /* domainInterfaceStats */
+ NULL, /* domainMemoryStats */
+ NULL, /* domainBlockPeek */
+ NULL, /* domainMemoryPeek */
+ NULL, /* domainGetBlockInfo */
+ NULL, /* nodeGetCellsFreeMemory */
+ NULL, /* getFreeMemory */
+ NULL, /* domainEventRegister */
+ NULL, /* domainEventDeregister */
+ NULL, /* domainMigratePrepare2 */
+ NULL, /* domainMigrateFinish2 */
+ NULL, /* nodeDeviceDettach */
+ NULL, /* nodeDeviceReAttach */
+ NULL, /* nodeDeviceReset */
+ NULL, /* domainMigratePrepareTunnel */
+ NULL, /* IsEncrypted */
+ NULL, /* IsSecure */
+ libxlDomainIsActive, /* DomainIsActive */
+ libxlDomainIsPersistent, /* DomainIsPersistent */
+ NULL, /* domainIsUpdated */
+ NULL, /* cpuCompare */
+ NULL, /* cpuBaseline */
+ NULL, /* domainGetJobInfo */
+ NULL, /* domainAbortJob */
+ NULL, /* domainMigrateSetMaxDowntime */
+ NULL, /* domainEventRegisterAny */
+ NULL, /* domainEventDeregisterAny */
+ NULL, /* domainManagedSave */
+ NULL, /* domainHasManagedSaveImage */
+ NULL, /* domainManagedSaveRemove */
+ NULL, /* domainSnapshotCreateXML */
+ NULL, /* domainSnapshotDumpXML */
+ NULL, /* domainSnapshotNum */
+ NULL, /* domainSnapshotListNames */
+ NULL, /* domainSnapshotLookupByName */
+ NULL, /* domainHasCurrentSnapshot */
+ NULL, /* domainSnapshotCurrent */
+ NULL, /* domainRevertToSnapshot */
+ NULL, /* domainSnapshotDelete */
+ NULL, /* qemuDomainMonitorCommand */
+ NULL, /* domainSetMemoryParameters */
+ NULL, /* domainGetMemoryParameters */
+ NULL, /* domainOpenConsole */
+};
+
+static virStateDriver libxlStateDriver = {
+ .name = "LIBXL",
+ .initialize = libxlStartup,
+ .cleanup = libxlShutdown,
+ .reload = libxlReload,
+ .active = libxlActive,
+};
+
+
+int
+libxlRegister(void)
+{
+ if (virRegisterDriver(&libxlDriver) < 0)
+ return -1;
+ if (virRegisterStateDriver(&libxlStateDriver) < 0)
+ return -1;
+
+ return 0;
+}
diff --git a/src/libxl/libxl_driver.h b/src/libxl/libxl_driver.h
new file mode 100644
index 0000000..e047552
--- /dev/null
+++ b/src/libxl/libxl_driver.h
@@ -0,0 +1,27 @@
+/*---------------------------------------------------------------------------*/
+/* Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * 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 LIBXL_DRIVER_H
+# define LIBXL_DRIVER_H
+
+# include <config.h>
+
+int libxlRegister(void);
+
+#endif /* LIBXL_DRIVER_H */
diff --git a/src/util/virterror.c b/src/util/virterror.c
index e45b582..c763d92 100644
--- a/src/util/virterror.c
+++ b/src/util/virterror.c
@@ -89,6 +89,9 @@ static const char *virErrorDomainName(virErrorDomain domain) {
case VIR_FROM_XENAPI:
dom = "XenAPI ";
break;
+ case VIR_FROM_LIBXL:
+ dom = "libxenlight ";
+ break;
case VIR_FROM_XML:
dom = "XML ";
break;
--
1.7.3.1
13 years, 9 months
[libvirt] [libvirt-php] docs: fixed uninitial private function name
by Lyre
* tools/generate-api-docs.c: add initialize for private function names
---
tools/generate-api-docs.c | 13 +++++++++----
1 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/tools/generate-api-docs.c b/tools/generate-api-docs.c
index 322f3ef..8a16e22 100644
--- a/tools/generate-api-docs.c
+++ b/tools/generate-api-docs.c
@@ -43,10 +43,15 @@ void parse_comment(char *line, int func_num, int *arg_num)
if (strncmp(ltrimmed, "Function name:", 14) == 0) {
functions[func_num].name = strdup( ltrim_string( ltrimmed + 14) );
}
- else
- if (strncmp(ltrimmed, "Description:", 12) == 0) {
- functions[func_num].desc = strdup( ltrim_string( ltrimmed + 12) );
- }
+ else
+ if (strncmp(ltrimmed, "Private function name:", 22) == 0)
+ {
+ functions[func_num].name = NULL;
+ }
+ else
+ if (strncmp(ltrimmed, "Description:", 12) == 0) {
+ functions[func_num].desc = strdup( ltrim_string( ltrimmed + 12) );
+ }
else
if (strncmp(ltrimmed, "Arguments:", 10) == 0) {
char *str = ltrim_string(ltrimmed + 11);
--
1.7.1
13 years, 9 months
[libvirt] [libvirt-snmp][PATCH v2 0/3] Add SNMP trap/notification support.
by Michal Privoznik
The second version, without formatting stuff.
Finally, we have a proof-of-concept implementation of SNMP trap.
Two new files were first generated using mib2c then edited, so be
careful when re-generating them.
Destination of traps is defined in snmpd.conf (trap2sink), and to
receive them snmptrapd must be configured and up.
The idea behind is - create a thread in which we poll for domain
events. Once we receive event notification, we just fire up
trap sending.
Michal Privoznik (3):
Add notification-type object to libvirt MIB
Create functions to fill in and send notification packets.
Add SNMP trap/notification support.
INSTALL | 9 +-
configure.ac | 7 +
src/LIBVIRT-MIB.txt | 9 ++
src/Makefile.am | 3 +
src/README.txt | 9 +-
src/libvirtNotifications.c | 109 +++++++++++++++++
src/libvirtNotifications.h | 21 ++++
src/libvirtSnmp.c | 277 +++++++++++++++++++++++++++++++++++++++++++-
8 files changed, 435 insertions(+), 9 deletions(-)
create mode 100644 src/libvirtNotifications.c
create mode 100644 src/libvirtNotifications.h
--
1.7.4
13 years, 9 months
[libvirt] [libvirt-php] add list function for storagepool
by Lyre
* add libvirt_list_active_storagepools & libvirt_list_inactive_storagepools
* modified EXTRA_DIST for necessary files
* generate libvirt-php.spec from .in file
* bug fix for memeory leak
---
Makefile.am | 2 +-
configure.ac | 1 +
libvirt-php.spec | 82 --------------------------
libvirt-php.spec.in | 82 ++++++++++++++++++++++++++
src/Makefile.am | 2 +-
src/libvirt.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++----
src/libvirt_php.h | 2 +
tools/Makefile.am | 2 +
8 files changed, 235 insertions(+), 97 deletions(-)
delete mode 100644 libvirt-php.spec
create mode 100644 libvirt-php.spec.in
diff --git a/Makefile.am b/Makefile.am
index 2e73743..45f396b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,3 +1,3 @@
SUBDIRS = tools src docs
-EXTRA_DIST = libvirt-php.spec
+EXTRA_DIST = libvirt-php.spec.in
diff --git a/configure.ac b/configure.ac
index f79317d..8d81b9d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -110,4 +110,5 @@ fi
AC_SUBST([PHPIZE])
AC_SUBST([PHPCONFIG])
AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_FILES([$PACKAGE.spec])
AC_OUTPUT
diff --git a/libvirt-php.spec b/libvirt-php.spec
deleted file mode 100644
index 51a9add..0000000
--- a/libvirt-php.spec
+++ /dev/null
@@ -1,82 +0,0 @@
-%define req_libvirt_version 0.6.2
-
-%if 0%{?suse_version}
-%define php_confdir %{_sysconfdir}/php5/conf.d
-%define php_extdir %{_libdir}/php5/extensions
-%else
-%define php_confdir %{_sysconfdir}/php.d
-%define php_extdir %{_libdir}/php/modules
-%endif
-
-Name: libvirt-php
-Version: 0.4
-Release: 1%{?dist}%{?extra_release}
-Summary: PHP language binding for Libvirt
-
-%if 0%{?suse_version}
-Group: Development/Libraries/PHP
-%else
-Group: Development/Libraries
-%endif
-License: PHP
-URL: http://libvirt.org/
-Source0: http://libvirt.org/sources/libvirt-php-%{version}.tar.gz
-BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
-
-BuildRequires: php-devel
-BuildRequires: libvirt-devel >= %{req_libvirt_version}
-BuildRequires: libxml2-devel
-%if 0%{?suse_version}
-BuildRequires: xhtml-dtd
-%else
-BuildRequires: xhtml1-dtds
-%endif
-Requires: libvirt >= %{req_libvirt_version}
-%if 0%{?suse_version}
-Requires: php5
-%else
-Requires: php
-%endif
-
-%description
-PHP language bindings for Libvirt API.
-For more details see: http://phplibvirt.cybersales.cz/ http://www.libvirt.org/ http://www.php.net/
-
-%package -n libvirt-php-doc
-Summary: Document of libvirt-php
-Group: Development/Libraries/PHP
-Requires: libvirt-php = %{version}
-
-%description -n libvirt-php-doc
-PHP language bindings for Libvirt API.
-For more details see: http://phplibvirt.cybersales.cz/ http://www.libvirt.org/ http://www.php.net/
-
-This package contain the document for libvirt-php.
-
-%prep
-%setup -q -n libvirt-php-%{version}
-
-%build
-%configure
-./configure --with-html-dir=%{_datadir}/doc --with-html-subdir=%{name}-%{version}/html
-make %{?_smp_mflags}
-
-%install
-make install DESTDIR=%{buildroot}
-
-%clean
-rm -rf %{buildroot}
-
-%files
-%defattr(-,root,root,-)
-%{php_extdir}/libvirt-php.so
-%config(noreplace) %{php_confdir}/libvirt-php.ini
-
-%files -n libvirt-php-doc
-%defattr(-,root,root,-)
-%doc
-%dir %{_datadir}/doc/%{name}-%{version}
-%{_datadir}/doc/%{name}-%{version}/html
-
-%changelog
-
diff --git a/libvirt-php.spec.in b/libvirt-php.spec.in
new file mode 100644
index 0000000..465532c
--- /dev/null
+++ b/libvirt-php.spec.in
@@ -0,0 +1,82 @@
+%define req_libvirt_version 0.6.2
+
+%if 0%{?suse_version}
+%define php_confdir %{_sysconfdir}/php5/conf.d
+%define php_extdir %{_libdir}/php5/extensions
+%else
+%define php_confdir %{_sysconfdir}/php.d
+%define php_extdir %{_libdir}/php/modules
+%endif
+
+Name: @PACKAGE@
+Version: @VERSION@
+Release: 1%{?dist}%{?extra_release}
+Summary: PHP language binding for Libvirt
+
+%if 0%{?suse_version}
+Group: Development/Libraries/PHP
+%else
+Group: Development/Libraries
+%endif
+License: PHP
+URL: http://libvirt.org/
+Source0: http://libvirt.org/sources/libvirt-php-%{version}.tar.gz
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
+
+BuildRequires: php-devel
+BuildRequires: libvirt-devel >= %{req_libvirt_version}
+BuildRequires: libxml2-devel
+%if 0%{?suse_version}
+BuildRequires: xhtml-dtd
+%else
+BuildRequires: xhtml1-dtds
+%endif
+Requires: libvirt >= %{req_libvirt_version}
+%if 0%{?suse_version}
+Requires: php5
+%else
+Requires: php
+%endif
+
+%description
+PHP language bindings for Libvirt API.
+For more details see: http://phplibvirt.cybersales.cz/ http://www.libvirt.org/ http://www.php.net/
+
+%package -n libvirt-php-doc
+Summary: Document of libvirt-php
+Group: Development/Libraries/PHP
+Requires: libvirt-php = %{version}
+
+%description -n libvirt-php-doc
+PHP language bindings for Libvirt API.
+For more details see: http://phplibvirt.cybersales.cz/ http://www.libvirt.org/ http://www.php.net/
+
+This package contain the document for libvirt-php.
+
+%prep
+%setup -q -n libvirt-php-%{version}
+
+%build
+%configure
+./configure --with-html-dir=%{_datadir}/doc --with-html-subdir=%{name}-%{version}/html
+make %{?_smp_mflags}
+
+%install
+make install DESTDIR=%{buildroot}
+
+%clean
+rm -rf %{buildroot}
+
+%files
+%defattr(-,root,root,-)
+%{php_extdir}/libvirt-php.so
+%config(noreplace) %{php_confdir}/libvirt-php.ini
+
+%files -n libvirt-php-doc
+%defattr(-,root,root,-)
+%doc
+%dir %{_datadir}/doc/%{name}-%{version}
+%{_datadir}/doc/%{name}-%{version}/html
+
+%changelog
+
diff --git a/src/Makefile.am b/src/Makefile.am
index d301ae2..9c7101d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,7 +3,7 @@ PHPEDIR=$(shell php-config --extension-dir)
PHPCDIR=$(shell php-config --configure-options | sed -n 's|.*--with-config-file-scan-dir=\([^ ]*\).*|\1|p')
DEFINES=-DHAVE_CONFIG_H
-EXTRA_DIST = libvirt.c php_libvirt.h
+EXTRA_DIST = libvirt.c libvirt_php.h
all-am: build clean-temp
diff --git a/src/libvirt.c b/src/libvirt.c
index 9293224..230aff2 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -109,6 +109,8 @@ static function_entry libvirt_functions[] = {
PHP_FE(libvirt_list_nodedevs, NULL)
PHP_FE(libvirt_list_networks,NULL)
PHP_FE(libvirt_list_storagepools,NULL)
+ PHP_FE(libvirt_list_active_storagepools,NULL)
+ PHP_FE(libvirt_list_inactive_storagepools,NULL)
PHP_FE(libvirt_storagepool_list_volumes,NULL)
PHP_FE(libvirt_list_active_domains, NULL)
PHP_FE(libvirt_list_active_domain_ids, NULL)
@@ -1994,10 +1996,11 @@ PHP_FUNCTION(libvirt_storagepool_get_info)
array_init(return_value);
// @todo: fix the long long returns
+ LONGLONG_INIT
add_assoc_long(return_value, "state", (long)poolInfo.state);
- add_assoc_long(return_value, "capacity", poolInfo.capacity);
- add_assoc_long(return_value, "allocation", poolInfo.allocation);
- add_assoc_long(return_value, "available", poolInfo.available);
+ LONGLONG_ASSOC(return_value, "capacity", poolInfo.capacity);
+ LONGLONG_ASSOC(return_value, "allocation", poolInfo.allocation);
+ LONGLONG_ASSOC(return_value, "available", poolInfo.available);
}
/*
@@ -2426,18 +2429,110 @@ PHP_FUNCTION(libvirt_list_storagepools)
names=emalloc(expectedcount*sizeof(char *));
count=virConnectListStoragePools(conn->conn,names,expectedcount);
- if ((count != expectedcount) || (count<0)) RETURN_FALSE;
+ if ((count != expectedcount) || (count<0))
+ {
+ efree (names);
+ RETURN_FALSE;
+ }
+
array_init(return_value);
for (i=0;i<count;i++)
{
add_next_index_string(return_value, names[i],1);
free(names[i]);
}
+ efree(names);
+
+
+ expectedcount = virConnectNumOfDefinedStoragePools (conn->conn);
+ names= emalloc (expectedcount * sizeof(char *));
+ count = virConnectListDefinedStoragePools (conn->conn, names, expectedcount);
+ if ((count != expectedcount) || (count < 0))
+ {
+ efree (names);
+ RETURN_FALSE;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ add_next_index_string (return_value, names[i], 1);
+ free (names[i]);
+ }
+ efree (names);
+}
+/*
+ Function name: libvirt_list_active_storagepools
+ Description: Function is used to list active storage pools on the connection
+ Arguments: @res [resource]: libvirt connection resource
+ Returns: libvirt storagepool names array for the connection
+*/
+PHP_FUNCTION(libvirt_list_active_storagepools)
+{
+ php_libvirt_connection *conn=NULL;
+ zval *zconn;
+ int count=-1;
+ int expectedcount=-1;
+ char **names;
+ int i;
+
+ GET_CONNECTION_FROM_ARGS("r",&zconn);
+
+ expectedcount=virConnectNumOfStoragePools(conn->conn);
+
+ names=emalloc(expectedcount*sizeof(char *));
+ count=virConnectListStoragePools(conn->conn,names,expectedcount);
+
+ if ((count != expectedcount) || (count<0))
+ {
+ efree (names);
+ RETURN_FALSE;
+ }
+ array_init(return_value);
+ for (i=0;i<count;i++)
+ {
+ add_next_index_string(return_value, names[i],1);
+ free(names[i]);
+ }
efree(names);
}
/*
+ Function name: libvirt_list_inactive_storagepools
+ Description: Function is used to list inactive storage pools on the connection
+ Arguments: @res [resource]: libvirt connection resource
+ Returns: libvirt storagepool names array for the connection
+*/
+PHP_FUNCTION(libvirt_list_inactive_storagepools)
+{
+ php_libvirt_connection *conn=NULL;
+ zval *zconn;
+ int count=-1;
+ int expectedcount=-1;
+ char **names;
+ int i;
+
+ GET_CONNECTION_FROM_ARGS("r",&zconn);
+
+ expectedcount = virConnectNumOfDefinedStoragePools (conn->conn);
+ names= emalloc (expectedcount * sizeof(char *));
+ count = virConnectListDefinedStoragePools (conn->conn, names, expectedcount);
+ if ((count != expectedcount) || (count < 0))
+ {
+ efree (names);
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+ for (i = 0; i < count; i++)
+ {
+ add_next_index_string (return_value, names[i], 1);
+ free (names[i]);
+ }
+ efree (names);
+}
+
+/*
Function name: libvirt_list_domains
Description: Function is used to list domains on the connection
Arguments: @res [resource]: libvirt connection resource
@@ -2513,7 +2608,11 @@ PHP_FUNCTION(libvirt_list_domain_resources)
ids=emalloc(sizeof(int)*expectedcount);
count=virConnectListDomains (conn->conn,ids,expectedcount);
- if ((count != expectedcount) || (count<0)) RETURN_FALSE;
+ if ((count != expectedcount) || (count<0))
+ {
+ efree (ids);
+ RETURN_FALSE;
+ }
array_init(return_value);
for (i=0;i<count;i++)
{
@@ -2535,7 +2634,11 @@ PHP_FUNCTION(libvirt_list_domain_resources)
expectedcount=virConnectNumOfDefinedDomains (conn->conn);
names=emalloc(expectedcount*sizeof(char *));
count=virConnectListDefinedDomains (conn->conn,names ,expectedcount);
- if ((count != expectedcount) || (count<0)) RETURN_FALSE;
+ if ((count != expectedcount) || (count<0))
+ {
+ efree (names);
+ RETURN_FALSE;
+ }
for (i=0;i<count;i++)
{
domain=virDomainLookupByName (conn->conn,names[i]);
@@ -2576,7 +2679,11 @@ PHP_FUNCTION(libvirt_list_active_domain_ids)
ids=emalloc(sizeof(int)*expectedcount);
count=virConnectListDomains (conn->conn,ids,expectedcount);
- if ((count != expectedcount) || (count<0)) RETURN_FALSE;
+ if ((count != expectedcount) || (count<0))
+ {
+ efree (ids);
+ RETURN_FALSE;
+ }
array_init(return_value);
for (i=0;i<count;i++)
{
@@ -2608,7 +2715,12 @@ PHP_FUNCTION(libvirt_list_active_domains)
ids=emalloc(sizeof(int)*expectedcount);
count=virConnectListDomains (conn->conn,ids,expectedcount);
- if ((count != expectedcount) || (count<0)) RETURN_FALSE;
+ if ((count != expectedcount) || (count<0))
+ {
+ efree (ids);
+ RETURN_FALSE;
+ }
+
array_init(return_value);
for (i=0;i<count;i++)
{
@@ -2616,7 +2728,12 @@ PHP_FUNCTION(libvirt_list_active_domains)
if (domain!=NULL)
{
name=virDomainGetName(domain);
- if (name==NULL) RETURN_FALSE;
+ if (name==NULL)
+ {
+ efree (ids);
+ RETURN_FALSE;
+ }
+
add_next_index_string(return_value, name, 1);
}
}
@@ -2645,7 +2762,11 @@ PHP_FUNCTION(libvirt_list_inactive_domains)
names=emalloc(expectedcount*sizeof(char *));
count=virConnectListDefinedDomains (conn->conn,names ,expectedcount);
- if ((count != expectedcount) || (count<0)) RETURN_FALSE;
+ if ((count != expectedcount) || (count<0))
+ {
+ efree (names);
+ RETURN_FALSE;
+ }
for (i=0;i<count;i++)
{
add_next_index_string(return_value, names[i],1);
@@ -2678,7 +2799,11 @@ PHP_FUNCTION(libvirt_list_networks)
expectedcount=virConnectNumOfNetworks(conn->conn);
names=emalloc(expectedcount*sizeof(char *));
count=virConnectListNetworks(conn->conn,names,expectedcount);
- if ((count != expectedcount) || (count<0)) RETURN_FALSE;
+ if ((count != expectedcount) || (count<0))
+ {
+ efree (names);
+ RETURN_FALSE;
+ }
for (i=0;i<count;i++)
{
@@ -2694,7 +2819,11 @@ PHP_FUNCTION(libvirt_list_networks)
expectedcount=virConnectNumOfDefinedNetworks(conn->conn);
names=emalloc(expectedcount*sizeof(char *));
count=virConnectListDefinedNetworks(conn->conn,names,expectedcount);
- if ((count != expectedcount) || (count<0)) RETURN_FALSE;
+ if ((count != expectedcount) || (count<0))
+ {
+ efree (names);
+ RETURN_FALSE;
+ }
for (i=0;i<count;i++)
{
@@ -2732,7 +2861,11 @@ PHP_FUNCTION(libvirt_list_nodedevs)
expectedcount=virNodeNumOfDevices(conn->conn, cap, 0);
names=emalloc(expectedcount*sizeof(char *));
count=virNodeListDevices(conn->conn, cap, names, expectedcount, 0);
- if ((count != expectedcount) || (count<0)) RETURN_FALSE;
+ if ((count != expectedcount) || (count<0))
+ {
+ efree (names);
+ RETURN_FALSE;
+ }
array_init(return_value);
for (i=0;i<count;i++)
diff --git a/src/libvirt_php.h b/src/libvirt_php.h
index 8667217..3cdc305 100644
--- a/src/libvirt_php.h
+++ b/src/libvirt_php.h
@@ -168,6 +168,8 @@ PHP_FUNCTION(libvirt_list_active_domains);
PHP_FUNCTION(libvirt_list_active_domain_ids);
PHP_FUNCTION(libvirt_list_inactive_domains);
PHP_FUNCTION(libvirt_list_storagepools);
+PHP_FUNCTION(libvirt_list_active_storagepools);
+PHP_FUNCTION(libvirt_list_inactive_storagepools);
PHP_FUNCTION(libvirt_version);
PHP_FUNCTION(libvirt_check_version);
diff --git a/tools/Makefile.am b/tools/Makefile.am
index b334717..e508371 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,3 +1,5 @@
+EXTRA_DIST = generate-api-docs.c
+
all-am:
$(CC) -Wall -o generate-api-docs generate-api-docs.c
./generate-api-docs ../src/libvirt.c ../docs/api-reference.html.in
--
1.7.1
13 years, 9 months
[libvirt] [PATCH] RFC: virsh setmem: configure inactive domains' memory size
by Taku Izumi
Currently "virsh setmem" is not allowed to use against inactive domains.
By applying this patch, we can change the memory size of inactive domains
by "virsh setmem".
Signed-off-by: Taku Izumi <izumi.taku(a)jp.fujitsu.com>
---
tools/virsh.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 62 insertions(+), 8 deletions(-)
Index: libvirt-git/tools/virsh.c
===================================================================
--- libvirt-git.orig/tools/virsh.c
+++ libvirt-git/tools/virsh.c
@@ -2919,39 +2919,93 @@ cmdSetmem(vshControl *ctl, const vshCmd
virDomainPtr dom;
virDomainInfo info;
unsigned long kilobytes;
- int ret = TRUE;
+ int ret = FALSE;
+
+ char *xmlStr;
+ virBuffer memBuf = VIR_BUFFER_INITIALIZER;
+ xmlDocPtr xmlDocObj = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ xmlXPathObjectPtr result = NULL;
+ xmlChar *newXml = NULL;
+ int newXmlSize;
if (!vshConnectionUsability(ctl, ctl->conn))
- return FALSE;
+ return ret;
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
- return FALSE;
+ return ret;
kilobytes = vshCommandOptUL(cmd, "kilobytes", NULL);
if (kilobytes <= 0) {
virDomainFree(dom);
vshError(ctl, _("Invalid value of %lu for memory size"), kilobytes);
- return FALSE;
+ return ret;
}
if (virDomainGetInfo(dom, &info) != 0) {
virDomainFree(dom);
vshError(ctl, "%s", _("Unable to verify MaxMemorySize"));
- return FALSE;
+ return ret;
}
if (kilobytes > info.maxMem) {
virDomainFree(dom);
vshError(ctl, _("Requested memory size %lu kb is larger than maximum of %lu
kb"),
kilobytes, info.maxMem);
- return FALSE;
+ return ret;
}
- if (virDomainSetMemory(dom, kilobytes) != 0) {
- ret = FALSE;
+ if (virDomainIsActive(dom) == 1) {
+ if (virDomainSetMemory(dom, kilobytes) == 0)
+ ret = TRUE;
+ virDomainFree(dom);
+ return ret;
}
+ /* domain is inactive */
+
+ xmlStr = virDomainGetXMLDesc(dom, VIR_DOMAIN_XML_SECURE |
+ VIR_DOMAIN_XML_INACTIVE);
+ if (!xmlStr)
+ goto cleanup;
+
+ xmlDocObj = xmlReadDoc((const xmlChar *)xmlStr, "domain.xml", NULL,
+ XML_PARSE_NOENT | XML_PARSE_NONET |
+ XML_PARSE_NOWARNING);
+ if (!xmlDocObj)
+ goto cleanup;
+
+ ctxt = xmlXPathNewContext(xmlDocObj);
+ if (!ctxt)
+ goto cleanup;
+
+ result = xmlXPathEvalExpression((xmlChar *)"/domain/currentMemory", ctxt);
+ if (xmlXPathNodeSetIsEmpty(result->nodesetval) ||
+ result->nodesetval->nodeNr != 1 ||
+ result->nodesetval->nodeTab[0]->type != XML_ELEMENT_NODE) {
+ goto cleanup;
+ }
+
+ virBufferVSprintf(&memBuf, "%lu", kilobytes);
+ xmlNodeSetContent(result->nodesetval->nodeTab[0],
+ (const xmlChar *)virBufferContentAndReset(&memBuf));
+ xmlDocDumpMemory(xmlDocObj, &newXml, &newXmlSize);
+ if (!newXml)
+ goto cleanup;
+
virDomainFree(dom);
+ dom = virDomainDefineXML(ctl->conn, (char *)newXml);
+ if (dom)
+ ret = TRUE;
+
+cleanup:
+ xmlFree(newXml);
+ xmlXPathFreeContext(ctxt);
+ xmlFreeDoc(xmlDocObj);
+ VIR_FREE(xmlStr);
+ if (dom)
+ virDomainFree(dom);
+
return ret;
}
13 years, 9 months
[libvirt] open source with power devices
by JamesTessier@Eaton.com
Hi, I am Jim Tessier from Eaton Corporation. We are a major producer of
UPSs and other data center power distribution equipment (and software).
Eaton is developing an open-source presence and would like to become
involved with libvert.
Our software is currently compatible with MicroSoft SCVMM and VMware
vCenter. It can do live migrations / vMotions and will shut down host
servers gracefully in the event of power loss. Libvirt appears to be a
natural fit for Eaton's products.
Can someone get back to me on how to work within the community?
thanks,
jt
Jim Tessier
Product Manager
Eaton Electrical Power Quality Division
(919) 870-3354 (o)
(919) 244-4554 (c)
JamesTessier(a)Eaton.com
13 years, 9 months
[libvirt] [PATCH v3 1/3] libvirt/conf - report OOM error in virDomainDiskInsert()
by KAMEZAWA Hiroyuki
Thank you for review. This is v3.
==
>From 0757ef3ff30779b3a9a5a07959fff6ada9b68d61 Mon Sep 17 00:00:00 2001
From: KAMEZAWA Hiroyuki <kamezawa(a)bluextal.(none)>
Date: Thu, 24 Feb 2011 16:00:29 +0900
Subject: [PATCH 1/3] report OOMError in virDomainDiskInsert()
Now, virDomainDiskInsert() returns -1 at memory allocation
failure but it should call virReportOOMError() by itself.
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu(a)jp.fujitsu.com>
---
src/conf/domain_conf.c | 4 +++-
src/xen/xm_internal.c | 4 +---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b97c1f0..b4193b9 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4857,8 +4857,10 @@ int virDomainDiskInsert(virDomainDefPtr def,
virDomainDiskDefPtr disk)
{
- if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
+ if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
+ virReportOOMError();
return -1;
+ }
virDomainDiskInsertPreAlloced(def, disk);
diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
index 27cc387..c3c72fe 100644
--- a/src/xen/xm_internal.c
+++ b/src/xen/xm_internal.c
@@ -1385,10 +1385,8 @@ xenXMDomainAttachDeviceFlags(virDomainPtr domain, const char *xml,
switch (dev->type) {
case VIR_DOMAIN_DEVICE_DISK:
{
- if (virDomainDiskInsert(def, dev->data.disk) < 0) {
- virReportOOMError();
+ if (virDomainDiskInsert(def, dev->data.disk) < 0)
goto cleanup;
- }
dev->data.disk = NULL;
}
break;
--
1.7.1
13 years, 9 months