1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-09-22 13:45:17 +03:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Daniel Veillard
9f25f7f0db First check-in in CVS 2005-11-02 12:50:21 +00:00
1280 changed files with 242 additions and 1237401 deletions

47
.gitignore vendored
View File

@@ -1,47 +0,0 @@
*.a
*.o
*~
.git
.git-module-status
ABOUT-NLS
COPYING
INSTALL
Makefile
Makefile.in
aclocal.m4
autom4te.cache
config.cache
config.guess
config.h
config.h.in
config.log
config.rpath
config.status
config.sub
configure
coverage
cscope.files
cscope.out
libtool
libvirt-*.tar.gz
libvirt.pc
libvirt.spec
ltconfig
ltmain.sh
mingw32-libvirt.spec
mkinstalldirs
results.log
stamp-h
stamp-h.in
stamp-h1
update.log
tests/*.log
/GNUmakefile
/maint.mk
gnulib/
*.orig
*.rej
*#*#
*.#*#
ChangeLog
NEWS

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "gnulib"]
path = .gnulib
url = git://git.sv.gnu.org/gnulib.git

Submodule .gnulib deleted from 3fd9a2df88

298
.hgignore
View File

@@ -1,298 +0,0 @@
syntax: glob
*.a
*.o
*~
.git
ABOUT-NLS
COPYING
INSTALL
Makefile
Makefile.in
aclocal.m4
autom4te.cache
build-aux/compile
build-aux/config.guess
build-aux/config.rpath
build-aux/config.sub
build-aux/depcomp
build-aux/install-sh
build-aux/ltmain.sh
build-aux/missing
build-aux/mkinstalldirs
build-aux/mktempd
config.cache
config.guess
config.h
config.h.in
config.log
config.rpath
config.status
config.sub
configure
coverage
docs/.memdump
docs/Makefile
docs/Makefile.in
docs/apibuild.pyc
docs/devhelp/Makefile
docs/devhelp/Makefile.in
docs/devhelp/libvirt.devhelp
docs/examples/.deps
docs/examples/.libs
docs/examples/.memdump
docs/examples/Makefile
docs/examples/Makefile.in
docs/examples/info1
docs/examples/python/Makefile
docs/examples/python/Makefile.in
docs/examples/suspend
docs/schemas/Makefile
docs/schemas/Makefile.in
examples/domain-events/events-c/*.exe
examples/domain-events/events-c/.deps
examples/domain-events/events-c/.libs
examples/domain-events/events-c/Makefile
examples/domain-events/events-c/Makefile.in
examples/domain-events/events-c/event-test
examples/hellolibvirt/.deps
examples/hellolibvirt/.libs
examples/hellolibvirt/Makefile
examples/hellolibvirt/Makefile.in
examples/hellolibvirt/hellolibvirt
gnulib/lib/*.la
gnulib/lib/*.lo
gnulib/lib/.deps
gnulib/lib/.libs
gnulib/lib/Makefile
gnulib/lib/Makefile.in
gnulib/lib/alloca.h
gnulib/lib/arpa/inet.h
gnulib/lib/arpa_inet.h
gnulib/lib/errno.h
gnulib/lib/float.h
gnulib/lib/netdb.h
gnulib/lib/netinet/in.h
gnulib/lib/netinet_in.h
gnulib/lib/poll.h
gnulib/lib/stdbool.h
gnulib/lib/stdint.h
gnulib/lib/stdio.h
gnulib/lib/stdlib.h
gnulib/lib/string.h
gnulib/lib/sys/select.h
gnulib/lib/sys/socket.h
gnulib/lib/sys/stat.h
gnulib/lib/sys/time.h
gnulib/lib/sys_ioctl.h
gnulib/lib/sys_select.h
gnulib/lib/sys_socket.h
gnulib/lib/sys_stat.h
gnulib/lib/sys_time.h
gnulib/lib/time.h
gnulib/lib/unistd.h
gnulib/lib/wchar.h
gnulib/tests/.deps
gnulib/tests/.libs
gnulib/tests/Makefile
gnulib/tests/Makefile.in
gnulib/tests/sys
gnulib/tests/test-EOVERFLOW
gnulib/tests/test-alloca-opt
gnulib/tests/test-arpa_inet
gnulib/tests/test-c-ctype
gnulib/tests/test-errno
gnulib/tests/test-fseeko
gnulib/tests/test-getaddrinfo
gnulib/tests/test-getdelim
gnulib/tests/test-gethostname
gnulib/tests/test-getline
gnulib/tests/test-gettimeofday
gnulib/tests/test-lseek
gnulib/tests/test-lstat
gnulib/tests/test-netdb
gnulib/tests/test-netinet_in
gnulib/tests/test-perror
gnulib/tests/test-poll
gnulib/tests/test-random_r
gnulib/tests/test-snprintf
gnulib/tests/test-sockets
gnulib/tests/test-stdbool
gnulib/tests/test-stdint
gnulib/tests/test-stdio
gnulib/tests/test-stdlib
gnulib/tests/test-strerror
gnulib/tests/test-string
gnulib/tests/test-sys_select
gnulib/tests/test-sys_socket
gnulib/tests/test-sys_stat
gnulib/tests/test-sys_time
gnulib/tests/test-time
gnulib/tests/test-unistd
gnulib/tests/test-vasnprintf
gnulib/tests/test-vasprintf
gnulib/tests/test-wchar
include/Makefile
include/Makefile.in
include/libvirt/Makefile
include/libvirt/Makefile.in
libtool
libvirt-*.tar.gz
libvirt.pc
libvirt.spec
ltconfig
ltmain.sh
m4/Makefile
m4/Makefile.in
m4/acinclude.m4
m4/aclocal.m4
m4/codeset.m4
m4/gettext.m4
m4/glibc21.m4
m4/iconv.m4
m4/intdiv0.m4
m4/intmax.m4
m4/inttypes-pri.m4
m4/inttypes.m4
m4/inttypes_h.m4
m4/isc-posix.m4
m4/lcmessage.m4
m4/lib-ld.m4
m4/lib-link.m4
m4/lib-prefix.m4
m4/libtool.m4
m4/longdouble.m4
m4/longlong.m4
m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
m4/nls.m4
m4/po.m4
m4/printf-posix.m4
m4/progtest.m4
m4/signed.m4
m4/size_max.m4
m4/stdint_h.m4
m4/uintmax_t.m4
m4/ulonglong.m4
m4/wchar_t.m4
m4/wint_t.m4
m4/xsize.m4
mingw32-libvirt.spec
mkinstalldirs
po/*.gmo
po/Makefile
po/Makefile.in
po/Makefile.in.in
po/Makevars.template
po/POTFILES
po/Rules-quot
po/boldquot.sed
po/en@boldquot.header
po/en@quot.header
po/insert-header.sin
po/quot.sed
po/remove-potcdate.sed
po/remove-potcdate.sin
po/stamp-po
proxy/.deps
proxy/.libs
proxy/Makefile
proxy/Makefile.in
proxy/libvirt_proxy
python/*.la
python/*.lo
python/*.loT
python/*.pyc
python/.deps
python/.libs
python/Makefile
python/Makefile.in
python/gen_prog
python/generated.stamp
python/libvirt-export.c
python/libvirt-py.[ch]
python/libvirt.py
python/libvirtclass.py
python/libvirtclass.txt
python/tests/Makefile
python/tests/Makefile.in
qemud/*.gcda
qemud/*.gcno
qemud/*.la
qemud/*.lo
qemud/.deps
qemud/.libs
qemud/Makefile
qemud/Makefile.in
qemud/libvirt_qemud
qemud/libvirtd
qemud/libvirtd.init
qemud/libvirtd.logrotate
results.log
src/*.cov
src/*.exe
src/*.gcda
src/*.gcno
src/*.gcov
src/*.i
src/*.la
src/*.lo
src/*.loT
src/*.s
src/.deps
src/.libs
src/Makefile
src/Makefile.in
src/libvirt.syms
src/libvirt_lxc
src/libvirt_parthelper
src/virsh
src/virsh-net-edit.c
src/virsh-pool-edit.c
stamp-h
stamp-h.in
stamp-h1
tests/*.exe
tests/*.gcda
tests/*.gcno
tests/.deps
tests/.libs
tests/Makefile
tests/Makefile.in
tests/confdata/Makefile
tests/confdata/Makefile.in
tests/conftest
tests/eventtest
tests/nodedevxml2xmltest
tests/nodeinfotest
tests/object-locking
tests/object-locking-files.txt
tests/object-locking.cmi
tests/object-locking.cmx
tests/qemuargv2xmltest
tests/qemuhelptest
tests/qemuxml2argvtest
tests/qemuxml2xmltest
tests/qparamtest
tests/reconnect
tests/seclabeltest
tests/sexpr2xmldata/Makefile
tests/sexpr2xmldata/Makefile.in
tests/sexpr2xmltest
tests/statstest
tests/virshtest
tests/xencapsdata/Makefile
tests/xencapsdata/Makefile.in
tests/xencapstest
tests/xmconfigdata/Makefile
tests/xmconfigdata/Makefile.in
tests/xmconfigtest
tests/xml2sexprdata/Makefile
tests/xml2sexprdata/Makefile.in
tests/xml2sexprtest
tools/Makefile
tools/Makefile.in
tools/virt-xml-validate
tools/virt-xml-validate.1
update.log

View File

@@ -1 +0,0 @@
^gnulib/.*

View File

@@ -1 +0,0 @@
^ChangeLog

View File

@@ -1,7 +0,0 @@
^src/libvirt\.c$
^src/qemu/qemu_driver\.c$
^src/qemu/qemu_monitor\.c$
^src/util/util\.c$
^src/xen/xend_internal\.c$
^daemon/libvirtd.c$
^gnulib/

View File

@@ -1 +0,0 @@
^gnulib/m4/intl\.m4$

View File

@@ -1 +0,0 @@
gnulib/.*

View File

@@ -1,5 +0,0 @@
^ChangeLog$
^ChangeLog-old$
^include/libvirt/virterror\.h$
^daemon/dispatch\.c$
^src/util/virterror\.c$

View File

@@ -1,3 +0,0 @@
^gnulib/
^po/
ChangeLog

View File

@@ -1,2 +0,0 @@
^gnulib/lib/getaddrinfo\.c$
^gnulib/m4/

View File

@@ -1,2 +0,0 @@
^src/util/util\.c$
^ChangeLog-old$

View File

@@ -1 +0,0 @@
^gnulib/lib/strsep\.c$

View File

@@ -1,10 +0,0 @@
^gnulib/
^po/
^ChangeLog$
^ChangeLog-old$
^Makefile*
^docs/
^tests/
^tools/virsh\.c$
^tools/console\.c$
^build-aux/

View File

@@ -1 +0,0 @@
^gnulib/

View File

@@ -1,9 +0,0 @@
^gnulib/
^ChangeLog-old$
^docs/
^examples/domain-events/events-c/event-test\.c$
^src/internal\.h$
^src/lxc/lxc_container\.c$
^src/node_device/node_device_devkit\.c$
^src/node_device/node_device_hal\.c$
^src/storage/parthelper\.c$

View File

@@ -1 +0,0 @@
^src/util/util\.c$

View File

@@ -1,4 +0,0 @@
^examples/
^gnulib/lib/dummy\.c$
^gnulib/tests/dummy\.c$
^ChangeLog$

View File

@@ -1 +0,0 @@
^examples/

View File

@@ -1,7 +0,0 @@
\.fig$
\.gif$
\.ico$
\.png$
^ChangeLog$
^NEWS$
^docs/.*

100
AUTHORS
View File

@@ -1,100 +0,0 @@
libvirt Authors
===============
The libvirt project was initiated by:
Daniel Veillard <veillard@redhat.com> or <daniel@veillard.com>
The primary maintainers and people with commit access rights:
Daniel Veillard <veillard@redhat.com>
Daniel Berrange <berrange@redhat.com>
Richard W.M. Jones <rjones@redhat.com>
Karel Zak <kzak@redhat.com>
Mark McLoughlin <markmc@redhat.com>
Anthony Liguori <aliguori@us.ibm.com>
Jim Meyering <meyering@redhat.com>
Jim Fehlig <jfehlig@novell.com>
Chris Lalancette <clalance@redhat.com>
Atsushi SAKAI <sakaia@jp.fujitsu.com>
Dave Leskovec <dlesko@linux.vnet.ibm.com>
Cole Robinson <crobinso@redhat.com>
Dan Smith <danms@us.ibm.com>
Guido Günther <agx@sigxcpu.org>
John Levon <john.levon@sun.com>
Matthias Bolte <matthias.bolte@googlemail.com>
Patches have also been contributed by:
David Lutterkort <dlutter@redhat.com>
Andrew Puch <apuch@redhat.com>
Philippe Berthault <philippe.berthault@Bull.net>
Hugh Brock <hbrock@redhat.com>
Michel Ponceau <michel.ponceau@bull.net>
Jeremy Katz <katzj@redhat.com>
Pete Vetere <pvetere@redhat.com>
Kazuki Mizushima <mizushima.kazuk@jp.fujitsu.com>
Saori Fukuta <fukuta.saori@jp.fujitsu.com>
Tatsuro Enokura <fj7716hz@aa.jp.fujitsu.com>
Takahashi Tomohiro <takatom@jp.fujitsu.com>
Nobuhiro Itou <fj0873gn@aa.jp.fujitsu.com>
Masayuki Sunou <fj1826dm@aa.jp.fujitsu.com>
Mark Johnson <johnson.nh@gmail.com>
Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
Shuveb Hussain <shuveb@binarykarma.com>
Jim Paris <jim@jtan.com>
Daniel Hokka Zakrisson <daniel@hozac.com>
Mads Chr. Olesen <shiyee@shiyee.dk>
Anton Protopopov <aspsk2@gmail.com>
Stefan de Konink <dekonink@kinkrsoftware.nl>
Kaitlin Rupert <kaitlin@linux.vnet.ibm.com>
Evgeniy Sokolov <evg@openvz.org>
David Lively <dlively@virtualiron.com>
Charles Duffy <Charles_Duffy@messageone.com>
Nguyen Anh Quynh <aquynh@gmail.com>
James Morris <jmorris@namei.org>
Chris Wright <chrisw@redhat.com>
Ben Guthro <ben.guthro@gmail.com>
Shigeki Sakamoto <fj0588di@aa.jp.fujitsu.com>
Gerd von Egidy <lists@egidy.de>
Itamar Heim <iheim@redhat.com>
Dave Allan <dallan@redhat.com>
Markus Armbruster <armbru@redhat.com>
Ryota Ozaki <ozaki.ryota@gmail.com>
James Morris <jmorris@namei.org>
Daniel J Walsh <dwalsh@redhat.com>
Maximilian Wilhelm <max@rfc2324.org>
Pritesh Kothari <Pritesh.Kothari@Sun.COM>
Amit Shah <amit.shah@redhat.com>
Florian Vichot <florian.vichot@diateam.net>
Takahashi Tomohiro <takatom@jp.fujitsu.com>
Serge E. Hallyn <serue@us.ibm.com>
Soren Hansen <soren@canonical.com>
Laine Stump <laine@redhat.com>
Abel Míguez Rodríguez<amiguezr@pdi.ucm.es>
Doug Goldstein <cardoe@gentoo.org>
Javier Fontan <jfontan@gmail.com>
Federico Simoncelli <federico.simoncelli@gmail.com>
Amy Griffis <amy.griffis@hp.com>
Henrik Persson E <henrik.e.persson@ericsson.com>
Satoru SATOH <satoru.satoh@gmail.com>
Paolo Bonzini <pbonzini@redhat.com>
Miloslav Trmač <mitr@redhat.com>
Jiri Denemark <jdenemar@redhat.com>
Jamie Strandboge <jamie@canonical.com>
Gerhard Stenzel <gerhard.stenzel@de.ibm.com>
Matthew Booth <mbooth@redhat.com>
Diego Elio Pettenò <flameeyes@gmail.com>
Adam Litke <agl@us.ibm.com>
Steve Yarmie <steve.yarmie@gmail.com>
Dan Kenigsberg <danken@redhat.com>
Yuji NISHIDA <nishidy@nict.go.jp>
[....send patches to get your name here....]
The libvirt Logo was designed by Diana Fong
-- End
;; Local Variables:
;; coding: utf-8
;; End:

View File

@@ -506,3 +506,5 @@ if necessary. Here is a sample; alter the names:
Ty Coon, President of Vice
That's all there is to it!

4
ChangeLog Normal file
View File

@@ -0,0 +1,4 @@
Wed Nov 2 13:44:47 CET 2005 Daniel Veillard <veillard@redhat.com>
* src/libxen.c src/Makefile.am include/libxen.h configure.in
Makefile.am COPYING.LIB: creation

File diff suppressed because it is too large Load Diff

394
HACKING
View File

@@ -1,394 +0,0 @@
Libvirt contributor guidelines
==============================
General tips for contributing patches
=====================================
(1) Discuss any large changes on the mailing list first. Post patches
early and listen to feedback.
(2) Post patches in unified diff format. A command similar to this
should work:
diff -urp libvirt.orig/ libvirt.modified/ > libvirt-myfeature.patch
or:
cvs diff -up > libvirt-myfeature.patch
(3) Split large changes into a series of smaller patches, self-contained
if possible, with an explanation of each patch and an explanation of how
the sequence of patches fits together.
(4) Make sure your patches apply against libvirt CVS. Developers
only follow CVS and don't care much about released versions.
(5) Run the automated tests on your code before submitting any changes.
In particular, configure with compile warnings set to -Werror:
./configure --enable-compile-warnings=error
and run the tests:
make check
make syntax-check
make -C tests valgrind
The latter test checks for memory leaks.
If you encounter any failing tests, the VIR_TEST_DEBUG environment variable
may provide extra information to debug the failures. Larger values of
VIR_TEST_DEBUG may provide larger amounts of information:
VIR_TEST_DEBUG=1 make check (or)
VIR_TEST_DEBUG=2 make check
Also, individual tests can be run from inside the 'tests/' directory, like:
./qemuxml2xmltest
(6) Update tests and/or documentation, particularly if you are adding
a new feature or changing the output of a program.
There is more on this subject, including lots of links to background
reading on the subject, on this page:
http://et.redhat.com/~rjones/how-to-supply-code-to-open-source-projects/
Code indentation
================
Libvirt's C source code generally adheres to some basic code-formatting
conventions. The existing code base is not totally consistent on this
front, but we do prefer that contributed code be formatted similarly.
In short, use spaces-not-TABs for indentation, use 4 spaces for each
indentation level, and other than that, follow the K&R style.
If you use Emacs, add the following to one of one of your start-up files
(e.g., ~/.emacs), to help ensure that you get indentation right:
;;; When editing C sources in libvirt, use this style.
(defun libvirt-c-mode ()
"C mode with adjusted defaults for use with libvirt."
(interactive)
(c-set-style "K&R")
(setq indent-tabs-mode nil) ; indent using spaces, not TABs
(setq c-indent-level 4)
(setq c-basic-offset 4))
(add-hook 'c-mode-hook
'(lambda () (if (string-match "/libvirt" (buffer-file-name))
(libvirt-c-mode))))
Code formatting (especially for new code)
=========================================
With new code, we can be even more strict.
Please apply the following function (using GNU indent) to any new code.
Note that this also gives you an idea of the type of spacing we prefer
around operators and keywords:
indent-libvirt()
{
indent -bad -bap -bbb -bli4 -br -ce -brs -cs -i4 -l75 -lc75 \
-sbi4 -psl -saf -sai -saw -sbi4 -ss -sc -cdw -cli4 -npcs -nbc \
--no-tabs "$@"
}
Note that sometimes you'll have to postprocess that output further, by
piping it through "expand -i", since some leading TABs can get through.
Usually they're in macro definitions or strings, and should be converted
anyhow.
C types
=======
Use the right type.
Scalars
-------
If you're using "int" or "long", odds are good that there's a better type.
If a variable is counting something, be sure to declare it with an
unsigned type.
If it's memory-size-related, use size_t (use ssize_t only if required).
If it's file-size related, use uintmax_t, or maybe off_t.
If it's file-offset related (i.e., signed), use off_t.
If it's just counting small numbers use "unsigned int";
(on all but oddball embedded systems, you can assume that that
type is at least four bytes wide).
If a variable has boolean semantics, give it the "bool" type
and use the corresponding "true" and "false" macros. It's ok
to include <stdbool.h>, since libvirt's use of gnulib ensures
that it exists and is usable.
In the unusual event that you require a specific width, use a
standard type like int32_t, uint32_t, uint64_t, etc.
While using "bool" is good for readability, it comes with minor caveats:
- Don't use "bool" in places where the type size must be constant across
all systems, like public interfaces and on-the-wire protocols. Note
that it would be possible (albeit wasteful) to use "bool" in libvirt's
logical wire protocol, since XDR maps that to its lower-level bool_t
type, which *is* fixed-size.
- Don't compare a bool variable against the literal, "true",
since a value with a logical non-false value need not be "1".
I.e., don't write "if (seen == true) ...". Rather, write "if (seen)...".
Of course, take all of the above with a grain of salt. If you're about
to use some system interface that requires a type like size_t, pid_t or
off_t, use matching types for any corresponding variables.
Also, if you try to use e.g., "unsigned int" as a type, and that
conflicts with the signedness of a related variable, sometimes
it's best just to use the *wrong* type, if "pulling the thread"
and fixing all related variables would be too invasive.
Finally, while using descriptive types is important, be careful not to
go overboard. If whatever you're doing causes warnings, or requires
casts, then reconsider or ask for help.
Pointers
--------
Ensure that all of your pointers are "const-correct".
Unless a pointer is used to modify the pointed-to storage,
give it the "const" attribute. That way, the reader knows
up-front that this is a read-only pointer. Perhaps more
importantly, if we're diligent about this, when you see a non-const
pointer, you're guaranteed that it is used to modify the storage
it points to, or it is aliased to another pointer that is.
Low level memory management
===========================
Use of the malloc/free/realloc/calloc APIs is deprecated in the libvirt
codebase, because they encourage a number of serious coding bugs and do
not enable compile time verification of checks for NULL. Instead of these
routines, use the macros from memory.h
- eg to allocate a single object:
virDomainPtr domain;
if (VIR_ALLOC(domain) < 0) {
__virRaiseError(VIR_ERROR_NO_MEMORY)
return NULL;
}
- eg to allocate an array of objects
virDomainPtr domains;
int ndomains = 10;
if (VIR_ALLOC_N(domains, ndomains) < 0) {
__virRaiseError(VIR_ERROR_NO_MEMORY)
return NULL;
}
- eg to allocate an array of object pointers
virDomainPtr *domains;
int ndomains = 10;
if (VIR_ALLOC_N(domains, ndomains) < 0) {
__virRaiseError(VIR_ERROR_NO_MEMORY)
return NULL;
}
- eg to re-allocate the array of domains to be longer
ndomains = 20
if (VIR_REALLOC_N(domains, ndomains) < 0) {
__virRaiseError(VIR_ERROR_NO_MEMORY)
return NULL;
}
- eg to free the domain
VIR_FREE(domain);
String comparisons
==================
Do not use the strcmp, strncmp, etc functions directly. Instead use
one of the following semantically named macros
- For strict equality:
STREQ(a,b)
STRNEQ(a,b)
- For case sensitive equality:
STRCASEEQ(a,b)
STRCASENEQ(a,b)
- For strict equality of a substring:
STREQLEN(a,b,n)
STRNEQLEN(a,b,n)
- For case sensitive equality of a substring:
STRCASEEQLEN(a,b,n)
STRCASENEQLEN(a,b,n)
- For strict equality of a prefix:
STRPREFIX(a,b)
String copying
==============
Do not use the strncpy function. According to the man page, it does
*not* guarantee a NULL-terminated buffer, which makes it extremely dangerous
to use. Instead, use one of the functionally equivalent functions:
- virStrncpy(char *dest, const char *src, size_t n, size_t destbytes)
The first three arguments have the same meaning as for strncpy; namely the
destination, source, and number of bytes to copy, respectively. The last
argument is the number of bytes available in the destination string; if a
copy of the source string (including a \0) will not fit into the
destination, no bytes are copied and the routine returns NULL.
Otherwise, n bytes from the source are copied into the destination and a
trailing \0 is appended.
- virStrcpy(char *dest, const char *src, size_t destbytes)
Use this variant if you know you want to copy the entire src string
into dest. Note that this is a macro, so arguments could be
evaluated more than once. This is equivalent to
virStrncpy(dest, src, strlen(src), destbytes)
- virStrcpyStatic(char *dest, const char *src)
Use this variant if you know you want to copy the entire src string
into dest *and* you know that your destination string is a static string
(i.e. that sizeof(dest) returns something meaningful). Note that
this is a macro, so arguments could be evaluated more than once. This is
equivalent to virStrncpy(dest, src, strlen(src), sizeof(dest)).
Variable length string buffer
=============================
If there is a need for complex string concatenations, avoid using
the usual sequence of malloc/strcpy/strcat/snprintf functions and
make use of the virBuffer API described in buf.h
eg typical usage is as follows:
char *
somefunction(...) {
virBuffer buf = VIR_BUFFER_INITIALIZER;
...
virBufferAddLit(&buf, "<domain>\n");
virBufferVSprint(&buf, " <memory>%d</memory>\n", memory);
...
virBufferAddLit(&buf, "</domain>\n");
...
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError(...);
return NULL;
}
return virBufferContentAndReset(&buf);
}
Include files
=============
There are now quite a large number of include files, both libvirt
internal and external, and system includes. To manage all this
complexity it's best to stick to the following general plan for all
*.c source files:
/*
* Copyright notice
* ....
* ....
* ....
*
*/
#include <config.h> Must come first in every file.
#include <stdio.h> Any system includes you need.
#include <string.h>
#include <limits.h>
#if HAVE_NUMACTL Some system includes aren't supported
#include <numa.h> everywhere so need these #if defences.
#endif
#include "internal.h" Include this first, after system includes.
#include "util.h" Any libvirt internal header files.
#include "buf.h"
static myInternalFunc () The actual code.
{
...
Of particular note: *DO NOT* include libvirt/libvirt.h or
libvirt/virterror.h. It is included by "internal.h" already and there
are some special reasons why you cannot include these files
explicitly.
Printf-style functions
======================
Whenever you add a new printf-style function, i.e., one with a format
string argument and following "..." in its prototype, be sure to use
gcc's printf attribute directive in the prototype. For example, here's
the one for virAsprintf, in util.h:
int virAsprintf(char **strp, const char *fmt, ...)
ATTRIBUTE_FMT_PRINTF(2, 3);
This makes it so gcc's -Wformat and -Wformat-security options can do
their jobs and cross-check format strings with the number and types
of arguments.
Libvirt commiters guidelines
============================
The AUTHORS files indicates the list of people with commit acces right
who can actually merge the patches.
The general rule for commiting patches is to make sure it has been reviewed
properly in the mailing-list first, usually if a couple of persons gave an
ACK or +1 to a patch and nobody raised an objection on the list it should
be good to go. If the patch touches a part of the code where you're not the
main maintainer or not have a very clear idea of how things work, it's better
to wait for a more authoritative feedback though. Before commiting please
also rebuild locally and run 'make check syntax-check' and make sure they
don't raise error. Try to look for warnings too for example configure with
--enable-compile-warnings=error
which adds -Werror to compile flags, so no warnings get missed
Exceptions to that 'review and approval on the list first' is fixing failures
to build:
- if a recently commited patch breaks compilation on a platform
or for a given driver then it's fine to commit a minimal fix
directly without getting the review feedback first
- similary if make check or make syntax-chek breaks, if there is
an obvious fix, it's fine to commit immediately
The patch should still be sent to the list (or tell what the fix was if
trivial) and 'make check syntax-check' should pass too before commiting
anything
Similary fixes for documentation and code comments can be managed
in the same way, but still make sure they get reviewed if non-trivial.

View File

@@ -1,91 +1,9 @@
## Process this file with automake to produce Makefile.in
LCOV = lcov
GENHTML = genhtml
SUBDIRS = gnulib/lib include src daemon tools proxy docs gnulib/tests \
python tests po examples/domain-events/events-c examples/hellolibvirt \
examples/dominfo examples/domsuspend examples/python examples/apparmor
ACLOCAL_AMFLAGS = -I m4 -I gnulib/m4
XML_EXAMPLES = $(wildcard examples/xml/test/*.xml) $(wildcard examples/xml/storage/*.xml)
EXTRA_DIST = \
ChangeLog-old \
libvirt.spec libvirt.spec.in \
mingw32-libvirt.spec.in \
libvirt.pc libvirt.pc.in \
autobuild.sh \
.x-sc_avoid_ctype_macros \
.x-sc_avoid_if_before_free \
.x-sc_avoid_write \
.x-sc_m4_quote_check \
.x-sc_prohibit_asprintf \
.x-sc_prohibit_gethostby \
.x-sc_prohibit_gethostname \
.x-sc_prohibit_have_config_h \
.x-sc_prohibit_HAVE_MBRTOWC \
.x-sc_prohibit_nonreentrant \
.x-sc_prohibit_strcmp \
.x-sc_prohibit_strcmp_and_strncmp \
.x-sc_prohibit_strncpy \
.x-sc_prohibit_VIR_ERR_NO_MEMORY \
.x-sc_require_config_h \
.x-sc_require_config_h_first \
.x-sc_trailing_blank \
Makefile.nonreentrant \
autogen.sh \
examples/domain-events/events-python \
$(XML_EXAMPLES)
SUBDIRS = src #docs
EXTRA_DIST = libxen.spec.in libxen.spec COPYING.LIB \
libxen.pc.in libxen.pc
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libvirt.pc
pkgconfig_DATA = libxen.pc
NEWS: $(top_srcdir)/docs/news.xsl $(top_srcdir)/docs/news.html.in
-@(if [ -x $(XSLTPROC) ] ; then \
$(XSLTPROC) --nonet $(top_srcdir)/docs/news.xsl \
$(top_srcdir)/docs/news.html.in \
| perl -0777 -pe 's/\n\n+$$/\n/' \
| perl -pe 's/[ \t]+$$//' \
> $@-t && mv $@-t $@ ; fi );
rpm: clean
@(unset CDPATH ; $(MAKE) dist && rpmbuild -ta $(distdir).tar.gz)
check-local: all tests
tests:
@(cd docs/examples ; $(MAKE) MAKEFLAGS+=--silent tests)
@(if [ "$(pythondir)" != "" ] ; then cd python ; \
$(MAKE) MAKEFLAGS+=--silent tests ; fi)
cov: clean-cov
mkdir $(top_builddir)/coverage
$(LCOV) -c -o $(top_builddir)/coverage/libvirt.info.tmp -d $(top_srcdir)/src -d $(top_srcdir)/daemon -d $(top_srcdir)/tests
$(LCOV) -r $(top_builddir)/coverage/libvirt.info.tmp -o $(top_builddir)/coverage/libvirt.info *usr*
rm $(top_builddir)/coverage/libvirt.info.tmp
$(GENHTML) -s -t "libvirt" -o $(top_builddir)/coverage --legend $(top_builddir)/coverage/libvirt.info
clean-cov:
rm -rf $(top_builddir)/coverage
MAINTAINERCLEANFILES = .git-module-status
# disable this check
distuninstallcheck:
dist-hook: gen-ChangeLog
# Generate the ChangeLog file (with all entries since the switch to git)
# and insert it into the directory we're about to use to create a tarball.
gen_start_date = 2009-07-04
.PHONY: gen-ChangeLog
gen-ChangeLog:
if test -d .git; then \
$(top_srcdir)/build-aux/gitlog-to-changelog \
--since=$(gen_start_date) > $(distdir)/cl-t; \
rm -f $(distdir)/ChangeLog; \
mv $(distdir)/cl-t $(distdir)/ChangeLog; \
fi

View File

@@ -1,85 +0,0 @@
#
# Generated by running the following on Fedora 9:
#
# nm -D --defined-only /lib/libc.so.6 \
# | grep '_r$' \
# | awk '{print $3}' \
# | grep -v __ \
# | grep -v qsort \ # Red herring since we don't need to pass extra args to qsort comparator
# | grep -v readdir \ # This is safe as long as each DIR * instance is only used by one thread
# | sort \
# | uniq \
# | sed -e 's/_r//'
#
NON_REENTRANT =
NON_REENTRANT += asctime
NON_REENTRANT += ctime
NON_REENTRANT += drand48
NON_REENTRANT += ecvt
NON_REENTRANT += erand48
NON_REENTRANT += ether_aton
NON_REENTRANT += ether_ntoa
NON_REENTRANT += fcvt
NON_REENTRANT += fgetgrent
NON_REENTRANT += fgetpwent
NON_REENTRANT += fgetspent
NON_REENTRANT += getaliasbyname
NON_REENTRANT += getaliasent
NON_REENTRANT += getdate
NON_REENTRANT += getgrent
NON_REENTRANT += getgrgid
NON_REENTRANT += getgrnam
NON_REENTRANT += gethostbyaddr
NON_REENTRANT += gethostbyname2
NON_REENTRANT += gethostbyname
NON_REENTRANT += gethostent
NON_REENTRANT += getlogin
NON_REENTRANT += getmntent
NON_REENTRANT += getnetbyaddr
NON_REENTRANT += getnetbyname
NON_REENTRANT += getnetent
NON_REENTRANT += getnetgrent
NON_REENTRANT += getprotobyname
NON_REENTRANT += getprotobynumber
NON_REENTRANT += getprotoent
NON_REENTRANT += getpwent
NON_REENTRANT += getpwnam
NON_REENTRANT += getpwuid
NON_REENTRANT += getrpcbyname
NON_REENTRANT += getrpcbynumber
NON_REENTRANT += getrpcent
NON_REENTRANT += getservbyname
NON_REENTRANT += getservbyport
NON_REENTRANT += getservent
NON_REENTRANT += getspent
NON_REENTRANT += getspnam
NON_REENTRANT += getutent
NON_REENTRANT += getutid
NON_REENTRANT += getutline
NON_REENTRANT += gmtime
NON_REENTRANT += hcreate
NON_REENTRANT += hdestroy
NON_REENTRANT += hsearch
NON_REENTRANT += initstate
NON_REENTRANT += jrand48
NON_REENTRANT += lcong48
NON_REENTRANT += localtime
NON_REENTRANT += lrand48
NON_REENTRANT += mrand48
NON_REENTRANT += nrand48
NON_REENTRANT += ptsname
NON_REENTRANT += qecvt
NON_REENTRANT += qfcvt
NON_REENTRANT += random
NON_REENTRANT += rand
NON_REENTRANT += seed48
NON_REENTRANT += setstate
NON_REENTRANT += sgetspent
NON_REENTRANT += srand48
NON_REENTRANT += srandom
NON_REENTRANT += strerror
NON_REENTRANT += strtok
NON_REENTRANT += tmpnam
NON_REENTRANT += ttyname

13
README
View File

@@ -1,13 +0,0 @@
LibVirt : simple API for virtualization
Libvirt is a C toolkit to interact with the virtualization capabilities
of recent versions of Linux (and other OSes). It is free software
available under the GNU Lesser General Public License. Virtualization of
the Linux Operating System means the ability to run multiple instances of
Operating Systems concurrently on a single hardware system where the basic
resources are driven by a Linux instance. The library aim at providing
long term stable C API initially for the Xen paravirtualization but
should be able to integrate other virtualization mechanisms if needed.
Daniel Veillard <veillard@redhat.com>

View File

@@ -1,52 +0,0 @@
-*- outline -*-
These notes intend to help people working on the checked-out sources.
These requirements do not apply when building from a distribution tarball.
See also HACKING for more detailed libvirt contribution guidelines.
* Requirements
We've opted to keep only the highest-level sources in the GIT repository.
This eases our maintenance burden, (fewer merges etc.), but imposes more
requirements on anyone wishing to build from the just-checked-out sources.
Note the requirements to build the released archive are much less and
are just the requirements of the standard ./configure && make procedure.
Specific development tools and versions will be checked for and listed by
the bootstrap script. See README-prereq for specific notes on obtaining
these prerequisite tools.
Valgrind <http://valgrind.org/> is also highly recommended, if
Valgrind supports your architecture. See also README-valgrind.
While building from a just-cloned source tree may require installing a
few prerequisites, later, a plain `git pull && make' should be sufficient.
* First GIT checkout
You can get a copy of the source repository like this:
$ git clone git://libvirt.org/libvirt
$ cd libvirt
The next step is to get all required pieces from gnulib,
to run autoreconf, and to invoke ./configure:
$ ./autogen.sh
And there you are! Just
$ make
$ make check
At this point, there should be no difference between your local copy,
and the GIT master copy:
$ git diff
should output no difference.
Enjoy!
Local Variables:
indent-tabs-mode: nil
End:

29
TODO
View File

@@ -1,29 +0,0 @@
TODO:
- libvirt_virDomainSetMemory should check memory is > 0
- check how to better handle renaming of domains (xm rename and cache)
- UUID lookup in hash.c
Other environment:
- support for UML
+ UML control layer should be easy at least for one user but incomplete
Probable TODOs:
- event on big domain state change (create, crashed, paused, shutdown, destroy)
- bindings for more languages
Would-be-nice TODO:
- man page for virsh and the libraries entry points
- more documentation and examples on using the toolkit
- examples for the error handling code
Cleanup:
- now that libxml2 is linked in, drop hash.[ch] and get back to libxml2 ones ?
same for the buffers
Autoconf:
- On Debian and other platforms, C++ compiler is required because
autoconf macros to detect libtool depend on it. (This is probably
an autoconf or libtool m4 macro bug, and the fact that it happens
on Debian is a red herring).

View File

@@ -1,109 +0,0 @@
dnl
dnl Taken from gnome-common/macros2/gnome-compiler-flags.m4
dnl
dnl We've added:
dnl -Wextra -Wshadow -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Winline -Wredundant-decls
dnl We've removed
dnl CFLAGS="$realsave_CFLAGS"
dnl to avoid clobbering user-specified CFLAGS
dnl
AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[
dnl ******************************
dnl More compiler warnings
dnl ******************************
AC_ARG_ENABLE(compile-warnings,
AC_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],
[Turn on compiler warnings]),,
[enable_compile_warnings="m4_default([$1],[maximum])"])
warnCFLAGS=
common_flags="-Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fasynchronous-unwind-tables"
case "$enable_compile_warnings" in
no)
try_compiler_flags=""
;;
minimum)
try_compiler_flags="-Wall -Wformat -Wformat-security $common_flags"
;;
yes)
try_compiler_flags="-Wall -Wformat -Wformat-security -Wmissing-prototypes $common_flags"
;;
maximum|error)
try_compiler_flags="-Wall -Wformat -Wformat-security -Wmissing-prototypes -Wnested-externs -Wpointer-arith"
try_compiler_flags="$try_compiler_flags -Wextra -Wshadow -Wcast-align -Wwrite-strings -Waggregate-return"
try_compiler_flags="$try_compiler_flags -Wstrict-prototypes -Winline -Wredundant-decls -Wno-sign-compare"
try_compiler_flags="$try_compiler_flags $common_flags"
if test "$enable_compile_warnings" = "error" ; then
try_compiler_flags="$try_compiler_flags -Werror"
fi
;;
*)
AC_MSG_ERROR(Unknown argument '$enable_compile_warnings' to --enable-compile-warnings)
;;
esac
COMPILER_FLAGS=
for option in $try_compiler_flags; do
gl_COMPILER_FLAGS($option)
done
unset option
unset try_compiler_flags
AC_ARG_ENABLE(iso-c,
AC_HELP_STRING([--enable-iso-c],
[Try to warn if code is not ISO C ]),,
[enable_iso_c=no])
AC_MSG_CHECKING(what language compliance flags to pass to the C compiler)
complCFLAGS=
if test "x$enable_iso_c" != "xno"; then
if test "x$GCC" = "xyes"; then
case " $CFLAGS " in
*[\ \ ]-ansi[\ \ ]*) ;;
*) complCFLAGS="$complCFLAGS -ansi" ;;
esac
case " $CFLAGS " in
*[\ \ ]-pedantic[\ \ ]*) ;;
*) complCFLAGS="$complCFLAGS -pedantic" ;;
esac
fi
fi
AC_MSG_RESULT($complCFLAGS)
WARN_CFLAGS="$COMPILER_FLAGS $complCFLAGS"
AC_SUBST(WARN_CFLAGS)
dnl Needed to keep compile quiet on python 2.4
COMPILER_FLAGS=
gl_COMPILER_FLAGS(-Wno-redundant-decls)
WARN_PYTHON_CFLAGS=$COMPILER_FLAGS
AC_SUBST(WARN_PYTHON_CFLAGS)
])
dnl
dnl To support the old pkg-config from RHEL4 vintage, we need
dnl to define the PKG_PROG_PKG_CONFIG macro if its not already
dnl present
m4_ifndef([PKG_PROG_PKG_CONFIG],
[AC_DEFUN([PKG_PROG_PKG_CONFIG],
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
fi
if test -n "$PKG_CONFIG"; then
_pkg_min_version=m4_default([$1], [0.9.0])
AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
PKG_CONFIG=""
fi
fi[]dnl
])])

View File

@@ -1,96 +0,0 @@
#!/bin/sh
set -e
set -v
# Make things clean.
test -n "$1" && RESULTS=$1 || RESULTS=results.log
test -f Makefile && make -k distclean || :
rm -rf coverage
#rm -rf build
#mkdir build
#cd build
./autogen.sh --prefix="$AUTOBUILD_INSTALL_ROOT" \
--enable-test-coverage \
--enable-compile-warnings=error \
--with-xen-proxy
# If the MAKEFLAGS envvar does not yet include a -j option,
# add -jN where N depends on the number of processors.
case $MAKEFLAGS in
*-j*) ;;
*) n=$(getconf _NPROCESSORS_ONLN 2> /dev/null)
test "$n" -gt 0 || n=1
n=$(expr $n + 1)
MAKEFLAGS="$MAKEFLAGS -j$n"
export MAKEFLAGS
;;
esac
make
make install
set -o pipefail
make check 2>&1 | tee "$RESULTS"
make syntax-check 2>&1 | tee -a "$RESULTS"
test -x /usr/bin/lcov && make cov
rm -f *.tar.gz
make dist
if [ -n "$AUTOBUILD_COUNTER" ]; then
EXTRA_RELEASE=".auto$AUTOBUILD_COUNTER"
else
NOW=`date +"%s"`
EXTRA_RELEASE=".$USER$NOW"
fi
if [ -f /usr/bin/rpmbuild ]; then
rpmbuild --nodeps \
--define "extra_release $EXTRA_RELEASE" \
--define "_sourcedir `pwd`" \
-ba --clean libvirt.spec
fi
if [ -x /usr/bin/i686-pc-mingw32-gcc ]; then
make distclean
PKG_CONFIG_PATH="$AUTOBUILD_INSTALL_ROOT/i686-pc-mingw32/sys-root/mingw/lib/pkgconfig" \
CC="i686-pc-mingw32-gcc" \
./configure \
--build=$(uname -m)-pc-linux \
--host=i686-pc-mingw32 \
--prefix="$AUTOBUILD_INSTALL_ROOT/i686-pc-mingw32/sys-root/mingw" \
--enable-compile-warnings=error \
--without-sasl \
--without-avahi \
--without-polkit \
--without-python \
--without-xen \
--without-qemu \
--without-lxc \
--without-uml \
--without-vbox \
--without-openvz \
--without-one \
--without-phyp \
--without-netcf \
--without-libvirtd
make
make install
#set -o pipefail
#make check 2>&1 | tee "$RESULTS"
if [ -f /usr/bin/rpmbuild ]; then
rpmbuild --nodeps \
--define "extra_release $EXTRA_RELEASE" \
--define "_sourcedir `pwd`" \
-ba --clean mingw32-libvirt.spec
fi
fi

View File

@@ -1,91 +0,0 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
THEDIR=`pwd`
cd $srcdir
DIE=0
(autopoint --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have autopoint installed to compile libvirt."
echo "Download the appropriate package for your distribution,"
echo "or see http://www.gnu.org/software/gettext"
DIE=1
}
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have autoconf installed to compile libvirt."
echo "Download the appropriate package for your distribution,"
echo "or see http://www.gnu.org/software/autoconf"
DIE=1
}
(libtool --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have libtool installed to compile libvirt."
echo "Download the appropriate package for your distribution,"
echo "or see http://www.gnu.org/software/libtool"
DIE=1
}
(automake --version) < /dev/null > /dev/null 2>&1 || {
echo
DIE=1
echo "You must have automake installed to compile libvirt."
echo "Download the appropriate package for your distribution,"
echo "or see http://www.gnu.org/software/automake"
}
if test "$DIE" -eq 1; then
exit 1
fi
test -f src/libvirt.c || {
echo "You must run this script in the top-level libvirt directory"
exit 1
}
EXTRA_ARGS=
if test "x$1" = "x--system"; then
shift
EXTRA_ARGS="--prefix=/usr --sysconfdir=/etc --localstatedir=/var"
echo "Running ./configure with $EXTRA_ARGS $@"
else
if test -z "$*"; then
echo "I am going to run ./configure with no arguments - if you wish "
echo "to pass any to it, please specify them on the $0 command line."
fi
fi
# Ensure that whenever we pull in a gnulib update or otherwise change to a
# different version (i.e., when switching branches), we also rerun ./bootstrap.
curr_status=.git-module-status
t=$(git submodule status)
if test "$t" = "$(cat $curr_status 2>/dev/null)"; then
: # good, it's up to date
else
echo running bootstrap...
./bootstrap && echo "$t" > $curr_status
fi
# Automake requires that ChangeLog exist.
touch ChangeLog
autoreconf -if
cd $THEDIR
if test x$OBJ_DIR != x; then
mkdir -p "$OBJ_DIR"
cd "$OBJ_DIR"
fi
$srcdir/configure $EXTRA_ARGS "$@" && {
echo
echo "Now type 'make' to compile libvirt."
}

117
bootstrap
View File

@@ -1,117 +0,0 @@
#!/bin/sh
# Run this before autogen.sh, to pull in all of the gnulib-related bits.
usage() {
echo >&2 "\
Usage: $0 [OPTION]...
Bootstrap this package from the checked-out sources.
Options:
--gnulib-srcdir=DIRNAME Specify the local directory where gnulib
sources reside. Use this if you already
have gnulib sources on your machine, and
do not want to waste your bandwidth downloading
them again.
If the file bootstrap.conf exists in the current working directory, its
contents are read as shell variables to configure the bootstrap.
Running without arguments will suffice in most cases.
"
}
for option
do
case $option in
--help)
usage
exit;;
--gnulib-srcdir=*)
GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
*)
echo >&2 "$0: $option: unknown option"
exit 1;;
esac
done
# Get gnulib files.
case ${GNULIB_SRCDIR--} in
-)
echo "$0: getting gnulib files..."
git submodule init || exit $?
git submodule update || exit $?
GNULIB_SRCDIR=.gnulib
;;
*)
# Redirect the gnulib submodule to the directory on the command line
# if possible.
if test -d "$GNULIB_SRCDIR"/.git && \
git config --file .gitmodules submodule.gnulib.url >/dev/null; then
git submodule init
GNULIB_SRCDIR=`cd $GNULIB_SRCDIR && pwd`
git config --replace-all submodule.gnulib.url $GNULIB_SRCDIR
echo "$0: getting gnulib files..."
git submodule update || exit $?
GNULIB_SRCDIR=.gnulib
else
echo >&2 "$0: invalid gnulib srcdir: $GNULIB_SRCDIR"
exit 1
fi
;;
esac
gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
<$gnulib_tool || exit
modules='
areadlink
base64
c-ctype
close
connect
getaddrinfo
gethostname
getpass
gettext
gitlog-to-changelog
gnumakefile
inet_pton
ioctl
maintainer-makefile
mkstemp
mktempd
perror
physmem
poll
posix-shell
recv
random_r
send
setsockopt
socket
stpcpy
strchrnul
strndup
strerror
strsep
sys_stat
time_r
useless-if-before-free
vasprintf
verify
vc-list-files
'
# Tell gnulib to:
# require LGPLv2+
# put *.m4 files in new gnulib/m4/ dir
# put *.[ch] files in new gnulib/lib/ dir.
$gnulib_tool \
--lgpl=2 \
--with-tests \
--m4-base=gnulib/m4 \
--source-base=gnulib/lib \
--tests-base=gnulib/tests \
--import $modules

View File

@@ -1,3 +0,0 @@
*
/link-warning.h
/mktempd

267
cfg.mk
View File

@@ -1,267 +0,0 @@
# Customize Makefile.maint. -*- makefile -*-
# Copyright (C) 2003-2009 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program 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 General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Use alpha.gnu.org for alpha and beta releases.
# Use ftp.gnu.org for major releases.
gnu_ftp_host-alpha = alpha.gnu.org
gnu_ftp_host-beta = alpha.gnu.org
gnu_ftp_host-major = ftp.gnu.org
gnu_rel_host = $(gnu_ftp_host-$(RELEASE_TYPE))
url_dir_list = \
ftp://$(gnu_rel_host)/gnu/coreutils
# Tests not to run as part of "make distcheck".
local-checks-to-skip = \
changelog-check \
check-AUTHORS \
makefile-check \
makefile_path_separator_check \
patch-check \
sc_GPL_version \
sc_always_defined_macros \
sc_cast_of_alloca_return_value \
sc_dd_max_sym_length \
sc_error_exit_success \
sc_file_system \
sc_immutable_NEWS \
sc_makefile_path_separator_check \
sc_obsolete_symbols \
sc_prohibit_S_IS_definition \
sc_prohibit_atoi_atof \
sc_prohibit_jm_in_m4 \
sc_prohibit_quote_without_use \
sc_prohibit_quotearg_without_use \
sc_prohibit_stat_st_blocks \
sc_root_tests \
sc_space_tab \
sc_sun_os_names \
sc_system_h_headers \
sc_tight_scope \
sc_two_space_separator_in_usage \
sc_error_message_uppercase \
sc_program_name \
sc_require_test_exit_idiom \
sc_makefile_check \
sc_useless_cpp_parens
useless_free_options = \
--name=sexpr_free \
--name=VIR_FREE \
--name=xmlFree \
--name=xmlXPathFreeContext \
--name=xmlXPathFreeObject
# Avoid uses of write(2). Either switch to streams (fwrite), or use
# the safewrite wrapper.
sc_avoid_write:
@if $(VC_LIST_EXCEPT) | grep '\.c$$' > /dev/null; then \
grep '\<write *(' $$($(VC_LIST_EXCEPT) | grep '\.c$$') && \
{ echo "$(ME): the above files use write;" \
" consider using the safewrite wrapper instead" \
1>&2; exit 1; } || :; \
else :; \
fi
# Use STREQ rather than comparing strcmp == 0, or != 0.
# Similarly, use STREQLEN or STRPREFIX rather than strncmp.
sc_prohibit_strcmp_and_strncmp:
@re='strn?cmp *\(' \
msg='use STREQ() in place of the above uses of str[n]cmp' \
$(_prohibit_regexp)
# Use virAsprintf rather than a'sprintf since *strp is undefined on error.
sc_prohibit_asprintf:
@re='\<[a]sprintf\>' \
msg='use virAsprintf, not a'sprintf \
$(_prohibit_regexp)
sc_prohibit_strncpy:
@re='strncpy *\(' \
msg='use virStrncpy, not strncpy' \
$(_prohibit_regexp)
sc_prohibit_gethostname:
@re='gethostname *\(' \
msg='use virGetHostname, not gethostname' \
$(_prohibit_regexp)
sc_prohibit_VIR_ERR_NO_MEMORY:
@re='\<V''IR_ERR_NO_MEMORY\>' \
msg='use virReportOOMError, not V'IR_ERR_NO_MEMORY \
$(_prohibit_regexp)
include $(srcdir)/Makefile.nonreentrant
sc_prohibit_nonreentrant:
@fail=0 ; \
for i in $(NON_REENTRANT) ; \
do \
grep --before 2 --after 1 -nE "\<$$i\>[:space:]*\(" $$($(VC_LIST_EXCEPT)) && \
fail=1 && echo "$(ME): use $${i}_r, not $${i}" || : ; \
done ; \
exit $$fail
# Prohibit the inclusion of <ctype.h>.
sc_prohibit_ctype_h:
@grep -E '^# *include *<ctype\.h>' $$($(VC_LIST_EXCEPT)) && \
{ echo "$(ME): don't use ctype.h; instead, use c-ctype.h" \
1>&2; exit 1; } || :
# Ensure that no C source file uses TABs for indentation.
# Also match *.h.in files, to get libvirt.h.in.
# Exclude files in gnulib, since they're imported.
sc_TAB_in_indentation:
@grep -lE '^ * ' /dev/null \
$$($(VC_LIST_EXCEPT) \
| grep -E '\.[ch](\.in)?$$' \
| grep -v '^gnulib/') && \
{ echo '$(ME): found TAB(s) used for indentation in C sources;'\
'use spaces' 1>&2; exit 1; } || :
ctype_re = isalnum|isalpha|isascii|isblank|iscntrl|isdigit|isgraph|islower\
|isprint|ispunct|isspace|isupper|isxdigit|tolower|toupper
sc_avoid_ctype_macros:
@grep -E '\b($(ctype_re)) *\(' /dev/null \
$$($(VC_LIST_EXCEPT)) && \
{ echo "$(ME): don't use ctype macros (use c-ctype.h)" \
1>&2; exit 1; } || :
sc_prohibit_virBufferAdd_with_string_literal:
@re='\<virBufferAdd *\([^,]+, *"[^"]' \
msg='use virBufferAddLit, not virBufferAdd, with a string literal' \
$(_prohibit_regexp)
# Not only do they fail to deal well with ipv6, but the gethostby*
# functions are also not thread-safe.
sc_prohibit_gethostby:
@re='\<gethostby(addr|name2?) *\(' \
msg='use getaddrinfo, not gethostby*' \
$(_prohibit_regexp)
# Many of the function names below came from this filter:
# git grep -B2 '\<_('|grep -E '\.c- *[[:alpha:]_][[:alnum:]_]* ?\(.*[,;]$' \
# |sed 's/.*\.c- *//'|perl -pe 's/ ?\(.*//'|sort -u \
# |grep -vE '^(qsort|if|close|assert|fputc|free|N_|vir.*GetName|.*Unlock|virNodeListDevices|virHashRemoveEntry|freeaddrinfo|.*[fF]ree|xdrmem_create|xmlXPathFreeObject|virUUIDFormat|openvzSetProgramSentinal|polkit_action_unref)$'
msg_gen_function =
msg_gen_function += DEBUG0
msg_gen_function += DISABLE_fprintf
msg_gen_function += ERROR
msg_gen_function += ERROR0
msg_gen_function += REMOTE_DEBUG
msg_gen_function += ReportError
msg_gen_function += VIR_FREE
msg_gen_function += VIR_INFO
msg_gen_function += VIR_USE_CPU
msg_gen_function += errorf
msg_gen_function += lxcError
msg_gen_function += networkLog
msg_gen_function += networkReportError
msg_gen_function += oneError
msg_gen_function += openvzError
msg_gen_function += openvzLog
msg_gen_function += qemudDispatchClientFailure
msg_gen_function += qemudLog
msg_gen_function += qemudReportError
msg_gen_function += regerror
msg_gen_function += remoteDispatchFormatError
msg_gen_function += umlLog
msg_gen_function += umlReportError
msg_gen_function += virConfError
msg_gen_function += virDomainReportError
msg_gen_function += virSecurityReportError
msg_gen_function += virHashError
msg_gen_function += virLibConnError
msg_gen_function += virLibDomainError
msg_gen_function += virLog
msg_gen_function += virNetworkReportError
msg_gen_function += virNodeDeviceReportError
msg_gen_function += virProxyError
msg_gen_function += virRaiseError
msg_gen_function += virReportErrorHelper
msg_gen_function += virReportSystemError
msg_gen_function += virSexprError
msg_gen_function += virStorageLog
msg_gen_function += virStorageReportError
msg_gen_function += virXMLError
msg_gen_function += virXenInotifyError
msg_gen_function += virXenStoreError
msg_gen_function += virXendError
msg_gen_function += vshCloseLogFile
msg_gen_function += xenUnifiedError
msg_gen_function += xenXMError
# Uncomment the following and run "make syntax-check" to see diagnostics
# that are not yet marked for translation, but that need to be rewritten
# so that they are translatable.
# msg_gen_function += error
# msg_gen_function += fprintf
# msg_gen_function += testError
# msg_gen_function += virXenError
# msg_gen_function += vshPrint
# msg_gen_function += vshError
func_or := $(shell printf '$(msg_gen_function)'|tr -s '[[:space:]]' '|')
func_re := ($(func_or))
# Look for diagnostics that aren't marked for translation.
# This won't find any for which error's format string is on a separate line.
# The sed filters eliminate false-positives like these:
# _("...: "
# "%s", _("no storage vol w..."
sc_libvirt_unmarked_diagnostics:
@grep -nE \
'\<$(func_re) \([^"]*"[^"]*[a-z]{3}' $$($(VC_LIST_EXCEPT)) \
| grep -v '_''(' && \
{ echo '$(ME): found unmarked diagnostic(s)' 1>&2; \
exit 1; } || :
@{ grep -nE '\<$(func_re) *\(.*;$$' $$($(VC_LIST_EXCEPT)); \
grep -A1 -nE '\<$(func_re) *\(.*,$$' $$($(VC_LIST_EXCEPT)); } \
| sed 's/_("[^"][^"]*"//;s/[ ]"%s"//' \
| grep '[ ]"' && \
{ echo '$(ME): found unmarked diagnostic(s)' 1>&2; \
exit 1; } || :
# Disallow trailing blank lines.
sc_prohibit_trailing_blank_lines:
@$(VC_LIST_EXCEPT) | xargs perl -ln -0777 -e \
'/\n\n+$$/ and print $$ARGV' > $@-t
@found=0; test -s $@-t && { found=1; cat $@-t 1>&2; \
echo '$(ME): found trailing blank line(s)' 1>&2; }; \
rm -f $@-t; \
test $$found = 0
# We don't use this feature of maint.mk.
prev_version_file = /dev/null
ifeq (0,$(MAKELEVEL))
_curr_status = .git-module-status
# The sed filter accommodates those who check out on a commit from which
# no tag is reachable. In that case, git submodule status prints a "-"
# in column 1 and does not print a "git describe"-style string after the
# submodule name. Contrast these:
# -b653eda3ac4864de205419d9f41eec267cb89eeb .gnulib
# b653eda3ac4864de205419d9f41eec267cb89eeb .gnulib (v0.0-2286-gb653eda)
_submodule_hash = sed 's/.//;s/ .*//'
_update_required := $(shell \
actual=$$(git submodule status | $(_submodule_hash)); \
stamp="$$($(_submodule_hash) $(_curr_status) 2>/dev/null)"; \
test "$$stamp" = "$$actual"; echo $$?)
ifeq (1,$(_update_required))
$(error gnulib update required; run ./autogen.sh first)
endif
endif

File diff suppressed because it is too large Load Diff

12
daemon/.gitignore vendored
View File

@@ -1,12 +0,0 @@
*.gcda
*.gcno
*.la
*.lo
.deps
.libs
Makefile
Makefile.in
libvirt_qemud
libvirtd
libvirtd.init
libvirtd.logrotate

View File

@@ -1,257 +0,0 @@
## Process this file with automake to produce Makefile.in
DAEMON_SOURCES = \
event.c event.h \
libvirtd.c libvirtd.h \
remote.c remote.h \
dispatch.c dispatch.h \
stream.c stream.h \
remote_dispatch_prototypes.h \
remote_dispatch_table.h \
remote_dispatch_args.h \
remote_dispatch_ret.h \
../src/remote/remote_protocol.c
AVAHI_SOURCES = \
mdns.c mdns.h
DISTCLEANFILES =
EXTRA_DIST = \
remote_generate_stubs.pl \
libvirtd.conf \
libvirtd.init.in \
libvirtd.policy-0 \
libvirtd.policy-1 \
libvirtd.sasl \
libvirtd.sysconf \
libvirtd.aug \
libvirtd.logrotate.in \
test_libvirtd.aug \
$(AVAHI_SOURCES) \
$(DAEMON_SOURCES)
BUILT_SOURCES =
if WITH_LIBVIRTD
sbin_PROGRAMS = libvirtd
confdir = $(sysconfdir)/libvirt/
conf_DATA = libvirtd.conf
augeasdir = $(datadir)/augeas/lenses
augeas_DATA = libvirtd.aug
augeastestsdir = $(datadir)/augeas/lenses/tests
augeastests_DATA = test_libvirtd.aug
libvirtd_SOURCES = $(DAEMON_SOURCES)
#-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_POSIX_C_SOURCE=199506L
libvirtd_CFLAGS = \
-I$(top_srcdir)/gnulib/lib -I../gnulib/lib \
-I$(top_srcdir)/include -I$(top_builddir)/include \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/util \
-I$(top_srcdir)/src/conf \
-I$(top_srcdir)/src/remote \
$(LIBXML_CFLAGS) $(GNUTLS_CFLAGS) $(SASL_CFLAGS) \
$(POLKIT_CFLAGS) \
$(WARN_CFLAGS) -DLOCAL_STATE_DIR="\"$(localstatedir)\"" \
$(COVERAGE_CFLAGS) \
-DSYSCONF_DIR="\"$(sysconfdir)\"" \
-DQEMUD_PID_FILE="\"$(QEMUD_PID_FILE)\"" \
-DREMOTE_PID_FILE="\"$(REMOTE_PID_FILE)\"" \
-DGETTEXT_PACKAGE=\"$(PACKAGE)\"
libvirtd_LDFLAGS = \
$(WARN_CFLAGS) \
$(COVERAGE_LDFLAGS)
libvirtd_LDADD = \
$(LIBXML_LIBS) \
$(GNUTLS_LIBS) \
$(SASL_LIBS) \
$(POLKIT_LIBS)
libvirtd_LDADD += ../src/libvirt_util.la
if WITH_DRIVER_MODULES
libvirtd_LDADD += ../src/libvirt_driver.la
else
if WITH_QEMU
libvirtd_LDADD += ../src/libvirt_driver_qemu.la
endif
if WITH_LXC
libvirtd_LDADD += ../src/libvirt_driver_lxc.la
endif
if WITH_UML
libvirtd_LDADD += ../src/libvirt_driver_uml.la
endif
if WITH_ONE
libvirtd_LDADD += ../src/libvirt_driver_one.la
endif
if WITH_STORAGE_DIR
libvirtd_LDADD += ../src/libvirt_driver_storage.la
endif
if WITH_NETWORK
libvirtd_LDADD += ../src/libvirt_driver_network.la
endif
if WITH_NETCF
libvirtd_LDADD += ../src/libvirt_driver_interface.la
endif
if WITH_NODE_DEVICES
libvirtd_LDADD += ../src/libvirt_driver_nodedev.la
endif
if WITH_SECRETS
libvirtd_LDADD += ../src/libvirt_driver_secret.la
endif
endif
libvirtd_LDADD += ../src/libvirt.la
if HAVE_POLKIT
if HAVE_POLKIT0
policydir = $(datadir)/PolicyKit/policy
policyfile = libvirtd.policy-0
else
policydir = $(datadir)/polkit-1/actions
policyfile = libvirtd.policy-1
endif
endif
if HAVE_AVAHI
libvirtd_SOURCES += $(AVAHI_SOURCES)
libvirtd_CFLAGS += $(AVAHI_CFLAGS)
libvirtd_LDADD += $(AVAHI_LIBS)
endif
install-data-local: install-init install-data-sasl install-data-polkit \
install-logrotate
mkdir -p $(DESTDIR)$(localstatedir)/log/libvirt
mkdir -p $(DESTDIR)$(localstatedir)/run/libvirt
mkdir -p $(DESTDIR)$(localstatedir)/lib/libvirt
uninstall-local:: uninstall-init uninstall-data-sasl uninstall-data-polkit
rmdir $(DESTDIR)$(localstatedir)/log/libvirt || :
rmdir $(DESTDIR)$(localstatedir)/run/libvirt || :
rmdir $(DESTDIR)$(localstatedir)/lib/libvirt || :
if HAVE_POLKIT
install-data-polkit:: install-init
mkdir -p $(DESTDIR)$(policydir)
$(INSTALL_DATA) $(srcdir)/$(policyfile) $(DESTDIR)$(policydir)/org.libvirt.unix.policy
uninstall-data-polkit:: install-init
rm -f $(DESTDIR)$(policydir)/org.libvirt.unix.policy
else
install-data-polkit::
uninstall-data-polkit::
endif
remote.c: remote_dispatch_prototypes.h \
remote_dispatch_table.h \
remote_dispatch_args.h \
remote_dispatch_ret.h
REMOTE_PROTOCOL = $(top_srcdir)/src/remote/remote_protocol.x
remote_dispatch_prototypes.h: $(srcdir)/remote_generate_stubs.pl $(REMOTE_PROTOCOL)
perl -w $(srcdir)/remote_generate_stubs.pl -p $(REMOTE_PROTOCOL) > $@
remote_dispatch_table.h: $(srcdir)/remote_generate_stubs.pl $(REMOTE_PROTOCOL)
perl -w $(srcdir)/remote_generate_stubs.pl -t $(REMOTE_PROTOCOL) > $@
remote_dispatch_args.h: $(srcdir)/remote_generate_stubs.pl $(REMOTE_PROTOCOL)
perl -w $(srcdir)/remote_generate_stubs.pl -a $(REMOTE_PROTOCOL) > $@
remote_dispatch_ret.h: $(srcdir)/remote_generate_stubs.pl $(REMOTE_PROTOCOL)
perl -w $(srcdir)/remote_generate_stubs.pl -r $(REMOTE_PROTOCOL) > $@
BUILT_SOURCES += libvirtd.logrotate
libvirtd.logrotate: libvirtd.logrotate.in
sed \
-e s!\@localstatedir\@!@localstatedir@!g \
< $< > $@-t
mv $@-t $@
install-logrotate: libvirtd.logrotate
mkdir -p $(DESTDIR)$(localstatedir)/log/libvirt/qemu/
mkdir -p $(DESTDIR)$(localstatedir)/log/libvirt/lxc/
mkdir -p $(DESTDIR)$(localstatedir)/log/libvirt/uml/
mkdir -p $(DESTDIR)$(sysconfdir)/logrotate.d/
$(INSTALL_DATA) $< $(DESTDIR)$(sysconfdir)/logrotate.d/libvirtd
if LIBVIRT_INIT_SCRIPT_RED_HAT
install-init: libvirtd.init
mkdir -p $(DESTDIR)$(sysconfdir)/rc.d/init.d
$(INSTALL_SCRIPT) libvirtd.init \
$(DESTDIR)$(sysconfdir)/rc.d/init.d/libvirtd
mkdir -p $(DESTDIR)$(sysconfdir)/sysconfig
$(INSTALL_SCRIPT) $(srcdir)/libvirtd.sysconf \
$(DESTDIR)$(sysconfdir)/sysconfig/libvirtd
uninstall-init:
rm -f $(DESTDIR)$(sysconfdir)/rc.d/init.d/libvirtd \
$(DESTDIR)$(sysconfdir)/sysconfig/libvirtd
BUILT_SOURCES += libvirtd.init
libvirtd.init: libvirtd.init.in
sed \
-e s!\@localstatedir\@!@localstatedir@!g \
-e s!\@sbindir\@!@sbindir@!g \
-e s!\@sysconfdir\@!@sysconfdir@!g \
< $< > $@-t
chmod a+x $@-t
mv $@-t $@
check-local:
test -x '$(AUGPARSE)' \
&& '$(AUGPARSE)' -I $(srcdir) $(srcdir)/test_libvirtd.aug || :
else
install-init:
uninstall-init:
libvirtd.init:
endif # LIBVIRT_INIT_SCRIPT_RED_HAT
# This must be added last, since functions it provides/replaces
# are used by nearly every other library.
libvirtd_LDADD += ../gnulib/lib/libgnu.la $(LIBSOCKET)
else # WITH_LIBVIRTD
install-data-local: install-data-sasl
uninstall-local:: uninstall-data-sasl
endif # WITH_LIBVIRTD
# This is needed for clients too, so can't wrap in
# the WITH_LIBVIRTD conditional
if HAVE_SASL
install-data-sasl:
mkdir -p $(DESTDIR)$(sysconfdir)/sasl2/
$(INSTALL_DATA) $(srcdir)/libvirtd.sasl $(DESTDIR)$(sysconfdir)/sasl2/libvirt.conf
uninstall-data-sasl:
rm -f $(DESTDIR)$(sysconfdir)/sasl2/libvirt.conf
rmdir $(DESTDIR)$(sysconfdir)/sasl2/
else
install-data-sasl:
uninstall-data-sasl:
endif
CLEANFILES = $(BUILT_SOURCES)
CLEANFILES += *.cov *.gcov .libs/*.gcda .libs/*.gcno *.gcno *.gcda

View File

@@ -1,52 +0,0 @@
Threading in the libvirtd daemon
================================
To allow efficient processing of RPC requests, the libvirtd daemon
makes use of threads.
- The process leader. This is the initial thread of control
when the daemon starts running. It is responsible for
initializing all the state, and starting the event loop.
Once that's all done, this thread does nothing except
wait for the event loop to quit, thus indicating an orderly
shutdown is required.
- The event loop. This thread runs the event loop, sitting
in poll() on all monitored file handles, and calculating
and dispatching any timers that may be registered. When
this thread quits, the entire daemon will shutdown.
- The workers. These 'n' threads all sit around waiting to
process incoming RPC requests. Since RPC requests may take
a long time to complete, with long idle periods, there will
be quite a few workers running.
The use of threads obviously requires locking to ensure safety when
accessing/changing data structures.
- the top level lock is on 'struct qemud_server'. This must be
held before acquiring any other lock
- Each 'struct qemud_client' object has a lock. The server lock
must be held before acquiring it. Once the client lock is acquired
the server lock can (optionally) be dropped.
- The event loop has its own self-contained lock. You can ignore
this as a caller of virEvent APIs.
The server lock is used in conjunction with a condition variable
to pass jobs from the event loop thread to the workers. The main
event loop thread handles I/O from the client socket, and once a
complete RPC message has been read off the wire (and optionally
decrypted), it will be placed onto the 'dx' job queue for the
associated client object. The job condition will be signalled and
a worker will wakup and process it.
The worker thread must quickly drop its locks on the server and
client to allow the main event loop thread to continue running
with its other work. Critically important, is that now libvirt
API call will ever be made with the server or client locks held.
-- End

View File

@@ -1,668 +0,0 @@
/*
* dispatch.h: RPC message dispatching infrastructure
*
* Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Richard W.M. Jones <rjones@redhat.com>
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#include <config.h>
#include "dispatch.h"
#include "remote.h"
#include "memory.h"
/* Convert a libvirt virError object into wire format */
static void
remoteDispatchCopyError (remote_error *rerr,
virErrorPtr verr)
{
rerr->code = verr->code;
rerr->domain = verr->domain;
rerr->message = verr->message ? malloc(sizeof(char*)) : NULL;
if (rerr->message) *rerr->message = strdup(verr->message);
rerr->level = verr->level;
rerr->str1 = verr->str1 ? malloc(sizeof(char*)) : NULL;
if (rerr->str1) *rerr->str1 = strdup(verr->str1);
rerr->str2 = verr->str2 ? malloc(sizeof(char*)) : NULL;
if (rerr->str2) *rerr->str2 = strdup(verr->str2);
rerr->str3 = verr->str3 ? malloc(sizeof(char*)) : NULL;
if (rerr->str3) *rerr->str3 = strdup(verr->str3);
rerr->int1 = verr->int1;
rerr->int2 = verr->int2;
}
/* A set of helpers for sending back errors to client
in various ways .... */
static void
remoteDispatchStringError (remote_error *rerr,
int code, const char *msg)
{
virError verr;
memset(&verr, 0, sizeof verr);
/* Construct the dummy libvirt virError. */
verr.code = code;
verr.domain = VIR_FROM_REMOTE;
verr.message = (char *)msg;
verr.level = VIR_ERR_ERROR;
verr.str1 = (char *)msg;
remoteDispatchCopyError(rerr, &verr);
}
void remoteDispatchAuthError (remote_error *rerr)
{
remoteDispatchStringError (rerr, VIR_ERR_AUTH_FAILED, "authentication failed");
}
void remoteDispatchFormatError (remote_error *rerr,
const char *fmt, ...)
{
va_list args;
char msgbuf[1024];
char *msg = msgbuf;
va_start (args, fmt);
vsnprintf (msgbuf, sizeof msgbuf, fmt, args);
va_end (args);
remoteDispatchStringError (rerr, VIR_ERR_RPC, msg);
}
void remoteDispatchGenericError (remote_error *rerr)
{
remoteDispatchStringError(rerr,
VIR_ERR_INTERNAL_ERROR,
"library function returned error but did not set virterror");
}
void remoteDispatchOOMError (remote_error *rerr)
{
remoteDispatchStringError(rerr,
VIR_ERR_NO_MEMORY,
"out of memory");
}
void remoteDispatchConnError (remote_error *rerr,
virConnectPtr conn)
{
virErrorPtr verr;
if (conn)
verr = virConnGetLastError(conn);
else
verr = virGetLastError();
if (verr)
remoteDispatchCopyError(rerr, verr);
else
remoteDispatchGenericError(rerr);
}
static int
remoteSerializeError(struct qemud_client *client,
remote_error *rerr,
int program,
int version,
int procedure,
int type,
int serial)
{
XDR xdr;
unsigned int len;
struct qemud_client_message *msg = NULL;
DEBUG("prog=%d ver=%d proc=%d type=%d serial=%d, msg=%s",
program, version, procedure, type, serial,
rerr->message ? *rerr->message : "(none)");
if (VIR_ALLOC(msg) < 0)
goto fatal_error;
/* Return header. */
msg->hdr.prog = program;
msg->hdr.vers = version;
msg->hdr.proc = procedure;
msg->hdr.type = type;
msg->hdr.serial = serial;
msg->hdr.status = REMOTE_ERROR;
msg->bufferLength = sizeof(msg->buffer);
/* Serialise the return header. */
xdrmem_create (&xdr,
msg->buffer,
msg->bufferLength,
XDR_ENCODE);
len = 0; /* We'll come back and write this later. */
if (!xdr_u_int (&xdr, &len))
goto xdr_error;
if (!xdr_remote_message_header (&xdr, &msg->hdr))
goto xdr_error;
/* Error was not set, so synthesize a generic error message. */
if (rerr->code == 0)
remoteDispatchGenericError(rerr);
if (!xdr_remote_error (&xdr, rerr))
goto xdr_error;
/* Write the length word. */
len = xdr_getpos (&xdr);
if (xdr_setpos (&xdr, 0) == 0)
goto xdr_error;
if (!xdr_u_int (&xdr, &len))
goto xdr_error;
xdr_destroy (&xdr);
msg->bufferLength = len;
msg->bufferOffset = 0;
/* Put reply on end of tx queue to send out */
qemudClientMessageQueuePush(&client->tx, msg);
qemudUpdateClientEvent(client);
xdr_free((xdrproc_t)xdr_remote_error, (char *)rerr);
return 0;
xdr_error:
xdr_destroy(&xdr);
VIR_FREE(msg);
fatal_error:
xdr_free((xdrproc_t)xdr_remote_error, (char *)rerr);
return -1;
}
/*
* @client: the client to send the error to
* @rerr: the error object to send
* @req: the message this error is in reply to
*
* Send an error message to the client
*
* Returns 0 if the error was sent, -1 upon fatal error
*/
int
remoteSerializeReplyError(struct qemud_client *client,
remote_error *rerr,
remote_message_header *req) {
/*
* For data streams, errors are sent back as data streams
* For method calls, errors are sent back as method replies
*/
return remoteSerializeError(client,
rerr,
req->prog,
req->vers,
req->proc,
req->type == REMOTE_STREAM ? REMOTE_STREAM : REMOTE_REPLY,
req->serial);
}
int
remoteSerializeStreamError(struct qemud_client *client,
remote_error *rerr,
int proc,
int serial)
{
return remoteSerializeError(client,
rerr,
REMOTE_PROGRAM,
REMOTE_PROTOCOL_VERSION,
proc,
REMOTE_STREAM,
serial);
}
/*
* @msg: the complete incoming message, whose header to decode
*
* Decodes the header part of the client message, but does not
* validate the decoded fields in the header. It expects
* bufferLength to refer to length of the data packet. Upon
* return bufferOffset will refer to the amount of the packet
* consumed by decoding of the header.
*
* returns 0 if successfully decoded, -1 upon fatal error
*/
int
remoteDecodeClientMessageHeader (struct qemud_client_message *msg)
{
XDR xdr;
int ret = -1;
msg->bufferOffset = REMOTE_MESSAGE_HEADER_XDR_LEN;
/* Parse the header. */
xdrmem_create (&xdr,
msg->buffer + msg->bufferOffset,
msg->bufferLength - msg->bufferOffset,
XDR_DECODE);
if (!xdr_remote_message_header (&xdr, &msg->hdr))
goto cleanup;
msg->bufferOffset += xdr_getpos(&xdr);
ret = 0;
cleanup:
xdr_destroy(&xdr);
return ret;
}
/*
* @msg: the outgoing message, whose header to encode
*
* Encodes the header part of the client message, setting the
* message offset ready to encode the payload. Leaves space
* for the length field later. Upon return bufferLength will
* refer to the total available space for message, while
* bufferOffset will refer to current space used by header
*
* returns 0 if successfully encoded, -1 upon fatal error
*/
int
remoteEncodeClientMessageHeader (struct qemud_client_message *msg)
{
XDR xdr;
int ret = -1;
unsigned int len = 0;
msg->bufferLength = sizeof(msg->buffer);
msg->bufferOffset = 0;
/* Format the header. */
xdrmem_create (&xdr,
msg->buffer,
msg->bufferLength,
XDR_ENCODE);
/* The real value is filled in shortly */
if (!xdr_u_int (&xdr, &len)) {
goto cleanup;
}
if (!xdr_remote_message_header (&xdr, &msg->hdr))
goto cleanup;
len = xdr_getpos(&xdr);
xdr_setpos(&xdr, 0);
/* Fill in current length - may be re-written later
* if a payload is added
*/
if (!xdr_u_int (&xdr, &len)) {
goto cleanup;
}
msg->bufferOffset += len;
ret = 0;
cleanup:
xdr_destroy(&xdr);
return ret;
}
int
remoteDispatchClientCall (struct qemud_server *server,
struct qemud_client *client,
struct qemud_client_message *msg);
/*
* @server: the unlocked server object
* @client: the locked client object
* @msg: the complete incoming message packet, with header already decoded
*
* This function gets called from qemud when it pulls a incoming
* remote protocol messsage off the dispatch queue for processing.
*
* The @msg parameter must have had its header decoded already by
* calling remoteDecodeClientMessageHeader
*
* Returns 0 if the message was dispatched, -1 upon fatal error
*/
int
remoteDispatchClientRequest (struct qemud_server *server,
struct qemud_client *client,
struct qemud_client_message *msg)
{
int ret;
remote_error rerr;
DEBUG("prog=%d ver=%d type=%d satus=%d serial=%d proc=%d",
msg->hdr.prog, msg->hdr.vers, msg->hdr.type,
msg->hdr.status, msg->hdr.serial, msg->hdr.proc);
memset(&rerr, 0, sizeof rerr);
/* Check version, etc. */
if (msg->hdr.prog != REMOTE_PROGRAM) {
remoteDispatchFormatError (&rerr,
_("program mismatch (actual %x, expected %x)"),
msg->hdr.prog, REMOTE_PROGRAM);
goto error;
}
if (msg->hdr.vers != REMOTE_PROTOCOL_VERSION) {
remoteDispatchFormatError (&rerr,
_("version mismatch (actual %x, expected %x)"),
msg->hdr.vers, REMOTE_PROTOCOL_VERSION);
goto error;
}
switch (msg->hdr.type) {
case REMOTE_CALL:
return remoteDispatchClientCall(server, client, msg);
case REMOTE_STREAM:
/* Since stream data is non-acked, async, we may continue to received
* stream packets after we closed down a stream. Just drop & ignore
* these.
*/
VIR_INFO("Ignoring unexpected stream data serial=%d proc=%d status=%d",
msg->hdr.serial, msg->hdr.proc, msg->hdr.status);
qemudClientMessageRelease(client, msg);
break;
default:
remoteDispatchFormatError (&rerr, _("type (%d) != REMOTE_CALL"),
(int) msg->hdr.type);
goto error;
}
return 0;
error:
ret = remoteSerializeReplyError(client, &rerr, &msg->hdr);
if (ret >= 0)
VIR_FREE(msg);
return ret;
}
/*
* @server: the unlocked server object
* @client: the locked client object
* @msg: the complete incoming method call, with header already decoded
*
* This method is used to dispatch an message representing an
* incoming method call from a client. It decodes the payload
* to obtain method call arguments, invokves the method and
* then sends a reply packet with the return values
*
* Returns 0 if the reply was sent, or -1 upon fatal error
*/
int
remoteDispatchClientCall (struct qemud_server *server,
struct qemud_client *client,
struct qemud_client_message *msg)
{
XDR xdr;
remote_error rerr;
dispatch_args args;
dispatch_ret ret;
const dispatch_data *data = NULL;
int rv = -1;
unsigned int len;
virConnectPtr conn = NULL;
memset(&args, 0, sizeof args);
memset(&ret, 0, sizeof ret);
memset(&rerr, 0, sizeof rerr);
if (msg->hdr.status != REMOTE_OK) {
remoteDispatchFormatError (&rerr, _("status (%d) != REMOTE_OK"),
(int) msg->hdr.status);
goto rpc_error;
}
/* If client is marked as needing auth, don't allow any RPC ops,
* except for authentication ones
*/
if (client->auth) {
if (msg->hdr.proc != REMOTE_PROC_AUTH_LIST &&
msg->hdr.proc != REMOTE_PROC_AUTH_SASL_INIT &&
msg->hdr.proc != REMOTE_PROC_AUTH_SASL_START &&
msg->hdr.proc != REMOTE_PROC_AUTH_SASL_STEP &&
msg->hdr.proc != REMOTE_PROC_AUTH_POLKIT
) {
/* Explicitly *NOT* calling remoteDispatchAuthError() because
we want back-compatability with libvirt clients which don't
support the VIR_ERR_AUTH_FAILED error code */
remoteDispatchFormatError (&rerr, "%s", _("authentication required"));
goto rpc_error;
}
}
data = remoteGetDispatchData(msg->hdr.proc);
if (!data) {
remoteDispatchFormatError (&rerr, _("unknown procedure: %d"),
msg->hdr.proc);
goto rpc_error;
}
/* De-serialize payload with args from the wire message */
xdrmem_create (&xdr,
msg->buffer + msg->bufferOffset,
msg->bufferLength - msg->bufferOffset,
XDR_DECODE);
if (!((data->args_filter)(&xdr, &args))) {
xdr_destroy (&xdr);
remoteDispatchFormatError (&rerr, "%s", _("parse args failed"));
goto rpc_error;
}
xdr_destroy (&xdr);
/* Call function. */
conn = client->conn;
virMutexUnlock(&client->lock);
/*
* When the RPC handler is called:
*
* - Server object is unlocked
* - Client object is unlocked
*
* Without locking, it is safe to use:
*
* 'conn', 'rerr', 'args and 'ret'
*/
rv = (data->fn)(server, client, conn, &msg->hdr, &rerr, &args, &ret);
virMutexLock(&server->lock);
virMutexLock(&client->lock);
virMutexUnlock(&server->lock);
xdr_free (data->args_filter, (char*)&args);
if (rv < 0)
goto rpc_error;
/* Return header. We're re-using same message object, so
* only need to tweak type/status fields */
/*msg->hdr.prog = msg->hdr.prog;*/
/*msg->hdr.vers = msg->hdr.vers;*/
/*msg->hdr.proc = msg->hdr.proc;*/
msg->hdr.type = REMOTE_REPLY;
/*msg->hdr.serial = msg->hdr.serial;*/
msg->hdr.status = REMOTE_OK;
if (remoteEncodeClientMessageHeader(msg) < 0) {
xdr_free (data->ret_filter, (char*)&ret);
goto fatal_error;
}
/* Now for the payload */
xdrmem_create (&xdr,
msg->buffer,
msg->bufferLength,
XDR_ENCODE);
if (xdr_setpos(&xdr, msg->bufferOffset) == 0)
goto xdr_error;
/* If OK, serialise return structure, if error serialise error. */
/* Serialise reply data */
if (!((data->ret_filter) (&xdr, &ret)))
goto xdr_error;
/* Update the length word. */
msg->bufferOffset += xdr_getpos (&xdr);
len = msg->bufferOffset;
if (xdr_setpos (&xdr, 0) == 0)
goto xdr_error;
if (!xdr_u_int (&xdr, &len))
goto xdr_error;
xdr_destroy (&xdr);
xdr_free (data->ret_filter, (char*)&ret);
/* Reset ready for I/O */
msg->bufferLength = len;
msg->bufferOffset = 0;
/* Put reply on end of tx queue to send out */
qemudClientMessageQueuePush(&client->tx, msg);
qemudUpdateClientEvent(client);
return 0;
rpc_error:
/* Semi-bad stuff happened, we can still try to send back
* an RPC error message to client */
rv = remoteSerializeReplyError(client, &rerr, &msg->hdr);
if (rv >= 0)
VIR_FREE(msg);
return rv;
xdr_error:
/* Seriously bad stuff happened, so we'll kill off this client
and not send back any RPC error */
xdr_free (data->ret_filter, (char*)&ret);
xdr_destroy (&xdr);
fatal_error:
return -1;
}
int
remoteSendStreamData(struct qemud_client *client,
struct qemud_client_stream *stream,
const char *data,
unsigned int len)
{
struct qemud_client_message *msg;
XDR xdr;
DEBUG("client=%p stream=%p data=%p len=%d", client, stream, data, len);
if (VIR_ALLOC(msg) < 0) {
return -1;
}
/* Return header. We're re-using same message object, so
* only need to tweak type/status fields */
msg->hdr.prog = REMOTE_PROGRAM;
msg->hdr.vers = REMOTE_PROTOCOL_VERSION;
msg->hdr.proc = stream->procedure;
msg->hdr.type = REMOTE_STREAM;
msg->hdr.serial = stream->serial;
/*
* NB
* data != NULL + len > 0 => REMOTE_CONTINUE (Sending back data)
* data != NULL + len == 0 => REMOTE_CONTINUE (Sending read EOF)
* data == NULL => REMOTE_OK (Sending finish handshake confirmation)
*/
msg->hdr.status = data ? REMOTE_CONTINUE : REMOTE_OK;
if (remoteEncodeClientMessageHeader(msg) < 0)
goto fatal_error;
if (data && len) {
if ((msg->bufferLength - msg->bufferOffset) < len)
goto fatal_error;
/* Now for the payload */
xdrmem_create (&xdr,
msg->buffer,
msg->bufferLength,
XDR_ENCODE);
/* Skip over existing header already written */
if (xdr_setpos(&xdr, msg->bufferOffset) == 0)
goto xdr_error;
memcpy(msg->buffer + msg->bufferOffset, data, len);
msg->bufferOffset += len;
/* Update the length word. */
len = msg->bufferOffset;
if (xdr_setpos (&xdr, 0) == 0)
goto xdr_error;
if (!xdr_u_int (&xdr, &len))
goto xdr_error;
xdr_destroy (&xdr);
DEBUG("Total %d", msg->bufferOffset);
}
if (data)
msg->streamTX = 1;
/* Reset ready for I/O */
msg->bufferLength = msg->bufferOffset;
msg->bufferOffset = 0;
/* Put reply on end of tx queue to send out */
qemudClientMessageQueuePush(&client->tx, msg);
qemudUpdateClientEvent(client);
return 0;
xdr_error:
xdr_destroy (&xdr);
fatal_error:
VIR_FREE(msg);
return -1;
}

View File

@@ -1,80 +0,0 @@
/*
* dispatch.h: RPC message dispatching infrastructure
*
* Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Richard W.M. Jones <rjones@redhat.com>
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#ifndef __LIBVIRTD_DISPATCH_H__
#define __LIBVIRTD_DISPATCH_H__
#include "libvirtd.h"
int
remoteDecodeClientMessageHeader (struct qemud_client_message *req);
int
remoteEncodeClientMessageHeader (struct qemud_client_message *req);
int
remoteDispatchClientRequest (struct qemud_server *server,
struct qemud_client *client,
struct qemud_client_message *req);
void remoteDispatchFormatError (remote_error *rerr,
const char *fmt, ...)
ATTRIBUTE_FMT_PRINTF(2, 3);
void remoteDispatchAuthError (remote_error *rerr);
void remoteDispatchGenericError (remote_error *rerr);
void remoteDispatchOOMError (remote_error *rerr);
void remoteDispatchConnError (remote_error *rerr,
virConnectPtr conn);
int
remoteSerializeReplyError(struct qemud_client *client,
remote_error *rerr,
remote_message_header *req);
int
remoteSerializeStreamError(struct qemud_client *client,
remote_error *rerr,
int proc,
int serial);
/* Having this here is dubious. It should be in remote.h
* but qemud.c shouldn't depend on that header directly.
* Refactor this later to deal with this properly.
*/
int remoteRelayDomainEvent (virConnectPtr conn ATTRIBUTE_UNUSED,
virDomainPtr dom,
int event,
int detail,
void *opaque);
int
remoteSendStreamData(struct qemud_client *client,
struct qemud_client_stream *stream,
const char *data,
unsigned int len);
#endif /* __LIBVIRTD_DISPATCH_H__ */

View File

@@ -1,712 +0,0 @@
/*
* event.c: event loop for monitoring file handles
*
* Copyright (C) 2007 Daniel P. Berrange
* Copyright (C) 2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>
#include "threads.h"
#include "logging.h"
#include "event.h"
#include "memory.h"
#include "util.h"
#define EVENT_DEBUG(fmt, ...) DEBUG(fmt, __VA_ARGS__)
static int virEventInterruptLocked(void);
/* State for a single file handle being monitored */
struct virEventHandle {
int watch;
int fd;
int events;
virEventHandleCallback cb;
virFreeCallback ff;
void *opaque;
int deleted;
};
/* State for a single timer being generated */
struct virEventTimeout {
int timer;
int frequency;
unsigned long long expiresAt;
virEventTimeoutCallback cb;
virFreeCallback ff;
void *opaque;
int deleted;
};
/* Allocate extra slots for virEventHandle/virEventTimeout
records in this multiple */
#define EVENT_ALLOC_EXTENT 10
/* State for the main event loop */
struct virEventLoop {
pthread_mutex_t lock;
int running;
pthread_t leader;
int wakeupfd[2];
int handlesCount;
int handlesAlloc;
struct virEventHandle *handles;
int timeoutsCount;
int timeoutsAlloc;
struct virEventTimeout *timeouts;
};
/* Only have one event loop */
static struct virEventLoop eventLoop;
/* Unique ID for the next FD watch to be registered */
static int nextWatch = 1;
/* Unique ID for the next timer to be registered */
static int nextTimer = 1;
static void virEventLock(void)
{
pthread_mutex_lock(&eventLoop.lock);
}
static void virEventUnlock(void)
{
pthread_mutex_unlock(&eventLoop.lock);
}
/*
* Register a callback for monitoring file handle events.
* NB, it *must* be safe to call this from within a callback
* For this reason we only ever append to existing list.
*/
int virEventAddHandleImpl(int fd, int events,
virEventHandleCallback cb,
void *opaque,
virFreeCallback ff) {
int watch;
EVENT_DEBUG("Add handle fd=%d events=%d cb=%p opaque=%p", fd, events, cb, opaque);
virEventLock();
if (eventLoop.handlesCount == eventLoop.handlesAlloc) {
EVENT_DEBUG("Used %d handle slots, adding %d more",
eventLoop.handlesAlloc, EVENT_ALLOC_EXTENT);
if (VIR_REALLOC_N(eventLoop.handles,
(eventLoop.handlesAlloc + EVENT_ALLOC_EXTENT)) < 0) {
virEventUnlock();
return -1;
}
eventLoop.handlesAlloc += EVENT_ALLOC_EXTENT;
}
watch = nextWatch++;
eventLoop.handles[eventLoop.handlesCount].watch = watch;
eventLoop.handles[eventLoop.handlesCount].fd = fd;
eventLoop.handles[eventLoop.handlesCount].events =
virEventHandleTypeToPollEvent(events);
eventLoop.handles[eventLoop.handlesCount].cb = cb;
eventLoop.handles[eventLoop.handlesCount].ff = ff;
eventLoop.handles[eventLoop.handlesCount].opaque = opaque;
eventLoop.handles[eventLoop.handlesCount].deleted = 0;
eventLoop.handlesCount++;
virEventInterruptLocked();
virEventUnlock();
return watch;
}
void virEventUpdateHandleImpl(int watch, int events) {
int i;
EVENT_DEBUG("Update handle w=%d e=%d", watch, events);
if (watch <= 0) {
VIR_WARN("Ignoring invalid update watch %d", watch);
return;
}
virEventLock();
for (i = 0 ; i < eventLoop.handlesCount ; i++) {
if (eventLoop.handles[i].watch == watch) {
eventLoop.handles[i].events =
virEventHandleTypeToPollEvent(events);
virEventInterruptLocked();
break;
}
}
virEventUnlock();
}
/*
* Unregister a callback from a file handle
* NB, it *must* be safe to call this from within a callback
* For this reason we only ever set a flag in the existing list.
* Actual deletion will be done out-of-band
*/
int virEventRemoveHandleImpl(int watch) {
int i;
EVENT_DEBUG("Remove handle w=%d", watch);
if (watch <= 0) {
VIR_WARN("Ignoring invalid remove watch %d", watch);
return -1;
}
virEventLock();
for (i = 0 ; i < eventLoop.handlesCount ; i++) {
if (eventLoop.handles[i].deleted)
continue;
if (eventLoop.handles[i].watch == watch) {
EVENT_DEBUG("mark delete %d %d", i, eventLoop.handles[i].fd);
eventLoop.handles[i].deleted = 1;
virEventInterruptLocked();
virEventUnlock();
return 0;
}
}
virEventUnlock();
return -1;
}
/*
* Register a callback for a timer event
* NB, it *must* be safe to call this from within a callback
* For this reason we only ever append to existing list.
*/
int virEventAddTimeoutImpl(int frequency,
virEventTimeoutCallback cb,
void *opaque,
virFreeCallback ff) {
struct timeval now;
int ret;
EVENT_DEBUG("Adding timer %d with %d ms freq", nextTimer, frequency);
if (gettimeofday(&now, NULL) < 0) {
return -1;
}
virEventLock();
if (eventLoop.timeoutsCount == eventLoop.timeoutsAlloc) {
EVENT_DEBUG("Used %d timeout slots, adding %d more",
eventLoop.timeoutsAlloc, EVENT_ALLOC_EXTENT);
if (VIR_REALLOC_N(eventLoop.timeouts,
(eventLoop.timeoutsAlloc + EVENT_ALLOC_EXTENT)) < 0) {
virEventUnlock();
return -1;
}
eventLoop.timeoutsAlloc += EVENT_ALLOC_EXTENT;
}
eventLoop.timeouts[eventLoop.timeoutsCount].timer = nextTimer++;
eventLoop.timeouts[eventLoop.timeoutsCount].frequency = frequency;
eventLoop.timeouts[eventLoop.timeoutsCount].cb = cb;
eventLoop.timeouts[eventLoop.timeoutsCount].ff = ff;
eventLoop.timeouts[eventLoop.timeoutsCount].opaque = opaque;
eventLoop.timeouts[eventLoop.timeoutsCount].deleted = 0;
eventLoop.timeouts[eventLoop.timeoutsCount].expiresAt =
frequency >= 0 ? frequency +
(((unsigned long long)now.tv_sec)*1000) +
(((unsigned long long)now.tv_usec)/1000) : 0;
eventLoop.timeoutsCount++;
ret = nextTimer-1;
virEventInterruptLocked();
virEventUnlock();
return ret;
}
void virEventUpdateTimeoutImpl(int timer, int frequency) {
struct timeval tv;
int i;
EVENT_DEBUG("Updating timer %d timeout with %d ms freq", timer, frequency);
if (timer <= 0) {
VIR_WARN("Ignoring invalid update timer %d", timer);
return;
}
if (gettimeofday(&tv, NULL) < 0) {
return;
}
virEventLock();
for (i = 0 ; i < eventLoop.timeoutsCount ; i++) {
if (eventLoop.timeouts[i].timer == timer) {
eventLoop.timeouts[i].frequency = frequency;
eventLoop.timeouts[i].expiresAt =
frequency >= 0 ? frequency +
(((unsigned long long)tv.tv_sec)*1000) +
(((unsigned long long)tv.tv_usec)/1000) : 0;
virEventInterruptLocked();
break;
}
}
virEventUnlock();
}
/*
* Unregister a callback for a timer
* NB, it *must* be safe to call this from within a callback
* For this reason we only ever set a flag in the existing list.
* Actual deletion will be done out-of-band
*/
int virEventRemoveTimeoutImpl(int timer) {
int i;
EVENT_DEBUG("Remove timer %d", timer);
if (timer <= 0) {
VIR_WARN("Ignoring invalid remove timer %d", timer);
return -1;
}
virEventLock();
for (i = 0 ; i < eventLoop.timeoutsCount ; i++) {
if (eventLoop.timeouts[i].deleted)
continue;
if (eventLoop.timeouts[i].timer == timer) {
eventLoop.timeouts[i].deleted = 1;
virEventInterruptLocked();
virEventUnlock();
return 0;
}
}
virEventUnlock();
return -1;
}
/* Iterates over all registered timeouts and determine which
* will be the first to expire.
* @timeout: filled with expiry time of soonest timer, or -1 if
* no timeout is pending
* returns: 0 on success, -1 on error
*/
static int virEventCalculateTimeout(int *timeout) {
unsigned long long then = 0;
int i;
EVENT_DEBUG("Calculate expiry of %d timers", eventLoop.timeoutsCount);
/* Figure out if we need a timeout */
for (i = 0 ; i < eventLoop.timeoutsCount ; i++) {
if (eventLoop.timeouts[i].frequency < 0)
continue;
EVENT_DEBUG("Got a timeout scheduled for %llu", eventLoop.timeouts[i].expiresAt);
if (then == 0 ||
eventLoop.timeouts[i].expiresAt < then)
then = eventLoop.timeouts[i].expiresAt;
}
/* Calculate how long we should wait for a timeout if needed */
if (then > 0) {
struct timeval tv;
if (gettimeofday(&tv, NULL) < 0) {
return -1;
}
*timeout = then -
((((unsigned long long)tv.tv_sec)*1000) +
(((unsigned long long)tv.tv_usec)/1000));
if (*timeout < 0)
*timeout = 0;
} else {
*timeout = -1;
}
EVENT_DEBUG("Timeout at %llu due in %d ms", then, *timeout);
return 0;
}
/*
* Allocate a pollfd array containing data for all registered
* file handles. The caller must free the returned data struct
* returns: the pollfd array, or NULL on error
*/
static struct pollfd *virEventMakePollFDs(int *nfds) {
struct pollfd *fds;
int i;
*nfds = 0;
for (i = 0 ; i < eventLoop.handlesCount ; i++) {
if (eventLoop.handles[i].events)
(*nfds)++;
}
/* Setup the poll file handle data structs */
if (VIR_ALLOC_N(fds, *nfds) < 0)
return NULL;
*nfds = 0;
for (i = 0 ; i < eventLoop.handlesCount ; i++) {
EVENT_DEBUG("Prepare n=%d w=%d, f=%d e=%d", i,
eventLoop.handles[i].watch,
eventLoop.handles[i].fd,
eventLoop.handles[i].events);
if (!eventLoop.handles[i].events)
continue;
fds[*nfds].fd = eventLoop.handles[i].fd;
fds[*nfds].events = eventLoop.handles[i].events;
fds[*nfds].revents = 0;
(*nfds)++;
//EVENT_DEBUG("Wait for %d %d", eventLoop.handles[i].fd, eventLoop.handles[i].events);
}
return fds;
}
/*
* Iterate over all timers and determine if any have expired.
* Invoke the user supplied callback for each timer whose
* expiry time is met, and schedule the next timeout. Does
* not try to 'catch up' on time if the actual expiry time
* was later than the requested time.
*
* This method must cope with new timers being registered
* by a callback, and must skip any timers marked as deleted.
*
* Returns 0 upon success, -1 if an error occurred
*/
static int virEventDispatchTimeouts(void) {
struct timeval tv;
unsigned long long now;
int i;
/* Save this now - it may be changed during dispatch */
int ntimeouts = eventLoop.timeoutsCount;
DEBUG("Dispatch %d", ntimeouts);
if (gettimeofday(&tv, NULL) < 0) {
return -1;
}
now = (((unsigned long long)tv.tv_sec)*1000) +
(((unsigned long long)tv.tv_usec)/1000);
for (i = 0 ; i < ntimeouts ; i++) {
if (eventLoop.timeouts[i].deleted || eventLoop.timeouts[i].frequency < 0)
continue;
/* Add 20ms fuzz so we don't pointlessly spin doing
* <10ms sleeps, particularly on kernels with low HZ
* it is fine that a timer expires 20ms earlier than
* requested
*/
if (eventLoop.timeouts[i].expiresAt <= (now+20)) {
virEventTimeoutCallback cb = eventLoop.timeouts[i].cb;
int timer = eventLoop.timeouts[i].timer;
void *opaque = eventLoop.timeouts[i].opaque;
eventLoop.timeouts[i].expiresAt =
now + eventLoop.timeouts[i].frequency;
virEventUnlock();
(cb)(timer, opaque);
virEventLock();
}
}
return 0;
}
/* Iterate over all file handles and dispatch any which
* have pending events listed in the poll() data. Invoke
* the user supplied callback for each handle which has
* pending events
*
* This method must cope with new handles being registered
* by a callback, and must skip any handles marked as deleted.
*
* Returns 0 upon success, -1 if an error occurred
*/
static int virEventDispatchHandles(int nfds, struct pollfd *fds) {
int i, n;
DEBUG("Dispatch %d", nfds);
/* NB, use nfds not eventLoop.handlesCount, because new
* fds might be added on end of list, and they're not
* in the fds array we've got */
for (i = 0, n = 0 ; n < nfds && i < eventLoop.handlesCount ; n++) {
while ((eventLoop.handles[i].fd != fds[n].fd ||
eventLoop.handles[i].events == 0) &&
i < eventLoop.handlesCount) {
i++;
}
if (i == eventLoop.handlesCount)
break;
DEBUG("i=%d w=%d", i, eventLoop.handles[i].watch);
if (eventLoop.handles[i].deleted) {
EVENT_DEBUG("Skip deleted n=%d w=%d f=%d", i,
eventLoop.handles[i].watch, eventLoop.handles[i].fd);
continue;
}
if (fds[n].revents) {
virEventHandleCallback cb = eventLoop.handles[i].cb;
void *opaque = eventLoop.handles[i].opaque;
int hEvents = virPollEventToEventHandleType(fds[n].revents);
EVENT_DEBUG("Dispatch n=%d f=%d w=%d e=%d %p", i,
fds[n].fd, eventLoop.handles[i].watch,
fds[n].revents, eventLoop.handles[i].opaque);
virEventUnlock();
(cb)(eventLoop.handles[i].watch,
fds[n].fd, hEvents, opaque);
virEventLock();
}
}
return 0;
}
/* Used post dispatch to actually remove any timers that
* were previously marked as deleted. This asynchronous
* cleanup is needed to make dispatch re-entrant safe.
*/
static int virEventCleanupTimeouts(void) {
int i;
DEBUG("Cleanup %d", eventLoop.timeoutsCount);
/* Remove deleted entries, shuffling down remaining
* entries as needed to form contiguous series
*/
for (i = 0 ; i < eventLoop.timeoutsCount ; ) {
if (!eventLoop.timeouts[i].deleted) {
i++;
continue;
}
EVENT_DEBUG("Purging timeout %d with id %d", i, eventLoop.timeouts[i].timer);
if (eventLoop.timeouts[i].ff)
(eventLoop.timeouts[i].ff)(eventLoop.timeouts[i].opaque);
if ((i+1) < eventLoop.timeoutsCount) {
memmove(eventLoop.timeouts+i,
eventLoop.timeouts+i+1,
sizeof(struct virEventTimeout)*(eventLoop.timeoutsCount-(i+1)));
}
eventLoop.timeoutsCount--;
}
/* Release some memory if we've got a big chunk free */
if ((eventLoop.timeoutsAlloc - EVENT_ALLOC_EXTENT) > eventLoop.timeoutsCount) {
EVENT_DEBUG("Releasing %d out of %d timeout slots used, releasing %d",
eventLoop.timeoutsCount, eventLoop.timeoutsAlloc, EVENT_ALLOC_EXTENT);
if (VIR_REALLOC_N(eventLoop.timeouts,
(eventLoop.timeoutsAlloc - EVENT_ALLOC_EXTENT)) < 0)
return -1;
eventLoop.timeoutsAlloc -= EVENT_ALLOC_EXTENT;
}
return 0;
}
/* Used post dispatch to actually remove any handles that
* were previously marked as deleted. This asynchronous
* cleanup is needed to make dispatch re-entrant safe.
*/
static int virEventCleanupHandles(void) {
int i;
DEBUG("Cleanupo %d", eventLoop.handlesCount);
/* Remove deleted entries, shuffling down remaining
* entries as needed to form contiguous series
*/
for (i = 0 ; i < eventLoop.handlesCount ; ) {
if (!eventLoop.handles[i].deleted) {
i++;
continue;
}
if (eventLoop.handles[i].ff)
(eventLoop.handles[i].ff)(eventLoop.handles[i].opaque);
if ((i+1) < eventLoop.handlesCount) {
memmove(eventLoop.handles+i,
eventLoop.handles+i+1,
sizeof(struct virEventHandle)*(eventLoop.handlesCount-(i+1)));
}
eventLoop.handlesCount--;
}
/* Release some memory if we've got a big chunk free */
if ((eventLoop.handlesAlloc - EVENT_ALLOC_EXTENT) > eventLoop.handlesCount) {
EVENT_DEBUG("Releasing %d out of %d handles slots used, releasing %d",
eventLoop.handlesCount, eventLoop.handlesAlloc, EVENT_ALLOC_EXTENT);
if (VIR_REALLOC_N(eventLoop.handles,
(eventLoop.handlesAlloc - EVENT_ALLOC_EXTENT)) < 0)
return -1;
eventLoop.handlesAlloc -= EVENT_ALLOC_EXTENT;
}
return 0;
}
/*
* Run a single iteration of the event loop, blocking until
* at least one file handle has an event, or a timer expires
*/
int virEventRunOnce(void) {
struct pollfd *fds = NULL;
int ret, timeout, nfds;
virEventLock();
eventLoop.running = 1;
eventLoop.leader = pthread_self();
if (virEventCleanupTimeouts() < 0 ||
virEventCleanupHandles() < 0)
goto error;
if (!(fds = virEventMakePollFDs(&nfds)) ||
virEventCalculateTimeout(&timeout) < 0)
goto error;
virEventUnlock();
retry:
EVENT_DEBUG("Poll on %d handles %p timeout %d", nfds, fds, timeout);
ret = poll(fds, nfds, timeout);
EVENT_DEBUG("Poll got %d event", ret);
if (ret < 0) {
if (errno == EINTR) {
goto retry;
}
goto error_unlocked;
}
virEventLock();
if (virEventDispatchTimeouts() < 0)
goto error;
if (ret > 0 &&
virEventDispatchHandles(nfds, fds) < 0)
goto error;
if (virEventCleanupTimeouts() < 0 ||
virEventCleanupHandles() < 0)
goto error;
eventLoop.running = 0;
virEventUnlock();
VIR_FREE(fds);
return 0;
error:
virEventUnlock();
error_unlocked:
VIR_FREE(fds);
return -1;
}
static void virEventHandleWakeup(int watch ATTRIBUTE_UNUSED,
int fd,
int events ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED)
{
char c;
virEventLock();
saferead(fd, &c, sizeof(c));
virEventUnlock();
}
int virEventInit(void)
{
if (pthread_mutex_init(&eventLoop.lock, NULL) != 0)
return -1;
if (pipe(eventLoop.wakeupfd) < 0 ||
virSetNonBlock(eventLoop.wakeupfd[0]) < 0 ||
virSetNonBlock(eventLoop.wakeupfd[1]) < 0 ||
virSetCloseExec(eventLoop.wakeupfd[0]) < 0 ||
virSetCloseExec(eventLoop.wakeupfd[1]) < 0)
return -1;
if (virEventAddHandleImpl(eventLoop.wakeupfd[0],
VIR_EVENT_HANDLE_READABLE,
virEventHandleWakeup, NULL, NULL) < 0)
return -1;
return 0;
}
static int virEventInterruptLocked(void)
{
char c = '\0';
if (!eventLoop.running ||
pthread_self() == eventLoop.leader) {
VIR_DEBUG("Skip interrupt, %d %d", eventLoop.running, (int)eventLoop.leader);
return 0;
}
VIR_DEBUG0("Interrupting");
if (safewrite(eventLoop.wakeupfd[1], &c, sizeof(c)) != sizeof(c))
return -1;
return 0;
}
int virEventInterrupt(void)
{
int ret;
virEventLock();
ret = virEventInterruptLocked();
virEventUnlock();
return ret;
}
int
virEventHandleTypeToPollEvent(int events)
{
int ret = 0;
if(events & VIR_EVENT_HANDLE_READABLE)
ret |= POLLIN;
if(events & VIR_EVENT_HANDLE_WRITABLE)
ret |= POLLOUT;
if(events & VIR_EVENT_HANDLE_ERROR)
ret |= POLLERR;
if(events & VIR_EVENT_HANDLE_HANGUP)
ret |= POLLHUP;
return ret;
}
int
virPollEventToEventHandleType(int events)
{
int ret = 0;
if(events & POLLIN)
ret |= VIR_EVENT_HANDLE_READABLE;
if(events & POLLOUT)
ret |= VIR_EVENT_HANDLE_WRITABLE;
if(events & POLLERR)
ret |= VIR_EVENT_HANDLE_ERROR;
if(events & POLLNVAL) /* Treat NVAL as error, since libvirt doesn't distinguish */
ret |= VIR_EVENT_HANDLE_ERROR;
if(events & POLLHUP)
ret |= VIR_EVENT_HANDLE_HANGUP;
return ret;
}

View File

@@ -1,134 +0,0 @@
/*
* event.h: event loop for monitoring file handles
*
* Copyright (C) 2007 Daniel P. Berrange
* Copyright (C) 2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#ifndef __VIRTD_EVENT_H__
#define __VIRTD_EVENT_H__
#include "internal.h"
/**
* virEventAddHandleImpl: register a callback for monitoring file handle events
*
* @fd: file handle to monitor for events
* @events: bitset of events to watch from POLLnnn constants
* @cb: callback to invoke when an event occurs
* @opaque: user data to pass to callback
*
* returns -1 if the file handle cannot be registered, 0 upon success
*/
int virEventAddHandleImpl(int fd, int events,
virEventHandleCallback cb,
void *opaque,
virFreeCallback ff);
/**
* virEventUpdateHandleImpl: change event set for a monitored file handle
*
* @watch: watch whose handle to update
* @events: bitset of events to watch from POLLnnn constants
*
* Will not fail if fd exists
*/
void virEventUpdateHandleImpl(int watch, int events);
/**
* virEventRemoveHandleImpl: unregister a callback from a file handle
*
* @watch: watch whose handle to remove
*
* returns -1 if the file handle was not registered, 0 upon success
*/
int virEventRemoveHandleImpl(int watch);
/**
* virEventAddTimeoutImpl: register a callback for a timer event
*
* @frequency: time between events in milliseconds
* @cb: callback to invoke when an event occurs
* @opaque: user data to pass to callback
*
* Setting frequency to -1 will disable the timer. Setting the frequency
* to zero will cause it to fire on every event loop iteration.
*
* returns -1 if the file handle cannot be registered, a positive
* integer timer id upon success
*/
int virEventAddTimeoutImpl(int frequency,
virEventTimeoutCallback cb,
void *opaque,
virFreeCallback ff);
/**
* virEventUpdateTimeoutImpl: change frequency for a timer
*
* @timer: timer id to change
* @frequency: time between events in milliseconds
*
* Setting frequency to -1 will disable the timer. Setting the frequency
* to zero will cause it to fire on every event loop iteration.
*
* Will not fail if timer exists
*/
void virEventUpdateTimeoutImpl(int timer, int frequency);
/**
* virEventRemoveTimeoutImpl: unregister a callback for a timer
*
* @timer: the timer id to remove
*
* returns -1 if the timer was not registered, 0 upon success
*/
int virEventRemoveTimeoutImpl(int timer);
/**
* virEventInit: Initialize the event loop
*
* returns -1 if initialization failed
*/
int virEventInit(void);
/**
* virEventRunOnce: run a single iteration of the event loop.
*
* Blocks the caller until at least one file handle has an
* event or the first timer expires.
*
* returns -1 if the event monitoring failed
*/
int virEventRunOnce(void);
int
virEventHandleTypeToPollEvent(int events);
int
virPollEventToEventHandleType(int events);
/**
* virEventInterrupt: wakeup any thread waiting in poll()
*
* return -1 if wakup failed
*/
int virEventInterrupt(void);
#endif /* __VIRTD_EVENT_H__ */

View File

@@ -1,82 +0,0 @@
(* /etc/libvirt/libvirtd.conf *)
module Libvirtd =
autoload xfm
let eol = del /[ \t]*\n/ "\n"
let value_sep = del /[ \t]*=[ \t]*/ " = "
let indent = del /[ \t]*/ ""
let array_sep = del /,[ \t\n]*/ ", "
let array_start = del /\[[ \t\n]*/ "[ "
let array_end = del /\]/ "]"
let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\""
let bool_val = store /0|1/
let int_val = store /[0-9]+/
let str_array_element = [ seq "el" . str_val ] . del /[ \t\n]*/ ""
let str_array_val = counter "el" . array_start . ( str_array_element . ( array_sep . str_array_element ) * ) ? . array_end
let str_entry (kw:string) = [ key kw . value_sep . str_val ]
let bool_entry (kw:string) = [ key kw . value_sep . bool_val ]
let int_entry (kw:string) = [ key kw . value_sep . int_val ]
let str_array_entry (kw:string) = [ key kw . value_sep . str_array_val ]
(* Config entry grouped by function - same order as example config *)
let network_entry = bool_entry "listen_tls"
| bool_entry "listen_tcp"
| str_entry "tls_port"
| str_entry "tcp_port"
| str_entry "listen_addr"
| bool_entry "mdns_adv"
| str_entry "mdns_name"
let sock_acl_entry = str_entry "unix_sock_group"
| str_entry "unix_sock_ro_perms"
| str_entry "unix_sock_rw_perms"
| str_entry "unix_sock_dir"
let authentication_entry = str_entry "auth_unix_ro"
| str_entry "auth_unix_rw"
| str_entry "auth_tcp"
| str_entry "auth_tls"
let certificate_entry = str_entry "key_file"
| str_entry "cert_file"
| str_entry "ca_file"
| str_entry "crl_file"
let authorization_entry = bool_entry "tls_no_verify_certificate"
| str_array_entry "tls_allowed_dn_list"
| str_array_entry "sasl_allowed_username_list"
let processing_entry = int_entry "min_workers"
| int_entry "max_workers"
| int_entry "max_clients"
| int_entry "max_requests"
| int_entry "max_client_requests"
let logging_entry = int_entry "log_level"
| str_entry "log_filters"
| str_entry "log_outputs"
(* Each enty in the config is one of the following three ... *)
let entry = network_entry
| sock_acl_entry
| authentication_entry
| certificate_entry
| authorization_entry
| processing_entry
| logging_entry
let comment = [ label "#comment" . del /#[ \t]*/ "# " . store /([^ \t\n][^\n]*)?/ . del /\n/ "\n" ]
let empty = [ label "#empty" . eol ]
let record = indent . entry . eol
let lns = ( record | comment | empty ) *
let filter = incl "/etc/libvirt/libvirtd.conf"
. Util.stdexcl
let xfm = transform lns filter

File diff suppressed because it is too large Load Diff

View File

@@ -1,314 +0,0 @@
# Master libvirt daemon configuration file
#
# For further information consult http://libvirt.org/format.html
#
# NOTE: the tests/daemon-conf regression test script requires
# that each "PARAMETER = VALUE" line in this file have the parameter
# name just after a leading "#".
#################################################################
#
# Network connectivity controls
#
# Flag listening for secure TLS connections on the public TCP/IP port.
# NB, must pass the --listen flag to the libvirtd process for this to
# have any effect.
#
# It is necessary to setup a CA and issue server certificates before
# using this capability.
#
# This is enabled by default, uncomment this to disable it
#listen_tls = 0
# Listen for unencrypted TCP connections on the public TCP/IP port.
# NB, must pass the --listen flag to the libvirtd process for this to
# have any effect.
#
# Using the TCP socket requires SASL authentication by default. Only
# SASL mechanisms which support data encryption are allowed. This is
# DIGEST_MD5 and GSSAPI (Kerberos5)
#
# This is disabled by default, uncomment this to enable it.
#listen_tcp = 1
# Override the port for accepting secure TLS connections
# This can be a port number, or service name
#
#tls_port = "16514"
# Override the port for accepting insecure TCP connections
# This can be a port number, or service name
#
#tcp_port = "16509"
# Override the default configuration which binds to all network
# interfaces. This can be a numeric IPv4/6 address, or hostname
#
#listen_addr = "192.168.0.1"
# Flag toggling mDNS advertizement of the libvirt service.
#
# Alternatively can disable for all services on a host by
# stopping the Avahi daemon
#
# This is enabled by default, uncomment this to disable it
#mdns_adv = 0
# Override the default mDNS advertizement name. This must be
# unique on the immediate broadcast network.
#
# The default is "Virtualization Host HOSTNAME", where HOSTNAME
# is subsituted for the short hostname of the machine (without domain)
#
#mdns_name = "Virtualization Host Joe Demo"
#################################################################
#
# UNIX socket access controls
#
# Set the UNIX domain socket group ownership. This can be used to
# allow a 'trusted' set of users access to management capabilities
# without becoming root.
#
# This is restricted to 'root' by default.
#unix_sock_group = "libvirt"
# Set the UNIX socket permissions for the R/O socket. This is used
# for monitoring VM status only
#
# Default allows any user. If setting group ownership may want to
# restrict this to:
#unix_sock_ro_perms = "0777"
# Set the UNIX socket permissions for the R/W socket. This is used
# for full management of VMs
#
# Default allows only root. If PolicyKit is enabled on the socket,
# the default will change to allow everyone (eg, 0777)
#
# If not using PolicyKit and setting group ownership for access
# control then you may want to relax this to:
#unix_sock_rw_perms = "0770"
# Set the name of the directory in which sockets will be found/created.
#unix_sock_dir = "/var/run/libvirt"
#################################################################
#
# Authentication.
#
# - none: do not perform auth checks. If you can connect to the
# socket you are allowed. This is suitable if there are
# restrictions on connecting to the socket (eg, UNIX
# socket permissions), or if there is a lower layer in
# the network providing auth (eg, TLS/x509 certificates)
#
# - sasl: use SASL infrastructure. The actual auth scheme is then
# controlled from /etc/sasl2/libvirt.conf. For the TCP
# socket only GSSAPI & DIGEST-MD5 mechanisms will be used.
# For non-TCP or TLS sockets, any scheme is allowed.
#
# - polkit: use PolicyKit to authenticate. This is only suitable
# for use on the UNIX sockets. The default policy will
# require a user to supply their own password to gain
# full read/write access (aka sudo like), while anyone
# is allowed read/only access.
#
# Set an authentication scheme for UNIX read-only sockets
# By default socket permissions allow anyone to connect
#
# To restrict monitoring of domains you may wish to enable
# an authentication mechanism here
#auth_unix_ro = "none"
# Set an authentication scheme for UNIX read-write sockets
# By default socket permissions only allow root. If PolicyKit
# support was compiled into libvirt, the default will be to
# use 'polkit' auth.
#
# If the unix_sock_rw_perms are changed you may wish to enable
# an authentication mechanism here
#auth_unix_rw = "none"
# Change the authentication scheme for TCP sockets.
#
# If you don't enable SASL, then all TCP traffic is cleartext.
# Don't do this outside of a dev/test scenario. For real world
# use, always enable SASL and use the GSSAPI or DIGEST-MD5
# mechanism in /etc/sasl2/libvirt.conf
#auth_tcp = "sasl"
# Change the authentication scheme for TLS sockets.
#
# TLS sockets already have encryption provided by the TLS
# layer, and limited authentication is done by certificates
#
# It is possible to make use of any SASL authentication
# mechanism as well, by using 'sasl' for this option
#auth_tls = "none"
#################################################################
#
# TLS x509 certificate configuration
#
# Override the default server key file path
#
#key_file = "/etc/pki/libvirt/private/serverkey.pem"
# Override the default server certificate file path
#
#cert_file = "/etc/pki/libvirt/servercert.pem"
# Override the default CA certificate path
#
#ca_file = "/etc/pki/CA/cacert.pem"
# Specify a certificate revocation list.
#
# Defaults to not using a CRL, uncomment to enable it
#crl_file = "/etc/pki/CA/crl.pem"
#################################################################
#
# Authorization controls
#
# Flag to disable verification of client certificates
#
# Client certificate verification is the primary authentication mechanism.
# Any client which does not present a certificate signed by the CA
# will be rejected.
#
# Default is to always verify. Uncommenting this will disable
# verification - make sure an IP whitelist is set
#tls_no_verify_certificate = 1
# A whitelist of allowed x509 Distinguished Names
# This list may contain wildcards such as
#
# "C=GB,ST=London,L=London,O=Red Hat,CN=*"
#
# See the POSIX fnmatch function for the format of the wildcards.
#
# NB If this is an empty list, no client can connect, so comment out
# entirely rather than using empty list to disable these checks
#
# By default, no DN's are checked
#tls_allowed_dn_list = ["DN1", "DN2"]
# A whitelist of allowed SASL usernames. The format for usernames
# depends on the SASL authentication mechanism. Kerberos usernames
# look like username@REALM
#
# This list may contain wildcards such as
#
# "*@EXAMPLE.COM"
#
# See the POSIX fnmatch function for the format of the wildcards.
#
# NB If this is an empty list, no client can connect, so comment out
# entirely rather than using empty list to disable these checks
#
# By default, no Username's are checked
#sasl_allowed_username_list = ["joe@EXAMPLE.COM", "fred@EXAMPLE.COM" ]
#################################################################
#
# Processing controls
#
# The maximum number of concurrent client connections to allow
# over all sockets combined.
#max_clients = 20
# The minimum limit sets the number of workers to start up
# initially. If the number of active clients exceeds this,
# then more threads are spawned, upto max_workers limit.
# Typically you'd want max_workers to equal maximum number
# of clients allowed
#min_workers = 5
#max_workers = 20
# Total global limit on concurrent RPC calls. Should be
# at least as large as max_workers. Beyond this, RPC requests
# will be read into memory and queued. This directly impact
# memory usage, currently each request requires 256 KB of
# memory. So by default upto 5 MB of memory is used
#
# XXX this isn't actually enforced yet, only the per-client
# limit is used so far
#max_requests = 20
# Limit on concurrent requests from a single client
# connection. To avoid one client monopolizing the server
# this should be a small fraction of the global max_requests
# and max_workers parameter
#max_client_requests = 5
#################################################################
#
# Logging controls
#
# Logging level: 4 errors, 3 warnings, 2 informations, 1 debug
# basically 1 will log everything possible
#log_level = 3
# Logging filters:
# A filter allows to select a different logging level for a given category
# of logs
# The format for a filter is:
# x:name
# where name is a match string e.g. remote or qemu
# the x prefix is the minimal level where matching messages should be logged
# 1: DEBUG
# 2: INFO
# 3: WARNING
# 4: ERROR
#
# Multiple filter can be defined in a single @filters, they just need to be
# separated by spaces.
#
# e.g:
# log_filters="3:remote 4:event"
# to only get warning or errors from the remote layer and only errors from
# the event layer.
# Logging outputs:
# An output is one of the places to save logging informations
# The format for an output can be:
# x:stderr
# output goes to stderr
# x:syslog:name
# use syslog for the output and use the given name as the ident
# x:file:file_path
# output to a file, with the given filepath
# In all case the x prefix is the minimal level, acting as a filter
# 1: DEBUG
# 2: INFO
# 3: WARNING
# 4: ERROR
#
# Multiple output can be defined, they just need to be separated by spaces.
# e.g.:
# log_outputs="3:syslog:libvirtd"
# to log all warnings and errors to syslog under the libvirtd ident

View File

@@ -1,312 +0,0 @@
/*
* libvirtd.h: daemon data structure definitions
*
* Copyright (C) 2006-2009 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* 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
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#ifndef QEMUD_INTERNAL_H__
#define QEMUD_INTERNAL_H__
#include <config.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include "gnutls_1_0_compat.h"
#if HAVE_SASL
#include <sasl/sasl.h>
#endif
#if HAVE_POLKIT0
#include <dbus/dbus.h>
#endif
#ifdef HAVE_SYS_SYSLIMITS_H
#include <sys/syslimits.h>
#endif
#include <rpc/types.h>
#include <rpc/xdr.h>
#include "remote_protocol.h"
#include "logging.h"
#include "threads.h"
#ifdef __GNUC__
#ifdef HAVE_ANSIDECL_H
#include <ansidecl.h>
#endif
#ifndef __GNUC_PREREQ
#if defined __GNUC__ && defined __GNUC_MINOR__
# define __GNUC_PREREQ(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
#else
#define __GNUC_PREREQ(maj,min) 0
#endif
#endif
/**
* ATTRIBUTE_UNUSED:
*
* Macro to flag conciously unused parameters to functions
*/
#ifndef ATTRIBUTE_UNUSED
#define ATTRIBUTE_UNUSED __attribute__((__unused__))
#endif
/**
* ATTRIBUTE_FMT_PRINTF
*
* Macro used to check printf like functions, if compiling
* with gcc.
*
* We use gnulib which guarentees we always have GNU style
* printf format specifiers even on broken Win32 platforms
* hence we have to force 'gnu_printf' for new GCC
*/
#ifndef ATTRIBUTE_FMT_PRINTF
#if __GNUC_PREREQ (4, 4)
#define ATTRIBUTE_FMT_PRINTF(fmtpos,argpos) __attribute__((__format__ (gnu_printf, fmtpos,argpos)))
#else
#define ATTRIBUTE_FMT_PRINTF(fmtpos,argpos) __attribute__((__format__ (printf, fmtpos,argpos)))
#endif
#endif
#ifndef ATTRIBUTE_RETURN_CHECK
#if __GNUC_PREREQ (3, 4)
#define ATTRIBUTE_RETURN_CHECK __attribute__((__warn_unused_result__))
#else
#define ATTRIBUTE_RETURN_CHECK
#endif
#endif
#else
#ifndef ATTRIBUTE_UNUSED
#define ATTRIBUTE_UNUSED
#endif
#ifndef ATTRIBUTE_FMT_PRINTF
#define ATTRIBUTE_FMT_PRINTF(...)
#endif
#ifndef ATTRIBUTE_RETURN_CHECK
#define ATTRIBUTE_RETURN_CHECK
#endif
#endif
#define qemudDebug DEBUG
/* Whether we're passing reads & writes through a sasl SSF */
enum qemud_sasl_ssf {
QEMUD_SASL_SSF_NONE = 0,
QEMUD_SASL_SSF_READ = 1,
QEMUD_SASL_SSF_WRITE = 2,
};
enum qemud_sock_type {
QEMUD_SOCK_TYPE_UNIX = 0,
QEMUD_SOCK_TYPE_TCP = 1,
QEMUD_SOCK_TYPE_TLS = 2,
};
struct qemud_client_message {
char buffer [REMOTE_MESSAGE_MAX + REMOTE_MESSAGE_HEADER_XDR_LEN];
unsigned int bufferLength;
unsigned int bufferOffset;
unsigned int async : 1;
unsigned int streamTX : 1;
remote_message_header hdr;
struct qemud_client_message *next;
};
struct qemud_client;
/* Allow for filtering of incoming messages to a custom
* dispatch processing queue, instead of client->dx.
*/
typedef int (*qemud_client_filter_func)(struct qemud_client *client,
struct qemud_client_message *msg, void *opaque);
struct qemud_client_filter {
qemud_client_filter_func query;
void *opaque;
struct qemud_client_filter *next;
};
struct qemud_client_stream {
virStreamPtr st;
int procedure;
int serial;
unsigned int recvEOF : 1;
unsigned int closed : 1;
struct qemud_client_filter filter;
struct qemud_client_message *rx;
int tx;
struct qemud_client_stream *next;
};
/* Stores the per-client connection state */
struct qemud_client {
virMutex lock;
int magic;
int fd;
int watch;
int readonly:1;
int closing:1;
struct sockaddr_storage addr;
socklen_t addrlen;
int type; /* qemud_sock_type */
gnutls_session_t tlssession;
int auth;
int handshake : 1; /* If we're in progress for TLS handshake */
#if HAVE_SASL
sasl_conn_t *saslconn;
int saslSSF;
const char *saslDecoded;
unsigned int saslDecodedLength;
unsigned int saslDecodedOffset;
const char *saslEncoded;
unsigned int saslEncodedLength;
unsigned int saslEncodedOffset;
char *saslUsername;
#endif
/* Count of meages in 'dx' or 'tx' queue
* ie RPC calls in progress. Does not count
* async events which are not used for
* throttling calculations */
int nrequests;
/* Zero or one messages being received. Zero if
* nrequests >= max_clients and throttling */
struct qemud_client_message *rx;
/* Zero or many messages waiting for a worker
* to process them */
struct qemud_client_message *dx;
/* Zero or many messages waiting for transmit
* back to client, including async events */
struct qemud_client_message *tx;
/* Filters to capture messages that would otherwise
* end up on the 'dx' queue */
struct qemud_client_filter *filters;
/* Data streams */
struct qemud_client_stream *streams;
/* This is only valid if a remote open call has been made on this
* connection, otherwise it will be NULL. Also if remote close is
* called, it will be set back to NULL if that succeeds.
*/
virConnectPtr conn;
int refs;
};
#define QEMUD_CLIENT_MAGIC 0x7788aaee
struct qemud_socket {
int fd;
int watch;
int readonly;
int type; /* qemud_sock_type */
int auth;
int port;
struct qemud_socket *next;
};
struct qemud_worker {
pthread_t thread;
int hasThread :1;
int processingCall :1;
int quitRequest : 1;
/* back-pointer to our server */
struct qemud_server *server;
};
/* Main server state */
struct qemud_server {
virMutex lock;
virCond job;
int privileged;
int nworkers;
int nactiveworkers;
struct qemud_worker *workers;
int nsockets;
struct qemud_socket *sockets;
int nclients;
struct qemud_client **clients;
int sigread;
int sigwrite;
char *logDir;
pthread_t eventThread;
unsigned int hasEventThread :1;
unsigned int quitEventThread :1;
#ifdef HAVE_AVAHI
struct libvirtd_mdns *mdns;
#endif
#if HAVE_SASL
char **saslUsernameWhitelist;
#endif
#if HAVE_POLKIT0
DBusConnection *sysbus;
#endif
};
void qemudLog(int priority, const char *fmt, ...)
ATTRIBUTE_FMT_PRINTF(2,3);
int qemudRegisterClientEvent(struct qemud_server *server,
struct qemud_client *client);
void qemudUpdateClientEvent(struct qemud_client *client);
void qemudDispatchClientFailure(struct qemud_client *client);
void
qemudClientMessageQueuePush(struct qemud_client_message **queue,
struct qemud_client_message *msg);
struct qemud_client_message *
qemudClientMessageQueueServe(struct qemud_client_message **queue);
void
qemudClientMessageRelease(struct qemud_client *client,
struct qemud_client_message *msg);
#if HAVE_POLKIT
int qemudGetSocketIdentity(int fd, uid_t *uid, pid_t *pid);
#endif
#endif

View File

@@ -1,116 +0,0 @@
#!/bin/sh
# the following is the LSB init header see
# http://www.linux-foundation.org/spec//booksets/LSB-Core-generic/LSB-Core-generic.html#INITSCRCOMCONV
#
### BEGIN INIT INFO
# Provides: libvirtd
# Required-Start: $network messagebus
# Should-Start: $named
# Should-Start: xend
# Should-Start: hal
# Should-Start: avahi
# Required-Stop: $network messagebus
# Should-Stop: $named
# Default-Start: 3 4 5
# Short-Description: daemon for libvirt virtualization API
# Description: This is a daemon for managing guest instances
# and libvirt virtual networks
# See http://libvirt.org
### END INIT INFO
# the following is chkconfig init header
#
# libvirtd: guest and virtual network management daemon
#
# chkconfig: 345 97 03
# description: This is a daemon for managing guest instances
# and libvirt virtual networks
# See http://libvirt.org
#
# processname: libvirtd
# pidfile: @localstatedir@/run/libvirtd.pid
#
# Sanity checks.
[ -x @sbindir@/libvirtd ] || exit 0
# Source function library.
. @sysconfdir@/rc.d/init.d/functions
SERVICE=libvirtd
PROCESS=libvirtd
PIDFILE=@localstatedir@/run/$SERVICE.pid
LIBVIRTD_CONFIG=
LIBVIRTD_ARGS=
KRB5_KTNAME=/etc/libvirt/krb5.tab
test -f @sysconfdir@/sysconfig/libvirtd && . @sysconfdir@/sysconfig/libvirtd
LIBVIRTD_CONFIG_ARGS=
if [ -n "$LIBVIRTD_CONFIG" ]
then
LIBVIRTD_CONFIG_ARGS="--config $LIBVIRTD_CONFIG"
fi
RETVAL=0
start() {
echo -n $"Starting $SERVICE daemon: "
mkdir -p @localstatedir@/cache/libvirt
rm -rf @localstatedir@/cache/libvirt/*
KRB5_KTNAME=$KRB5_KTNAME daemon --pidfile $PIDFILE --check $SERVICE $PROCESS --daemon $LIBVIRTD_CONFIG_ARGS $LIBVIRTD_ARGS
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch @localstatedir@/lock/subsys/$SERVICE
}
stop() {
echo -n $"Stopping $SERVICE daemon: "
killproc -p $PIDFILE $PROCESS
RETVAL=$?
echo
if [ $RETVAL -eq 0 ]; then
rm -f @localstatedir@/lock/subsys/$SERVICE
rm -f $PIDFILE
rm -rf @localstatedir@/cache/libvirt/*
fi
}
restart() {
stop
start
}
reload() {
echo -n $"Reloading $SERVICE configuration: "
killproc -p $PIDFILE $PROCESS -HUP
RETVAL=$?
echo
return $RETVAL
}
# See how we were called.
case "$1" in
start|stop|restart|reload)
$1
;;
status)
status -p $PIDFILE $PROCESS
RETVAL=$?
;;
force-reload)
reload
;;
condrestart|try-restart)
[ -f @localstatedir@/lock/subsys/$SERVICE ] && restart || :
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"
exit 1
;;
esac
exit $RETVAL

View File

@@ -1,9 +0,0 @@
@localstatedir@/log/libvirt/qemu/*.log @localstatedir@/log/libvirt/uml/*.log @localstatedir@/log/libvirt/lxc/*.log {
weekly
missingok
rotate 4
compress
delaycompress
copytruncate
minsize 100k
}

View File

@@ -1,42 +0,0 @@
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
<!--
Policy definitions for libvirt daemon
Copyright (c) 2007 Daniel P. Berrange <berrange redhat com>
libvirt is licensed to you under the GNU Lesser General Public License
version 2. See COPYING for details.
NOTE: If you make changes to this file, make sure to validate the file
using the polkit-policy-file-validate(1) tool. Changes made to this
file are instantly applied.
-->
<policyconfig>
<action id="org.libvirt.unix.monitor">
<description>Monitor local virtualized systems</description>
<message>System policy prevents monitoring of local virtualized systems</message>
<defaults>
<!-- Any program can use libvirt in read-only mode for monitoring,
even if not part of a session -->
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.libvirt.unix.manage">
<description>Manage local virtualized systems</description>
<message>System policy prevents management of local virtualized systems</message>
<defaults>
<!-- Only a program in the active host session can use libvirt in
read-write mode for management, and we require user password -->
<allow_any>no</allow_any>
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin_keep_session</allow_active>
</defaults>
</action>
</policyconfig>

View File

@@ -1,42 +0,0 @@
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
<!--
Policy definitions for libvirt daemon
Copyright (c) 2007 Daniel P. Berrange <berrange redhat com>
libvirt is licensed to you under the GNU Lesser General Public License
version 2. See COPYING for details.
NOTE: If you make changes to this file, make sure to validate the file
using the polkit-policy-file-validate(1) tool. Changes made to this
file are instantly applied.
-->
<policyconfig>
<action id="org.libvirt.unix.monitor">
<description>Monitor local virtualized systems</description>
<message>System policy prevents monitoring of local virtualized systems</message>
<defaults>
<!-- Any program can use libvirt in read-only mode for monitoring,
even if not part of a session -->
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.libvirt.unix.manage">
<description>Manage local virtualized systems</description>
<message>System policy prevents management of local virtualized systems</message>
<defaults>
<!-- Only a program in the active host session can use libvirt in
read-write mode for management, and we require user password -->
<allow_any>no</allow_any>
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
</policyconfig>

View File

@@ -1,28 +0,0 @@
# If you want to use the non-TLS socket, then you *must* include
# the GSSAPI or DIGEST-MD5 mechanisms, because they are the only
# ones that can offer session encryption as well as authentication.
#
# If you're only using TLS, then you can turn on any mechanisms
# you like for authentication, because TLS provides the encryption
#
# Default to a simple username+password mechanism
mech_list: digest-md5
# Before you can use GSSAPI, you need a service principle on the
# KDC server for libvirt, and that to be exported to the keytab
# file listed below
#mech_list: gssapi
#
# You can also list many mechanisms at once, then the user can choose
# by adding '?auth=sasl.gssapi' to their libvirt URI, eg
# qemu+tcp://hostname/system?auth=sasl.gssapi
#mech_list: digest-md5 gssapi
# MIT kerberos ignores this option & needs KRB5_KTNAME env var.
# May be useful for other non-Linux OS though....
keytab: /etc/libvirt/krb5.tab
# If using digest-md5 for username/passwds, then this is the file
# containing the passwds. Use 'saslpasswd2 -a libvirt [username]'
# to add entries, and 'sasldblistusers2 -a libvirt' to browse it
sasldb_path: /etc/libvirt/passwd.db

View File

@@ -1,17 +0,0 @@
# Override the default config file
#LIBVIRTD_CONFIG=/etc/libvirt/libvirtd.conf
# Listen for TCP/IP connections
# NB. must setup TLS/SSL keys prior to using this
#LIBVIRTD_ARGS="--listen"
# Override Kerberos service keytab for SASL/GSSAPI
#KRB5_KTNAME=/etc/libvirt/krb5.tab
# Override the QEMU/SDL default audio driver probing when
# starting virtual machines using SDL graphics
#
# NB these have no effect for VMs using VNC
#QEMU_AUDIO_DRV=sdl
#
#SDL_AUDIODRIVER=pulse

View File

@@ -1,508 +0,0 @@
/*
* mdns.c: advertise libvirt hypervisor connections
*
* Copyright (C) 2007 Daniel P. Berrange
*
* Derived from Avahi example service provider code.
*
* 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
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#include <config.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <avahi-client/client.h>
#include <avahi-client/publish.h>
#include <avahi-common/alternative.h>
#include <avahi-common/simple-watch.h>
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>
#include <avahi-common/timeval.h>
#include "libvirtd.h"
#include "mdns.h"
#include "event.h"
#include "memory.h"
#define AVAHI_DEBUG(fmt, ...) DEBUG(fmt, __VA_ARGS__)
struct libvirtd_mdns_entry {
char *type;
int port;
struct libvirtd_mdns_entry *next;
};
struct libvirtd_mdns_group {
struct libvirtd_mdns *mdns;
AvahiEntryGroup *handle;
char *name;
struct libvirtd_mdns_entry *entry;
struct libvirtd_mdns_group *next;
};
struct libvirtd_mdns {
AvahiClient *client;
AvahiPoll *poller;
struct libvirtd_mdns_group *group;
};
/* Avahi API requires this struct names in the app :-( */
struct AvahiWatch {
int watch;
int fd;
int revents;
AvahiWatchCallback callback;
void *userdata;
};
/* Avahi API requires this struct names in the app :-( */
struct AvahiTimeout {
int timer;
AvahiTimeoutCallback callback;
void *userdata;
};
static void libvirtd_mdns_create_services(struct libvirtd_mdns_group *group);
/* Called whenever the entry group state changes */
static void libvirtd_mdns_group_callback(AvahiEntryGroup *g ATTRIBUTE_UNUSED, AvahiEntryGroupState state, void *userdata) {
struct libvirtd_mdns_group *group = (struct libvirtd_mdns_group *)userdata;
switch (state) {
case AVAHI_ENTRY_GROUP_ESTABLISHED:
/* The entry group has been established successfully */
AVAHI_DEBUG("Group '%s' established", group->name);
break;
case AVAHI_ENTRY_GROUP_COLLISION:
{
char *n;
/* A service name collision happened. Let's pick a new name */
n = avahi_alternative_service_name(group->name);
VIR_FREE(group->name);
group->name = n;
AVAHI_DEBUG("Group name collision, renaming service to '%s'", group->name);
/* And recreate the services */
libvirtd_mdns_create_services(group);
}
break;
case AVAHI_ENTRY_GROUP_FAILURE :
AVAHI_DEBUG("Group failure: %s", avahi_strerror(avahi_client_errno(group->mdns->client)));
/* Some kind of failure happened while we were registering our services */
//avahi_simple_poll_quit(simple_poll);
break;
case AVAHI_ENTRY_GROUP_UNCOMMITED:
case AVAHI_ENTRY_GROUP_REGISTERING:
;
}
}
static void libvirtd_mdns_create_services(struct libvirtd_mdns_group *group) {
struct libvirtd_mdns *mdns = group->mdns;
struct libvirtd_mdns_entry *entry;
int ret;
AVAHI_DEBUG("Adding services to '%s'", group->name);
/* If we've no services to advertise, just reset the group to make
* sure it is emptied of any previously advertised services */
if (!group->entry) {
if (group->handle)
avahi_entry_group_reset(group->handle);
return;
}
/* If this is the first time we're called, let's create a new entry group */
if (!group->handle) {
AVAHI_DEBUG("Creating initial group %s", group->name);
if (!(group->handle = avahi_entry_group_new(mdns->client, libvirtd_mdns_group_callback, group))) {
AVAHI_DEBUG("avahi_entry_group_new() failed: %s", avahi_strerror(avahi_client_errno(mdns->client)));
return;
}
}
entry = group->entry;
while (entry) {
if ((ret = avahi_entry_group_add_service(group->handle,
AVAHI_IF_UNSPEC,
AVAHI_PROTO_UNSPEC,
0,
group->name,
entry->type,
NULL,
NULL,
entry->port,
NULL)) < 0) {
AVAHI_DEBUG("Failed to add %s service on port %d: %s",
entry->type, entry->port, avahi_strerror(ret));
avahi_entry_group_reset(group->handle);
return;
}
entry = entry->next;
}
/* Tell the server to register the service */
if ((ret = avahi_entry_group_commit(group->handle)) < 0) {
avahi_entry_group_reset(group->handle);
AVAHI_DEBUG("Failed to commit entry_group: %s", avahi_strerror(ret));
return;
}
}
static void libvirtd_mdns_client_callback(AvahiClient *c, AvahiClientState state, void *userdata) {
struct libvirtd_mdns *mdns = (struct libvirtd_mdns *)userdata;
struct libvirtd_mdns_group *group;
if (!mdns->client)
mdns->client = c;
/* Called whenever the client or server state changes */
switch (state) {
case AVAHI_CLIENT_S_RUNNING:
/* The server has startup successfully and registered its host
* name on the network, so it's time to create our services */
AVAHI_DEBUG("Client running %p", mdns->client);
group = mdns->group;
while (group) {
libvirtd_mdns_create_services(group);
group = group->next;
}
break;
case AVAHI_CLIENT_FAILURE:
AVAHI_DEBUG("Client failure: %s", avahi_strerror(avahi_client_errno(c)));
libvirtd_mdns_stop(mdns);
libvirtd_mdns_start(mdns);
break;
case AVAHI_CLIENT_S_COLLISION:
/* Let's drop our registered services. When the server is back
* in AVAHI_SERVER_RUNNING state we will register them
* again with the new host name. */
/* Fallthrough */
case AVAHI_CLIENT_S_REGISTERING:
/* The server records are now being established. This
* might be caused by a host name change. We need to wait
* for our own records to register until the host name is
* properly established. */
AVAHI_DEBUG("Client collision/connecting %p", mdns->client);
group = mdns->group;
while (group) {
if (group->handle)
avahi_entry_group_reset(group->handle);
group = group->next;
}
break;
case AVAHI_CLIENT_CONNECTING:
AVAHI_DEBUG("Client connecting.... %p", mdns->client);
;
}
}
static void libvirtd_mdns_watch_dispatch(int watch, int fd, int events, void *opaque)
{
AvahiWatch *w = (AvahiWatch*)opaque;
int fd_events = virEventHandleTypeToPollEvent(events);
AVAHI_DEBUG("Dispatch watch %d FD %d Event %d", watch, fd, fd_events);
w->revents = fd_events;
w->callback(w, fd, fd_events, w->userdata);
}
static void libvirtd_mdns_watch_dofree(void *w)
{
VIR_FREE(w);
}
static AvahiWatch *libvirtd_mdns_watch_new(const AvahiPoll *api ATTRIBUTE_UNUSED,
int fd, AvahiWatchEvent event,
AvahiWatchCallback cb, void *userdata) {
AvahiWatch *w;
virEventHandleType hEvents;
if (VIR_ALLOC(w) < 0)
return NULL;
w->fd = fd;
w->revents = 0;
w->callback = cb;
w->userdata = userdata;
AVAHI_DEBUG("New handle %p FD %d Event %d", w, w->fd, event);
hEvents = virPollEventToEventHandleType(event);
if ((w->watch = virEventAddHandleImpl(fd, hEvents,
libvirtd_mdns_watch_dispatch,
w,
libvirtd_mdns_watch_dofree)) < 0) {
VIR_FREE(w);
return NULL;
}
return w;
}
static void libvirtd_mdns_watch_update(AvahiWatch *w, AvahiWatchEvent event)
{
AVAHI_DEBUG("Update handle %p FD %d Event %d", w, w->fd, event);
virEventUpdateHandleImpl(w->watch, event);
}
static AvahiWatchEvent libvirtd_mdns_watch_get_events(AvahiWatch *w)
{
AVAHI_DEBUG("Get handle events %p %d", w, w->fd);
return w->revents;
}
static void libvirtd_mdns_watch_free(AvahiWatch *w)
{
AVAHI_DEBUG("Free handle %p %d", w, w->fd);
virEventRemoveHandleImpl(w->watch);
}
static void libvirtd_mdns_timeout_dispatch(int timer ATTRIBUTE_UNUSED, void *opaque)
{
AvahiTimeout *t = (AvahiTimeout*)opaque;
AVAHI_DEBUG("Dispatch timeout %p %d", t, timer);
virEventUpdateTimeoutImpl(t->timer, -1);
t->callback(t, t->userdata);
}
static void libvirtd_mdns_timeout_dofree(void *t)
{
VIR_FREE(t);
}
static AvahiTimeout *libvirtd_mdns_timeout_new(const AvahiPoll *api ATTRIBUTE_UNUSED,
const struct timeval *tv,
AvahiTimeoutCallback cb,
void *userdata)
{
AvahiTimeout *t;
struct timeval now;
long long nowms, thenms, timeout;
AVAHI_DEBUG("Add timeout TV %p", tv);
if (VIR_ALLOC(t) < 0)
return NULL;
if (gettimeofday(&now, NULL) < 0) {
VIR_FREE(t);
return NULL;
}
AVAHI_DEBUG("Trigger timed for %d %d %d %d",
(int)now.tv_sec, (int)now.tv_usec,
(int)(tv ? tv->tv_sec : 0), (int)(tv ? tv->tv_usec : 0));
nowms = (now.tv_sec * 1000ll) + (now.tv_usec / 1000ll);
if (tv) {
thenms = (tv->tv_sec * 1000ll) + (tv->tv_usec/1000ll);
timeout = thenms > nowms ? nowms - thenms : 0;
if (timeout < 0)
timeout = 0;
} else {
timeout = -1;
}
t->timer = virEventAddTimeoutImpl(timeout,
libvirtd_mdns_timeout_dispatch,
t,
libvirtd_mdns_timeout_dofree);
t->callback = cb;
t->userdata = userdata;
if (t->timer < 0) {
VIR_FREE(t);
return NULL;
}
return t;
}
static void libvirtd_mdns_timeout_update(AvahiTimeout *t, const struct timeval *tv)
{
struct timeval now;
long long nowms, thenms, timeout;
AVAHI_DEBUG("Update timeout %p TV %p", t, tv);
if (gettimeofday(&now, NULL) < 0) {
VIR_FREE(t);
return;
}
nowms = (now.tv_sec * 1000ll) + (now.tv_usec / 1000ll);
if (tv) {
thenms = ((tv->tv_sec * 1000ll) + (tv->tv_usec/1000ll));
timeout = thenms > nowms ? nowms - thenms : 0;
if (timeout < 0)
timeout = 0;
} else {
timeout = -1;
}
virEventUpdateTimeoutImpl(t->timer, timeout);
}
static void libvirtd_mdns_timeout_free(AvahiTimeout *t)
{
AVAHI_DEBUG("Free timeout %p", t);
virEventRemoveTimeoutImpl(t->timer);
}
static AvahiPoll *libvirtd_create_poll(void)
{
AvahiPoll *p;
if (VIR_ALLOC(p) < 0)
return NULL;
p->userdata = NULL;
p->watch_new = libvirtd_mdns_watch_new;
p->watch_update = libvirtd_mdns_watch_update;
p->watch_get_events = libvirtd_mdns_watch_get_events;
p->watch_free = libvirtd_mdns_watch_free;
p->timeout_new = libvirtd_mdns_timeout_new;
p->timeout_update = libvirtd_mdns_timeout_update;
p->timeout_free = libvirtd_mdns_timeout_free;
return p;
}
struct libvirtd_mdns *libvirtd_mdns_new(void)
{
struct libvirtd_mdns *mdns;
if (VIR_ALLOC(mdns) < 0)
return NULL;
/* Allocate main loop object */
if (!(mdns->poller = libvirtd_create_poll())) {
VIR_FREE(mdns);
return NULL;
}
return mdns;
}
int libvirtd_mdns_start(struct libvirtd_mdns *mdns)
{
int error;
AVAHI_DEBUG("Starting client %p", mdns);
mdns->client = avahi_client_new(mdns->poller, AVAHI_CLIENT_NO_FAIL, libvirtd_mdns_client_callback, mdns, &error);
if (!mdns->client) {
AVAHI_DEBUG("Failed to create mDNS client: %s", avahi_strerror(error));
return -1;
}
return 0;
}
struct libvirtd_mdns_group *libvirtd_mdns_add_group(struct libvirtd_mdns *mdns, const char *name) {
struct libvirtd_mdns_group *group;
AVAHI_DEBUG("Adding group '%s'", name);
if (VIR_ALLOC(group) < 0)
return NULL;
if (!(group->name = strdup(name))) {
VIR_FREE(group);
return NULL;
}
group->mdns = mdns;
group->next = mdns->group;
mdns->group = group;
return group;
}
void libvirtd_mdns_remove_group(struct libvirtd_mdns *mdns, struct libvirtd_mdns_group *group) {
struct libvirtd_mdns_group *tmp = mdns->group, *prev = NULL;
while (tmp) {
if (tmp == group) {
VIR_FREE(group->name);
if (prev)
prev->next = group->next;
else
group->mdns->group = group->next;
VIR_FREE(group);
return;
}
prev = tmp;
tmp = tmp->next;
}
}
struct libvirtd_mdns_entry *libvirtd_mdns_add_entry(struct libvirtd_mdns_group *group, const char *type, int port) {
struct libvirtd_mdns_entry *entry;
AVAHI_DEBUG("Adding entry %s %d to group %s", type, port, group->name);
if (VIR_ALLOC(entry) < 0)
return NULL;
entry->port = port;
if (!(entry->type = strdup(type))) {
VIR_FREE(entry);
return NULL;
}
entry->next = group->entry;
group->entry = entry;
return entry;
}
void libvirtd_mdns_remove_entry(struct libvirtd_mdns_group *group, struct libvirtd_mdns_entry *entry) {
struct libvirtd_mdns_entry *tmp = group->entry, *prev = NULL;
while (tmp) {
if (tmp == entry) {
VIR_FREE(entry->type);
if (prev)
prev->next = entry->next;
else
group->entry = entry->next;
return;
}
prev = tmp;
tmp = tmp->next;
}
}
void libvirtd_mdns_stop(struct libvirtd_mdns *mdns)
{
struct libvirtd_mdns_group *group = mdns->group;
while (group) {
if (group->handle) {
avahi_entry_group_free(group->handle);
group->handle = NULL;
}
group = group->next;
}
if (mdns->client)
avahi_client_free(mdns->client);
mdns->client = NULL;
}

View File

@@ -1,96 +0,0 @@
/*
* mdns.c: advertise libvirt hypervisor connections
*
* Copyright (C) 2007 Daniel P. Berrange
*
* Derived from Avahi example service provider code.
*
* 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
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#include "internal.h"
#ifndef __VIRTD_MDNS_H__
#define __VIRTD_MDNS_H__
struct libvirtd_mdns;
struct libvirtd_mdns_group;
struct libvirtd_mdns_entry;
/**
* Prepares a new mdns manager object for use
*/
struct libvirtd_mdns *libvirtd_mdns_new(void);
/**
* Starts the mdns client, advertising any groups/entries currently registered
*
* @mdns: manager to start advertising
*
* Starts the mdns client. Services may not be immediately visible, since
* it may asynchronously wait for the mdns service to startup
*
* returns -1 upon failure, 0 upon success.
*/
int libvirtd_mdns_start(struct libvirtd_mdns *mdns);
/**
* Stops the mdns client, removing any advertisements
*
* @mdns: manager to start advertising
*
*/
void libvirtd_mdns_stop(struct libvirtd_mdns *mdns);
/**
* Adds a group container for advertisement
*
* @mdns manager to attach the group to
* @name unique human readable service name
*
* returns the group record, or NULL upon failure
*/
struct libvirtd_mdns_group *libvirtd_mdns_add_group(struct libvirtd_mdns *mdns, const char *name);
/**
* Removes a group container from advertisement
*
* @mdns amanger to detach group from
* @group group to remove
*/
void libvirtd_mdns_remove_group(struct libvirtd_mdns *mdns, struct libvirtd_mdns_group *group);
/**
* Adds a service entry in a group
*
* @group group to attach the entry to
* @type service type string
* @port tcp port number
*
* returns the service record, or NULL upon failure
*/
struct libvirtd_mdns_entry *libvirtd_mdns_add_entry(struct libvirtd_mdns_group *group, const char *type, int port);
/**
* Removes a service entry from a group
*
* @group group to detach service entry from
* @entry service entry to remove
*/
void libvirtd_mdns_remove_entry(struct libvirtd_mdns_group *group, struct libvirtd_mdns_entry *entry);
#endif /* __VIRTD_MDNS_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,73 +0,0 @@
/*
* remote.h: handlers for RPC method calls
*
* Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Richard W.M. Jones <rjones@redhat.com>
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#ifndef __LIBVIRTD_REMOTE_H__
#define __LIBVIRTD_REMOTE_H__
#include "libvirtd.h"
typedef union {
#include "remote_dispatch_args.h"
} dispatch_args;
typedef union {
#include "remote_dispatch_ret.h"
} dispatch_ret;
/**
* When the RPC handler is called:
*
* - Server object is unlocked
* - Client object is unlocked
*
* Both must be locked before use. Server lock must
* be held before attempting to lock client.
*
* Without any locking, it is safe to use:
*
* 'conn', 'rerr', 'args and 'ret'
*/
typedef int (*dispatch_fn) (struct qemud_server *server,
struct qemud_client *client,
virConnectPtr conn,
remote_message_header *hdr,
remote_error *err,
dispatch_args *args,
dispatch_ret *ret);
typedef struct {
dispatch_fn fn;
xdrproc_t args_filter;
xdrproc_t ret_filter;
} dispatch_data;
const dispatch_data const *remoteGetDispatchData(int proc);
#endif /* __LIBVIRTD_REMOTE_H__ */

View File

@@ -1,137 +0,0 @@
/* Automatically generated by remote_generate_stubs.pl.
* Do not edit this file. Any changes you make will be lost.
*/
remote_open_args val_remote_open_args;
remote_get_max_vcpus_args val_remote_get_max_vcpus_args;
remote_domain_attach_device_args val_remote_domain_attach_device_args;
remote_domain_create_args val_remote_domain_create_args;
remote_domain_create_xml_args val_remote_domain_create_xml_args;
remote_domain_define_xml_args val_remote_domain_define_xml_args;
remote_domain_destroy_args val_remote_domain_destroy_args;
remote_domain_detach_device_args val_remote_domain_detach_device_args;
remote_domain_dump_xml_args val_remote_domain_dump_xml_args;
remote_domain_get_autostart_args val_remote_domain_get_autostart_args;
remote_domain_get_info_args val_remote_domain_get_info_args;
remote_domain_get_max_memory_args val_remote_domain_get_max_memory_args;
remote_domain_get_max_vcpus_args val_remote_domain_get_max_vcpus_args;
remote_domain_get_os_type_args val_remote_domain_get_os_type_args;
remote_domain_get_vcpus_args val_remote_domain_get_vcpus_args;
remote_list_defined_domains_args val_remote_list_defined_domains_args;
remote_domain_lookup_by_id_args val_remote_domain_lookup_by_id_args;
remote_domain_lookup_by_name_args val_remote_domain_lookup_by_name_args;
remote_domain_lookup_by_uuid_args val_remote_domain_lookup_by_uuid_args;
remote_domain_pin_vcpu_args val_remote_domain_pin_vcpu_args;
remote_domain_reboot_args val_remote_domain_reboot_args;
remote_domain_resume_args val_remote_domain_resume_args;
remote_domain_set_autostart_args val_remote_domain_set_autostart_args;
remote_domain_set_max_memory_args val_remote_domain_set_max_memory_args;
remote_domain_set_memory_args val_remote_domain_set_memory_args;
remote_domain_set_vcpus_args val_remote_domain_set_vcpus_args;
remote_domain_shutdown_args val_remote_domain_shutdown_args;
remote_domain_suspend_args val_remote_domain_suspend_args;
remote_domain_undefine_args val_remote_domain_undefine_args;
remote_list_defined_networks_args val_remote_list_defined_networks_args;
remote_list_domains_args val_remote_list_domains_args;
remote_list_networks_args val_remote_list_networks_args;
remote_network_create_args val_remote_network_create_args;
remote_network_create_xml_args val_remote_network_create_xml_args;
remote_network_define_xml_args val_remote_network_define_xml_args;
remote_network_destroy_args val_remote_network_destroy_args;
remote_network_dump_xml_args val_remote_network_dump_xml_args;
remote_network_get_autostart_args val_remote_network_get_autostart_args;
remote_network_get_bridge_name_args val_remote_network_get_bridge_name_args;
remote_network_lookup_by_name_args val_remote_network_lookup_by_name_args;
remote_network_lookup_by_uuid_args val_remote_network_lookup_by_uuid_args;
remote_network_set_autostart_args val_remote_network_set_autostart_args;
remote_network_undefine_args val_remote_network_undefine_args;
remote_domain_core_dump_args val_remote_domain_core_dump_args;
remote_domain_restore_args val_remote_domain_restore_args;
remote_domain_save_args val_remote_domain_save_args;
remote_domain_get_scheduler_type_args val_remote_domain_get_scheduler_type_args;
remote_domain_get_scheduler_parameters_args val_remote_domain_get_scheduler_parameters_args;
remote_domain_set_scheduler_parameters_args val_remote_domain_set_scheduler_parameters_args;
remote_supports_feature_args val_remote_supports_feature_args;
remote_domain_migrate_prepare_args val_remote_domain_migrate_prepare_args;
remote_domain_migrate_perform_args val_remote_domain_migrate_perform_args;
remote_domain_migrate_finish_args val_remote_domain_migrate_finish_args;
remote_domain_block_stats_args val_remote_domain_block_stats_args;
remote_domain_interface_stats_args val_remote_domain_interface_stats_args;
remote_auth_sasl_start_args val_remote_auth_sasl_start_args;
remote_auth_sasl_step_args val_remote_auth_sasl_step_args;
remote_list_storage_pools_args val_remote_list_storage_pools_args;
remote_list_defined_storage_pools_args val_remote_list_defined_storage_pools_args;
remote_find_storage_pool_sources_args val_remote_find_storage_pool_sources_args;
remote_storage_pool_create_xml_args val_remote_storage_pool_create_xml_args;
remote_storage_pool_define_xml_args val_remote_storage_pool_define_xml_args;
remote_storage_pool_create_args val_remote_storage_pool_create_args;
remote_storage_pool_build_args val_remote_storage_pool_build_args;
remote_storage_pool_destroy_args val_remote_storage_pool_destroy_args;
remote_storage_pool_delete_args val_remote_storage_pool_delete_args;
remote_storage_pool_undefine_args val_remote_storage_pool_undefine_args;
remote_storage_pool_refresh_args val_remote_storage_pool_refresh_args;
remote_storage_pool_lookup_by_name_args val_remote_storage_pool_lookup_by_name_args;
remote_storage_pool_lookup_by_uuid_args val_remote_storage_pool_lookup_by_uuid_args;
remote_storage_pool_lookup_by_volume_args val_remote_storage_pool_lookup_by_volume_args;
remote_storage_pool_get_info_args val_remote_storage_pool_get_info_args;
remote_storage_pool_dump_xml_args val_remote_storage_pool_dump_xml_args;
remote_storage_pool_get_autostart_args val_remote_storage_pool_get_autostart_args;
remote_storage_pool_set_autostart_args val_remote_storage_pool_set_autostart_args;
remote_storage_pool_num_of_volumes_args val_remote_storage_pool_num_of_volumes_args;
remote_storage_pool_list_volumes_args val_remote_storage_pool_list_volumes_args;
remote_storage_vol_create_xml_args val_remote_storage_vol_create_xml_args;
remote_storage_vol_delete_args val_remote_storage_vol_delete_args;
remote_storage_vol_lookup_by_name_args val_remote_storage_vol_lookup_by_name_args;
remote_storage_vol_lookup_by_key_args val_remote_storage_vol_lookup_by_key_args;
remote_storage_vol_lookup_by_path_args val_remote_storage_vol_lookup_by_path_args;
remote_storage_vol_get_info_args val_remote_storage_vol_get_info_args;
remote_storage_vol_dump_xml_args val_remote_storage_vol_dump_xml_args;
remote_storage_vol_get_path_args val_remote_storage_vol_get_path_args;
remote_node_get_cells_free_memory_args val_remote_node_get_cells_free_memory_args;
remote_domain_block_peek_args val_remote_domain_block_peek_args;
remote_domain_memory_peek_args val_remote_domain_memory_peek_args;
remote_domain_migrate_prepare2_args val_remote_domain_migrate_prepare2_args;
remote_domain_migrate_finish2_args val_remote_domain_migrate_finish2_args;
remote_node_num_of_devices_args val_remote_node_num_of_devices_args;
remote_node_list_devices_args val_remote_node_list_devices_args;
remote_node_device_lookup_by_name_args val_remote_node_device_lookup_by_name_args;
remote_node_device_dump_xml_args val_remote_node_device_dump_xml_args;
remote_node_device_get_parent_args val_remote_node_device_get_parent_args;
remote_node_device_num_of_caps_args val_remote_node_device_num_of_caps_args;
remote_node_device_list_caps_args val_remote_node_device_list_caps_args;
remote_node_device_dettach_args val_remote_node_device_dettach_args;
remote_node_device_re_attach_args val_remote_node_device_re_attach_args;
remote_node_device_reset_args val_remote_node_device_reset_args;
remote_domain_get_security_label_args val_remote_domain_get_security_label_args;
remote_node_device_create_xml_args val_remote_node_device_create_xml_args;
remote_node_device_destroy_args val_remote_node_device_destroy_args;
remote_storage_vol_create_xml_from_args val_remote_storage_vol_create_xml_from_args;
remote_list_interfaces_args val_remote_list_interfaces_args;
remote_interface_lookup_by_name_args val_remote_interface_lookup_by_name_args;
remote_interface_lookup_by_mac_string_args val_remote_interface_lookup_by_mac_string_args;
remote_interface_get_xml_desc_args val_remote_interface_get_xml_desc_args;
remote_interface_define_xml_args val_remote_interface_define_xml_args;
remote_interface_undefine_args val_remote_interface_undefine_args;
remote_interface_create_args val_remote_interface_create_args;
remote_interface_destroy_args val_remote_interface_destroy_args;
remote_domain_xml_from_native_args val_remote_domain_xml_from_native_args;
remote_domain_xml_to_native_args val_remote_domain_xml_to_native_args;
remote_list_defined_interfaces_args val_remote_list_defined_interfaces_args;
remote_list_secrets_args val_remote_list_secrets_args;
remote_secret_lookup_by_uuid_args val_remote_secret_lookup_by_uuid_args;
remote_secret_define_xml_args val_remote_secret_define_xml_args;
remote_secret_get_xml_desc_args val_remote_secret_get_xml_desc_args;
remote_secret_set_value_args val_remote_secret_set_value_args;
remote_secret_get_value_args val_remote_secret_get_value_args;
remote_secret_undefine_args val_remote_secret_undefine_args;
remote_secret_lookup_by_usage_args val_remote_secret_lookup_by_usage_args;
remote_domain_migrate_prepare_tunnel_args val_remote_domain_migrate_prepare_tunnel_args;
remote_domain_is_active_args val_remote_domain_is_active_args;
remote_domain_is_persistent_args val_remote_domain_is_persistent_args;
remote_network_is_active_args val_remote_network_is_active_args;
remote_network_is_persistent_args val_remote_network_is_persistent_args;
remote_storage_pool_is_active_args val_remote_storage_pool_is_active_args;
remote_storage_pool_is_persistent_args val_remote_storage_pool_is_persistent_args;
remote_interface_is_active_args val_remote_interface_is_active_args;
remote_cpu_compare_args val_remote_cpu_compare_args;
remote_domain_memory_stats_args val_remote_domain_memory_stats_args;

File diff suppressed because it is too large Load Diff

View File

@@ -1,119 +0,0 @@
/* Automatically generated by remote_generate_stubs.pl.
* Do not edit this file. Any changes you make will be lost.
*/
remote_get_type_ret val_remote_get_type_ret;
remote_get_version_ret val_remote_get_version_ret;
remote_get_max_vcpus_ret val_remote_get_max_vcpus_ret;
remote_node_get_info_ret val_remote_node_get_info_ret;
remote_get_capabilities_ret val_remote_get_capabilities_ret;
remote_domain_create_xml_ret val_remote_domain_create_xml_ret;
remote_domain_define_xml_ret val_remote_domain_define_xml_ret;
remote_domain_dump_xml_ret val_remote_domain_dump_xml_ret;
remote_domain_get_autostart_ret val_remote_domain_get_autostart_ret;
remote_domain_get_info_ret val_remote_domain_get_info_ret;
remote_domain_get_max_memory_ret val_remote_domain_get_max_memory_ret;
remote_domain_get_max_vcpus_ret val_remote_domain_get_max_vcpus_ret;
remote_domain_get_os_type_ret val_remote_domain_get_os_type_ret;
remote_domain_get_vcpus_ret val_remote_domain_get_vcpus_ret;
remote_list_defined_domains_ret val_remote_list_defined_domains_ret;
remote_domain_lookup_by_id_ret val_remote_domain_lookup_by_id_ret;
remote_domain_lookup_by_name_ret val_remote_domain_lookup_by_name_ret;
remote_domain_lookup_by_uuid_ret val_remote_domain_lookup_by_uuid_ret;
remote_num_of_defined_domains_ret val_remote_num_of_defined_domains_ret;
remote_list_defined_networks_ret val_remote_list_defined_networks_ret;
remote_list_domains_ret val_remote_list_domains_ret;
remote_list_networks_ret val_remote_list_networks_ret;
remote_network_create_xml_ret val_remote_network_create_xml_ret;
remote_network_define_xml_ret val_remote_network_define_xml_ret;
remote_network_dump_xml_ret val_remote_network_dump_xml_ret;
remote_network_get_autostart_ret val_remote_network_get_autostart_ret;
remote_network_get_bridge_name_ret val_remote_network_get_bridge_name_ret;
remote_network_lookup_by_name_ret val_remote_network_lookup_by_name_ret;
remote_network_lookup_by_uuid_ret val_remote_network_lookup_by_uuid_ret;
remote_num_of_defined_networks_ret val_remote_num_of_defined_networks_ret;
remote_num_of_domains_ret val_remote_num_of_domains_ret;
remote_num_of_networks_ret val_remote_num_of_networks_ret;
remote_domain_get_scheduler_type_ret val_remote_domain_get_scheduler_type_ret;
remote_domain_get_scheduler_parameters_ret val_remote_domain_get_scheduler_parameters_ret;
remote_get_hostname_ret val_remote_get_hostname_ret;
remote_supports_feature_ret val_remote_supports_feature_ret;
remote_domain_migrate_prepare_ret val_remote_domain_migrate_prepare_ret;
remote_domain_migrate_finish_ret val_remote_domain_migrate_finish_ret;
remote_domain_block_stats_ret val_remote_domain_block_stats_ret;
remote_domain_interface_stats_ret val_remote_domain_interface_stats_ret;
remote_auth_list_ret val_remote_auth_list_ret;
remote_auth_sasl_init_ret val_remote_auth_sasl_init_ret;
remote_auth_sasl_start_ret val_remote_auth_sasl_start_ret;
remote_auth_sasl_step_ret val_remote_auth_sasl_step_ret;
remote_auth_polkit_ret val_remote_auth_polkit_ret;
remote_num_of_storage_pools_ret val_remote_num_of_storage_pools_ret;
remote_list_storage_pools_ret val_remote_list_storage_pools_ret;
remote_num_of_defined_storage_pools_ret val_remote_num_of_defined_storage_pools_ret;
remote_list_defined_storage_pools_ret val_remote_list_defined_storage_pools_ret;
remote_find_storage_pool_sources_ret val_remote_find_storage_pool_sources_ret;
remote_storage_pool_create_xml_ret val_remote_storage_pool_create_xml_ret;
remote_storage_pool_define_xml_ret val_remote_storage_pool_define_xml_ret;
remote_storage_pool_lookup_by_name_ret val_remote_storage_pool_lookup_by_name_ret;
remote_storage_pool_lookup_by_uuid_ret val_remote_storage_pool_lookup_by_uuid_ret;
remote_storage_pool_lookup_by_volume_ret val_remote_storage_pool_lookup_by_volume_ret;
remote_storage_pool_get_info_ret val_remote_storage_pool_get_info_ret;
remote_storage_pool_dump_xml_ret val_remote_storage_pool_dump_xml_ret;
remote_storage_pool_get_autostart_ret val_remote_storage_pool_get_autostart_ret;
remote_storage_pool_num_of_volumes_ret val_remote_storage_pool_num_of_volumes_ret;
remote_storage_pool_list_volumes_ret val_remote_storage_pool_list_volumes_ret;
remote_storage_vol_create_xml_ret val_remote_storage_vol_create_xml_ret;
remote_storage_vol_lookup_by_name_ret val_remote_storage_vol_lookup_by_name_ret;
remote_storage_vol_lookup_by_key_ret val_remote_storage_vol_lookup_by_key_ret;
remote_storage_vol_lookup_by_path_ret val_remote_storage_vol_lookup_by_path_ret;
remote_storage_vol_get_info_ret val_remote_storage_vol_get_info_ret;
remote_storage_vol_dump_xml_ret val_remote_storage_vol_dump_xml_ret;
remote_storage_vol_get_path_ret val_remote_storage_vol_get_path_ret;
remote_node_get_cells_free_memory_ret val_remote_node_get_cells_free_memory_ret;
remote_node_get_free_memory_ret val_remote_node_get_free_memory_ret;
remote_domain_block_peek_ret val_remote_domain_block_peek_ret;
remote_domain_memory_peek_ret val_remote_domain_memory_peek_ret;
remote_domain_events_register_ret val_remote_domain_events_register_ret;
remote_domain_events_deregister_ret val_remote_domain_events_deregister_ret;
remote_domain_migrate_prepare2_ret val_remote_domain_migrate_prepare2_ret;
remote_domain_migrate_finish2_ret val_remote_domain_migrate_finish2_ret;
remote_get_uri_ret val_remote_get_uri_ret;
remote_node_num_of_devices_ret val_remote_node_num_of_devices_ret;
remote_node_list_devices_ret val_remote_node_list_devices_ret;
remote_node_device_lookup_by_name_ret val_remote_node_device_lookup_by_name_ret;
remote_node_device_dump_xml_ret val_remote_node_device_dump_xml_ret;
remote_node_device_get_parent_ret val_remote_node_device_get_parent_ret;
remote_node_device_num_of_caps_ret val_remote_node_device_num_of_caps_ret;
remote_node_device_list_caps_ret val_remote_node_device_list_caps_ret;
remote_domain_get_security_label_ret val_remote_domain_get_security_label_ret;
remote_node_get_security_model_ret val_remote_node_get_security_model_ret;
remote_node_device_create_xml_ret val_remote_node_device_create_xml_ret;
remote_storage_vol_create_xml_from_ret val_remote_storage_vol_create_xml_from_ret;
remote_num_of_interfaces_ret val_remote_num_of_interfaces_ret;
remote_list_interfaces_ret val_remote_list_interfaces_ret;
remote_interface_lookup_by_name_ret val_remote_interface_lookup_by_name_ret;
remote_interface_lookup_by_mac_string_ret val_remote_interface_lookup_by_mac_string_ret;
remote_interface_get_xml_desc_ret val_remote_interface_get_xml_desc_ret;
remote_interface_define_xml_ret val_remote_interface_define_xml_ret;
remote_domain_xml_from_native_ret val_remote_domain_xml_from_native_ret;
remote_domain_xml_to_native_ret val_remote_domain_xml_to_native_ret;
remote_num_of_defined_interfaces_ret val_remote_num_of_defined_interfaces_ret;
remote_list_defined_interfaces_ret val_remote_list_defined_interfaces_ret;
remote_num_of_secrets_ret val_remote_num_of_secrets_ret;
remote_list_secrets_ret val_remote_list_secrets_ret;
remote_secret_lookup_by_uuid_ret val_remote_secret_lookup_by_uuid_ret;
remote_secret_define_xml_ret val_remote_secret_define_xml_ret;
remote_secret_get_xml_desc_ret val_remote_secret_get_xml_desc_ret;
remote_secret_get_value_ret val_remote_secret_get_value_ret;
remote_secret_lookup_by_usage_ret val_remote_secret_lookup_by_usage_ret;
remote_is_secure_ret val_remote_is_secure_ret;
remote_domain_is_active_ret val_remote_domain_is_active_ret;
remote_domain_is_persistent_ret val_remote_domain_is_persistent_ret;
remote_network_is_active_ret val_remote_network_is_active_ret;
remote_network_is_persistent_ret val_remote_network_is_persistent_ret;
remote_storage_pool_is_active_ret val_remote_storage_pool_is_active_ret;
remote_storage_pool_is_persistent_ret val_remote_storage_pool_is_persistent_ret;
remote_interface_is_active_ret val_remote_interface_is_active_ret;
remote_get_lib_version_ret val_remote_get_lib_version_ret;
remote_cpu_compare_ret val_remote_cpu_compare_ret;
remote_domain_memory_stats_ret val_remote_domain_memory_stats_ret;

View File

@@ -1,804 +0,0 @@
/* Automatically generated by remote_generate_stubs.pl.
* Do not edit this file. Any changes you make will be lost.
*/
{ /* (unused) => 0 */
.fn = NULL,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* Open => 1 */
.fn = (dispatch_fn) remoteDispatchOpen,
.args_filter = (xdrproc_t) xdr_remote_open_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* Close => 2 */
.fn = (dispatch_fn) remoteDispatchClose,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* GetType => 3 */
.fn = (dispatch_fn) remoteDispatchGetType,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_get_type_ret,
},
{ /* GetVersion => 4 */
.fn = (dispatch_fn) remoteDispatchGetVersion,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_get_version_ret,
},
{ /* GetMaxVcpus => 5 */
.fn = (dispatch_fn) remoteDispatchGetMaxVcpus,
.args_filter = (xdrproc_t) xdr_remote_get_max_vcpus_args,
.ret_filter = (xdrproc_t) xdr_remote_get_max_vcpus_ret,
},
{ /* NodeGetInfo => 6 */
.fn = (dispatch_fn) remoteDispatchNodeGetInfo,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_node_get_info_ret,
},
{ /* GetCapabilities => 7 */
.fn = (dispatch_fn) remoteDispatchGetCapabilities,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_get_capabilities_ret,
},
{ /* DomainAttachDevice => 8 */
.fn = (dispatch_fn) remoteDispatchDomainAttachDevice,
.args_filter = (xdrproc_t) xdr_remote_domain_attach_device_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainCreate => 9 */
.fn = (dispatch_fn) remoteDispatchDomainCreate,
.args_filter = (xdrproc_t) xdr_remote_domain_create_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainCreateXml => 10 */
.fn = (dispatch_fn) remoteDispatchDomainCreateXml,
.args_filter = (xdrproc_t) xdr_remote_domain_create_xml_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_create_xml_ret,
},
{ /* DomainDefineXml => 11 */
.fn = (dispatch_fn) remoteDispatchDomainDefineXml,
.args_filter = (xdrproc_t) xdr_remote_domain_define_xml_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_define_xml_ret,
},
{ /* DomainDestroy => 12 */
.fn = (dispatch_fn) remoteDispatchDomainDestroy,
.args_filter = (xdrproc_t) xdr_remote_domain_destroy_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainDetachDevice => 13 */
.fn = (dispatch_fn) remoteDispatchDomainDetachDevice,
.args_filter = (xdrproc_t) xdr_remote_domain_detach_device_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainDumpXml => 14 */
.fn = (dispatch_fn) remoteDispatchDomainDumpXml,
.args_filter = (xdrproc_t) xdr_remote_domain_dump_xml_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_dump_xml_ret,
},
{ /* DomainGetAutostart => 15 */
.fn = (dispatch_fn) remoteDispatchDomainGetAutostart,
.args_filter = (xdrproc_t) xdr_remote_domain_get_autostart_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_get_autostart_ret,
},
{ /* DomainGetInfo => 16 */
.fn = (dispatch_fn) remoteDispatchDomainGetInfo,
.args_filter = (xdrproc_t) xdr_remote_domain_get_info_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_get_info_ret,
},
{ /* DomainGetMaxMemory => 17 */
.fn = (dispatch_fn) remoteDispatchDomainGetMaxMemory,
.args_filter = (xdrproc_t) xdr_remote_domain_get_max_memory_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_get_max_memory_ret,
},
{ /* DomainGetMaxVcpus => 18 */
.fn = (dispatch_fn) remoteDispatchDomainGetMaxVcpus,
.args_filter = (xdrproc_t) xdr_remote_domain_get_max_vcpus_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_get_max_vcpus_ret,
},
{ /* DomainGetOsType => 19 */
.fn = (dispatch_fn) remoteDispatchDomainGetOsType,
.args_filter = (xdrproc_t) xdr_remote_domain_get_os_type_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_get_os_type_ret,
},
{ /* DomainGetVcpus => 20 */
.fn = (dispatch_fn) remoteDispatchDomainGetVcpus,
.args_filter = (xdrproc_t) xdr_remote_domain_get_vcpus_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_get_vcpus_ret,
},
{ /* ListDefinedDomains => 21 */
.fn = (dispatch_fn) remoteDispatchListDefinedDomains,
.args_filter = (xdrproc_t) xdr_remote_list_defined_domains_args,
.ret_filter = (xdrproc_t) xdr_remote_list_defined_domains_ret,
},
{ /* DomainLookupById => 22 */
.fn = (dispatch_fn) remoteDispatchDomainLookupById,
.args_filter = (xdrproc_t) xdr_remote_domain_lookup_by_id_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_lookup_by_id_ret,
},
{ /* DomainLookupByName => 23 */
.fn = (dispatch_fn) remoteDispatchDomainLookupByName,
.args_filter = (xdrproc_t) xdr_remote_domain_lookup_by_name_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_lookup_by_name_ret,
},
{ /* DomainLookupByUuid => 24 */
.fn = (dispatch_fn) remoteDispatchDomainLookupByUuid,
.args_filter = (xdrproc_t) xdr_remote_domain_lookup_by_uuid_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_lookup_by_uuid_ret,
},
{ /* NumOfDefinedDomains => 25 */
.fn = (dispatch_fn) remoteDispatchNumOfDefinedDomains,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_num_of_defined_domains_ret,
},
{ /* DomainPinVcpu => 26 */
.fn = (dispatch_fn) remoteDispatchDomainPinVcpu,
.args_filter = (xdrproc_t) xdr_remote_domain_pin_vcpu_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainReboot => 27 */
.fn = (dispatch_fn) remoteDispatchDomainReboot,
.args_filter = (xdrproc_t) xdr_remote_domain_reboot_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainResume => 28 */
.fn = (dispatch_fn) remoteDispatchDomainResume,
.args_filter = (xdrproc_t) xdr_remote_domain_resume_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainSetAutostart => 29 */
.fn = (dispatch_fn) remoteDispatchDomainSetAutostart,
.args_filter = (xdrproc_t) xdr_remote_domain_set_autostart_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainSetMaxMemory => 30 */
.fn = (dispatch_fn) remoteDispatchDomainSetMaxMemory,
.args_filter = (xdrproc_t) xdr_remote_domain_set_max_memory_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainSetMemory => 31 */
.fn = (dispatch_fn) remoteDispatchDomainSetMemory,
.args_filter = (xdrproc_t) xdr_remote_domain_set_memory_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainSetVcpus => 32 */
.fn = (dispatch_fn) remoteDispatchDomainSetVcpus,
.args_filter = (xdrproc_t) xdr_remote_domain_set_vcpus_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainShutdown => 33 */
.fn = (dispatch_fn) remoteDispatchDomainShutdown,
.args_filter = (xdrproc_t) xdr_remote_domain_shutdown_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainSuspend => 34 */
.fn = (dispatch_fn) remoteDispatchDomainSuspend,
.args_filter = (xdrproc_t) xdr_remote_domain_suspend_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainUndefine => 35 */
.fn = (dispatch_fn) remoteDispatchDomainUndefine,
.args_filter = (xdrproc_t) xdr_remote_domain_undefine_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* ListDefinedNetworks => 36 */
.fn = (dispatch_fn) remoteDispatchListDefinedNetworks,
.args_filter = (xdrproc_t) xdr_remote_list_defined_networks_args,
.ret_filter = (xdrproc_t) xdr_remote_list_defined_networks_ret,
},
{ /* ListDomains => 37 */
.fn = (dispatch_fn) remoteDispatchListDomains,
.args_filter = (xdrproc_t) xdr_remote_list_domains_args,
.ret_filter = (xdrproc_t) xdr_remote_list_domains_ret,
},
{ /* ListNetworks => 38 */
.fn = (dispatch_fn) remoteDispatchListNetworks,
.args_filter = (xdrproc_t) xdr_remote_list_networks_args,
.ret_filter = (xdrproc_t) xdr_remote_list_networks_ret,
},
{ /* NetworkCreate => 39 */
.fn = (dispatch_fn) remoteDispatchNetworkCreate,
.args_filter = (xdrproc_t) xdr_remote_network_create_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* NetworkCreateXml => 40 */
.fn = (dispatch_fn) remoteDispatchNetworkCreateXml,
.args_filter = (xdrproc_t) xdr_remote_network_create_xml_args,
.ret_filter = (xdrproc_t) xdr_remote_network_create_xml_ret,
},
{ /* NetworkDefineXml => 41 */
.fn = (dispatch_fn) remoteDispatchNetworkDefineXml,
.args_filter = (xdrproc_t) xdr_remote_network_define_xml_args,
.ret_filter = (xdrproc_t) xdr_remote_network_define_xml_ret,
},
{ /* NetworkDestroy => 42 */
.fn = (dispatch_fn) remoteDispatchNetworkDestroy,
.args_filter = (xdrproc_t) xdr_remote_network_destroy_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* NetworkDumpXml => 43 */
.fn = (dispatch_fn) remoteDispatchNetworkDumpXml,
.args_filter = (xdrproc_t) xdr_remote_network_dump_xml_args,
.ret_filter = (xdrproc_t) xdr_remote_network_dump_xml_ret,
},
{ /* NetworkGetAutostart => 44 */
.fn = (dispatch_fn) remoteDispatchNetworkGetAutostart,
.args_filter = (xdrproc_t) xdr_remote_network_get_autostart_args,
.ret_filter = (xdrproc_t) xdr_remote_network_get_autostart_ret,
},
{ /* NetworkGetBridgeName => 45 */
.fn = (dispatch_fn) remoteDispatchNetworkGetBridgeName,
.args_filter = (xdrproc_t) xdr_remote_network_get_bridge_name_args,
.ret_filter = (xdrproc_t) xdr_remote_network_get_bridge_name_ret,
},
{ /* NetworkLookupByName => 46 */
.fn = (dispatch_fn) remoteDispatchNetworkLookupByName,
.args_filter = (xdrproc_t) xdr_remote_network_lookup_by_name_args,
.ret_filter = (xdrproc_t) xdr_remote_network_lookup_by_name_ret,
},
{ /* NetworkLookupByUuid => 47 */
.fn = (dispatch_fn) remoteDispatchNetworkLookupByUuid,
.args_filter = (xdrproc_t) xdr_remote_network_lookup_by_uuid_args,
.ret_filter = (xdrproc_t) xdr_remote_network_lookup_by_uuid_ret,
},
{ /* NetworkSetAutostart => 48 */
.fn = (dispatch_fn) remoteDispatchNetworkSetAutostart,
.args_filter = (xdrproc_t) xdr_remote_network_set_autostart_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* NetworkUndefine => 49 */
.fn = (dispatch_fn) remoteDispatchNetworkUndefine,
.args_filter = (xdrproc_t) xdr_remote_network_undefine_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* NumOfDefinedNetworks => 50 */
.fn = (dispatch_fn) remoteDispatchNumOfDefinedNetworks,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_num_of_defined_networks_ret,
},
{ /* NumOfDomains => 51 */
.fn = (dispatch_fn) remoteDispatchNumOfDomains,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_num_of_domains_ret,
},
{ /* NumOfNetworks => 52 */
.fn = (dispatch_fn) remoteDispatchNumOfNetworks,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_num_of_networks_ret,
},
{ /* DomainCoreDump => 53 */
.fn = (dispatch_fn) remoteDispatchDomainCoreDump,
.args_filter = (xdrproc_t) xdr_remote_domain_core_dump_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainRestore => 54 */
.fn = (dispatch_fn) remoteDispatchDomainRestore,
.args_filter = (xdrproc_t) xdr_remote_domain_restore_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainSave => 55 */
.fn = (dispatch_fn) remoteDispatchDomainSave,
.args_filter = (xdrproc_t) xdr_remote_domain_save_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainGetSchedulerType => 56 */
.fn = (dispatch_fn) remoteDispatchDomainGetSchedulerType,
.args_filter = (xdrproc_t) xdr_remote_domain_get_scheduler_type_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_get_scheduler_type_ret,
},
{ /* DomainGetSchedulerParameters => 57 */
.fn = (dispatch_fn) remoteDispatchDomainGetSchedulerParameters,
.args_filter = (xdrproc_t) xdr_remote_domain_get_scheduler_parameters_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_get_scheduler_parameters_ret,
},
{ /* DomainSetSchedulerParameters => 58 */
.fn = (dispatch_fn) remoteDispatchDomainSetSchedulerParameters,
.args_filter = (xdrproc_t) xdr_remote_domain_set_scheduler_parameters_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* GetHostname => 59 */
.fn = (dispatch_fn) remoteDispatchGetHostname,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_get_hostname_ret,
},
{ /* SupportsFeature => 60 */
.fn = (dispatch_fn) remoteDispatchSupportsFeature,
.args_filter = (xdrproc_t) xdr_remote_supports_feature_args,
.ret_filter = (xdrproc_t) xdr_remote_supports_feature_ret,
},
{ /* DomainMigratePrepare => 61 */
.fn = (dispatch_fn) remoteDispatchDomainMigratePrepare,
.args_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare_ret,
},
{ /* DomainMigratePerform => 62 */
.fn = (dispatch_fn) remoteDispatchDomainMigratePerform,
.args_filter = (xdrproc_t) xdr_remote_domain_migrate_perform_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainMigrateFinish => 63 */
.fn = (dispatch_fn) remoteDispatchDomainMigrateFinish,
.args_filter = (xdrproc_t) xdr_remote_domain_migrate_finish_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_migrate_finish_ret,
},
{ /* DomainBlockStats => 64 */
.fn = (dispatch_fn) remoteDispatchDomainBlockStats,
.args_filter = (xdrproc_t) xdr_remote_domain_block_stats_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_block_stats_ret,
},
{ /* DomainInterfaceStats => 65 */
.fn = (dispatch_fn) remoteDispatchDomainInterfaceStats,
.args_filter = (xdrproc_t) xdr_remote_domain_interface_stats_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_interface_stats_ret,
},
{ /* AuthList => 66 */
.fn = (dispatch_fn) remoteDispatchAuthList,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_auth_list_ret,
},
{ /* AuthSaslInit => 67 */
.fn = (dispatch_fn) remoteDispatchAuthSaslInit,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_auth_sasl_init_ret,
},
{ /* AuthSaslStart => 68 */
.fn = (dispatch_fn) remoteDispatchAuthSaslStart,
.args_filter = (xdrproc_t) xdr_remote_auth_sasl_start_args,
.ret_filter = (xdrproc_t) xdr_remote_auth_sasl_start_ret,
},
{ /* AuthSaslStep => 69 */
.fn = (dispatch_fn) remoteDispatchAuthSaslStep,
.args_filter = (xdrproc_t) xdr_remote_auth_sasl_step_args,
.ret_filter = (xdrproc_t) xdr_remote_auth_sasl_step_ret,
},
{ /* AuthPolkit => 70 */
.fn = (dispatch_fn) remoteDispatchAuthPolkit,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_auth_polkit_ret,
},
{ /* NumOfStoragePools => 71 */
.fn = (dispatch_fn) remoteDispatchNumOfStoragePools,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_num_of_storage_pools_ret,
},
{ /* ListStoragePools => 72 */
.fn = (dispatch_fn) remoteDispatchListStoragePools,
.args_filter = (xdrproc_t) xdr_remote_list_storage_pools_args,
.ret_filter = (xdrproc_t) xdr_remote_list_storage_pools_ret,
},
{ /* NumOfDefinedStoragePools => 73 */
.fn = (dispatch_fn) remoteDispatchNumOfDefinedStoragePools,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_num_of_defined_storage_pools_ret,
},
{ /* ListDefinedStoragePools => 74 */
.fn = (dispatch_fn) remoteDispatchListDefinedStoragePools,
.args_filter = (xdrproc_t) xdr_remote_list_defined_storage_pools_args,
.ret_filter = (xdrproc_t) xdr_remote_list_defined_storage_pools_ret,
},
{ /* FindStoragePoolSources => 75 */
.fn = (dispatch_fn) remoteDispatchFindStoragePoolSources,
.args_filter = (xdrproc_t) xdr_remote_find_storage_pool_sources_args,
.ret_filter = (xdrproc_t) xdr_remote_find_storage_pool_sources_ret,
},
{ /* StoragePoolCreateXml => 76 */
.fn = (dispatch_fn) remoteDispatchStoragePoolCreateXml,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_create_xml_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_pool_create_xml_ret,
},
{ /* StoragePoolDefineXml => 77 */
.fn = (dispatch_fn) remoteDispatchStoragePoolDefineXml,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_define_xml_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_pool_define_xml_ret,
},
{ /* StoragePoolCreate => 78 */
.fn = (dispatch_fn) remoteDispatchStoragePoolCreate,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_create_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* StoragePoolBuild => 79 */
.fn = (dispatch_fn) remoteDispatchStoragePoolBuild,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_build_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* StoragePoolDestroy => 80 */
.fn = (dispatch_fn) remoteDispatchStoragePoolDestroy,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_destroy_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* StoragePoolDelete => 81 */
.fn = (dispatch_fn) remoteDispatchStoragePoolDelete,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_delete_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* StoragePoolUndefine => 82 */
.fn = (dispatch_fn) remoteDispatchStoragePoolUndefine,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_undefine_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* StoragePoolRefresh => 83 */
.fn = (dispatch_fn) remoteDispatchStoragePoolRefresh,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_refresh_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* StoragePoolLookupByName => 84 */
.fn = (dispatch_fn) remoteDispatchStoragePoolLookupByName,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_name_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_name_ret,
},
{ /* StoragePoolLookupByUuid => 85 */
.fn = (dispatch_fn) remoteDispatchStoragePoolLookupByUuid,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_uuid_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_uuid_ret,
},
{ /* StoragePoolLookupByVolume => 86 */
.fn = (dispatch_fn) remoteDispatchStoragePoolLookupByVolume,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_volume_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_volume_ret,
},
{ /* StoragePoolGetInfo => 87 */
.fn = (dispatch_fn) remoteDispatchStoragePoolGetInfo,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_get_info_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_pool_get_info_ret,
},
{ /* StoragePoolDumpXml => 88 */
.fn = (dispatch_fn) remoteDispatchStoragePoolDumpXml,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_dump_xml_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_pool_dump_xml_ret,
},
{ /* StoragePoolGetAutostart => 89 */
.fn = (dispatch_fn) remoteDispatchStoragePoolGetAutostart,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_get_autostart_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_pool_get_autostart_ret,
},
{ /* StoragePoolSetAutostart => 90 */
.fn = (dispatch_fn) remoteDispatchStoragePoolSetAutostart,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_set_autostart_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* StoragePoolNumOfVolumes => 91 */
.fn = (dispatch_fn) remoteDispatchStoragePoolNumOfVolumes,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_num_of_volumes_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_pool_num_of_volumes_ret,
},
{ /* StoragePoolListVolumes => 92 */
.fn = (dispatch_fn) remoteDispatchStoragePoolListVolumes,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_list_volumes_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_pool_list_volumes_ret,
},
{ /* StorageVolCreateXml => 93 */
.fn = (dispatch_fn) remoteDispatchStorageVolCreateXml,
.args_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_ret,
},
{ /* StorageVolDelete => 94 */
.fn = (dispatch_fn) remoteDispatchStorageVolDelete,
.args_filter = (xdrproc_t) xdr_remote_storage_vol_delete_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* StorageVolLookupByName => 95 */
.fn = (dispatch_fn) remoteDispatchStorageVolLookupByName,
.args_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_name_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_name_ret,
},
{ /* StorageVolLookupByKey => 96 */
.fn = (dispatch_fn) remoteDispatchStorageVolLookupByKey,
.args_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_key_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_key_ret,
},
{ /* StorageVolLookupByPath => 97 */
.fn = (dispatch_fn) remoteDispatchStorageVolLookupByPath,
.args_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_path_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_path_ret,
},
{ /* StorageVolGetInfo => 98 */
.fn = (dispatch_fn) remoteDispatchStorageVolGetInfo,
.args_filter = (xdrproc_t) xdr_remote_storage_vol_get_info_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_vol_get_info_ret,
},
{ /* StorageVolDumpXml => 99 */
.fn = (dispatch_fn) remoteDispatchStorageVolDumpXml,
.args_filter = (xdrproc_t) xdr_remote_storage_vol_dump_xml_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_vol_dump_xml_ret,
},
{ /* StorageVolGetPath => 100 */
.fn = (dispatch_fn) remoteDispatchStorageVolGetPath,
.args_filter = (xdrproc_t) xdr_remote_storage_vol_get_path_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_vol_get_path_ret,
},
{ /* NodeGetCellsFreeMemory => 101 */
.fn = (dispatch_fn) remoteDispatchNodeGetCellsFreeMemory,
.args_filter = (xdrproc_t) xdr_remote_node_get_cells_free_memory_args,
.ret_filter = (xdrproc_t) xdr_remote_node_get_cells_free_memory_ret,
},
{ /* NodeGetFreeMemory => 102 */
.fn = (dispatch_fn) remoteDispatchNodeGetFreeMemory,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_node_get_free_memory_ret,
},
{ /* DomainBlockPeek => 103 */
.fn = (dispatch_fn) remoteDispatchDomainBlockPeek,
.args_filter = (xdrproc_t) xdr_remote_domain_block_peek_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_block_peek_ret,
},
{ /* DomainMemoryPeek => 104 */
.fn = (dispatch_fn) remoteDispatchDomainMemoryPeek,
.args_filter = (xdrproc_t) xdr_remote_domain_memory_peek_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_memory_peek_ret,
},
{ /* DomainEventsRegister => 105 */
.fn = (dispatch_fn) remoteDispatchDomainEventsRegister,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_domain_events_register_ret,
},
{ /* DomainEventsDeregister => 106 */
.fn = (dispatch_fn) remoteDispatchDomainEventsDeregister,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_domain_events_deregister_ret,
},
{ /* Async event DomainEvent => 107 */
.fn = NULL,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainMigratePrepare2 => 108 */
.fn = (dispatch_fn) remoteDispatchDomainMigratePrepare2,
.args_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare2_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare2_ret,
},
{ /* DomainMigrateFinish2 => 109 */
.fn = (dispatch_fn) remoteDispatchDomainMigrateFinish2,
.args_filter = (xdrproc_t) xdr_remote_domain_migrate_finish2_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_migrate_finish2_ret,
},
{ /* GetUri => 110 */
.fn = (dispatch_fn) remoteDispatchGetUri,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_get_uri_ret,
},
{ /* NodeNumOfDevices => 111 */
.fn = (dispatch_fn) remoteDispatchNodeNumOfDevices,
.args_filter = (xdrproc_t) xdr_remote_node_num_of_devices_args,
.ret_filter = (xdrproc_t) xdr_remote_node_num_of_devices_ret,
},
{ /* NodeListDevices => 112 */
.fn = (dispatch_fn) remoteDispatchNodeListDevices,
.args_filter = (xdrproc_t) xdr_remote_node_list_devices_args,
.ret_filter = (xdrproc_t) xdr_remote_node_list_devices_ret,
},
{ /* NodeDeviceLookupByName => 113 */
.fn = (dispatch_fn) remoteDispatchNodeDeviceLookupByName,
.args_filter = (xdrproc_t) xdr_remote_node_device_lookup_by_name_args,
.ret_filter = (xdrproc_t) xdr_remote_node_device_lookup_by_name_ret,
},
{ /* NodeDeviceDumpXml => 114 */
.fn = (dispatch_fn) remoteDispatchNodeDeviceDumpXml,
.args_filter = (xdrproc_t) xdr_remote_node_device_dump_xml_args,
.ret_filter = (xdrproc_t) xdr_remote_node_device_dump_xml_ret,
},
{ /* NodeDeviceGetParent => 115 */
.fn = (dispatch_fn) remoteDispatchNodeDeviceGetParent,
.args_filter = (xdrproc_t) xdr_remote_node_device_get_parent_args,
.ret_filter = (xdrproc_t) xdr_remote_node_device_get_parent_ret,
},
{ /* NodeDeviceNumOfCaps => 116 */
.fn = (dispatch_fn) remoteDispatchNodeDeviceNumOfCaps,
.args_filter = (xdrproc_t) xdr_remote_node_device_num_of_caps_args,
.ret_filter = (xdrproc_t) xdr_remote_node_device_num_of_caps_ret,
},
{ /* NodeDeviceListCaps => 117 */
.fn = (dispatch_fn) remoteDispatchNodeDeviceListCaps,
.args_filter = (xdrproc_t) xdr_remote_node_device_list_caps_args,
.ret_filter = (xdrproc_t) xdr_remote_node_device_list_caps_ret,
},
{ /* NodeDeviceDettach => 118 */
.fn = (dispatch_fn) remoteDispatchNodeDeviceDettach,
.args_filter = (xdrproc_t) xdr_remote_node_device_dettach_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* NodeDeviceReAttach => 119 */
.fn = (dispatch_fn) remoteDispatchNodeDeviceReAttach,
.args_filter = (xdrproc_t) xdr_remote_node_device_re_attach_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* NodeDeviceReset => 120 */
.fn = (dispatch_fn) remoteDispatchNodeDeviceReset,
.args_filter = (xdrproc_t) xdr_remote_node_device_reset_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainGetSecurityLabel => 121 */
.fn = (dispatch_fn) remoteDispatchDomainGetSecurityLabel,
.args_filter = (xdrproc_t) xdr_remote_domain_get_security_label_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_get_security_label_ret,
},
{ /* NodeGetSecurityModel => 122 */
.fn = (dispatch_fn) remoteDispatchNodeGetSecurityModel,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_node_get_security_model_ret,
},
{ /* NodeDeviceCreateXml => 123 */
.fn = (dispatch_fn) remoteDispatchNodeDeviceCreateXml,
.args_filter = (xdrproc_t) xdr_remote_node_device_create_xml_args,
.ret_filter = (xdrproc_t) xdr_remote_node_device_create_xml_ret,
},
{ /* NodeDeviceDestroy => 124 */
.fn = (dispatch_fn) remoteDispatchNodeDeviceDestroy,
.args_filter = (xdrproc_t) xdr_remote_node_device_destroy_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* StorageVolCreateXmlFrom => 125 */
.fn = (dispatch_fn) remoteDispatchStorageVolCreateXmlFrom,
.args_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_from_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_from_ret,
},
{ /* NumOfInterfaces => 126 */
.fn = (dispatch_fn) remoteDispatchNumOfInterfaces,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_num_of_interfaces_ret,
},
{ /* ListInterfaces => 127 */
.fn = (dispatch_fn) remoteDispatchListInterfaces,
.args_filter = (xdrproc_t) xdr_remote_list_interfaces_args,
.ret_filter = (xdrproc_t) xdr_remote_list_interfaces_ret,
},
{ /* InterfaceLookupByName => 128 */
.fn = (dispatch_fn) remoteDispatchInterfaceLookupByName,
.args_filter = (xdrproc_t) xdr_remote_interface_lookup_by_name_args,
.ret_filter = (xdrproc_t) xdr_remote_interface_lookup_by_name_ret,
},
{ /* InterfaceLookupByMacString => 129 */
.fn = (dispatch_fn) remoteDispatchInterfaceLookupByMacString,
.args_filter = (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_args,
.ret_filter = (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_ret,
},
{ /* InterfaceGetXmlDesc => 130 */
.fn = (dispatch_fn) remoteDispatchInterfaceGetXmlDesc,
.args_filter = (xdrproc_t) xdr_remote_interface_get_xml_desc_args,
.ret_filter = (xdrproc_t) xdr_remote_interface_get_xml_desc_ret,
},
{ /* InterfaceDefineXml => 131 */
.fn = (dispatch_fn) remoteDispatchInterfaceDefineXml,
.args_filter = (xdrproc_t) xdr_remote_interface_define_xml_args,
.ret_filter = (xdrproc_t) xdr_remote_interface_define_xml_ret,
},
{ /* InterfaceUndefine => 132 */
.fn = (dispatch_fn) remoteDispatchInterfaceUndefine,
.args_filter = (xdrproc_t) xdr_remote_interface_undefine_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* InterfaceCreate => 133 */
.fn = (dispatch_fn) remoteDispatchInterfaceCreate,
.args_filter = (xdrproc_t) xdr_remote_interface_create_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* InterfaceDestroy => 134 */
.fn = (dispatch_fn) remoteDispatchInterfaceDestroy,
.args_filter = (xdrproc_t) xdr_remote_interface_destroy_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* DomainXmlFromNative => 135 */
.fn = (dispatch_fn) remoteDispatchDomainXmlFromNative,
.args_filter = (xdrproc_t) xdr_remote_domain_xml_from_native_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_xml_from_native_ret,
},
{ /* DomainXmlToNative => 136 */
.fn = (dispatch_fn) remoteDispatchDomainXmlToNative,
.args_filter = (xdrproc_t) xdr_remote_domain_xml_to_native_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_xml_to_native_ret,
},
{ /* NumOfDefinedInterfaces => 137 */
.fn = (dispatch_fn) remoteDispatchNumOfDefinedInterfaces,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_num_of_defined_interfaces_ret,
},
{ /* ListDefinedInterfaces => 138 */
.fn = (dispatch_fn) remoteDispatchListDefinedInterfaces,
.args_filter = (xdrproc_t) xdr_remote_list_defined_interfaces_args,
.ret_filter = (xdrproc_t) xdr_remote_list_defined_interfaces_ret,
},
{ /* NumOfSecrets => 139 */
.fn = (dispatch_fn) remoteDispatchNumOfSecrets,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_num_of_secrets_ret,
},
{ /* ListSecrets => 140 */
.fn = (dispatch_fn) remoteDispatchListSecrets,
.args_filter = (xdrproc_t) xdr_remote_list_secrets_args,
.ret_filter = (xdrproc_t) xdr_remote_list_secrets_ret,
},
{ /* SecretLookupByUuid => 141 */
.fn = (dispatch_fn) remoteDispatchSecretLookupByUuid,
.args_filter = (xdrproc_t) xdr_remote_secret_lookup_by_uuid_args,
.ret_filter = (xdrproc_t) xdr_remote_secret_lookup_by_uuid_ret,
},
{ /* SecretDefineXml => 142 */
.fn = (dispatch_fn) remoteDispatchSecretDefineXml,
.args_filter = (xdrproc_t) xdr_remote_secret_define_xml_args,
.ret_filter = (xdrproc_t) xdr_remote_secret_define_xml_ret,
},
{ /* SecretGetXmlDesc => 143 */
.fn = (dispatch_fn) remoteDispatchSecretGetXmlDesc,
.args_filter = (xdrproc_t) xdr_remote_secret_get_xml_desc_args,
.ret_filter = (xdrproc_t) xdr_remote_secret_get_xml_desc_ret,
},
{ /* SecretSetValue => 144 */
.fn = (dispatch_fn) remoteDispatchSecretSetValue,
.args_filter = (xdrproc_t) xdr_remote_secret_set_value_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* SecretGetValue => 145 */
.fn = (dispatch_fn) remoteDispatchSecretGetValue,
.args_filter = (xdrproc_t) xdr_remote_secret_get_value_args,
.ret_filter = (xdrproc_t) xdr_remote_secret_get_value_ret,
},
{ /* SecretUndefine => 146 */
.fn = (dispatch_fn) remoteDispatchSecretUndefine,
.args_filter = (xdrproc_t) xdr_remote_secret_undefine_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* SecretLookupByUsage => 147 */
.fn = (dispatch_fn) remoteDispatchSecretLookupByUsage,
.args_filter = (xdrproc_t) xdr_remote_secret_lookup_by_usage_args,
.ret_filter = (xdrproc_t) xdr_remote_secret_lookup_by_usage_ret,
},
{ /* DomainMigratePrepareTunnel => 148 */
.fn = (dispatch_fn) remoteDispatchDomainMigratePrepareTunnel,
.args_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare_tunnel_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* IsSecure => 149 */
.fn = (dispatch_fn) remoteDispatchIsSecure,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_is_secure_ret,
},
{ /* DomainIsActive => 150 */
.fn = (dispatch_fn) remoteDispatchDomainIsActive,
.args_filter = (xdrproc_t) xdr_remote_domain_is_active_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_is_active_ret,
},
{ /* DomainIsPersistent => 151 */
.fn = (dispatch_fn) remoteDispatchDomainIsPersistent,
.args_filter = (xdrproc_t) xdr_remote_domain_is_persistent_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_is_persistent_ret,
},
{ /* NetworkIsActive => 152 */
.fn = (dispatch_fn) remoteDispatchNetworkIsActive,
.args_filter = (xdrproc_t) xdr_remote_network_is_active_args,
.ret_filter = (xdrproc_t) xdr_remote_network_is_active_ret,
},
{ /* NetworkIsPersistent => 153 */
.fn = (dispatch_fn) remoteDispatchNetworkIsPersistent,
.args_filter = (xdrproc_t) xdr_remote_network_is_persistent_args,
.ret_filter = (xdrproc_t) xdr_remote_network_is_persistent_ret,
},
{ /* StoragePoolIsActive => 154 */
.fn = (dispatch_fn) remoteDispatchStoragePoolIsActive,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_is_active_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_pool_is_active_ret,
},
{ /* StoragePoolIsPersistent => 155 */
.fn = (dispatch_fn) remoteDispatchStoragePoolIsPersistent,
.args_filter = (xdrproc_t) xdr_remote_storage_pool_is_persistent_args,
.ret_filter = (xdrproc_t) xdr_remote_storage_pool_is_persistent_ret,
},
{ /* InterfaceIsActive => 156 */
.fn = (dispatch_fn) remoteDispatchInterfaceIsActive,
.args_filter = (xdrproc_t) xdr_remote_interface_is_active_args,
.ret_filter = (xdrproc_t) xdr_remote_interface_is_active_ret,
},
{ /* GetLibVersion => 157 */
.fn = (dispatch_fn) remoteDispatchGetLibVersion,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_remote_get_lib_version_ret,
},
{ /* CpuCompare => 158 */
.fn = (dispatch_fn) remoteDispatchCpuCompare,
.args_filter = (xdrproc_t) xdr_remote_cpu_compare_args,
.ret_filter = (xdrproc_t) xdr_remote_cpu_compare_ret,
},
{ /* DomainMemoryStats => 159 */
.fn = (dispatch_fn) remoteDispatchDomainMemoryStats,
.args_filter = (xdrproc_t) xdr_remote_domain_memory_stats_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_memory_stats_ret,
},

View File

@@ -1,179 +0,0 @@
#!/usr/bin/perl -w
#
# This script parses remote_protocol.x and produces lots of boilerplate
# code for both ends of the remote connection.
#
# By Richard Jones <rjones@redhat.com>
use strict;
use Getopt::Std;
# Command line options.
our ($opt_p, $opt_t, $opt_a, $opt_r, $opt_d);
getopts ('ptard');
# Convert name_of_call to NameOfCall.
sub name_to_ProcName {
my $name = shift;
my @elems = split /_/, $name;
@elems = map ucfirst, @elems;
join "", @elems
}
# Read the input file (usually remote_protocol.x) and form an
# opinion about the name, args and return type of each RPC.
my ($name, $ProcName, $id, %calls, @calls);
# REMOTE_PROC_CLOSE has no args or ret.
$calls{close} = {
name => "close",
ProcName => "Close",
UC_NAME => "CLOSE",
args => "void",
ret => "void",
};
while (<>) {
if (/^struct remote_(.*)_args/) {
$name = $1;
$ProcName = name_to_ProcName ($name);
die "duplicate definition of remote_${name}_args"
if exists $calls{$name};
$calls{$name} = {
name => $name,
ProcName => $ProcName,
UC_NAME => uc $name,
args => "remote_${name}_args",
ret => "void",
};
} elsif (/^struct remote_(.*)_ret/) {
$name = $1;
$ProcName = name_to_ProcName ($name);
if (exists $calls{$name}) {
$calls{$name}->{ret} = "remote_${name}_ret";
} else {
$calls{$name} = {
name => $name,
ProcName => $ProcName,
UC_NAME => uc $name,
args => "void",
ret => "remote_${name}_ret"
}
}
} elsif (/^struct remote_(.*)_msg/) {
$name = $1;
$ProcName = name_to_ProcName ($name);
$calls{$name} = {
name => $name,
ProcName => $ProcName,
UC_NAME => uc $name,
msg => "remote_${name}_msg"
}
} elsif (/^\s*REMOTE_PROC_(.*?)\s+=\s+(\d+),?$/) {
$name = lc $1;
$id = $2;
$ProcName = name_to_ProcName ($name);
$calls[$id] = $calls{$name};
}
}
#----------------------------------------------------------------------
# Output
print <<__EOF__;
/* Automatically generated by remote_generate_stubs.pl.
* Do not edit this file. Any changes you make will be lost.
*/
__EOF__
# Debugging.
if ($opt_d) {
my @keys = sort (keys %calls);
foreach (@keys) {
print "$_:\n";
print " name $calls{$_}->{name} ($calls{$_}->{ProcName})\n";
print " $calls{$_}->{args} -> $calls{$_}->{ret}\n";
}
}
# Prototypes for dispatch functions ("remote_dispatch_prototypes.h").
elsif ($opt_p) {
my @keys = sort (keys %calls);
foreach (@keys) {
# Skip things which are REMOTE_MESSAGE
next if $calls{$_}->{msg};
print "static int remoteDispatch$calls{$_}->{ProcName}(\n";
print " struct qemud_server *server,\n";
print " struct qemud_client *client,\n";
print " virConnectPtr conn,\n";
print " remote_message_header *hdr,\n";
print " remote_error *err,\n";
print " $calls{$_}->{args} *args,\n";
print " $calls{$_}->{ret} *ret);\n";
}
}
# Union of all arg types
# ("remote_dispatch_args.h").
elsif ($opt_a) {
for ($id = 0 ; $id <= $#calls ; $id++) {
if (defined $calls[$id] &&
!$calls[$id]->{msg} &&
$calls[$id]->{args} ne "void") {
print " $calls[$id]->{args} val_$calls[$id]->{args};\n";
}
}
}
# Union of all arg types
# ("remote_dispatch_ret.h").
elsif ($opt_r) {
for ($id = 0 ; $id <= $#calls ; $id++) {
if (defined $calls[$id] &&
!$calls[$id]->{msg} &&
$calls[$id]->{ret} ne "void") {
print " $calls[$id]->{ret} val_$calls[$id]->{ret};\n";
}
}
}
# Inside the switch statement, prepare the 'fn', 'args_filter', etc
# ("remote_dispatch_table.h").
elsif ($opt_t) {
for ($id = 0 ; $id <= $#calls ; $id++) {
if (defined $calls[$id] && !$calls[$id]->{msg}) {
print "{ /* $calls[$id]->{ProcName} => $id */\n";
print " .fn = (dispatch_fn) remoteDispatch$calls[$id]->{ProcName},\n";
if ($calls[$id]->{args} ne "void") {
print " .args_filter = (xdrproc_t) xdr_$calls[$id]->{args},\n";
} else {
print " .args_filter = (xdrproc_t) xdr_void,\n";
}
if ($calls[$id]->{ret} ne "void") {
print " .ret_filter = (xdrproc_t) xdr_$calls[$id]->{ret},\n";
} else {
print " .ret_filter = (xdrproc_t) xdr_void,\n";
}
print "},\n";
} else {
if ($calls[$id]->{msg}) {
print "{ /* Async event $calls[$id]->{ProcName} => $id */\n";
} else {
print "{ /* (unused) => $id */\n";
}
print " .fn = NULL,\n";
print " .args_filter = (xdrproc_t) xdr_void,\n";
print " .ret_filter = (xdrproc_t) xdr_void,\n";
print "},\n";
}
}
}

View File

@@ -1,607 +0,0 @@
/*
* stream.c: APIs for managing client streams
*
* Copyright (C) 2009 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#include <config.h>
#include "stream.h"
#include "memory.h"
#include "dispatch.h"
#include "logging.h"
static int
remoteStreamHandleWrite(struct qemud_client *client,
struct qemud_client_stream *stream);
static int
remoteStreamHandleRead(struct qemud_client *client,
struct qemud_client_stream *stream);
static int
remoteStreamHandleFinish(struct qemud_client *client,
struct qemud_client_stream *stream,
struct qemud_client_message *msg);
static int
remoteStreamHandleAbort(struct qemud_client *client,
struct qemud_client_stream *stream,
struct qemud_client_message *msg);
static void
remoteStreamUpdateEvents(struct qemud_client_stream *stream)
{
int newEvents = 0;
if (stream->rx)
newEvents |= VIR_STREAM_EVENT_WRITABLE;
if (stream->tx && !stream->recvEOF)
newEvents |= VIR_STREAM_EVENT_READABLE;
virStreamEventUpdateCallback(stream->st, newEvents);
}
/*
* Callback that gets invoked when a stream becomes writable/readable
*/
static void
remoteStreamEvent(virStreamPtr st, int events, void *opaque)
{
struct qemud_client *client = opaque;
struct qemud_client_stream *stream;
/* XXX sub-optimal - we really should be taking the server lock
* first, but we have no handle to the server object
* We're lucky to get away with it for now, due to this callback
* executing in the main thread, but this should really be fixed
*/
virMutexLock(&client->lock);
stream = remoteFindClientStream(client, st);
if (!stream) {
VIR_WARN("event for client=%p stream st=%p, but missing stream state", client, st);
virStreamEventRemoveCallback(st);
goto cleanup;
}
DEBUG("st=%p events=%d", st, events);
if (events & VIR_STREAM_EVENT_WRITABLE) {
if (remoteStreamHandleWrite(client, stream) < 0) {
remoteRemoveClientStream(client, stream);
qemudDispatchClientFailure(client);
goto cleanup;
}
}
if (!stream->recvEOF &&
(events & (VIR_STREAM_EVENT_READABLE | VIR_STREAM_EVENT_HANGUP))) {
events = events & ~(VIR_STREAM_EVENT_READABLE | VIR_STREAM_EVENT_HANGUP);
if (remoteStreamHandleRead(client, stream) < 0) {
remoteRemoveClientStream(client, stream);
qemudDispatchClientFailure(client);
goto cleanup;
}
}
if (!stream->closed &&
(events & (VIR_STREAM_EVENT_ERROR | VIR_STREAM_EVENT_HANGUP))) {
int ret;
remote_error rerr;
memset(&rerr, 0, sizeof rerr);
stream->closed = 1;
virStreamAbort(stream->st);
if (events & VIR_STREAM_EVENT_HANGUP)
remoteDispatchFormatError(&rerr, "%s", _("stream had unexpected termination"));
else
remoteDispatchFormatError(&rerr, "%s", _("stream had I/O failure"));
ret = remoteSerializeStreamError(client, &rerr, stream->procedure, stream->serial);
remoteRemoveClientStream(client, stream);
if (ret < 0)
qemudDispatchClientFailure(client);
goto cleanup;
}
if (stream->closed) {
remoteRemoveClientStream(client, stream);
} else {
remoteStreamUpdateEvents(stream);
}
cleanup:
virMutexUnlock(&client->lock);
}
/*
* @client: a locked client object
*
* Invoked by the main loop when filtering incoming messages.
*
* Returns 1 if the message was processed, 0 if skipped,
* -1 on fatal client error
*/
static int
remoteStreamFilter(struct qemud_client *client,
struct qemud_client_message *msg, void *opaque)
{
struct qemud_client_stream *stream = opaque;
if (msg->hdr.serial == stream->serial &&
msg->hdr.proc == stream->procedure &&
msg->hdr.type == REMOTE_STREAM) {
DEBUG("Incoming rx=%p serial=%d proc=%d status=%d",
stream->rx, msg->hdr.proc, msg->hdr.serial, msg->hdr.status);
/* If there are queued packets, we need to queue all further
* messages, since they must be processed strictly in order.
* If there are no queued packets, then OK/ERROR messages
* should be processed immediately. Data packets are still
* queued to only be processed when the stream is marked as
* writable.
*/
if (stream->rx) {
qemudClientMessageQueuePush(&stream->rx, msg);
remoteStreamUpdateEvents(stream);
} else {
int ret = 0;
switch (msg->hdr.status) {
case REMOTE_OK:
ret = remoteStreamHandleFinish(client, stream, msg);
if (ret == 0)
qemudClientMessageRelease(client, msg);
break;
case REMOTE_CONTINUE:
qemudClientMessageQueuePush(&stream->rx, msg);
remoteStreamUpdateEvents(stream);
break;
case REMOTE_ERROR:
default:
ret = remoteStreamHandleAbort(client, stream, msg);
if (ret == 0)
qemudClientMessageRelease(client, msg);
break;
}
if (ret < 0)
return -1;
}
return 1;
}
return 0;
}
/*
* @conn: a connection object to associate the stream with
* @hdr: the method call to associate with the stram
*
* Creates a new stream for this conn
*
* Returns a new stream object, or NULL upon OOM
*/
struct qemud_client_stream *
remoteCreateClientStream(virConnectPtr conn,
remote_message_header *hdr)
{
struct qemud_client_stream *stream;
DEBUG("proc=%d serial=%d", hdr->proc, hdr->serial);
if (VIR_ALLOC(stream) < 0)
return NULL;
stream->procedure = hdr->proc;
stream->serial = hdr->serial;
stream->st = virStreamNew(conn, VIR_STREAM_NONBLOCK);
if (!stream->st) {
VIR_FREE(stream);
return NULL;
}
stream->filter.query = remoteStreamFilter;
stream->filter.opaque = stream;
return stream;
}
/*
* @stream: an unused client stream
*
* Frees the memory associated with this inactive client
* stream
*/
void remoteFreeClientStream(struct qemud_client *client,
struct qemud_client_stream *stream)
{
struct qemud_client_message *msg;
if (!stream)
return;
DEBUG("proc=%d serial=%d", stream->procedure, stream->serial);
msg = stream->rx;
while (msg) {
struct qemud_client_message *tmp = msg->next;
qemudClientMessageRelease(client, msg);
msg = tmp;
}
virStreamFree(stream->st);
VIR_FREE(stream);
}
/*
* @client: a locked client to add the stream to
* @stream: a stream to add
*/
int remoteAddClientStream(struct qemud_client *client,
struct qemud_client_stream *stream,
int transmit)
{
struct qemud_client_stream *tmp = client->streams;
DEBUG("client=%p proc=%d serial=%d", client, stream->procedure, stream->serial);
if (virStreamEventAddCallback(stream->st, 0,
remoteStreamEvent, client, NULL) < 0)
return -1;
if (tmp) {
while (tmp->next)
tmp = tmp->next;
tmp->next = stream;
} else {
client->streams = stream;
}
stream->filter.next = client->filters;
client->filters = &stream->filter;
if (transmit)
stream->tx = 1;
remoteStreamUpdateEvents(stream);
return 0;
}
/*
* @client: a locked client object
* @procedure: procedure associated with the stream
* @serial: serial number associated with the stream
*
* Finds a existing active stream
*
* Returns a stream object matching the procedure+serial number, or NULL
*/
struct qemud_client_stream *
remoteFindClientStream(struct qemud_client *client,
virStreamPtr st)
{
struct qemud_client_stream *stream = client->streams;
while (stream) {
if (stream->st == st)
return stream;
stream = stream->next;
}
return NULL;
}
/*
* @client: a locked client object
* @stream: an inactive, closed stream object
*
* Removes a stream from the list of active streams for the client
*
* Returns 0 if the stream was removd, -1 if it doesn't exist
*/
int
remoteRemoveClientStream(struct qemud_client *client,
struct qemud_client_stream *stream)
{
DEBUG("client=%p proc=%d serial=%d", client, stream->procedure, stream->serial);
struct qemud_client_stream *curr = client->streams;
struct qemud_client_stream *prev = NULL;
struct qemud_client_filter *filter = NULL;
if (client->filters == &stream->filter) {
client->filters = client->filters->next;
} else {
filter = client->filters;
while (filter) {
if (filter->next == &stream->filter) {
filter->next = filter->next->next;
break;
}
}
}
if (!stream->closed)
virStreamAbort(stream->st);
while (curr) {
if (curr == stream) {
if (prev)
prev->next = curr->next;
else
client->streams = curr->next;
remoteFreeClientStream(client, stream);
return 0;
}
prev = curr;
curr = curr->next;
}
return -1;
}
/*
* Returns:
* -1 if fatal error occurred
* 0 if message was fully processed
* 1 if message is still being processed
*/
static int
remoteStreamHandleWriteData(struct qemud_client *client,
struct qemud_client_stream *stream,
struct qemud_client_message *msg)
{
remote_error rerr;
int ret;
DEBUG("stream=%p proc=%d serial=%d len=%d offset=%d",
stream, msg->hdr.proc, msg->hdr.serial, msg->bufferLength, msg->bufferOffset);
memset(&rerr, 0, sizeof rerr);
ret = virStreamSend(stream->st,
msg->buffer + msg->bufferOffset,
msg->bufferLength - msg->bufferOffset);
if (ret > 0) {
msg->bufferOffset += ret;
/* Partial write, so indicate we have more todo later */
if (msg->bufferOffset < msg->bufferLength)
return 1;
} else if (ret == -2) {
/* Blocking, so indicate we have more todo later */
return 1;
} else {
VIR_INFO0("Stream send failed");
stream->closed = 1;
remoteDispatchConnError(&rerr, client->conn);
return remoteSerializeReplyError(client, &rerr, &msg->hdr);
}
return 0;
}
/*
* Process an finish handshake from the client.
*
* Returns a REMOTE_OK confirmation if successful, or a REMOTE_ERROR
* if there was a stream error
*
* Returns 0 if successfully sent RPC reply, -1 upon fatal error
*/
static int
remoteStreamHandleFinish(struct qemud_client *client,
struct qemud_client_stream *stream,
struct qemud_client_message *msg)
{
remote_error rerr;
int ret;
DEBUG("stream=%p proc=%d serial=%d",
stream, msg->hdr.proc, msg->hdr.serial);
memset(&rerr, 0, sizeof rerr);
stream->closed = 1;
ret = virStreamFinish(stream->st);
if (ret < 0) {
remoteDispatchConnError(&rerr, client->conn);
return remoteSerializeReplyError(client, &rerr, &msg->hdr);
} else {
/* Send zero-length confirm */
if (remoteSendStreamData(client, stream, NULL, 0) < 0)
return -1;
}
return 0;
}
/*
* Process an abort request from the client.
*
* Returns 0 if successfully aborted, -1 upon error
*/
static int
remoteStreamHandleAbort(struct qemud_client *client,
struct qemud_client_stream *stream,
struct qemud_client_message *msg)
{
remote_error rerr;
DEBUG("stream=%p proc=%d serial=%d",
stream, msg->hdr.proc, msg->hdr.serial);
memset(&rerr, 0, sizeof rerr);
stream->closed = 1;
virStreamAbort(stream->st);
if (msg->hdr.status == REMOTE_ERROR)
remoteDispatchFormatError(&rerr, "%s", _("stream aborted at client request"));
else {
VIR_WARN("unexpected stream status %d", msg->hdr.status);
remoteDispatchFormatError(&rerr, _("stream aborted with unexpected status %d"),
msg->hdr.status);
}
return remoteSerializeReplyError(client, &rerr, &msg->hdr);
}
/*
* Called when the stream is signalled has being able to accept
* data writes. Will process all pending incoming messages
* until they're all gone, or I/O blocks
*
* Returns 0 on success, or -1 upon fatal error
*/
static int
remoteStreamHandleWrite(struct qemud_client *client,
struct qemud_client_stream *stream)
{
struct qemud_client_message *msg, *tmp;
DEBUG("stream=%p", stream);
msg = stream->rx;
while (msg && !stream->closed) {
int ret;
switch (msg->hdr.status) {
case REMOTE_OK:
ret = remoteStreamHandleFinish(client, stream, msg);
break;
case REMOTE_CONTINUE:
ret = remoteStreamHandleWriteData(client, stream, msg);
break;
case REMOTE_ERROR:
default:
ret = remoteStreamHandleAbort(client, stream, msg);
break;
}
if (ret == 0)
qemudClientMessageQueueServe(&stream->rx);
else if (ret < 0)
return -1;
else
break; /* still processing data */
tmp = msg->next;
qemudClientMessageRelease(client, msg);
msg = tmp;
}
return 0;
}
/*
* Invoked when a stream is signalled as having data
* available to read. This reads upto one message
* worth of data, and then queues that for transmission
* to the client.
*
* Returns 0 if data was queued for TX, or a error RPC
* was sent, or -1 on fatal error, indicating client should
* be killed
*/
static int
remoteStreamHandleRead(struct qemud_client *client,
struct qemud_client_stream *stream)
{
char *buffer;
size_t bufferLen = REMOTE_MESSAGE_PAYLOAD_MAX;
int ret;
DEBUG("stream=%p", stream);
/* Shouldn't ever be called unless we're marked able to
* transmit, but doesn't hurt to check */
if (!stream->tx)
return 0;
if (VIR_ALLOC_N(buffer, bufferLen) < 0)
return -1;
ret = virStreamRecv(stream->st, buffer, bufferLen);
if (ret == -2) {
/* Should never get this, since we're only called when we know
* we're readable, but hey things change... */
ret = 0;
} else if (ret < 0) {
remote_error rerr;
memset(&rerr, 0, sizeof rerr);
remoteDispatchConnError(&rerr, NULL);
ret = remoteSerializeStreamError(client, &rerr, stream->procedure, stream->serial);
} else {
stream->tx = 0;
if (ret == 0)
stream->recvEOF = 1;
ret = remoteSendStreamData(client, stream, buffer, ret);
}
VIR_FREE(buffer);
return ret;
}
/*
* Invoked when an outgoing data packet message has been fully sent.
* This simply re-enables TX of further data.
*
* The idea is to stop the daemon growing without bound due to
* fast stream, but slow client
*/
void
remoteStreamMessageFinished(struct qemud_client *client,
struct qemud_client_message *msg)
{
struct qemud_client_stream *stream = client->streams;
while (stream) {
if (msg->hdr.proc == stream->procedure &&
msg->hdr.serial == stream->serial)
break;
stream = stream->next;
}
DEBUG("Message client=%p stream=%p proc=%d serial=%d", client, stream, msg->hdr.proc, msg->hdr.serial);
if (stream) {
stream->tx = 1;
remoteStreamUpdateEvents(stream);
}
}

View File

@@ -1,54 +0,0 @@
/*
* stream.h: APIs for managing client streams
*
* Copyright (C) 2009 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#ifndef __LIBVIRTD_STREAM_H__
#define __LIBVIRTD_STREAM_H__
#include "libvirtd.h"
struct qemud_client_stream *
remoteCreateClientStream(virConnectPtr conn,
remote_message_header *hdr);
void remoteFreeClientStream(struct qemud_client *client,
struct qemud_client_stream *stream);
int remoteAddClientStream(struct qemud_client *client,
struct qemud_client_stream *stream,
int transmit);
struct qemud_client_stream *
remoteFindClientStream(struct qemud_client *client,
virStreamPtr stream);
int
remoteRemoveClientStream(struct qemud_client *client,
struct qemud_client_stream *stream);
void
remoteStreamMessageFinished(struct qemud_client *client,
struct qemud_client_message *msg);
#endif /* __LIBVIRTD_STREAM_H__ */

View File

@@ -1,545 +0,0 @@
module Test_libvirtd =
let conf = "# Master libvirt daemon configuration file
#
# For further information consult http://libvirt.org/format.html
#################################################################
#
# Network connectivity controls
#
# Flag listening for secure TLS connections on the public TCP/IP port.
# NB, must pass the --listen flag to the libvirtd process for this to
# have any effect.
#
# It is necessary to setup a CA and issue server certificates before
# using this capability.
#
# This is enabled by default, uncomment this to disable it
listen_tls = 0
# Listen for unencrypted TCP connections on the public TCP/IP port.
# NB, must pass the --listen flag to the libvirtd process for this to
# have any effect.
#
# Using the TCP socket requires SASL authentication by default. Only
# SASL mechanisms which support data encryption are allowed. This is
# DIGEST_MD5 and GSSAPI (Kerberos5)
#
# This is disabled by default, uncomment this to enable it.
listen_tcp = 1
# Override the port for accepting secure TLS connections
# This can be a port number, or service name
#
tls_port = \"16514\"
# Override the port for accepting insecure TCP connections
# This can be a port number, or service name
#
tcp_port = \"16509\"
# Override the default configuration which binds to all network
# interfaces. This can be a numeric IPv4/6 address, or hostname
#
listen_addr = \"192.168.0.1\"
# Flag toggling mDNS advertizement of the libvirt service.
#
# Alternatively can disable for all services on a host by
# stopping the Avahi daemon
#
# This is enabled by default, uncomment this to disable it
mdns_adv = 0
# Override the default mDNS advertizement name. This must be
# unique on the immediate broadcast network.
#
# The default is \"Virtualization Host HOSTNAME\", where HOSTNAME
# is subsituted for the short hostname of the machine (without domain)
#
mdns_name = \"Virtualization Host Joe Demo\"
#################################################################
#
# UNIX socket access controls
#
# Set the UNIX domain socket group ownership. This can be used to
# allow a 'trusted' set of users access to management capabilities
# without becoming root.
#
# This is restricted to 'root' by default.
unix_sock_group = \"libvirt\"
# Set the UNIX socket permissions for the R/O socket. This is used
# for monitoring VM status only
#
# Default allows any user. If setting group ownership may want to
# restrict this to:
unix_sock_ro_perms = \"0777\"
# Set the UNIX socket permissions for the R/W socket. This is used
# for full management of VMs
#
# Default allows only root. If PolicyKit is enabled on the socket,
# the default will change to allow everyone (eg, 0777)
#
# If not using PolicyKit and setting group ownership for access
# control then you may want to relax this to:
unix_sock_rw_perms = \"0770\"
#################################################################
#
# Authentication.
#
# - none: do not perform auth checks. If you can connect to the
# socket you are allowed. This is suitable if there are
# restrictions on connecting to the socket (eg, UNIX
# socket permissions), or if there is a lower layer in
# the network providing auth (eg, TLS/x509 certificates)
#
# - sasl: use SASL infrastructure. The actual auth scheme is then
# controlled from /etc/sasl2/libvirt.conf. For the TCP
# socket only GSSAPI & DIGEST-MD5 mechanisms will be used.
# For non-TCP or TLS sockets, any scheme is allowed.
#
# - polkit: use PolicyKit to authenticate. This is only suitable
# for use on the UNIX sockets. The default policy will
# require a user to supply their own password to gain
# full read/write access (aka sudo like), while anyone
# is allowed read/only access.
#
# Set an authentication scheme for UNIX read-only sockets
# By default socket permissions allow anyone to connect
#
# To restrict monitoring of domains you may wish to enable
# an authentication mechanism here
auth_unix_ro = \"none\"
# Set an authentication scheme for UNIX read-write sockets
# By default socket permissions only allow root. If PolicyKit
# support was compiled into libvirt, the default will be to
# use 'polkit' auth.
#
# If the unix_sock_rw_perms are changed you may wish to enable
# an authentication mechanism here
auth_unix_rw = \"none\"
# Change the authentication scheme for TCP sockets.
#
# If you don't enable SASL, then all TCP traffic is cleartext.
# Don't do this outside of a dev/test scenario. For real world
# use, always enable SASL and use the GSSAPI or DIGEST-MD5
# mechanism in /etc/sasl2/libvirt.conf
auth_tcp = \"sasl\"
# Change the authentication scheme for TLS sockets.
#
# TLS sockets already have encryption provided by the TLS
# layer, and limited authentication is done by certificates
#
# It is possible to make use of any SASL authentication
# mechanism as well, by using 'sasl' for this option
auth_tls = \"none\"
#################################################################
#
# TLS x509 certificate configuration
#
# Override the default server key file path
#
key_file = \"/etc/pki/libvirt/private/serverkey.pem\"
# Override the default server certificate file path
#
cert_file = \"/etc/pki/libvirt/servercert.pem\"
# Override the default CA certificate path
#
ca_file = \"/etc/pki/CA/cacert.pem\"
# Specify a certificate revocation list.
#
# Defaults to not using a CRL, uncomment to enable it
crl_file = \"/etc/pki/CA/crl.pem\"
#################################################################
#
# Authorization controls
#
# Flag to disable verification of client certificates
#
# Client certificate verification is the primary authentication mechanism.
# Any client which does not present a certificate signed by the CA
# will be rejected.
#
# Default is to always verify. Uncommenting this will disable
# verification - make sure an IP whitelist is set
tls_no_verify_certificate = 1
# A whitelist of allowed x509 Distinguished Names
# This list may contain wildcards such as
#
# \"C=GB,ST=London,L=London,O=Red Hat,CN=*\"
#
# See the POSIX fnmatch function for the format of the wildcards.
#
# NB If this is an empty list, no client can connect, so comment out
# entirely rather than using empty list to disable these checks
#
# By default, no DN's are checked
tls_allowed_dn_list = [\"DN1\", \"DN2\"]
# A whitelist of allowed SASL usernames. The format for usernames
# depends on the SASL authentication mechanism. Kerberos usernames
# look like username@REALM
#
# This list may contain wildcards such as
#
# \"*@EXAMPLE.COM\"
#
# See the POSIX fnmatch function for the format of the wildcards.
#
# NB If this is an empty list, no client can connect, so comment out
# entirely rather than using empty list to disable these checks
#
# By default, no Username's are checked
sasl_allowed_username_list = [
\"joe@EXAMPLE.COM\",
\"fred@EXAMPLE.COM\"
]
#################################################################
#
# Processing controls
#
# The maximum number of concurrent client connections to allow
# over all sockets combined.
max_clients = 20
# The minimum limit sets the number of workers to start up
# initially. If the number of active clients exceeds this,
# then more threads are spawned, upto max_workers limit.
# Typically you'd want max_workers to equal maximum number
# of clients allowed
min_workers = 5
max_workers = 20
# Total global limit on concurrent RPC calls. Should be
# at least as large as max_workers. Beyond this, RPC requests
# will be read into memory and queued. This directly impact
# memory usage, currently each request requires 256 KB of
# memory. So by default upto 5 MB of memory is used
max_requests = 20
# Limit on concurrent requests from a single client
# connection. To avoid one client monopolizing the server
# this should be a small fraction of the global max_requests
# and max_workers parameter
max_client_requests = 5
# Logging level:
log_level = 4
# Logging outputs:
log_outputs=\"4:stderr\"
# Logging filters:
log_filters=\"a\"
"
test Libvirtd.lns get conf =
{ "#comment" = "Master libvirt daemon configuration file" }
{ "#comment" = "" }
{ "#comment" = "For further information consult http://libvirt.org/format.html" }
{ "#empty" }
{ "#empty" }
{ "#comment" = "################################################################" }
{ "#comment" = "" }
{ "#comment" = "Network connectivity controls" }
{ "#comment" = "" }
{ "#empty" }
{ "#comment" = "Flag listening for secure TLS connections on the public TCP/IP port." }
{ "#comment" = "NB, must pass the --listen flag to the libvirtd process for this to" }
{ "#comment" = "have any effect." }
{ "#comment" = "" }
{ "#comment" = "It is necessary to setup a CA and issue server certificates before" }
{ "#comment" = "using this capability." }
{ "#comment" = "" }
{ "#comment" = "This is enabled by default, uncomment this to disable it" }
{ "listen_tls" = "0" }
{ "#empty" }
{ "#comment" = "Listen for unencrypted TCP connections on the public TCP/IP port." }
{ "#comment" = "NB, must pass the --listen flag to the libvirtd process for this to" }
{ "#comment" = "have any effect." }
{ "#comment" = "" }
{ "#comment" = "Using the TCP socket requires SASL authentication by default. Only" }
{ "#comment" = "SASL mechanisms which support data encryption are allowed. This is" }
{ "#comment" = "DIGEST_MD5 and GSSAPI (Kerberos5)" }
{ "#comment" = "" }
{ "#comment" = "This is disabled by default, uncomment this to enable it." }
{ "listen_tcp" = "1" }
{ "#empty" }
{ "#empty" }
{ "#empty" }
{ "#comment" = "Override the port for accepting secure TLS connections" }
{ "#comment" = "This can be a port number, or service name" }
{ "#comment" = "" }
{ "tls_port" = "16514" }
{ "#empty" }
{ "#comment" = "Override the port for accepting insecure TCP connections" }
{ "#comment" = "This can be a port number, or service name" }
{ "#comment" = "" }
{ "tcp_port" = "16509" }
{ "#empty" }
{ "#empty" }
{ "#comment" = "Override the default configuration which binds to all network" }
{ "#comment" = "interfaces. This can be a numeric IPv4/6 address, or hostname" }
{ "#comment" = "" }
{ "listen_addr" = "192.168.0.1" }
{ "#empty" }
{ "#empty" }
{ "#comment" = "Flag toggling mDNS advertizement of the libvirt service." }
{ "#comment" = "" }
{ "#comment" = "Alternatively can disable for all services on a host by" }
{ "#comment" = "stopping the Avahi daemon" }
{ "#comment" = "" }
{ "#comment" = "This is enabled by default, uncomment this to disable it" }
{ "mdns_adv" = "0" }
{ "#empty" }
{ "#comment" = "Override the default mDNS advertizement name. This must be" }
{ "#comment" = "unique on the immediate broadcast network." }
{ "#comment" = "" }
{ "#comment" = "The default is \"Virtualization Host HOSTNAME\", where HOSTNAME" }
{ "#comment" = "is subsituted for the short hostname of the machine (without domain)" }
{ "#comment" = "" }
{ "mdns_name" = "Virtualization Host Joe Demo" }
{ "#empty" }
{ "#empty" }
{ "#comment" = "################################################################" }
{ "#comment" = "" }
{ "#comment" = "UNIX socket access controls" }
{ "#comment" = "" }
{ "#empty" }
{ "#comment" = "Set the UNIX domain socket group ownership. This can be used to" }
{ "#comment" = "allow a 'trusted' set of users access to management capabilities" }
{ "#comment" = "without becoming root." }
{ "#comment" = "" }
{ "#comment" = "This is restricted to 'root' by default." }
{ "unix_sock_group" = "libvirt" }
{ "#empty" }
{ "#comment" = "Set the UNIX socket permissions for the R/O socket. This is used" }
{ "#comment" = "for monitoring VM status only" }
{ "#comment" = "" }
{ "#comment" = "Default allows any user. If setting group ownership may want to" }
{ "#comment" = "restrict this to:" }
{ "unix_sock_ro_perms" = "0777" }
{ "#empty" }
{ "#comment" = "Set the UNIX socket permissions for the R/W socket. This is used" }
{ "#comment" = "for full management of VMs" }
{ "#comment" = "" }
{ "#comment" = "Default allows only root. If PolicyKit is enabled on the socket," }
{ "#comment" = "the default will change to allow everyone (eg, 0777)" }
{ "#comment" = "" }
{ "#comment" = "If not using PolicyKit and setting group ownership for access" }
{ "#comment" = "control then you may want to relax this to:" }
{ "unix_sock_rw_perms" = "0770" }
{ "#empty" }
{ "#empty" }
{ "#empty" }
{ "#comment" = "################################################################" }
{ "#comment" = "" }
{ "#comment" = "Authentication." }
{ "#comment" = "" }
{ "#comment" = "- none: do not perform auth checks. If you can connect to the" }
{ "#comment" = "socket you are allowed. This is suitable if there are" }
{ "#comment" = "restrictions on connecting to the socket (eg, UNIX" }
{ "#comment" = "socket permissions), or if there is a lower layer in" }
{ "#comment" = "the network providing auth (eg, TLS/x509 certificates)" }
{ "#comment" = "" }
{ "#comment" = "- sasl: use SASL infrastructure. The actual auth scheme is then" }
{ "#comment" = "controlled from /etc/sasl2/libvirt.conf. For the TCP" }
{ "#comment" = "socket only GSSAPI & DIGEST-MD5 mechanisms will be used." }
{ "#comment" = "For non-TCP or TLS sockets, any scheme is allowed." }
{ "#comment" = "" }
{ "#comment" = "- polkit: use PolicyKit to authenticate. This is only suitable" }
{ "#comment" = "for use on the UNIX sockets. The default policy will" }
{ "#comment" = "require a user to supply their own password to gain" }
{ "#comment" = "full read/write access (aka sudo like), while anyone" }
{ "#comment" = "is allowed read/only access." }
{ "#comment" = "" }
{ "#comment" = "Set an authentication scheme for UNIX read-only sockets" }
{ "#comment" = "By default socket permissions allow anyone to connect" }
{ "#comment" = "" }
{ "#comment" = "To restrict monitoring of domains you may wish to enable" }
{ "#comment" = "an authentication mechanism here" }
{ "auth_unix_ro" = "none" }
{ "#empty" }
{ "#comment" = "Set an authentication scheme for UNIX read-write sockets" }
{ "#comment" = "By default socket permissions only allow root. If PolicyKit" }
{ "#comment" = "support was compiled into libvirt, the default will be to" }
{ "#comment" = "use 'polkit' auth." }
{ "#comment" = "" }
{ "#comment" = "If the unix_sock_rw_perms are changed you may wish to enable" }
{ "#comment" = "an authentication mechanism here" }
{ "auth_unix_rw" = "none" }
{ "#empty" }
{ "#comment" = "Change the authentication scheme for TCP sockets." }
{ "#comment" = "" }
{ "#comment" = "If you don't enable SASL, then all TCP traffic is cleartext." }
{ "#comment" = "Don't do this outside of a dev/test scenario. For real world" }
{ "#comment" = "use, always enable SASL and use the GSSAPI or DIGEST-MD5" }
{ "#comment" = "mechanism in /etc/sasl2/libvirt.conf" }
{ "auth_tcp" = "sasl" }
{ "#empty" }
{ "#comment" = "Change the authentication scheme for TLS sockets." }
{ "#comment" = "" }
{ "#comment" = "TLS sockets already have encryption provided by the TLS" }
{ "#comment" = "layer, and limited authentication is done by certificates" }
{ "#comment" = "" }
{ "#comment" = "It is possible to make use of any SASL authentication" }
{ "#comment" = "mechanism as well, by using 'sasl' for this option" }
{ "auth_tls" = "none" }
{ "#empty" }
{ "#empty" }
{ "#empty" }
{ "#comment" = "################################################################" }
{ "#comment" = "" }
{ "#comment" = "TLS x509 certificate configuration" }
{ "#comment" = "" }
{ "#empty" }
{ "#empty" }
{ "#comment" = "Override the default server key file path" }
{ "#comment" = "" }
{ "key_file" = "/etc/pki/libvirt/private/serverkey.pem" }
{ "#empty" }
{ "#comment" = "Override the default server certificate file path" }
{ "#comment" = "" }
{ "cert_file" = "/etc/pki/libvirt/servercert.pem" }
{ "#empty" }
{ "#comment" = "Override the default CA certificate path" }
{ "#comment" = "" }
{ "ca_file" = "/etc/pki/CA/cacert.pem" }
{ "#empty" }
{ "#comment" = "Specify a certificate revocation list." }
{ "#comment" = "" }
{ "#comment" = "Defaults to not using a CRL, uncomment to enable it" }
{ "crl_file" = "/etc/pki/CA/crl.pem" }
{ "#empty" }
{ "#empty" }
{ "#empty" }
{ "#comment" = "################################################################" }
{ "#comment" = "" }
{ "#comment" = "Authorization controls" }
{ "#comment" = "" }
{ "#empty" }
{ "#empty" }
{ "#comment" = "Flag to disable verification of client certificates" }
{ "#comment" = "" }
{ "#comment" = "Client certificate verification is the primary authentication mechanism." }
{ "#comment" = "Any client which does not present a certificate signed by the CA" }
{ "#comment" = "will be rejected." }
{ "#comment" = "" }
{ "#comment" = "Default is to always verify. Uncommenting this will disable" }
{ "#comment" = "verification - make sure an IP whitelist is set" }
{ "tls_no_verify_certificate" = "1" }
{ "#empty" }
{ "#empty" }
{ "#comment" = "A whitelist of allowed x509 Distinguished Names" }
{ "#comment" = "This list may contain wildcards such as" }
{ "#comment" = "" }
{ "#comment" = "\"C=GB,ST=London,L=London,O=Red Hat,CN=*\"" }
{ "#comment" = "" }
{ "#comment" = "See the POSIX fnmatch function for the format of the wildcards." }
{ "#comment" = "" }
{ "#comment" = "NB If this is an empty list, no client can connect, so comment out" }
{ "#comment" = "entirely rather than using empty list to disable these checks" }
{ "#comment" = "" }
{ "#comment" = "By default, no DN's are checked" }
{ "tls_allowed_dn_list"
{ "1" = "DN1"}
{ "2" = "DN2"}
}
{ "#empty" }
{ "#empty" }
{ "#comment" = "A whitelist of allowed SASL usernames. The format for usernames" }
{ "#comment" = "depends on the SASL authentication mechanism. Kerberos usernames" }
{ "#comment" = "look like username@REALM" }
{ "#comment" = "" }
{ "#comment" = "This list may contain wildcards such as" }
{ "#comment" = "" }
{ "#comment" = "\"*@EXAMPLE.COM\"" }
{ "#comment" = "" }
{ "#comment" = "See the POSIX fnmatch function for the format of the wildcards." }
{ "#comment" = "" }
{ "#comment" = "NB If this is an empty list, no client can connect, so comment out" }
{ "#comment" = "entirely rather than using empty list to disable these checks" }
{ "#comment" = "" }
{ "#comment" = "By default, no Username's are checked" }
{ "sasl_allowed_username_list"
{ "1" = "joe@EXAMPLE.COM" }
{ "2" = "fred@EXAMPLE.COM" }
}
{ "#empty" }
{ "#empty" }
{ "#comment" = "################################################################"}
{ "#comment" = ""}
{ "#comment" = "Processing controls"}
{ "#comment" = ""}
{ "#empty" }
{ "#comment" = "The maximum number of concurrent client connections to allow"}
{ "#comment" = "over all sockets combined."}
{ "max_clients" = "20" }
{ "#empty" }
{ "#empty" }
{ "#comment" = "The minimum limit sets the number of workers to start up"}
{ "#comment" = "initially. If the number of active clients exceeds this,"}
{ "#comment" = "then more threads are spawned, upto max_workers limit."}
{ "#comment" = "Typically you'd want max_workers to equal maximum number"}
{ "#comment" = "of clients allowed"}
{ "min_workers" = "5" }
{ "max_workers" = "20" }
{ "#empty" }
{ "#comment" = "Total global limit on concurrent RPC calls. Should be" }
{ "#comment" = "at least as large as max_workers. Beyond this, RPC requests" }
{ "#comment" = "will be read into memory and queued. This directly impact" }
{ "#comment" = "memory usage, currently each request requires 256 KB of" }
{ "#comment" = "memory. So by default upto 5 MB of memory is used" }
{ "max_requests" = "20" }
{ "#empty" }
{ "#comment" = "Limit on concurrent requests from a single client" }
{ "#comment" = "connection. To avoid one client monopolizing the server" }
{ "#comment" = "this should be a small fraction of the global max_requests" }
{ "#comment" = "and max_workers parameter" }
{ "max_client_requests" = "5" }
{ "#empty" }
{ "#comment" = "Logging level:" }
{ "log_level" = "4" }
{ "#empty" }
{ "#comment" = "Logging outputs:" }
{ "log_outputs" = "4:stderr" }
{ "#empty" }
{ "#comment" = "Logging filters:" }
{ "log_filters" = "a" }

7
docs/.gitignore vendored
View File

@@ -1,7 +0,0 @@
Makefile
Makefile.in
.memdump
apibuild.pyc
*.html
libvirt-api.xml
libvirt-refs.xml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 783 B

View File

@@ -1,49 +0,0 @@
#!/bin/awk -f
function translate(str) {
while (sub(/&/, "#amp;", str) == 1);
while (sub(/#amp;/, "\\&amp;", str) == 1); # fun isn't it ?
while (sub(/</, "\\&lt;", str) == 1);
while (sub(/>/, "\\&gt;", str) == 1);
sub(/[0-9][0-9][0-9][0-9][0-9]+/, "<bug number='&'/>", str)
return(str)
}
BEGIN {
nb_entry = 0
in_entry = 0
in_item = 0
print "<?xml version='1.0' encoding='ISO-8859-1'?>"
print "<log>"
}
END {
if (in_item == 1) printf("%s</item>\n", translate(item))
if (in_entry == 1) print " </entry>"
print "</log>"
}
/^[ \t]*$/ { next }
/^[A-Za-z0-9]/ {
match($0, "\(.*\) \([A-Z]+\) \([0-9][0-9][0-9][0-9]\) \(.*\) <\(.*\)>", loge)
if (in_item == 1) printf("%s</item>\n", translate(item))
if (in_entry == 1) print " </entry>"
nb_entry = nb_entry + 1
if (nb_entry > 50) {
in_entry = 0
in_item = 0
exit
}
in_entry = 1
in_item = 0
printf(" <entry date='%s' timezone='%s' year='%s'\n who='%s' email='%s'>\n", loge[1], loge[2], loge[3], loge[4], loge[5])
}
/^[ \t]*\*/ {
if (in_item == 1) printf("%s</item>\n", translate(item))
in_item = 1
printf(" <item>")
match($0, "[ \t]*. *\(.*\)", loge)
item = loge[1]
}
/^[ \t]*[a-zA-Z0-9\#]/ {
if (in_item == 1) {
match($0, "[ \t]*\(.*\)[ \t]*", loge)
item = sprintf("%s %s", item, loge[1])
}
}

View File

@@ -1,37 +0,0 @@
<?xml version="1.0"?>
<!-- this stylesheet builds the ChangeLog.html -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Generate XHTML-1.0 transitional -->
<xsl:output method="xml" encoding="UTF-8" indent="yes"
doctype-public="-//W3C//DTD XHTML 1.0//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>
<xsl:template match="item">
<li><xsl:apply-templates/></li>
</xsl:template>
<xsl:template match="entry">
<p>
<span class="author"><xsl:value-of select="@who"/> </span>
<span class="date"><xsl:value-of select="@date"/> </span>
<span class="timezone"><xsl:value-of select="@timezone"/> </span>
</p>
<ul>
<xsl:apply-templates select="item"/>
</ul>
</xsl:template>
<xsl:template match="log">
<html>
<body>
<h1>Log of recent changes to libvirt</h1>
<div id="changelog">
<xsl:apply-templates select="entry"/>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@@ -1,144 +0,0 @@
<?xml version="1.0"?>
<html>
<body>
<h1 >FAQ</h1>
<p>Table of Contents:</p>
<ul>
<li>
<a href="FAQ.html#License">License(s)</a>
</li>
<li>
<a href="FAQ.html#Installati">Installation</a>
</li>
<li>
<a href="FAQ.html#Compilatio">Compilation</a>
</li>
<li>
<a href="FAQ.html#Developer">Developer corner</a>
</li>
</ul>
<h3><a name="License" id="License">License</a>(s)</h3>
<ol>
<li>
<em>Licensing Terms for libvirt</em>
<p>libvirt is released under the <a href="http://www.opensource.org/licenses/lgpl-license.html">GNU Lesser
General Public License</a>, see the file COPYING.LIB in the distribution
for the precise wording. The only library that libvirt depends upon is
the Xen store access library which is also licenced under the LGPL.</p>
</li>
<li>
<em>Can I embed libvirt in a proprietary application ?</em>
<p>Yes. The LGPL allows you to embed libvirt into a proprietary
application. It would be graceful to send-back bug fixes and improvements
as patches for possible incorporation in the main development tree. It
will decrease your maintenance costs anyway if you do so.</p>
</li>
</ol>
<h3>
<a name="Installati" id="Installati">Installation</a>
</h3>
<ol>
<li><em>Where can I get libvirt</em> ?
<p>The original distribution comes from <a href="ftp://libvirt.org/libvirt/">ftp://libvirt.org/libvirt/</a>.</p>
</li>
<li>
<em>I can't install the libvirt/libvirt-devel RPM packages due to
failed dependencies</em>
<p>The most generic solution is to re-fetch the latest src.rpm , and
rebuild it locally with</p>
<p><code>rpm --rebuild libvirt-xxx.src.rpm</code>.</p>
<p>If everything goes well it will generate two binary rpm packages (one
providing the shared libs and virsh, and the other one, the -devel
package, providing includes, static libraries and scripts needed to build
applications with libvirt that you can install locally.</p>
<p>One can also rebuild the RPMs from a tarball:</p>
<p>
<code>rpmbuild -ta libdir-xxx.tar.gz</code>
</p>
<p>Or from a configured tree with:</p>
<p>
<code>make rpm</code>
</p>
</li>
<li>
<em>Failure to use the API for non-root users</em>
<p>Large parts of the API may only be accessible with root privileges,
however the read only access to the xenstore data doesnot have to be
forbidden to user, at least for monitoring purposes. If "virsh dominfo"
fails to run as an user, change the mode of the xenstore read-only socket
with:</p>
<p>
<code>chmod 666 /var/run/xenstored/socket_ro</code>
</p>
<p>and also make sure that the Xen Daemon is running correctly with local
HTTP server enabled, this is defined in
<code>/etc/xen/xend-config.sxp</code> which need the following line to be
enabled:</p>
<p>
<code>(xend-http-server yes)</code>
</p>
<p>If needed restart the xend daemon after making the change with the
following command run as root:</p>
<p>
<code>service xend restart</code>
</p>
</li>
</ol>
<h3>
<a name="Compilatio" id="Compilatio">Compilation</a>
</h3>
<ol>
<li>
<em>What is the process to compile libvirt ?</em>
<p>As most UNIX libraries libvirt follows the "standard":</p>
<p>
<code>gunzip -c libvirt-xxx.tar.gz | tar xvf -</code>
</p>
<p>
<code>cd libvirt-xxxx</code>
</p>
<p>
<code>./configure --help</code>
</p>
<p>to see the options, then the compilation/installation proper</p>
<p>
<code>./configure [possible options]</code>
</p>
<p>
<code>make</code>
</p>
<p>
<code>make install</code>
</p>
<p>At that point you may have to rerun ldconfig or a similar utility to
update your list of installed shared libs.</p>
</li>
<li>
<em>What other libraries are needed to compile/install libvirt ?</em>
<p>Libvirt requires libxenstore, which is usually provided by the xen
packages as well as the public headers to compile against libxenstore.</p>
</li>
<li>
<em>I use the CVS version and there is no configure script</em>
<p>The configure script (and other Makefiles) are generated. Use the
autogen.sh script to regenerate the configure script and Makefiles,
like:</p>
<p>
<code>./autogen.sh --prefix=/usr --disable-shared</code>
</p>
</li>
</ol>
<h3><a name="Developer" id="Developer">Developer</a> corner</h3>
<ol>
<li>
<em>Troubles compiling or linking programs using libvirt</em>
<p>To simplify the process of reusing the library, libvirt comes with
pkgconfig support, which can be used directly from autoconf support or
via the pkg-config command line tool, like:</p>
<p>
<code>pkg-config libvirt --libs</code>
</p>
</li>
</ol>
</body>
</html>

View File

@@ -1,162 +0,0 @@
## Process this file with automake to produce Makefile.in
SUBDIRS= schemas
# The directory containing the source code (if it contains documentation).
DOC_SOURCE_DIR=../src
DEVHELP_DIR=$(datadir)/gtk-doc/html/libvirt
apihtml = \
html/index.html \
html/libvirt-libvirt.html \
html/libvirt-virterror.html
apipng = \
html/left.png \
html/up.png \
html/home.png \
html/right.png
devhelphtml = \
devhelp/libvirt.devhelp \
devhelp/index.html \
devhelp/general.html \
devhelp/libvirt-libvirt.html \
devhelp/libvirt-virterror.html
devhelppng = \
devhelp/home.png \
devhelp/left.png \
devhelp/right.png \
devhelp/up.png
devhelpcss = devhelp/style.css
devhelpxsl = devhelp/devhelp.xsl devhelp/html.xsl
png = \
32favicon.png \
footer_corner.png \
footer_pattern.png \
libvirt-header-bg.png \
libvirt-header-logo.png \
libvirtLogo.png \
libvirt-net-logical.png \
libvirt-net-physical.png \
libvirt-daemon-arch.png \
libvirt-driver-arch.png \
libvirt-object-model.png \
madeWith.png \
et.png
gif = \
architecture.gif \
node.gif
dot_html_in = $(wildcard *.html.in)
dot_html = $(dot_html_in:%.html.in=%.html)
patches = $(wildcard api_extension/*.patch)
xml = \
libvirt-api.xml \
libvirt-refs.xml
fig = \
libvirt-net-logical.fig \
libvirt-net-physical.fig \
libvirt-daemon-arch.fig \
libvirt-driver-arch.fig \
libvirt-object-model.fig
EXTRA_DIST= \
libvirt-api.xml libvirt-refs.xml apibuild.py \
site.xsl newapi.xsl news.xsl page.xsl ChangeLog.xsl \
$(dot_html) $(dot_html_in) $(gif) $(apihtml) $(apipng) \
$(devhelphtml) $(devhelppng) $(devhelpcss) $(devhelpxsl) \
$(xml) $(fig) $(png) \
$(patches) \
ChangeLog.awk
CLEANFILES = $(dot_html) $(apihtml) $(devhelphtml)
all: web
api: libvirt-api.xml libvirt-refs.xml
web: $(dot_html) html/index.html devhelp/index.html
ChangeLog.xml: ../ChangeLog ChangeLog.awk
awk -f ChangeLog.awk < $< > $@
ChangeLog.html.in: ChangeLog.xml ChangeLog.xsl
@(if [ -x $(XSLTPROC) ] ; then \
echo "Generating $@"; \
name=`echo $@ | sed -e 's/.tmp//'`; \
$(XSLTPROC) --nonet $(top_srcdir)/docs/ChangeLog.xsl $< > $@ || (rm $@ && exit 1) ; fi )
%.png: %.fig
convert -rotate 90 $< $@
%.html.tmp: %.html.in site.xsl page.xsl sitemap.html.in
@(if [ -x $(XSLTPROC) ] ; then \
echo "Generating $@"; \
name=`echo $@ | sed -e 's/.tmp//'`; \
$(XSLTPROC) --stringparam pagename $$name --nonet --html $(top_srcdir)/docs/site.xsl $< > $@ || (rm $@ && exit 1) ; fi )
%.html: %.html.tmp
@(if [ -x $(XMLLINT) -a -x $(XMLCATALOG) ] ; then \
if $(XMLCATALOG) /etc/xml/catalog "-//W3C//DTD XHTML 1.0 Strict//EN" > /dev/null ; then \
echo "Validating $@" ; \
$(XMLLINT) --nonet --format --valid $< > $@ || : ; \
else echo "missing XHTML1 DTD" ; fi ; fi );
html/index.html: libvirt-api.xml newapi.xsl page.xsl sitemap.html.in
-@(if [ -x $(XSLTPROC) ] ; then \
echo "Rebuilding the HTML pages from the XML API" ; \
$(XSLTPROC) --nonet $(srcdir)/newapi.xsl libvirt-api.xml ; fi )
-@(if [ -x $(XMLLINT) -a -x $(XMLCATALOG) ] ; then \
if $(XMLCATALOG) /etc/xml/catalog "-//W3C//DTD XHTML 1.0 Strict//EN" > /dev/null ; then \
echo "Validating the resulting XHTML pages" ; \
$(XMLLINT) --nonet --valid --noout html/*.html ; \
else echo "missing XHTML1 DTD" ; fi ; fi );
devhelp/index.html devhelp/libvirt.devhelp: libvirt-api.xml $(devhelpxsl)
-@(echo Rebuilding devhelp files)
-@(if [ -x $(XSLTPROC) ] ; then \
$(XSLTPROC) --nonet -o devhelp/libvirt.devhelp $(top_srcdir)/docs/devhelp/devhelp.xsl $(top_srcdir)/docs/libvirt-api.xml ; fi );
libvirt-api.xml libvirt-refs.xml: apibuild.py \
$(srcdir)/../include/libvirt/*.h \
$(srcdir)/../src/libvirt.c $(srcdir)/../src/util/virterror.c
-(./apibuild.py)
clean-local:
rm -f *~ *.bak *.hierarchy *.signals *-unused.txt
maintainer-clean-local: clean-local
rm -rf libvirt-api.xml libvirt-refs.xml
rebuild: api all
install-data-local:
$(mkinstalldirs) $(DESTDIR)$(HTML_DIR)
-@INSTALL@ -m 0644 $(srcdir)/FAQ.html \
$(srcdir)/Libxml2-Logo-90x34.gif $(DESTDIR)$(HTML_DIR)
$(mkinstalldirs) $(DESTDIR)$(HTML_DIR)/html
for h in $(apihtml); do \
$(INSTALL) -m 0644 $(srcdir)/$$h $(DESTDIR)$(HTML_DIR)/html; done
for p in $(apipng); do \
$(INSTALL) -m 0644 $(srcdir)/$$p $(DESTDIR)$(HTML_DIR)/html; done
$(mkinstalldirs) $(DESTDIR)$(DEVHELP_DIR)
for file in $(devhelphtml) $(devhelppng) $(devhelpcss); do \
@INSTALL@ -m 0644 $(srcdir)/$${file} $(DESTDIR)$(DEVHELP_DIR) ; \
done
uninstall-local:
for h in $(apihtml); do rm $(DESTDIR)$(HTML_DIR)/$$h; done
for p in $(apipng); do rm $(DESTDIR)$(HTML_DIR)/$$p; done
for f in $(devhelphtml) $(devhelppng) $(devhelpcss); do \
rm $(DESTDIR)$(DEVHELP_DIR)$$f ; done

4
docs/Plan Normal file
View File

@@ -0,0 +1,4 @@
1/ go for a minimal library first, expand on use cases
2/ reuse xenctrl.h / libxenctrl in a first implementation, but make
sure to clearly isolate the bits calling them
3/

33
docs/analysis Normal file
View File

@@ -0,0 +1,33 @@
arch/xen/kernel/evtchn.c: Communication via Xen event channels
->HYPERVISOR_xen_version call
->HYPERVISOR_physdev_op call
->HYPERVISOR_event_channel_op call
-> global HYPERVISOR_shared_info
arch/xen/kernel/fixup.c: binary rewrinting for threads TLS
-> message to suppress... + boot delay
arch/xen/kernel/gnttab.c: memory access and sharing
inline assemby from privcmd.c using TRAP_INSTR macro to do an hypervisor
call apparently.
arch/xen/kernel/reboot.c:
-> HYPERVISOR_suspend call
include/asm-xen/asm-i386/hypercall.h:
-> assembly macro for the hypervisor calls
tools/libxc/xc_*.c: library for xen control
tools/libxc/xc_private.h:
-> Xen hypervisor call is an ioctl() with an privcmd_hypercall_t parameter
xc_domain.c:
-> API for all domain supervisor calls, create, memory, cpu weight, destroy
=> Fraser all over the place ...
/Xen/xen-unstable.hg/tools/libxc
The hypervisor calls are defined as inlined functions in xc_private.h
This is GPL and not installed.

View File

@@ -1,136 +0,0 @@
<?xml version="1.0"?>
<html>
<body>
<h1>The libvirt API concepts</h1>
<p> This page describes the main principles and architecture choices
behind the definition of the libvirt API:
<ul>
<li>
<a href="#Objects">Objects exposed</a>
</li>
<li>
<a href="#Functions">Functions and naming conventions</a>
</li>
<li>
<a href="#Driver">The drivers</a>
</li>
<li>
<a href="#Remote">Daemon and remote access</a>
</li>
</ul>
<h2><a name="Objects" id="Objects">Objects exposed</a></h2>
<p> As defined in the <a href="goals.html">goals section</a>, libvirt
API need to expose all the resources needed to manage the virtualization
support of recent operating systems. The first object manipulated though
the API is <code>virConnectPtr</code> which represent a connection to
an hypervisor. Any application using libvirt is likely to start using the
API by calling one of <a href="html/libvirt-libvirt.html#virConnectOpen"
>the virConnectOpen functions</a>. You will note that those functions take
a name argument which is actually an URI to select the right hypervisor to
open, this is needed to allow remote connections and also select between
different possible hypervisors (for example on a Linux system it may be
possible to use both KVM and LinuxContainers on the same node). A NULL
name will default to a preselected hypervisor but it's probably not a
wise thing to do in most cases. See the <a href="uri.html">connection
URI</a> page for a full descriptions of the values allowed.<p>
<p> Once the application obtained a <code class='docref'>virConnectPtr</code>
connection to the
hypervisor it can then use it to manage domains and related resources
available for virtualization like storage and networking. All those are
exposed as first class objects, and connected to the hypervisor connection
(and the node or cluster where it is available).</p>
<p class="image">
<img alt="first class objects exposed by the API"
src="libvirt-object-model.png"/>
</p>
<p> The figure above shows the five main objects exported by the API:</p>
<ul>
<li>virConnectPtr: represent a connection to an hypervisor.</li>
<li>virDomainPtr: represent one domain either active or defined (i.e.
existing as permanent config file and storage but not currently running
on that node). The function <code class='docref'>virConnectListDomains</code>
allows to list all the IDs for the domains active on this hypervisor.</li>
<li>virNetworkPtr: represent one network either active or defined (i.e.
existing as permanent config file and storage but not currently activated.
The function <code class='docref'>virConnectListNetworks</code>
allows to list all the virtualization networks actived on this node.</li>
<li>virStorageVolPtr: represent one storage volume, usually this is used
as a block device available to one of the domains. The function
<code class="docref">virStorageVolLookupByPath</code> allows to find
the object based on its path on the node.</li>
<li>virStoragePoolPtr: represent a storage pool, i.e. a logical area
which can be used to allocate and store storage volumes. The function
<code class="docref">virStoragePoolLookupByVolume</code> allows to find
the storage pool containing a given storage volume.</li>
</ul>
<p> Most object manipulated by the library can also be represented using
XML descriptions. This is used primarily to create those object, but is
also helpful to modify or save their description back.</p>
<p> Domains, network and storage pools can be either <code>active</code>
i.e. either running or available for immediate use, or
<code>defined</code> in which case they are inactive but there is
a permanent definition available in the system for them. Based on this
thay can be activated dynamically in order to be used.</p>
<p> Most kind of object can also be named in various ways:<p>
<ul>
<li>by their <code>name</code>, an user friendly identifier but
whose unicity cannot be garanteed between two nodes.</li>
<li>by their <code>ID</code>, which is a runtime unique identifier
provided by the hypervisor for one given activation of the object,
but it becomes invalid once the resource is deactivated.</li >
<li>by their <code>UUID</code>, a 16 bytes unique identifier
as defined in <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>,
which is garanteed to be unique for long term usage and across a
set of nodes.</li>
</ul>
<h2><a name="Functions" id="Functions">Functions and naming
conventions</a></h2>
<p> The naming of the functions present in the library is usually
made of a prefix describing the object associated to the function
and a verb describing the action on that object.</p>
<p> For each first class object you will find apis
for the following actions:</p>
<ul>
<li><b>Lookup</b>:...LookupByName,
<li><b>Enumeration</b>:virConnectList... and virConnectNumOf...:
those are used to enumerate a set of object available to an given
hypervisor connection like:
<code class='docref'>virConnectListDomains</code>,
<code class='docref'>virConnectNumOfDomains</code>,
<code class='docref'>virConnectListNetworks</code>,
<code class='docref'>virConnectListStoragePools</code>, etc.</li>
<li><b>Description</b>: ...GetInfo: those are generic accessor providing
a set of informations about an object, they are
<code class='docref'>virNodeGetInfo</code>,
<code class='docref'>virDomainGetInfo</code>,
<code class='docref'>virStoragePoolGetInfo</code>,
<code class='docref'>virStorageVolGetInfo</code>.</li>
<li><b>Accessors</b>: ...Get... and ...Set...: those are more specific
accessors to query or modify the given object, like
<code class='docref'>virConnectGetType</code>,
<code class='docref'>virDomainGetMaxMemory</code>,
<code class='docref'>virDomainSetMemory</code>,
<code class='docref'>virDomainGetVcpus</code>,
<code class='docref'>virStoragePoolSetAutostart</code>,
<code class='docref'>virNetworkGetBridgeName</code>, etc.</li>
<li><b>Creation</b>: </li>
<li><b>Destruction</b>: ... </li>
</ul>
<p> For more in-depth details of the storage related APIs see
<a href="storage.html">the storage management page</a>,
<h2><a name="Driver" id="Driver">The libvirt drivers</a></h2>
<p></p>
<p class="image">
<img alt="The libvirt driver architecture"
src="libvirt-driver-arch.png"/>
</p>
<h2><a name="Remote" id="Remote">Daemon and remote access</a></h2>
<p></p>
<p class="image">
<img alt="The libvirt daemon and remote architecture"
src="libvirt-daemon-arch.png"/>
</p>
</body>
</html>

View File

@@ -1,302 +0,0 @@
<html>
<head>
<title>Implementing a new API in Libvirt</title>
</head>
<body>
<h1>Implementing a new API in Libvirt</h1>
<ul id="toc"></ul>
<p>
This document walks you through the process of implementing a new
API in libvirt. It uses as an example the addition of the node device
create and destroy APIs.
</p>
<p>
Before you begin coding, it is critical that you propose your
changes on the libvirt mailing list and get feedback on your ideas to
make sure what you're proposing fits with the general direction of the
project. Even before doing a proof of concept implementation, send an
email giving an overview of the functionality you think should be
added to libvirt. Someone may already be working on the feature you
want. Also, recognize that everything you write is likely to undergo
significant rework as you discuss it with the other developers, so
don't wait too long before getting feedback.
</p>
<p>
Adding a new API to libvirt is not difficult, but there are quite a
few steps. This document assumes that you are familiar with C
programming and have checked out the libvirt code from the source code
repository and successfully built the existing tree. Instructions on
how to check out and build the code can be found at:
</p>
<p>
<a href="http://libvirt.org/downloads.html">http://libvirt.org/downloads.html</a>
</p>
<p>
Once you have a working development environment, the steps to create a
new API are:
</p>
<ol>
<li>define the public API</li>
<li>define the internal driver API</li>
<li>implement the public API</li>
<li>define the wire protocol format</li>
<li>implement the RPC client</li>
<li>implement the server side dispatcher</li>
<li>implement the driver methods</li>
<li>add virsh support</li>
</ol>
<p>
It is, of course, possible to implement the pieces in any order, but
if the development tasks are completed in the order listed, the code
will compile after each step. Given the number of changes required,
verification after each step is highly recommended.
</p>
<p>
Submit new code in the form shown in the example code: one patch
per step. That's not to say submit patches before you have working
functionality--get the whole thing working and make sure you're happy
with it. Then use git or some other version control system that lets
you rewrite your commit history and break patches into pieces so you
don't drop a big blob of code on the mailing list at one go. For
example, I didn't follow my own advice when I originally submitted the
example code to the libvirt list but rather submitted it in several
large chunks. I've used git's ability to rewrite my commit history to
break the code apart into the example patches shown.
</p>
<p>
Don't mix anything else into the patches you submit. The patches
should be the minimal changes required to implement the functionality
you're adding. If you notice a bug in unrelated code (i.e., code you
don't have to touch to implement your API change) during development,
create a patch that just addresses that bug and submit it
separately.
</p>
<p>With that said, let's begin.</p>
<h2><a name='publicapi'>Defining the public API</a></h2>
<p>The first task is to define the public API and add it to:</p>
<p><code>include/libvirt/libvirt.h.in</code></p>
<p>
This task is in many ways the most important to get right, since once
the API has been committed to the repository, it's libvirt's policy
never to change it. Mistakes in the implementation are bugs that you
can fix. Make a mistake in the API definition and you're stuck with
it, so think carefully about the interface and don't be afraid to
rework it as you go through the process of implementing it.
</p>
<p>Once you have defined the API, you have to add the symbol names to:</p>
<p><code>src/libvirt_public.syms</code></p>
<p class="example">See <a href="api_extension/0001-Step-1-of-8-Define-the-public-API.patch">0001-Step-1-of-8-Define-the-public-API.patch</a> for example code.</p>
<h2><a name='internalapi'>Defining the internal API</a></h2>
<p>
Each public API call is associated with a driver, such as a host
virtualization driver, a network virtualization driver, a storage
virtualization driver, a state driver, or a device monitor. Adding
the internal API is ordinarily a matter of adding a new member to the
struct representing one of these drivers.
</p>
<p>
Of course, it's possible that the new API will involve the creation of
an entire new driver type, in which case the changes will include the
creation of a new struct type to represent the new driver type.
</p>
<p>The driver structs are defined in:</p>
<p><code>src/driver.h</code></p>
<p>
To define the internal API, first typedef the driver function
prototype and then add a new field for it to the relevant driver
struct.
</p>
<p class="example">See <a href="api_extension/0002-Step-2-of-8-Define-the-internal-driver-API.patch">0002-Step-2-of-8-Define-the-internal-driver-API.patch</a></p>
<h2><a name='implpublic'>Implementing the public API</a></h2>
<p>
Implementing the public API is largely a formality in which we wire up
public API to the internal driver API. The public API implementation
takes care of some basic validity checks before passing control to the
driver implementation. In RFC 2119 vocabulary, this function:
</p>
<ol class="ordinarylist">
<li>SHOULD log a message with VIR_DEBUG() indicating that it is
being called and its parameters;</li>
<li>MUST call virResetLastError();</li>
<li>SHOULD confirm that the connection is valid with
VIR_IS_CONNECT(conn);</li>
<li><strong>SECURITY: If the API requires a connection with write
privileges, MUST confirm that the connection flags do not
indicate that the connection is read-only;</strong></li>
<li>SHOULD do basic validation of the parameters that are being
passed in;</li>
<li>MUST confirm that the driver for this connection exists and that
it implements this function;</li>
<li>MUST call the internal API;</li>
<li>SHOULD log a message with VIR_DEBUG() indicating that it is
returning, its return value, and status.</li>
<li>MUST return status to the caller.</li>
</ol>
<p>The public API calls are implemented in:</p>
<p><code>src/libvirt.c</code></p>
<p class="example">See <a href="api_extension/0003-Step-3-of-8-Implement-the-public-API.patch">0003-Step-3-of-8-Implement-the-public-API.patch</a></p>
<h2><a name='wireproto'>Defining the wire protocol format</a></h2>
<p>
Defining the wire protocol is essentially a straightforward exercise
which is probably most easily understood by referring to the existing
remote protocol wire format definitions and the example patch. It
involves making two additions to:
</p>
<p><code>qemud/remote_protocol.x</code></p>
<p>
First, create two new structs for each new function that you're adding
to the API. One struct describes the parameters to be passed to the
remote function, and a second struct describes the value returned by
the remote function. The one exception to this rule is that functions
that return only integer status do not require a struct for returned
data.
</p>
<p>
Second, add values to the remote_procedure enum for each new function
added to the API.
</p>
<p class="example">See <a href="api_extension/0004-Step-4-of-8-Define-the-wire-protocol-format.patch">0004-Step-4-of-8-Define-the-wire-protocol-format.patch</a></p>
<p>
Once these changes are in place, it's necessary to run 'make rpcgen'
in the qemud directory to create the .c and .h files required by the
remote protocol code. This must be done on a Linux host using the
GLibC rpcgen program. Other rpcgen versions may generate code which
results in bogus compile time warnings
</p>
<h2><a name='rpcclient'>Implement the RPC client</a></h2>
<p>
Implementing the RPC client is also relatively mechanical, so refer to
the exising code and example patch for guidance. The RPC client uses
the rpcgen generated .h files. The remote method calls go in:
</p>
<p><code>src/remote_internal.c</code></p>
<p>Each remote method invocation does the following:</p>
<ol class="ordinarylist">
<li>locks the remote driver;</li>
<li>sets up the method arguments;</li>
<li>invokes the remote function;</li>
<li>checks the return value, if necessary;</li>
<li>extracts any returned data;</li>
<li>frees any returned data;</li>
<li>unlocks the remote driver.</li>
</ol>
<p>
Once you have created the remote method calls, you have to add fields
for them to the driver structs for the appropriate remote driver.
</p>
<p class="example">See <a href="api_extension/0005-Step-5-of-8-Implement-the-RPC-client.patch">0005-Step-5-of-8-Implement-the-RPC-client.patch</a></p>
<h2><a name="serverdispatch">Implement the server side dispatcher</a></h2>
<p>
Implementing the server side of the remote function calls is simply a
matter of deserializing the parameters passed in from the remote
caller and passing them to the corresponding internal API function.
The server side dispatchers are implemented in:
</p>
<p><code>qemud/remote.c</code></p>
<p>Again, this step uses the .h files generated by make rpcgen.</p>
<p class="example">See <a href="api_extension/0006-Step-6-of-8-Implement-the-server-side-dispatcher.patch">0006-Step-6-of-8-Implement-the-server-side-dispatcher.patch</a></p>
<h2><a name="driverimpl">Implement the driver methods</a></h2>
<p>
So, after all that, we get to the fun part. All functionality in
libvirt is implemented inside a driver. Thus, here is where you
implement whatever functionality you're adding to libvirt. You'll
either need to add additional files to the src directory or extend
files that are already there, depending on what functionality you're
adding.
</p>
<p>
In the example code, the extension is only an additional two function
calls in the node device API, so most of the new code is additions to
existing files. The only new files are there for multi-platform
implementation convenience, as some of the new code is Linux specific.
</p>
<p>
The example code is probably uninteresting unless you're concerned
with libvirt storage, but I've included it here to show how new files
are added to the build environment.
</p>
<p class="example">See <a href="api_extension/0007-Step-7-of-8-Implement-the-driver-methods.patch">0007-Step-7-of-8-Implement-the-driver-methods.patch</a></p>
<h2><a name="virsh">Implement virsh commands</a></h2>
<p>
Once you have the new functionality in place, the easiest way to test
it and also to provide it to end users is to implement support for it
in virsh.
</p>
<p>
A virsh command is composed of a few pieces of code. You need to
define an array of vshCmdInfo structs for each new command that
contain the help text and the command description text. You also need
an array of vshCmdOptDef structs to describe the command options.
Once you have those pieces of data in place you can write the function
implementing the virsh command. Finally, you need to add the new
command to the commands[] array.
</p>
<p class="example">See <a href="api_extension/0008-Step-8-of-8-Add-virsh-support.patch">0008-Step-8-of-8-Add-virsh-support.patch</a></p>
<p>Once you have working functionality, run make check and make
syntax-check before generating patches.</p>
</body>
</html>

View File

@@ -1,44 +0,0 @@
From 2ae8fd62a1e5e085b7902da9bc207b806d84fd91 Mon Sep 17 00:00:00 2001
From: David Allan <dallan@redhat.com>
Date: Tue, 19 May 2009 16:16:11 -0400
Subject: [PATCH] Step 1 of 8 Define the public API
---
include/libvirt/libvirt.h.in | 6 ++++++
src/libvirt_public.syms | 6 ++++++
2 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index a028b21..2f7076f 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1124,6 +1124,12 @@ int virNodeDeviceDettach (virNodeDevicePtr dev);
int virNodeDeviceReAttach (virNodeDevicePtr dev);
int virNodeDeviceReset (virNodeDevicePtr dev);
+virNodeDevicePtr virNodeDeviceCreateXML (virConnectPtr conn,
+ const char *xmlDesc,
+ unsigned int flags);
+
+int virNodeDeviceDestroy (virNodeDevicePtr dev);
+
/*
* Domain Event Notification
*/
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index f7ebbc3..b8f9128 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -258,4 +258,10 @@ LIBVIRT_0.6.1 {
virNodeGetSecurityModel;
} LIBVIRT_0.6.0;
+LIBVIRT_0.6.3 {
+ global:
+ virNodeDeviceCreateXML;
+ virNodeDeviceDestroy;
+} LIBVIRT_0.6.1;
+
# .... define new API here using predicted next version number ....
--
1.6.0.6

View File

@@ -1,36 +0,0 @@
From b26d7fc2d64e7e6e4d3ea2b43361015d3620d7a6 Mon Sep 17 00:00:00 2001
From: David Allan <dallan@redhat.com>
Date: Tue, 19 May 2009 16:19:14 -0400
Subject: [PATCH] Step 2 of 8 Define the internal driver API
---
src/driver.h | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/src/driver.h b/src/driver.h
index 39dc413..c357b76 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -684,6 +684,11 @@ typedef int (*virDevMonDeviceListCaps)(virNodeDevicePtr dev,
char **const names,
int maxnames);
+typedef virNodeDevicePtr (*virDrvNodeDeviceCreateXML)(virConnectPtr conn,
+ const char *xmlDesc,
+ unsigned int flags);
+typedef int (*virDrvNodeDeviceDestroy)(virNodeDevicePtr dev);
+
/**
* _virDeviceMonitor:
*
@@ -702,6 +707,8 @@ struct _virDeviceMonitor {
virDevMonDeviceGetParent deviceGetParent;
virDevMonDeviceNumOfCaps deviceNumOfCaps;
virDevMonDeviceListCaps deviceListCaps;
+ virDrvNodeDeviceCreateXML deviceCreateXML;
+ virDrvNodeDeviceDestroy deviceDestroy;
};
/*
--
1.6.0.6

View File

@@ -1,119 +0,0 @@
From fc585594a207dfb9149e7d3d01c9eb1c79b6d52d Mon Sep 17 00:00:00 2001
From: David Allan <dallan@redhat.com>
Date: Tue, 19 May 2009 16:22:23 -0400
Subject: [PATCH] Step 3 of 8 Implement the public API
---
src/libvirt.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 97 insertions(+), 0 deletions(-)
diff --git a/src/libvirt.c b/src/libvirt.c
index f3d4484..ded18a7 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -7509,6 +7509,103 @@ error:
}
+/**
+ * virNodeDeviceCreateXML:
+ * @conn: pointer to the hypervisor connection
+ * @xmlDesc: string containing an XML description of the device to be created
+ * @flags: callers should always pass 0
+ *
+ * Create a new device on the VM host machine, for example, virtual
+ * HBAs created using vport_create.
+ *
+ * Returns a node device object if successful, NULL in case of failure
+ */
+virNodeDevicePtr
+virNodeDeviceCreateXML(virConnectPtr conn,
+ const char *xmlDesc,
+ unsigned int flags)
+{
+ VIR_DEBUG("conn=%p, xmlDesc=%s, flags=%d", conn, xmlDesc, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+ return NULL;
+ }
+
+ if (conn->flags & VIR_CONNECT_RO) {
+ virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ goto error;
+ }
+
+ if (xmlDesc == NULL) {
+ virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ goto error;
+ }
+
+ if (conn->deviceMonitor &&
+ conn->deviceMonitor->deviceCreateXML) {
+ virNodeDevicePtr dev = conn->deviceMonitor->deviceCreateXML(conn, xmlDesc, flags);
+ if (dev == NULL)
+ goto error;
+ return dev;
+ }
+
+ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ /* Copy to connection error object for back compatability */
+ virSetConnError(conn);
+ return NULL;
+}
+
+
+/**
+ * virNodeDeviceDestroy:
+ * @dev: a device object
+ *
+ * Destroy the device object. The virtual device is removed from the host operating system.
+ * This function may require privileged access
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virNodeDeviceDestroy(virNodeDevicePtr dev)
+{
+ DEBUG("dev=%p", dev);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) {
+ virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__);
+ return (-1);
+ }
+
+ if (dev->conn->flags & VIR_CONNECT_RO) {
+ virLibConnError(dev->conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ goto error;
+ }
+
+ if (dev->conn->deviceMonitor &&
+ dev->conn->deviceMonitor->deviceDestroy) {
+ int retval = dev->conn->deviceMonitor->deviceDestroy(dev);
+ if (retval < 0) {
+ goto error;
+ }
+
+ return 0;
+ }
+
+ virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ /* Copy to connection error object for back compatability */
+ virSetConnError(dev->conn);
+ return -1;
+}
+
+
/*
* Domain Event Notification
*/
--
1.6.0.6

View File

@@ -1,47 +0,0 @@
From bce8f1243b0454c0d70e3db832a039d22faab09a Mon Sep 17 00:00:00 2001
From: David Allan <dallan@redhat.com>
Date: Wed, 20 May 2009 13:58:58 -0400
Subject: [PATCH] Step 4 of 8 Define the wire protocol format
---
qemud/remote_protocol.x | 18 +++++++++++++++++-
1 files changed, 17 insertions(+), 1 deletions(-)
diff --git a/qemud/remote_protocol.x b/qemud/remote_protocol.x
index 2d8e6a2..2c79949 100644
--- a/qemud/remote_protocol.x
+++ b/qemud/remote_protocol.x
@@ -1109,6 +1109,19 @@ struct remote_node_device_reset_args {
remote_nonnull_string name;
};
+struct remote_node_device_create_xml_args {
+ remote_nonnull_string xml_desc;
+ int flags;
+};
+
+struct remote_node_device_create_xml_ret {
+ remote_nonnull_node_device dev;
+};
+
+struct remote_node_device_destroy_args {
+ remote_nonnull_string name;
+};
+
/**
* Events Register/Deregister:
@@ -1270,7 +1283,10 @@ enum remote_procedure {
REMOTE_PROC_NODE_DEVICE_RESET = 120,
REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL = 121,
- REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122
+ REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122,
+
+ REMOTE_PROC_NODE_DEVICE_CREATE_XML = 123,
+ REMOTE_PROC_NODE_DEVICE_DESTROY = 124
};
/* Custom RPC structure. */
--
1.6.0.6

View File

@@ -1,84 +0,0 @@
From ff272552c297966ace3492aefe91fc830152251a Mon Sep 17 00:00:00 2001
From: David Allan <dallan@redhat.com>
Date: Tue, 19 May 2009 16:26:12 -0400
Subject: [PATCH] Step 5 of 8 Implement the RPC client
---
src/remote_internal.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/src/remote_internal.c b/src/remote_internal.c
index 4b3afb0..e665ef8 100644
--- a/src/remote_internal.c
+++ b/src/remote_internal.c
@@ -4978,6 +4978,59 @@ done:
}
+static virNodeDevicePtr
+remoteNodeDeviceCreateXML(virConnectPtr conn,
+ const char *xmlDesc,
+ unsigned int flags)
+{
+ remote_node_device_create_xml_args args;
+ remote_node_device_create_xml_ret ret;
+ virNodeDevicePtr dev = NULL;
+ struct private_data *priv = conn->privateData;
+
+ remoteDriverLock(priv);
+
+ memset(&ret, 0, sizeof ret);
+ args.xml_desc = (char *)xmlDesc;
+ args.flags = flags;
+
+ if (call(conn, priv, 0, REMOTE_PROC_NODE_DEVICE_CREATE_XML,
+ (xdrproc_t) xdr_remote_node_device_create_xml_args, (char *) &args,
+ (xdrproc_t) xdr_remote_node_device_create_xml_ret, (char *) &ret) == -1)
+ goto done;
+
+ dev = get_nonnull_node_device(conn, ret.dev);
+ xdr_free ((xdrproc_t) xdr_remote_node_device_create_xml_ret, (char *) &ret);
+
+done:
+ remoteDriverUnlock(priv);
+ return dev;
+}
+
+static int
+remoteNodeDeviceDestroy(virNodeDevicePtr dev)
+{
+ int rv = -1;
+ remote_node_device_destroy_args args;
+ struct private_data *priv = dev->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ args.name = dev->name;
+
+ if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_DESTROY,
+ (xdrproc_t) xdr_remote_node_device_destroy_args, (char *) &args,
+ (xdrproc_t) xdr_void, (char *) NULL) == -1)
+ goto done;
+
+ rv = 0;
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
+
/*----------------------------------------------------------------------*/
static int
@@ -6982,6 +7035,8 @@ static virDeviceMonitor dev_monitor = {
.deviceGetParent = remoteNodeDeviceGetParent,
.deviceNumOfCaps = remoteNodeDeviceNumOfCaps,
.deviceListCaps = remoteNodeDeviceListCaps,
+ .deviceCreateXML = remoteNodeDeviceCreateXML,
+ .deviceDestroy = remoteNodeDeviceDestroy
};
--
1.6.0.6

View File

@@ -1,70 +0,0 @@
From 4c5166df583459574526841234d61d6ae5be19a0 Mon Sep 17 00:00:00 2001
From: David Allan <dallan@redhat.com>
Date: Tue, 19 May 2009 16:26:55 -0400
Subject: [PATCH] Step 6 of 8 Implement the server side dispatcher
---
qemud/remote.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 48 insertions(+), 0 deletions(-)
diff --git a/qemud/remote.c b/qemud/remote.c
index e27820f..8d24a3a 100644
--- a/qemud/remote.c
+++ b/qemud/remote.c
@@ -4323,6 +4323,54 @@ remoteDispatchNodeDeviceReset (struct qemud_server *server ATTRIBUTE_UNUSED,
}
+static int
+remoteDispatchNodeDeviceCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_error *rerr,
+ remote_node_device_create_xml_args *args,
+ remote_node_device_create_xml_ret *ret)
+{
+ virNodeDevicePtr dev;
+
+ dev = virNodeDeviceCreateXML (conn, args->xml_desc, args->flags);
+ if (dev == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ make_nonnull_node_device (&ret->dev, dev);
+ virNodeDeviceFree(dev);
+
+ return 0;
+}
+
+
+static int
+remoteDispatchNodeDeviceDestroy(struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_error *rerr,
+ remote_node_device_destroy_args *args,
+ void *ret ATTRIBUTE_UNUSED)
+{
+ virNodeDevicePtr dev;
+
+ dev = virNodeDeviceLookupByName(conn, args->name);
+ if (dev == NULL) {
+ remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
+ return -1;
+ }
+
+ if (virNodeDeviceDestroy(dev) == -1) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ return 0;
+}
+
+
/**************************
* Async Events
**************************/
--
1.6.0.6

View File

@@ -1,132 +0,0 @@
From 193cc4abbb6c2fc5557d3699f86ff0103d5a21ef Mon Sep 17 00:00:00 2001
From: David Allan <dallan@redhat.com>
Date: Tue, 19 May 2009 16:47:31 -0400
Subject: [PATCH 8/8] Step 8 of 8 Add virsh support
---
src/virsh.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 103 insertions(+), 0 deletions(-)
diff --git a/src/virsh.c b/src/virsh.c
index cb32ede..ab2a2b7 100644
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -2962,6 +2962,107 @@ cmdPoolCreate(vshControl *ctl, const vshCmd *cmd)
/*
+ * "nodedev-create" command
+ */
+static const vshCmdInfo info_node_device_create[] = {
+ {"help", gettext_noop("create a device defined "
+ "by an XML file on the node")},
+ {"desc", gettext_noop("Create a device on the node. Note that this "
+ "command creates devices on the physical host "
+ "that can then be assigned to a virtual machine.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_node_device_create[] = {
+ {"file", VSH_OT_DATA, VSH_OFLAG_REQ,
+ gettext_noop("file containing an XML description of the device")},
+ {NULL, 0, 0, NULL}
+};
+
+static int
+cmdNodeDeviceCreate(vshControl *ctl, const vshCmd *cmd)
+{
+ virNodeDevicePtr dev = NULL;
+ char *from;
+ int found = 0;
+ int ret = TRUE;
+ char *buffer;
+
+ if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+ return FALSE;
+
+ from = vshCommandOptString(cmd, "file", &found);
+ if (!found) {
+ return FALSE;
+ }
+
+ if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
+ return FALSE;
+ }
+
+ dev = virNodeDeviceCreateXML(ctl->conn, buffer, 0);
+ free (buffer);
+
+ if (dev != NULL) {
+ vshPrint(ctl, _("Node device %s created from %s\n"),
+ virNodeDeviceGetName(dev), from);
+ } else {
+ vshError(ctl, FALSE, _("Failed to create node device from %s"), from);
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
+
+/*
+ * "nodedev-destroy" command
+ */
+static const vshCmdInfo info_node_device_destroy[] = {
+ {"help", gettext_noop("destroy a device on the node")},
+ {"desc", gettext_noop("Destroy a device on the node. Note that this "
+ "command destroys devices on the physical host ")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_node_device_destroy[] = {
+ {"name", VSH_OT_DATA, VSH_OFLAG_REQ,
+ gettext_noop("name of the device to be destroyed")},
+ {NULL, 0, 0, NULL}
+};
+
+static int
+cmdNodeDeviceDestroy(vshControl *ctl, const vshCmd *cmd)
+{
+ virNodeDevicePtr dev = NULL;
+ int ret = TRUE;
+ int found = 0;
+ char *name;
+
+ if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) {
+ return FALSE;
+ }
+
+ name = vshCommandOptString(cmd, "name", &found);
+ if (!found) {
+ return FALSE;
+ }
+
+ dev = virNodeDeviceLookupByName(ctl->conn, name);
+
+ if (virNodeDeviceDestroy(dev) == 0) {
+ vshPrint(ctl, _("Destroyed node device '%s'\n"), name);
+ } else {
+ vshError(ctl, FALSE, _("Failed to destroy node device '%s'"), name);
+ ret = FALSE;
+ }
+
+ virNodeDeviceFree(dev);
+ return ret;
+}
+
+
+/*
* XML Building helper for pool-define-as and pool-create-as
*/
static const vshCmdOptDef opts_pool_X_as[] = {
@@ -5895,6 +5996,8 @@ static const vshCmdDef commands[] = {
{"nodedev-dettach", cmdNodeDeviceDettach, opts_node_device_dettach, info_node_device_dettach},
{"nodedev-reattach", cmdNodeDeviceReAttach, opts_node_device_reattach, info_node_device_reattach},
{"nodedev-reset", cmdNodeDeviceReset, opts_node_device_reset, info_node_device_reset},
+ {"nodedev-create", cmdNodeDeviceCreate, opts_node_device_create, info_node_device_create},
+ {"nodedev-destroy", cmdNodeDeviceDestroy, opts_node_device_destroy, info_node_device_destroy},
{"pool-autostart", cmdPoolAutostart, opts_pool_autostart, info_pool_autostart},
{"pool-build", cmdPoolBuild, opts_pool_build, info_pool_build},
--
1.6.0.6

File diff suppressed because it is too large Load Diff

View File

@@ -1,142 +0,0 @@
<html>
<body>
<h1>Applications using <strong>libvirt</strong></h1>
<p>
This page provides an illustration of the wide variety of
applications using the libvirt management API. If you know
of interesting applications not listed on this page, send
a message to the <a href="contact.html">mailing list</a>
to request that it be added here. If your application uses
libvirt as its API, the following graphic is available for
your website to advertise support for libvirt:
</p>
<p class="image">
<img src="madeWith.png" alt="Made with libvirt"/>
</p>
<h2>Command line tools</h2>
<dl>
<dt>virsh</dt>
<dd>
An interactive shell, and batch scriptable tool for performing
management tasks on all libvirt managed domains, networks and
storage. This is part of the libvirt core distribution.
</dd>
<dt><a href="http://virt-manager.org/">virt-install</a></dt>
<dd>
Provides a way to provision new virtual machines from a
OS distribution install tree. It supports provisioning from
local CD images, and the network over NFS, HTTP and FTP.
</dd>
<dt><a href="http://virt-manager.org/">virt-clone</a></dt>
<dd>
Allows the disk image(s) and configuration for an existing
virtual machine to be cloned to form a new virtual machine.
It automates copying of data across to new disk images, and
updates the UUID, Mac address and name in the configuration
</dd>
<dt><a href="http://virt-manager.org/">virt-image</a></dt>
<dd>
Provides a way to deploy virtual appliances. It defines a
simplified portable XML format describing the pre-requisites
of a virtual machine. At time of deployment this is translated
into the domain XML format for execution under any libvirt
hypervisor meeting the pre-requisites.
</dd>
<dt><a href="http://et.redhat.com/~rjones/virt-df/">virt-df</a></dt>
<dd>
Examine the utilization of each filesystem in a virtual machine
from the comfort of the host machine. This tool peeks into the
guest disks and determines how much space is used. It can cope
with common Linux filesystems and LVM volumes.
</dd>
<dt><a href="http://et.redhat.com/~rjones/virt-top/">virt-top</a></dt>
<dd>
Watch the CPU, memory, network and disk utilization of all
virtual machines running on a host.
</dd>
</dl>
<h2>Desktop applications</h2>
<dl>
<dt><a href="http://virt-manager.org/">virt-manager</a></dt>
<dd>
A general purpose desktop management tool, able to manage
virtual machines across both local and remotely accessed
hypervisors. It is targeted at home and small office usage
upto managing 10-20 hosts and their VMs.
</dd>
<dt><a href="http://virt-manager.org/">virt-viewer</a></dt>
<dd>
A lightweight tool for accessing the graphical console
associated with a virtual machine. It can securely connect
to remote consoles supporting the VNC protocol. Also provides
an optional mozilla browser plugin.
</dd>
</dl>
<h2>Web applications</h2>
<dl>
<dt><a href="http://ovirt.org/">oVirt</a></dt>
<dd>
oVirt provides the ability to manage large numbers of virtual
machines across an entire data center of hosts. It integrates
with FreeIPA for Kerberos authentication, and in the future,
certificate management.
</dd>
<dt><a href="http://community.abiquo.com/display/AbiCloud">AbiCloud</a></dt>
<dd>
AbiCloud is an open source cloud platform manager which allows to
easily deploy a private cloud in your datacenter. One of the key
differences of AbiCloud is the web rich interface for managing the
infrastructure. You can deploy a new service just dragging and
dropping a VM.
</dd>
</dl>
<h2>LiveCD / Appliances</h2>
<dl>
<dt><a href="http://et.redhat.com/~rjones/virt-p2v/">virt-p2v</a></dt>
<dd>
A tool for converting a physical machine into a virtual machine. It
is a LiveCD which is booted on the machine to be converted. It collects
a little information from the user and then copies the disks over to
a remote machine and defines the XML for a domain to run the guest.
</dd>
</dl>
<h2>Monitoring plugins</h2>
<dl>
<dt><a href="http://honk.sigxcpu.org/projects/libvirt/#munin">for munin</a></dt>
<dd>
The plugins provided by Guido Günther allow to monitor various things
like network and block I/O with
<a href="http://munin.projects.linpro.no/">Munin</a>.
</dd>
<dt><a href="http://collectd.org/plugins/libvirt.shtml">for collectd</a></dt>
<dd>
The libvirt-plugin is part of <a href="http://collectd.org/">collectd</a>
and gather statistics about virtualized guests on a system. This
way, you can collect CPU, network interface and block device usage
for each guest without installing collectd on the guest systems.
or a full description of available please refer to the libvirt section
in the collectd.conf(5) manual page.
</dd>
<dt><a href="http://et.redhat.com/~rjones/nagios-virt/">nagios-virt</a></dt>
<dd>
Nagios-virt is a configuration tool for adding monitoring of your
virtualised domains to <a href="http://www.nagios.org/">Nagios</a>.
You can use this tool to either set up a new Nagios installation for
your Xen or QEMU/KVM guests, or to integrate with your existing Nagios
installation.
</dd>
</dl>
</body>
</html>

View File

@@ -1,5 +0,0 @@
<html>
<body>
<h1>Domain management architecture</h1>
</body>
</html>

View File

@@ -1,87 +0,0 @@
#FIG 3.2
Landscape
Center
Inches
Letter
100.00
Single
-2
1200 2
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
1050 7500 9375 7500 9375 8700 1050 8700 1050 7500
2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5
3525 7275 3525 4125 1050 4125 1050 7275 3525 7275
2 1 1 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2
1050 6540 3540 6525
2 4 0 1 0 7 50 -1 -1 4.000 0 0 7 0 0 5
1590 6900 1590 6645 1140 6645 1140 6900 1590 6900
2 4 0 1 0 7 50 -1 -1 4.000 0 0 7 0 0 5
1590 7185 1590 6930 1140 6930 1140 7185 1590 7185
2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
1 1 2.00 120.00 240.00
1 1 2.00 120.00 240.00
1875 7725 8625 7725
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
1650 5625 3000 5625 3000 6375 1650 6375 1650 5625
2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
1 1 2.00 120.00 240.00
2850 7725 2850 6375
2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5
6450 7275 6450 4125 3975 4125 3975 7275 6450 7275
2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5
9300 7275 9300 4125 6825 4125 6825 7275 9300 7275
2 1 1 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2
3975 6540 6465 6525
2 1 1 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2
6825 6540 9315 6525
2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
1 1 2.00 120.00 240.00
5400 7725 5400 7050
2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
1 1 2.00 120.00 240.00
8025 7725 8025 7050
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
1050 8925 9375 8925 9375 9900 1050 9900 1050 8925
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
2100 4575 3450 4575 3450 5325 2100 5325 2100 4575
2 1 1 3 0 7 50 -1 -1 2.000 0 0 -1 1 0 2
1 1 2.00 120.00 240.00
3225 5325 3225 8325
2 1 1 3 0 7 50 -1 -1 2.000 0 0 -1 1 0 2
1 1 2.00 120.00 240.00
6225 6900 6225 8250
2 1 1 3 0 7 50 -1 -1 2.000 0 0 -1 1 0 2
1 1 2.00 120.00 240.00
8925 6900 8925 8250
2 1 1 3 0 7 50 -1 -1 2.000 0 0 -1 1 0 2
1 1 2.00 120.00 240.00
1725 7125 1725 8325
2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
1 1 2.00 120.00 240.00
1 1 2.00 120.00 240.00
2850 5850 2850 5025
2 1 1 3 0 7 50 -1 -1 2.000 0 0 -1 1 0 2
1 1 2.00 120.00 240.00
5175 8475 5175 9375
2 1 1 3 0 7 50 -1 -1 2.000 0 0 -1 1 0 2
1 1 2.00 120.00 240.00
1350 7125 1350 9450
2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
1 1 2.00 120.00 240.00
2325 7725 2325 7200
2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 1
900 3975
2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 1
9525 9975
4 0 0 50 -1 0 18 0.0000 4 195 870 4350 7980 XenBus\001
4 0 0 50 -1 0 18 0.0000 4 195 780 1680 6870 drivers\001
4 0 0 50 -1 0 18 0.0000 4 195 1050 1800 6075 XenStore\001
4 0 0 50 -1 0 18 0.0000 4 195 900 1875 7125 Kernel0\001
4 0 0 50 -1 0 18 0.0000 4 195 960 4875 6975 KernelU\001
4 0 0 50 -1 0 18 0.0000 4 195 960 7650 6975 KernelU\001
4 0 0 50 -1 0 18 0.0000 4 255 1740 4050 8400 Xen Hypervisor\001
4 0 0 50 -1 0 18 0.0000 4 195 585 2325 4950 Xend\001
4 0 0 50 -1 0 18 0.0000 4 195 690 1200 4725 Dom0\001
4 0 0 50 -1 0 18 0.0000 4 195 750 4875 5325 DomU\001
4 0 0 50 -1 0 18 0.0000 4 195 750 7650 5325 DomU\001
4 0 0 50 -1 0 18 0.0000 4 195 1080 3750 9450 Hardware\001

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -1,101 +0,0 @@
<html>
<body>
<h1 >libvirt architecture</h1>
<p>Currently libvirt supports 2 kind of virtualization, and its
internal structure is based on a driver model which simplifies adding new
engines:</p>
<ul>
<li>
<a href="#Xen">Xen hypervisor</a>
</li>
<li>
<a href="#QEmu">QEmu and KVM based virtualization</a>
</li>
<li>
<a href="#drivers">the driver architecture</a>
</li>
</ul>
<h3>
<a name="Xen" id="Xen">Libvirt Xen support</a>
</h3>
<p>When running in a Xen environment, programs using libvirt have to execute
in "Domain 0", which is the primary Linux OS loaded on the machine. That OS
kernel provides most if not all of the actual drivers used by the set of
domains. It also runs the Xen Store, a database of information shared by the
hypervisor, the kernels, the drivers and the xen daemon. Xend. The xen daemon
supervise the control and execution of the sets of domains. The hypervisor,
drivers, kernels and daemons communicate though a shared system bus
implemented in the hypervisor. The figure below tries to provide a view of
this environment:</p>
<img src="architecture.gif" alt="The Xen architecture" />
<p>The library can be initialized in 2 ways depending on the level of
privilege of the embedding program. If it runs with root access,
virConnectOpen() can be used, it will use three different ways to connect to
the Xen infrastructure:</p>
<ul>
<li>a connection to the Xen Daemon though an HTTP RPC layer</li>
<li>a read/write connection to the Xen Store</li>
<li>use Xen Hypervisor calls</li>
<li>when used as non-root libvirt connect to a proxy daemon running
as root and providing read-only support</li>
</ul>
<p>The library will usually interact with the Xen daemon for any operation
changing the state of the system, but for performance and accuracy reasons
may talk directly to the hypervisor when gathering state information at
least when possible (i.e. when the running program using libvirt has root
privilege access).</p>
<p>If it runs without root access virConnectOpenReadOnly() should be used to
connect to initialize the library. It will then fork a libvirt_proxy
program running as root and providing read_only access to the API, this is
then only useful for reporting and monitoring.</p>
<h3>
<a name="QEmu" id="QEmu">Libvirt QEmu and KVM support</a>
</h3>
<p>The model for QEmu and KVM is completely similar, basically KVM is based
on QEmu for the process controlling a new domain, only small details differs
between the two. In both case the libvirt API is provided by a controlling
process forked by libvirt in the background and which launch and control the
QEmu or KVM process. That program called libvirt_qemud talks though a specific
protocol to the library, and connects to the console of the QEmu process in
order to control and report on its status. Libvirt tries to expose all the
emulations models of QEmu, the selection is done when creating the new
domain, by specifying the architecture and machine type targeted.</p>
<p>The code controlling the QEmu process is available in the
<code>qemud/</code> directory.</p>
<h3>
<a name="drivers" id="drivers">the driver based architecture</a>
</h3>
<p>As the previous section explains, libvirt can communicate using different
channels with the current hypervisor, and should also be able to use
different kind of hypervisor. To simplify the internal design, code, ease
maintenance and simplify the support of other virtualization engine the
internals have been structured as one core component, the libvirt.c module
acting as a front-end for the library API and a set of hypervisor drivers
defining a common set of routines. That way the Xen Daemon access, the Xen
Store one, the Hypervisor hypercall are all isolated in separate C modules
implementing at least a subset of the common operations defined by the
drivers present in driver.h:</p>
<ul>
<li>xend_internal: implements the driver functions though the Xen
Daemon</li>
<li>xs_internal: implements the subset of the driver available though the
Xen Store</li>
<li>xen_internal: provide the implementation of the functions possible via
direct hypervisor access</li>
<li>proxy_internal: provide read-only Xen access via a proxy, the proxy code
is in the <code>proxy/</code>directory.</li>
<li>xm_internal: provide support for Xen defined but not running
domains.</li>
<li>qemu_internal: implement the driver functions for QEmu and
KVM virtualization engines. It also uses a qemud/ specific daemon
which interacts with the QEmu process to implement libvirt API.</li>
<li>test: this is a test driver useful for regression tests of the
front-end part of libvirt.</li>
</ul>
<p>Note that a given driver may only implement a subset of those functions,
(for example saving a Xen domain state to disk and restoring it is only
possible though the Xen Daemon), in that case the driver entry points for
unsupported functions are initialized to NULL.</p>
<p></p>
</body>
</html>

View File

@@ -1,50 +0,0 @@
<html>
<body>
<h1>Network management architecture</h1>
<h2>Architecture illustration</h2>
<p>
The diagrams below illustrate some of the network configurations
enabled by the libvirt networking APIs
</p>
<ul>
<li><strong>VLAN 1</strong>. This virtual network has connectivity
to <code>LAN 2</code> with traffic forwarded and NATed.
</li>
<li><strong>VLAN 2</strong>. This virtual network is completely
isolated from any physical LAN.
</li>
<li><strong>Guest A</strong>. The first network interface is bridged
to the physical <code>LAN 1</code>. The second interface is connected
to a virtual network <code>VLAN 1</code>.
</li>
<li><strong>Guest B</strong>. The first network interface is connected
to a virtual network <code>VLAN 1</code>, giving it limited NAT
based connectivity to LAN2. It has a second network interface
connected to <code>VLAN 2</code>. It acts a router allowing limited
traffic between the two VLANs, thus giving <code>Guest C</code>
connectivity to the physical <code>LAN 2</code>.
</li>
<li><strong>Guest C</strong>. The only network interface is connected
to a virtual network <code>VLAN 2</code>. It has no direct connectivity
to a physical LAN, relying on <code>Guest B</codE> to route traffic
on its behalf.
</li>
</ul>
<h3>Logical diagram</h3>
<p class="image">
<img src="libvirt-net-logical.png" alt="Logical network architecture"/>
</p>
<h3>Physical diagram</h3>
<p class="image">
<img src="libvirt-net-physical.png" alt="Physical network architecture"/>
</p>
</body>
</html>

View File

@@ -1,5 +0,0 @@
<html>
<body>
<h1>Node device management architecture</h1>
</body>
</html>

View File

@@ -1,30 +0,0 @@
<html>
<body>
<h1>Storage management architecture</h1>
<p>
The storage management APIs are based around 2 core concepts
</p>
<ol>
<li>
<strong>Volume</strong> - a single storage volume which can
be assigned to a guest, or used for creating further pools. A
volume is either a block device, a raw file, or a special format
file.
</li>
<li>
<strong>Pool</strong> - provides a means for taking a chunk
of storage and carving it up into volumes. A pool can be used to
manage things such as a physical disk, a NFS server, a iSCSI target,
a host adapter, an LVM group.
</li>
</ol>
<p>
These two concepts are mapped through to two libvirt objects, a
<code>virStorageVolPtr</code> and a <code>virStoragePoolPtr</code>,
each with a collection of APIs for their management.
</p>
</body>
</html>

View File

@@ -1,187 +0,0 @@
<html>
<body>
<h1 >Access control</h1>
<p>
When connecting to libvirt, some connections may require client
authentication before allowing use of the APIs. The set of possible
authentication mechanisms is administrator controlled, independent
of applications using libvirt.
</p>
<ul>
<li>
<a href="#ACL_server_config">Server configuration</a>
</li>
<li>
<a href="#ACL_server_unix_perms">UNIX socket permissions/group</a>
</li>
<li>
<a href="#ACL_server_polkit">UNIX socket PolicyKit auth</a>
</li>
<li>
<a href="#ACL_server_username">Username/password auth</a>
</li>
<li>
<a href="#ACL_server_kerberos">Kerberos auth</a>
</li>
</ul>
<h3><a name="ACL_server_config">Server configuration</a></h3>
<p>
The libvirt daemon allows the administrator to choose the authentication
mechanisms used for client connections on each network socket independently.
This is primarily controlled via the libvirt daemon master config file in
<code>/etc/libvirt/libvirtd.conf</code>. Each of the libvirt sockets can
have its authentication mechanism configured independently. There is
currently a choice of <code>none</code>, <code>polkit</code>, and <code>sasl</code>.
The SASL scheme can be further configured to choose between a large
number of different mechanisms.
</p>
<h3><a name="ACL_server_unix_perms">UNIX socket permissions/group</a></h3>
<p>
If libvirt does not contain support for PolicyKit, then access control for
the UNIX domain socket is done using traditional file user/group ownership
and permissions. There are 2 sockets, one for full read-write access, the
other for read-only access. The RW socket will be restricted (mode 0700) to
only allow the <code>root</code> user to connect. The read-only socket will
be open access (mode 0777) to allow any user to connect.
</p>
<p>
To allow non-root users greater access, the <code>libvirtd.conf</code> file
can be edited to change the permissions via the <code>unix_sock_rw_perms</code>,
config parameter and to set a user group via the <code>unix_sock_group</code>
parameter. For example, setting the former to mode <code>0770</code> and the
latter <code>wheel</code> would let any user in the wheel group connect to
the libvirt daemon.
</p>
<h3><a name="ACL_server_polkit">UNIX socket PolicyKit auth</a></h3>
<p>
If libvirt contains support for PolicyKit, then access control options are
more advanced. The <code>unix_sock_auth</code> parameter will default to
<code>polkit</code>, and the file permissions will default to <code>0777</code>
even on the RW socket. Upon connecting to the socket, the client application
will be required to identify itself with PolicyKit. The default policy for the
RW daemon socket will require any application running in the current desktop
session to authenticate using the user's password. This is akin to <code>sudo</code>
auth, but does not require that the client application ultimately run as root.
Default policy will still allow any application to connect to the RO socket.
</p>
<p>
The default policy can be overridden by the administrator using the PolicyKit
master configuration file in <code>/etc/PolicyKit/PolicyKit.conf</code>. The
<code>PolicyKit.conf(5)</code> manual page provides details on the syntax
available. The two libvirt daemon actions available are named <code>org.libvirt.unix.monitor</code>
for the RO socket, and <code>org.libvirt.unix.manage</code> for the RW socket.
</p>
<p>
As an example, to allow a user <code>fred</code>full access to the RW socket,
while requiring <code>joe</code> to authenticate with the admin password,
would require adding the following snippet to <code>PolicyKit.conf</code>.
</p>
<pre>
&lt;match action="org.libvirt.unix.manage"&gt;
&lt;match user="fred"&gt;
&lt;return result="yes"/&gt;
&lt;/match&gt;
&lt;/match&gt;
&lt;match action="org.libvirt.unix.manage"&gt;
&lt;match user="joe"&gt;
&lt;return result="auth_admin"/&gt;
&lt;/match&gt;
&lt;/match&gt;
</pre>
<h3><a name="ACL_server_username">Username/password auth</a></h3>
<p>
The plain TCP socket of the libvirt daemon defaults to using SASL for authentication.
The SASL mechanism configured by default is DIGEST-MD5, which provides a basic
username+password style authentication. It also provides for encryption of the data
stream, so the security of the plain TCP socket is on a par with that of the TLS
socket. If desired the UNIX socket and TLS socket can also have SASL enabled by
setting the <code>auth_unix_ro</code>, <code>auth_unix_rw</code>, <code>auth_tls</code>
config params in <code>libvirt.conf</code>.
</p>
<p>
Out of the box, no user accounts are defined, so no clients will be able to authenticate
on the TCP socket. Adding users and setting their passwords is done with the <code>saslpasswd2</code>
command. When running this command it is important to tell it that the appname is <code>libvirt</code>.
As an example, to add a user <code>fred</code>, run
</p>
<pre>
# saslpasswd2 -a libvirt fred
Password: xxxxxx
Again (for verification): xxxxxx
</pre>
<p>
To see a list of all accounts the <code>sasldblistusers2</code> command can be used.
This command expects to be given the path to the libvirt user database, which is kept
in <code>/etc/libvirt/passwd.db</code>
</p>
<pre>
# sasldblistusers2 -f /etc/libvirt/passwd.db
fred@t60wlan.home.berrange.com: userPassword
</pre>
<p>
Finally, to disable a user's access, the <code>saslpasswd2</code> command can be used
again:
</p>
<pre>
# saslpasswd2 -a libvirt -d fred
</pre>
<h3><a name="ACL_server_kerberos">Kerberos auth</a></h3>
<p>
The plain TCP socket of the libvirt daemon defaults to using SASL for authentication.
The SASL mechanism configured by default is DIGEST-MD5, which provides a basic
username+password style authentication. To enable Kerberos single-sign-on instead,
the libvirt SASL configuration file must be changed. This is <code>/etc/sasl2/libvirt.conf</code>.
The <code>mech_list</code> parameter must first be changed to <code>gssapi</code>
instead of the default <code>digest-md5</code>. If SASL is enabled on the UNIX
and/or TLS sockets, Kerberos will also be used for them. Like DIGEST-MD5, the Kerberos
mechanism provides data encryption of the session.
</p>
<p>
Some operating systems do not install the SASL kerberos plugin by default. It
may be necessary to install a sub-package such as <code>cyrus-sasl-gssapi</code>.
To check whether the Kerberos plugin is installed run the <code>pluginviewer</code>
program and verify that <code>gssapi</code> is listed,eg:
</p>
<pre>
# pluginviewer
...snip...
Plugin "gssapiv2" [loaded], API version: 4
SASL mechanism: GSSAPI, best SSF: 56
security flags: NO_ANONYMOUS|NO_PLAINTEXT|NO_ACTIVE|PASS_CREDENTIALS|MUTUAL_AUTH
features: WANT_CLIENT_FIRST|PROXY_AUTHENTICATION|NEED_SERVER_FQDN
</pre>
<p>
Next it is necessary for the administrator of the Kerberos realm to issue a principle
for the libvirt server. There needs to be one principle per host running the libvirt
daemon. The principle should be named <code>libvirt/full.hostname@KERBEROS.REALM</code>.
This is typically done by running the <code>kadmin.local</code> command on the Kerberos
server, though some Kerberos servers have alternate ways of setting up service principles.
Once created, the principle should be exported to a keytab, copied to the host running
the libvirt daemon and placed in <code>/etc/libvirt/krb5.tab</code>
</p>
<pre>
# kadmin.local
kadmin.local: add_principal libvirt/foo.example.com
Enter password for principal "libvirt/foo.example.com@EXAMPLE.COM":
Re-enter password for principal "libvirt/foo.example.com@EXAMPLE.COM":
Principal "libvirt/foo.example.com@EXAMPLE.COM" created.
kadmin.local: ktadd -k /root/libvirt-foo-example.tab libvirt/foo.example.com@EXAMPLE.COM
Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/root/libvirt-foo-example.tab.
Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type ArcFour with HMAC/md5 added to keytab WRFILE:/root/libvirt-foo-example.tab.
Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type DES with HMAC/sha1 added to keytab WRFILE:/root/libvirt-foo-example.tab.
Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type DES cbc mode with RSA-MD5 added to keytab WRFILE:/root/libvirt-foo-example.tab.
kadmin.local: quit
# scp /root/libvirt-foo-example.tab root@foo.example.com:/etc/libvirt/krb5.tab
# rm /root/libvirt-foo-example.tab
</pre>
<p>
Any client application wishing to connect to a Kerberos enabled libvirt server
merely needs to run <code>kinit</code> to gain a user principle. This may well
be done automatically when a user logs into a desktop session, if PAM is setup
to authenticate against Kerberos.
</p>
</body>
</html>

View File

@@ -1,30 +0,0 @@
<html>
<body>
<h1 >Bindings for other languages</h1>
<p>Libvirt comes with bindings to support other languages than
pure <strong>C</strong>. First the headers embeds the necessary declarations to
allow direct access from <strong>C++</strong> code, but also we have bindings for
higher level kind of languages:</p>
<ul>
<li><strong>Python</strong>: Libvirt comes with direct support for the Python language
(just make sure you installed the libvirt-python package if not
compiling from sources). See below for more information about
using libvirt with python</li>
<li><strong>Perl</strong>: Daniel Berrange provides <a href="http://search.cpan.org/dist/Sys-Virt/">bindings for
Perl</a>.</li>
<li><strong>OCaml</strong>: Richard Jones supplies <a href="http://libvirt.org/ocaml/">bindings for OCaml</a>.</li>
<li><strong>Ruby</strong>: David Lutterkort provides <a href="http://libvirt.org/ruby/">bindings for Ruby</a>.</li>
<li><strong>Java</strong>: Daniel Veillard maintains <a href="java.html">Java bindings</a>.</li>
<li><strong>C#</strong>: Jarom&iacute;r &#x010C;ervenka maintains <a href="http://svn.i-tux.cz/listing.php?repname=SharpLibVirt">C# bindings here</a>.</li>
</ul>
<p>For information on using libvirt on <strong>Windows</strong>
<a href="windows.html">please see the Windows
support page</a>.
</p>
<p>Support, requests or help for libvirt bindings are welcome on
the <a href="https://www.redhat.com/mailman/listinfo/libvir-list/">mailing
list</a>, as usual try to provide enough background information
and make sure you use recent version, see the <a href="bugs.html">help
page</a>.</p>
</body>
</html>

View File

@@ -1,82 +0,0 @@
<?xml version="1.0"?>
<html>
<body>
<h1>Bug reporting</h1>
<p>
The <a href="http://bugzilla.redhat.com">Red Hat Bugzilla Server</a>
should be used to report bugs and request features against libvirt.
Before submitting a ticket, check the existing tickets to see if
the bug/feature is already tracked.
</p>
<h2>General libvirt bug reports</h2>
<p>
If you are using official libvirt binaries from a Linux distribution
check below for distribution specific bug reporting policies first.
For general libvirt bug reports, from self-built releases, CVS snapshots
and any other non-distribution supported builds, enter tickets under
the <code>Virtualization Tools</code> product and the <code>libvirt</code>
component.
</p>
<ul>
<li><a href="http://bugzilla.redhat.com/buglist.cgi?component=libvirt&amp;product=Virtualization%20Tools">View libvirt tickets</a></li>
<li><a href="http://bugzilla.redhat.com/bugzilla/enter_bug.cgi?product=Virtualization%20Tools&amp;component=libvirt">New libvirt ticket</a></li>
</ul>
<h2>Linux Distribution specific bug reports</h2>
<ul>
<li>
If you are using official binaries from a <strong>Fedora distribution</strong>, enter
tickets against the <code>Fedora</code> product and the <code>libvirt</code>
component.
<ul>
<li><a href="http://bugzilla.redhat.com/buglist.cgi?component=libvirt&amp;product=Fedora">View Fedora libvirt tickets</a></li>
<li><a href="http://bugzilla.redhat.com/bugzilla/enter_bug.cgi?product=Fedora&amp;component=libvirt">New Fedora libvirt ticket</a></li>
</ul>
</li>
<li>
If you are using official binaries from <strong>Red Hat Enterprise Linux distribution</strong>,
tickets against the <code>Red Hat Enterprise Linux 5</code> product and
the <code>libvirt</code> component.
<ul>
<li><a href="http://bugzilla.redhat.com/buglist.cgi?component=libvirt&amp;product=Red%20Hat%20Enterprise%20Linux%205">View Red Hat Enterprise Linux libvirt tickets</a></li>
<li><a href="http://bugzilla.redhat.com/bugzilla/enter_bug.cgi?product=Red%20Hat%20Enterprise%20Linux%205&amp;component=libvirt">New Red Hat Enterprise Linux libvirt ticket</a></li>
</ul>
</li>
<li>
If you are using official binaries from another Linux distribution first
follow their own bug reporting guidelines.
</li>
</ul>
<h2>How to file high quality bug reports</h2>
<p>
To increase the likelihood of your bug report being addressed it is
important to provide as much information as possible. When filing
libvirt bugs use this checklist to see if you are providing enough
information:
</p>
<ul>
<li>The version number of the libvirt build, or date of the CVS
checkout</li>
<li>The hardware architecture being used</li>
<li>The name of the hypervisor (Xen, QEMU, KVM)</li>
<li>The XML config of the guest domain if relevant</li>
<li>For Xen hypervisor, the XenD logfile from /var/log/xen</li>
<li>For QEMU/KVM, the domain logfile from /var/log/libvirt/qemu</li>
</ul>
<p>
If requesting a new feature attach any available patch to the ticket
and also email the patch to the libvirt mailing list for discussion
</p>
</body>
</html>

View File

@@ -1,37 +0,0 @@
<?xml version="1.0"?>
<html>
<body>
<h1>Contacting the development team</h1>
<h2>Mailing list</h2>
<p>
There is a mailing-list <a href="mailto:libvir-list@redhat.com">libvir-list@redhat.com</a> for libvirt,
with an <a href="https://www.redhat.com/archives/libvir-list/">on-line archive</a>.
Please subscribe to this list before posting by visiting the
<a href="https://www.redhat.com/mailman/listinfo/libvir-list">associated Web</a>
page and follow the instructions. Patches with explanations and provided as
attachments are really appreciated and will be discussed on the mailing list.
If possible generate the patches by using <code>cvs diff -up</code> in a CVS
checkout.
</p>
<h2>IRC discussion</h2>
<p>
Some of the libvirt developers may be found on IRC on the <a href="http://oftc.net">OFTC IRC</a>
network. Use the settings:
</p>
<ul>
<li>server: irc.oftc.net</li>
<li>port: 6667 (the usual IRC port)</li>
<li>channel: #virt</li>
</ul>
<p>
NB There is no guarantee that someone will be watching or able to reply
promptly, so use the mailing-list if you don't get an answer on the IRC
channel.
</p>
</body>
</html>

View File

@@ -1,46 +0,0 @@
<html>
<body>
<h1>Deployment</h1>
<h2>Pre-packaged releases</h2>
<p>
The libvirt API is now available in all major Linux distributions
so the simplest deployment approach is to use your distributions'
package management software to install the <code>libvirt</code>
module.
</p>
<h2>Self-built releases</h2>
<p>
libvirt uses GNU autotools for its build system, so deployment
follows the usual process of <code>configure; make ; make install</code>
</p>
<pre>
# ./configure --prefix=$HOME/usr
# make
# make install
</pre>
<h2>Built from CVS / GIT</h2>
<p>
When building from CVS it is necessary to generate the autotools
support files. This requires having <code>autoconf</code>,
<code>automake</code>, <code>libtool</code> and <code>intltool</code>
installed. The process can be automated with the <code>autogen.sh</code>
script.
</p>
<pre>
# ./autogen.sh --prefix=$HOME/usr
# make
# make install
</pre>
</body>
</html>

View File

@@ -1,4 +0,0 @@
Makefile
Makefile.in
libvirt.devhelp
*.html

Some files were not shown because too many files have changed in this diff Show More