1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-08-22 01:50:06 +03:00

Compare commits

..

147 Commits

Author SHA1 Message Date
2d0a9b97bb Prep for release 1.0.5.8 2013-12-14 14:26:49 -05:00
46a6015bec Tie SASL callbacks lifecycle to virNetSessionSASLContext
The array of sasl_callback_t callbacks which is passed to sasl_client_new()
must be kept alive as long as the created sasl_conn_t object is alive as
cyrus-sasl uses this structure internally for things like logging, so
the memory used for callbacks must only be freed after sasl_dispose() has
been called.

During testing of successful SASL logins with
virsh -c qemu+tls:///system list --all
I've been getting invalid read reports from valgrind

==9237== Invalid read of size 8
==9237==    at 0x6E93B6F: _sasl_getcallback (common.c:1745)
==9237==    by 0x6E95430: _sasl_log (common.c:1850)
==9237==    by 0x16593D87: digestmd5_client_mech_dispose (digestmd5.c:4580)
==9237==    by 0x6E91653: client_dispose (client.c:332)
==9237==    by 0x6E9476A: sasl_dispose (common.c:851)
==9237==    by 0x4E225A1: virNetSASLSessionDispose (virnetsaslcontext.c:678)
==9237==    by 0x4CBC551: virObjectUnref (virobject.c:262)
==9237==    by 0x4E254D1: virNetSocketDispose (virnetsocket.c:1042)
==9237==    by 0x4CBC551: virObjectUnref (virobject.c:262)
==9237==    by 0x4E2701C: virNetSocketEventFree (virnetsocket.c:1794)
==9237==    by 0x4C965D3: virEventPollCleanupHandles (vireventpoll.c:583)
==9237==    by 0x4C96987: virEventPollRunOnce (vireventpoll.c:652)
==9237==    by 0x4C94730: virEventRunDefaultImpl (virevent.c:274)
==9237==    by 0x12C7BA: vshEventLoop (virsh.c:2407)
==9237==    by 0x4CD3D04: virThreadHelper (virthreadpthread.c:161)
==9237==    by 0x7DAEF32: start_thread (pthread_create.c:309)
==9237==    by 0x8C86EAC: clone (clone.S:111)
==9237==  Address 0xe2d61b0 is 0 bytes inside a block of size 168 free'd
==9237==    at 0x4A07577: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==9237==    by 0x4C73827: virFree (viralloc.c:580)
==9237==    by 0x4DE4BC7: remoteAuthSASL (remote_driver.c:4219)
==9237==    by 0x4DE33D0: remoteAuthenticate (remote_driver.c:3639)
==9237==    by 0x4DDBFAA: doRemoteOpen (remote_driver.c:832)
==9237==    by 0x4DDC8DC: remoteConnectOpen (remote_driver.c:1031)
==9237==    by 0x4D8595F: do_open (libvirt.c:1239)
==9237==    by 0x4D863F3: virConnectOpenAuth (libvirt.c:1481)
==9237==    by 0x12762B: vshReconnect (virsh.c:337)
==9237==    by 0x12C9B0: vshInit (virsh.c:2470)
==9237==    by 0x12E9A5: main (virsh.c:3338)

This commit changes virNetSASLSessionNewClient() to take ownership of the SASL
callbacks. Then we can free them in virNetSASLSessionDispose() after the corresponding
sasl_conn_t has been freed.

(cherry picked from commit 13fdc6d63e)
2013-12-14 13:44:31 -05:00
140485abaf spec: Don't save/restore running VMs on libvirt-client update
The previous attempt (commit d65e0e1) removed just one of two
libvirt-guests restarts that happened on libvirt-client update. Let's
remove the last one too :-)

https://bugzilla.redhat.com/show_bug.cgi?id=962225

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
(cherry picked from commit 604f79b360)
2013-12-14 13:41:52 -05:00
dba6ded80d Return right error code for baselineCPU
This Python interface code is returning a -1 on errors for the
`baselineCPU' API.  Since this API is supposed to return a pointer
the error return value should really be VIR_PY_NONE.

NB:  I've checked all the other APIs in this file and this is the
only pointer API that is returning -1.

Signed-off-by: Don Dugger <donald.d.dugger@intel.com>

(crobinso: Upstream in libvirt-python.git)
2013-12-14 13:39:20 -05:00
390ed2087c spec: Don't save/restore running VMs on libvirt-client update
Restarting an active libvirt-guests.service is the equivalent of
doing:

/usr/libexec/libvirt-guests.sh stop
/usr/libexec/libvirt-guests.sh start

Which in a default configuration will managedsave every running VM,
and then restore them. Certainly not something we should do every
time the libvirt-client RPM is updated.

Just drop the try-restart attempt, I don't know what purpose it
serves anyways.

https://bugzilla.redhat.com/show_bug.cgi?id=962225
(cherry picked from commit d65e0e1466)
2013-11-22 09:33:59 -05:00
6b2e21795e Fix busy wait loop in LXC container I/O handling
If the host side of an LXC container console disconnected
and the guest side continued to write data, until the PTY
buffer filled up, the LXC controller would busy wait. It
would repeatedly see POLLHUP from poll() and not disable
the watch.

This was due to some bogus logic detecting blocking
conditions. Upon seeing a POLLHUP we must disable all
reading & writing from the PTY, and setup the epoll to
wake us up again when the connection comes back.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit 5087a5a009)
2013-11-20 10:32:25 -05:00
bd719a0114 libvirt-guests: Run only after libvirtd
Possible fix for occasional libvirt-guests failure at boot time:

https://bugzilla.redhat.com/show_bug.cgi?id=906009
(cherry picked from commit d92036754a)
2013-11-20 09:04:09 -05:00
777e19cb90 Don't depend on syslog.service
Syslog is socket activated since at least systemd v35 so we can drop
this dependency. Debian's linitian otherwise complains about it.

References:

    http://www.freedesktop.org/wiki/Software/systemd/syslog/
    http://lintian.debian.org/tags/systemd-service-file-refers-to-obsolete-target.html

(cherry picked from commit 3c9e40a1e8)
2013-11-20 09:04:06 -05:00
e51fa6486d libxl: fix dubious cpumask handling in libxlDomainSetVcpuAffinities
Rather than casting the virBitmap pointer to uint8_t* and then using
the structure contents as a byte array, use the virBitmap API to determine
the bitmap size and test each bit.

Signed-off-by: Jeremy Fitzhardinge <jeremy@goop.org>
(cherry picked from commit ba1bf10063)
2013-11-17 18:02:46 -05:00
9265a89ae8 util: recognize SMB/CIFS filesystems as shared
This should resolve:

  https://bugzilla.redhat.com/show_bug.cgi?id=1012085

libvirt previously recognized NFS, GFS2, OCFS2, and AFS filesystems as
"shared", and thus eligible for exceptions to certain rules/actions
about chowning image files before handing them off to a guest. This
patch widens the definition of "shared filesystem" to include SMB and
CIFS filesystems (aka "Windows file sharing"); both of these use the
same protocol, but different drivers so there are different magic
numbers for each.

(cherry picked from commit e4e73337e5)
2013-11-17 18:02:40 -05:00
b2c87be92e Disable nwfilter driver when running unprivileged
When opening a new connection to the driver, nwfilterOpen
only succeeds if the driverState has been allocated.

Move the privilege check in driver initialization before
the state allocation to disable the driver.

This changes the nwfilter-define error from:
error: cannot create config directory (null): Bad address
To:
this function is not supported by the connection driver:
virNWFilterDefineXML

https://bugzilla.redhat.com/show_bug.cgi?id=1029266
(cherry picked from commit b7829f959b)
2013-11-13 11:02:20 +01:00
c75683da9e spec: Explicitly require libgcrypt-devel
Our configure.ac says:

    Not all versions of gnutls include -lgcrypt, and so we add
    it explicitly for the calls to gcry_control/check_version

Thus we cannot rely on gnutls-devel to bring grcypt-devel as a
dependency.

(cherry picked from commit 3b50a711f0)
2013-11-06 13:55:32 -05:00
7fd01c6aa1 Prep for release 1.0.5.7 2013-11-06 12:36:15 -05:00
11253a09f2 qemuSetupMemoryCgroup: Handle hard_limit properly
Since 16bcb3 we have a regression. The hard_limit is set
unconditionally. By default the limit is zero. Hence, if user hasn't
configured any, we set the zero in cgroup subsystem making the kernel
kill the corresponding qemu process immediately. The proper fix is to
set hard_limit iff user has configured any.

(cherry picked from commit 94a24dd3a9)

Conflicts:
	src/qemu/qemu_cgroup.c
2013-11-06 12:16:25 -05:00
9421fd0010 qemu: Drop qemuDomainMemoryLimit
This function is to guess the correct limit for maximal memory
usage by qemu for given domain. This can never be guessed
correctly, not to mention all the pains and sleepless nights this
code has caused. Once somebody discovers algorithm to solve the
Halting Problem, we can compute the limit algorithmically. But
till then, this code should never see the light of the release
again.

(cherry picked from commit 16bcb3b616)

Conflicts:
	src/qemu/qemu_cgroup.c
	src/qemu/qemu_command.c
	src/qemu/qemu_domain.c
	src/qemu/qemu_domain.h
	src/qemu/qemu_hotplug.c
2013-11-06 11:42:45 -05:00
03ba101aa2 remote: fix regression in event deregistration
Introduced by 7b87a3
When I quit the process which only register VIR_DOMAIN_EVENT_ID_REBOOT,
I got error like:
"libvirt: XML-RPC error : internal error: domain event 0 not registered".
Then I add the following code, it fixed.

Signed-off-by: Zhou Yimin <zhouyimin@huawei.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 9712c2510e)
2013-10-18 07:56:11 -06:00
99fa1ade4b virsh: Fix debugging
Commit a0b6a36f "fixed" what abfff210 broke (URI precedence), but
there was still one more thing missing to fix.  When using virsh
parameters to setup debugging, those weren't honored, because at the
time debugging was initializing, arguments weren't parsed yet.  To
make ewerything work as expected, we need to initialize the debugging
twice, once before debugging (so we can debug option parsing properly)
and then again after these options are parsed.

As a side effect, this patch also fixes a leak when virsh is ran with
multiple '-l' parameters.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
(cherry picked from commit ac43da705f)
2013-10-18 08:11:34 +02:00
4c881b5503 Fix URI connect precedence
Commit abfff210 changed the order of vshParseArgv() and vshInit() in
order to make fix debugging of parameter parsing.  However, vshInit()
did a vshReconnect() even though ctl->name wasn't set according to the
'-c' parameter yet.  In order to keep both issues fixed, I've split
the vshInit() into vshInitDebug() and vshInit().

One simple memleak of ctl->name is fixed as a part of this patch,
since it is related to the issue it's fixing.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=999323
(cherry picked from commit a0b6a36f94)
2013-10-15 15:48:22 +02:00
cdc148ec5b virDomainDefParseXML: set the argument of virBitmapFree to NULL after calling virBitmapFree
After freeing the bitmap pointer, it must set the pointer to NULL.
This will avoid any other use of the freed memory of the bitmap pointer.

https://bugzilla.redhat.com/show_bug.cgi?id=1006710

Signed-off-by: Liuji (Jeremy) <jeremy.liu@huawei.com>
(cherry picked from commit ef5d51d491)
2013-10-15 15:17:44 +02:00
e69a585db4 build: Add lxc testcase to dist list
Introduced by commit 3f029fb531 the RPM build
was broken due to a missing LXC textcase.

Signed-off-by: Daniel Hansel <daniel.hansel@linux.vnet.ibm.com>
(cherry picked from commit 6285c17f79)
2013-10-15 15:17:33 +02:00
34ba55e9e2 LXC: Fix handling of RAM filesystem size units
Since 76b644c when the support for RAM filesystems was introduced,
libvirt accepted the following XML:
<source usage='1024' unit='KiB'/>

This was parsed correctly and internally stored in bytes, but it
was formatted as (with an extra 's'):
<source usage='1024' units='KiB'/>
When read again, this was treated as if the units were missing,
meaning libvirt was unable to parse its own XML correctly.

The usage attribute was documented as being in KiB, but it was not
scaled if the unit was missing. Transient domains still worked,
because this was balanced by an extra 'k' in the mount options.

This patch:
Changes the parser to use 'units' instead of 'unit', as the latter
was never documented (fixing persistent domains) and some programs
(libvirt-glib, libvirt-sandbox) already parse the 'units' attribute.

Removes the extra 'k' from the tmpfs mount options, which is needed
because now we parse our own XML correctly.

Changes the default input unit to KiB to match documentation, fixing:
https://bugzilla.redhat.com/show_bug.cgi?id=1015689
(cherry picked from commit 3f029fb531)

Conflicts:
	src/conf/domain_conf.c
	src/conf/domain_conf.h - missing format
	src/lxc/lxc_container.c - virAsprintf doesn't report OOM errors
	tests/lxcxml2xmltest.c - missing format test
2013-10-15 13:26:55 +02:00
5b2b4d5e63 qemuMonitorJSONSendKey: Avoid double free
After successful @cmd construction the memory where @keys points to is
part of @cmd. Avoid double freeing it.
(cherry picked from commit 3e8343e151)
2013-10-15 13:26:55 +02:00
168f70cfe9 virsh domjobinfo: Do not return 1 if job is NONE
https://bugzilla.redhat.com/show_bug.cgi?id=1006864

Commit 38ab1225 changed the default value of ret from true to false but
forgot to set ret = true when job is NONE. Thus, virsh domjobinfo
returned 1 when there was no job running for a domain but it used to
(and should) return 0 in this case.
(cherry picked from commit f084caae7c)
2013-10-15 13:26:55 +02:00
c22cb488de Remove use of virConnectPtr from all remaining nwfilter code
The virConnectPtr is passed around loads of nwfilter code in
order to provide it as a parameter to the callback registered
by the virt drivers. None of the virt drivers use this param
though, so it serves no purpose.

Avoiding the need to pass a virConnectPtr means that the
nwfilterStateReload method no longer needs to open a bogus
QEMU driver connection. This addresses a race condition that
can lead to a crash on startup.

The nwfilter driver starts before the QEMU driver and registers
some callbacks with DBus to detect firewalld reload. If the
firewalld reload happens while the QEMU driver is still starting
up though, the nwfilterStateReload method will open a connection
to the partially initialized QEMU driver and cause a crash.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit 999d72fbd5)

Conflicts:
	src/nwfilter/nwfilter_driver.c
2013-10-07 09:55:30 -04:00
0b9f930836 Don't pass virConnectPtr in nwfilter 'struct domUpdateCBStruct'
The nwfilter driver only needs a reference to its private
state object, not a full virConnectPtr. Update the domUpdateCBStruct
struct to have a 'void *opaque' field instead of a virConnectPtr.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit ebca369e3f)
2013-10-07 09:53:33 -04:00
3598addc9e Remove virConnectPtr arg from virNWFilterDefParse*
None of the virNWFilterDefParse* methods require a virConnectPtr
arg, so just drop it

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit b77b16ce41)

Conflicts:
	tests/nwfilterxml2xmltest.c
2013-10-07 09:53:23 -04:00
f22180a383 virNetDevBandwidthEqual: Make it more robust
So far the virNetDevBandwidthEqual() expected both ->in and ->out items
to be allocated for both @a and @b compared. This is not necessary true
for all our code. For instance, running 'update-device' twice over a NIC
with the very same XML results in SIGSEGV-ing in this function.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit ee02fbc8e4)
2013-10-07 09:51:48 -04:00
e6f4742b97 qemu_hotplug: Allow QoS update in qemuDomainChangeNet
The qemuDomainChangeNet() is called when 'virsh update-device' is
invoked on a NIC. Currently, we fail to update the QoS even though
we have routines for that.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 9fa10d3901)
2013-10-07 09:51:48 -04:00
eaf803e7f0 qemu: Use "migratable" XML definition when doing external checkpoints
In the original implementation of external checkpoints I've mistakenly
used the live definition to be stored in the save image. The normal
approach is to use the "migratable" definition. This was discovered when
commit 07966f6a8b changed the behavior to
use a converted XML from the user to do the compatibility check to fix
problem when using the regular machine saving.

As the previous patch added a compatibility layer, we can now change the
type of the XML in the image.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1008340
(cherry picked from commit 1b7bfa65e3)
2013-10-06 14:46:18 -04:00
51a1506b29 qemu: Fix checking of ABI stability when restoring external checkpoints
External checkpoints have a bug in the implementation where they use the
normal definition instead of the "migratable" one. This causes errors
when the snapshot is being reverted using the workaround method via
qemuDomainRestoreFlags() with a custom XML. This issue was introduced
when commit 07966f6a8b changed the code to
compare "migratable" XMLs from the user as we should have used
migratable in the image too.

This patch adds a compatibility layer, so that fixing the snapshot code
won't make existing snapshots fail to load.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1008340
(cherry picked from commit 59898a88ce)
2013-10-06 14:46:18 -04:00
729bd0a37a virsh: Fix regression of vol-resize
Introduced by commit 1daa4ba33a. vshCommandOptStringReq returns
0 on *success* or the option is not required && not present, both
are right result. Error out when returning 0 is not correct.
the caller, it doesn't have to check wether it
(cherry picked from commit 2a3a725c33)
2013-10-03 10:00:05 +02:00
3e070c81ab Prep for release 1.0.5.6 2013-09-20 16:30:44 -04:00
ff165c6a92 virsh: fix change-media bug on disk block type
Resolves:https://bugzilla.redhat.com/show_bug.cgi?id=923053
When cdrom is block type, the virsh change-media failed to insert
source info because virsh uses "<source block='/dev/sdb'/>" while
the correct name of the attribute for block disks is "dev".

(cherry picked from commit 7729a16814)
2013-09-20 15:54:53 -04:00
118d26dc1f Fix crash in remoteDispatchDomainMemoryStats (CVE-2013-4296)
The 'stats' variable was not initialized to NULL, so if some
early validation of the RPC call fails, it is possible to jump
to the 'cleanup' label and VIR_FREE an uninitialized pointer.
This is a security flaw, since the API can be called from a
readonly connection which can trigger the validation checks.

This was introduced in release v0.9.1 onwards by

  commit 158ba8730e
  Author: Daniel P. Berrange <berrange@redhat.com>
  Date:   Wed Apr 13 16:21:35 2011 +0100

    Merge all returns paths from dispatcher into single path

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit e7f400a110)

Conflicts:
	daemon/remote.c - context
2013-09-18 14:03:38 -06:00
85ca41529d Add support for using 3-arg pkcheck syntax for process (CVE-2013-4311)
With the existing pkcheck (pid, start time) tuple for identifying
the process, there is a race condition, where a process can make
a libvirt RPC call and in another thread exec a setuid application,
causing it to change to effective UID 0. This in turn causes polkit
to do its permission check based on the wrong UID.

To address this, libvirt must get the UID the caller had at time
of connect() (from SO_PEERCRED) and pass a (pid, start time, uid)
triple to the pkcheck program.

Signed-off-by: Colin Walters <walters@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit 922b7fda77)

Conflicts:
	src/access/viraccessdriverpolkit.c

Resolution:
  Dropped file that does not exist in this branch.
2013-09-18 12:22:38 -06:00
4407b19b83 Include process start time when doing polkit checks
Since PIDs can be reused, polkit prefers to be given
a (PID,start time) pair. If given a PID on its own,
it will attempt to lookup the start time in /proc/pid/stat,
though this is subject to races.

It is safer if the client app resolves the PID start
time itself, because as long as the app has the client
socket open, the client PID won't be reused.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit 979e9c56a7)
Signed-off-by: Eric Blake <eblake@redhat.com>

Conflicts:
	src/rpc/virnetsocket.h - context
	src/util/virprocess.c - needed #include "virstring.h"
	src/util/virstring.c - context
	src/util/virstring.h - context
2013-09-18 12:22:25 -06:00
073812898a qemuDomainChangeGraphics: Check listen address change by listen type
https://bugzilla.redhat.com/show_bug.cgi?id=1006697

Currently, we have a bug when updating a graphics device. A graphics device can
have a listen address set. This address is either defined by user (in which case
it's type is VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) or it can be inherited
from a network (in which case it's type is
VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK). However, in both cases we have a
listen address to process (e.g. during migration, as I've tried to fix in
7f15ebc7).
Later, when a user tries to update the graphics device (e.g. set a password),
we check if listen addresses match the original as qemu doesn't know how to
change listen address yet. Hence, users are required to not change the listen
address. The implementation then just dumps listen addresses and compare them.
Previously, while dumping the listen addresses, NULL was returned for NETWORK.
After my patch, this is no longer true, and we get a listen address for olddev
even if it is a type of NETWORK. So we have a real string on one side, the NULL
from user's XML on the other side and hence we think user wants to change the
listen address and we refuse it.

Therefore, we must take the type of listen address into account as well.

(cherry picked from commit 752596b5dd)
2013-09-11 20:27:22 -06:00
9a1145a987 security: provide supplemental groups even when parsing label (CVE-2013-4291)
Commit 29fe5d7 (released in 1.1.1) introduced a latent problem
for any caller of virSecurityManagerSetProcessLabel and where
the domain already had a uid:gid label to be parsed.  Such a
setup would collect the list of supplementary groups during
virSecurityManagerPreFork, but then ignores that information,
and thus fails to call setgroups() to adjust the supplementary
groups of the process.

Upstream does not use virSecurityManagerSetProcessLabel for
qemu (it uses virSecurityManagerSetChildProcessLabel instead),
so this problem remained latent until backporting the initial
commit into v0.10.2-maint (commit c061ff5, released in 0.10.2.7),
where virSecurityManagerSetChildProcessLabel has not been
backported.  As a result of using a different code path in the
backport, attempts to start a qemu domain that runs as qemu:qemu
will end up with supplementary groups unchanged from the libvirtd
parent process, rather than the desired supplementary groups of
the qemu user.  This can lead to failure to start a domain
(typical Fedora setup assigns user 107 'qemu' to both group 107
'qemu' and group 36 'kvm', so a disk image that is only readable
under kvm group rights is locked out).  Worse, it is a security
hole (the qemu process will inherit supplemental group rights
from the parent libvirtd process, which means it has access
rights to files owned by group 0 even when such files should
not normally be visible to user qemu).

LXC does not use the DAC security driver, so it is not vulnerable
at this time.  Still, it is better to plug the latent hole on
the master branch first, before cherry-picking it to the only
vulnerable branch v0.10.2-maint.

* src/security/security_dac.c (virSecurityDACGetIds): Always populate
groups and ngroups, rather than only when no label is parsed.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 745aa55fbf)
2013-08-29 09:17:31 -06:00
c43e7e20fc python: return dictionary without value in case of no blockjob
https://bugzilla.redhat.com/show_bug.cgi?id=999077

Currently, when there is no blockjob, dom.blockJobInfo('vda')
still reports error because it doesn't distinguish return value 0 from -1.
libvirt.libvirtError: virDomainGetBlockJobInfo() failed

virDomainGetBlockJobInfo() API return value:
 -1 in case of failure, 0 when nothing found, 1 found.

And use PyDict_SetItemString instead of PyDict_SetItem when key is
of string type. PyDict_SetItemString increments key/value reference
count, so call Py_DECREF() for value. For key, we don't need to
do this, because PyDict_SetItemString will handle it internally.

(cherry picked from commit 0f9e67bfad)
2013-08-20 11:44:55 -06:00
1ffdaced5b virbitmap: Refactor virBitmapParse to avoid access beyond bounds of array
The virBitmapParse function was calling virBitmapIsSet() function that
requires the caller to check the bounds of the bitmap without checking
them. This resulted into crashes when parsing a bitmap string that was
exceeding the bounds used as argument.

This patch refactors the function to use virBitmapSetBit without
checking if the bit is set (this function does the checks internally)
and then counts the bits in the bitmap afterwards (instead of keeping
track while parsing the string).

This patch also changes the "parse_error" label to a more common
"error".

The refactor should also get rid of the need to call sa_assert on the
returned variable as the callpath should allow coverity to infer the
possible return values.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=997367

Thanks to Alex Jia for tracking down the issue. This issue is introduced
by commit 0fc8909.

(cherry picked from commit 47b9127e88)
2013-08-20 14:13:43 +02:00
ed5274ca2e Prep for release 1.0.5.5 2013-08-01 17:48:53 -04:00
f32ea9937f Set the number of elements 0 in virNetwork*Clear
Decrementing it when it was already 0 causes an invalid free
in virNetworkDefUpdateDNSHost if virNetworkDNSHostDefParseXML
fails and virNetworkDNSHostDefClear gets called twice.

virNetworkForwardDefClear left the number untouched even if it
freed all the elements.
(cherry picked from commit c4e23388e6)
2013-08-01 17:14:41 +02:00
80fffee94b Don't check validity of missing attributes in DNS SRV XML
This fixes a crash if one of them is missing.

https://bugzilla.redhat.com/show_bug.cgi?id=988718
(cherry picked from commit 461fd86a66)
2013-08-01 17:14:27 +02:00
90688b148c cgroup: reuse buffer for getline
Reuse the buffer for getline and track buffer allocation
separately from the string length to prevent unlikely
out-of-bounds memory access.

This fixes the following leak that happened when zero bytes were read:

==404== 120 bytes in 1 blocks are definitely lost in loss record 1,344 of 1,671
==404==    at 0x4C2C71B: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==404==    by 0x906F862: getdelim (iogetdelim.c:68)
==404==    by 0x52A48FB: virCgroupPartitionNeedsEscaping (vircgroup.c:1136)
==404==    by 0x52A0FB4: virCgroupPartitionEscape (vircgroup.c:1171)
==404==    by 0x52A0EA4: virCgroupNewDomainPartition (vircgroup.c:1450)
(cherry picked from commit cc7329317f)
2013-08-01 17:14:14 +02:00
c636c41af7 rbd: Do not free the secret if it is not set
Not all RBD (Ceph) storage pools have cephx authentication turned on,
so "secret" might not be initialized.

It could also be that the secret couldn't be located.

Only call virSecretFree() if "secret" is initialized earlier.

Signed-off-by: Wido den Hollander <wido@widodh.nl>
(cherry picked from commit d58c847844)
2013-08-01 17:13:58 +02:00
146d12c6cc caps: use -device for primary video when qemu >=1.6
libvirt: https://bugzilla.redhat.com/show_bug.cgi?id=986384

qemu: https://bugzilla.redhat.com/show_bug.cgi?id=981094
The commit 0ad9025ef introduce qemu flag QEMU_CAPS_DEVICE_VIDEO_PRIMARY
for using -device VGA, -device cirrus-vga, -device vmware-svga and
-device qxl-vga. In use, for -device qxl-vga, mouse doesn't display
in guest window like the desciption in above bug.
This patch try to use -device for primary video when qemu >=1.6 which
contains the bug fix patch

(cherry picked from commit e3f2686bdf)

Conflicts:
	src/qemu/qemu_capabilities.c - context with other new capabilities not backported
2013-07-29 16:43:05 -06:00
ad4e7f90b4 examples: fix mingw build vs. printf
Mingw *printf is a moving target; newer mingw now provides a version
of asprintf() that fails to understand %lld:

  CC       event_test-event-test.o
../../../../examples/domain-events/events-c/event-test.c: In function 'myDomainEventRTCChangeCallback':
../../../../examples/domain-events/events-c/event-test.c:270:18: error: unknown conversion type character 'l' in format [-Werror=format=]
                  virDomainGetID(dom), offset) < 0)
                  ^

But since our examples already admitted that they were hacking around
a mingw deficiency, it is easier to just use printf() directly, coupled
with <inttypes.h> macros, for a more portable work-around.

* examples/domain-events/events-c/event-test.c
(myDomainEventRTCChangeCallback): Use PRIdMAX instead of asprintf.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 6f4458a017)
2013-07-29 16:20:29 -06:00
ec15df4e85 build: fix virutil build on mingw
https://bugzilla.redhat.com/show_bug.cgi?id=964358

On platforms without decent group support, the build failed:

Cannot export virGetGroupList: symbol not defined
./.libs/libvirt_security_manager.a(libvirt_security_manager_la-security_dac.o): In function `virSecurityDACPreFork':
/home/eblake/libvirt-tmp/build/src/../../src/security/security_dac.c:248: undefined reference to `virGetGroupList'
collect2: error: ld returned 1 exit status

* src/util/virutil.c (virGetGroupList): Provide dummy implementation.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit cd725c7a93)
2013-07-29 16:17:40 -06:00
aa11d6888f build: work around mingw header pollution
On Fedora 18, when cross-compiling to mingw with the mingw*-dbus
packages installed, compilation fails with:

  CC       libvirt_net_rpc_server_la-virnetserver.lo
In file included from /usr/i686-w64-mingw32/sys-root/mingw/include/dbus-1.0/dbus/dbus-connection.h:32:0,
                 from /usr/i686-w64-mingw32/sys-root/mingw/include/dbus-1.0/dbus/dbus-bus.h:30,
                 from /usr/i686-w64-mingw32/sys-root/mingw/include/dbus-1.0/dbus/dbus.h:31,
                 from ../../src/util/virdbus.h:26,
                 from ../../src/rpc/virnetserver.c:39:
/usr/i686-w64-mingw32/sys-root/mingw/include/dbus-1.0/dbus/dbus-message.h:74:58: error: expected ';', ',' or ')' before 'struct'

I have reported this as a bug against two packages:
- mingw-headers, for polluting the namespace
https://bugzilla.redhat.com/show_bug.cgi?id=980270
- dbus, for not dealing with the pollution
https://bugzilla.redhat.com/show_bug.cgi?id=980278

At least dbus has agreed that a future version of dbus headers will
do s/interface/iface/, regardless of what happens in mingw. But it
is also easy to workaround in libvirt in the meantime, without having
to wait for either mingw or dbus to upgrade.

* src/util/virdbus.h (includes): Undo mingw's pollution so that
dbus doesn't fail.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 1528e8b23a)
2013-07-29 16:13:48 -06:00
543e5adf05 build: configure must not affect tarball contents
On mingw, configure sets the name of the lxc symfile to
libvirt_lxc.defs rather than libvirt_lxc.syms.  But tarballs
must be arch-independent, regardless of the configure options
used for the tree where we ran 'make dist'.  This led to the
following failure in autobuild.sh:

  CCLD     libvirt-lxc.la
  CCLD     libvirt-qemu.la
/usr/lib64/gcc/i686-w64-mingw32/4.7.2/../../../../i686-w64-mingw32/bin/ld: cannot find libvirt_lxc.def: No such file or directory
collect2: error: ld returned 1 exit status
make[3]: *** [libvirt-lxc.la] Error 1
make[3]: *** Waiting for unfinished jobs....

We were already doing the right thing with libvirt_qemu.syms.

* src/Makefile.am (EXTRA_DIST): Don't ship a built file which
depends on configure for its final name.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit d79c9273b0)
2013-07-29 16:13:44 -06:00
ef10647e2e build: avoid build failure without gnutls
Found while trying to cross-compile to mingw:

  CC       libvirt_driver_remote_la-remote_driver.lo
../../src/remote/remote_driver.c: In function 'doRemoteOpen':
../../src/remote/remote_driver.c:487:23: error: variable 'verify' set but not used [-Werror=unused-but-set-variable]

* src/remote/remote_driver.c (doRemoteOpen): Also ignore 'verify'.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 4e6a78e712)
2013-07-29 16:10:55 -06:00
15bde978da Fix build with clang
Partially revert cdd703f's revert of c163410, as linking with clang
with --param=ssp-buffer-size=4 still fails with:
"argument unused during compilation".

(cherry picked from commit 4b91dc24d1)
2013-07-29 15:59:21 -06:00
ab9ff9ed37 maint: update to latest gnulib
Upstream gnulib recently patched a bug in bootstrap, for projects
that use a different name than build-aux for a subdirectory.  We
don't, but it doesn't hurt to update.

* .gnulib: Update, for bootstrap fix.
* bootstrap: Sync to upstream.
* bootstrap.conf: Match upstream bug fix.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit ac0852c72a)
2013-07-29 15:59:14 -06:00
4a10d56125 maint: update to latest gnulib
Future patches need LGPLv2+ versions of some modules that had
recent license changes; but separating the gnulib update from
the actual use of the modules makes it easier to backport to
an older version while avoiding a submodule update (assuming,
of course, that the backport is to a system where glibc provides
adequate functionaliy without needing the gnulib module).

* .gnulib: Update to latest, for modules needed in later patches.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 7961ad2107)
2013-07-29 15:59:08 -06:00
29e57f770b build: honor autogen.sh --no-git
Based on a report by Chandrashekar Shastri, at
https://bugzilla.redhat.com/show_bug.cgi?id=979360

On systems where git cannot access the outside world, a developer
can instead arrange to get a copy of gnulib at the right commit
via side channels (such as NFS share drives), set GNULIB_SRCDIR,
then use ./autogen.sh --no-git.  In this setup, we will now
avoid direct use of git.  Of course, this means no automatic
gnulib updates when libvirt.git updates its submodule, but it
is expected that any developer in such a situation is already
prepared to deal with the fallout.

* .gnulib: Update to latest, for bootstrap.
* bootstrap: Synchronize from gnulib.
* autogen.sh (no_git): Avoid git when requested.
* cfg.mk (_update_required): Skip automatic rerun of bootstrap if
we can't use git.
* docs/compiling.html.in: Document this setup.
* docs/hacking.html.in: Mention this.
* HACKING: Regenerate.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 1e503ee534)
2013-07-29 15:58:59 -06:00
ed3a0d830f maint: update to latest gnulib
The latest mingw headers on Fedora 19 fail to build with gnulib
without an update.

Meanwhile, now that upstream gnulib has better handling of -W
probing for clang, we can drop some of our own solutions in
favor of upstream; thus this reverts commit c1634100, "Correctly
detect warning flags with clang".

* .gnulib: Update to latest, for mingw and clang.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit cdd703f475)
2013-07-29 15:58:36 -06:00
f3b9bb7d4e FreeBSD: disable buggy -fstack-protector-all
FreeBSD ships an old gcc 4.2.1 which generates
bogus code, e.g. getsockopt() call returns
struct xucred with bogus values, which doesn't even
allow to connect to libvirtd:

error: Failed to find group record for gid '1284660778': No error: 0

So roll back to just -fstack-protector on FreeBSD.

(cherry picked from commit cc7cd6232e)
2013-07-29 15:58:34 -06:00
6fd56b7e20 build: update to latest gnulib, for syntax-check
This picks up a fix for a syntax-check weakness mentioned here:
https://www.redhat.com/archives/libvir-list/2013-May/msg00811.html

* .gnulib: Update to latest, for maint.mk improvement.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 12bd22c70d)
2013-07-29 15:55:05 -06:00
a2d23560d0 maint: update to latest gnulib
Among others, this fixes a cosmetic bug where bootstrap stated:

./bootstrap: Bootstrapping from checked-out http://libvirt.org sources...

instead of the intended:

./bootstrap: Bootstrapping from checked-out libvirt sources...

* .gnulib: Update to latest, for bootstrap improvement.
* bootstrap: Resync from gnulib.

(cherry picked from commit 3dfc2b71aa)
2013-07-29 15:54:47 -06:00
a10d077ef2 lxc: correctly backport /dev/tty fix
https://bugzilla.redhat.com/show_bug.cgi?id=982317

maint-only patch; reported by Geert Jansen

Commit 17cdc298 tried to backport upstream 90a0c6d, but in
resolving conflicts, failed to account that upstream commit
e1d32bb refactored code to leave off a leading /dev.

* src/lxc/lxc_container.c (lxcContainerPopulateDevices): Use
correct device name.

Signed-off-by: Eric Blake <eblake@redhat.com>
2013-07-29 15:49:22 -06:00
6598510159 security: fix deadlock with prefork
https://bugzilla.redhat.com/show_bug.cgi?id=964358

Attempts to start a domain with both SELinux and DAC security
modules loaded will deadlock; latent problem introduced in commit
fdb3bde and exposed in commit 29fe5d7.  Basically, when recursing
into the security manager for other driver's prefork, we have to
undo the asymmetric lock taken at the manager level.

Reported by Jiri Denemark, with diagnosis help from Dan Berrange.

* src/security/security_stack.c (virSecurityStackPreFork): Undo
extra lock grabbed during recursion.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit bfc183c1e3)
2013-07-22 14:04:22 -06:00
00c2003e25 security_dac: compute supplemental groups before fork
https://bugzilla.redhat.com/show_bug.cgi?id=964358

Commit 75c1256 states that virGetGroupList must not be called
between fork and exec, then commit ee777e99 promptly violated
that for lxc's use of virSecurityManagerSetProcessLabel.  Hoist
the supplemental group detection to the time that the security
manager needs to fork.  Qemu is safe, as it uses
virSecurityManagerSetChildProcessLabel which in turn uses
virCommand to determine supplemental groups.

This does not fix the fact that virSecurityManagerSetProcessLabel
calls virSecurityDACParseIds calls parseIds which eventually
calls getpwnam_r, which also violates fork/exec async-signal-safe
safety rules, but so far no one has complained of hitting
deadlock in that case.

* src/security/security_dac.c (_virSecurityDACData): Track groups
in private data.
(virSecurityDACPreFork): New function, to set them.
(virSecurityDACClose): Clean up new fields.
(virSecurityDACGetIds): Alter signature.
(virSecurityDACSetSecurityHostdevLabelHelper)
(virSecurityDACSetChardevLabel, virSecurityDACSetProcessLabel)
(virSecurityDACSetChildProcessLabel): Update callers.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 29fe5d745f)

Conflicts:
	src/security/security_dac.c - virSecurityDACSetSecurityUSBLabel needed similar treatment
2013-07-22 14:00:57 -06:00
689d014686 security: framework for driver PreFork handler
https://bugzilla.redhat.com/show_bug.cgi?id=964358

A future patch wants the DAC security manager to be able to safely
get the supplemental group list for a given uid, but at the time
of a fork rather than during initialization so as to pick up on
live changes to the system's group database.  This patch adds the
framework, including the possibility of a pre-fork callback
failing.

For now, any driver that implements a prefork callback must be
robust against the possibility of being part of a security stack
where a later element in the chain fails prefork.  This means
that drivers cannot do any action that requires a call to postfork
for proper cleanup (no grabbing a mutex, for example).  If this
is too prohibitive in the future, we would have to switch to a
transactioning sequence, where each driver has (up to) 3 callbacks:
PreForkPrepare, PreForkCommit, and PreForkAbort, to either clean
up or commit changes made during prepare.

* src/security/security_driver.h (virSecurityDriverPreFork): New
callback.
* src/security/security_manager.h (virSecurityManagerPreFork):
Change signature.
* src/security/security_manager.c (virSecurityManagerPreFork):
Optionally call into driver, and allow returning failure.
* src/security/security_stack.c (virSecurityDriverStack):
Wrap the handler for the stack driver.
* src/qemu/qemu_process.c (qemuProcessStart): Adjust caller.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit fdb3bde31c)
2013-07-22 11:41:50 -06:00
7d24a0a226 util: make virSetUIDGID async-signal-safe
https://bugzilla.redhat.com/show_bug.cgi?id=964358

POSIX states that multi-threaded apps should not use functions
that are not async-signal-safe between fork and exec, yet we
were using getpwuid_r and initgroups.  Although rare, it is
possible to hit deadlock in the child, when it tries to grab
a mutex that was already held by another thread in the parent.
I actually hit this deadlock when testing multiple domains
being started in parallel with a command hook, with the following
backtrace in the child:

 Thread 1 (Thread 0x7fd56bbf2700 (LWP 3212)):
 #0  __lll_lock_wait ()
     at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136
 #1  0x00007fd5761e7388 in _L_lock_854 () from /lib64/libpthread.so.0
 #2  0x00007fd5761e7257 in __pthread_mutex_lock (mutex=0x7fd56be00360)
     at pthread_mutex_lock.c:61
 #3  0x00007fd56bbf9fc5 in _nss_files_getpwuid_r (uid=0, result=0x7fd56bbf0c70,
     buffer=0x7fd55c2a65f0 "", buflen=1024, errnop=0x7fd56bbf25b8)
     at nss_files/files-pwd.c:40
 #4  0x00007fd575aeff1d in __getpwuid_r (uid=0, resbuf=0x7fd56bbf0c70,
     buffer=0x7fd55c2a65f0 "", buflen=1024, result=0x7fd56bbf0cb0)
     at ../nss/getXXbyYY_r.c:253
 #5  0x00007fd578aebafc in virSetUIDGID (uid=0, gid=0) at util/virutil.c:1031
 #6  0x00007fd578aebf43 in virSetUIDGIDWithCaps (uid=0, gid=0, capBits=0,
     clearExistingCaps=true) at util/virutil.c:1388
 #7  0x00007fd578a9a20b in virExec (cmd=0x7fd55c231f10) at util/vircommand.c:654
 #8  0x00007fd578a9dfa2 in virCommandRunAsync (cmd=0x7fd55c231f10, pid=0x0)
     at util/vircommand.c:2247
 #9  0x00007fd578a9d74e in virCommandRun (cmd=0x7fd55c231f10, exitstatus=0x0)
     at util/vircommand.c:2100
 #10 0x00007fd56326fde5 in qemuProcessStart (conn=0x7fd53c000df0,
     driver=0x7fd55c0dc4f0, vm=0x7fd54800b100, migrateFrom=0x0, stdin_fd=-1,
     stdin_path=0x0, snapshot=0x0, vmop=VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
     flags=1) at qemu/qemu_process.c:3694
 ...

The solution is to split the work of getpwuid_r/initgroups into the
unsafe portions (getgrouplist, called pre-fork) and safe portions
(setgroups, called post-fork).

* src/util/virutil.h (virSetUIDGID, virSetUIDGIDWithCaps): Adjust
signature.
* src/util/virutil.c (virSetUIDGID): Add parameters.
(virSetUIDGIDWithCaps): Adjust clients.
* src/util/vircommand.c (virExec): Likewise.
* src/util/virfile.c (virFileAccessibleAs, virFileOpenForked)
(virDirCreate): Likewise.
* src/security/security_dac.c (virSecurityDACSetProcessLabel):
Likewise.
* src/lxc/lxc_container.c (lxcContainerSetID): Likewise.
* configure.ac (AC_CHECK_FUNCS_ONCE): Check for setgroups, not
initgroups.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit ee777e9949)

Conflicts:
	src/lxc/lxc_container.c - did not use setUIDGID before 1.1.0
	src/util/virutil.c - oom handling changes not backported
	src/util/virfile.c - functions still lived in virutil.c this far back
	configure.ac - context with previous commit
2013-07-22 11:40:26 -06:00
fcdaa3df33 util: add virGetGroupList
https://bugzilla.redhat.com/show_bug.cgi?id=964358

Since neither getpwuid_r() nor initgroups() are safe to call in
between fork and exec (they obtain a mutex, but if some other
thread in the parent also held the mutex at the time of the fork,
the child will deadlock), we have to split out the functionality
that is unsafe.  At least glibc's initgroups() uses getgrouplist
under the hood, so the ideal split is to expose getgrouplist for
use before a fork.  Gnulib already gives us a nice wrapper via
mgetgroups; we wrap it once more to look up by uid instead of name.

* bootstrap.conf (gnulib_modules): Add mgetgroups.
* src/util/virutil.h (virGetGroupList): New declaration.
* src/util/virutil.c (virGetGroupList): New function.
* src/libvirt_private.syms (virutil.h): Export it.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 75c125641a)

Conflicts:
	bootstrap.conf - not updating gnulib submodule...
	configure.ac - ...so checking for getgrouplist by hand...
	src/util/virutil.c - ...and copying only the getgrouplist implementation rather than calling the gnulib function
2013-07-22 10:25:48 -06:00
3a2d5e7e70 util: improve user lookup helper
https://bugzilla.redhat.com/show_bug.cgi?id=964358

A future patch needs to look up pw_gid; but it is wasteful
to crawl through getpwuid_r twice for two separate pieces
of information, and annoying to copy that much boilerplate
code for doing the crawl.  The current internal-only
virGetUserEnt is also a rather awkward interface; it's easier
to just design it to let callers request multiple pieces of
data as needed from one traversal.

And while at it, I noticed that virGetXDGDirectory could deref
NULL if the getpwuid_r lookup fails.

* src/util/virutil.c (virGetUserEnt): Alter signature.
(virGetUserDirectory, virGetXDGDirectory, virGetUserName): Adjust
callers.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit c1983ba4e3)

Conflicts:
	src/util/virutil.c - oom reporting/strdup changes not backported
2013-07-19 17:14:34 -06:00
b5ed23b7d1 Prep for release 1.0.5.4 2013-07-12 08:56:21 -04:00
efa2739be6 qemu: fix double free in qemuMigrationPrepareDirect
Remove assignment of the string freed by virURIFree
to hostname, since it's not used anywhere.

Double free introduced by ddf8ad8, useless code
introduced by f03dcc5.

https://bugzilla.redhat.com/show_bug.cgi?id=977961
(cherry picked from commit 5744d96f21)
2013-07-12 09:27:04 +02:00
508a7a7523 Prep for release 1.0.5.3 2013-07-11 18:12:46 -04:00
b5b269cbc5 pci: initialize virtual_functions array pointer to avoid segfault
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=971325

The problem was that if virPCIGetVirtualFunctions was given the name
of a non-existent interface, it would return to its caller without
initializing the pointer to the array of virtual functions to NULL,
and the caller (virNetDevGetVirtualFunctions) would try to VIR_FREE()
the invalid pointer.

The final error message before the crash would be:

 virPCIGetVirtualFunctions:2088 :
  Failed to open dir '/sys/class/net/eth2/device':
  No such file or directory

In this patch I move the initialization in virPCIGetVirtualFunctions()
to the begining of the function, and also do an explicit
initialization in virNetDevGetVirtualFunctions, just in case someone
in the future adds code into that function prior to the call to
virPCIGetVirtualFunctions.

(cherry picked from commit 2c2525ab6a)
2013-07-11 17:49:19 -04:00
a717d7ba0f qemu: check if block I/O limits fit into long long
We can only pass values up to LLONG_MAX through JSON
and QEMU checks if the int64_t number is not negative
at startup since 1.5.0.

https://bugzilla.redhat.com/show_bug.cgi?id=974010
(cherry picked from commit d3c8788492)
2013-07-11 17:48:44 -04:00
22d9d9a28f network: increase max number of routes
This fixes the problem reported in:

   https://bugzilla.redhat.com/show_bug.cgi?id=972690

When checking for a collision of a new libvirt network's subnet with
any existing routes, we read all of /proc/net/route into memory, then
parse all the entries. The function that we use to read this file
requires a "maximum length" parameter, which had previously been set
to 64*1024. As each line in /proc/net/route is 128 bytes, this would
allow for a maximum of 512 entries in the routing table.

This patch increases that number to 128 * 100000, which allows for
100,000 routing table entries. This means that it's possible that 12MB
would be allocated, but that would only happen if there really were
100,000 route table entries on the system, it's only held for a very
short time.

Since there is no method of specifying and unlimited max (and that
would create a potential denial of service anyway) hopefully this
limit is large enough to accomodate everyone.

(cherry picked from commit 2bdf548f5f)
2013-07-11 17:47:58 -04:00
0943603d9e qemu: allow restore with non-migratable XML input
Convert input XML to migratable before using it in
qemuDomainSaveImageOpen.

XML in the save image is migratable, i.e. doesn't contain implicit
controllers. If these controllers were in a non-default order in the
input XML, the ABI check would fail. Removing and re-adding these
controllers fixes it.

https://bugzilla.redhat.com/show_bug.cgi?id=834196
(cherry picked from commit 07966f6a8b)
2013-07-11 17:47:39 -04:00
ca305a756d qemu_migrate: Dispose listen address if set from config
https://bugzilla.redhat.com/show_bug.cgi?id=971485

As of d7f9d82753 we copy the listen
address from the qemu.conf config file in case none has been provided
via XML. But later, when migrating, we should not include such listen
address in the migratable XML as it is something autogenerated, not
requested by user. Moreover, the binding to the listen address will
likely fail, unless the address is '0.0.0.0' or its IPv6 equivalent.
This patch introduces a new boolean attribute to virDomainGraphicsListenDef
to distinguish autofilled listen addresses. However, we must keep the
attribute over libvirtd restarts, so it must be kept within status XML.

(cherry picked from commit 6546017c50)
2013-07-11 17:47:18 -04:00
3b6bc5eda6 iscsi: pass hostnames to iscsiadm instead of resolving them
iscsiadm now supports specifying hostnames in the portal argument [1]

Instead of resolving the hostname to a single IPv4 address, pass the
hostname to isciadm, allowing IPv6 targets to work.

[1] https://bugzilla.redhat.com/show_bug.cgi?id=624437

(cherry picked from commit cbdb3c7326)
2013-07-11 17:46:53 -04:00
818a933141 qemu: Report the offset from host UTC for RTC_CHANGE event
https://bugzilla.redhat.com/show_bug.cgi?id=964177

Though both libvirt and QEMU's document say RTC_CHANGE returns
the offset from the host UTC, qemu actually returns the offset
from the specified date instead when specific date is provided
(-rtc base=$date).

It's not safe for qemu to fix it in code, it worked like that
for 3 years, changing it now may break other QEMU use cases.
What qemu tries to do is to fix the document:

http://lists.gnu.org/archive/html/qemu-devel/2013-05/msg04782.html

And in libvirt side, instead of replying on the value from qemu,
this converts the offset returned from qemu to the offset from
host UTC, by:

  /*
   * a: the offset from qemu RTC_CHANGE event
   * b: The specified date (-rtc base=$date)
   * c: the host date when libvirt gets the RTC_CHANGE event
   * offset: What libvirt will report
   */

  offset = a + (b - c);

The specified date (-rtc base=$date) is recorded in clock's def as
an internal only member (may be useful to exposed outside?).

Internal only XML tag "basetime" is introduced to not lose the
guest's basetime after libvirt restarting/reloading:

<clock offset='variable' adjustment='304' basis='utc' basetime='1370423588'/>

(cherry picked from commit e31b5cf393)
2013-07-11 17:46:45 -04:00
44758cea54 storage: Provide better error message if metadata pre-alloc is unsupported
Instead of a unknown flag error report that metadata pre-allocation is
not supported with the requested volume creation method.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=969982
(cherry picked from commit 77e7f69c3b)
2013-07-11 17:46:32 -04:00
ffe68a85c9 usb: don't spoil decimal addresses
For USB devices, dev->name gets formated as %.3o:%.3o even though the
numbers are decimal.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=967712
(cherry picked from commit dc0c791569)
2013-07-11 17:45:55 -04:00
e01eedf9bf Check for existence of interface prior to setting terminate flag
https://bugzilla.redhat.com/show_bug.cgi?id=903480

During domain destruction it's possible that the learnIPAddressThread has
already removed the interface prior to the teardown filter path being run.
The teardown code would only be telling the thread to terminate.

(cherry picked from commit 64919d978e)
2013-07-11 17:45:32 -04:00
b14ced3932 qemu: snapshot: Don't kill access to disk if snapshot creation fails
If snapshot creation failed for example due to invalid use of the
"REUSE_EXTERNAL" flag, libvirt killed access to the original image file
instead of the new image file. On machines with selinux this kills the
whole VM as the selinux context is enforced immediately.

* qemu_driver.c:qemuDomainSnapshotUndoSingleDiskActive():
    - Kill access to the new image file instead of the old one.

Partially resolves: https://bugzilla.redhat.com/show_bug.cgi?id=906639

(cherry picked from commit 177046753f)
2013-07-11 17:45:22 -04:00
b2c2dd60f1 Fix blkdeviotune for shutoff domain
Function qemuDomainSetBlockIoTune() was checking QEMU capabilities
even when !(flags & VIR_DOMAIN_AFFECT_LIVE) and the domain was
shutoff, resulting in the following problem:

 virsh # domstate asdf; blkdeviotune asdf vda --write-bytes-sec 100
 shut off

 error: Unable to change block I/O throttle
 error: unsupported configuration: block I/O throttling not supported with this QEMU binary

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=965016
(cherry picked from commit 5af3ce8277)
2013-07-11 17:45:08 -04:00
1a6333f842 Ensure non-root can read /proc/meminfo file in LXC containers
By default files in a FUSE mount can only be accessed by the
user which created them, even if the file permissions would
otherwise allow it. To allow other users to access the FUSE
mount the 'allow_other' mount option must be used. This bug
prevented non-root users in an LXC container from reading
the /proc/meminfo file.

https://bugzilla.redhat.com/show_bug.cgi?id=967977

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit 922ebe4ead)
2013-07-11 17:42:26 -04:00
17cdc298ac LXC: Create /dev/tty within a container
Many applications use /dev/tty to read from stdin.
e.g. zypper on openSUSE.

Let's create this device node to unbreak those applications.
As /dev/tty is a synonym for the current controlling terminal
it cannot harm the host or any other containers.

Signed-off-by: Richard Weinberger <richard@nod.at>
(cherry picked from commit 9a0ac6d9c2)

Conflicts:
	src/lxc/lxc_controller.c
2013-07-11 17:38:47 -04:00
6cdff51fb3 qemu: Implement new QMP command for cpu hotplug
This patch implements support for the "cpu-add" QMP command that plugs
CPUs into a live guest. The "cpu-add" command was introduced in QEMU
1.5. For the hotplug to work machine type "pc-i440fx-1.5" is required.

(cherry picked from commit c12b2be516)
2013-07-11 17:29:48 -04:00
ad02b24871 udev: fix crash in libudev logging
Call virLogVMessage instead of virLogMessage, since libudev
called us with a va_list object, not a list of arguments.

Honor message priority and strip the trailing newline.

https://bugzilla.redhat.com/show_bug.cgi?id=969152
(cherry picked from commit f753dd62f9)
2013-07-11 17:29:33 -04:00
647156870e Don't mount selinux fs in LXC if selinux is disabled
Before trying to mount the selinux filesystem in a container
use is_selinux_enabled() to check if the machine actually
has selinux support (eg not booted with selinux=0)

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit 95c6cc344b)
2013-07-11 10:52:04 -06:00
269dfa0e08 Re-add selinux/selinux.h to lxc_container.c
Re-add the selinux header to lxc_container.c since other
functions now use it, beyond the patch that was just
reverted.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit 63ea1e5432)
2013-07-11 10:51:32 -06:00
0616172bdf Fix failure to detect missing cgroup partitions
Change bbe97ae968 caused the
QEMU driver to ignore ENOENT errors from cgroups, in order
to cope with missing /proc/cgroups. This is not good though
because many other things can cause ENOENT and should not
be ignored. The callers expect to see ENXIO when cgroups
are not present, so adjust the code to report that errno
when /proc/cgroups is missing

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit c2cf5f1c2a)
2013-07-11 10:39:45 -06:00
68d92eea16 Fix starting domains when kernel has no cgroups support
Found that I was unable to start existing domains after updating
to a kernel with no cgroups support

  # zgrep CGROUP /proc/config.gz
  # CONFIG_CGROUPS is not set
  # virsh start test
  error: Failed to start domain test
  error: Unable to initialize /machine cgroup: Cannot allocate memory

virCgroupPartitionNeedsEscaping() correctly returns errno (ENOENT) when
attempting to open /proc/cgroups on such a system, but it was being
dropped in virCgroupSetPartitionSuffix().

Change virCgroupSetPartitionSuffix() to propagate errors returned by
its callees.  Also check for ENOENT in qemuInitCgroup() when determining
if cgroups support is available.
(cherry picked from commit bbe97ae968)
2013-07-11 10:38:45 -06:00
e0dd41e564 Escaping leading '.' in cgroup names
Escaping a leading '.' with '_' in the cgroup names

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit 0ced83dcfb)
2013-07-11 10:37:49 -06:00
fdaa5c825c Add docs about cgroups layout and usage
Describe the new cgroups layout, how to customize placement
of guests and what virsh commands are used to access the
parameters.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit 486a86eb18)
2013-07-11 10:37:09 -06:00
4769d2ae9f Cope with missing swap cgroup controls
It is possible to build a kernel without swap cgroup controls
present. This causes a fatal error when querying memory
parameters. Treat missing swap controls as meaning "unlimited".
The fatal error remains if the user tries to actually change
the limit.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit f493d83fbd)
2013-07-11 10:36:17 -06:00
8c4faa9044 libxl: fix build with Xen4.3
Xen 4.3 fixes a mistake in the libxl event handler signature where the
event owned by the application was defined as const.  Detect this and
define the libvirt libxl event handler signature appropriately.
(cherry picked from commit 43b0ff5b1e)
2013-07-11 10:27:35 -06:00
233a616bda qemu: fix return value of qemuDomainBlockPivot on errors
If qemuMonitorBlockJob returned 0, qemuDomainBlockPivot
might return 0 even if an error occured.

https://bugzilla.redhat.com/show_bug.cgi?id=977678
(cherry picked from commit c34107dfd3)
2013-07-11 14:34:16 +02:00
14ce155a3a storage: return -1 when fs pool can't be mounted
Don't reuse the return value of virStorageBackendFileSystemIsMounted.
If it's 0, we'd return it even if the mount command failed.

Also, don't report another error if it's -1, since one has already
been reported.

Introduced by 258e06c.

https://bugzilla.redhat.com/show_bug.cgi?id=981251
(cherry picked from commit 13fde7ceab)
2013-07-11 14:33:44 +02:00
4d21d84532 Fix vPort management: FC vHBA creation
When creating a virtual FC HBA with virsh/libvirt API, an error message
will be returned: "error: Node device not found",
also the 'nodedev-dumpxml' shows wrong information of wwpn & wwnn
for the new created device.

Signed-off-by: xschen@tnsoft.com.cn

This reverts f90af69 which switched wwpn & wwwn in the wrong place.

https://www.kernel.org/doc/Documentation/scsi/scsi_fc_transport.txt
(cherry picked from commit 3c0d5e224c)
2013-07-01 11:54:22 +02:00
0347e778ca bridge: don't crash on bandwidth unplug with no bandwidth
If networkUnplugBandwidth is called on a network which has
no bandwidth defined, print a warning instead of crashing.

This can happen when destroying a domain with bandwidth if
bandwidth was removed from the network after the domain was
started.

https://bugzilla.redhat.com/show_bug.cgi?id=975359
(cherry picked from commit 658c932ab4)
2013-07-01 11:54:11 +02:00
1b4cd1e5f0 Fix invalid read in virCgroupGetValueStr
Don't check for '\n' at the end of file if zero bytes were read.

Found by valgrind:
==404== Invalid read of size 1
==404==    at 0x529B09F: virCgroupGetValueStr (vircgroup.c:540)
==404==    by 0x529AF64: virCgroupMoveTask (vircgroup.c:1079)
==404==    by 0x1EB475: qemuSetupCgroupForEmulator (qemu_cgroup.c:1061)
==404==    by 0x1D9489: qemuProcessStart (qemu_process.c:3801)
==404==    by 0x18557E: qemuDomainObjStart (qemu_driver.c:5787)
==404==    by 0x190FA4: qemuDomainCreateWithFlags (qemu_driver.c:5839)

Introduced by 0d0b409.

https://bugzilla.redhat.com/show_bug.cgi?id=978356
(cherry picked from commit 306c49ffd5)
2013-06-26 17:31:28 +02:00
c93aef4946 virsh: edit: don't leak XML string on reedit or redefine
Free the old XML strings before overwriting them if the user
has chosen to reedit the file or force the redefinition.

Found by Alex Jia trying to reproduce another bug:
https://bugzilla.redhat.com/show_bug.cgi?id=977430#c3
(cherry picked from commit 1e3a252974)
2013-06-26 17:31:16 +02:00
f1e454457d lxc: Resolve issue with GetScheduler APIs for non running domain
Cherry-picked from 38ada092d1

As a consequence of the cgroup layout changes from commit 'cfed9ad4', the
lxcDomainGetSchedulerParameters[Flags]()' and lxcGetSchedulerType() APIs
failed to return data for a non running domain.  This can be seen through
a 'virsh schedinfo <domain>' command which returns:

Scheduler      : Unknown
error: Requested operation is not valid: cgroup CPU controller is not mounted

Prior to that change a non running domain would return:

Scheduler      : posix
cpu_shares     : 0
vcpu_period    : 0
vcpu_quota     : 0
emulator_period: 0
emulator_quota : 0

This patch will restore the capability to return configuration only data
for a non running domain regardless of whether cgroups are available.

NOTE: Needed to change the VIR_STRDUP(ret, "posix"); to ret = strdup("posix");
      and added the virReportOOMError(); on failure.
2013-06-20 09:38:51 -04:00
f1729409fb qemu: Resolve issue with GetScheduler APIs for non running domain
Cherry-picked from b237545341

As a consequence of the cgroup layout changes from commit '632f78ca', the
qemuDomainGetSchedulerParameters[Flags]()' and qemuGetSchedulerType() APIs
failed to return data for a non running domain.  This can be seen through
a 'virsh schedinfo <domain>' command which returns:

Scheduler      : Unknown
error: Requested operation is not valid: cgroup CPU controller is not mounted

Prior to that change a non running domain would return:

Scheduler      : posix
cpu_shares     : 0
vcpu_period    : 0
vcpu_quota     : 0
emulator_period: 0
emulator_quota : 0

This patch will restore the capability to return configuration only data
for a non running domain regardless of whether cgroups are available.

NOTE: Needed to change the VIR_STRDUP(ret, "posix"); to ret = strdup("posix");
      and added the virReportOOMError(); on failure.
2013-06-20 09:37:54 -04:00
a06bf7b287 conf: fix use after free in virChrdevOpen
Don't free the stream on error if we've successfully added it
to the hash table, since it will be freed by virChrdevHashEntryFree
callback.

Preserve the error message before calling virStreamFree, since it
resets the error.

Introduced by 4716138, crashing since 6921892.

Reported by Sergey Fionov on libvir-list.
(cherry picked from commit a32b41746c)
2013-06-18 15:30:23 +02:00
067e9988a2 qemu: Avoid leaking uri in qemuMigrationPrepareDirect
(cherry picked from commit ddf8ad82eb)
2013-06-18 15:30:03 +02:00
1fc28a4743 virtlockd: fix socket path
Change the socket path to match the one used by lockd driver.

https://bugzilla.redhat.com/show_bug.cgi?id=968128
(cherry picked from commit 70fe129546)
2013-06-18 15:29:54 +02:00
7e0b15f2f0 nodedev: fix vport detection for FC HBA
Use the host number as the host number when constructing the sysfs path
instead of the variable we are trying to fill.

https://bugzilla.redhat.com/show_bug.cgi?id=973543
(cherry picked from commit 371c15517c)
2013-06-18 15:29:42 +02:00
419605b3a0 Prep for release 1.0.5.2 2013-06-12 16:50:01 -04:00
feb2d3375c virsh: migrate: Don't disallow --p2p and --migrateuri
Because it's a valid combination. p2p still uses a separate channel
for qemu migration, so there's value in letting the user specify a manual
migrate URI for overriding auto-port, or libvirt's FQDN lookup.

What _isn't_ allowed is --migrateuri and TUNNELLED, since there is
no separate migration channel. Disallow that instead
(cherry picked from commit 5e1de4fcdd)
2013-06-12 16:37:55 -04:00
12b0af5905 qemu: migration: error if tunnelled + storage specified
Since as the code indicates it doesn't work yet, so let's be
explicit about it.
(cherry picked from commit 98bbda00cf)
2013-06-12 16:37:55 -04:00
69de4ce80d qemu: migration: Improve p2p error if we can't open conn
By actually showing the Open() error to the user
(cherry picked from commit 5751fc4f4e)
2013-06-12 16:37:55 -04:00
9b3455cb78 Add a virGetLastErrorMessage() function
Apps using libvirt will often have code like

   if (virXXXX() < 0) {
      virErrorPtr err = virGetLastError();
      fprintf(stderr, "Something failed: %s\n",
              err && err->message ? err->message :
              "unknown error");
      return -1;
   }

Checking for a NULL error object or message leads to very
verbose code. A virGetLastErrorMessage() helper from libvirt
can simplify this to

   if (virXXXX() < 0) {
      fprintf(stderr, "Something failed: %s\n",
              virGetLastErrorMessage());
      return -1;
   }

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit 69c6a58a1d)
2013-06-12 16:37:55 -04:00
bdb5808173 qemu: Don't report error on successful media eject
If we are just ejecting media, ret == -1 even after the retry loop
determines that the tray is open, as requested. This means media
disconnect always report's error.

Fix it, and fix some other mini issues:

- Don't overwrite the 'eject' error message if the retry loop fails
- Move the retries decrement inside the loop, otherwise the final loop
  might succeed, yet retries == 0 and we will raise error
- Setting ret = -1 in the disk->src check is unneeded
- Fix comment typos

cc: mprivozn@redhat.com
(cherry picked from commit 406d8a9809)
2013-06-12 15:25:08 -04:00
dc0efacb6f qemuDomainChangeEjectableMedia: Unlock domain while waiting for event
In 84c59ffa I've tried to fix changing ejectable media process. The
process should go like this:

1) we need to call 'eject' on the monitor
2) we should wait for 'DEVICE_TRAY_MOVED' event
3) now we can issue 'change' command

However, while waiting in step 2) the domain monitor was locked. So
even if qemu reported the desired event, the proper callback was not
called immediately. The monitor handling code needs to lock the
monitor in order to read the event. So that's the first lock we must
not hold while waiting. The second one is the domain lock. When
monitor handling code reads an event, the appropriate callback is
called then. The first thing that each callback does is locking the
corresponding domain as a domain or its device is about to change
state. So we need to unlock both monitor and VM lock. Well, holding
any lock while sleep()-ing is not the best thing to do anyway.
(cherry picked from commit 543af79a14)
2013-06-12 15:24:44 -04:00
0e6aa8fcd2 storage: Ensure 'qemu-img resize' size arg is a 512 multiple
qemu-img resize will fail with "The new size must be a multiple of 512"
if libvirt doesn't round it first.
This fixes rhbz#951495

Signed-off-by: Christophe Fergeau <cfergeau@redhat.com>
(cherry picked from commit 9a8f39d097)
2013-06-12 15:11:50 -04:00
12f18158c7 nwfilter: grab driver lock earlier during init (bz96649)
This patch is in relation to Bug 966449:

https://bugzilla.redhat.com/show_bug.cgi?id=966449

This is a patch addressing the coredump.

Thread 1 must be calling  nwfilterDriverRemoveDBusMatches(). It does so with
nwfilterDriverLock held. In the patch below I am now moving the
nwfilterDriverLock(driverState) further up so that the initialization, which
seems to either take a long time or is entirely stuck, occurs with the lock
held and the shutdown cannot occur at the same time.

Remove the lock in virNWFilterDriverIsWatchingFirewallD to avoid
double-locking.

(cherry picked from commit 0ec376c20a)
2013-06-11 18:40:43 -04:00
ab7e3039e0 Fix use of VIR_STRDUP vs strdup
Commit 894f784948 broke the v1.0.5-maint
branch because VIR_STRDUP() didn't exist in the v1.0.5 release so the
resulting build is missing that symbol.

This patch is only for the v1.0.5-maint branch.
2013-06-10 09:36:06 -04:00
dc200aa851 qemu: Fix crash in migration of graphics-less guests.
Commit 7f15ebc7a2 introduced a bug
happening when guests without a <graphics> element are migrated.
The initialization of listenAddress happens unconditionally
from the cookie even if the cookie->graphics pointer was NULL.
Moved the initialization to where it is safe.

Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
(cherry picked from commit 9684bb11fd)
2013-05-31 22:36:32 +02:00
2f2ed992c0 qemu: prevent termination of guests w/hostdev on driver reconnect
This should resolve:

  https://bugzilla.redhat.com/show_bug.cgi?id=959191

The problem was that qemuUpdateActivePciHostdevs was returning 0
(success) when no hostdevs were present, but would otherwise return -1
(failure) even when it completed successfully. It is only called from
qemuProcessReconnect(), and when qemuProcessReconnect got back an
error, it would not only stop reconnecting, but would terminate the
guest qemu process "to remove danger of it ending up running twice if
user tries to start it again later".

(This bug was introduced in commit 011cf7ad, which was pushed between
v1.0.2 and v1.0.3, so all maintenance branches from v1.0.3 up to 1.0.5
will need this one line patch applied.)
(cherry picked from commit 2ea45647bc)
2013-05-31 15:16:06 -04:00
894f784948 qemu: escape literal IPv6 address in NBD migration
A literal IPv6 must be escaped, otherwise migration fails with:
unable to execute QEMU command 'drive-mirror': address resolution failed
for f0::0d:5901: Servname not supported for ai_socktype
since QEMU treats everything after the first ':' as the port.
(cherry picked from commit 2136327e23)
2013-05-31 17:28:31 +02:00
0ecc5ad70d build: fix build with older gcc
gcc 4.1.2 (hello, RHEL 5!) fails to build on 32-bit platforms with:

conf/domain_conf.c: In function 'virDomainDefParseXML':
conf/domain_conf.c:10581: warning: integer constant is too large for 'long' type

Problem introduced in commit f8e3221f9.

* src/conf/domain_conf.c (virDomainDefParseXML): Mark large constants.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit f6817c70b4)
2013-05-28 20:21:50 -06:00
3accd7eb25 qemu: fix NBD migration to hosts with IPv6 enabled
Since f03dcc5 we use [::] as the listening address both on qemu
command line in -incoming and in nbd-server-start QMP command.
However the latter requires just :: without the braces.
(cherry picked from commit 2326006410)
2013-05-25 16:55:19 -04:00
b4541a2f3d cgroup: be robust against cgroup movement races
https://bugzilla.redhat.com/show_bug.cgi?id=965169 documents a
problem starting domains when cgroups are enabled; I was able
to reliably reproduce the race about 5% of the time when I added
hooks to domain startup by 3 seconds (as that seemed to be about
the length of time that qemu created and then closed a temporary
thread, probably related to aio handling of initially opening
a disk image).  The problem has existed since we introduced
virCgroupMoveTask in commit 9102829 (v0.10.0).

There are some inherent TOCTTOU races when moving tasks between
kernel cgroups, precisely because threads can be created or
completed in the window between when we read a thread id from the
source and when we write to the destination.  As the goal of
virCgroupMoveTask is merely to move ALL tasks into the new
cgroup, it is sufficient to iterate until no more threads are
being created in the old group, and ignoring any threads that
die before we can move them.

It would be nicer to start the threads in the right cgroup to
begin with, but by default, all child threads are created in
the same cgroup as their parent, and we don't want vcpu child
threads in the emulator cgroup, so I don't see any good way
of avoiding the move.  It would also be nice if the kernel were
to implement something like rename() as a way to atomically move
a group of threads from one cgroup to another, instead of forcing
a window where we have to read and parse the source, then format
and write back into the destination.

* src/util/vircgroup.c (virCgroupAddTaskStrController): Ignore
ESRCH, because a thread ended between read and write attempts.
(virCgroupMoveTask): Loop until all threads have moved.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 83e4c77547)
2013-05-21 11:57:07 -06:00
6bf4e0e0d0 Prep for release 1.0.5.1 2013-05-19 18:01:21 -04:00
6a7ae990e7 tests: use portable shell code
'make check' fails since commit 470d5c46 on any system with dash
as /bin/sh, because '<<<' is a bash extension.  For example:

nwfilterschematest: 23: /home/eblake/libvirt/tests/schematestutils.sh: Syntax error: redirection unexpected

Also, there is no need to spawn a grep process when shell globbing
can do the same.

* tests/schematestutils.sh: Replace bashism and subprocess with a
faster and portable construct.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 1d21b884a3)
2013-05-17 21:40:49 -06:00
3efa02e3ed qemu: Fix cgroup handling when setting VCPU BW
Commit 632f78c introduced a regression which causes schedinfo being
unable to set some parameters.  When migrating to priv->cgroup there
was missing variable left out and due to passed NULL to underlying
function, the setting failed.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=963592
2013-05-16 22:16:09 +02:00
71e7f1392b daemon: fix leak after listing all volumes
CVE-2013-1962

remoteDispatchStoragePoolListAllVolumes wasn't freeing the pool.
The pool also held a reference to the connection, preventing it from
getting freed and closing the netcf interface driver, which held two
sockets open.
(cherry picked from commit ca697e90d5)
2013-05-16 16:07:43 +02:00
a36dbe6475 Fix iohelper usage with streams opened for read
bz #960879

In b2878ed860 we added the O_NOCTTY
flag when opening files in the stream code. Unfortunately a later
piece of code was comparing the flags == O_RDONLY, without masking
out the non-access mode flags. This broke the iohelper when used
with streams for read, since it caused us to attach the stream
output pipe to the stream input FD instead of output FD :-(

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit a2214c5257)
2013-05-14 16:02:29 -06:00
ce902dcaf0 util: fix virFileOpenAs return value and resulting error logs
This resolves:

     https://bugzilla.redhat.com/show_bug.cgi?id=851411
     https://bugzilla.redhat.com/show_bug.cgi?id=955500

The first problem was that virFileOpenAs was returning fd (-1) in one
of the error cases rather than ret (-errno), so the caller thought
that the error was EPERM rather than ENOENT.

The second problem was that some log messages in the general purpose
qemuOpenFile() function would always say "Failed to create" even if
the caller hadn't included O_CREAT (i.e. they were trying to open an
existing file).

This fixes virFileOpenAs to jump down to the error return (which
returns ret instead of fd) in the previously mentioned incorrect
failure case of virFileOpenAs(), removes all error logging from
virFileOpenAs() (since the callers report it), and modifies
qemuOpenFile to appropriately use "open" or "create" in its log
messages.

NB: I seriously considered removing logging from all callers of
virFileOpenAs(), but there is at least one case where the caller
doesn't want virFileOpenAs() to log any errors, because it's just
going to try again (qemuOpenFile()). We can't simply make a silent
variation of virFileOpenAs() though, because qemuOpenFile() can't make
the decision about whether or not it wants to retry until after
virFileOpenAs() has already returned an error code.

Likewise, I also considered changing virFileOpenAs() to return -1 with
errno set on return, and may still do that, but only as a separate
patch, as it obscures the intent of this patch too much.
(cherry picked from commit a2c1bedbd8)
2013-05-10 13:10:07 -04:00
a4f45888ce iscsi: don't leak portal string when starting a pool
(cherry picked from commit 413274f63b)
2013-05-09 15:05:07 +02:00
c12dc47c27 don't mention disk controllers in generic controller errors
The controller element supports non-disk controller types too.

https://bugzilla.redhat.com/show_bug.cgi?id=960958
(cherry picked from commit c075f89fa2)
2013-05-09 15:04:48 +02:00
9fc6618e74 conf: don't crash on a tpm device with no backends
Print an error instead of crashing when a TPM device without
a backend is specified.

Add a test for tpm device with no backend, which should fail
with a parse error.

https://bugzilla.redhat.com/show_bug.cgi?id=961252
(cherry picked from commit 1d96440a06)
2013-05-09 14:57:00 +02:00
a3f71eb908 tests: files named '.*-invalid.xml' should fail validation
Currently, using an invalid XML in tests fails, because
the schema test expects all of them to be valid.

Treat files with -invalid.xml suffix as invalid and expect
them to fail validation.
(cherry picked from commit 470d5c4654)
2013-05-09 14:56:36 +02:00
6597cc25a1 qemu: allocate network connections sooner during domain startup
VFIO device assignment requires a cgroup ACL to be setup for access to
the /dev/vfio/nn "group" device for any devices that will be assigned
to a guest. In the case of a host device that is allocated from a
pool, it was being allocated during qemuBuildCommandLine(), which is
called by qemuProcessStart() *after* the all-encompassing
qemuSetupCgroup() was called, meaning that the standard Cgroup ACL
setup wasn't creating ACLs for these devices allocated from pools.

One possible solution was to manually add a single ACL down inside
qemuBuildCommandLine() when networkAllocateActualDevice() is called,
but that has two problems: 1) the function that adds the cgroup ACL
requires a virDomainObjPtr, which isn't available in
qemuBuildCommandLine(), and 2) we really shouldn't be doing network
device setup inside qemuBuildCommandLine() anyway.

Instead, I've created a new function called
qemuNetworkPrepareDevices() which is called just before
qemuPrepareHostDevices() during qemuProcessStart() (explanation of
ordering in the comments), i.e. well before the call to
qemuSetupCgroup(). To minimize code churn in a patch that will be
backported to 1.0.5-maint, qemuNetworkPrepareDevices only does
networkAllocateActualDevice() and the bare amount of setup required
for type='hostdev network devices, but it eventually should do *all*
device setup for guest network devices.

Note that some of the code that was previously needed in
qemuBuildCommandLine() is no longer required when
networkAllocateActualDevice() is called earlier:

 * qemuAssignDeviceHostdevAlias() is already done further down in
   qemuProcessStart().

 * qemuPrepareHostdevPCIDevices() is called by
   qemuPrepareHostDevices() which is called after
   qemuNetworkPrepareDevices() in qemuProcessStart().

As hinted above, this new function should be moved into a separate
qemu_network.c (or similarly named) file along with
qemuPhysIfaceConnect(), qemuNetworkIfaceConnect(), and
qemuOpenVhostNet(), and expanded to call those functions as well, then
the nnets loop in qemuBuildCommandLine() should be reduced to only
build the commandline string (which itself can be in a separate
qemuInterfaceBuilldCommandLine() function as suggested by
Michal). However, this will require storing away an array of tapfd and
vhostfd that are needed for the commandline, so I would rather do that
in a separate patch and leave this patch at the minimum to fix the
bug.
(cherry picked from commit 8cd40e7e0d)
2013-05-07 12:46:09 -04:00
3b8f6e5fd6 Make detect_scsi_host_caps a function on all architectures
In the non linux case some callers like gather_scsi_host_caps needed the
return code of -1 while others like update_caps needed an empty
statement (to avoid a "statement without effect" warning). This is much
simpler solved by using a function instead of a define.
(cherry picked from commit 58662f4416)
2013-05-06 14:20:33 -06:00
4a4d2300ff Fixup rpcgen code on kFreeBSD too
since it uses glibc's rpcgen.
(cherry picked from commit b562d7b7e4)
2013-05-06 14:20:18 -06:00
14ba72b640 Fix release of resources with lockd plugin
The lockd plugin for the lock manager was not correctly
handling the release of resource locks. This meant that
during migration, or when pausing a VM, the locks would
not get released. This in turn made it impossible to
resume the domain, or finish migration
(cherry picked from commit 8dc93ffadc)
2013-05-06 14:19:47 -06:00
fc8a231018 build: avoid non-portable cast of pthread_t
POSIX says pthread_t is opaque.  We can't guarantee if it is scaler
or a pointer, nor what size it is; and BSD differs from Linux.
We've also had reports of gcc complaining on attempts to cast it,
if we use a cast to the wrong type (for example, pointers have to be
cast to void* or intptr_t before being narrowed; while casting a
function return of scalar pthread_t to void* triggers a different
warning).

Give up on casts, and use unions to get at decent bits instead.  And
rather than futz around with figuring which 32 bits of a potentially
64-bit pointer are most likely to be unique, convert the rest of
the code base to use 64-bit values when using a debug id.

Based on a report by Guido Günther against kFreeBSD, but with a
fix that doesn't regress commit 4d970fd29 for FreeBSD.

* src/util/virthreadpthread.c (virThreadSelfID, virThreadID): Use
union to get at a decent bit representation of thread_t bits.
* src/util/virthread.h (virThreadSelfID, virThreadID): Alter
signature.
* src/util/virthreadwin32.c (virThreadSelfID, virThreadID):
Likewise.
* src/qemu/qemu_domain.h (qemuDomainJobObj): Alter type of owner.
* src/qemu/qemu_domain.c (qemuDomainObjTransferJob)
(qemuDomainObjSetJobPhase, qemuDomainObjReleaseAsyncJob)
(qemuDomainObjBeginNestedJob, qemuDomainObjBeginJobInternal): Fix
clients.
* src/util/virlog.c (virLogFormatString): Likewise.
* src/util/vireventpoll.c (virEventPollInterruptLocked):
Likewise.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 22d12905e6)
2013-05-06 14:19:35 -06:00
832049ca29 Fix potential use of undefined variable in remote dispatch code
If an early dispatch check caused a jump to the 'cleanup' branch
then virTypeParamsFree() would be called with an uninitialized
'nparams' variable. Fortunately 'params' is initialized to NULL,
so the uninitialized 'nparams' variable would not be used.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit 31dbbb667f)
2013-05-06 14:18:23 -06:00
6381c1c130 build: fix mingw build of virprocess.c
Commit 776d49f4 added a static function that is only called
conditionally; leading to this compile error on mingw:

  CC       libvirt_util_la-virprocess.lo
../../src/util/virprocess.c:624:26: error: 'struct rlimit' declared inside parameter list [-Werror]
../../src/util/virprocess.c:624:26: error: its scope is only this definition or declaration, which is probably not what you want [-Werror]
../../src/util/virprocess.c:622:1: error: 'virProcessPrLimit' defined but not used [-Werror=unused-function]

* src/util/virprocess.c (virProcessPrLimit): Only declare
virProcessPrLimit when used.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 05f79a3894)
2013-05-06 14:17:35 -06:00
3b9243e018 Fix F_DUPFD_CLOEXEC operation args
The F_DUPFD_CLOEXEC operation with fcntl() expects a single
int argument, specifying the minimum FD number for the newly
dup'd file descriptor. We were not specifying that causing
random stack data to be accessed as the FD number. Sometimes
that worked, sometimes it didn't.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit d6670a64e1)
2013-05-06 14:16:14 -06:00
fa8692cd2e spec: proper soft static allocation of qemu uid
https://bugzilla.redhat.com/show_bug.cgi?id=924501 tracks a
problem that occurs if uid 107 is already in use at the time
libvirt is first installed.  In response that problem, Fedora
packaging guidelines were recently updated.  This fixes the
spec file to comply with the new guidelines:
https://fedoraproject.org/wiki/Packaging:UsersAndGroups

* libvirt.spec.in (daemon): Follow updated Fedora guidelines.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit a2584d58f6)
2013-05-06 14:09:13 -06:00
c0431c10ee build: clean up stray files found by 'make distcheck'
'make distcheck' complained:

ERROR: files left in build directory after distclean:
./python/libvirt.pyc
./tests/commandhelper.log

Problems introduced in commits f015495 and 25ea8e4 (both v1.0.3).

* tests/commandtest.c (test21): Check (and clean) log file.
* tests/commanddata/test21.log: New file.
* python/Makefile.am (CLEANFILES): Clean up compiled python files.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit c21c38d71b)
2013-05-06 14:09:11 -06:00
343ab629cf build: always include libvirt_lxc.syms in tarball
On a mingw build, 'make distcheck' fails with:

  GEN      libvirt_qemu.def
make[3]: *** No rule to make target `../../src/libvirt_lxc.syms', needed by `libvirt_lxc.def'.  Stop.

I traced it to a missing entry in EXTRA_DIST.  But rather than keep
the entire list in sync, it is easier to list the three syms files
that drive .so files directly, and then reuse existing makefile
variables for the remaining files (that is, I validated that all
remaining files are added to SYM_FILES, possibly via USED_SYM_FILES,
according to makefile conditionals).

Problem introduced in commit 3d1596b (v1.0.2).

* src/Makefile.am (EXTRA_DIST): Ensure all syms files are shipped.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit ed11ab93fa)
2013-05-06 14:09:10 -06:00
97633c8682 qemu: fix stupid typos in VFIO cgroup setup/teardown
I must have looked at this a couple dozen times before I noticed it
had "!=" instead of "==". Not doing this setup prevented qemu from
doing anything with the vfio group device.
(cherry picked from commit 52ba0f6e1c)
2013-05-03 14:49:51 -04:00
3e7adcf682 build: always include sanitytest in tarball
The libvirt 1.0.5 tarball is missing a file which renders 'make
check' broken; first reported on list by Guido Günther.

* python/Makefile.am (EXTRA_DIST): Hoist sanitytest.py out of
HAVE_PYTHON conditional.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 5a3487dadb)
2013-05-03 11:26:38 -04:00
2b9bf71b6c virInitctlRequest: unbreak make syntax check
introduced by dcf97846d5

To trigger this cppi needs to be installed.
(cherry picked from commit ca75c44310)
2013-05-03 11:26:25 -04:00
c2de882f32 virInitctlRequest: unbreak make syntax check
introduced by dcf97846d5
(cherry picked from commit a1365d7351)
2013-05-03 11:26:07 -04:00
d2686140e1 network: fix network driver startup for qemu:///session
This should resolve https://bugzilla.redhat.com/show_bug.cgi?id=958907

Recent new addition of code to read/write active network state to the
NETWORK_STATE_DIR in the network driver broke startup for
qemu:///session. The network driver had several state file paths
hardcoded to /var, which could never possibly work in session mode.

This patch modifies *all* state files to use a variable string that is
set differently according to whether or not we're running
privileged. (It turns out that logDir was never used, so it's been
completely eliminated.)

There are very definitely other problems preventing dnsmasq and radvd
from running in non-privileged mode, but it's more consistent to have
the directories used by them be determined in the same fashion.

NB: I've noted before that the network driver is storing its state
(including dnsmasq and radvd state) in /var/lib, while qemu stores its
state in /var/run. It would probably have been better if the two
matched, but it's been this way for a long time, and changing it would
break running installations during an upgrade, so it's best to just
leave it as it is.
(cherry picked from commit 2ffd87d820)

Conflicts:
	src/network/bridge_driver.c - code removed by this patch had
                                      been modified upstream.
2013-05-03 11:06:20 -04:00
10887 changed files with 2782622 additions and 1846394 deletions

View File

@ -1,40 +0,0 @@
-I@abs_top_builddir@
-I@abs_top_srcdir@
-I@abs_top_builddir@/gnulib/lib
-I@abs_top_srcdir@/gnulib/lib
-I@abs_top_builddir@/include
-I@abs_top_srcdir@/include
-I@abs_top_builddir@/src
-I@abs_top_srcdir@/src
-I@abs_top_builddir@/src/access
-I@abs_top_srcdir@/src/access
-I@abs_top_builddir@/src/admin
-I@abs_top_srcdir@/src/admin
-I@abs_top_builddir@/src/bhyve
-I@abs_top_srcdir@/src/bhyve
-I@abs_top_builddir@/src/conf
-I@abs_top_srcdir@/src/conf
-I@abs_top_builddir@/src/libxl
-I@abs_top_srcdir@/src/libxl
-I@abs_top_builddir@/src/locking
-I@abs_top_srcdir@/src/locking
-I@abs_top_builddir@/src/logging
-I@abs_top_srcdir@/src/logging
-I@abs_top_builddir@/src/lxc
-I@abs_top_srcdir@/src/lxc
-I@abs_top_builddir@/src/qemu
-I@abs_top_srcdir@/src/qemu
-I@abs_top_builddir@/src/remote
-I@abs_top_srcdir@/src/remote
-I@abs_top_builddir@/src/rpc
-I@abs_top_srcdir@/src/rpc
-I@abs_top_builddir@/src/secret
-I@abs_top_srcdir@/src/secret
-I@abs_top_builddir@/src/security
-I@abs_top_srcdir@/src/security
-I@abs_top_builddir@/src/util
-I@abs_top_srcdir@/src/util
-I@abs_top_builddir@/src/vmx
-I@abs_top_srcdir@/src/vmx
-I@abs_top_builddir@/src/xenconfig
-I@abs_top_srcdir@/src/xenconfig

6
.ctags
View File

@ -1,6 +0,0 @@
--recurse
--exclude=*.orig
--exclude=*.html
--exclude=*.html.in
--langmap=c:+.h.in
--c-kinds=+p

179
.gitignore vendored
View File

@ -1,34 +1,24 @@
*#*#
*.#*#
*.[187]
*.[187].in
*.a
*.cov
*.exe
*.exe.manifest
*.gcda
*.gcno
*.gcov
*.html
*.i
*.init
*.la
*.lo
*.loT
*.o
*.orig
*.pem
*.pyc
*.rej
*.s
*.service
*.socket
*.swp
*~
.#*
.color_coded
.deps
.dirstamp
.gdb_history
.git
.git-module-status
@ -36,17 +26,18 @@
.lvimrc
.memdump
.sc-start-sc_*
.ycm_extra_conf.py
/ABOUT-NLS
/AUTHORS
/COPYING
/ChangeLog
/GNUmakefile
/INSTALL
/NEWS
/aclocal.m4
/autom4te.cache
/build-aux/*
/build-aux
/build-aux/
/build/
/confdefs.h
/config.cache
/config.guess
/config.h
@ -57,42 +48,39 @@
/config.sub
/configure
/configure.lineno
/conftest.*
/docs/aclperms.htmlinc
/daemon/*_dispatch.h
/daemon/libvirt_qemud
/daemon/libvirtd
/daemon/libvirtd*.logrotate
/daemon/libvirtd.8
/daemon/libvirtd.8.in
/daemon/libvirtd.init
/daemon/libvirtd.pod
/daemon/libvirtd.policy
/daemon/libvirtd.service
/daemon/test_libvirtd.aug
/docs/apibuild.py.stamp
/docs/devhelp/libvirt.devhelp
/docs/hvsupport.html.in
/docs/libvirt-admin-*.xml
/docs/libvirt-api.xml
/docs/libvirt-lxc-*.xml
/docs/libvirt-qemu-*.xml
/docs/libvirt-refs.xml
/docs/news.html.in
/docs/search.php
/docs/todo.html.in
/examples/admin/client_close
/examples/admin/client_info
/examples/admin/client_limits
/examples/admin/list_clients
/examples/admin/list_servers
/examples/admin/logging
/examples/admin/threadpool_params
/examples/object-events/event-test
/examples/domain-events/events-c/event-test
/examples/dominfo/info1
/examples/domsuspend/suspend
/examples/dommigrate/dommigrate
/examples/domtop/domtop
/examples/hellolibvirt/hellolibvirt
/examples/openauth/openauth
/examples/rename/rename
/gnulib/lib/*
/gnulib/m4/*
/gnulib/tests/*
/include/libvirt/libvirt-common.h
/include/libvirt/libvirt.h
/libtool
/libvirt-*.tar.xz
/libvirt-*.tar.gz
/libvirt-[0-9]*
/libvirt*.pc
/libvirt.pc
/libvirt.spec
/ltconfig
/ltmain.sh
@ -100,52 +88,35 @@
/maint.mk
/mingw-libvirt.spec
/mkinstalldirs
/po/*gmo
/po/*po
!/po/*.mini.po
/po/*pot
/po/*
/proxy/
/python/
/python/generated.stamp
/python/generator.py.stamp
/python/libvirt-export.c
/python/libvirt-lxc-export.c
/python/libvirt-lxc.[ch]
/python/libvirt-qemu-export.c
/python/libvirt-qemu.[ch]
/python/libvirt.[ch]
/python/libvirt.py
/python/libvirt_lxc.py
/python/libvirt_qemu.py
/run
/sc_*
/src/.*.stamp
/src/*.pc
/src/access/org.libvirt.api.policy
/src/access/viraccessapicheck.c
/src/access/viraccessapicheck.h
/src/access/viraccessapichecklxc.c
/src/access/viraccessapichecklxc.h
/src/access/viraccessapicheckqemu.c
/src/access/viraccessapicheckqemu.h
/src/admin/admin_client.h
/src/admin/admin_protocol.[ch]
/src/admin/admin_server_dispatch_stubs.h
/src/esx/*.generated.*
/src/hyperv/*.generated.*
/src/libvirt*.def
/src/libvirt.syms
/src/libvirt_access.syms
/src/libvirt_access.xml
/src/libvirt_access_lxc.syms
/src/libvirt_access_lxc.xml
/src/libvirt_access_qemu.syms
/src/libvirt_access_qemu.xml
/src/libvirt_admin.syms
/src/libvirt_*.stp
/src/libvirt_*helper
/src/libvirt_*probes.h
/src/libvirt_lxc
/src/libvirtd
/src/libvirtd*.logrotate
/src/locking/libxl-lockd.conf
/src/locking/libxl-sanlock.conf
/src/locking/lock_daemon_dispatch_stubs.h
/src/locking/lock_protocol.[ch]
/src/locking/qemu-lockd.conf
/src/locking/qemu-sanlock.conf
/src/locking/test_libvirt_sanlock.aug
/src/logging/log_daemon_dispatch_stubs.h
/src/logging/log_protocol.[ch]
/src/lxc/lxc_controller_dispatch.h
/src/lxc/lxc_monitor_dispatch.h
/src/lxc/lxc_monitor_protocol.c
@ -155,47 +126,85 @@
/src/qemu/test_libvirtd_qemu.aug
/src/remote/*_client_bodies.h
/src/remote/*_protocol.[ch]
/src/remote/*_stubs.h
/src/rpc/virkeepaliveprotocol.[ch]
/src/rpc/virnetprotocol.[ch]
/src/test_libvirt*.aug
/src/test_virtlockd.aug
/src/test_virtlogd.aug
/src/util/virkeycodetable*.h
/src/util/virkeynametable*.h
/src/util/virkeymaps.h
/src/virt-aa-helper
/src/virtlockd
/src/virtlogd
/src/virt-guest-shutdown.target
/src/virtlockd.init
/tests/*.log
/tests/*.pid
/tests/*.trs
/tests/*test
/tests/*xml2*test
/tests/commandhelper
/tests/qemucapsprobe
!/tests/virsh-self-test
!/tests/virt-aa-helper-test
!/tests/virt-admin-self-test
/tests/objectlocking
/tests/objectlocking-files.txt
/tests/objectlocking.cm[ix]
/tests/commandtest
/tests/conftest
/tests/cputest
/tests/domainsnapshotxml2xmltest
/tests/esxutilstest
/tests/eventtest
/tests/hashtest
/tests/jsontest
/tests/libvirtdconftest
/tests/networkxml2argvtest
/tests/nodeinfotest
/tests/nwfilterxml2xmltest
/tests/object-locking
/tests/object-locking-files.txt
/tests/object-locking.cm[ix]
/tests/openvzutilstest
/tests/qemuargv2xmltest
/tests/qemuhelptest
/tests/qemumonitorjsontest
/tests/qemumonitortest
/tests/qemuxmlnstest
/tests/qparamtest
/tests/reconnect
/tests/secaatest
/tests/seclabeltest
/tests/securityselinuxlabeltest
/tests/securityselinuxtest
/tests/sexpr2xmltest
/tests/shunloadtest
/tests/sockettest
/tests/ssh
/tests/test_file_access.txt
/tests/statstest
/tests/storagebackendsheepdogtest
/tests/sysinfotest
/tests/test_conf
/tests/utiltest
/tests/viratomictest
/tests/virauthconfigtest
/tests/virbitmaptest
/tests/virbuftest
/tests/vircgrouptest
/tests/virdrivermoduletest
/tests/virendiantest
/tests/virhashtest
/tests/viridentitytest
/tests/virkeycodetest
/tests/virkeyfiletest
/tests/virlockspacetest
/tests/virnet*test
/tests/virportallocatortest
/tests/virshtest
/tests/virstoragetest
/tests/virstringtest
/tests/virtimetest
/tests/viruritest
/tests/vmx2xmltest
/tests/xencapstest
/tests/xmconfigtest
/tools/*.[18]
/tools/libvirt-guests.init
/tools/libvirt-guests.service
/tools/libvirt-guests.sh
/tools/virt-login-shell
/tools/virsh
/tools/virsh-*-edit.c
/tools/virt-admin
/tools/virt-*-validate
/tools/virt-sanlock-cleanup
/tools/wireshark/src/plugin.c
/tools/wireshark/src/libvirt
/update.log
GPATH
GRTAGS
GTAGS
Makefile
Makefile.in
TAGS
@ -209,7 +218,9 @@ stamp-h
stamp-h.in
stamp-h1
tags
!/build-aux/*.pl
!/gnulib/lib/Makefile.am
!/gnulib/tests/Makefile.am
!/m4/virt-*.m4
!/po/*.po
!/po/POTFILES.in
!/po/libvirt.pot

5
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "gnulib"]
path = .gnulib
url = https://git.savannah.gnu.org/git/gnulib.git/
[submodule "keycodemapdb"]
path = src/keycodemapdb
url = https://gitlab.com/keycodemap/keycodemapdb.git
url = git://git.sv.gnu.org/gnulib.git

View File

@ -1,3 +0,0 @@
[gitpublishprofile "default"]
base = master
to = libvir-list@redhat.com

Submodule .gnulib updated: 8089c00979...644c40496c

View File

@ -5,10 +5,7 @@
<bozzolan@gmail.com> <redshift@gmx.com>
<charles_duffy@messageone.com> <charles@dyfis.net>
<claudio.bley@gmail.com> <cbley@av-test.de>
<dfj@redhat.com> <dfj@dfj.bne.redhat.com>
<dpkshetty@gmail.com> <deepakcs@linux.vnet.ibm.com>
<dpkshetty@gmail.com> <deepakcs@redhat.com>
<eblake@redhat.com> <ebb9@byu.net>
<gdolley@arpnetworks.com> <gdolley@ucla.edu>
<gerhard.stenzel@de.ibm.com> <gstenzel@linux.vnet.ibm.com>
@ -20,6 +17,7 @@
<jfehlig@suse.com> <jfehlig@novell.com>
<jfehlig@suse.com> <jfehlig@linux-ypgk.site>
<jclift@redhat.com> <justin@salasaga.org>
<berrange@redhat.com> <dan@berrange.com>
<soren@linux2go.dk> <soren@canonical.com>
<cfergeau@redhat.com> <teuf@gnome.org>
<wency@cn.fujitsu.com> <wency cn fujitsu com>
@ -38,11 +36,6 @@
<zhlcindy@linux.vnet.ibm.com> <zhlcindy@gmail.com>
<serge.hallyn@canonical.com> <serue@us.ibm.com>
<pritesh.kothari@sun.com> <Pritesh.Kothari@Sun.COM>
<cbosdonnat@suse.com> <cedric.bosdonnat@free.fr>
<mnestratov@virtuozzo.com> <mnestratov@parallels.com>
<nshirokovskiy@virtuozzo.com> <nshirokovskiy@parallels.com>
<jyang@redhat.com> <osier@yunify.com>
<kkoukiou@redhat.com> <k.koukiou@googlemail.com>
# Name consolidation:
# Preferred author spelling <preferred email>
@ -60,16 +53,6 @@ Aurelien Rougemont <beorn@binaries.fr>
Serge E. Hallyn <serge.hallyn@canonical.com>
Henrik Persson E <henrik.e.persson@ericsson.com>
Philipp Hahn <hahn@univention.de>
Marco Bozzolan <bozzolan@gmail.com>
Marco Bozzolan <redshift@gmx.com>
Pritesh Kothari <pritesh.kothari@sun.com>
Wang Yufei (James) <james.wangyufei@huawei.com>
Deepak C Shetty <dpkshetty@gmail.com>
Dave Allan <dallan@redhat.com>
Richard W.M. Jones <rjones@redhat.com>
# Non-trivial consolidation:
# see git documentation for information about the format
Daniel P. Berrangé <berrange@redhat.com>
Daniel P. Berrangé <berrange@redhat.com> <dan@berrange.com>
Michal Prívozník <mprivozn@redhat.com>
Michal Prívozník <mprivozn@redhat.com> <miso.privoznik@gmail.com>
Marco Bozzolan <bozzolan@gmail.com> <redshift@gmx.com>

View File

@ -1,111 +0,0 @@
sudo: required
language: generic
branches:
except:
- /^.*-maint$/
matrix:
include:
- services:
- docker
env:
- IMAGE="ubuntu-18"
- DISTCHECK_CONFIGURE_FLAGS="--with-init-script=systemd"
- DOCKER_CMD="$LINUX_CMD"
- services:
- docker
env:
- IMAGE="centos-7"
- DISTCHECK_CONFIGURE_FLAGS="--with-init-script=upstart"
- DOCKER_CMD="$LINUX_CMD"
- services:
- docker
env:
- IMAGE="fedora-rawhide"
- MINGW="mingw32"
- DOCKER_CMD="$MINGW_CMD"
- services:
- docker
env:
- IMAGE="fedora-rawhide"
- MINGW="mingw64"
- DOCKER_CMD="$MINGW_CMD"
- compiler: clang
language: c
os: osx
env:
- PATH="/usr/local/opt/gettext/bin:/usr/local/opt/ccache/libexec:/usr/local/opt/rpcgen/bin:$PATH"
script:
/bin/sh -xc "$MACOS_CMD"
script:
- docker run
-v $(pwd):/build
-w /build
-e VIR_TEST_DEBUG="$VIR_TEST_DEBUG"
-e MINGW="$MINGW"
-e DISTCHECK_CONFIGURE_FLAGS="$DISTCHECK_CONFIGURE_FLAGS"
"quay.io/libvirt/buildenv-$IMAGE:master"
/bin/sh -xc "$DOCKER_CMD"
git:
submodules: true
env:
global:
- VIR_TEST_DEBUG=1
- LINUX_CMD="
./autogen.sh &&
make -j3 syntax-check &&
make -j3 distcheck DISTCHECK_CONFIGURE_FLAGS=\"\$DISTCHECK_CONFIGURE_FLAGS\" ||
(
echo '=== LOG FILE(S) START ===';
find -name test-suite.log | xargs cat;
echo '=== LOG FILE(S) END ===';
exit 1
)
"
- MINGW_CMD="
NOCONFIGURE=1 ./autogen.sh &&
\$MINGW-configure &&
make -j3 ||
(
echo '=== LOG FILE(S) START ===';
find -name test-suite.log | xargs cat;
echo '=== LOG FILE(S) END ===';
exit 1
)
"
# We can't run 'distcheck' or 'syntax-check' because they fail on
# macOS, but doing 'install' and 'dist' gives us some useful coverage
- MACOS_CMD="
brew update &&
brew install ccache rpcgen xz yajl &&
./autogen.sh --prefix=\$(pwd)/install-root &&
make -j3 &&
make -j3 install &&
make -j3 dist ||
(
echo '=== LOG FILE(S) START ===';
find -name test-suite.log | xargs cat;
echo '=== LOG FILE(S) END ===';
exit 1
)
"
notifications:
irc:
# The channel name "irc.oftc.net#virt" is encrypted against libvirt/libvirt
# to prevent IRC notifications from github forks. This was created using:
# $ travis encrypt -r "libvirt/libvirt" "irc.oftc.net#virt"
channels:
- secure: "hUPdkLxX7nh75+clpnk4U0XLExLfV9DFKSvQSAUtf5JtDNMslj7AeOCf2wcbkNsEhkiF557odTAnov1s5m1w/yaa56zbjFAh5agzqRKya3QjqsrvlBKw/WuN+l82iMNLLeebTgCPAXrbAbGWH8YmYssp/7+eMsnKaVh84EQQNbMCHlLg6ovE26Fs18mZ6J5RC3OPa1vbv+xkdCHvGg/Oyp4K8bpU7RYyimA56jdxI/OfdTH9HxntHYSzykR7hDbyzZhdIlAUyRKReQVjcV5+R8fdDL/1imyGA/88KTztMeKXpZ5Rf+Ss3vYLZb6qsLLegCZ4AU/q0vvbWxjpZGJZoeyrVpfBTZdYGIzmLTMl9GYXXa/gDwFlbvRDiPDG4TIy6GlMUROinj7KRKEHu1fWRYu012ife5OjidxcwrTnz21vYaCv3AKWPpMPxwIzQPkY1hex9uLLX6z+TrAxxDLF+7UzRT9w2RLFBkLYlj2aDVrLAVb/ynRsxDz5CGzC61FSQVft2e308SkGjdn8YxvguCuXv+N70Fu1cvFyh5XYeHb4fbBRo0Ctzaec78leHlQvRGWKJxXDXRkE2lvvBc7YbBNSAYh7Fs8Y+zY7l7rMxvXdrt3nuaNQhe74V3yhxPDAld66qmAn9TYMmaZW2f5/KKKILLbCa0t2MxiAc6L2OI8="
on_success: change
on_failure: always
email:
# The list name 'libvirt-ci@redhat.com" is encrypted against libvirt/libvirt
# to prevent IRC notifications from github forks. This was created using:
# $ travis encrypt -r "libvirt/libvirt" "libvirt-ci@redhat.com"
recipients:
- secure: "QcU9eP96P0RlDNzVRZl/4sxyydPStGzECrpgJhr2IPB/7pHk23yaBrmUsq9S830tB+jwLGma1IscNB8uf7Sf7WY+cYIpfR8v030OffWnaipo/Gcs0dpnlfURWHjOFQI3RJzGEihsqvbwUFOwsM+3IDyO3qdWaiT6cN2Tj9ROlwYCySSX5YWzLyX7arBZ4lp8ESs7ohQaEwp2cegnMP2oGPJJe4SebvlCDjHZbjkU5aEradwUWnRQDJZWTKknpNLArVFxN2/ixp6f/MGY4DmkHoDweio6mHIPN5zTs5Jt32aiX6wDBa+bBa4v8TCRqzhYkQ63ZZhNV8bY5Uf9ufTdyvt96yIANyakd85b1QpMdAX76IyJi1l0/Uub6DTQZAcq3vK7iPjGeTVSpyoXrqTfGy4JxMjqDoocpWvv8ALX1wrYI/HfN2R2Aepw9jModTimOsebYhJ1yMhSt8qnh5AQNftGKL2JBKoA1LWdU2YJ5fO1bGjKNiVEkGFQTPYFWrYCUY5JcT+s5WCzNeMNm8s9na8liYhGl3WtS3rPr5M8bof+BMsBhG2hQ0loduc94x2GkvyhQZUgRbqrwNR+y4hn+rWFC3hBzzyiAULs43vY/PJ+eBdKEf3VAc0MkhQ8GgXGSA61fR6aXYonroI/WnBVItwDmUnnMfSziZXxk09GLl4="

View File

@ -1,45 +0,0 @@
flags = [
'-I@abs_top_builddir@',
'-I@abs_top_srcdir@',
'-I@abs_top_builddir@/gnulib/lib',
'-I@abs_top_srcdir@/gnulib/lib',
'-I@abs_top_builddir@/include',
'-I@abs_top_srcdir@/include',
'-I@abs_top_builddir@/src',
'-I@abs_top_srcdir@/src',
'-I@abs_top_builddir@/src/access',
'-I@abs_top_srcdir@/src/access',
'-I@abs_top_builddir@/src/admin',
'-I@abs_top_srcdir@/src/admin',
'-I@abs_top_builddir@/src/bhyve',
'-I@abs_top_srcdir@/src/bhyve',
'-I@abs_top_builddir@/src/conf',
'-I@abs_top_srcdir@/src/conf',
'-I@abs_top_builddir@/src/libxl',
'-I@abs_top_srcdir@/src/libxl',
'-I@abs_top_builddir@/src/locking',
'-I@abs_top_srcdir@/src/locking',
'-I@abs_top_builddir@/src/logging',
'-I@abs_top_srcdir@/src/logging',
'-I@abs_top_builddir@/src/lxc',
'-I@abs_top_srcdir@/src/lxc',
'-I@abs_top_builddir@/src/qemu',
'-I@abs_top_srcdir@/src/qemu',
'-I@abs_top_builddir@/src/remote',
'-I@abs_top_srcdir@/src/remote',
'-I@abs_top_builddir@/src/rpc',
'-I@abs_top_srcdir@/src/rpc',
'-I@abs_top_builddir@/src/secret',
'-I@abs_top_srcdir@/src/secret',
'-I@abs_top_builddir@/src/security',
'-I@abs_top_srcdir@/src/security',
'-I@abs_top_builddir@/src/util',
'-I@abs_top_srcdir@/src/util',
'-I@abs_top_builddir@/src/vmx',
'-I@abs_top_srcdir@/src/vmx',
'-I@abs_top_builddir@/src/xenconfig',
'-I@abs_top_srcdir@/src/xenconfig',
]
def FlagsForFile(filename, **kwargs):
return { 'flags': flags, 'do_cache': True }

View File

@ -1 +0,0 @@
po/README.md

View File

@ -8,53 +8,42 @@ Daniel Veillard <veillard@redhat.com> or <daniel@veillard.com>
The primary maintainers and people with commit access rights:
Alex Jia <ajia@redhat.com>
Andrea Bolognani <abologna@redhat.com>
Cédric Bosdonnat <cbosdonnat@suse.com>
Christian Ehrhardt <christian.ehrhardt@canonical.com>
Anthony Liguori <aliguori@us.ibm.com>
Chris Lalancette <clalance@redhat.com>
Christophe Fergeau <cfergeau@redhat.com>
Claudio Bley <claudio.bley@gmail.com>
Claudio Bley <cbley@av-test.de>
Cole Robinson <crobinso@redhat.com>
Daniel P. Berrangé <berrange@redhat.com>
Daniel Berrange <berrange@redhat.com>
Daniel Veillard <veillard@redhat.com>
Dave Allan <dallan@redhat.com>
Doug Goldstein <cardoe@gentoo.org>
Eric Blake <eblake@redhat.com>
Erik Skultety <eskultet@redhat.com>
Gao Feng <gaofeng@cn.fujitsu.com>
Guannan Ren <gren@redhat.com>
Guido Günther <agx@sigxcpu.org>
Ján Tomko <jtomko@redhat.com>
Jim Fehlig <jfehlig@suse.com>
Jim Meyering <meyering@redhat.com>
Jiří Denemark <jdenemar@redhat.com>
John Ferlan <jferlan@redhat.com>
Katerina Koukiou <kkoukiou@redhat.com>
John Levon <john.levon@sun.com>
Justin Clift <jclift@redhat.com>
Laine Stump <laine@redhat.com>
Mark McLoughlin <markmc@redhat.com>
Martin Kletzander <mkletzan@redhat.com>
Matthias Bolte <matthias.bolte@googlemail.com>
Maxim Nestratov <mnestratov@virtuozzo.com>
Michal Prívozník <mprivozn@redhat.com>
Nikolay Shirokovskiy <nshirokovskiy@virtuozzo.com>
Pavel Hrdina <phrdina@redhat.com>
Osier Yang <jyang@redhat.com>
Peter Krempa <pkrempa@redhat.com>
Richard W.M. Jones <rjones@redhat.com>
Roman Bogorodskiy <bogorodskiy@gmail.com>
Stefan Berger <stefanb@us.ibm.com>
Wen Congyang <wency@cn.fujitsu.com>
Previous maintainers:
Anthony Liguori <aliguori@us.ibm.com>
Atsushi SAKAI <sakaia@jp.fujitsu.com>
Chris Lalancette <clalance@redhat.com>
Dan Smith <danms@us.ibm.com>
Dave Allan <dallan@redhat.com>
Dave Leskovec <dlesko@linux.vnet.ibm.com>
Dmitry Guryanov <dguryanov@parallels.com>
Guannan Ren <gren@redhat.com>
Jim Meyering <meyering@redhat.com>
John Levon <john.levon@sun.com>
Justin Clift <jclift@redhat.com>
Karel Zak <kzak@redhat.com>
Osier Yang <jyang@redhat.com>
Patches have also been contributed by:
@ -63,6 +52,7 @@ Amit Shah <amit.shah@redhat.com>
Andrew Puch <apuch@redhat.com>
Anton Protopopov <aspsk2@gmail.com>
Ben Guthro <ben.guthro@gmail.com>
Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
Daniel Hokka Zakrisson <daniel@hozac.com>
Dan Wendlandt <dan@nicira.com>
David Lively <dlively@virtualiron.com>
@ -91,7 +81,9 @@ Stefan de Konink <dekonink@kinkrsoftware.nl>
Takahashi Tomohiro <takatom@jp.fujitsu.com>
Tatsuro Enokura <fj7716hz@aa.jp.fujitsu.com>
#contributorslist#
#authorslist#
[....send patches to get your name here....]
The libvirt logo was designed by Diana Fong

339
COPYING
View File

@ -1,339 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 2 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -1,502 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

502
COPYING.LIB Normal file
View File

@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@ -4286,7 +4286,7 @@ Wed Dec 17 21:45:39 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
Wed Dec 17 21:41:39 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
* src/libvirt_sym.version.in: Remove non-existent symbols
* src/libvirt_sym.version.in: Remove non-existant symbols
(John Levon)
Wed Dec 17 21:35:39 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
@ -5504,7 +5504,7 @@ Tue Nov 11 15:51:42 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
Mon Nov 10 12:05:42 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
* src/openvz_conf.c: Read filesystem template name from config
* src/openvz_conf.c: Read filesytem template name from config
files. Increase buffer size when parsing vzctl version number
Thu Nov 6 20:45:42 CET 2008 Jim Meyering <meyering@redhat.com>
@ -12415,7 +12415,7 @@ Thu Jul 12 11:02:17 EST 2007 Daniel P. Berrange <berrange@redhat.com>
Thu Jul 12 11:00:17 EST 2007 Daniel P. Berrange <berrange@redhat.com>
* qemud/qemud.c: Add explicit checks for existence of x509
* qemud/qemud.c: Add explicit checks for existance of x509
certificate & key files to get better error reporting than
GNU TLS offers when it can't load a file
@ -13276,7 +13276,7 @@ Tue Apr 17 11:30:46 CEST 2007 Daniel Veillard <veillard@redhat.com>
Mon Apr 16 09:11:04 EST 2007 Daniel P. Berrange <berrange@redhat.com>
* qemud/conf.c: Check for existence of QEMU binary path. Fix check
* qemud/conf.c: Check for existance of QEMU binary path. Fix check
for -no-kqemu flag to work with x86_64 on i386
Mon Apr 16 09:09:04 EST 2007 Daniel P. Berrange <berrange@redhat.com>
@ -13920,7 +13920,7 @@ Tue Feb 27 10:20:43 EST 2007 Daniel P. Berrange <berrange@redhat.com>
* src/xend_internal.c: Only hardcode port = 5900+domid if
running against old XenD < 3.0.3, because in newer XenD
port is guaranteed to be available in XenStore if the VNC
port is guarenteed to be available in XenStore if the VNC
server is running.
Mon Feb 26 15:33:08 IST 2007 Mark McLoughlin <markmc@redhat.com>
@ -15020,7 +15020,7 @@ Tue Nov 7 16:33:43 CET 2006 Daniel Veillard <veillard@redhat.com>
Tue Oct 31 10:31:34 CET 2006 Daniel Veillard <veillard@redhat.com>
* src/xend_internal.c: when getting informations about a non
existent domain, it is not a good idea to raise the HTTP
existant domain, it is not a good idea to raise the HTTP
404 GET error, the handling is better done somewhere up in
the stack.
@ -15228,7 +15228,7 @@ Sun Sep 3 12:34:23 EDT 2006 Daniel Berrange <berrange@redhat.com>
iterating over list of ids/names, because it is not neccessarily
the same as the value returned by virConnectNumOfDomains. Use qsort
to sort active domains by Id, and inactive domains by name, since
there is no guaranteed sort ordering when listing domains. For inactive
there is no guarenteed sort ordering when listing domains. For inactive
domains display a '-' instead of '-1' to make it clear they have no
sensible ID number.

902
HACKING Normal file
View File

@ -0,0 +1,902 @@
-*- buffer-read-only: t -*- vi: set ro:
DO NOT EDIT THIS FILE! IT IS GENERATED AUTOMATICALLY
from docs/hacking.html.in!
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, with git rename detection enabled. You
need a one-time setup of:
git config diff.renames true
After that, a command similar to this should work:
diff -urp libvirt.orig/ libvirt.modified/ > libvirt-myfeature.patch
or:
git diff > libvirt-myfeature.patch
Also, for code motion patches, you may find that "git diff --patience"
provides an easier-to-read patch. However, the usual workflow of libvirt
developer is:
git checkout master
git pull
git checkout -t origin -b workbranch
Hack, committing any changes along the way
More hints on compiling can be found here <compiling.html>. When you want to
post your patches:
git pull --rebase
(fix any conflicts)
git send-email --cover-letter --no-chain-reply-to --annotate \
--to=libvir-list@redhat.com master
(Note that the "git send-email" subcommand may not be in the main git package
and using it may require installion of a separate package, for example the
"git-email" package in Fedora.) For a single patch you can omit
"--cover-letter", but a series of two or more patches needs a cover letter. If
you get tired of typing "--to=libvir-list@redhat.com" designation you can set
it in git config:
git config sendemail.to libvir-list@redhat.com
Please follow this as close as you can, especially the rebase and git
send-email part, as it makes life easier for other developers to review your
patch set. One should avoid sending patches as attachments, but rather send
them in email body along with commit message. If a developer is sending
another version of the patch (e.g. to address review comments), he is advised
to note differences to previous versions after the "---" line in the patch so
that it helps reviewers but doesn't become part of git history. Moreover, such
patch needs to be prefixed correctly with "--subject-prefix=PATCHv2" appended
to "git send-email" (substitute "v2" with the correct version if needed
though).
(3) In your commit message, make the summary line reasonably short (60 characters
is typical), followed by a blank line, followed by any longer description of
why your patch makes sense. If the patch fixes a regression, and you know what
commit introduced the problem, mentioning that is useful. If the patch
resolves a bugzilla report, mentioning the URL of the bug number is useful;
but also summarize the issue rather than making all readers follow the link.
You can use 'git shortlog -30' to get an idea of typical summary lines.
Libvirt does not currently attach any meaning to Signed-off-by: lines, so it
is up to you if you want to include or omit them in the commit message.
(4) 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. Moreover, please keep in mind that it's
required to be able to compile cleanly (*including* "make check" and "make
syntax-check") after each patch. A feature does not have to work until the end
of a series, but intermediate patches must compile and not cause test-suite
failures (this is to preserve the usefulness of "git bisect", among other
things).
(5) Make sure your patches apply against libvirt GIT. Developers only follow GIT
and don't care much about released versions.
(6) Run the automated tests on your code before submitting any changes. In
particular, configure with compile warnings set to -Werror. This is done
automatically for a git checkout; from a tarball, use:
./configure --enable-werror
and run the tests:
make check
make syntax-check
make -C tests valgrind
Valgrind
http://valgrind.org/is a test that checks for memory management issues, such as leaks or use of
uninitialized variables.
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
There is also a "./run" script at the top level, to make it easier to run
programs that have not yet been installed, as well as to wrap invocations of
various tests under gdb or Valgrind.
(7) The Valgrind test should produce similar output to "make check". If the output
has traces within libvirt API's, then investigation is required in order to
determine the cause of the issue. Output such as the following indicates some
sort of leak:
==5414== 4 bytes in 1 blocks are definitely lost in loss record 3 of 89
==5414== at 0x4A0881C: malloc (vg_replace_malloc.c:270)
==5414== by 0x34DE0AAB85: xmlStrndup (in /usr/lib64/libxml2.so.2.7.8)
==5414== by 0x4CC97A6: virDomainVideoDefParseXML (domain_conf.c:7410)
==5414== by 0x4CD581D: virDomainDefParseXML (domain_conf.c:10188)
==5414== by 0x4CD8C73: virDomainDefParseNode (domain_conf.c:10640)
==5414== by 0x4CD8DDB: virDomainDefParse (domain_conf.c:10590)
==5414== by 0x41CB1D: testCompareXMLToArgvHelper (qemuxml2argvtest.c:100)
==5414== by 0x41E20F: virtTestRun (testutils.c:161)
==5414== by 0x41C7CB: mymain (qemuxml2argvtest.c:866)
==5414== by 0x41E84A: virtTestMain (testutils.c:723)
==5414== by 0x34D9021734: (below main) (in /usr/lib64/libc-2.15.so)
In this example, the "virDomainDefParseXML()" had an error path where the
"virDomainVideoDefPtr video" pointer was not properly disposed. By simply
adding a "virDomainVideoDefFree(video);" in the error path, the issue was
resolved.
Another common mistake is calling a printing function, such as "VIR_DEBUG()"
without initializing a variable to be printed. The following example involved
a call which could return an error, but not set variables passed by reference
to the call. The solution was to initialize the variables prior to the call.
==4749== Use of uninitialised value of size 8
==4749== at 0x34D904650B: _itoa_word (in /usr/lib64/libc-2.15.so)
==4749== by 0x34D9049118: vfprintf (in /usr/lib64/libc-2.15.so)
==4749== by 0x34D9108F60: __vasprintf_chk (in /usr/lib64/libc-2.15.so)
==4749== by 0x4CAEEF7: virVasprintf (stdio2.h:199)
==4749== by 0x4C8A55E: virLogVMessage (virlog.c:814)
==4749== by 0x4C8AA96: virLogMessage (virlog.c:751)
==4749== by 0x4DA0056: virNetTLSContextCheckCertKeyUsage (virnettlscontext.c:225)
==4749== by 0x4DA06DB: virNetTLSContextCheckCert (virnettlscontext.c:439)
==4749== by 0x4DA1620: virNetTLSContextNew (virnettlscontext.c:562)
==4749== by 0x4DA26FC: virNetTLSContextNewServer (virnettlscontext.c:927)
==4749== by 0x409C39: testTLSContextInit (virnettlscontexttest.c:467)
==4749== by 0x40AB8F: virtTestRun (testutils.c:161)
Valgrind will also find some false positives or code paths which cannot be
resolved by making changes to the libvirt code. For these paths, it is
possible to add a filter to avoid the errors. For example:
==4643== 7 bytes in 1 blocks are possibly lost in loss record 4 of 20
==4643== at 0x4A0881C: malloc (vg_replace_malloc.c:270)
==4643== by 0x34D90853F1: strdup (in /usr/lib64/libc-2.15.so)
==4643== by 0x34EEC2C08A: ??? (in /usr/lib64/libnl.so.1.1)
==4643== by 0x34EEC15B81: ??? (in /usr/lib64/libnl.so.1.1)
==4643== by 0x34D8C0EE15: call_init.part.0 (in /usr/lib64/ld-2.15.so)
==4643== by 0x34D8C0EECF: _dl_init (in /usr/lib64/ld-2.15.so)
==4643== by 0x34D8C01569: ??? (in /usr/lib64/ld-2.15.so)
In this instance, it is acceptible to modify the "tests/.valgrind.supp" file
in order to add a suppression filter. The filter should be unique enough to
not suppress real leaks, but it should be generic enough to cover multiple
code paths. The format of the entry can be found in the documentation found at
the
Valgrind home page.
http://valgrind.org/The following trace was added to "tests/.valgrind.supp" in order to suppress
the warning:
{
dlInitMemoryLeak1
Memcheck:Leak
fun:?alloc
...
fun:call_init.part.0
fun:_dl_init
...
obj:*/lib*/ld-2.*so*
}
(8) 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
Richard Jones' guide to working with open source projects
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))))
If you use vim, append the following to your ~/.vimrc file:
set nocompatible
filetype on
set autoindent
set smartindent
set cindent
set tabstop=8
set shiftwidth=4
set expandtab
set cinoptions=(0,:0,l1,t0
filetype plugin indent on
au FileType make setlocal noexpandtab
au BufRead,BufNewFile *.am setlocal noexpandtab
match ErrorMsg /\s\+$\| \+\ze\t/
Or if you don't want to mess your ~/.vimrc up, you can save the above into a
file called .lvimrc (not .vimrc) located at the root of libvirt source, then
install a vim script from
http://www.vim.org/scripts/script.php?script_id=1408, which will load the
.lvimrc only when you edit libvirt code.
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 post-process 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.
Libvirt requires a C99 compiler for various reasons. However, most of the code
base prefers to stick to C89 syntax unless there is a compelling reason
otherwise. For example, it is preferable to use "/* */" comments rather than
"//". Also, when declaring local variables, the prevailing style has been to
declare them at the beginning of a scope, rather than immediately before use.
Bracket spacing
===============
The keywords "if", "for", "while", and "switch" must have a single space
following them before the opening bracket. E.g.
if(foo) // Bad
if (foo) // Good
Function implementations mustnothave any whitespace between the function name and the opening bracket. E.g.
int foo (int wizz) // Bad
int foo(int wizz) // Good
Function calls mustnothave any whitespace between the function name and the opening bracket. E.g.
bar = foo (wizz); // Bad
bar = foo(wizz); // Good
Function typedefs mustnothave any whitespace between the closing bracket of the function name and
opening bracket of the arg list. E.g.
typedef int (*foo) (int wizz); // Bad
typedef int (*foo)(int wizz); // Good
There must not be any whitespace immediately following any opening bracket, or
immediately prior to any closing bracket. E.g.
int foo( int wizz ); // Bad
int foo(int wizz); // Good
Curly braces
============
Omit the curly braces around an "if", "while", "for" etc. body only when that
body occupies a single line. In every other case we require the braces. This
ensures that it is trivially easy to identify a single-'statement' loop: each
has only one 'line' in its body.
Omitting braces with a single-line body is fine:
while (expr) // one-line body -> omitting curly braces is ok
single_line_stmt();
However, the moment your loop/if/else body extends on to a second line, for
whatever reason (even if it's just an added comment), then you should add
braces. Otherwise, it would be too easy to insert a statement just before that
comment (without adding braces), thinking it is already a multi-statement loop:
while (true) // BAD! multi-line body with no braces
/* comment... */
single_line_stmt();
Do this instead:
while (true) { // Always put braces around a multi-line body.
/* comment... */
single_line_stmt();
}
There is one exception: when the second body line is not at the same
indentation level as the first body line:
if (expr)
die("a diagnostic that would make this line"
" extend past the 80-column limit"));
It is safe to omit the braces in the code above, since the further-indented
second body line makes it obvious that this is still a single-statement body.
To reiterate, don't do this:
if (expr) // BAD: no braces around...
while (expr_2) { // ... a multi-line body
...
}
Do this, instead:
if (expr) {
while (expr_2) {
...
}
}
However, there is one exception in the other direction, when even a one-line
block should have braces. That occurs when that one-line, brace-less block is
an "if" or "else" block, and the counterpart block *does* use braces. In that
case, put braces around both blocks. Also, if the "else" block is much shorter
than the "if" block, consider negating the "if"-condition and swapping the
bodies, putting the short block first and making the longer, multi-line block
be the "else" block.
if (expr) {
...
...
}
else
x = y; // BAD: braceless "else" with braced "then",
// and short block last
if (expr)
x = y; // BAD: braceless "if" with braced "else"
else {
...
...
}
Keeping braces consistent and putting the short block first is preferred,
especially when the multi-line body is more than a few lines long, because it
is easier to read and grasp the semantics of an if-then-else block when the
simpler block occurs first, rather than after the more involved block:
if (!expr) {
x = y; // putting the smaller block first is more readable
} else {
...
...
}
But if negating a complex condition is too ugly, then at least add braces:
if (complex expr not worth negating) {
...
...
} else {
x = y;
}
Preprocessor
============
For variadic macros, stick with C99 syntax:
#define vshPrint(_ctl, ...) fprintf(stdout, __VA_ARGS__)
Use parenthesis when checking if a macro is defined, and use indentation to
track nesting:
#if defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_FALLOCATE)
# define fallocate(a,ignored,b,c) posix_fallocate(a,b,c)
#endif
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.
- To allocate a single object:
virDomainPtr domain;
if (VIR_ALLOC(domain) < 0) {
virReportOOMError();
return NULL;
}
- To allocate an array of objects:
virDomainPtr domains;
size_t ndomains = 10;
if (VIR_ALLOC_N(domains, ndomains) < 0) {
virReportOOMError();
return NULL;
}
- To allocate an array of object pointers:
virDomainPtr *domains;
size_t ndomains = 10;
if (VIR_ALLOC_N(domains, ndomains) < 0) {
virReportOOMError();
return NULL;
}
- To re-allocate the array of domains to be 1 element longer (however, note that
repeatedly expanding an array by 1 scales quadratically, so this is
recommended only for smaller arrays):
virDomainPtr domains;
size_t ndomains = 0;
if (VIR_EXPAND_N(domains, ndomains, 1) < 0) {
virReportOOMError();
return NULL;
}
domains[ndomains - 1] = domain;
- To ensure an array has room to hold at least one more element (this approach
scales better, but requires tracking allocation separately from usage)
virDomainPtr domains;
size_t ndomains = 0;
size_t ndomains_max = 0;
if (VIR_RESIZE_N(domains, ndomains_max, ndomains, 1) < 0) {
virReportOOMError();
return NULL;
}
domains[ndomains++] = domain;
- To trim an array of domains from its allocated size down to the actual used
size:
virDomainPtr domains;
size_t ndomains = x;
size_t ndomains_max = y;
VIR_SHRINK_N(domains, ndomains_max, ndomains_max - ndomains);
- To free an array of domains:
virDomainPtr domains;
size_t ndomains = x;
size_t ndomains_max = y;
size_t i;
for (i = 0; i < ndomains; i++)
VIR_FREE(domains[i]);
VIR_FREE(domains);
ndomains_max = ndomains = 0;
File handling
=============
Usage of the "fdopen()", "close()", "fclose()" APIs is deprecated in libvirt
code base to help avoiding double-closing of files or file descriptors, which
is particularly dangerous in a multi-threaded application. Instead of these
APIs, use the macros from virfile.h
- Open a file from a file descriptor:
if ((file = VIR_FDOPEN(fd, "r")) == NULL) {
virReportSystemError(errno, "%s",
_("failed to open file from file descriptor"));
return -1;
}
/* fd is now invalid; only access the file using file variable */
- Close a file descriptor:
if (VIR_CLOSE(fd) < 0) {
virReportSystemError(errno, "%s", _("failed to close file"));
}
- Close a file:
if (VIR_FCLOSE(file) < 0) {
virReportSystemError(errno, "%s", _("failed to close file"));
}
- Close a file or file descriptor in an error path, without losing the previous
"errno" value:
VIR_FORCE_CLOSE(fd);
VIR_FORCE_FCLOSE(file);
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 insensitive equality:
STRCASEEQ(a,b)
STRCASENEQ(a,b)
- For strict equality of a substring:
STREQLEN(a,b,n)
STRNEQLEN(a,b,n)
- For case insensitive equality of a substring:
STRCASEEQLEN(a,b,n)
STRCASENEQLEN(a,b,n)
- For strict equality of a prefix:
STRPREFIX(a,b)
- To avoid having to check if a or b are NULL:
STREQ_NULLABLE(a, b)
STRNEQ_NULLABLE(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
Typical usage is as follows:
char *
somefunction(...)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
...
virBufferAddLit(&buf, "<domain>\n");
virBufferAsprintf(&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 WITH_NUMACTL Some system includes aren't supported
# include <numa.h> everywhere so need these #if guards.
#endif
#include "internal.h" Include this first, after system includes.
#include "util.h" Any libvirt internal header files.
#include "buf.h"
static int
myInternalFunc() The actual code.
{
...
Of particular note: *Do not* include libvirt/libvirt.h, libvirt/virterror.h,
libvirt/libvirt-qemu.h, or libvirt/libvirt-lxc.h. They are included by
"internal.h" already and there are some special reasons why you cannot include
these files explicitly. One of the special cases, "libvirt/libvirt.h" is
included prior to "internal.h" in "remote_protocol.x", to avoid exposing
*_LAST enum elements.
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_FORMAT(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.
When printing to a string, consider using virBuffer for incremental
allocations, virAsprintf for a one-shot allocation, and snprintf for
fixed-width buffers. Do not use sprintf, even if you can prove the buffer
won't overflow, since gnulib does not provide the same portability guarantees
for sprintf as it does for snprintf.
Use of goto
===========
The use of goto is not forbidden, and goto is widely used throughout libvirt.
While the uncontrolled use of goto will quickly lead to unmaintainable code,
there is a place for it in well structured code where its use increases
readability and maintainability. In general, if goto is used for error
recovery, it's likely to be ok, otherwise, be cautious or avoid it all
together.
The typical use of goto is to jump to cleanup code in the case of a long list
of actions, any of which may fail and cause the entire operation to fail. In
this case, a function will have a single label at the end of the function.
It's almost always ok to use this style. In particular, if the cleanup code
only involves free'ing memory, then having multiple labels is overkill.
VIR_FREE() and every function named XXXFree() in libvirt is required to handle
NULL as its arg. Thus you can safely call free on all the variables even if
they were not yet allocated (yes they have to have been initialized to NULL).
This is much simpler and clearer than having multiple labels.
There are a couple of signs that a particular use of goto is not ok:
- You're using multiple labels. If you find yourself using multiple labels,
you're strongly encouraged to rework your code to eliminate all but one of
them.
- The goto jumps back up to a point above the current line of code being
executed. Please use some combination of looping constructs to re-execute code
instead; it's almost certainly going to be more understandable by others. One
well-known exception to this rule is restarting an i/o operation following
EINTR.
- The goto jumps down to an arbitrary place in the middle of a function followed
by further potentially failing calls. You should almost certainly be using a
conditional and a block instead of a goto. Perhaps some of your function's
logic would be better pulled out into a helper function.
Although libvirt does not encourage the Linux kernel wind/unwind style of
multiple labels, there's a good general discussion of the issue archived at
KernelTrap
http://kerneltrap.org/node/553/2131
When using goto, please use one of these standard labels if it makes sense:
error: A path only taken upon return with an error code
cleanup: A path taken upon return with success code + optional error
no_memory: A path only taken upon return with an OOM error code
retry: If needing to jump upwards (e.g., retry on EINTR)
Libvirt committer guidelines
============================
The AUTHORS files indicates the list of people with commit access right who
can actually merge the patches.
The general rule for committing a patch is to make sure it has been reviewed
properly in the mailing-list first, usually if a couple of people 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 where you do not have a very clear idea of how things work,
it's better to wait for a more authoritative feedback though. Before
committing, please also rebuild locally, run 'make check syntax-check', and
make sure you don't raise errors. 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
An exception to 'review and approval on the list first' is fixing failures to
build:
- if a recently committed 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
- if make check or make syntax-check 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 committing anything
- 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,86 +1,69 @@
## Process this file with automake to produce Makefile.in
## Copyright (C) 2005-2013 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, see
## <http://www.gnu.org/licenses/>.
## Copyright (C) 2005-2012 Red Hat, Inc.
## See COPYING.LIB for the License of this software
LCOV = lcov
GENHTML = genhtml
SUBDIRS = . gnulib/lib include/libvirt src tools docs gnulib/tests \
tests po examples
SUBDIRS = gnulib/lib include src daemon tools docs gnulib/tests \
python tests po examples/domain-events/events-c examples/hellolibvirt \
examples/dominfo examples/domsuspend examples/python examples/apparmor \
examples/xml/nwfilter examples/openauth examples/systemtap
XZ_OPT ?= -v -T0
export XZ_OPT
ACLOCAL_AMFLAGS = -I m4 -I gnulib/m4
ACLOCAL_AMFLAGS = -I m4
XML_EXAMPLES = \
$(patsubst $(srcdir)/%,%,$(wildcard $(addprefix $(srcdir)/examples/xml/, \
test/*.xml storage/*.xml)))
EXTRA_DIST = \
config-post.h \
ChangeLog-old \
libvirt.spec libvirt.spec.in \
mingw-libvirt.spec.in \
libvirt.pc.in \
libvirt-qemu.pc.in \
libvirt-lxc.pc.in \
libvirt-admin.pc.in \
autobuild.sh \
Makefile.nonreentrant \
autogen.sh \
cfg.mk \
examples/domain-events/events-python \
run.in \
README.md \
AUTHORS.in
AUTHORS.in \
$(XML_EXAMPLES)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libvirt.pc libvirt-qemu.pc libvirt-lxc.pc libvirt-admin.pc
pkgconfig_DATA = libvirt.pc
NEWS: \
$(srcdir)/docs/news.xml \
$(srcdir)/docs/news-ascii.xsl \
$(srcdir)/docs/reformat-news.py
$(AM_V_GEN) \
if [ -x $(XSLTPROC) ]; then \
$(XSLTPROC) --nonet \
$(srcdir)/docs/news-ascii.xsl \
$(srcdir)/docs/news.xml \
>$@-tmp \
|| { rm -f $@-tmp; exit 1; }; \
$(PYTHON) $(srcdir)/docs/reformat-news.py $@-tmp >$@ \
|| { rm -f $@-tmp; exit 1; }; \
rm -f $@-tmp; \
fi
EXTRA_DIST += \
$(srcdir)/docs/news.xml \
$(srcdir)/docs/news-ascii.xsl \
$(srcdir)/docs/reformat-news.py
NEWS: $(top_srcdir)/docs/news.xsl $(top_srcdir)/docs/news.html.in
$(AM_V_GEN)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
$(top_srcdir)/HACKING: $(top_srcdir)/docs/hacking1.xsl $(top_srcdir)/docs/hacking2.xsl \
$(top_srcdir)/docs/wrapstring.xsl $(top_srcdir)/docs/hacking.html.in
$(AM_V_GEN)if [ -x $(XSLTPROC) ] ; then \
$(XSLTPROC) --nonet $(top_srcdir)/docs/hacking1.xsl $(top_srcdir)/docs/hacking.html.in | \
$(XSLTPROC) --nonet $(top_srcdir)/docs/hacking2.xsl - \
| perl -0777 -pe 's/\n\n+$$/\n/' \
> $@-t && mv $@-t $@ ; fi;
rpm: clean
@(unset CDPATH ; $(MAKE) dist && rpmbuild -ta $(distdir).tar.xz)
srpm: clean
@(unset CDPATH ; $(MAKE) dist && rpmbuild -ts $(distdir).tar.xz)
@(unset CDPATH ; $(MAKE) dist && rpmbuild -ta $(distdir).tar.gz)
check-local: all tests
check-access:
@($(MAKE) $(AM_MAKEFLAGS) -C tests check-access)
tests:
@(cd docs/examples ; $(MAKE) MAKEFLAGS+=--silent tests)
@(if [ "$(pythondir)" != "" ] ; then cd python ; \
$(MAKE) MAKEFLAGS+=--silent tests ; fi)
cov: clean-cov
$(MKDIR_P) $(top_builddir)/coverage
mkdir $(top_builddir)/coverage
$(LCOV) -c -o $(top_builddir)/coverage/libvirt.info.tmp \
-d $(top_builddir)/src \
-d $(top_builddir)/src -d $(top_builddir)/daemon \
-d $(top_builddir)/tests
$(LCOV) -r $(top_builddir)/coverage/libvirt.info.tmp \
-o $(top_builddir)/coverage/libvirt.info
@ -93,6 +76,9 @@ clean-cov:
MAINTAINERCLEANFILES = .git-module-status
# disable this check
distuninstallcheck:
dist-hook: gen-ChangeLog gen-AUTHORS
# Generate the ChangeLog file (with all entries since the switch to git)
@ -100,26 +86,18 @@ dist-hook: gen-ChangeLog gen-AUTHORS
gen_start_date = 2009-07-04
.PHONY: gen-ChangeLog
gen-ChangeLog:
$(AM_V_GEN)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; \
$(AM_V_GEN)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
.PHONY: gen-AUTHORS
gen-AUTHORS:
$(AM_V_GEN)\
if test -d $(srcdir)/.git; then \
( \
cd $(srcdir) && \
git log --pretty=format:'%aN <%aE>' | sort -u \
) > all.list && \
sort -u $(srcdir)/AUTHORS.in > maint.list && \
comm -23 all.list maint.list > contrib.list && \
contrib="`cat contrib.list`" && \
perl -p -e "s/#contributorslist#// and print '$$contrib'" \
< $(srcdir)/AUTHORS.in > $(distdir)/AUTHORS-tmp && \
mv -f $(distdir)/AUTHORS-tmp $(distdir)/AUTHORS && \
rm -f all.list maint.list contrib.list; \
$(AM_V_GEN)if test -d $(srcdir)/.git; then \
out="`cd $(srcdir) && git log --pretty=format:'%aN <%aE>' | sort -u`" && \
perl -p -e "s/#authorslist#// and print '$$out'" \
< $(srcdir)/AUTHORS.in > $(distdir)/AUTHORS-tmp && \
mv -f $(distdir)/AUTHORS-tmp $(distdir)/AUTHORS ; \
fi

View File

@ -1,23 +1,8 @@
## Copyright (C) 2009-2010, 2013 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, see
## <http://www.gnu.org/licenses/>.
#
# Generated by running the following on Fedora 26:
# Generated by running the following on Fedora 9:
#
# nm -D --defined-only /lib64/libc.so.6 \
# nm -D --defined-only /lib/libc.so.6 \
# | grep '_r$' \
# | awk '{print $3}' \
# | grep -v __ \
@ -43,7 +28,6 @@ NON_REENTRANT += ether_ntoa
NON_REENTRANT += fcvt
NON_REENTRANT += fgetgrent
NON_REENTRANT += fgetpwent
NON_REENTRANT += fgetsgent
NON_REENTRANT += fgetspent
NON_REENTRANT += getaliasbyname
NON_REENTRANT += getaliasent
@ -73,8 +57,6 @@ NON_REENTRANT += getrpcent
NON_REENTRANT += getservbyname
NON_REENTRANT += getservbyport
NON_REENTRANT += getservent
NON_REENTRANT += getsgent
NON_REENTRANT += getsgnam
NON_REENTRANT += getspent
NON_REENTRANT += getspnam
NON_REENTRANT += getutent
@ -98,7 +80,6 @@ NON_REENTRANT += random
NON_REENTRANT += rand
NON_REENTRANT += seed48
NON_REENTRANT += setstate
NON_REENTRANT += sgetsgent
NON_REENTRANT += sgetspent
NON_REENTRANT += srand48
NON_REENTRANT += srandom
@ -117,11 +98,3 @@ NON_REENTRANT += inet_nsap_ntoa
NON_REENTRANT += inet_ntoa
NON_REENTRANT += inet_ntop
NON_REENTRANT += inet_pton
# Separate two nothings by space to get one space in a variable
space =
space +=
# The space needs to be in a variable otherwise it would be ignored.
# And there must be no spaces around the commas because they would
# not be ignored, logically.
NON_REENTRANT_RE=$(subst $(space),|,$(NON_REENTRANT))

1
README
View File

@ -1 +0,0 @@
README.md

13
README Normal file
View File

@ -0,0 +1,13 @@
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

@ -2,8 +2,7 @@
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 docs/hacking.html (after building libvirt using the information
included in this file) for more detailed contribution guidelines.
See also HACKING for more detailed libvirt contribution guidelines.
* Requirements
@ -16,7 +15,7 @@ Specific development tools and versions will be checked for and listed by
the bootstrap script.
Valgrind <http://valgrind.org/> is also highly recommended, if
Valgrind supports your architecture.
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.
@ -25,7 +24,7 @@ few prerequisites, later, a plain `git pull && make' should be sufficient.
You can get a copy of the source repository like this:
$ git clone https://libvirt.org/git/libvirt.git
$ git clone git://libvirt.org/libvirt
$ cd libvirt
As an optional step, if you already have a copy of the gnulib git

View File

@ -1,83 +0,0 @@
[![Build Status](https://travis-ci.org/libvirt/libvirt.svg)](https://travis-ci.org/libvirt/libvirt)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/355/badge)](https://bestpractices.coreinfrastructure.org/projects/355)
Libvirt API for virtualization
==============================
Libvirt provides a portable, long term stable C API for managing the
virtualization technologies provided by many operating systems. It
includes support for QEMU, KVM, Xen, LXC, bhyve, Virtuozzo, VMware
vCenter and ESX, VMware Desktop, Hyper-V, VirtualBox and the POWER
Hypervisor.
For some of these hypervisors, it provides a stateful management
daemon which runs on the virtualization host allowing access to the
API both by non-privileged local users and remote users.
Layered packages provide bindings of the libvirt C API into other
languages including Python, Perl, PHP, Go, Java, OCaml, as well as
mappings into object systems such as GObject, CIM and SNMP.
Further information about the libvirt project can be found on the
website:
[https://libvirt.org](https://libvirt.org)
License
-------
The libvirt C API is distributed under the terms of GNU Lesser General
Public License, version 2.1 (or later). Some parts of the code that are
not part of the C library may have the more restrictive GNU General
Public License, version 2.1 (or later). See the files `COPYING.LESSER`
and `COPYING` for full license terms & conditions.
Installation
------------
Libvirt uses the GNU Autotools build system, so in general can be built
and installed with the usual commands. For example, to build in a manner
that is suitable for installing as root, use:
```
$ ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
$ make
$ sudo make install
```
While to build & install as an unprivileged user
```
$ ./configure --prefix=$HOME/usr
$ make
$ make install
```
The libvirt code relies on a large number of 3rd party libraries. These will
be detected during execution of the `configure` script and a summary printed
which lists any missing (optional) dependencies.
Contributing
------------
The libvirt project welcomes contributions in many ways. For most components
the best way to contribute is to send patches to the primary development
mailing list. Further guidance on this can be found on the website:
[https://libvirt.org/contribute.html](https://libvirt.org/contribute.html)
Contact
-------
The libvirt project has two primary mailing lists:
* libvirt-users@redhat.com (**for user discussions**)
* libvir-list@redhat.com (**for development only**)
Further details on contacting the project are available on the website:
[https://libvirt.org/contact.html](https://libvirt.org/contact.html)

22
TODO Normal file
View File

@ -0,0 +1,22 @@
libvirt TODO list
=================
The TODO list changes frequently, so is maintained online
in the libvirt bugzilla
http://bugzilla.redhat.com/
Search against
Product: Virtualization Tools
Component: libvirt
Subject: RFE
Or browse dependent bugs under
https://bugzilla.redhat.com/show_bug.cgi?id=libvirtTodo
Summarized reports automatically generated from bugzilla
and provided online at
http://libvirt.org/todo.html

114
autobuild.sh Executable file
View File

@ -0,0 +1,114 @@
#!/bin/sh
set -e
set -v
# Make things clean.
test -n "$1" && RESULTS=$1 || RESULTS=results.log
: ${AUTOBUILD_INSTALL_ROOT=$HOME/builder}
test -f Makefile && make -k distclean || :
rm -rf coverage
rm -rf build
mkdir build
cd build
# Run with options not normally exercised by the rpm build, for
# more complete code coverage.
../autogen.sh --prefix="$AUTOBUILD_INSTALL_ROOT" \
--enable-test-coverage \
--disable-nls \
--enable-werror \
--enable-static
# 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 is a bashism; this use of exec is the POSIX alternative
exec 3>&1
st=$(
exec 4>&1 >&3
{ make check syntax-check 2>&1 3>&- 4>&-; echo $? >&4; } | tee "$RESULTS"
)
exec 3>&-
test "$st" = 0
test -x /usr/bin/lcov && make cov
rm -f *.tar.gz
make dist
if test -n "$AUTOBUILD_COUNTER" ; then
EXTRA_RELEASE=".auto$AUTOBUILD_COUNTER"
else
NOW=`date +"%s"`
EXTRA_RELEASE=".$USER$NOW"
fi
if test -f /usr/bin/rpmbuild ; then
rpmbuild --nodeps \
--define "extra_release $EXTRA_RELEASE" \
--define "_sourcedir `pwd`" \
-ba --clean libvirt.spec
fi
# Test mingw32 cross-compile
if test -x /usr/bin/i686-w64-mingw32-gcc ; then
make distclean
PKG_CONFIG_PATH="$AUTOBUILD_INSTALL_ROOT/i686-w64-mingw32/sys-root/mingw/lib/pkgconfig" \
CC="i686-w64-mingw32-gcc" \
../configure \
--build=$(uname -m)-w64-linux \
--host=i686-w64-mingw32 \
--prefix="$AUTOBUILD_INSTALL_ROOT/i686-w64-mingw32/sys-root/mingw" \
--enable-werror \
--without-libvirtd \
--without-python
make
make install
fi
# Test mingw64 cross-compile
if test -x /usr/bin/x86_64-w64-mingw32-gcc ; then
make distclean
PKG_CONFIG_PATH="$AUTOBUILD_INSTALL_ROOT/x86_64-w64-mingw32/sys-root/mingw/lib/pkgconfig" \
CC="x86_64-w64-mingw32-gcc" \
../configure \
--build=$(uname -m)-w64-linux \
--host=x86_64-w64-mingw32 \
--prefix="$AUTOBUILD_INSTALL_ROOT/x86_64-w64-mingw32/sys-root/mingw" \
--enable-werror \
--without-libvirtd \
--without-python
make
make install
fi
if test -x /usr/bin/i686-w64-mingw32-gcc && test -x /usr/bin/x86_64-w64-mingw32-gcc ; then
if test -f /usr/bin/rpmbuild ; then
rpmbuild --nodeps \
--define "extra_release $EXTRA_RELEASE" \
--define "_sourcedir `pwd`" \
-ba --clean mingw-libvirt.spec
fi
fi

View File

@ -1,208 +1,113 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
die()
{
echo "error: $1" >&2
set -e
srcdir=`dirname "$0"`
test -z "$srcdir" && srcdir=.
THEDIR=`pwd`
cd "$srcdir"
test -f src/libvirt.c || {
echo "You must run this script in the top-level libvirt directory"
exit 1
}
starting_point=$(pwd)
srcdir=$(dirname "$0")
test "$srcdir" || srcdir=.
cd "$srcdir" || {
die "Failed to cd into $srcdir"
}
test -f src/libvirt.c || {
die "$0 must live in the top-level libvirt directory"
}
dry_run=
EXTRA_ARGS=
no_git=
gnulib_srcdir=
extra_args=
while test "$#" -gt 0; do
case "$1" in
--dry-run)
# This variable will serve both as an indicator of the fact that
# a dry run has been requested, and to store the result of the
# dry run. It will be ultimately used as return code for the
# script: 0 means no action is necessary, 2 means that autogen.sh
# needs to be executed, and 1 is reserved for failures
dry_run=0
shift
;;
--no-git)
no_git=" $1"
shift
;;
--gnulib-srcdir=*)
gnulib_srcdir=" $1"
shift
;;
--gnulib-srcdir)
gnulib_srcdir=" $1=$2"
shift
shift
;;
--system)
prefix=/usr
sysconfdir=/etc
localstatedir=/var
if test -d $prefix/lib64; then
libdir=$prefix/lib64
else
libdir=$prefix/lib
fi
extra_args="--prefix=$prefix --localstatedir=$localstatedir"
extra_args="$extra_args --sysconfdir=$sysconfdir --libdir=$libdir"
shift
;;
*)
# All remaining arguments will be passed to configure verbatim
break
;;
esac
done
no_git="$no_git$gnulib_srcdir"
if test "x$1" = "x--no-git"; then
no_git=" $1"
shift
fi
if test -z "$NOCONFIGURE" ; then
if test "x$1" = "x--system"; then
shift
prefix=/usr
libdir=$prefix/lib
sysconfdir=/etc
localstatedir=/var
if [ -d /usr/lib64 ]; then
libdir=$prefix/lib64
fi
EXTRA_ARGS="--prefix=$prefix --sysconfdir=$sysconfdir --localstatedir=$localstatedir --libdir=$libdir"
echo "Running ./configure with $EXTRA_ARGS $@"
else
if test -z "$*" && test ! -f "$THEDIR/config.status"; 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
fi
gnulib_hash()
# Compute the hash we'll use to determine whether rerunning bootstrap
# is required. The first is just the SHA1 that selects a gnulib snapshot.
# The second ensures that whenever we change the set of gnulib modules used
# by this package, we rerun bootstrap to pull in the matching set of files.
# The third ensures that whenever we change the set of local gnulib diffs,
# we rerun bootstrap to pull in those diffs.
bootstrap_hash()
{
local no_git=$1
if test "$no_git"; then
echo "no-git"
echo no-git
return
fi
# Compute the hash we'll use to determine whether rerunning bootstrap
# is required. The first is just the SHA1 that selects a gnulib snapshot.
# The second ensures that whenever we change the set of gnulib modules used
# by this package, we rerun bootstrap to pull in the matching set of files.
# The third ensures that whenever we change the set of local gnulib diffs,
# we rerun bootstrap to pull in those diffs.
git submodule status .gnulib | awk '{ print $1 }'
git submodule status | sed 's/^[ +-]//;s/ .*//'
git hash-object bootstrap.conf
git ls-tree -d HEAD gnulib/local | awk '{ print $3 }'
git ls-tree -d HEAD gnulib/local | awk '{print $3}'
}
# Only look into git submodules if we're in a git checkout
if test -d .git || test -f .git; then
# Check for dirty submodules
if test -z "$CLEAN_SUBMODULE"; then
for path in $(git submodule status | awk '{ print $2 }'); do
case "$(git diff "$path")" in
*-dirty*)
echo "error: $path is dirty, please investigate" >&2
echo "set CLEAN_SUBMODULE to discard submodule changes" >&2
exit 1
;;
esac
done
# 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.
# Also, running 'make rpm' tends to litter the po/ directory, and some people
# like to run 'git clean -x -f po' to fix it; but only ./bootstrap regenerates
# the required file po/Makevars.
# Only run bootstrap from a git checkout, never from a tarball.
if test -d .git; then
curr_status=.git-module-status t=
if test "$no_git"; then
t=no-git
elif test -d .gnulib; then
t=$(bootstrap_hash; git diff .gnulib)
fi
if test "$CLEAN_SUBMODULE" && test -z "$no_git"; then
if test -z "$dry_run"; then
echo "Cleaning up submodules..."
git submodule foreach 'git clean -dfqx && git reset --hard' || {
die "Cleaning up submodules failed"
}
fi
fi
# Update all submodules. If any of the submodules has not been
# initialized yet, it will be initialized now; moreover, any submodule
# with uncommitted changes will be returned to the expected state
echo "Updating submodules..."
git submodule update --init || {
die "Updating submodules failed"
}
# The expected hash, eg. the one computed after the last
# successful bootstrap run, is stored on disk
state_file=.git-module-status
expected_hash=$(cat "$state_file" 2>/dev/null)
actual_hash=$(gnulib_hash "$no_git")
if test "$actual_hash" = "$expected_hash" && test -f AUTHORS; then
# The gnulib hash matches our expectations, and all the files
# that can only be generated through bootstrap are present:
# we just need to run autoreconf. Unless we're performing a
# dry run, of course...
if test -z "$dry_run"; then
echo "Running autoreconf..."
autoreconf -if || {
die "autoreconf failed"
}
fi
case $t:${CLEAN_SUBMODULE+set} in
*:set) ;;
*-dirty*)
echo "error: gnulib submodule is dirty, please investigate" 2>&1
echo "set env-var CLEAN_SUBMODULE to discard gnulib changes" 2>&1
exit 1 ;;
esac
# Keep this test in sync with cfg.mk:_update_required
if test "$t" = "$(cat $curr_status 2>/dev/null)" \
&& test -f "po/Makevars" && test -f AUTHORS; then
# good, it's up to date, all we need is autoreconf
autoreconf -if
else
# Whenever the gnulib submodule or any of the related bits
# has been changed in some way (see gnulib_hash) we need to
# run bootstrap again. If we're performing a dry run, we
# change the return code instead to signal our caller
if test "$dry_run"; then
dry_run=2
else
echo "Running bootstrap..."
./bootstrap$no_git --bootstrap-sync || {
die "bootstrap failed"
}
gnulib_hash >"$state_file"
if test -z "$no_git" && test ${CLEAN_SUBMODULE+set}; then
echo cleaning up submodules...
git submodule foreach 'git clean -dfqx && git reset --hard'
fi
echo running bootstrap$no_git...
./bootstrap$no_git --bootstrap-sync && bootstrap_hash > $curr_status \
|| { echo "Failed to bootstrap, please investigate."; exit 1; }
fi
fi
# When performing a dry run, we can stop here
test "$dry_run" && exit "$dry_run"
test -n "$NOCONFIGURE" && exit 0
# If asked not to run configure, we can stop here
test "$NOCONFIGURE" && exit 0
cd "$THEDIR"
cd "$starting_point" || {
die "Failed to cd into $starting_point"
}
if test "$OBJ_DIR"; then
mkdir -p "$OBJ_DIR" || {
die "Failed to create $OBJ_DIR"
}
cd "$OBJ_DIR" || {
die "Failed to cd into $OBJ_DIR"
}
if test "x$OBJ_DIR" != x; then
mkdir -p "$OBJ_DIR"
cd "$OBJ_DIR"
fi
# Make sure we can find GNU make and tell the user
# the right command to run
MAKE=
for cmd in make gmake; do
if $cmd -v 2>&1 | grep -q "GNU Make"; then
MAKE=$cmd
break
fi
done
test "$MAKE" || {
die "GNU make is required to build libvirt"
}
if test -z "$*" && test -z "$extra_args" && test -f config.status; then
echo "Running config.status..."
./config.status --recheck || {
die "config.status failed"
}
if test -z "$*" && test -z "$EXTRA_ARGS" && test -f config.status; then
./config.status --recheck
else
if test -z "$*" && test -z "$extra_args"; 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."
else
echo "Running configure with $extra_args $@"
fi
"$srcdir/configure" $extra_args "$@" || {
die "configure failed"
}
fi
echo
echo "Now type '$MAKE' to compile libvirt."
$srcdir/configure $EXTRA_ARGS "$@"
fi && {
echo
echo "Now type 'make' to compile libvirt."
}

428
bootstrap
View File

@ -1,10 +1,10 @@
#! /bin/sh
# Print a version string.
scriptversion=2019-01-04.17; # UTC
scriptversion=2013-07-03.20; # UTC
# Bootstrap this package from checked-out sources.
# Copyright (C) 2003-2019 Free Software Foundation, Inc.
# Copyright (C) 2003-2013 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
@ -17,7 +17,7 @@ scriptversion=2019-01-04.17; # UTC
# 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 <https://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Originally written by Paul Eggert. The canonical version of this
# script is maintained as build-aux/bootstrap in gnulib, however, to
@ -42,13 +42,8 @@ export LC_ALL
local_gl_dir=gl
# Honor $PERL, but work even if there is none.
PERL="${PERL-perl}"
me=$0
default_gnulib_url=git://git.sv.gnu.org/gnulib
usage() {
cat <<EOF
Usage: $me [OPTION]...
@ -78,37 +73,6 @@ contents are read as shell variables to configure the bootstrap.
For build prerequisites, environment variables like \$AUTOCONF and \$AMTAR
are honored.
Gnulib sources can be fetched in various ways:
* If this package is in a git repository with a 'gnulib' submodule
configured, then that submodule is initialized and updated and sources
are fetched from there. If \$GNULIB_SRCDIR is set (directly or via
--gnulib-srcdir) and is a git repository, then it is used as a reference.
* Otherwise, if \$GNULIB_SRCDIR is set (directly or via --gnulib-srcdir),
then sources are fetched from that local directory. If it is a git
repository and \$GNULIB_REVISION is set, then that revision is checked
out.
* Otherwise, if this package is in a git repository with a 'gnulib'
submodule configured, then that submodule is initialized and updated and
sources are fetched from there.
* Otherwise, if the 'gnulib' directory does not exist, Gnulib sources are
cloned into that directory using git from \$GNULIB_URL, defaulting to
$default_gnulib_url.
If \$GNULIB_REVISION is set, then that revision is checked out.
* Otherwise, the existing Gnulib sources in the 'gnulib' directory are
used. If it is a git repository and \$GNULIB_REVISION is set, then that
revision is checked out.
If you maintain a package and want to pin a particular revision of the
Gnulib sources that has been tested with your package, then there are two
possible approaches: either configure a 'gnulib' submodule with the
appropriate revision, or set \$GNULIB_REVISION (and if necessary
\$GNULIB_URL) in $me.conf.
Running without arguments will suffice in most cases.
EOF
}
@ -162,12 +126,19 @@ bootstrap_post_import_hook() { :; }
# Override it via your own definition in bootstrap.conf.
bootstrap_epilogue() { :; }
# The command to download all .po files for a specified domain into a
# specified directory. Fill in the first %s with the destination
# directory and the second with the domain name.
# The command to download all .po files for a specified domain into
# a specified directory. Fill in the first %s is the domain name, and
# the second with the destination directory. Use rsync's -L and -r
# options because the latest/%s directory and the .po files within are
# all symlinks.
po_download_command_format=\
"wget --mirror --level=1 -nd -q -A.po -P '%s' \
https://translationproject.org/latest/%s/"
"rsync --delete --exclude '*.s1' -Lrtvz \
'translationproject.org::tp/latest/%s/' '%s'"
# Fallback for downloading .po files (if rsync fails).
po_download_command_format2=\
"wget --mirror -nd -q -np -A.po -P '%s' \
http://translationproject.org/latest/%s/"
# Prefer a non-empty tarname (4th argument of AC_INIT if given), else
# fall back to the package name (1st argument with munging)
@ -196,15 +167,7 @@ source_base=lib
m4_base=m4
doc_base=doc
tests_base=tests
gnulib_extra_files="
build-aux/install-sh
build-aux/mdate-sh
build-aux/texinfo.tex
build-aux/depcomp
build-aux/config.guess
build-aux/config.sub
doc/INSTALL
"
gnulib_extra_files=''
# Additional gnulib-tool options to use. Use "\newline" to break lines.
gnulib_tool_option_extras=
@ -246,26 +209,12 @@ bootstrap_sync=false
# Use git to update gnulib sources
use_git=true
check_exists() {
if test "$1" = "--verbose"; then
($2 --version </dev/null) >/dev/null 2>&1
if test $? -ge 126; then
# If not found, run with diagnostics as one may be
# presented with env variables to set to find the right version
($2 --version </dev/null)
fi
else
($1 --version </dev/null) >/dev/null 2>&1
fi
test $? -lt 126
}
# find_tool ENVVAR NAMES...
# -------------------------
# Search for a required program. Use the value of ENVVAR, if set,
# otherwise find the first of the NAMES that can be run.
# If found, set ENVVAR to the program name, die otherwise.
# otherwise find the first of the NAMES that can be run (i.e.,
# supports --version). If found, set ENVVAR to the program name,
# die otherwise.
#
# FIXME: code duplication, see also gnu-web-doc-update.
find_tool ()
@ -275,21 +224,27 @@ find_tool ()
find_tool_names=$@
eval "find_tool_res=\$$find_tool_envvar"
if test x"$find_tool_res" = x; then
for i; do
if check_exists $i; then
find_tool_res=$i
break
for i
do
if ($i --version </dev/null) >/dev/null 2>&1; then
find_tool_res=$i
break
fi
done
else
find_tool_error_prefix="\$$find_tool_envvar: "
fi
if test x"$find_tool_res" = x; then
warn_ "one of these is required: $find_tool_names;"
die "alternatively set $find_tool_envvar to a compatible tool"
fi
test x"$find_tool_res" != x \
|| die "one of these is required: $find_tool_names"
($find_tool_res --version </dev/null) >/dev/null 2>&1 \
|| die "${find_tool_error_prefix}cannot run $find_tool_res --version"
eval "$find_tool_envvar=\$find_tool_res"
eval "export $find_tool_envvar"
}
# Find sha1sum, named gsha1sum on MacPorts, and shasum on Mac OS X 10.6.
find_tool SHA1SUM sha1sum gsha1sum shasum
# Override the default configuration, if necessary.
# Make sure that bootstrap.conf is sourced from the current directory
# if we were invoked as "sh bootstrap".
@ -298,18 +253,24 @@ case "$0" in
*) test -r "$0.conf" && . ./"$0.conf" ;;
esac
# Extra files from gnulib, which override files from other sources.
test -z "${gnulib_extra_files}" && \
gnulib_extra_files="
build-aux/install-sh
build-aux/mdate-sh
build-aux/texinfo.tex
build-aux/depcomp
build-aux/config.guess
build-aux/config.sub
doc/INSTALL
"
if test "$vc_ignore" = auto; then
vc_ignore=
test -d .git && vc_ignore=.gitignore
test -d CVS && vc_ignore="$vc_ignore .cvsignore"
fi
if test x"$gnulib_modules$gnulib_files$gnulib_extra_files" = x; then
use_gnulib=false
else
use_gnulib=true
fi
# Translate configuration into internal form.
# Parse options.
@ -365,7 +326,7 @@ insert_if_absent() {
die "Error: Duplicate entries in $file: " $duplicate_entries
fi
linesold=$(gitignore_entries $file | wc -l)
linesnew=$( { echo "$str"; cat $file; } | gitignore_entries | sort -u | wc -l)
linesnew=$(echo "$str" | gitignore_entries - $file | sort -u | wc -l)
if [ $linesold != $linesnew ] ; then
{ echo "$str" | cat - $file > $file.bak && mv $file.bak $file; } \
|| die "insert_if_absent $file $str: failed"
@ -446,30 +407,28 @@ sort_ver() { # sort -V is not generally available
done
}
get_version_sed='
# Move version to start of line.
s/.*[v ]\([0-9]\)/\1/
# Skip lines that do not start with version.
/^[0-9]/!d
# Remove characters after the version.
s/[^.a-z0-9-].*//
# The first component must be digits only.
s/^\([0-9]*\)[a-z-].*/\1/
#the following essentially does s/5.005/5.5/
s/\.0*\([1-9]\)/.\1/g
p
q'
get_version() {
app=$1
$app --version >/dev/null 2>&1 || { $app --version; return 1; }
$app --version >/dev/null 2>&1 || return 1
$app --version 2>&1 | sed -n "$get_version_sed"
$app --version 2>&1 |
sed -n '# Move version to start of line.
s/.*[v ]\([0-9]\)/\1/
# Skip lines that do not start with version.
/^[0-9]/!d
# Remove characters after the version.
s/[^.a-z0-9-].*//
# The first component must be digits only.
s/^\([0-9]*\)[a-z-].*/\1/
#the following essentially does s/5.005/5.5/
s/\.0*\([1-9]\)/.\1/g
p
q'
}
check_versions() {
@ -489,7 +448,6 @@ check_versions() {
test "$appvar" = TAR && appvar=AMTAR
case $appvar in
GZIP) ;; # Do not use $GZIP: it contains gzip options.
PERL::*) ;; # Keep perl modules as-is
*) eval "app=\${$appvar-$app}" ;;
esac
@ -507,22 +465,12 @@ check_versions() {
ret=1
continue
} ;;
# Another check is for perl modules. These can be written as
# e.g. perl::XML::XPath in case of XML::XPath module, etc.
perl::*)
# Extract module name
app="${app#perl::}"
if ! $PERL -m"$app" -e 'exit 0' >/dev/null 2>&1; then
warn_ "Error: perl module '$app' not found"
ret=1
fi
continue
;;
esac
if [ "$req_ver" = "-" ]; then
# Merely require app to exist; not all prereq apps are well-behaved
# so we have to rely on $? rather than get_version.
if ! check_exists --verbose $app; then
$app --version >/dev/null 2>&1
if [ 126 -le $? ]; then
warn_ "Error: '$app' not found"
ret=1
fi
@ -555,12 +503,6 @@ print_versions() {
# can't depend on column -t
}
# Find sha1sum, named gsha1sum on MacPorts, shasum on Mac OS X 10.6.
# Also find the compatible sha1 utility on the BSDs
if test x"$SKIP_PO" = x; then
find_tool SHA1SUM sha1sum gsha1sum shasum sha1
fi
use_libtool=0
# We'd like to use grep -E, to see if any of LT_INIT,
# AC_PROG_LIBTOOL, AM_PROG_LIBTOOL is used in configure.ac,
@ -606,21 +548,13 @@ if ! printf "$buildreq" | check_versions; then
fi
fi
# Warn the user if autom4te appears to be broken; this causes known
# issues with at least gettext 0.18.3.
probe=$(echo 'm4_quote([hi])' | autom4te -l M4sugar -t 'm4_quote:$%' -)
if test "x$probe" != xhi; then
warn_ "WARNING: your autom4te wrapper eats stdin;"
warn_ "if bootstrap fails, consider upgrading your autotools"
fi
echo "$0: Bootstrapping from checked-out $package sources..."
# See if we can use gnulib's git-merge-changelog merge driver.
if $use_git && test -d .git && check_exists git; then
if $use_git && test -d .git && (git --version) >/dev/null 2>/dev/null ; then
if git config merge.merge-changelog.driver >/dev/null ; then
:
elif check_exists git-merge-changelog; then
elif (git-merge-changelog --version) >/dev/null 2>/dev/null ; then
echo "$0: initializing git-merge-changelog driver"
git config merge.merge-changelog.name 'GNU-style ChangeLog merge driver'
git config merge.merge-changelog.driver 'git-merge-changelog %O %A %B'
@ -640,101 +574,94 @@ git_modules_config () {
test -f .gitmodules && git config --file .gitmodules "$@"
}
if $use_gnulib; then
if $use_git; then
gnulib_path=$(git_modules_config submodule.gnulib.path)
test -z "$gnulib_path" && gnulib_path=gnulib
if $use_git; then
gnulib_path=$(git_modules_config submodule.gnulib.path)
test -z "$gnulib_path" && gnulib_path=gnulib
fi
# Get gnulib files. Populate $GNULIB_SRCDIR, possibly updating a
# submodule, for use in the rest of the script.
case ${GNULIB_SRCDIR--} in
-)
# Note that $use_git is necessarily true in this case.
if git_modules_config submodule.gnulib.url >/dev/null; then
echo "$0: getting gnulib files..."
git submodule init || exit $?
git submodule update || exit $?
elif [ ! -d "$gnulib_path" ]; then
echo "$0: getting gnulib files..."
trap cleanup_gnulib 1 2 13 15
shallow=
git clone -h 2>&1 | grep -- --depth > /dev/null && shallow='--depth 2'
git clone $shallow git://git.sv.gnu.org/gnulib "$gnulib_path" ||
cleanup_gnulib
trap - 1 2 13 15
fi
# Get gnulib files. Populate $GNULIB_SRCDIR, possibly updating a
# submodule, for use in the rest of the script.
case ${GNULIB_SRCDIR--} in
-)
# Note that $use_git is necessarily true in this case.
if git_modules_config submodule.gnulib.url >/dev/null; then
echo "$0: getting gnulib files..."
git submodule init -- "$gnulib_path" || exit $?
git submodule update -- "$gnulib_path" || exit $?
elif [ ! -d "$gnulib_path" ]; then
echo "$0: getting gnulib files..."
trap cleanup_gnulib 1 2 13 15
shallow=
if test -z "$GNULIB_REVISION"; then
git clone -h 2>&1 | grep -- --depth > /dev/null && shallow='--depth 2'
GNULIB_SRCDIR=$gnulib_path
;;
*)
# Use GNULIB_SRCDIR directly or as a reference.
if $use_git && test -d "$GNULIB_SRCDIR"/.git && \
git_modules_config submodule.gnulib.url >/dev/null; then
echo "$0: getting gnulib files..."
if git submodule -h|grep -- --reference > /dev/null; then
# Prefer the one-liner available in git 1.6.4 or newer.
git submodule update --init --reference "$GNULIB_SRCDIR" \
"$gnulib_path" || exit $?
else
# This fallback allows at least git 1.5.5.
if test -f "$gnulib_path"/gnulib-tool; then
# Since file already exists, assume submodule init already complete.
git submodule update || exit $?
else
# Older git can't clone into an empty directory.
rmdir "$gnulib_path" 2>/dev/null
git clone --reference "$GNULIB_SRCDIR" \
"$(git_modules_config submodule.gnulib.url)" "$gnulib_path" \
&& git submodule init && git submodule update \
|| exit $?
fi
git clone $shallow ${GNULIB_URL:-$default_gnulib_url} "$gnulib_path" \
|| cleanup_gnulib
trap - 1 2 13 15
fi
GNULIB_SRCDIR=$gnulib_path
;;
*)
# Use GNULIB_SRCDIR directly or as a reference.
if $use_git && test -d "$GNULIB_SRCDIR"/.git && \
git_modules_config submodule.gnulib.url >/dev/null; then
echo "$0: getting gnulib files..."
if git submodule -h|grep -- --reference > /dev/null; then
# Prefer the one-liner available in git 1.6.4 or newer.
git submodule update --init --reference "$GNULIB_SRCDIR" \
"$gnulib_path" || exit $?
else
# This fallback allows at least git 1.5.5.
if test -f "$gnulib_path"/gnulib-tool; then
# Since file already exists, assume submodule init already complete.
git submodule update -- "$gnulib_path" || exit $?
else
# Older git can't clone into an empty directory.
rmdir "$gnulib_path" 2>/dev/null
git clone --reference "$GNULIB_SRCDIR" \
"$(git_modules_config submodule.gnulib.url)" "$gnulib_path" \
&& git submodule init -- "$gnulib_path" \
&& git submodule update -- "$gnulib_path" \
|| exit $?
fi
fi
GNULIB_SRCDIR=$gnulib_path
fi
;;
esac
if test -d "$GNULIB_SRCDIR"/.git && test -n "$GNULIB_REVISION" \
&& ! git_modules_config submodule.gnulib.url >/dev/null; then
(cd "$GNULIB_SRCDIR" && git checkout "$GNULIB_REVISION") || cleanup_gnulib
fi
;;
esac
# $GNULIB_SRCDIR now points to the version of gnulib to use, and
# we no longer need to use git or $gnulib_path below here.
# $GNULIB_SRCDIR now points to the version of gnulib to use, and
# we no longer need to use git or $gnulib_path below here.
if $bootstrap_sync; then
cmp -s "$0" "$GNULIB_SRCDIR/build-aux/bootstrap" || {
echo "$0: updating bootstrap and restarting..."
case $(sh -c 'echo "$1"' -- a) in
a) ignored=--;;
*) ignored=ignored;;
esac
exec sh -c \
'cp "$1" "$2" && shift && exec "${CONFIG_SHELL-/bin/sh}" "$@"' \
$ignored "$GNULIB_SRCDIR/build-aux/bootstrap" \
"$0" "$@" --no-bootstrap-sync
}
fi
gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
<$gnulib_tool || exit $?
if $bootstrap_sync; then
cmp -s "$0" "$GNULIB_SRCDIR/build-aux/bootstrap" || {
echo "$0: updating bootstrap and restarting..."
case $(sh -c 'echo "$1"' -- a) in
a) ignored=--;;
*) ignored=ignored;;
esac
exec sh -c \
'cp "$1" "$2" && shift && exec "${CONFIG_SHELL-/bin/sh}" "$@"' \
$ignored "$GNULIB_SRCDIR/build-aux/bootstrap" \
"$0" "$@" --no-bootstrap-sync
}
fi
gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
<$gnulib_tool || exit $?
# Get translations.
download_po_files() {
subdir=$1
domain=$2
echo "$me: getting translations into $subdir for $domain..."
cmd=$(printf "$po_download_command_format" "$subdir" "$domain")
cmd=$(printf "$po_download_command_format" "$domain" "$subdir")
eval "$cmd" && return
# Fallback to HTTP.
cmd=$(printf "$po_download_command_format2" "$subdir" "$domain")
eval "$cmd"
}
@ -765,10 +692,11 @@ update_po_files() {
cksum_file="$ref_po_dir/$po.s1"
if ! test -f "$cksum_file" ||
! test -f "$po_dir/$po.po" ||
! $SHA1SUM -c "$cksum_file" < "$new_po" > /dev/null 2>&1; then
! $SHA1SUM -c --status "$cksum_file" \
< "$new_po" > /dev/null; then
echo "$me: updated $po_dir/$po.po..."
cp "$new_po" "$po_dir/$po.po" \
&& $SHA1SUM < "$new_po" > "$cksum_file" || return
&& $SHA1SUM < "$new_po" > "$cksum_file"
fi
done
}
@ -824,9 +752,9 @@ symlink_to_dir()
# Leave any existing symlink alone, if it already points to the source,
# so that broken build tools that care about symlink times
# aren't confused into doing unnecessary builds. Conversely, if the
# existing symlink's timestamp is older than the source, make it afresh,
# existing symlink's time stamp is older than the source, make it afresh,
# so that broken tools aren't confused into skipping needed builds. See
# <https://lists.gnu.org/r/bug-gnulib/2011-05/msg00326.html>.
# <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00326.html>.
test -h "$dst" &&
src_ls=$(ls -diL "$src" 2>/dev/null) && set $src_ls && src_i=$1 &&
dst_ls=$(ls -diL "$dst" 2>/dev/null) && set $dst_ls && dst_i=$1 &&
@ -932,47 +860,35 @@ fi
# Import from gnulib.
if $use_gnulib; then
gnulib_tool_options="\
--no-changelog\
--aux-dir=$build_aux\
--doc-base=$doc_base\
--lib=$gnulib_name\
--m4-base=$m4_base/\
--source-base=$source_base/\
--tests-base=$tests_base\
--local-dir=$local_gl_dir\
$gnulib_tool_option_extras\
"
if test $use_libtool = 1; then
case "$gnulib_tool_options " in
*' --libtool '*) ;;
*) gnulib_tool_options="$gnulib_tool_options --libtool" ;;
esac
fi
echo "$0: $gnulib_tool $gnulib_tool_options --import ..."
$gnulib_tool $gnulib_tool_options --import $gnulib_modules \
|| die "gnulib-tool failed"
for file in $gnulib_files; do
symlink_to_dir "$GNULIB_SRCDIR" $file \
|| die "failed to symlink $file"
done
gnulib_tool_options="\
--import\
--no-changelog\
--aux-dir $build_aux\
--doc-base $doc_base\
--lib $gnulib_name\
--m4-base $m4_base/\
--source-base $source_base/\
--tests-base $tests_base\
--local-dir $local_gl_dir\
$gnulib_tool_option_extras\
"
if test $use_libtool = 1; then
case "$gnulib_tool_options " in
*' --libtool '*) ;;
*) gnulib_tool_options="$gnulib_tool_options --libtool" ;;
esac
fi
echo "$0: $gnulib_tool $gnulib_tool_options --import ..."
$gnulib_tool $gnulib_tool_options --import $gnulib_modules &&
for file in $gnulib_files; do
symlink_to_dir "$GNULIB_SRCDIR" $file \
|| die "failed to symlink $file"
done
bootstrap_post_import_hook \
|| die "bootstrap_post_import_hook failed"
# Don't proceed if there are uninitialized submodules. In particular,
# the next step will remove dangling links, which might be links into
# uninitialized submodules.
#
# Uninitialized submodules are listed with an initial dash.
if $use_git && git submodule | grep '^-' >/dev/null; then
die "some git submodules are not initialized. " \
"Run 'git submodule init' and bootstrap again."
fi
# Remove any dangling symlink matching "*.m4" or "*.[ch]" in some
# gnulib-populated directories. Such .m4 files would cause aclocal to fail.
# The following requires GNU find 4.2.3 or newer. Considering the usual
@ -1065,9 +981,9 @@ bootstrap_epilogue
echo "$0: done. Now you can run './configure'."
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@ -1,6 +1,6 @@
# Bootstrap configuration.
# Copyright (C) 2010-2014 Red Hat, Inc.
# Copyright (C) 2010-2013 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
@ -35,8 +35,9 @@ clock-time
close
connect
configmake
count-leading-zeros
count-one-bits
crypto/md5
crypto/sha256
dirname-lgpl
environ
execinfo
@ -52,10 +53,10 @@ func
getaddrinfo
getcwd-lgpl
gethostname
getopt-posix
getpass
getpeername
getsockname
gettext-h
gettimeofday
gitlog-to-changelog
gnumakefile
@ -70,8 +71,6 @@ listen
localeconv
maintainer-makefile
manywarnings
mgetgroups
mkdtemp
mkostemp
mkostemps
mktempd
@ -90,8 +89,8 @@ pthread
pthread_sigmask
recv
regex
random_r
sched
secure_getenv
send
setenv
setsockopt
@ -117,7 +116,6 @@ time_r
timegm
ttyname_r
uname
unsetenv
useless-if-before-free
usleep
vasprintf
@ -126,9 +124,18 @@ vc-list-files
vsnprintf
waitpid
warnings
wcwidth
'
# Additional xgettext options to use. Use "\\\newline" to break lines.
XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
--flag=virAsprintf:2:c-format\\\
--from-code=UTF-8\\\
'
# This is not a GNU package, so the default bug address is invalid,
# and the translation project is not in use.
MSGID_BUGS_ADDRESS=libvir-list@redhat.com
COPYRIGHT_HOLDER='Red Hat, Inc.'
SKIP_PO=true
# Enable copy-mode for MSYS/MinGW. MSYS' ln doesn't work well in the way
@ -137,15 +144,40 @@ if test -n "$MSYSTEM"; then
copy=true
fi
# If "AM_GNU_GETTEXT(external" or "AM_GNU_GETTEXT([external]"
# appears in configure.ac, exclude some unnecessary files.
# Without grep's -E option (not portable enough, pre-configure),
# the following test is ugly. Also, this depends on the existence
# of configure.ac, not the obsolescent-named configure.in. But if
# you're using this infrastructure, you should care about such things.
gettext_external=0
grep '^[ ]*AM_GNU_GETTEXT(external\>' configure.ac > /dev/null &&
gettext_external=1
grep '^[ ]*AM_GNU_GETTEXT(\[external\]' configure.ac > /dev/null &&
gettext_external=1
if test $gettext_external = 1; then
# Gettext supplies these files, but we don't need them since
# we don't have an intl subdirectory.
excluded_files='
m4/glibc2.m4
m4/intdiv0.m4
m4/lcmessage.m4
m4/uintmax_t.m4
m4/ulonglong.m4
m4/visibility.m4
'
fi
# Tell gnulib to:
# require LGPLv2+
# apply any local diffs in gnulib/local/ dir
# put *.m4 files in m4/ dir
# put *.m4 files in new gnulib/m4/ dir
# put *.[ch] files in new gnulib/lib/ dir
# import gnulib tests in new gnulib/tests/ dir
gnulib_name=libgnu
m4_base=m4
m4_base=gnulib/m4
source_base=gnulib/lib
tests_base=gnulib/tests
gnulib_tool_option_extras="\
@ -157,24 +189,42 @@ gnulib_tool_option_extras="\
"
local_gl_dir=gnulib/local
# Convince bootstrap to use multiple m4 directories.
: ${ACLOCAL=aclocal}
ACLOCAL="$ACLOCAL -I m4"
export ACLOCAL
# Build prerequisites
# Note that some of these programs are only required for 'make dist' to
# succeed from a fresh git checkout; not all of these programs are
# required to run 'make dist' on a tarball.
# required to run 'make dist' on a tarball. As a special case, we want
# to require the equivalent of the Fedora python-devel package, but
# RHEL 5 lacks the witness python-config package; we hack around that
# old environment below.
buildreq="\
autoconf 2.59
automake 1.9.6
autopoint -
gettext 0.17
git 1.5.5
gzip -
libtool -
patch -
perl 5.5
pkg-config -
python-config -
rpcgen -
tar -
xmllint -
xsltproc -
"
# Use rpm as a fallback to bypass the bootstrap probe for python-config,
# for the sake of RHEL 5; without requiring it on newer systems that
# have python-config to begin with.
if `(${PYTHON_CONFIG-python-config} --version;
test $? -lt 126 || rpm -q python-devel) >/dev/null 2>&1`; then
PYTHON_CONFIG=true
fi
# Automake requires that ChangeLog and AUTHORS exist.
touch AUTHORS ChangeLog || exit 1
@ -189,11 +239,12 @@ gnulib_extra_files="
"
bootstrap_post_import_hook()
bootstrap_epilogue()
{
# Change paths in gnulib/tests/gnulib.mk from "../../.." to "../..",
# and make tests conditional by changing "TESTS" to "GNULIB_TESTS".
# then ensure that gnulib/tests/Makefile.in is up-to-date.
m=gnulib/tests/gnulib.mk
sed 's,\.\./\.\./\.\.,../..,g; s/^TESTS /GNULIB_TESTS /' $m > $m-t
sed 's,\.\./\.\./\.\.,../..,g' $m > $m-t
mv -f $m-t $m
${AUTOMAKE-automake} gnulib/tests/Makefile
}

View File

@ -1,4 +1,4 @@
#!/usr/bin/env perl
#!/usr/bin/perl
#
# augeas-gentest.pl: Generate an augeas test file, from an
# example config file + test file template
@ -16,6 +16,9 @@
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see
# <http://www.gnu.org/licenses/>.
#
# Authors:
# Daniel P. Berrange <berrange@redhat.com>
use strict;
use warnings;

116
build-aux/bracket-spacing.pl Executable file
View File

@ -0,0 +1,116 @@
#!/usr/bin/perl
#
# bracket-spacing.pl: Report any usage of 'function (..args..)'
#
# 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, see
# <http://www.gnu.org/licenses/>.
#
# Authors:
# Daniel P. Berrange <berrange@redhat.com>
use strict;
use warnings;
my $ret = 0;
my $incomment = 0;
foreach my $file (@ARGV) {
open FILE, $file;
while (defined (my $line = <FILE>)) {
my $data = $line;
# Kill any quoted strongs
$data =~ s,".*?","XXX",g;
# Kill any C++ style comments
$data =~ s,//.*$,//,;
next if $data =~ /^#/;
# Kill contents of multi-line comments
# and detect end of multi-line comments
if ($incomment) {
if ($data =~ m,\*/,) {
$incomment = 0;
$data =~ s,^.*\*/,*/,;
} else {
$data = "";
}
}
# Kill single line comments, and detect
# start of multi-line comments
if ($data =~ m,/\*.*\*/,) {
$data =~ s,/\*.*\*/,/* */,;
} elsif ($data =~ m,/\*,) {
$incomment = 1;
$data =~ s,/\*.*,/*,;
}
# We need to match things like
#
# int foo (int bar, bool wizz);
# foo (bar, wizz);
#
# but not match things like:
#
# typedef int (*foo)(bar wizz)
#
# we can't do this (efficiently) without
# missing things like
#
# foo (*bar, wizz);
#
while ($data =~ /(\w+)\s\((?!\*)/) {
my $kw = $1;
# Allow space after keywords only
if ($kw =~ /^(if|for|while|switch|return)$/) {
$data =~ s/($kw\s\()/XXX(/;
} else {
print "$file:$.: $line";
$ret = 1;
last;
}
}
# Require whitespace immediately after keywords,
# but none after the opening bracket
while ($data =~ /(if|for|while|switch|return)\(/ ||
$data =~ /(if|for|while|switch|return)\s+\(\s/) {
print "$file:$.: $line";
$ret = 1;
last;
}
# Forbid whitespace between )( of a function typedef
while ($data =~ /\(\*\w+\)\s+\(/) {
print "$file:$.: $line";
$ret = 1;
last;
}
# Forbid whitespace following ( or prior to )
while ($data =~ /\S\s+\)/ ||
$data =~ /\(\s+\S/) {
print "$file:$.: $line";
$ret = 1;
last;
}
}
close FILE;
}
exit $ret;

View File

@ -1,198 +0,0 @@
#!/usr/bin/env perl
#
# check-spacing.pl: Report any usage of 'function (..args..)'
# Also check for other syntax issues, such as correct use of ';'
#
# 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, see
# <http://www.gnu.org/licenses/>.
use strict;
use warnings;
my $ret = 0;
my $incomment = 0;
foreach my $file (@ARGV) {
# Per-file variables for multiline Curly Bracket (cb_) check
my $cb_linenum = 0;
my $cb_code = "";
my $cb_scolon = 0;
open FILE, $file;
while (defined (my $line = <FILE>)) {
my $data = $line;
# For temporary modifications
my $tmpdata;
# Kill any quoted , ; = or "
$data =~ s/'[";,=]'/'X'/g;
# Kill any quoted strings
$data =~ s,"(?:[^\\\"]|\\.)*","XXX",g;
next if $data =~ /^#/;
# Kill contents of multi-line comments
# and detect end of multi-line comments
if ($incomment) {
if ($data =~ m,\*/,) {
$incomment = 0;
$data =~ s,^.*\*/,*/,;
} else {
$data = "";
}
}
# Kill single line comments, and detect
# start of multi-line comments
if ($data =~ m,/\*.*\*/,) {
$data =~ s,/\*.*\*/,/* */,;
} elsif ($data =~ m,/\*,) {
$incomment = 1;
$data =~ s,/\*.*,/*,;
}
# We need to match things like
#
# int foo (int bar, bool wizz);
# foo (bar, wizz);
#
# but not match things like:
#
# typedef int (*foo)(bar wizz)
#
# we can't do this (efficiently) without
# missing things like
#
# foo (*bar, wizz);
#
# We also don't want to spoil the $data so it can be used
# later on.
$tmpdata = $data;
while ($tmpdata =~ /(\w+)\s\((?!\*)/) {
my $kw = $1;
# Allow space after keywords only
if ($kw =~ /^(?:if|for|while|switch|return)$/) {
$tmpdata =~ s/(?:$kw\s\()/XXX(/;
} else {
print "Whitespace after non-keyword:\n";
print "$file:$.: $line";
$ret = 1;
last;
}
}
# Require whitespace immediately after keywords
if ($data =~ /\b(?:if|for|while|switch|return)\(/) {
print "No whitespace after keyword:\n";
print "$file:$.: $line";
$ret = 1;
}
# Forbid whitespace between )( of a function typedef
if ($data =~ /\(\*\w+\)\s+\(/) {
print "Whitespace between ')' and '(':\n";
print "$file:$.: $line";
$ret = 1;
}
# Forbid whitespace following ( or prior to )
# but allow whitespace before ) on a single line
# (optionally followed by a semicolon)
if (($data =~ /\s\)/ && not $data =~ /^\s+\);?$/) ||
$data =~ /\((?!$)\s/) {
print "Whitespace after '(' or before ')':\n";
print "$file:$.: $line";
$ret = 1;
}
# Forbid whitespace before ";" or ",". Things like below are allowed:
#
# 1) The expression is empty for "for" loop. E.g.
# for (i = 0; ; i++)
#
# 2) An empty statement. E.g.
# while (write(statuswrite, &status, 1) == -1 &&
# errno == EINTR)
# ;
#
if ($data =~ /\s[;,]/) {
unless ($data =~ /\S; ; / ||
$data =~ /^\s+;/) {
print "Whitespace before semicolon or comma:\n";
print "$file:$.: $line";
$ret = 1;
}
}
# Require EOL, macro line continuation, or whitespace after ";".
# Allow "for (;;)" as an exception.
if ($data =~ /;[^ \\\n;)]/) {
print "Invalid character after semicolon:\n";
print "$file:$.: $line";
$ret = 1;
}
# Require EOL, space, or enum/struct end after comma.
if ($data =~ /,[^ \\\n)}]/) {
print "Invalid character after comma:\n";
print "$file:$.: $line";
$ret = 1;
}
# Require spaces around assignment '=', compounds and '=='
if ($data =~ /[^ ]\b[!<>&|\-+*\/%\^=]?=/ ||
$data =~ /=[^= \\\n]/) {
print "Spacing around '=' or '==':\n";
print "$file:$.: $line";
$ret = 1;
}
# One line conditional statements with one line bodies should
# not use curly brackets.
if ($data =~ /^\s*(if|while|for)\b.*\{$/) {
$cb_linenum = $.;
$cb_code = $line;
$cb_scolon = 0;
}
# We need to check for exactly one semicolon inside the body,
# because empty statements (e.g. with comment only) are
# allowed
if ($cb_linenum == $. - 1 && $data =~ /^[^;]*;[^;]*$/) {
$cb_code .= $line;
$cb_scolon = 1;
}
if ($data =~ /^\s*}\s*$/ &&
$cb_linenum == $. - 2 &&
$cb_scolon) {
print "Curly brackets around single-line body:\n";
print "$file:$cb_linenum-$.:\n$cb_code$line";
$ret = 1;
# There _should_ be no need to reset the values; but to
# keep my inner peace...
$cb_linenum = 0;
$cb_scolon = 0;
$cb_code = "";
}
}
close FILE;
}
exit $ret;

View File

@ -1,156 +0,0 @@
#!/usr/bin/perl
#
# Validate that header files follow a standard layout:
#
# /*
# ...copyright header...
# */
# <one blank line>
# #ifndef SYMBOL
# # define SYMBOL
# ....content....
# #endif /* SYMBOL */
#
# For any file ending priv.h, before the #ifndef
# We will have a further section
#
# #ifndef SYMBOL_ALLOW
# # error ....
# #endif /* SYMBOL_ALLOW */
# <one blank line>
use strict;
use warnings;
my $STATE_COPYRIGHT_COMMENT = 0;
my $STATE_COPYRIGHT_BLANK = 1;
my $STATE_PRIV_START = 2;
my $STATE_PRIV_ERROR = 3;
my $STATE_PRIV_END = 4;
my $STATE_PRIV_BLANK = 5;
my $STATE_GUARD_START = 6;
my $STATE_GUARD_DEFINE = 7;
my $STATE_GUARD_END = 8;
my $STATE_EOF = 9;
my $file = " ";
my $ret = 0;
my $ifdef = "";
my $ifdefpriv = "";
my $state = $STATE_EOF;
my $mistake = 0;
sub mistake {
my $msg = shift;
warn $msg;
$mistake = 1;
$ret = 1;
}
while (<>) {
if (not $file eq $ARGV) {
if ($state == $STATE_COPYRIGHT_COMMENT) {
&mistake("$file: missing copyright comment");
} elsif ($state == $STATE_COPYRIGHT_BLANK) {
&mistake("$file: missing blank line after copyright header");
} elsif ($state == $STATE_PRIV_START) {
&mistake("$file: missing '#ifndef $ifdefpriv'");
} elsif ($state == $STATE_PRIV_ERROR) {
&mistake("$file: missing '# error ...priv allow...'");
} elsif ($state == $STATE_PRIV_END) {
&mistake("$file: missing '#endif /* $ifdefpriv */'");
} elsif ($state == $STATE_PRIV_BLANK) {
&mistake("$file: missing blank line after priv header check");
} elsif ($state == $STATE_GUARD_START) {
&mistake("$file: missing '#ifndef $ifdef'");
} elsif ($state == $STATE_GUARD_DEFINE) {
&mistake("$file: missing '# define $ifdef'");
} elsif ($state == $STATE_GUARD_END) {
&mistake("$file: missing '#endif /* $ifdef */'");
}
$ifdef = uc $ARGV;
$ifdef =~ s,.*/,,;
$ifdef =~ s,[^A-Z0-9],_,g;
$ifdef =~ s,__+,_,g;
unless ($ifdef =~ /^LIBVIRT_/ && $ARGV !~ /libvirt_internal.h/) {
$ifdef = "LIBVIRT_" . $ifdef;
}
$ifdefpriv = $ifdef . "_ALLOW";
$file = $ARGV;
$state = $STATE_COPYRIGHT_COMMENT;
$mistake = 0;
}
if ($mistake ||
$ARGV =~ /config-post\.h$/ ||
$ARGV =~ /vbox_(CAPI|XPCOM)/) {
$state = $STATE_EOF;
next;
}
if ($state == $STATE_COPYRIGHT_COMMENT) {
if (m,\*/,) {
$state = $STATE_COPYRIGHT_BLANK;
}
} elsif ($state == $STATE_COPYRIGHT_BLANK) {
if (! /^$/) {
&mistake("$file: missing blank line after copyright header");
}
if ($ARGV =~ /priv\.h$/) {
$state = $STATE_PRIV_START;
} else {
$state = $STATE_GUARD_START;
}
} elsif ($state == $STATE_PRIV_START) {
if (/^$/) {
&mistake("$file: too many blank lines after coyright header");
} elsif (/#ifndef $ifdefpriv$/) {
$state = $STATE_PRIV_ERROR;
} else {
&mistake("$file: missing '#ifndef $ifdefpriv'");
}
} elsif ($state == $STATE_PRIV_ERROR) {
if (/# error ".*"$/) {
$state = $STATE_PRIV_END;
} else {
&mistake("$file: missing '#error ...priv allow...'");
}
} elsif ($state == $STATE_PRIV_END) {
if (m,#endif /\* $ifdefpriv \*/,) {
$state = $STATE_PRIV_BLANK;
} else {
&mistake("$file: missing '#endif /* $ifdefpriv */'");
}
} elsif ($state == $STATE_PRIV_BLANK) {
if (! /^$/) {
&mistake("$file: missing blank line after priv guard");
}
$state = $STATE_GUARD_START;
} elsif ($state == $STATE_GUARD_START) {
if (/^$/) {
&mistake("$file: too many blank lines after coyright header");
} elsif (/#ifndef $ifdef$/) {
$state = $STATE_GUARD_DEFINE;
} else {
&mistake("$file: missing '#ifndef $ifdef'");
}
} elsif ($state == $STATE_GUARD_DEFINE) {
if (/# define $ifdef$/) {
$state = $STATE_GUARD_END;
} else {
&mistake("$file: missing '# define $ifdef'");
}
} elsif ($state == $STATE_GUARD_END) {
if (m,#endif /\* $ifdef \*/$,) {
$state = $STATE_EOF;
}
} elsif ($state == $STATE_EOF) {
die "$file: unexpected content after '#endif /* $ifdef */'";
} else {
die "$file: unexpected state $state";
}
}
exit $ret;

View File

@ -1,37 +0,0 @@
#!/usr/bin/perl
my @block;
my $msgstr = 0;
my $empty = 0;
my $unused = 0;
my $fuzzy = 0;
while (<>) {
if (/^$/) {
if (!$empty && !$unused && !$fuzzy) {
print @block;
}
@block = ();
$msgstr = 0;
$fuzzy = 0;
push @block, $_;
} else {
if (/^msgstr/) {
$msgstr = 1;
$empty = 1;
}
if (/^#.*fuzzy/) {
$fuzzy = 1;
}
if (/^#~ msgstr/) {
$unused = 1;
}
if ($msgstr && /".+"/) {
$empty = 0;
}
push @block, $_;
}
}
if (@block && !$empty && !$unused) {
print @block;
}

View File

@ -1,72 +0,0 @@
#!/usr/bin/env perl
my %noninlined;
my %mocked;
# Functions in public header don't get the noinline annotation
# so whitelist them here
$noninlined{"virEventAddTimeout"} = 1;
foreach my $arg (@ARGV) {
if ($arg =~ /\.h$/) {
#print "Scan header $arg\n";
&scan_annotations($arg);
} elsif ($arg =~ /mock\.c$/) {
#print "Scan mock $arg\n";
&scan_overrides($arg);
}
}
my $warned = 0;
foreach my $func (keys %mocked) {
next if exists $noninlined{$func};
$warned++;
print STDERR "$func is mocked at $mocked{$func} but missing noinline annotation\n";
}
exit $warned ? 1 : 0;
sub scan_annotations {
my $file = shift;
open FH, $file or die "cannot read $file: $!";
my $func;
while (<FH>) {
if (/^\s*(\w+)\(/ || /^(?:\w+\*?\s+)+(?:\*\s*)?(\w+)\(/) {
my $name = $1;
if ($name !~ /ATTRIBUTE/) {
$func = $name;
}
} elsif (/^\s*$/) {
$func = undef;
}
if (/ATTRIBUTE_NOINLINE/) {
if (defined $func) {
$noninlined{$func} = 1;
}
}
}
close FH
}
sub scan_overrides {
my $file = shift;
open FH, $file or die "cannot read $file: $!";
my $func;
while (<FH>) {
if (/^(\w+)\(/ || /^\w+\s*(?:\*\s*)?(\w+)\(/) {
my $name = $1;
if ($name =~ /^vir/) {
$mocked{$name} = "$file:$.";
}
}
}
close FH
}

View File

@ -1,26 +0,0 @@
#!/usr/bin/env perl
use strict;
my $file = " ";
my $ret = 0;
my %includes = ( );
my $lineno = 0;
while (<>) {
if (not $file eq $ARGV) {
%includes = ( );
$file = $ARGV;
$lineno = 0;
}
$lineno++;
if (/^# *include *[<"]([^>"]*\.h)[">]/) {
$includes{$1}++;
if ($includes{$1} == 2) {
$ret = 1;
print STDERR "$ARGV:$lineno: $_";
print STDERR "Do not include a header more than once per file\n";
}
}
}
exit $ret;

1245
cfg.mk

File diff suppressed because it is too large Load Diff

View File

@ -1,93 +0,0 @@
/*
* Copyright (C) 2013 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, see
* <http://www.gnu.org/licenses/>.
*/
/*
* Since virt-login-shell will be setuid, we must do everything
* we can to avoid linking to other libraries. Many of them do
* unsafe things in functions marked __attribute__((constructor)).
* The only way to avoid such deps is to re-compile the
* functions with the code in question disabled, and for that we
* must override the main config.h rules. Hence this file :-(
*/
#ifdef LIBVIRT_SETUID_RPC_CLIENT
# undef HAVE_LIBNL
# undef HAVE_LIBNL3
# undef HAVE_LIBSASL2
# undef HAVE_SYS_ACL_H
# undef WITH_CAPNG
# undef WITH_CURL
# undef WITH_DBUS
# undef WITH_DEVMAPPER
# undef WITH_DTRACE_PROBES
# undef WITH_GNUTLS
# undef WITH_LIBSSH
# undef WITH_MACVTAP
# undef WITH_NUMACTL
# undef WITH_SASL
# undef WITH_SSH2
# undef WITH_SYSTEMD_DAEMON
# undef WITH_VIRTUALPORT
# undef WITH_YAJL
# undef WITH_YAJL2
#endif
/*
* With the NSS module it's the same story as virt-login-shell. See the
* explanation above.
*/
#ifdef LIBVIRT_NSS
# undef HAVE_LIBNL
# undef HAVE_LIBNL3
# undef HAVE_LIBSASL2
# undef HAVE_SYS_ACL_H
# undef WITH_CAPNG
# undef WITH_CURL
# undef WITH_DEVMAPPER
# undef WITH_DTRACE_PROBES
# undef WITH_GNUTLS
# undef WITH_LIBSSH
# undef WITH_MACVTAP
# undef WITH_NUMACTL
# undef WITH_SASL
# undef WITH_SSH2
# undef WITH_VIRTUALPORT
# undef WITH_SECDRIVER_SELINUX
# undef WITH_SECDRIVER_APPARMOR
# undef WITH_CAPNG
#endif /* LIBVIRT_NSS */
#ifndef __GNUC__
# error "Libvirt requires GCC >= 4.4, or CLang"
#endif
/*
* Define __GNUC_PREREQ to a sane default if it isn't yet defined.
* This is done here so that it's included as early as possible; gnulib relies
* on this to be defined in features.h, which should be included from ctype.h.
* This doesn't happen on many non-glibc systems.
* When __GNUC_PREREQ is not defined, gnulib defines it to 0, which breaks things.
*/
#ifndef __GNUC_PREREQ
# define __GNUC_PREREQ(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
#endif
#if !(__GNUC_PREREQ(4, 4) || defined(__clang__))
# error "Libvirt requires GCC >= 4.4, or CLang"
#endif

File diff suppressed because it is too large Load Diff

422
daemon/Makefile.am Normal file
View File

@ -0,0 +1,422 @@
## Process this file with automake to produce Makefile.in
## Copyright (C) 2005-2013 Red Hat, Inc.
## See COPYING.LIB for the License of this software
INCLUDES = \
-I$(top_builddir)/gnulib/lib -I$(top_srcdir)/gnulib/lib \
-I$(top_builddir)/include -I$(top_srcdir)/include \
-I$(top_builddir)/src -I$(top_srcdir)/src \
-I$(top_srcdir)/src/util \
-I$(top_srcdir)/src/conf \
-I$(top_srcdir)/src/rpc \
-I$(top_srcdir)/src/remote \
$(GETTEXT_CPPFLAGS)
CLEANFILES =
DAEMON_GENERATED = \
$(srcdir)/remote_dispatch.h \
$(srcdir)/lxc_dispatch.h \
$(srcdir)/qemu_dispatch.h \
$(NULL)
DAEMON_SOURCES = \
libvirtd.c libvirtd.h \
libvirtd-config.c libvirtd-config.h \
remote.c remote.h \
stream.c stream.h \
../src/remote/remote_protocol.c \
../src/remote/lxc_protocol.c \
../src/remote/qemu_protocol.c \
$(DAEMON_GENERATED)
DISTCLEANFILES =
EXTRA_DIST = \
remote_dispatch.h \
lxc_dispatch.h \
qemu_dispatch.h \
libvirtd.conf \
libvirtd.init.in \
libvirtd.upstart \
libvirtd.policy.in \
libvirtd.sasl \
libvirtd.service.in \
libvirtd.sysconf \
libvirtd.sysctl \
libvirtd.aug \
libvirtd.logrotate.in \
libvirtd.qemu.logrotate.in \
libvirtd.lxc.logrotate.in \
libvirtd.uml.logrotate.in \
test_libvirtd.aug.in \
THREADS.txt \
libvirtd.pod.in \
libvirtd.8.in \
$(DAEMON_SOURCES)
BUILT_SOURCES =
REMOTE_PROTOCOL = $(top_srcdir)/src/remote/remote_protocol.x
LXC_PROTOCOL = $(top_srcdir)/src/remote/lxc_protocol.x
QEMU_PROTOCOL = $(top_srcdir)/src/remote/qemu_protocol.x
$(srcdir)/remote_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \
$(REMOTE_PROTOCOL)
$(AM_V_GEN)$(PERL) -w $(srcdir)/../src/rpc/gendispatch.pl \
--mode=server remote REMOTE $(REMOTE_PROTOCOL) > $@
$(srcdir)/lxc_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \
$(LXC_PROTOCOL)
$(AM_V_GEN)$(PERL) -w $(srcdir)/../src/rpc/gendispatch.pl \
--mode=server lxc LXC $(LXC_PROTOCOL) > $@
$(srcdir)/qemu_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \
$(QEMU_PROTOCOL)
$(AM_V_GEN)$(PERL) -w $(srcdir)/../src/rpc/gendispatch.pl \
--mode=server qemu QEMU $(QEMU_PROTOCOL) > $@
if WITH_LIBVIRTD
man8_MANS = libvirtd.8
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
CLEANFILES += test_libvirtd.aug
libvirtd.8: $(srcdir)/libvirtd.8.in
$(AM_V_GEN)sed \
-e 's|[@]sysconfdir[@]|$(sysconfdir)|g' \
-e 's|[@]localstatedir[@]|$(localstatedir)|g' \
< $< > $@-t && \
mv $@-t $@
libvirtd_SOURCES = $(DAEMON_SOURCES)
#-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_POSIX_C_SOURCE=199506L
libvirtd_CFLAGS = \
$(LIBXML_CFLAGS) $(GNUTLS_CFLAGS) $(SASL_CFLAGS) \
$(XDR_CFLAGS) $(POLKIT_CFLAGS) $(DBUS_CFLAGS) $(LIBNL_CFLAGS) \
$(WARN_CFLAGS) $(PIE_CFLAGS) \
$(COVERAGE_CFLAGS) \
-DQEMUD_PID_FILE="\"$(QEMUD_PID_FILE)\""
libvirtd_LDFLAGS = \
$(WARN_LDFLAGS) \
$(PIE_LDFLAGS) \
$(RELRO_LDFLAGS) \
$(COVERAGE_LDFLAGS)
libvirtd_LDADD = \
$(LIBXML_LIBS) \
$(GNUTLS_LIBS) \
$(SASL_LIBS) \
$(DBUS_LIBS) \
$(POLKIT_LIBS) \
$(LIBNL_LIBS)
if WITH_DTRACE_PROBES
libvirtd_LDADD += ../src/libvirt_probes.lo
endif
libvirtd_LDADD += \
../src/libvirt-lxc.la \
../src/libvirt-qemu.la
if ! WITH_DRIVER_MODULES
if WITH_QEMU
libvirtd_LDADD += ../src/libvirt_driver_qemu.la
if WITH_DTRACE_PROBES
libvirtd_LDADD += ../src/libvirt_qemu_probes.lo
endif
endif
if WITH_LXC
libvirtd_LDADD += ../src/libvirt_driver_lxc.la
endif
if WITH_XEN
libvirtd_LDADD += ../src/libvirt_driver_xen.la
endif
if WITH_LIBXL
libvirtd_LDADD += ../src/libvirt_driver_libxl.la
endif
if WITH_UML
libvirtd_LDADD += ../src/libvirt_driver_uml.la
endif
if WITH_STORAGE
libvirtd_LDADD += ../src/libvirt_driver_storage.la
endif
if WITH_NETWORK
libvirtd_LDADD += ../src/libvirt_driver_network.la
endif
if WITH_INTERFACE
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
if WITH_NWFILTER
libvirtd_LDADD += ../src/libvirt_driver_nwfilter.la
endif
endif
libvirtd_LDADD += ../src/libvirt.la
if WITH_POLKIT
if WITH_POLKIT0
policydir = $(datadir)/PolicyKit/policy
policyauth = auth_admin_keep_session
else
policydir = $(datadir)/polkit-1/actions
policyauth = auth_admin_keep
endif
endif
libvirtd.policy: libvirtd.policy.in $(top_builddir)/config.status
$(AM_V_GEN) sed \
-e 's|[@]authaction[@]|$(policyauth)|g' \
< $< > $@-t && \
mv $@-t $@
BUILT_SOURCES += libvirtd.policy
install-data-local: install-init-redhat install-init-systemd install-init-upstart \
install-data-sasl install-data-polkit \
install-logrotate install-sysctl
$(MKDIR_P) $(DESTDIR)$(localstatedir)/log/libvirt \
$(DESTDIR)$(localstatedir)/run/libvirt \
$(DESTDIR)$(localstatedir)/lib/libvirt
uninstall-local:: uninstall-init-redhat uninstall-init-systemd uninstall-init-upstart \
uninstall-data-sasl uninstall-data-polkit \
uninstall-logrotate uninstall-sysctl
rmdir $(DESTDIR)$(localstatedir)/log/libvirt || :
rmdir $(DESTDIR)$(localstatedir)/run/libvirt || :
rmdir $(DESTDIR)$(localstatedir)/lib/libvirt || :
if WITH_POLKIT
install-data-polkit::
$(MKDIR_P) $(DESTDIR)$(policydir)
$(INSTALL_DATA) libvirtd.policy $(DESTDIR)$(policydir)/org.libvirt.unix.policy
uninstall-data-polkit::
rm -f $(DESTDIR)$(policydir)/org.libvirt.unix.policy
rmdir $(DESTDIR)$(policydir) || :
else
install-data-polkit::
uninstall-data-polkit::
endif
remote.c: $(DAEMON_GENERATED)
remote.h: $(DAEMON_GENERATED)
LOGROTATE_CONFS = libvirtd.qemu.logrotate libvirtd.lxc.logrotate \
libvirtd.uml.logrotate libvirtd.logrotate
BUILT_SOURCES += $(LOGROTATE_CONFS)
libvirtd.logrotate: libvirtd.logrotate.in
$(AM_V_GEN)sed \
-e 's|[@]localstatedir[@]|$(localstatedir)|g' \
< $< > $@-t && \
mv $@-t $@
libvirtd.qemu.logrotate: libvirtd.qemu.logrotate.in
$(AM_V_GEN)sed \
-e 's|[@]localstatedir[@]|$(localstatedir)|g' \
< $< > $@-t && \
mv $@-t $@
libvirtd.lxc.logrotate: libvirtd.lxc.logrotate.in
$(AM_V_GEN)sed \
-e 's|[@]localstatedir[@]|$(localstatedir)|g' \
< $< > $@-t && \
mv $@-t $@
libvirtd.uml.logrotate: libvirtd.uml.logrotate.in
$(AM_V_GEN)sed \
-e 's|[@]localstatedir[@]|$(localstatedir)|g' \
< $< > $@-t && \
mv $@-t $@
install-logrotate: $(LOGROTATE_CONFS)
$(MKDIR_P) $(DESTDIR)$(localstatedir)/log/libvirt/qemu/ \
$(DESTDIR)$(localstatedir)/log/libvirt/lxc/ \
$(DESTDIR)$(localstatedir)/log/libvirt/uml/ \
$(DESTDIR)$(sysconfdir)/logrotate.d/
$(INSTALL_DATA) libvirtd.logrotate $(DESTDIR)$(sysconfdir)/logrotate.d/libvirtd
$(INSTALL_DATA) libvirtd.qemu.logrotate $(DESTDIR)$(sysconfdir)/logrotate.d/libvirtd.qemu
$(INSTALL_DATA) libvirtd.lxc.logrotate $(DESTDIR)$(sysconfdir)/logrotate.d/libvirtd.lxc
$(INSTALL_DATA) libvirtd.uml.logrotate $(DESTDIR)$(sysconfdir)/logrotate.d/libvirtd.uml
uninstall-logrotate:
rm -f $(DESTDIR)$(sysconfdir)/logrotate.d/libvirtd \
$(DESTDIR)$(sysconfdir)/logrotate.d/libvirtd.qemu \
$(DESTDIR)$(sysconfdir)/logrotate.d/libvirtd.lxc \
$(DESTDIR)$(sysconfdir)/logrotate.d/libvirtd.uml
rmdir $(DESTDIR)$(localstatedir)/log/libvirt/qemu || :
rmdir $(DESTDIR)$(localstatedir)/log/libvirt/lxc || :
rmdir $(DESTDIR)$(localstatedir)/log/libvirt/uml || :
rmdir $(DESTDIR)$(sysconfdir)/logrotate.d || :
install-sysconfig:
$(MKDIR_P) $(DESTDIR)$(sysconfdir)/sysconfig
$(INSTALL_DATA) $(srcdir)/libvirtd.sysconf \
$(DESTDIR)$(sysconfdir)/sysconfig/libvirtd
uninstall-sysconfig:
rm -f $(DESTDIR)$(sysconfdir)/sysconfig/libvirtd
rmdir $(DESTDIR)$(sysconfdir)/sysconfig || :
if WITH_SYSCTL
# Use $(prefix)/lib rather than $(libdir), since man sysctl.d insists on
# /usr/lib/sysctl.d/ even when libdir is /usr/lib64
install-sysctl:
$(MKDIR_P) $(DESTDIR)$(prefix)/lib/sysctl.d
$(INSTALL_DATA) $(srcdir)/libvirtd.sysctl \
$(DESTDIR)$(prefix)/lib/sysctl.d/libvirtd.conf
uninstall-sysctl:
rm -f $(DESTDIR)$(prefix)/lib/sysctl.d/libvirtd.conf
rmdir $(DESTDIR)$(prefix)/lib/sysctl.d || :
else
install-sysctl:
uninstall-sysctl:
endif
if LIBVIRT_INIT_SCRIPT_RED_HAT
BUILT_SOURCES += libvirtd.init
install-init-redhat: install-sysconfig libvirtd.init
$(MKDIR_P) $(DESTDIR)$(sysconfdir)/rc.d/init.d
$(INSTALL_SCRIPT) libvirtd.init \
$(DESTDIR)$(sysconfdir)/rc.d/init.d/libvirtd
uninstall-init-redhat: uninstall-sysconfig
rm -f $(DESTDIR)$(sysconfdir)/rc.d/init.d/libvirtd
rmdir $(DESTDIR)$(sysconfdir)/rc.d/init.d || :
else
install-init-redhat:
uninstall-init-redhat:
endif # LIBVIRT_INIT_SCRIPT_RED_HAT
if LIBVIRT_INIT_SCRIPT_UPSTART
install-init-upstart: install-sysconfig
$(MKDIR_P) $(DESTDIR)$(sysconfdir)/event.d
$(INSTALL_SCRIPT) libvirtd.upstart \
$(DESTDIR)$(sysconfdir)/event.d/libvirtd
uninstall-init-upstart: uninstall-sysconfig
rm -f $(DESTDIR)$(sysconfdir)/event.d/libvirtd
rmdir $(DESTDIR)$(sysconfdir)/event.d || :
else
install-init-upstart:
uninstall-init-upstart:
endif # LIBVIRT_INIT_SCRIPT_UPSTART
if LIBVIRT_INIT_SCRIPT_SYSTEMD
SYSTEMD_UNIT_DIR = /lib/systemd/system
BUILT_SOURCES += libvirtd.service
install-init-systemd: install-sysconfig libvirtd.service
$(MKDIR_P) $(DESTDIR)$(SYSTEMD_UNIT_DIR)
$(INSTALL_DATA) libvirtd.service \
$(DESTDIR)$(SYSTEMD_UNIT_DIR)/libvirtd.service
uninstall-init-systemd: uninstall-sysconfig
rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/libvirtd.service
rmdir $(DESTDIR)$(SYSTEMD_UNIT_DIR) || :
else
install-init-systemd:
uninstall-init-systemd:
endif # LIBVIRT_INIT_SCRIPT_SYSTEMD
libvirtd.init: libvirtd.init.in $(top_builddir)/config.status
$(AM_V_GEN)sed \
-e 's|[@]localstatedir[@]|$(localstatedir)|g' \
-e 's|[@]sbindir[@]|$(sbindir)|g' \
-e 's|[@]sysconfdir[@]|$(sysconfdir)|g' \
< $< > $@-t && \
chmod a+x $@-t && \
mv $@-t $@
libvirtd.service: libvirtd.service.in $(top_builddir)/config.status
$(AM_V_GEN)sed \
-e 's|[@]localstatedir[@]|$(localstatedir)|g' \
-e 's|[@]sbindir[@]|$(sbindir)|g' \
-e 's|[@]sysconfdir[@]|$(sysconfdir)|g' \
< $< > $@-t && \
mv $@-t $@
check-local: check-augeas
AUG_GENTEST = $(PERL) $(top_srcdir)/build-aux/augeas-gentest.pl
test_libvirtd.aug: test_libvirtd.aug.in $(srcdir)/libvirtd.conf
$(AM_V_GEN)$(AUG_GENTEST) $(srcdir)/libvirtd.conf $< $@
check-augeas: test_libvirtd.aug
$(AM_V_GEN)if test -x '$(AUGPARSE)'; then \
'$(AUGPARSE)' -I $(srcdir) test_libvirtd.aug; \
fi
# 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
POD2MAN = pod2man -c "Virtualization Support" \
-r "$(PACKAGE)-$(VERSION)" -s 8
$(srcdir)/libvirtd.8.in: libvirtd.pod.in $(top_srcdir)/configure.ac
$(AM_V_GEN)$(POD2MAN) --name LIBVIRTD $< $@ \
&& if grep 'POD ERROR' $@ ; then rm $@; exit 1; fi
# This is needed for clients too, so can't wrap in
# the WITH_LIBVIRTD conditional
if WITH_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) $(man8_MANS)
CLEANFILES += *.cov *.gcov .libs/*.gcda .libs/*.gcno *.gcno *.gcda
MAINTAINERCLEANFILES = $(srcdir)/libvirtd.8.in $(DAEMON_GENERATED)

52
daemon/THREADS.txt Normal file
View File

@ -0,0 +1,52 @@
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 on 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

492
daemon/libvirtd-config.c Normal file
View File

@ -0,0 +1,492 @@
/*
* libvirtd.c: daemon start of day, guest process & i/o management
*
* Copyright (C) 2006-2012 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, see
* <http://www.gnu.org/licenses/>.
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#include <config.h>
#include "libvirtd-config.h"
#include "virconf.h"
#include "viralloc.h"
#include "virerror.h"
#include "virlog.h"
#include "rpc/virnetserver.h"
#include "configmake.h"
#include "remote/remote_protocol.h"
#include "remote/remote_driver.h"
#define VIR_FROM_THIS VIR_FROM_CONF
/* Allocate an array of malloc'd strings from the config file, filename
* (used only in diagnostics), using handle "conf". Upon error, return -1
* and free any allocated memory. Otherwise, save the array in *list_arg
* and return 0.
*/
static int
remoteConfigGetStringList(virConfPtr conf, const char *key, char ***list_arg,
const char *filename)
{
char **list;
virConfValuePtr p = virConfGetValue(conf, key);
if (!p)
return 0;
switch (p->type) {
case VIR_CONF_STRING:
if (VIR_ALLOC_N(list, 2) < 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("failed to allocate memory for %s config list"),
key);
return -1;
}
list[0] = strdup(p->str);
list[1] = NULL;
if (list[0] == NULL) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("failed to allocate memory for %s config list value"),
key);
VIR_FREE(list);
return -1;
}
break;
case VIR_CONF_LIST: {
int i, len = 0;
virConfValuePtr pp;
for (pp = p->list; pp; pp = pp->next)
len++;
if (VIR_ALLOC_N(list, 1+len) < 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("failed to allocate memory for %s config list"),
key);
return -1;
}
for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
if (pp->type != VIR_CONF_STRING) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("remoteReadConfigFile: %s: %s:"
" must be a string or list of strings"),
filename, key);
VIR_FREE(list);
return -1;
}
list[i] = strdup(pp->str);
if (list[i] == NULL) {
int j;
for (j = 0 ; j < i ; j++)
VIR_FREE(list[j]);
VIR_FREE(list);
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("failed to allocate memory for %s config list value"),
key);
return -1;
}
}
list[i] = NULL;
break;
}
default:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("remoteReadConfigFile: %s: %s:"
" must be a string or list of strings"),
filename, key);
return -1;
}
*list_arg = list;
return 0;
}
/* A helper function used by each of the following macros. */
static int
checkType(virConfValuePtr p, const char *filename,
const char *key, virConfType required_type)
{
if (p->type != required_type) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("remoteReadConfigFile: %s: %s: invalid type:"
" got %s; expected %s"), filename, key,
virConfTypeName(p->type),
virConfTypeName(required_type));
return -1;
}
return 0;
}
/* If there is no config data for the key, #var_name, then do nothing.
If there is valid data of type VIR_CONF_STRING, and strdup succeeds,
store the result in var_name. Otherwise, (i.e. invalid type, or strdup
failure), give a diagnostic and "goto" the cleanup-and-fail label. */
#define GET_CONF_STR(conf, filename, var_name) \
do { \
virConfValuePtr p = virConfGetValue(conf, #var_name); \
if (p) { \
if (checkType(p, filename, #var_name, VIR_CONF_STRING) < 0) \
goto error; \
VIR_FREE(data->var_name); \
if (!(data->var_name = strdup(p->str))) { \
virReportOOMError(); \
goto error; \
} \
} \
} while (0)
/* Like GET_CONF_STR, but for integral values. */
#define GET_CONF_INT(conf, filename, var_name) \
do { \
virConfValuePtr p = virConfGetValue(conf, #var_name); \
if (p) { \
if (checkType(p, filename, #var_name, VIR_CONF_LONG) < 0) \
goto error; \
data->var_name = p->l; \
} \
} while (0)
static int remoteConfigGetAuth(virConfPtr conf, const char *key, int *auth, const char *filename) {
virConfValuePtr p;
p = virConfGetValue(conf, key);
if (!p)
return 0;
if (checkType(p, filename, key, VIR_CONF_STRING) < 0)
return -1;
if (!p->str)
return 0;
if (STREQ(p->str, "none")) {
*auth = VIR_NET_SERVER_SERVICE_AUTH_NONE;
#if WITH_SASL
} else if (STREQ(p->str, "sasl")) {
*auth = VIR_NET_SERVER_SERVICE_AUTH_SASL;
#endif
} else if (STREQ(p->str, "polkit")) {
*auth = VIR_NET_SERVER_SERVICE_AUTH_POLKIT;
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("remoteReadConfigFile: %s: %s: unsupported auth %s"),
filename, key, p->str);
return -1;
}
return 0;
}
int
daemonConfigFilePath(bool privileged, char **configfile)
{
if (privileged) {
if (!(*configfile = strdup(SYSCONFDIR "/libvirt/libvirtd.conf")))
goto no_memory;
} else {
char *configdir = NULL;
if (!(configdir = virGetUserConfigDirectory()))
goto error;
if (virAsprintf(configfile, "%s/libvirtd.conf", configdir) < 0) {
VIR_FREE(configdir);
goto no_memory;
}
VIR_FREE(configdir);
}
return 0;
no_memory:
virReportOOMError();
error:
return -1;
}
struct daemonConfig*
daemonConfigNew(bool privileged ATTRIBUTE_UNUSED)
{
struct daemonConfig *data;
char *localhost;
int ret;
if (VIR_ALLOC(data) < 0) {
virReportOOMError();
return NULL;
}
data->listen_tls = 1;
data->listen_tcp = 0;
if (!(data->tls_port = strdup(LIBVIRTD_TLS_PORT)))
goto no_memory;
if (!(data->tcp_port = strdup(LIBVIRTD_TCP_PORT)))
goto no_memory;
/* Only default to PolicyKit if running as root */
#if WITH_POLKIT
if (privileged) {
data->auth_unix_rw = REMOTE_AUTH_POLKIT;
data->auth_unix_ro = REMOTE_AUTH_POLKIT;
} else {
#endif
data->auth_unix_rw = REMOTE_AUTH_NONE;
data->auth_unix_ro = REMOTE_AUTH_NONE;
#if WITH_POLKIT
}
#endif
if (data->auth_unix_rw == REMOTE_AUTH_POLKIT)
data->unix_sock_rw_perms = strdup("0777"); /* Allow world */
else
data->unix_sock_rw_perms = strdup("0700"); /* Allow user only */
data->unix_sock_ro_perms = strdup("0777"); /* Always allow world */
if (!data->unix_sock_ro_perms ||
!data->unix_sock_rw_perms)
goto no_memory;
#if WITH_SASL
data->auth_tcp = REMOTE_AUTH_SASL;
#else
data->auth_tcp = REMOTE_AUTH_NONE;
#endif
data->auth_tls = REMOTE_AUTH_NONE;
data->mdns_adv = 0;
data->min_workers = 5;
data->max_workers = 20;
data->max_clients = 20;
data->prio_workers = 5;
data->max_requests = 20;
data->max_client_requests = 5;
data->log_buffer_size = 64;
data->audit_level = 1;
data->audit_logging = 0;
data->keepalive_interval = 5;
data->keepalive_count = 5;
data->keepalive_required = 0;
localhost = virGetHostname(NULL);
if (localhost == NULL) {
/* we couldn't resolve the hostname; assume that we are
* running in disconnected operation, and report a less
* useful Avahi string
*/
ret = virAsprintf(&data->mdns_name, "Virtualization Host");
} else {
char *tmp;
/* Extract the host part of the potentially FQDN */
if ((tmp = strchr(localhost, '.')))
*tmp = '\0';
ret = virAsprintf(&data->mdns_name, "Virtualization Host %s",
localhost);
}
VIR_FREE(localhost);
if (ret < 0)
goto no_memory;
return data;
no_memory:
virReportOOMError();
daemonConfigFree(data);
return NULL;
}
void
daemonConfigFree(struct daemonConfig *data)
{
char **tmp;
if (!data)
return;
VIR_FREE(data->listen_addr);
VIR_FREE(data->tls_port);
VIR_FREE(data->tcp_port);
VIR_FREE(data->unix_sock_ro_perms);
VIR_FREE(data->unix_sock_rw_perms);
VIR_FREE(data->unix_sock_group);
VIR_FREE(data->unix_sock_dir);
VIR_FREE(data->mdns_name);
tmp = data->tls_allowed_dn_list;
while (tmp && *tmp) {
VIR_FREE(*tmp);
tmp++;
}
VIR_FREE(data->tls_allowed_dn_list);
tmp = data->sasl_allowed_username_list;
while (tmp && *tmp) {
VIR_FREE(*tmp);
tmp++;
}
VIR_FREE(data->sasl_allowed_username_list);
VIR_FREE(data->key_file);
VIR_FREE(data->ca_file);
VIR_FREE(data->cert_file);
VIR_FREE(data->crl_file);
VIR_FREE(data->host_uuid);
VIR_FREE(data->log_filters);
VIR_FREE(data->log_outputs);
VIR_FREE(data);
}
static int
daemonConfigLoadOptions(struct daemonConfig *data,
const char *filename,
virConfPtr conf)
{
GET_CONF_INT(conf, filename, listen_tcp);
GET_CONF_INT(conf, filename, listen_tls);
GET_CONF_STR(conf, filename, tls_port);
GET_CONF_STR(conf, filename, tcp_port);
GET_CONF_STR(conf, filename, listen_addr);
if (remoteConfigGetAuth(conf, "auth_unix_rw", &data->auth_unix_rw, filename) < 0)
goto error;
#if WITH_POLKIT
/* Change default perms to be wide-open if PolicyKit is enabled.
* Admin can always override in config file
*/
if (data->auth_unix_rw == REMOTE_AUTH_POLKIT) {
VIR_FREE(data->unix_sock_rw_perms);
if (!(data->unix_sock_rw_perms = strdup("0777"))) {
virReportOOMError();
goto error;
}
}
#endif
if (remoteConfigGetAuth(conf, "auth_unix_ro", &data->auth_unix_ro, filename) < 0)
goto error;
if (remoteConfigGetAuth(conf, "auth_tcp", &data->auth_tcp, filename) < 0)
goto error;
if (remoteConfigGetAuth(conf, "auth_tls", &data->auth_tls, filename) < 0)
goto error;
GET_CONF_STR(conf, filename, unix_sock_group);
GET_CONF_STR(conf, filename, unix_sock_ro_perms);
GET_CONF_STR(conf, filename, unix_sock_rw_perms);
GET_CONF_STR(conf, filename, unix_sock_dir);
GET_CONF_INT(conf, filename, mdns_adv);
GET_CONF_STR(conf, filename, mdns_name);
GET_CONF_INT(conf, filename, tls_no_sanity_certificate);
GET_CONF_INT(conf, filename, tls_no_verify_certificate);
GET_CONF_STR(conf, filename, key_file);
GET_CONF_STR(conf, filename, cert_file);
GET_CONF_STR(conf, filename, ca_file);
GET_CONF_STR(conf, filename, crl_file);
if (remoteConfigGetStringList(conf, "tls_allowed_dn_list",
&data->tls_allowed_dn_list, filename) < 0)
goto error;
if (remoteConfigGetStringList(conf, "sasl_allowed_username_list",
&data->sasl_allowed_username_list, filename) < 0)
goto error;
GET_CONF_INT(conf, filename, min_workers);
GET_CONF_INT(conf, filename, max_workers);
GET_CONF_INT(conf, filename, max_clients);
GET_CONF_INT(conf, filename, prio_workers);
GET_CONF_INT(conf, filename, max_requests);
GET_CONF_INT(conf, filename, max_client_requests);
GET_CONF_INT(conf, filename, audit_level);
GET_CONF_INT(conf, filename, audit_logging);
GET_CONF_STR(conf, filename, host_uuid);
GET_CONF_INT(conf, filename, log_level);
GET_CONF_STR(conf, filename, log_filters);
GET_CONF_STR(conf, filename, log_outputs);
GET_CONF_INT(conf, filename, log_buffer_size);
GET_CONF_INT(conf, filename, keepalive_interval);
GET_CONF_INT(conf, filename, keepalive_count);
GET_CONF_INT(conf, filename, keepalive_required);
return 0;
error:
return -1;
}
/* Read the config file if it exists.
* Only used in the remote case, hence the name.
*/
int
daemonConfigLoadFile(struct daemonConfig *data,
const char *filename,
bool allow_missing)
{
virConfPtr conf;
int ret;
if (allow_missing &&
access(filename, R_OK) == -1 &&
errno == ENOENT)
return 0;
conf = virConfReadFile(filename, 0);
if (!conf)
return -1;
ret = daemonConfigLoadOptions(data, filename, conf);
virConfFree(conf);
return ret;
}
int daemonConfigLoadData(struct daemonConfig *data,
const char *filename,
const char *filedata)
{
virConfPtr conf;
int ret;
conf = virConfReadMem(filedata, strlen(filedata), 0);
if (!conf)
return -1;
ret = daemonConfigLoadOptions(data, filename, conf);
virConfFree(conf);
return ret;
}

94
daemon/libvirtd-config.h Normal file
View File

@ -0,0 +1,94 @@
/*
* libvirtd.c: daemon start of day, guest process & i/o management
*
* Copyright (C) 2006-2012 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, see
* <http://www.gnu.org/licenses/>.
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#ifndef __LIBVIRTD_CONFIG_H__
# define __LIBVIRTD_CONFIG_H__
# include "internal.h"
struct daemonConfig {
char *host_uuid;
int listen_tls;
int listen_tcp;
char *listen_addr;
char *tls_port;
char *tcp_port;
char *unix_sock_ro_perms;
char *unix_sock_rw_perms;
char *unix_sock_group;
char *unix_sock_dir;
int auth_unix_rw;
int auth_unix_ro;
int auth_tcp;
int auth_tls;
int mdns_adv;
char *mdns_name;
int tls_no_verify_certificate;
int tls_no_sanity_certificate;
char **tls_allowed_dn_list;
char **sasl_allowed_username_list;
char *key_file;
char *cert_file;
char *ca_file;
char *crl_file;
int min_workers;
int max_workers;
int max_clients;
int prio_workers;
int max_requests;
int max_client_requests;
int log_level;
char *log_filters;
char *log_outputs;
int log_buffer_size;
int audit_level;
int audit_logging;
int keepalive_interval;
unsigned int keepalive_count;
int keepalive_required;
};
int daemonConfigFilePath(bool privileged, char **configfile);
struct daemonConfig* daemonConfigNew(bool privileged);
void daemonConfigFree(struct daemonConfig *data);
int daemonConfigLoadFile(struct daemonConfig *data,
const char *filename,
bool allow_missing);
int daemonConfigLoadData(struct daemonConfig *data,
const char *filename,
const char *filedata);
#endif /* __LIBVIRTD_CONFIG_H__ */

View File

@ -13,7 +13,7 @@ module Libvirtd =
let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\""
let bool_val = store /0|1/
let int_val = store /-?[0-9]+/
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
@ -35,7 +35,6 @@ module Libvirtd =
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_admin_perms"
| str_entry "unix_sock_dir"
let authentication_entry = str_entry "auth_unix_ro"
@ -52,26 +51,18 @@ module Libvirtd =
| bool_entry "tls_no_sanity_certificate"
| str_array_entry "tls_allowed_dn_list"
| str_array_entry "sasl_allowed_username_list"
| str_array_entry "access_drivers"
| str_entry "tls_priority"
let processing_entry = int_entry "min_workers"
| int_entry "max_workers"
| int_entry "max_clients"
| int_entry "max_queued_clients"
| int_entry "max_anonymous_clients"
| int_entry "max_requests"
| int_entry "max_client_requests"
| int_entry "prio_workers"
let admin_processing_entry = int_entry "admin_min_workers"
| int_entry "admin_max_workers"
| int_entry "admin_max_clients"
| int_entry "admin_max_queued_clients"
| int_entry "admin_max_client_requests"
let logging_entry = int_entry "log_level"
| str_entry "log_filters"
| str_entry "log_outputs"
| int_entry "log_buffer_size"
let auditing_entry = int_entry "audit_level"
| bool_entry "audit_logging"
@ -80,13 +71,7 @@ module Libvirtd =
| int_entry "keepalive_count"
| bool_entry "keepalive_required"
let admin_keepalive_entry = int_entry "admin_keepalive_interval"
| int_entry "admin_keepalive_count"
| bool_entry "admin_keepalive_required"
let misc_entry = str_entry "host_uuid"
| str_entry "host_uuid_source"
| int_entry "ovs_timeout"
(* Each enty in the config is one of the following three ... *)
let entry = network_entry
@ -95,11 +80,9 @@ module Libvirtd =
| certificate_entry
| authorization_entry
| processing_entry
| admin_processing_entry
| logging_entry
| auditing_entry
| keepalive_entry
| admin_keepalive_entry
| misc_entry
let comment = [ label "#comment" . del /#[ \t]*/ "# " . store /([^ \t\n][^\n]*)?/ . del /\n/ "\n" ]
let empty = [ label "#empty" . eol ]

1519
daemon/libvirtd.c Normal file

File diff suppressed because it is too large Load Diff

395
daemon/libvirtd.conf Normal file
View File

@ -0,0 +1,395 @@
# 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 disabled by default, uncomment this to enable it
#mdns_adv = 1
# 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 our own server certificates
#
# When libvirtd starts it performs some sanity checks against
# its own certificates.
#
# Default is to always run sanity checks. Uncommenting this
# will disable sanity checks which is not a good idea
#tls_no_sanity_certificate = 1
# 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, up to max_workers limit.
# Typically you'd want max_workers to equal maximum number
# of clients allowed
#min_workers = 5
#max_workers = 20
# The number of priority workers. If all workers from above
# pool will stuck, some calls marked as high priority
# (notably domainDestroy) can be executed in this pool.
#prio_workers = 5
# 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 up to 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 information, 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 one of:
# x:name
# x:+name
# where name is a string which is matched against source file name,
# e.g., "remote", "qemu", or "util/json", the optional "+" prefix
# tells libvirt to log stack trace for each message matching name,
# and x 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. to only get warning or errors from the remote layer and only errors
# from the event layer:
#log_filters="3:remote 4:event"
# Logging outputs:
# An output is one of the places to save logging information
# 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. to log all warnings and errors to syslog under the libvirtd ident:
#log_outputs="3:syslog:libvirtd"
#
# Log debug buffer size: default 64
# The daemon keeps an internal debug log buffer which will be dumped in case
# of crash or upon receiving a SIGUSR2 signal. This setting allows to override
# the default buffer size in kilobytes.
# If value is 0 or less the debug log buffer is deactivated
#log_buffer_size = 64
##################################################################
#
# Auditing
#
# This setting allows usage of the auditing subsystem to be altered:
#
# audit_level == 0 -> disable all auditing
# audit_level == 1 -> enable auditing, only if enabled on host (default)
# audit_level == 2 -> enable auditing, and exit if disabled on host
#
#audit_level = 2
#
# If set to 1, then audit messages will also be sent
# via libvirt logging infrastructure. Defaults to 0
#
#audit_logging = 1
###################################################################
# UUID of the host:
# Provide the UUID of the host here in case the command
# 'dmidecode -s system-uuid' does not provide a valid uuid. In case
# 'dmidecode' does not provide a valid UUID and none is provided here, a
# temporary UUID will be generated.
# Keep the format of the example UUID below. UUID must not have all digits
# be the same.
# NB This default all-zeros UUID will not work. Replace
# it with the output of the 'uuidgen' command and then
# uncomment this entry
#host_uuid = "00000000-0000-0000-0000-000000000000"
###################################################################
# Keepalive protocol:
# This allows libvirtd to detect broken client connections or even
# dead client. A keepalive message is sent to a client after
# keepalive_interval seconds of inactivity to check if the client is
# still responding; keepalive_count is a maximum number of keepalive
# messages that are allowed to be sent to the client without getting
# any response before the connection is considered broken. In other
# words, the connection is automatically closed approximately after
# keepalive_interval * (keepalive_count + 1) seconds since the last
# message received from the client. If keepalive_interval is set to
# -1, libvirtd will never send keepalive requests; however clients
# can still send them and the deamon will send responses. When
# keepalive_count is set to 0, connections will be automatically
# closed after keepalive_interval seconds of inactivity without
# sending any keepalive messages.
#
#keepalive_interval = 5
#keepalive_count = 5
#
# If set to 1, libvirtd will refuse to talk to clients that do not
# support keepalive protocol. Defaults to 0.
#
#keepalive_required = 1

76
daemon/libvirtd.h Normal file
View File

@ -0,0 +1,76 @@
/*
* libvirtd.h: daemon data structure definitions
*
* Copyright (C) 2006-2012 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, see
* <http://www.gnu.org/licenses/>.
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#ifndef LIBVIRTD_H__
# define LIBVIRTD_H__
# define VIR_ENUM_SENTINELS
# include <config.h>
# include <rpc/types.h>
# include <rpc/xdr.h>
# include "remote_protocol.h"
# include "lxc_protocol.h"
# include "qemu_protocol.h"
# include "virlog.h"
# include "virthread.h"
# if WITH_SASL
# include "virnetsaslcontext.h"
# endif
# include "virnetserverprogram.h"
typedef struct daemonClientStream daemonClientStream;
typedef daemonClientStream *daemonClientStreamPtr;
typedef struct daemonClientPrivate daemonClientPrivate;
typedef daemonClientPrivate *daemonClientPrivatePtr;
/* Stores the per-client connection state */
struct daemonClientPrivate {
/* Hold while accessing any data except conn */
virMutex lock;
int domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LAST];
# if WITH_SASL
virNetSASLSessionPtr sasl;
# endif
/* 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;
daemonClientStreamPtr streams;
bool keepalive_supported;
};
# if WITH_SASL
extern virNetSASLContextPtr saslCtxt;
# endif
extern virNetServerProgramPtr remoteProgram;
extern virNetServerProgramPtr qemuProgram;
#endif

View File

@ -1,20 +1,21 @@
#!/bin/sh
# the following is the LSB init header see
# http://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/initscrcomconv.html
# http://www.linux-foundation.org/spec//booksets/LSB-Core-generic/LSB-Core-generic.html#INITSCRCOMCONV
#
### BEGIN INIT INFO
# Provides: libvirtd
# Default-Start: 3 4 5
# Default-Stop: 0 1 2 6
# Required-Start: $network messagebus virtlogd
# Required-Start: $network messagebus
# Should-Start: $named
# Should-Start: xend
# Should-Start: avahi-daemon
# Required-Stop: $network messagebus
# Should-Start: $named xend avahi-daemon virtlockd
# 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 https://libvirt.org
# See http://libvirt.org
### END INIT INFO
# the following is chkconfig init header
@ -24,7 +25,7 @@
# chkconfig: 345 97 03
# description: This is a daemon for managing guest instances \
# and libvirt virtual networks \
# See https://libvirt.org
# See http://libvirt.org
#
# processname: libvirtd
# pidfile: @localstatedir@/run/libvirtd.pid

View File

@ -5,4 +5,5 @@
compress
delaycompress
copytruncate
minsize 100k
}

204
daemon/libvirtd.pod.in Normal file
View File

@ -0,0 +1,204 @@
=head1 NAME
libvirtd - libvirtd management daemon
=head1 SYNOPSIS
B<libvirtd> [ -dlv ] [ -f config_file ] [ -p pid_file ] [ -t timeout_seconds ]
B<libvirtd> --version
=head1 DESCRIPTION
The B<libvirtd> program is the server side daemon component of the libvirt
virtualization management system.
This daemon runs on host servers and performs required management tasks for
virtualized guests. This includes activities such as starting, stopping
and migrating guests between host servers, configuring and manipulating
networking, and managing storage for use by guests.
The libvirt client libraries and utilities connect to this daemon to issue
tasks and collect information about the configuration and resources of the host
system and guests.
By default, the libvirtd daemon listens for requests on a local Unix domain
socket. Using the B<-l>|B<--listen> command line option, the libvirtd daemon
can be instructed to additionally listen on a TCP/IP socket. The TCP/IP socket
to use is defined in the libvirtd configuration file.
Restarting libvirtd does not impact running guests. Guests continue to operate
and will be picked up automatically if their XML configuration has been
defined. Any guests whose XML configuration has not been defined will be lost
from the configuration.
=head1 OPTIONS
=over
=item B<-d, --daemon>
Run as a daemon & write PID file.
=item B<-f, --config> I<FILE>
Use this configuration file, overriding the default value.
=item B<-l, --listen>
Listen for TCP/IP connections.
=item B<-p, --pid-file> I<FILE>
Use this name for the PID file, overriding the default value.
=item B<-t, --timeout> I<SECONDS>
Exit after timeout period (in seconds) elapse with no client connections
or registered resources. Be aware that resources such as autostart
networks will result in never reaching the timeout, even when there are
no client connections.
=item B<-v, --verbose>
Enable output of verbose messages.
=item B< --version>
Display version information then exit.
=back
=head1 SIGNALS
On receipt of B<SIGHUP> libvirtd will reload its configuration.
=head1 FILES
=head2 When run as B<root>.
=over
=item F<SYSCONFDIR/libvirtd.conf>
The default configuration file used by libvirtd, unless overridden on the
command line using the B<-f>|B<--config> option.
=item F<LOCALSTATEDIR/run/libvirt/libvirt-sock>
=item F<LOCALSTATEDIR/run/libvirt/libvirt-sock-ro>
The sockets libvirtd will use.
=item F<SYSCONFDIR/pki/CA/cacert.pem>
The TLS B<Certificate Authority> certificate libvirtd will use.
=item F<SYSCONFDIR/pki/libvirt/servercert.pem>
The TLS B<Server> certificate libvirtd will use.
=item F<SYSCONFDIR/pki/libvirt/private/serverkey.pem>
The TLS B<Server> private key libvirtd will use.
=item F<LOCALSTATEDIR/run/libvirtd.pid>
The PID file to use, unless overridden by the B<-p>|B<--pid-file> option.
=back
=head2 When run as B<non-root>.
=over
=item F<$XDG_CONFIG_HOME/libvirtd.conf>
The default configuration file used by libvirtd, unless overridden on the
command line using the B<-f>|B<--config> option.
=item F<$XDG_RUNTIME_DIR/libvirt/libvirt-sock>
The socket libvirtd will use.
=item F<$HOME/.pki/libvirt/cacert.pem>
The TLS B<Certificate Authority> certificate libvirtd will use.
=item F<$HOME/.pki/libvirt/servercert.pem>
The TLS B<Server> certificate libvirtd will use.
=item F<$HOME/.pki/libvirt/serverkey.pem>
The TLS B<Server> private key libvirtd will use.
=item F<$XDG_RUNTIME_DIR/libvirt/libvirtd.pid>
The PID file to use, unless overridden by the B<-p>|B<--pid-file> option.
=item If $XDG_CONFIG_HOME is not set in your environment, libvirtd will use F<$HOME/.config>
=item If $XDG_RUNTIME_DIR is not set in your environment, libvirtd will use F<$HOME/.cache>
=back
=head1 EXAMPLES
To retrieve the version of libvirtd:
# libvirtd --version
libvirtd (libvirt) 0.8.2
#
To start libvirtd, instructing it to daemonize and create a PID file:
# libvirtd -d
# ls -la LOCALSTATEDIR/run/libvirtd.pid
-rw-r--r-- 1 root root 6 Jul 9 02:40 LOCALSTATEDIR/run/libvirtd.pid
#
=head1 BUGS
Please report all bugs you discover. This should be done via either:
=over
=item a) the mailing list
L<http://libvirt.org/contact.html>
=item or,
B<>
=item b) the bug tracker
L<http://libvirt.org/bugs.html>
=item Alternatively, you may report bugs to your software distributor / vendor.
=back
=head1 AUTHORS
Please refer to the AUTHORS file distributed with libvirt.
=head1 COPYRIGHT
Copyright (C) 2006-2012 Red Hat, Inc., and the authors listed in the
libvirt AUTHORS file.
=head1 LICENSE
libvirtd is distributed under the terms of the GNU LGPL v2.1+.
This is free software; see the source for copying conditions. There
is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE
=head1 SEE ALSO
L<virsh(1)>, L<virt-install(1)>, L<virt-xml-validate(1)>, L<virt-top(1)>,
L<virt-df(1)>, L<http://www.libvirt.org/>
=cut

51
daemon/libvirtd.policy.in Normal file
View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<!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) 2012 Red Hat, Inc.
Copyright (C) 2007 Daniel P. Berrange <berrange redhat com>
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, see
<http://www.gnu.org/licenses/>.
-->
<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>
<!-- Any program can use libvirt in read/write mode if they
provide the root password -->
<allow_any>@authaction@</allow_any>
<allow_inactive>@authaction@</allow_inactive>
<allow_active>@authaction@</allow_active>
</defaults>
</action>
</policyconfig>

View File

@ -5,4 +5,5 @@
compress
delaycompress
copytruncate
minsize 100k
}

31
daemon/libvirtd.sasl Normal file
View File

@ -0,0 +1,31 @@
# 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
# Some older builds of MIT kerberos on Linux ignore this option &
# instead need KRB5_KTNAME env var.
# For modern Linux, and other OS, this should be sufficient
#
# There is no default value here, uncomment if you need this
#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

@ -0,0 +1,22 @@
# NB we don't use socket activation. When libvirtd starts it will
# spawn any virtual machines registered for autostart. We want this
# to occur on every boot, regardless of whether any client connects
# to a socket. Thus socket activation doesn't have any benefit
[Unit]
Description=Virtualization daemon
Before=libvirt-guests.service
After=network.target
After=dbus.service
After=iscsid.service
[Service]
EnvironmentFile=-/etc/sysconfig/libvirtd
ExecStart=@sbindir@/libvirtd $LIBVIRTD_ARGS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
# Override the maximum number of opened files
#LimitNOFILE=2048
[Install]
WantedBy=multi-user.target

24
daemon/libvirtd.sysconf Normal file
View File

@ -0,0 +1,24 @@
# Override the default config file
# NOTE: This setting is no longer honoured if using
# systemd. Set '--config /etc/libvirt/libvirtd.conf'
# in LIBVIRTD_ARGS instead.
#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, unless vnc_allow_host_audio
# is enabled in /etc/libvirt/qemu.conf
#QEMU_AUDIO_DRV=sdl
#
#SDL_AUDIODRIVER=pulse
# Override the maximum number of opened files
#LIBVIRTD_NOFILES_LIMIT=2048

View File

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

4891
daemon/remote.c Normal file

File diff suppressed because it is too large Load Diff

45
daemon/remote.h Normal file
View File

@ -0,0 +1,45 @@
/*
* 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, see
* <http://www.gnu.org/licenses/>.
*
* Author: Richard W.M. Jones <rjones@redhat.com>
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#ifndef __LIBVIRTD_REMOTE_H__
# define __LIBVIRTD_REMOTE_H__
# include "remote_protocol.h"
# include "rpc/virnetserverprogram.h"
# include "rpc/virnetserverclient.h"
extern virNetServerProgramProc remoteProcs[];
extern size_t remoteNProcs;
extern virNetServerProgramProc lxcProcs[];
extern size_t lxcNProcs;
extern virNetServerProgramProc qemuProcs[];
extern size_t qemuNProcs;
void remoteClientFreeFunc(void *data);
void *remoteClientInitHook(virNetServerClientPtr client,
void *opaque);
#endif /* __LIBVIRTD_REMOTE_H__ */

777
daemon/stream.c Normal file
View File

@ -0,0 +1,777 @@
/*
* stream.c: APIs for managing client streams
*
* Copyright (C) 2009, 2011 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, see
* <http://www.gnu.org/licenses/>.
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#include <config.h>
#include "stream.h"
#include "remote.h"
#include "viralloc.h"
#include "virlog.h"
#include "virnetserverclient.h"
#include "virerror.h"
#define VIR_FROM_THIS VIR_FROM_STREAMS
struct daemonClientStream {
daemonClientPrivatePtr priv;
int refs;
virNetServerProgramPtr prog;
virStreamPtr st;
int procedure;
int serial;
unsigned int recvEOF : 1;
unsigned int closed : 1;
int filterID;
virNetMessagePtr rx;
int tx;
daemonClientStreamPtr next;
};
static int
daemonStreamHandleWrite(virNetServerClientPtr client,
daemonClientStream *stream);
static int
daemonStreamHandleRead(virNetServerClientPtr client,
daemonClientStream *stream);
static int
daemonStreamHandleFinish(virNetServerClientPtr client,
daemonClientStream *stream,
virNetMessagePtr msg);
static int
daemonStreamHandleAbort(virNetServerClientPtr client,
daemonClientStream *stream,
virNetMessagePtr msg);
static void
daemonStreamUpdateEvents(daemonClientStream *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);
}
/*
* 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
*/
static void
daemonStreamMessageFinished(virNetMessagePtr msg ATTRIBUTE_UNUSED,
void *opaque)
{
daemonClientStream *stream = opaque;
VIR_DEBUG("stream=%p proc=%d serial=%d",
stream, msg->header.proc, msg->header.serial);
stream->tx = 1;
daemonStreamUpdateEvents(stream);
daemonFreeClientStream(NULL, stream);
}
/*
* Callback that gets invoked when a stream becomes writable/readable
*/
static void
daemonStreamEvent(virStreamPtr st, int events, void *opaque)
{
virNetServerClientPtr client = opaque;
daemonClientStream *stream;
daemonClientPrivatePtr priv = virNetServerClientGetPrivateData(client);
virMutexLock(&priv->lock);
stream = priv->streams;
while (stream) {
if (stream->st == st)
break;
stream = stream->next;
}
if (!stream) {
VIR_WARN("event for client=%p stream st=%p, but missing stream state", client, st);
virStreamEventRemoveCallback(st);
goto cleanup;
}
VIR_DEBUG("st=%p events=%d EOF=%d closed=%d", st, events, stream->recvEOF, stream->closed);
if (!stream->closed &&
(events & VIR_STREAM_EVENT_WRITABLE)) {
if (daemonStreamHandleWrite(client, stream) < 0) {
daemonRemoveClientStream(client, stream);
virNetServerClientClose(client);
goto cleanup;
}
}
if (!stream->closed && !stream->recvEOF &&
(events & (VIR_STREAM_EVENT_READABLE))) {
events = events & ~(VIR_STREAM_EVENT_READABLE);
if (daemonStreamHandleRead(client, stream) < 0) {
daemonRemoveClientStream(client, stream);
virNetServerClientClose(client);
goto cleanup;
}
/* If we detected EOF during read processing,
* then clear hangup/error conditions, since
* we want the client to see the EOF message
* we just sent them
*/
if (stream->recvEOF)
events = events & ~(VIR_STREAM_EVENT_HANGUP |
VIR_STREAM_EVENT_ERROR);
}
/* If we have a completion/abort message, always process it */
if (stream->rx) {
virNetMessagePtr msg = stream->rx;
switch (msg->header.status) {
case VIR_NET_CONTINUE:
/* nada */
break;
case VIR_NET_OK:
virNetMessageQueueServe(&stream->rx);
if (daemonStreamHandleFinish(client, stream, msg) < 0) {
virNetMessageFree(msg);
daemonRemoveClientStream(client, stream);
virNetServerClientClose(client);
goto cleanup;
}
break;
case VIR_NET_ERROR:
default:
virNetMessageQueueServe(&stream->rx);
if (daemonStreamHandleAbort(client, stream, msg) < 0) {
virNetMessageFree(msg);
daemonRemoveClientStream(client, stream);
virNetServerClientClose(client);
goto cleanup;
}
break;
}
}
/* If we got HANGUP, we need to only send an empty
* packet so the client sees an EOF and cleans up
*/
if (!stream->closed && !stream->recvEOF &&
(events & VIR_STREAM_EVENT_HANGUP)) {
virNetMessagePtr msg;
events &= ~(VIR_STREAM_EVENT_HANGUP);
stream->tx = 0;
stream->recvEOF = 1;
if (!(msg = virNetMessageNew(false))) {
daemonRemoveClientStream(client, stream);
virNetServerClientClose(client);
goto cleanup;
}
msg->cb = daemonStreamMessageFinished;
msg->opaque = stream;
stream->refs++;
if (virNetServerProgramSendStreamData(remoteProgram,
client,
msg,
stream->procedure,
stream->serial,
"", 0) < 0) {
virNetMessageFree(msg);
daemonRemoveClientStream(client, stream);
virNetServerClientClose(client);
goto cleanup;
}
}
if (!stream->closed &&
(events & (VIR_STREAM_EVENT_ERROR | VIR_STREAM_EVENT_HANGUP))) {
int ret;
virNetMessagePtr msg;
virNetMessageError rerr;
memset(&rerr, 0, sizeof(rerr));
stream->closed = 1;
virStreamEventRemoveCallback(stream->st);
virStreamAbort(stream->st);
if (events & VIR_STREAM_EVENT_HANGUP)
virReportError(VIR_ERR_RPC,
"%s", _("stream had unexpected termination"));
else
virReportError(VIR_ERR_RPC,
"%s", _("stream had I/O failure"));
msg = virNetMessageNew(false);
if (!msg) {
ret = -1;
} else {
ret = virNetServerProgramSendStreamError(remoteProgram,
client,
msg,
&rerr,
stream->procedure,
stream->serial);
}
daemonRemoveClientStream(client, stream);
if (ret < 0)
virNetServerClientClose(client);
goto cleanup;
}
if (stream->closed) {
daemonRemoveClientStream(client, stream);
} else {
daemonStreamUpdateEvents(stream);
}
cleanup:
virMutexUnlock(&priv->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
daemonStreamFilter(virNetServerClientPtr client ATTRIBUTE_UNUSED,
virNetMessagePtr msg,
void *opaque)
{
daemonClientStream *stream = opaque;
int ret = 0;
virMutexLock(&stream->priv->lock);
if (msg->header.type != VIR_NET_STREAM)
goto cleanup;
if (!virNetServerProgramMatches(stream->prog, msg))
goto cleanup;
if (msg->header.proc != stream->procedure ||
msg->header.serial != stream->serial)
goto cleanup;
VIR_DEBUG("Incoming client=%p, rx=%p, serial=%d, proc=%d, status=%d",
client, stream->rx, msg->header.proc,
msg->header.serial, msg->header.status);
virNetMessageQueuePush(&stream->rx, msg);
daemonStreamUpdateEvents(stream);
ret = 1;
cleanup:
virMutexUnlock(&stream->priv->lock);
return ret;
}
/*
* @conn: a connection object to associate the stream with
* @header: the method call to associate with the stream
*
* Creates a new stream for this conn
*
* Returns a new stream object, or NULL upon OOM
*/
daemonClientStream *
daemonCreateClientStream(virNetServerClientPtr client,
virStreamPtr st,
virNetServerProgramPtr prog,
virNetMessageHeaderPtr header)
{
daemonClientStream *stream;
daemonClientPrivatePtr priv = virNetServerClientGetPrivateData(client);
VIR_DEBUG("client=%p, proc=%d, serial=%d, st=%p",
client, header->proc, header->serial, st);
if (VIR_ALLOC(stream) < 0) {
virReportOOMError();
return NULL;
}
stream->refs = 1;
stream->priv = priv;
stream->prog = virObjectRef(prog);
stream->procedure = header->proc;
stream->serial = header->serial;
stream->filterID = -1;
stream->st = st;
return stream;
}
/*
* @stream: an unused client stream
*
* Frees the memory associated with this inactive client
* stream
*/
int daemonFreeClientStream(virNetServerClientPtr client,
daemonClientStream *stream)
{
virNetMessagePtr msg;
int ret = 0;
if (!stream)
return 0;
stream->refs--;
if (stream->refs)
return 0;
VIR_DEBUG("client=%p, proc=%d, serial=%d",
client, stream->procedure, stream->serial);
virObjectUnref(stream->prog);
msg = stream->rx;
while (msg) {
virNetMessagePtr tmp = msg->next;
if (client) {
/* Send a dummy reply to free up 'msg' & unblock client rx */
virNetMessageClear(msg);
msg->header.type = VIR_NET_REPLY;
if (virNetServerClientSendMessage(client, msg) < 0) {
virNetServerClientImmediateClose(client);
virNetMessageFree(msg);
ret = -1;
}
} else {
virNetMessageFree(msg);
}
msg = tmp;
}
virStreamFree(stream->st);
VIR_FREE(stream);
return ret;
}
/*
* @client: a locked client to add the stream to
* @stream: a stream to add
*/
int daemonAddClientStream(virNetServerClientPtr client,
daemonClientStream *stream,
bool transmit)
{
VIR_DEBUG("client=%p, proc=%d, serial=%d, st=%p, transmit=%d",
client, stream->procedure, stream->serial, stream->st, transmit);
daemonClientPrivatePtr priv = virNetServerClientGetPrivateData(client);
if (stream->filterID != -1) {
VIR_WARN("Filter already added to client %p", client);
return -1;
}
if (virStreamEventAddCallback(stream->st, 0,
daemonStreamEvent, client,
virObjectFreeCallback) < 0)
return -1;
virObjectRef(client);
if ((stream->filterID = virNetServerClientAddFilter(client,
daemonStreamFilter,
stream)) < 0) {
virStreamEventRemoveCallback(stream->st);
return -1;
}
if (transmit)
stream->tx = 1;
virMutexLock(&priv->lock);
stream->next = priv->streams;
priv->streams = stream;
daemonStreamUpdateEvents(stream);
virMutexUnlock(&priv->lock);
return 0;
}
/*
* @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
daemonRemoveClientStream(virNetServerClientPtr client,
daemonClientStream *stream)
{
VIR_DEBUG("client=%p, proc=%d, serial=%d, st=%p",
client, stream->procedure, stream->serial, stream->st);
daemonClientPrivatePtr priv = virNetServerClientGetPrivateData(client);
daemonClientStream *curr = priv->streams;
daemonClientStream *prev = NULL;
if (stream->filterID != -1) {
virNetServerClientRemoveFilter(client,
stream->filterID);
stream->filterID = -1;
}
if (!stream->closed) {
virStreamEventRemoveCallback(stream->st);
virStreamAbort(stream->st);
}
while (curr) {
if (curr == stream) {
if (prev)
prev->next = curr->next;
else
priv->streams = curr->next;
return daemonFreeClientStream(client, stream);
}
prev = curr;
curr = curr->next;
}
return -1;
}
void
daemonRemoveAllClientStreams(daemonClientStream *stream)
{
daemonClientStream *tmp;
VIR_DEBUG("stream=%p", stream);
while (stream) {
tmp = stream->next;
if (!stream->closed) {
virStreamEventRemoveCallback(stream->st);
virStreamAbort(stream->st);
}
daemonFreeClientStream(NULL, stream);
VIR_DEBUG("next stream=%p", tmp);
stream = tmp;
}
}
/*
* Returns:
* -1 if fatal error occurred
* 0 if message was fully processed
* 1 if message is still being processed
*/
static int
daemonStreamHandleWriteData(virNetServerClientPtr client,
daemonClientStream *stream,
virNetMessagePtr msg)
{
int ret;
VIR_DEBUG("client=%p, stream=%p, proc=%d, serial=%d, len=%zu, offset=%zu",
client, stream, msg->header.proc, msg->header.serial,
msg->bufferLength, msg->bufferOffset);
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 {
virNetMessageError rerr;
memset(&rerr, 0, sizeof(rerr));
VIR_INFO("Stream send failed");
stream->closed = 1;
return virNetServerProgramSendReplyError(stream->prog,
client,
msg,
&rerr,
&msg->header);
}
return 0;
}
/*
* Process a finish handshake from the client.
*
* Returns a VIR_NET_OK confirmation if successful, or a VIR_NET_ERROR
* if there was a stream error
*
* Returns 0 if successfully sent RPC reply, -1 upon fatal error
*/
static int
daemonStreamHandleFinish(virNetServerClientPtr client,
daemonClientStream *stream,
virNetMessagePtr msg)
{
int ret;
VIR_DEBUG("client=%p, stream=%p, proc=%d, serial=%d",
client, stream, msg->header.proc, msg->header.serial);
stream->closed = 1;
virStreamEventRemoveCallback(stream->st);
ret = virStreamFinish(stream->st);
if (ret < 0) {
virNetMessageError rerr;
memset(&rerr, 0, sizeof(rerr));
return virNetServerProgramSendReplyError(stream->prog,
client,
msg,
&rerr,
&msg->header);
} else {
/* Send zero-length confirm */
return virNetServerProgramSendStreamData(stream->prog,
client,
msg,
stream->procedure,
stream->serial,
NULL, 0);
}
}
/*
* Process an abort request from the client.
*
* Returns 0 if successfully aborted, -1 upon error
*/
static int
daemonStreamHandleAbort(virNetServerClientPtr client,
daemonClientStream *stream,
virNetMessagePtr msg)
{
VIR_DEBUG("client=%p, stream=%p, proc=%d, serial=%d",
client, stream, msg->header.proc, msg->header.serial);
virNetMessageError rerr;
memset(&rerr, 0, sizeof(rerr));
stream->closed = 1;
virStreamEventRemoveCallback(stream->st);
virStreamAbort(stream->st);
if (msg->header.status == VIR_NET_ERROR)
virReportError(VIR_ERR_RPC,
"%s", _("stream aborted at client request"));
else {
VIR_WARN("unexpected stream status %d", msg->header.status);
virReportError(VIR_ERR_RPC,
_("stream aborted with unexpected status %d"),
msg->header.status);
}
return virNetServerProgramSendReplyError(remoteProgram,
client,
msg,
&rerr,
&msg->header);
}
/*
* 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
daemonStreamHandleWrite(virNetServerClientPtr client,
daemonClientStream *stream)
{
VIR_DEBUG("client=%p, stream=%p", client, stream);
while (stream->rx && !stream->closed) {
virNetMessagePtr msg = stream->rx;
int ret;
switch (msg->header.status) {
case VIR_NET_OK:
ret = daemonStreamHandleFinish(client, stream, msg);
break;
case VIR_NET_CONTINUE:
ret = daemonStreamHandleWriteData(client, stream, msg);
break;
case VIR_NET_ERROR:
default:
ret = daemonStreamHandleAbort(client, stream, msg);
break;
}
if (ret > 0)
break; /* still processing data from msg */
virNetMessageQueueServe(&stream->rx);
if (ret < 0) {
virNetMessageFree(msg);
virNetServerClientImmediateClose(client);
return -1;
}
/* 'CONTINUE' messages don't send a reply (unless error
* occurred), so to release the 'msg' object we need to
* send a fake zero-length reply. Nothing actually gets
* onto the wire, but this causes the client to reset
* its active request count / throttling
*/
if (msg->header.status == VIR_NET_CONTINUE) {
virNetMessageClear(msg);
msg->header.type = VIR_NET_REPLY;
if (virNetServerClientSendMessage(client, msg) < 0) {
virNetMessageFree(msg);
virNetServerClientImmediateClose(client);
return -1;
}
}
}
return 0;
}
/*
* Invoked when a stream is signalled as having data
* available to read. This reads up to 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
daemonStreamHandleRead(virNetServerClientPtr client,
daemonClientStream *stream)
{
char *buffer;
size_t bufferLen = VIR_NET_MESSAGE_PAYLOAD_MAX;
int ret;
VIR_DEBUG("client=%p, stream=%p tx=%d closed=%d",
client, stream, stream->tx, stream->closed);
/* We might have had an event pending before we shut
* down the stream, so if we're marked as closed,
* then do nothing
*/
if (stream->closed)
return 0;
/* 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) {
virNetMessagePtr msg;
virNetMessageError rerr;
memset(&rerr, 0, sizeof(rerr));
if (!(msg = virNetMessageNew(false)))
ret = -1;
else
ret = virNetServerProgramSendStreamError(remoteProgram,
client,
msg,
&rerr,
stream->procedure,
stream->serial);
} else {
virNetMessagePtr msg;
stream->tx = 0;
if (ret == 0)
stream->recvEOF = 1;
if (!(msg = virNetMessageNew(false)))
ret = -1;
if (msg) {
msg->cb = daemonStreamMessageFinished;
msg->opaque = stream;
stream->refs++;
ret = virNetServerProgramSendStreamData(remoteProgram,
client,
msg,
stream->procedure,
stream->serial,
buffer, ret);
}
}
VIR_FREE(buffer);
return ret;
}

51
daemon/stream.h Normal file
View File

@ -0,0 +1,51 @@
/*
* 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, see
* <http://www.gnu.org/licenses/>.
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#ifndef __LIBVIRTD_STREAM_H__
# define __LIBVIRTD_STREAM_H__
# include "libvirtd.h"
daemonClientStream *
daemonCreateClientStream(virNetServerClientPtr client,
virStreamPtr st,
virNetServerProgramPtr prog,
virNetMessageHeaderPtr hdr);
int daemonFreeClientStream(virNetServerClientPtr client,
daemonClientStream *stream);
int daemonAddClientStream(virNetServerClientPtr client,
daemonClientStream *stream,
bool transmit);
int
daemonRemoveClientStream(virNetServerClientPtr client,
daemonClientStream *stream);
void
daemonRemoveAllClientStreams(daemonClientStream *stream);
#endif /* __LIBVIRTD_STREAM_H__ */

View File

@ -0,0 +1,49 @@
module Test_libvirtd =
::CONFIG::
test Libvirtd.lns get conf =
{ "listen_tls" = "0" }
{ "listen_tcp" = "1" }
{ "tls_port" = "16514" }
{ "tcp_port" = "16509" }
{ "listen_addr" = "192.168.0.1" }
{ "mdns_adv" = "1" }
{ "mdns_name" = "Virtualization Host Joe Demo" }
{ "unix_sock_group" = "libvirt" }
{ "unix_sock_ro_perms" = "0777" }
{ "unix_sock_rw_perms" = "0770" }
{ "unix_sock_dir" = "/var/run/libvirt" }
{ "auth_unix_ro" = "none" }
{ "auth_unix_rw" = "none" }
{ "auth_tcp" = "sasl" }
{ "auth_tls" = "none" }
{ "key_file" = "/etc/pki/libvirt/private/serverkey.pem" }
{ "cert_file" = "/etc/pki/libvirt/servercert.pem" }
{ "ca_file" = "/etc/pki/CA/cacert.pem" }
{ "crl_file" = "/etc/pki/CA/crl.pem" }
{ "tls_no_sanity_certificate" = "1" }
{ "tls_no_verify_certificate" = "1" }
{ "tls_allowed_dn_list"
{ "1" = "DN1"}
{ "2" = "DN2"}
}
{ "sasl_allowed_username_list"
{ "1" = "joe@EXAMPLE.COM" }
{ "2" = "fred@EXAMPLE.COM" }
}
{ "max_clients" = "20" }
{ "min_workers" = "5" }
{ "max_workers" = "20" }
{ "prio_workers" = "5" }
{ "max_requests" = "20" }
{ "max_client_requests" = "5" }
{ "log_level" = "3" }
{ "log_filters" = "3:remote 4:event" }
{ "log_outputs" = "3:syslog:libvirtd" }
{ "log_buffer_size" = "64" }
{ "audit_level" = "2" }
{ "audit_logging" = "1" }
{ "host_uuid" = "00000000-0000-0000-0000-000000000000" }
{ "keepalive_interval" = "5" }
{ "keepalive_count" = "5" }
{ "keepalive_required" = "1" }

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<?xml version="1.0"?>
<html>
<body>
<h1>404 page not found</h1>
@ -9,11 +8,16 @@
page you were looking for. You might want to try
</p>
<ul>
<li>going back to the <a href="https://libvirt.org/">home page</a> to find
<li>going back to the <a href="http://libvirt.org/">home page</a> to find
a collection of links to interesting pages on this site</li>
<li>using the search box at the top right corner of the screen to
locate the content on this site or mailing list archives</li>
</ul>
<p class="image">
<img src="/libvirtLogo404.png" alt="libvirt Logo"/>
</p>
</body>
</html>

View File

@ -1,108 +1,66 @@
## Process this file with automake to produce Makefile.in
## Copyright (C) 2005-2016 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, see
## <http://www.gnu.org/licenses/>.
## Copyright (C) 2005-2012 Red Hat, Inc.
## See COPYING.LIB for the License of this software
SUBDIRS= schemas
PERL = perl
# 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 \
$(apihtml_generated)
BUILT_SOURCES=hvsupport.html.in
apihtml_generated = \
html/libvirt-libvirt-common.html \
html/libvirt-libvirt-domain.html \
html/libvirt-libvirt-domain-snapshot.html \
html/libvirt-libvirt-event.html \
html/libvirt-libvirt-host.html \
html/libvirt-libvirt-interface.html \
html/libvirt-libvirt-network.html \
html/libvirt-libvirt-nodedev.html \
html/libvirt-libvirt-nwfilter.html \
html/libvirt-libvirt-secret.html \
html/libvirt-libvirt-storage.html \
html/libvirt-libvirt-stream.html \
apihtml = \
html/index.html \
html/libvirt-libvirt.html \
html/libvirt-virterror.html
apipng = \
html/left.png \
html/up.png \
html/home.png \
apipng = \
html/left.png \
html/up.png \
html/home.png \
html/right.png
devhelphtml = \
devhelp/libvirt.devhelp \
devhelp/index.html \
devhelp/general.html \
devhelphtml = \
devhelp/libvirt.devhelp \
devhelp/index.html \
devhelp/general.html \
devhelp/libvirt-libvirt.html \
devhelp/libvirt-virterror.html
css = \
css = \
generic.css \
libvirt.css \
mobile.css \
main.css
fonts = \
fonts/LICENSE.md \
fonts/stylesheet.css \
fonts/overpass-bold-italic.woff \
fonts/overpass-bold.woff \
fonts/overpass-italic.woff \
fonts/overpass-light-italic.woff \
fonts/overpass-light.woff \
fonts/overpass-mono-bold.woff \
fonts/overpass-mono-light.woff \
fonts/overpass-mono-regular.woff \
fonts/overpass-mono-semibold.woff \
fonts/overpass-regular.woff
devhelppng = \
devhelp/home.png \
devhelp/left.png \
devhelp/right.png \
devhelppng = \
devhelp/home.png \
devhelp/left.png \
devhelp/right.png \
devhelp/up.png
devhelpcss = devhelp/style.css
devhelpxsl = devhelp/devhelp.xsl devhelp/html.xsl
logofiles = \
logos/logo-base.svg \
logos/logo-square.svg \
logos/logo-square-powered.svg \
logos/logo-banner-dark.svg \
logos/logo-banner-light.svg \
logos/logo-square-96.png \
logos/logo-square-128.png \
logos/logo-square-192.png \
logos/logo-square-256.png \
logos/logo-square-powered-96.png \
logos/logo-square-powered-128.png \
logos/logo-square-powered-192.png \
logos/logo-square-powered-256.png \
logos/logo-banner-dark-256.png \
logos/logo-banner-dark-800.png \
logos/logo-banner-light-256.png \
logos/logo-banner-light-800.png
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 \
migration-managed-direct.png \
migration-managed-p2p.png \
migration-native.png \
@ -118,20 +76,17 @@ internals_html_in = \
$(patsubst $(srcdir)/%,%,$(wildcard $(srcdir)/internals/*.html.in))
internals_html = $(internals_html_in:%.html.in=%.html)
# Since we ship pre-built html in the tarball, we must also
# ship the sources, even when those sources are themselves
# generated.
# Generate hvsupport.html and news.html first, since they take one extra step.
dot_html_in = \
hvsupport.html.in \
news.html.in \
$(notdir $(wildcard $(srcdir)/*.html.in))
dot_html_in = $(notdir $(wildcard $(srcdir)/*.html.in)) \
todo.html.in \
hvsupport.html.in
dot_html = $(dot_html_in:%.html.in=%.html)
dot_php_in = $(notdir $(wildcard $(srcdir)/*.php.in))
dot_php_code_in = $(dot_php_in:%.php.in=%.php.code.in)
dot_php = $(dot_php_in:%.php.in=%.php)
patches = $(patsubst $(srcdir)/%,%,$(wildcard $(srcdir)/api_extension/*.patch))
xml = \
libvirt-api.xml \
libvirt-refs.xml
@ -144,18 +99,12 @@ lxc_xml = \
libvirt-lxc-api.xml \
libvirt-lxc-refs.xml
admin_xml = \
libvirt-admin-api.xml \
libvirt-admin-refs.xml
apidir = $(pkgdatadir)/api
api_DATA = \
libvirt-api.xml \
libvirt-qemu-api.xml \
libvirt-lxc-api.xml \
libvirt-admin-api.xml
api_DATA = libvirt-api.xml libvirt-qemu-api.xml libvirt-lxc-api.xml
fig = \
libvirt-net-logical.fig \
libvirt-net-physical.fig \
libvirt-daemon-arch.fig \
libvirt-driver-arch.fig \
libvirt-object-model.fig \
@ -165,137 +114,120 @@ fig = \
migration-tunnel.fig \
migration-unmanaged-direct.fig
schemadir = $(pkgdatadir)/schemas
schema_DATA = $(wildcard $(srcdir)/schemas/*.rng)
EXTRA_DIST= \
apibuild.py genaclperms.pl \
site.xsl subsite.xsl newapi.xsl page.xsl \
wrapstring.xsl \
EXTRA_DIST= \
apibuild.py \
site.xsl newapi.xsl news.xsl page.xsl \
hacking1.xsl hacking2.xsl wrapstring.xsl \
$(dot_html) $(dot_html_in) $(gif) $(apihtml) $(apipng) \
$(devhelphtml) $(devhelppng) $(devhelpcss) $(devhelpxsl) \
$(xml) $(qemu_xml) $(lxc_xml) $(admin_xml) $(fig) $(png) $(css) \
$(logofiles) $(dot_php_in) $(dot_php_code_in) $(dot_php)\
$(internals_html_in) $(internals_html) $(fonts) \
aclperms.htmlinc \
hvsupport.pl \
$(schema_DATA)
acl_generated = aclperms.htmlinc
$(srcdir)/aclperms.htmlinc: $(top_srcdir)/src/access/viraccessperm.h \
$(srcdir)/genaclperms.pl Makefile.am
$(AM_V_GEN)$(PERL) $(srcdir)/genaclperms.pl $< > $@
$(xml) $(qemu_xml) $(lxc_xml) $(fig) $(png) $(css) \
$(patches) $(dot_php_in) $(dot_php_code_in) $(dot_php)\
$(internals_html_in) $(internals_html) \
sitemap.html.in \
todo.pl hvsupport.pl todo.cfg-example
MAINTAINERCLEANFILES = \
$(addprefix $(srcdir)/,$(dot_html)) \
$(addprefix $(srcdir)/,$(apihtml)) \
$(addprefix $(srcdir)/,$(devhelphtml)) \
$(addprefix $(srcdir)/,$(internals_html)) \
$(addprefix $(srcdir)/,$(dot_php)) \
$(srcdir)/hvsupport.html.in $(srcdir)/aclperms.htmlinc
timestamp="$(shell if test -n "$$SOURCE_DATE_EPOCH"; \
then \
date -u --date="@$$SOURCE_DATE_EPOCH"; \
else \
date -u; \
fi)"
$(addprefix $(srcdir)/,$(dot_php))
all-am: web
api: $(srcdir)/libvirt-api.xml $(srcdir)/libvirt-refs.xml
qemu_api: $(srcdir)/libvirt-qemu-api.xml $(srcdir)/libvirt-qemu-refs.xml
lxc_api: $(srcdir)/libvirt-lxc-api.xml $(srcdir)/libvirt-lxc-refs.xml
admin_api: $(srcdir)/libvirt-admin-api.xml $(srcdir)/libvirt-admin-refs.xml
web: $(dot_html) $(internals_html) html/index.html devhelp/index.html \
$(dot_php)
hvsupport.html: $(srcdir)/hvsupport.html.in
todo.html.in: todo.pl
if [ -f todo.cfg ]; then \
echo "Generating $@"; \
$(PERL) $< > $@ \
|| { rm $@ && exit 1; }; \
else \
echo "Stubbing $@"; \
echo "<html><body><h1>Todo list</h1></body></html>" > $@ ; \
fi
$(srcdir)/hvsupport.html.in: $(srcdir)/hvsupport.pl $(api_DATA) \
$(top_srcdir)/src/libvirt_public.syms \
$(top_srcdir)/src/libvirt_qemu.syms $(top_srcdir)/src/libvirt_lxc.syms \
$(top_srcdir)/src/driver.h
$(AM_V_GEN)$(PERL) $(srcdir)/hvsupport.pl $(top_srcdir)/src > $@ \
|| { rm $@ && exit 1; }
todo:
rm -f todo.html.in
$(MAKE) todo.html
# xsltproc seems to add the xmlns="" attribute to random output elements:
# use sed to strip it out, as leaving it there triggers XML errors during
# further transformation steps
news.html.in: \
$(srcdir)/news.xml \
$(srcdir)/news-html.xsl
$(AM_V_GEN)$(XSLTPROC) --nonet \
$(srcdir)/news-html.xsl \
$(srcdir)/news.xml \
>$@-tmp \
|| { rm -f $@-tmp; exit 1; }; \
sed 's/ xmlns=""//g' $@-tmp >$@ \
|| { rm -f $@-tmp; exit 1; }; \
rm -f $@-tmp
EXTRA_DIST += \
$(srcdir)/news.xml \
$(srcdir)/news.rng \
$(srcdir)/news-html.xsl
MAINTAINERCLEANFILES += \
$(srcdir)/news.html.in
hvsupport.html.in: $(srcdir)/hvsupport.pl $(srcdir)/../src/libvirt_public.syms \
$(srcdir)/../src/libvirt_qemu.syms $(srcdir)/../src/libvirt_lxc.syms \
$(srcdir)/../src/driver.h
$(AM_V_GEN)$(PERL) $(srcdir)/hvsupport.pl $(srcdir)/../src > $@ || { rm $@ && exit 1; }
.PHONY: todo
%.png: %.fig
convert -rotate 90 $< $@
%.html.tmp: %.html.in site.xsl subsite.xsl page.xsl \
$(acl_generated)
$(AM_V_GEN)name=`echo $@ | sed -e 's/.tmp//'`; \
dir=`dirname $@` ; \
if test "$$dir" = "."; \
then \
style=site.xsl; \
else \
$(MKDIR_P) $$dir; \
style=subsite.xsl; \
fi; \
$(XSLTPROC) --stringparam pagename $$name \
--stringparam timestamp $(timestamp) --nonet \
$(top_srcdir)/docs/$$style $< > $@ \
|| { rm $@ && exit 1; }
internals/%.html.tmp: internals/%.html.in subsite.xsl page.xsl sitemap.html.in
@if [ -x $(XSLTPROC) ] ; then \
echo "Generating $@"; \
$(MKDIR_P) internals; \
name=`echo $@ | sed -e 's/.tmp//'`; \
$(XSLTPROC) --stringparam pagename $$name --nonet --html \
$(top_srcdir)/docs/subsite.xsl $< > $@ \
|| { rm $@ && exit 1; }; fi
%.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
$(AM_V_GEN)$(XMLLINT) --nonet --format $< > $(srcdir)/$@ \
|| { rm $(srcdir)/$@ && exit 1; }
@if test -x $(XMLLINT) && test -x $(XMLCATALOG) ; then \
if $(XMLCATALOG) '$(XML_CATALOG_FILE)' \
"-//W3C//DTD XHTML 1.0 Strict//EN" > /dev/null ; then \
echo "Validating $@" ; \
SGML_CATALOG_FILES='$(XML_CATALOG_FILE)' \
$(XMLLINT) --catalogs --nonet --format --valid $< > $(srcdir)/$@ \
|| { rm $(srcdir)/$@ && exit 1; }; \
else echo "missing XHTML1 DTD" ; fi ; fi
%.php.tmp: %.php.in site.xsl page.xsl
$(AM_V_GEN)$(XSLTPROC) --stringparam pagename $(@:.tmp=) \
--stringparam timestamp $(timestamp) --nonet \
%.php.tmp: %.php.in site.xsl page.xsl sitemap.html.in
@if [ -x $(XSLTPROC) ] ; then \
echo "Generating $@"; \
$(XSLTPROC) --stringparam pagename $(@:.tmp=) --nonet --html \
$(top_srcdir)/docs/site.xsl $< > $@ \
|| { rm $@ && exit 1; }
|| { rm $@ && exit 1; }; fi
%.php: %.php.tmp %.php.code.in
$(AM_V_GEN)sed \
-e '/<span id="php_placeholder"><\/span>/r '"$(srcdir)/$@.code.in" \
@if [ -x $(XSLTPROC) ] ; then \
echo "Scripting $@"; \
sed -e '/<a id="php_placeholder"><\/a>/r '"$(srcdir)/$@.code.in" \
-e /php_placeholder/d < $@.tmp > $(srcdir)/$@ \
|| { rm $(srcdir)/$@ && exit 1; }
|| { rm $(srcdir)/$@ && exit 1; }; fi
$(apihtml_generated): html/index.html
html/index.html: libvirt-api.xml newapi.xsl page.xsl $(APIBUILD_STAMP)
$(AM_V_GEN)$(XSLTPROC) --nonet -o $(srcdir)/ \
--stringparam builddir '$(abs_top_builddir)' \
--stringparam timestamp $(timestamp) \
$(srcdir)/newapi.xsl $(srcdir)/libvirt-api.xml && \
$(XMLLINT) --nonet --noout $(srcdir)/html/*.html
html/index.html: libvirt-api.xml newapi.xsl page.xsl sitemap.html.in
$(AM_V_GEN)if [ -x $(XSLTPROC) ] ; then \
$(XSLTPROC) --nonet -o $(srcdir)/ \
$(srcdir)/newapi.xsl $(srcdir)/libvirt-api.xml ; fi && \
if test -x $(XMLLINT) && test -x $(XMLCATALOG) ; then \
if $(XMLCATALOG) '$(XML_CATALOG_FILE)' "-//W3C//DTD XHTML 1.0 Strict//EN" \
> /dev/null ; then \
SGML_CATALOG_FILES='$(XML_CATALOG_FILE)' \
$(XMLLINT) --catalogs --nonet --valid --noout $(srcdir)/html/*.html ; \
else echo "missing XHTML1 DTD" ; fi ; fi
$(addprefix $(srcdir)/,$(devhelphtml)): $(srcdir)/libvirt-api.xml $(devhelpxsl)
$(AM_V_GEN)$(XSLTPROC) --stringparam timestamp $(timestamp) \
--nonet -o $(srcdir)/devhelp/ \
$(top_srcdir)/docs/devhelp/devhelp.xsl $(srcdir)/libvirt-api.xml
$(AM_V_GEN)if [ -x $(XSLTPROC) ] ; then \
$(XSLTPROC) --nonet -o $(srcdir)/devhelp/ \
$(top_srcdir)/docs/devhelp/devhelp.xsl $(srcdir)/libvirt-api.xml ; fi
python_generated_files = \
$(srcdir)/html/libvirt-libvirt.html \
$(srcdir)/html/libvirt-libvirt-lxc.html \
$(srcdir)/html/libvirt-libvirt-qemu.html \
$(srcdir)/html/libvirt-libvirt-admin.html \
$(srcdir)/html/libvirt-virterror.html \
$(srcdir)/libvirt-api.xml \
$(srcdir)/libvirt-refs.xml \
@ -303,8 +235,6 @@ python_generated_files = \
$(srcdir)/libvirt-lxc-refs.xml \
$(srcdir)/libvirt-qemu-api.xml \
$(srcdir)/libvirt-qemu-refs.xml \
$(srcdir)/libvirt-admin-api.xml \
$(srcdir)/libvirt-admin-refs.xml \
$(NULL)
APIBUILD=$(srcdir)/apibuild.py
@ -314,66 +244,37 @@ EXTRA_DIST += $(APIBUILD_STAMP)
$(python_generated_files): $(APIBUILD_STAMP)
$(APIBUILD_STAMP): $(srcdir)/apibuild.py \
$(top_srcdir)/include/libvirt/libvirt.h \
$(top_srcdir)/include/libvirt/libvirt-common.h.in \
$(top_srcdir)/include/libvirt/libvirt-domain-snapshot.h \
$(top_srcdir)/include/libvirt/libvirt-domain.h \
$(top_srcdir)/include/libvirt/libvirt-event.h \
$(top_srcdir)/include/libvirt/libvirt-host.h \
$(top_srcdir)/include/libvirt/libvirt-interface.h \
$(top_srcdir)/include/libvirt/libvirt-network.h \
$(top_srcdir)/include/libvirt/libvirt-nodedev.h \
$(top_srcdir)/include/libvirt/libvirt-nwfilter.h \
$(top_srcdir)/include/libvirt/libvirt-secret.h \
$(top_srcdir)/include/libvirt/libvirt-storage.h \
$(top_srcdir)/include/libvirt/libvirt-stream.h \
$(top_srcdir)/include/libvirt/libvirt-lxc.h \
$(top_srcdir)/include/libvirt/libvirt-qemu.h \
$(top_srcdir)/include/libvirt/libvirt-admin.h \
$(top_srcdir)/include/libvirt/virterror.h \
$(top_srcdir)/src/libvirt.c \
$(top_srcdir)/src/libvirt-domain-snapshot.c \
$(top_srcdir)/src/libvirt-domain.c \
$(top_srcdir)/src/libvirt-host.c \
$(top_srcdir)/src/libvirt-interface.c \
$(top_srcdir)/src/libvirt-network.c \
$(top_srcdir)/src/libvirt-nodedev.c \
$(top_srcdir)/src/libvirt-nwfilter.c \
$(top_srcdir)/src/libvirt-secret.c \
$(top_srcdir)/src/libvirt-storage.c \
$(top_srcdir)/src/libvirt-stream.c \
$(top_srcdir)/src/libvirt-lxc.c \
$(top_srcdir)/src/libvirt-qemu.c \
$(top_srcdir)/src/libvirt-admin.c \
$(top_srcdir)/src/util/virerror.c \
$(top_srcdir)/src/util/virevent.c \
$(top_srcdir)/src/util/virtypedparam.c
$(AM_V_GEN)srcdir=$(srcdir) builddir=$(builddir) $(PYTHON) $(APIBUILD)
$(srcdir)/../include/libvirt/libvirt.h.in \
$(srcdir)/../include/libvirt/libvirt-lxc.h \
$(srcdir)/../include/libvirt/libvirt-qemu.h \
$(srcdir)/../include/libvirt/virterror.h \
$(srcdir)/../src/libvirt.c \
$(srcdir)/../src/libvirt-lxc.c \
$(srcdir)/../src/libvirt-qemu.c \
$(srcdir)/../src/util/virerror.c \
$(srcdir)/../src/util/virevent.c \
$(srcdir)/../src/util/virtypedparam.c
$(AM_V_GEN)srcdir=$(srcdir) $(PYTHON) $(APIBUILD)
touch $@
check-local: all
dist-local: all
clean-local:
rm -f *~ *.bak *.hierarchy *.signals *-unused.txt *.html html/*.html
rm -f *~ *.bak *.hierarchy *.signals *-unused.txt *.html
maintainer-clean-local: clean-local
rm -rf $(srcdir)/libvirt-api.xml $(srcdir)/libvirt-refs.xml
rm -rf $(srcdir)/libvirt-api.xml $(srcdir)/libvirt-refs.xml todo.html.in hvsupport.html.in
rm -rf $(srcdir)/libvirt-qemu-api.xml $(srcdir)/libvirt-qemu-refs.xml
rm -rf $(srcdir)/libvirt-lxc-api.xml $(srcdir)/libvirt-lxc-refs.xml
rm -rf $(srcdir)/libvirt-admin-api.xml $(srcdir)/libvirt-admin-refs.xml
rm -rf $(APIBUILD_STAMP)
rebuild: api qemu_api lxc_api admin_api all
rebuild: api qemu_api lxc_api all
install-data-local:
$(mkinstalldirs) $(DESTDIR)$(HTML_DIR)
for f in $(css) $(dot_html) $(gif) $(png); do \
$(INSTALL) -m 0644 $(srcdir)/$$f $(DESTDIR)$(HTML_DIR); done
$(mkinstalldirs) $(DESTDIR)$(HTML_DIR)/logos
for f in $(logofiles); do \
$(INSTALL) -m 0644 $(srcdir)/$$f $(DESTDIR)$(HTML_DIR)/logos; done
$(mkinstalldirs) $(DESTDIR)$(HTML_DIR)/html
for h in $(apihtml); do \
$(INSTALL) -m 0644 $(srcdir)/$$h $(DESTDIR)$(HTML_DIR)/html; done
@ -386,23 +287,11 @@ install-data-local:
for file in $(devhelphtml) $(devhelppng) $(devhelpcss); do \
$(INSTALL) -m 0644 $(srcdir)/$${file} $(DESTDIR)$(DEVHELP_DIR) ; \
done
$(mkinstalldirs) $(DESTDIR)$(HTML_DIR)/fonts
for f in $(fonts); do \
$(INSTALL) -m 0644 $(srcdir)/$$f $(DESTDIR)$(HTML_DIR)/fonts; \
done
$(INSTALL_DATA) $(srcdir)/libvirtLogo.png $(DESTDIR)$(pkgdatadir)
uninstall-local:
for f in $(css) $(dot_html) $(gif) $(png) $(fonts); do \
rm -f $(DESTDIR)$(HTML_DIR)/$$f; \
done
for f in $(logofiles); do \
rm -f $(DESTDIR)$(HTML_DIR)/$$f; \
done
for h in $(apihtml); do rm -f $(DESTDIR)$(HTML_DIR)/$$h; done
for p in $(apipng); do rm -f $(DESTDIR)$(HTML_DIR)/$$p; done
for f in $(internals_html); do \
rm -f $(DESTDIR)$(HTML_DIR)/$$f; \
done
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 -f $(DESTDIR)$(DEVHELP_DIR)/$$(basename $$f); \
rm $(DESTDIR)$(DEVHELP_DIR)/$$(basename $$f); \
done

View File

@ -1,100 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<h1>Client access control</h1>
<p>
Libvirt's client access control framework allows administrators
to setup fine grained permission rules across client users,
managed objects and API operations. This allows client connections
to be locked down to a minimal set of privileges.
</p>
<ul id="toc"></ul>
<h2><a id="intro">Access control introduction</a></h2>
<p>
In a default configuration, the libvirtd daemon has three levels
of access control. All connections start off in an unauthenticated
state, where the only API operations allowed are those required
to complete authentication. After successful authentication, a
connection either has full, unrestricted access to all libvirt
API calls, or is locked down to only "read only" operations,
according to what socket a client connection originated on.
</p>
<p>
The access control framework allows authenticated connections to
have fine grained permission rules to be defined by the administrator.
Every API call in libvirt has a set of permissions that will
be validated against the object being used. For example, the
<code>virDomainSetSchedulerParametersFlags</code> method will
check whether the client user has the <code>write</code>
permission on the <code>domain</code> object instance passed
in as a parameter. Further permissions will also be checked
if certain flags are set in the API call. In addition to
checks on the object passed in to an API call, some methods
will filter their results. For example the <code>virConnectListAllDomains</code>
method will check the <code>search_domains</code> on the <code>connect</code>
object, but will also filter the returned <code>domain</code>
objects to only those on which the client user has the
<code>getattr</code> permission.
</p>
<h2><a id="drivers">Access control drivers</a></h2>
<p>
The access control framework is designed as a pluggable
system to enable future integration with arbitrary access
control technologies. By default, the <code>none</code>
driver is used, which does no access control checks at
all. At this time, libvirt ships with support for using
<a href="http://www.freedesktop.org/wiki/Software/polkit/">polkit</a> as a real access
control driver. To learn how to use the polkit access
driver consult <a href="aclpolkit.html">the configuration
docs</a>.
</p>
<p>
The access driver is configured in the <code>libvirtd.conf</code>
configuration file, using the <code>access_drivers</code>
parameter. This parameter accepts an array of access control
driver names. If more than one access driver is requested,
then all must succeed in order for access to be granted.
To enable 'polkit' as the driver:
</p>
<pre>
# augtool -s set '/files/etc/libvirt/libvirtd.conf/access_drivers[1]' polkit
</pre>
<p>
And to reset back to the default (no-op) driver
</p>
<pre>
# augtool -s rm /files/etc/libvirt/libvirtd.conf/access_drivers
</pre>
<p>
<strong>Note:</strong> changes to libvirtd.conf require that
the libvirtd daemon be restarted.
</p>
<h2><a id="perms">Objects and permissions</a></h2>
<p>
Libvirt applies access control to all the main object
types in its API. Each object type, in turn, has a set
of permissions defined. To determine what permissions
are checked for specific API call, consult the
<a href="html/index.html">API reference manual</a>
documentation for the API in question.
</p>
<div id="include" filename="aclperms.htmlinc"/>
</body>
</html>

View File

@ -1,531 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<h1>Polkit access control</h1>
<p>
Libvirt's client <a href="acl.html">access control framework</a> allows
administrators to setup fine grained permission rules across client users,
managed objects and API operations. This allows client connections
to be locked down to a minimal set of privileges. The polkit driver
provides a simple implementation of the access control framework.
</p>
<ul id="toc"></ul>
<h2><a id="intro">Introduction</a></h2>
<p>
A default install of libvirt will typically use
<a href="http://www.freedesktop.org/wiki/Software/polkit/">polkit</a>
to authenticate the initial user connection to libvirtd. This is a
very coarse grained check though, either allowing full read-write
access to all APIs, or just read-only access. The polkit access
control driver in libvirt builds on this capability to allow for
fine grained control over the operations a user may perform on an
object.
</p>
<h2><a id="perms">Permission names</a></h2>
<p>
The libvirt <a href="acl.html#perms">object names and permission names</a>
are mapped onto polkit action names using the simple pattern:
</p>
<pre>org.libvirt.api.$object.$permission
</pre>
<p>
The only caveat is that any underscore characters in the
object or permission names are converted to hyphens. So,
for example, the <code>search_storage_vols</code> permission
on the <code>storage_pool</code> object maps to the polkit
action:
</p>
<pre>org.libvirt.api.storage-pool.search-storage-vols
</pre>
<p>
The default policy for any permission which corresponds to
a "read only" operation, is to allow access. All other
permissions default to deny access.
</p>
<h2><a id="attrs">Object identity attributes</a></h2>
<p>
To allow polkit authorization rules to be written to match
against individual object instances, libvirt provides a number
of authorization detail attributes when performing a permission
check. The set of attributes varies according to the type
of object being checked
</p>
<h3><a id="object_connect">virConnectPtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>connect_driver</td>
<td>Name of the libvirt connection driver</td>
</tr>
</tbody>
</table>
<h3><a id="object_domain">virDomainPtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>connect_driver</td>
<td>Name of the libvirt connection driver</td>
</tr>
<tr>
<td>domain_name</td>
<td>Name of the domain, unique to the local host</td>
</tr>
<tr>
<td>domain_uuid</td>
<td>UUID of the domain, globally unique</td>
</tr>
</tbody>
</table>
<h3><a id="object_interface">virInterfacePtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>connect_driver</td>
<td>Name of the libvirt connection driver</td>
</tr>
<tr>
<td>interface_name</td>
<td>Name of the network interface, unique to the local host</td>
</tr>
<tr>
<td>interface_macaddr</td>
<td>MAC address of the network interface, not unique</td>
</tr>
</tbody>
</table>
<h3><a id="object_network">virNetworkPtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>connect_driver</td>
<td>Name of the libvirt connection driver</td>
</tr>
<tr>
<td>network_name</td>
<td>Name of the network, unique to the local host</td>
</tr>
<tr>
<td>network_uuid</td>
<td>UUID of the network, globally unique</td>
</tr>
</tbody>
</table>
<h3><a id="object_node_device">virNodeDevicePtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>connect_driver</td>
<td>Name of the libvirt connection driver</td>
</tr>
<tr>
<td>node_device_name</td>
<td>Name of the node device, unique to the local host</td>
</tr>
</tbody>
</table>
<h3><a id="object_nwfilter">virNWFilterPtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>connect_driver</td>
<td>Name of the libvirt connection driver</td>
</tr>
<tr>
<td>nwfilter_name</td>
<td>Name of the network filter, unique to the local host</td>
</tr>
<tr>
<td>nwfilter_uuid</td>
<td>UUID of the network filter, globally unique</td>
</tr>
</tbody>
</table>
<h3><a id="object_secret">virSecretPtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>connect_driver</td>
<td>Name of the libvirt connection driver</td>
</tr>
<tr>
<td>secret_uuid</td>
<td>UUID of the secret, globally unique</td>
</tr>
<tr>
<td>secret_usage_volume</td>
<td>Name of the associated volume, if any</td>
</tr>
<tr>
<td>secret_usage_ceph</td>
<td>Name of the associated Ceph server, if any</td>
</tr>
<tr>
<td>secret_usage_target</td>
<td>Name of the associated iSCSI target, if any</td>
</tr>
<tr>
<td>secret_usage_name</td>
<td>Name of the associated TLS secret, if any</td>
</tr>
</tbody>
</table>
<h3><a id="object_storage_pool">virStoragePoolPtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>connect_driver</td>
<td>Name of the libvirt connection driver</td>
</tr>
<tr>
<td>pool_name</td>
<td>Name of the storage pool, unique to the local host</td>
</tr>
<tr>
<td>pool_uuid</td>
<td>UUID of the storage pool, globally unique</td>
</tr>
</tbody>
</table>
<h3><a id="object_storage_vol">virStorageVolPtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>connect_driver</td>
<td>Name of the libvirt connection driver</td>
</tr>
<tr>
<td>pool_name</td>
<td>Name of the storage pool, unique to the local host</td>
</tr>
<tr>
<td>pool_uuid</td>
<td>UUID of the storage pool, globally unique</td>
</tr>
<tr>
<td>vol_name</td>
<td>Name of the storage volume, unique to the pool</td>
</tr>
<tr>
<td>vol_key</td>
<td>Key of the storage volume, globally unique</td>
</tr>
</tbody>
</table>
<h2><a id="connect_driver">Hypervisor Driver connect_driver</a></h2>
<p>
The <code>connect_driver</code> parameter describes the
client's <a href="remote.html">remote Connection Driver</a>
name based on the <a href="uri.html">URI</a> used for the
connection.
</p>
<p>
<span class="since">Since 4.1.0</span>, when calling an API
outside the scope of the primary connection driver, the
primary driver will attempt to open a secondary connection
to the specific API driver in order to process the API. For
example, when hypervisor domain processing needs to make an
API call within the storage driver or the network filter driver
an attempt to open a connection to the "storage" or "nwfilter"
driver will be made. Similarly, a "storage" primary connection
may need to create a connection to the "secret" driver in order
to process secrets for the API. If successful, then calls to
those API's will occur in the <code>connect_driver</code> context
of the secondary connection driver rather than in the context of
the primary driver. This affects the <code>connect_driver</code>
returned from rule generation from the <code>action.loookup</code>
function. The following table provides a list of the various
connection drivers and the <code>connect_driver</code> name
used by each regardless of primary or secondary connection.
The access denied error message from libvirt will list the
connection driver by name that denied the access.
</p>
<h3><a id="object_connect_driver">Connection Driver Name</a></h3>
<table class="acl">
<thead>
<tr>
<th>Connection Driver</th>
<th><code>connect_driver</code> name</th>
</tr>
</thead>
<tbody>
<tr>
<td>bhyve</td>
<td>bhyve</td>
</tr>
<tr>
<td>esx</td>
<td>ESX</td>
</tr>
<tr>
<td>hyperv</td>
<td>Hyper-V</td>
</tr>
<tr>
<td>interface</td>
<td>interface</td>
</tr>
<tr>
<td>libxl</td>
<td>xenlight</td>
</tr>
<tr>
<td>lxc</td>
<td>LXC</td>
</tr>
<tr>
<td>network</td>
<td>network</td>
</tr>
<tr>
<td>nodedev</td>
<td>nodedev</td>
</tr>
<tr>
<td>nwfilter</td>
<td>NWFilter</td>
</tr>
<tr>
<td>openvz</td>
<td>OPENVZ</td>
</tr>
<tr>
<td>phyp</td>
<td>PHYP</td>
</tr>
<tr>
<td>qemu</td>
<td>QEMU</td>
</tr>
<tr>
<td>secret</td>
<td>secret</td>
</tr>
<tr>
<td>storage</td>
<td>storage</td>
</tr>
<tr>
<td>vbox</td>
<td>VBOX</td>
</tr>
<tr>
<td>vmware</td>
<td>VMWARE</td>
</tr>
<tr>
<td>vz</td>
<td>vz</td>
</tr>
<tr>
<td>xenapi</td>
<td>XenAPI</td>
</tr>
</tbody>
</table>
<h2><a id="user">User identity attributes</a></h2>
<p>
At this point in time, the only attribute provided by
libvirt to identify the user invoking the operation
is the PID of the client program. This means that the
polkit access control driver is only useful if connections
to libvirt are restricted to its UNIX domain socket. If
connections are being made to a TCP socket, no identifying
information is available and access will be denied.
Also note that if the client is connecting via an SSH
tunnel, it is the local SSH user that will be identified.
In future versions, it is expected that more information
about the client user will be provided, including the
SASL / Kerberos username and/or x509 distinguished
name obtained from the authentication provider in use.
</p>
<h2><a id="checks">Writing access control policies</a></h2>
<p>
If using versions of polkit prior to 0.106 then it is only
possible to validate (user, permission) pairs via the <code>.pkla</code>
files. Fully validation of the (user, permission, object) triple
requires the new JavaScript <code>.rules</code> support that
was introduced in version 0.106. The latter is what will be
described here.
</p>
<p>
Libvirt does not ship any rules files by default. It merely
provides a definition of the default behaviour for each
action (permission). As noted earlier, permissions which
correspond to read-only operations in libvirt will be allowed
to all users by default; everything else is denied by default.
Defining custom rules requires creation of a file in the
<code>/etc/polkit-1/rules.d</code> directory with a name
chosen by the administrator (<code>100-libvirt-acl.rules</code>
would be a reasonable choice). See the <code>polkit(8)</code>
manual page for a description of how to write these files
in general. The key idea is to create a file containing
something like
</p>
<pre>
polkit.addRule(function(action, subject) {
....logic to check 'action' and 'subject'...
});
</pre>
<p>
In this code snippet above, the <code>action</code> object
instance will represent the libvirt permission being checked
along with identifying attributes for the object it is being
applied to. The <code>subject</code> meanwhile will identify
the libvirt client app (with the caveat above about it only
dealing with local clients connected via the UNIX socket).
On the <code>action</code> object, the permission name is
accessible via the <code>id</code> attribute, while the
object identifying attributes are exposed via the
<code>lookup</code> method.
</p>
<p>
See
<a href="https://libvirt.org/git/?p=libvirt.git;a=tree;f=examples/polkit;hb=HEAD">source code</a>
for a more complex example.
</p>
<h3><a id="exconnect">Example: restricting ability to connect to drivers</a></h3>
<p>
Consider a local user <code>berrange</code>
who has been granted permission to connect to libvirt in
full read-write mode. The goal is to only allow them to
use the <code>QEMU</code> driver and not the Xen or LXC
drivers which are also available in libvirtd.
To achieve this we need to write a rule which checks
whether the <code>connect_driver</code> attribute
is <code>QEMU</code>, and match on an action
name of <code>org.libvirt.api.connect.getattr</code>. Using
the javascript rules format, this ends up written as
</p>
<pre>
polkit.addRule(function(action, subject) {
if (action.id == "org.libvirt.api.connect.getattr" &amp;&amp;
subject.user == "berrange") {
if (action.lookup("connect_driver") == 'QEMU') {
return polkit.Result.YES;
} else {
return polkit.Result.NO;
}
}
});
</pre>
<h3><a id="exdomain">Example: restricting access to a single domain</a></h3>
<p>
Consider a local user <code>berrange</code>
who has been granted permission to connect to libvirt in
full read-write mode. The goal is to only allow them to
see the domain called <code>demo</code> on the LXC driver.
To achieve this we need to write a rule which checks
whether the <code>connect_driver</code> attribute
is <code>LXC</code> and the <code>domain_name</code>
attribute is <code>demo</code>, and match on an action
name of <code>org.libvirt.api.domain.getattr</code>. Using
the javascript rules format, this ends up written as
</p>
<pre>
polkit.addRule(function(action, subject) {
if (action.id == "org.libvirt.api.domain.getattr" &amp;&amp;
subject.user == "berrange") {
if (action.lookup("connect_driver") == 'LXC' &amp;&amp;
action.lookup("domain_name") == 'demo') {
return polkit.Result.YES;
} else {
return polkit.Result.NO;
}
}
});
</pre>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<?xml version="1.0"?>
<html>
<body>
<h1>The libvirt API concepts</h1>
@ -9,14 +8,14 @@
<ul id="toc"></ul>
<h2><a id="Objects">Objects Exposed</a></h2>
<h2><a name="Objects">Objects Exposed</a></h2>
<p> As defined in the <a href="goals.html">goals section</a>, the libvirt
API is designed to expose all the resources needed to manage the
virtualization support of recent operating systems. The first object
manipulated through the API is the <code>virConnectPtr</code>, which
represents the connection to a hypervisor. Any application using libvirt
is likely to start using the
API by calling one of <a href="html/libvirt-libvirt-host.html#virConnectOpen"
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 a <a href="uri.html">connection URI</a>
to select the right hypervisor to open.
@ -26,10 +25,7 @@
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> OnDevice the application obtains a
<a href="/html/libvirt-libvirt-host.html#virConnectPtr">
<code>virConnectPtr</code>
</a>
<p> Once the application obtains a <code class='docref'>virConnectPtr</code>
connection to the hypervisor it can then use it to manage the hypervisor's
available domains and related virtualization
resources, such as storage and networking. All those are
@ -41,61 +37,33 @@
</p>
<p> The figure above shows the five main objects exported by the API:</p>
<ul>
<li>
<a href="html/libvirt-libvirt-host.html#virConnectPtr">
<code>virConnectPtr</code>
</a>
<li><code class='docref'>virConnectPtr</code>
<p>Represents the connection to a hypervisor. Use one of the
<a href="html/libvirt-libvirt-host.html#virConnectOpen">virConnectOpen</a>
<a href="html/libvirt-libvirt.html#virConnectOpen">virConnectOpen</a>
functions to obtain connection to the hypervisor which is then used
as a parameter to other connection API's.</p></li>
<li>
<a href="html/libvirt-libvirt-domain.html#virDomainPtr">
<code>virDomainPtr</code>
</a>
<li><code class='docref'>virDomainPtr</code>
<p>Represents one domain either active or defined (i.e. existing as
permanent config file and storage but not currently running on that
node). The function
<a href="html/libvirt-libvirt-domain.html#virConnectListAllDomains">
<code>virConnectListAllDomains</code>
</a>
node). The function <code class='docref'>virConnectListAllDomains</code>
lists all the domains for the hypervisor.</p></li>
<li>
<a href="html/libvirt-libvirt-network.html#virNetworkPtr">
<code>virNetworkPtr</code>
</a>
<li><code class='docref'>virNetworkPtr</code>
<p>Represents one network either active or defined (i.e. existing
as permanent config file and storage but not currently activated).
The function
<a href="html/libvirt-libvirt-network.html#virConnectListAllNetworks">
<code>virConnectListAllNetworks</code>
</a>
The function <code class='docref'>virConnectListAllNetworks</code>
lists all the virtualization networks for the hypervisor.</p></li>
<li>
<a href="html/libvirt-libvirt-storage.html#virStorageVolPtr">
<code>virStorageVolPtr</code>
</a>
<li><code class='docref'>virStorageVolPtr</code>
<p>Represents one storage volume generally used
as a block device available to one of the domains. The function
<a href="html/libvirt-libvirt-storage.html#virStorageVolLookupByPath">
<code>virStorageVolLookupByPath</code>
</a>
finds the storage volume object based on its path on the node.</p></li>
<li>
<a href="html/libvirt-libvirt-storage.html#virStoragePoolPtr">
<code>virStoragePoolPtr</code>
</a>
<code class="docref">virStorageVolLookupByPath</code> finds
the storage volume object based on its path on the node.</p></li>
<li><code class='docref'>virStoragePoolPtr</code>
<p>Represents a storage pool, which is a logical area
used to allocate and store storage volumes. The function
<a href="html/libvirt-libvirt-storage.html#virConnectListAllStoragePools">
<code>virConnectListAllStoragePools</code>
</a>
lists all of the virtualization storage pools on the hypervisor.
The function
<a href="html/libvirt-libvirt-storage.html#virStoragePoolLookupByVolume">
<code>virStoragePoolLookupByVolume</code>
</a>
finds the storage pool containing a given storage volume.</p></li>
<code class='docref'>virConnectListAllStoragePools</code> lists
all of the virtualization storage pools on the hypervisor. The function
<code class="docref">virStoragePoolLookupByVolume</code> finds
the storage pool containing a given storage volume.</p></li>
</ul>
<p> Most objects manipulated by the library can also be represented using
XML descriptions. This is used primarily to create those object, but is
@ -121,7 +89,7 @@
set of nodes.</p></li>
</ul>
<h2><a id="Functions">Functions and Naming Conventions</a></h2>
<h2><a name="Functions">Functions and Naming Conventions</a></h2>
<p> The naming of the functions present in the library is usually
composed by a prefix describing the object associated to the function
and a verb describing the action on that object.</p>
@ -132,114 +100,42 @@
<p>Used to perform lookups on objects by some type of identifier,
such as:</p>
<ul>
<li>
<a href="html/libvirt-libvirt-domain.html#virDomainLookupByID">
<code>virDomainLookupByID</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-domain.html#virDomainLookupByName">
<code>virDomainLookupByName</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-domain.html#virDomainLookupByUUID">
<code>virDomainLookupByUUID</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-domain.html#virDomainLookupByUUIDString">
<code>virDomainLookupByUUIDString</code>
</a>
</li>
<li><code class='docref'>virDomainLookupByID</code></li>
<li><code class='docref'>virDomainLookupByName</code></li>
<li><code class='docref'>virDomainLookupByUUID</code></li>
<li><code class='docref'>virDomainLookupByUUIDString</code></li>
</ul>
</li>
<li><b>Enumeration</b> [virConnectList..., virConnectNumOf...]
<p>Used to enumerate a set of object available to a given
<p>Used to enumerate a set of object available to an given
hypervisor connection such as:</p>
<ul>
<li>
<a href="html/libvirt-libvirt-domain.html#virConnectListDomains">
<code>virConnectListDomains</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-domain.html#virConnectNumOfDomains">
<code>virConnectNumOfDomains</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-network.html#virConnectListNetworks">
<code>virConnectListNetworks</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-storage.html#virConnectListStoragePools">
<code>virConnectListStoragePools</code>
</a>
</li>
<li><code class='docref'>virConnectListDomains</code></li>
<li><code class='docref'>virConnectNumOfDomains</code></li>
<li><code class='docref'>virConnectListNetworks</code></li>
<li><code class='docref'>virConnectListStoragePools</code></li>
</ul>
</li>
<li><b>Description</b> [...GetInfo]
<p>Generic accessor providing a set of generic information about an
object, such as: </p>
<ul>
<li>
<a href="html/libvirt-libvirt-host.html#virNodeGetInfo">
<code>virNodeGetInfo</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-domain.html#virDomainGetInfo">
<code>virDomainGetInfo</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-storage.html#virStoragePoolGetInfo">
<code>virStoragePoolGetInfo</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-storage.html#virStorageVolGetInfo">
<code>virStorageVolGetInfo</code>
</a>
</li>
<li><code class='docref'>virNodeGetInfo</code></li>
<li><code class='docref'>virDomainGetInfo</code></li>
<li><code class='docref'>virStoragePoolGetInfo</code></li>
<li><code class='docref'>virStorageVolGetInfo</code></li>
</ul>
</li>
<li><b>Accessors</b> [...Get..., ...Set...]
<p>Specific accessors used to query or modify data for the given object,
such as: </p>
<ul>
<li>
<a href="html/libvirt-libvirt-host.html#virConnectGetType">
<code>virConnectGetType</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-domain.html#virDomainGetMaxMemory">
<code>virDomainGetMaxMemory</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-domain.html#virDomainSetMemory">
<code>virDomainSetMemory</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-domain.html#virDomainGetVcpus">
<code>virDomainGetVcpus</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-storage.html#virStoragePoolSetAutostart">
<code>virStoragePoolSetAutostart</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-network.html#virNetworkGetBridgeName">
<code>virNetworkGetBridgeName</code>
</a>
</li>
<li><code class='docref'>virConnectGetType</code></li>
<li><code class='docref'>virDomainGetMaxMemory</code></li>
<li><code class='docref'>virDomainSetMemory</code></li>
<li><code class='docref'>virDomainGetVcpus</code></li>
<li><code class='docref'>virStoragePoolSetAutostart</code></li>
<li><code class='docref'>virNetworkGetBridgeName</code></li>
</ul>
</li>
<li><b>Creation</b> [...Create, ...CreateXML]
@ -247,65 +143,29 @@
the object based on an XML description, while the ...Create APIs will
create the object based on existing object pointer, such as: </p>
<ul>
<li>
<a href="html/libvirt-libvirt-domain.html#virDomainCreate">
<code>virDomainCreate</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-domain.html#virDomainCreateXML">
<code>virDomainCreateXML</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-network.html#virNetworkCreate">
<code>virNetworkCreate</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-network.html#virNetworkCreateXML">
<code>virNetworkCreateXML</code>
</a>
</li>
<li><code class='docref'>virDomainCreate</code></li>
<li><code class='docref'>virDomainCreateXML</code></li>
<li><code class='docref'>virNetworkCreate</code></li>
<li><code class='docref'>virNetworkCreateXML</code></li>
</ul>
</li>
<li><b>Destruction</b> [...Destroy]
<p>Used to shutdown or deactivate and destroy objects, such as: </p>
<ul>
<li>
<a href="html/libvirt-libvirt-domain.html#virDomainDestroy">
<code>virDomainDestroy</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-network.html#virNetworkDestroy">
<code>virNetworkDestroy</code>
</a>
</li>
<li>
<a href="html/libvirt-libvirt-storage.html#virStoragePoolDestroy">
<code>virStoragePoolDestroy</code>
</a>
</li>
<li><code class='docref'>virDomainDestroy</code></li>
<li><code class='docref'>virNetworkDestroy</code></li>
<li><code class='docref'>virStoragePoolDestroy</code></li>
</ul>
</li>
</ul>
<p>Note: functions returning vir*Ptr (like the virDomainLookup functions)
allocate memory which needs to be freed by the caller by the corresponding
vir*Free function (e.g. virDomainFree for a virDomainPtr object).
</p>
<p> For more in-depth details of the storage related APIs see
<a href="storage.html">the storage management page</a>.
</p>
<h2><a id="Drivers">The libvirt Drivers</a></h2>
<h2><a name="Drivers">The libvirt Drivers</a></h2>
<p>Drivers are the basic building block for libvirt functionality
to support the capability to handle specific hypervisor driver calls.
Drivers are discovered and registered during connection processing as
part of the
<a href="html/libvirt-libvirt-host.html#virInitialize">
<code>virInitialize</code>
</a>
API. Each driver
part of the <code class='docref'>virInitialize</code> API. Each driver
has a registration API which loads up the driver specific function
references for the libvirt APIs to call. The following is a simplistic
view of the hypervisor driver mechanism. Consider the stacked list of
@ -325,19 +185,16 @@
the various functions and support found in each driver by the version
support was added into libvirt.
</p>
<h2><a id="Remote">Daemon and Remote Access</a></h2>
<h2><a name="Remote">Daemon and Remote Access</a></h2>
<p>Access to libvirt drivers is primarily handled by the libvirtd
daemon through the <a href="remote.html">remote</a> driver via an
<a href="internals/rpc.html">RPC</a>. Some hypervisors do support
client-side connections and responses, such as Test, OpenVZ, VMware,
Power VM (phyp), VirtualBox (vbox), ESX, Hyper-V, Xen, and Virtuozzo.
Power VM (phyp), VirtualBox (vbox), ESX, Hyper-V, Xen, and Parallels.
The libvirtd daemon service is started on the host at system boot
time and can also be restarted at any time by a properly privileged
user, such as root. The libvirtd daemon uses the same libvirt API
<a href="html/libvirt-libvirt-host.html#virInitialize">
<code>virInitialize</code>
</a>
sequence as applications
<code class='docref'>virInitialize</code> sequence as applications
for client-side driver registrations, but then extends the registered
driver list to encompass all known drivers supported for all driver
types supported on the host. </p>
@ -349,7 +206,7 @@
virtualization <a href="#Functions">functions</a>. Depending upon the
driver being used, calls will be routed through the remote driver to
the libvirtd daemon. The daemon will reference the connection specific
driver in order to retrieve the requested information and then pass
driver in order to retreive the requested information and then pass
back status and/or data through the connection back to the application.
The application can then decide what to do with that data, such as
display, write log data, etc. <a href="migration.html">Migration</a>

View File

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<html>
<body>
<h1>Implementing a new API in Libvirt</h1>
@ -8,9 +6,14 @@
<p>
This document walks you through the process of implementing a new
API in libvirt. Remember that new API consists of any new public
functions, as well as the addition of flags or extensions of XML used by
existing functions.
API in libvirt. It uses as an example the addition of an API for
separating maximum from current vcpu usage of a domain, over
the course of a fifteen-patch series.
Remember that new API consists of any new public functions, as
well as the addition of flags or extensions of XML used by
existing functions. The example in this document adds both new
functions and an XML extension. Not all libvirt API additions
require quite as many patches.
</p>
<p>
@ -22,7 +25,12 @@
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.
don't wait too long before getting feedback. In the vcpu example
below, list feedback was first requested
<a href="https://www.redhat.com/archives/libvir-list/2010-September/msg00423.html">here</a>
and resulted in several rounds of improvements before coding
began. In turn, this example is slightly rearranged from the actual
order of the commits.
</p>
<p>
@ -34,7 +42,7 @@
</p>
<p>
<a href="https://libvirt.org/downloads.html">https://libvirt.org/downloads.html</a>
<a href="http://libvirt.org/downloads.html">http://libvirt.org/downloads.html</a>
</p>
<p>
@ -71,12 +79,14 @@
</p>
<p>
Submit new code in the form of 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 to break the
changes into pieces so you don't drop a big blob of code on the
mailing list in one go. Also, you should follow the upstream tree, and
rebase your series to adapt your patches to work with any other changes
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 in one go.
Also, you should follow the upstream tree, and rebase your
series to adapt your patches to work with any other changes
that were accepted upstream during your development.
</p>
@ -89,6 +99,8 @@
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. If the new API
@ -96,7 +108,7 @@
schema and document the new elements or attributes:</p>
<p><code>
docs/schemas/domaincommon.rng<br/>
docs/schemas/domain.rng<br/>
docs/formatdomain.html.in
</code></p>
@ -106,7 +118,7 @@
libvirt library and call the new function:</p>
<p><code>
include/libvirt/libvirt-$MODULE.h.in
include/libvirt/libvirt.h.in
src/libvirt_public.syms
</code></p>
@ -119,6 +131,10 @@
rework it as you go through the process of implementing it.
</p>
<p class="example">See <a href="api_extension/0001-add-to-xml.patch">0001-add-to-xml.patch</a>
and <a href="api_extension/0002-add-new-public-API.patch">0002-add-new-public-API.patch</a>
for example code.</p>
<h2><a name='internalapi'>Defining the internal API</a></h2>
<p>
@ -137,7 +153,7 @@
<p>The driver structs are defined in:</p>
<p><code>src/driver-$MODULE.h</code></p>
<p><code>src/driver.h</code></p>
<p>
To define the internal API, first typedef the driver function
@ -146,6 +162,8 @@
provide a <code>NULL</code> stub for the new function.
</p>
<p class="example">See <a href="api_extension/0003-define-internal-driver-API.patch">0003-define-internal-driver-API.patch</a></p>
<h2><a name='implpublic'>Implementing the public API</a></h2>
<p>
@ -160,13 +178,12 @@
being called and its parameters;</li>
<li>MUST call virResetLastError();</li>
<li>SHOULD confirm that the connection is valid with
virCheckConnectReturn() or virCheckConnectGoto();</li>
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 with
virCheckReadOnlyGoto();</strong></li>
indicate that the connection is read-only;</strong></li>
<li>SHOULD do basic validation of the parameters that are being
passed in, using helpers like virCheckNonNullArgGoto();</li>
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>
@ -177,16 +194,22 @@
<p>The public API calls are implemented in:</p>
<p><code>src/libvirt-$MODULE.c</code></p>
<p><code>src/libvirt.c</code></p>
<p class="example">See <a href="api_extension/0004-implement-the-public-APIs.patch">0004-implement-the-public-APIs.patch</a></p>
<h2><a name='remoteproto'>Implementing the remote protocol</a></h2>
<p>
Implementing the remote protocol is essentially a
straightforward exercise which is probably most easily
understood by referring to the existing code.
understood by referring to the existing code and the example
patch. It involves several related changes, including the
regeneration of derived files, with further details below.
</p>
<p class="example">See <a href="api_extension/0005-implement-the-remote-protocol.patch">0005-implement-the-remote-protocol.patch</a></p>
<h3><a name='wireproto'>Defining the wire protocol format</a></h3>
<p>
@ -219,9 +242,9 @@
</p>
<p><code>
src/remote/remote_daemon_dispatch_stubs.h
src/remote/remote_daemon_dispatch.h
src/remote/remote_daemon_dispatch.c
daemon/remote_dispatch_args.h
daemon/remote_dispatch_prototypes.h
daemon/remote_dispatch_table.h
src/remote/remote_protocol.c
src/remote/remote_protocol.h
</code></p>
@ -233,7 +256,7 @@
method calls go in:
</p>
<p><code>src/remote/remote_driver.c</code></p>
<p><code>src/remote/remote_internal.c</code></p>
<p>Each remote method invocation does the following:</p>
@ -247,7 +270,7 @@
<li>unlocks the remote driver.</li>
</ol>
<h3><a id="serverdispatch">Implement the server side dispatcher</a></h3>
<h3><a name="serverdispatch">Implement the server side dispatcher</a></h3>
<p>
Implementing the server side of the remote function call is simply a
@ -256,7 +279,7 @@
The server side dispatchers are implemented in:
</p>
<p><code>src/remote/daemon_dispatch.c</code></p>
<p><code>daemon/remote.c</code></p>
<p>Again, this step uses the .h files generated by make rpcgen.</p>
@ -272,7 +295,9 @@
existing lines probably imply a backwards-incompatible API change.
</p>
<h2><a id="internaluseapi">Use the new API internally</a></h2>
<p class="example">See <a href="api_extension/0005-implement-the-remote-protocol.patch">0005-implement-the-remote-protocol.patch</a></p>
<h2><a name="internaluseapi">Use the new API internally</a></h2>
<p>
Sometimes, a new API serves as a superset of existing API, by
@ -284,7 +309,9 @@
not necessary if the new API has no relation to existing API.
</p>
<h2><a id="virshuseapi">Expose the new API in virsh</a></h2>
<p class="example">See <a href="api_extension/0006-make-old-API-trivially-wrap-to-new-API.patch">0006-make-old-API-trivially-wrap-to-new-API.patch</a></p>
<h2><a name="virshuseapi">Expose the new API in virsh</a></h2>
<p>
All new API should be manageable from the virsh command line
@ -309,11 +336,13 @@
</p>
<p><code>
tools/virsh-$MODULE.c<br/>
tools/virsh.c<br/>
tools/virsh.pod
</code></p>
<h2><a id="driverimpl">Implement the driver methods</a></h2>
<p class="example">See <a href="api_extension/0007-add-virsh-support.patch">0007-add-virsh-support.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
@ -324,7 +353,7 @@
adding.
</p>
<h3><a id="commonimpl">Implement common handling</a></h3>
<h3><a name="commonimpl">Implement common handling</a></h3>
<p>
If the new API is applicable to more than one driver, it may
@ -339,7 +368,9 @@
the same way as the older API wrappers.
</p>
<h3><a id="drivercode">Implement driver handling</a></h3>
<p class="example">See <a href="api_extension/0008-support-new-xml.patch">0008-support-new-xml.patch</a></p>
<h3><a name="drivercode">Implement driver handling</a></h3>
<p>
The remaining patches should only touch one driver at a time.
@ -350,14 +381,41 @@
</p>
<p>
It is always a good idea to patch the test driver in addition to the
target driver, to prove that the API can be used for more than one
driver.
In the example patches, three separate drivers are supported:
test, qemu, and xen. It is always a good idea to patch the test
driver in addition to the target driver, to prove that the API
can be used for more than one driver. The example updates the
test driver in one patch:
</p>
<p class="example">See <a href="api_extension/0009-support-all-flags-in-test-driver.patch">0009-support-all-flags-in-test-driver.patch</a></p>
<p>
Any cleanups resulting from the changes should be added as separate
patches at the end of the series.
The qemu changes were easier to split into two phases, one for
updating the mapping between the new XML and the hypervisor
command line arguments, and one for supporting all possible
flags of the new API:
</p>
<p class="example">See <a href="api_extension/0010-improve-vcpu-support-in-qemu-command-line.patch">0010-improve-vcpu-support-in-qemu-command-line.patch</a>
and <a href="api_extension/0011-complete-vcpu-support-in-qemu-driver.patch">0011-complete-vcpu-support-in-qemu-driver.patch</a></p>
<p>
Finally, the example breaks the xen driver changes across four
patches. One maps the XML changes to the hypervisor command,
the next two are independently implementing the getter and
setter APIs, and the last one provides cleanup of code that was
rendered dead by the new API.
</p>
<p class="example">See <a href="api_extension/0012-improve-vcpu-support-in-xen-command-line.patch">0012-improve-vcpu-support-in-xen-command-line.patch</a>,
<a href="api_extension/0013-improve-getting-xen-vcpu-counts.patch">0013-improve-getting-xen-vcpu-counts.patch</a>,
<a href="api_extension/0014-improve-setting-xen-vcpu-counts.patch">0014-improve-setting-xen-vcpu-counts.patch</a>,
and <a href="api_extension/0015-remove-dead-xen-code.patch">0015-remove-dead-xen-code.patch</a></p>
<p>
The exact details of the example code are probably uninteresting
unless you're concerned with virtual cpu management.
</p>
<p>

View File

@ -0,0 +1,145 @@
From a74f4e44649906dcd82151f7ef837f66d7fa2ab1 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Mon, 27 Sep 2010 17:36:06 -0600
Subject: [PATCH 01/15] vcpu: add current attribute to <vcpu> element
Syntax agreed on in
https://www.redhat.com/archives/libvir-list/2010-September/msg00476.html
<domain ...>
<vcpu current='x'>y</vcpu>
...
can now be used to specify 1 <= x <= y current vcpus, in relation
to the boot-time max of y vcpus. If current is omitted, then
current and max are assumed to be the same value.
* docs/schemas/domain.rng: Add new attribute.
* docs/formatdomain.html.in: Document it.
* tests/qemuxml2argvdata/qemuxml2argv-smp.xml: Add to
domainschematest.
* tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml: Likewise.
---
docs/formatdomain.html.in | 9 +++++--
docs/schemas/domain.rng | 5 ++++
tests/qemuxml2argvdata/qemuxml2argv-smp.xml | 28 +++++++++++++++++++++++++++
tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml | 22 +++++++++++++++++++++
4 files changed, 61 insertions(+), 3 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smp.xml
create mode 100644 tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index a8a1fac..96de121 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -200,7 +200,7 @@
&lt;swap_hard_limit&gt;2097152&lt;/swap_hard_limit&gt;
&lt;min_guarantee&gt;65536&lt;/min_guarantee&gt;
&lt;/memtune&gt;
- &lt;vcpu cpuset="1-4,^3,6"&gt;2&lt;/vcpu&gt;
+ &lt;vcpu cpuset="1-4,^3,6" current="1"&gt;2&lt;/vcpu&gt;
...</pre>
<dl>
@@ -238,7 +238,7 @@
minimum memory allocation for the guest. The units for this value are
kilobytes (i.e. blocks of 1024 bytes)</dd>
<dt><code>vcpu</code></dt>
- <dd>The content of this element defines the number of virtual
+ <dd>The content of this element defines the maximum number of virtual
CPUs allocated for the guest OS, which must be between 1 and
the maximum supported by the hypervisor. <span class="since">Since
0.4.4</span>, this element can contain an optional
@@ -246,7 +246,10 @@
list of physical CPU numbers that virtual CPUs can be pinned
to. Each element in that list is either a single CPU number,
a range of CPU numbers, or a caret followed by a CPU number to
- be excluded from a previous range.
+ be excluded from a previous range. <span class="since">Since
+ 0.8.5</span>, the optional attribute <code>current</code> can
+ be used to specify whether fewer than the maximum number of
+ virtual CPUs should be enabled.
</dd>
</dl>
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index f230263..a934a77 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -337,6 +337,11 @@
<ref name="cpuset"/>
</attribute>
</optional>
+ <optional>
+ <attribute name="current">
+ <ref name="countCPU"/>
+ </attribute>
+ </optional>
<ref name="countCPU"/>
</element>
</optional>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smp.xml b/tests/qemuxml2argvdata/qemuxml2argv-smp.xml
new file mode 100644
index 0000000..975f873
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-smp.xml
@@ -0,0 +1,28 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu current='1'>2</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <cpu>
+ <topology sockets='2' cores='1' threads='1'/>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' unit='0'/>
+ </disk>
+ <controller type='ide' index='0'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml b/tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml
new file mode 100644
index 0000000..d061e11
--- /dev/null
+++ b/tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml
@@ -0,0 +1,22 @@
+<domain type='xen' id='15'>
+ <name>pvtest</name>
+ <uuid>596a5d2171f48fb2e068e2386a5c413e</uuid>
+ <os>
+ <type>linux</type>
+ <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel>
+ <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd>
+ <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os </cmdline>
+ </os>
+ <memory>430080</memory>
+ <vcpu current='2'>4</vcpu>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>destroy</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <disk type='file' device='disk'>
+ <source file='/root/some.img'/>
+ <target dev='xvda'/>
+ </disk>
+ <console tty='/dev/pts/4'/>
+ </devices>
+</domain>
--
1.7.2.3

View File

@ -0,0 +1,62 @@
From ea3f5c68093429c6ad507b45689cdf209c2c257b Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Fri, 24 Sep 2010 16:48:45 -0600
Subject: [PATCH 02/15] vcpu: add new public API
API agreed on in
https://www.redhat.com/archives/libvir-list/2010-September/msg00456.html,
but modified for enum names to be consistent with virDomainDeviceModifyFlags.
* include/libvirt/libvirt.h.in (virDomainVcpuFlags)
(virDomainSetVcpusFlags, virDomainGetVcpusFlags): New
declarations.
* src/libvirt_public.syms: Export new symbols.
---
include/libvirt/libvirt.h.in | 15 +++++++++++++++
src/libvirt_public.syms | 2 ++
2 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 2eba61e..d0cc4c0 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -915,8 +915,23 @@ struct _virVcpuInfo {
};
typedef virVcpuInfo *virVcpuInfoPtr;
+/* Flags for controlling virtual CPU hot-plugging. */
+typedef enum {
+ /* Must choose at least one of these two bits; SetVcpus can choose both */
+ VIR_DOMAIN_VCPU_LIVE = (1 << 0), /* Affect active domain */
+ VIR_DOMAIN_VCPU_CONFIG = (1 << 1), /* Affect next boot */
+
+ /* Additional flags to be bit-wise OR'd in */
+ VIR_DOMAIN_VCPU_MAXIMUM = (1 << 2), /* Max rather than current count */
+} virDomainVcpuFlags;
+
int virDomainSetVcpus (virDomainPtr domain,
unsigned int nvcpus);
+int virDomainSetVcpusFlags (virDomainPtr domain,
+ unsigned int nvcpus,
+ unsigned int flags);
+int virDomainGetVcpusFlags (virDomainPtr domain,
+ unsigned int flags);
int virDomainPinVcpu (virDomainPtr domain,
unsigned int vcpu,
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index fceb516..a8091b1 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -409,6 +409,8 @@ LIBVIRT_0.8.5 {
global:
virDomainSetMemoryParameters;
virDomainGetMemoryParameters;
+ virDomainGetVcpusFlags;
+ virDomainSetVcpusFlags;
} LIBVIRT_0.8.2;
# .... define new API here using predicted next version number ....
--
1.7.2.3

View File

@ -0,0 +1,222 @@
From dd255d64053e9960cd375994ce8f056522e12acc Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Mon, 27 Sep 2010 09:18:22 -0600
Subject: [PATCH 03/15] vcpu: define internal driver API
* src/driver.h (virDrvDomainSetVcpusFlags)
(virDrvDomainGetVcpusFlags): New typedefs.
(_virDriver): New callback members.
* src/esx/esx_driver.c (esxDriver): Add stub for driver.
* src/lxc/lxc_driver.c (lxcDriver): Likewise.
* src/opennebula/one_driver.c (oneDriver): Likewise.
* src/openvz/openvz_driver.c (openvzDriver): Likewise.
* src/phyp/phyp_driver.c (phypDriver): Likewise.
* src/qemu/qemu_driver.c (qemuDriver): Likewise.
* src/remote/remote_driver.c (remote_driver): Likewise.
* src/test/test_driver.c (testDriver): Likewise.
* src/uml/uml_driver.c (umlDriver): Likewise.
* src/vbox/vbox_tmpl.c (Driver): Likewise.
* src/xen/xen_driver.c (xenUnifiedDriver): Likewise.
* src/xenapi/xenapi_driver.c (xenapiDriver): Likewise.
---
src/driver.h | 9 +++++++++
src/esx/esx_driver.c | 2 ++
src/lxc/lxc_driver.c | 2 ++
src/opennebula/one_driver.c | 2 ++
src/openvz/openvz_driver.c | 2 ++
src/phyp/phyp_driver.c | 2 ++
src/qemu/qemu_driver.c | 2 ++
src/remote/remote_driver.c | 2 ++
src/test/test_driver.c | 2 ++
src/uml/uml_driver.c | 2 ++
src/vbox/vbox_tmpl.c | 2 ++
src/xen/xen_driver.c | 2 ++
src/xenapi/xenapi_driver.c | 2 ++
13 files changed, 33 insertions(+), 0 deletions(-)
diff --git a/src/driver.h b/src/driver.h
index 32aeb04..79a96c1 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -185,6 +185,13 @@ typedef int
(*virDrvDomainSetVcpus) (virDomainPtr domain,
unsigned int nvcpus);
typedef int
+ (*virDrvDomainSetVcpusFlags) (virDomainPtr domain,
+ unsigned int nvcpus,
+ unsigned int flags);
+typedef int
+ (*virDrvDomainGetVcpusFlags) (virDomainPtr domain,
+ unsigned int flags);
+typedef int
(*virDrvDomainPinVcpu) (virDomainPtr domain,
unsigned int vcpu,
unsigned char *cpumap,
@@ -520,6 +527,8 @@ struct _virDriver {
virDrvDomainRestore domainRestore;
virDrvDomainCoreDump domainCoreDump;
virDrvDomainSetVcpus domainSetVcpus;
+ virDrvDomainSetVcpusFlags domainSetVcpusFlags;
+ virDrvDomainGetVcpusFlags domainGetVcpusFlags;
virDrvDomainPinVcpu domainPinVcpu;
virDrvDomainGetVcpus domainGetVcpus;
virDrvDomainGetMaxVcpus domainGetMaxVcpus;
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 1b4ee29..2a32374 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -4160,6 +4160,8 @@ static virDriver esxDriver = {
NULL, /* domainRestore */
NULL, /* domainCoreDump */
esxDomainSetVcpus, /* domainSetVcpus */
+ NULL, /* domainSetVcpusFlags */
+ NULL, /* domainGetVcpusFlags */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
esxDomainGetMaxVcpus, /* domainGetMaxVcpus */
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index df814da..7563a8c 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -2768,6 +2768,8 @@ static virDriver lxcDriver = {
NULL, /* domainRestore */
NULL, /* domainCoreDump */
NULL, /* domainSetVcpus */
+ NULL, /* domainSetVcpusFlags */
+ NULL, /* domainGetVcpusFlags */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
NULL, /* domainGetMaxVcpus */
diff --git a/src/opennebula/one_driver.c b/src/opennebula/one_driver.c
index ced9a38..199fca3 100644
--- a/src/opennebula/one_driver.c
+++ b/src/opennebula/one_driver.c
@@ -751,6 +751,8 @@ static virDriver oneDriver = {
NULL, /* domainRestore */
NULL, /* domainCoreDump */
NULL, /* domainSetVcpus */
+ NULL, /* domainSetVcpusFlags */
+ NULL, /* domainGetVcpusFlags */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
NULL, /* domainGetMaxVcpus */
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index 92cf4a1..9d19aeb 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -1590,6 +1590,8 @@ static virDriver openvzDriver = {
NULL, /* domainRestore */
NULL, /* domainCoreDump */
openvzDomainSetVcpus, /* domainSetVcpus */
+ NULL, /* domainSetVcpusFlags */
+ NULL, /* domainGetVcpusFlags */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
index e63d8d9..6e0a5e9 100644
--- a/src/phyp/phyp_driver.c
+++ b/src/phyp/phyp_driver.c
@@ -3941,6 +3941,8 @@ static virDriver phypDriver = {
NULL, /* domainRestore */
NULL, /* domainCoreDump */
phypDomainSetCPU, /* domainSetVcpus */
+ NULL, /* domainSetVcpusFlags */
+ NULL, /* domainGetVcpusFlags */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
phypGetLparCPUMAX, /* domainGetMaxVcpus */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index abd8e9d..3d17e04 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12938,6 +12938,8 @@ static virDriver qemuDriver = {
qemudDomainRestore, /* domainRestore */
qemudDomainCoreDump, /* domainCoreDump */
qemudDomainSetVcpus, /* domainSetVcpus */
+ NULL, /* domainSetVcpusFlags */
+ NULL, /* domainGetVcpusFlags */
qemudDomainPinVcpu, /* domainPinVcpu */
qemudDomainGetVcpus, /* domainGetVcpus */
qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 0b10406..1a687ad 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -10468,6 +10468,8 @@ static virDriver remote_driver = {
remoteDomainRestore, /* domainRestore */
remoteDomainCoreDump, /* domainCoreDump */
remoteDomainSetVcpus, /* domainSetVcpus */
+ NULL, /* domainSetVcpusFlags */
+ NULL, /* domainGetVcpusFlags */
remoteDomainPinVcpu, /* domainPinVcpu */
remoteDomainGetVcpus, /* domainGetVcpus */
remoteDomainGetMaxVcpus, /* domainGetMaxVcpus */
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 7d4d119..6a00558 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -5260,6 +5260,8 @@ static virDriver testDriver = {
testDomainRestore, /* domainRestore */
testDomainCoreDump, /* domainCoreDump */
testSetVcpus, /* domainSetVcpus */
+ NULL, /* domainSetVcpusFlags */
+ NULL, /* domainGetVcpusFlags */
testDomainPinVcpu, /* domainPinVcpu */
testDomainGetVcpus, /* domainGetVcpus */
testDomainGetMaxVcpus, /* domainGetMaxVcpus */
diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
index 3dcd321..5161012 100644
--- a/src/uml/uml_driver.c
+++ b/src/uml/uml_driver.c
@@ -2129,6 +2129,8 @@ static virDriver umlDriver = {
NULL, /* domainRestore */
NULL, /* domainCoreDump */
NULL, /* domainSetVcpus */
+ NULL, /* domainSetVcpusFlags */
+ NULL, /* domainGetVcpusFlags */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
NULL, /* domainGetMaxVcpus */
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 7e7d8e4..cb9193a 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -8267,6 +8267,8 @@ virDriver NAME(Driver) = {
NULL, /* domainRestore */
NULL, /* domainCoreDump */
vboxDomainSetVcpus, /* domainSetVcpus */
+ NULL, /* domainSetVcpusFlags */
+ NULL, /* domainGetVcpusFlags */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
vboxDomainGetMaxVcpus, /* domainGetMaxVcpus */
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c
index c2a4de3..7d67ced 100644
--- a/src/xen/xen_driver.c
+++ b/src/xen/xen_driver.c
@@ -1951,6 +1951,8 @@ static virDriver xenUnifiedDriver = {
xenUnifiedDomainRestore, /* domainRestore */
xenUnifiedDomainCoreDump, /* domainCoreDump */
xenUnifiedDomainSetVcpus, /* domainSetVcpus */
+ NULL, /* domainSetVcpusFlags */
+ NULL, /* domainGetVcpusFlags */
xenUnifiedDomainPinVcpu, /* domainPinVcpu */
xenUnifiedDomainGetVcpus, /* domainGetVcpus */
xenUnifiedDomainGetMaxVcpus, /* domainGetMaxVcpus */
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
index e62a139..753169c 100644
--- a/src/xenapi/xenapi_driver.c
+++ b/src/xenapi/xenapi_driver.c
@@ -1754,6 +1754,8 @@ static virDriver xenapiDriver = {
NULL, /* domainRestore */
NULL, /* domainCoreDump */
xenapiDomainSetVcpus, /* domainSetVcpus */
+ NULL, /* domainSetVcpusFlags */
+ NULL, /* domainGetVcpusFlags */
xenapiDomainPinVcpu, /* domainPinVcpu */
xenapiDomainGetVcpus, /* domainGetVcpus */
xenapiDomainGetMaxVcpus, /* domainGetMaxVcpus */
--
1.7.2.3

View File

@ -0,0 +1,188 @@
From 9d2c60799271d605f82dfd4bfa6ed7d14ad87e26 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Mon, 27 Sep 2010 09:37:22 -0600
Subject: [PATCH 04/15] vcpu: implement the public APIs
Factors common checks (such as nonzero vcpu count) up front, but
drivers will still need to do additional flag checks.
* src/libvirt.c (virDomainSetVcpusFlags, virDomainGetVcpusFlags):
New functions.
(virDomainSetVcpus, virDomainGetMaxVcpus): Refer to new API.
---
src/libvirt.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 134 insertions(+), 6 deletions(-)
diff --git a/src/libvirt.c b/src/libvirt.c
index 629d97b..1b39210 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -5192,7 +5192,9 @@ error:
* This function requires privileged access to the hypervisor.
*
* This command only changes the runtime configuration of the domain,
- * so can only be called on an active domain.
+ * so can only be called on an active domain. It is hypervisor-dependent
+ * whether it also affects persistent configuration; for more control,
+ * use virDomainSetVcpusFlags().
*
* Returns 0 in case of success, -1 in case of failure.
*/
@@ -5237,13 +5239,139 @@ error:
}
/**
+ * virDomainSetVcpusFlags:
+ * @domain: pointer to domain object, or NULL for Domain0
+ * @nvcpus: the new number of virtual CPUs for this domain, must be at least 1
+ * @flags: an OR'ed set of virDomainVcpuFlags
+ *
+ * Dynamically change the number of virtual CPUs used by the domain.
+ * Note that this call may fail if the underlying virtualization hypervisor
+ * does not support it or if growing the number is arbitrary limited.
+ * This function requires privileged access to the hypervisor.
+ *
+ * @flags must include VIR_DOMAIN_VCPU_LIVE to affect a running
+ * domain (which may fail if domain is not active), or
+ * VIR_DOMAIN_VCPU_CONFIG to affect the next boot via the XML
+ * description of the domain. Both flags may be set.
+ *
+ * If @flags includes VIR_DOMAIN_VCPU_MAXIMUM, then
+ * VIR_DOMAIN_VCPU_LIVE must be clear, and only the maximum virtual
+ * CPU limit is altered; generally, this value must be less than or
+ * equal to virConnectGetMaxVcpus(). Otherwise, this call affects the
+ * current virtual CPU limit, which must be less than or equal to the
+ * maximum limit.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+
+int
+virDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+ VIR_DEBUG("domain=%p, nvcpus=%u, flags=%u", domain, nvcpus, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ virDispatchError(NULL);
+ return (-1);
+ }
+ if (domain->conn->flags & VIR_CONNECT_RO) {
+ virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ goto error;
+ }
+
+ /* Perform some argument validation common to all implementations. */
+ if (nvcpus < 1 || (unsigned short) nvcpus != nvcpus ||
+ (flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0) {
+ virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ goto error;
+ }
+ conn = domain->conn;
+
+ if (conn->driver->domainSetVcpusFlags) {
+ int ret;
+ ret = conn->driver->domainSetVcpusFlags (domain, nvcpus, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(domain->conn);
+ return -1;
+}
+
+/**
+ * virDomainGetVcpusFlags:
+ * @domain: pointer to domain object, or NULL for Domain0
+ * @flags: an OR'ed set of virDomainVcpuFlags
+ *
+ * Query the number of virtual CPUs used by the domain. Note that
+ * this call may fail if the underlying virtualization hypervisor does
+ * not support it. This function requires privileged access to the
+ * hypervisor.
+ *
+ * @flags must include either VIR_DOMAIN_VCPU_ACTIVE to query a
+ * running domain (which will fail if domain is not active), or
+ * VIR_DOMAIN_VCPU_PERSISTENT to query the XML description of the
+ * domain. It is an error to set both flags.
+ *
+ * If @flags includes VIR_DOMAIN_VCPU_MAXIMUM, then the maximum
+ * virtual CPU limit is queried. Otherwise, this call queries the
+ * current virtual CPU limit.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+
+int
+virDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
+{
+ virConnectPtr conn;
+ VIR_DEBUG("domain=%p, flags=%u", domain, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ virDispatchError(NULL);
+ return (-1);
+ }
+
+ /* Exactly one of these two flags should be set. */
+ if (!(flags & VIR_DOMAIN_VCPU_LIVE) == !(flags & VIR_DOMAIN_VCPU_CONFIG)) {
+ virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ goto error;
+ }
+ conn = domain->conn;
+
+ if (conn->driver->domainGetVcpusFlags) {
+ int ret;
+ ret = conn->driver->domainGetVcpusFlags (domain, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(domain->conn);
+ return -1;
+}
+
+/**
* virDomainPinVcpu:
* @domain: pointer to domain object, or NULL for Domain0
* @vcpu: virtual CPU number
* @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN)
- * Each bit set to 1 means that corresponding CPU is usable.
- * Bytes are stored in little-endian order: CPU0-7, 8-15...
- * In each byte, lowest CPU number is least significant bit.
+ * Each bit set to 1 means that corresponding CPU is usable.
+ * Bytes are stored in little-endian order: CPU0-7, 8-15...
+ * In each byte, lowest CPU number is least significant bit.
* @maplen: number of bytes in cpumap, from 1 up to size of CPU map in
* underlying virtualization system (Xen...).
* If maplen < size, missing bytes are set to zero.
@@ -5371,9 +5499,9 @@ error:
*
* Provides the maximum number of virtual CPUs supported for
* the guest VM. If the guest is inactive, this is basically
- * the same as virConnectGetMaxVcpus. If the guest is running
+ * the same as virConnectGetMaxVcpus(). If the guest is running
* this will reflect the maximum number of virtual CPUs the
- * guest was booted with.
+ * guest was booted with. For more details, see virDomainGetVcpusFlags().
*
* Returns the maximum of virtual CPU or -1 in case of error.
*/
--
1.7.2.3

View File

@ -0,0 +1,421 @@
From eb826444f90c2563dadf148630b0cd6a9b41ba1e Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Mon, 27 Sep 2010 10:10:06 -0600
Subject: [PATCH 05/15] vcpu: implement the remote protocol
Done by editing the first three files, then running
'make -C src rpcgen', then editing src/remote_protocol-structs
to match.
* daemon/remote.c (remoteDispatchDomainSetVcpusFlags)
(remoteDispatchDomainGetVcpusFlags): New functions.
* src/remote/remote_driver.c (remoteDomainSetVcpusFlags)
(remoteDomainGetVcpusFlags, remote_driver): Client side
serialization.
* src/remote/remote_protocol.x
(remote_domain_set_vcpus_flags_args)
(remote_domain_get_vcpus_flags_args)
(remote_domain_get_vcpus_flags_ret)
(REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS)
(REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS): Define wire format.
* daemon/remote_dispatch_args.h: Regenerate.
* daemon/remote_dispatch_prototypes.h: Likewise.
* daemon/remote_dispatch_table.h: Likewise.
* src/remote/remote_protocol.c: Likewise.
* src/remote/remote_protocol.h: Likewise.
* src/remote_protocol-structs: Likewise.
---
daemon/remote.c | 53 ++++++++++++++++++++++++++++++++
daemon/remote_dispatch_args.h | 2 +
daemon/remote_dispatch_prototypes.h | 16 ++++++++++
daemon/remote_dispatch_ret.h | 1 +
daemon/remote_dispatch_table.h | 10 ++++++
src/remote/remote_driver.c | 57 +++++++++++++++++++++++++++++++++-
src/remote/remote_protocol.c | 33 ++++++++++++++++++++
src/remote/remote_protocol.h | 26 ++++++++++++++++
src/remote/remote_protocol.x | 19 +++++++++++-
src/remote_protocol-structs | 12 +++++++
10 files changed, 226 insertions(+), 3 deletions(-)
diff --git a/daemon/remote.c b/daemon/remote.c
index 7a96e29..323f00c 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -1751,6 +1751,33 @@ oom:
}
static int
+remoteDispatchDomainGetVcpusFlags (struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_message_header *hdr ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ remote_domain_get_vcpus_flags_args *args,
+ remote_domain_get_vcpus_flags_ret *ret)
+{
+ virDomainPtr dom;
+
+ dom = get_nonnull_domain (conn, args->dom);
+ if (dom == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ ret->num = virDomainGetVcpusFlags (dom, args->flags);
+ if (ret->num == -1) {
+ virDomainFree(dom);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+ virDomainFree(dom);
+ return 0;
+}
+
+static int
remoteDispatchDomainMigratePrepare (struct qemud_server *server ATTRIBUTE_UNUSED,
struct qemud_client *client ATTRIBUTE_UNUSED,
virConnectPtr conn,
@@ -2568,6 +2595,32 @@ remoteDispatchDomainSetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
}
static int
+remoteDispatchDomainSetVcpusFlags (struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_message_header *hdr ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ remote_domain_set_vcpus_flags_args *args,
+ void *ret ATTRIBUTE_UNUSED)
+{
+ virDomainPtr dom;
+
+ dom = get_nonnull_domain (conn, args->dom);
+ if (dom == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ if (virDomainSetVcpusFlags (dom, args->nvcpus, args->flags) == -1) {
+ virDomainFree(dom);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+ virDomainFree(dom);
+ return 0;
+}
+
+static int
remoteDispatchDomainShutdown (struct qemud_server *server ATTRIBUTE_UNUSED,
struct qemud_client *client ATTRIBUTE_UNUSED,
virConnectPtr conn,
diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h
index d8528b6..9583e9c 100644
--- a/daemon/remote_dispatch_args.h
+++ b/daemon/remote_dispatch_args.h
@@ -167,3 +167,5 @@
remote_domain_create_with_flags_args val_remote_domain_create_with_flags_args;
remote_domain_set_memory_parameters_args val_remote_domain_set_memory_parameters_args;
remote_domain_get_memory_parameters_args val_remote_domain_get_memory_parameters_args;
+ remote_domain_set_vcpus_flags_args val_remote_domain_set_vcpus_flags_args;
+ remote_domain_get_vcpus_flags_args val_remote_domain_get_vcpus_flags_args;
diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h
index b674bb4..6b35851 100644
--- a/daemon/remote_dispatch_prototypes.h
+++ b/daemon/remote_dispatch_prototypes.h
@@ -306,6 +306,14 @@ static int remoteDispatchDomainGetVcpus(
remote_error *err,
remote_domain_get_vcpus_args *args,
remote_domain_get_vcpus_ret *ret);
+static int remoteDispatchDomainGetVcpusFlags(
+ struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *err,
+ remote_domain_get_vcpus_flags_args *args,
+ remote_domain_get_vcpus_flags_ret *ret);
static int remoteDispatchDomainHasCurrentSnapshot(
struct qemud_server *server,
struct qemud_client *client,
@@ -554,6 +562,14 @@ static int remoteDispatchDomainSetVcpus(
remote_error *err,
remote_domain_set_vcpus_args *args,
void *ret);
+static int remoteDispatchDomainSetVcpusFlags(
+ struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *err,
+ remote_domain_set_vcpus_flags_args *args,
+ void *ret);
static int remoteDispatchDomainShutdown(
struct qemud_server *server,
struct qemud_client *client,
diff --git a/daemon/remote_dispatch_ret.h b/daemon/remote_dispatch_ret.h
index 17c9bca..3723b00 100644
--- a/daemon/remote_dispatch_ret.h
+++ b/daemon/remote_dispatch_ret.h
@@ -136,3 +136,4 @@
remote_domain_get_block_info_ret val_remote_domain_get_block_info_ret;
remote_domain_create_with_flags_ret val_remote_domain_create_with_flags_ret;
remote_domain_get_memory_parameters_ret val_remote_domain_get_memory_parameters_ret;
+ remote_domain_get_vcpus_flags_ret val_remote_domain_get_vcpus_flags_ret;
diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h
index 47d95eb..dd2adc7 100644
--- a/daemon/remote_dispatch_table.h
+++ b/daemon/remote_dispatch_table.h
@@ -997,3 +997,13 @@
.args_filter = (xdrproc_t) xdr_remote_domain_get_memory_parameters_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_get_memory_parameters_ret,
},
+{ /* DomainSetVcpusFlags => 199 */
+ .fn = (dispatch_fn) remoteDispatchDomainSetVcpusFlags,
+ .args_filter = (xdrproc_t) xdr_remote_domain_set_vcpus_flags_args,
+ .ret_filter = (xdrproc_t) xdr_void,
+},
+{ /* DomainGetVcpusFlags => 200 */
+ .fn = (dispatch_fn) remoteDispatchDomainGetVcpusFlags,
+ .args_filter = (xdrproc_t) xdr_remote_domain_get_vcpus_flags_args,
+ .ret_filter = (xdrproc_t) xdr_remote_domain_get_vcpus_flags_ret,
+},
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 1a687ad..37c37ef 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -2580,6 +2580,59 @@ done:
}
static int
+remoteDomainSetVcpusFlags (virDomainPtr domain, unsigned int nvcpus,
+ unsigned int flags)
+{
+ int rv = -1;
+ remote_domain_set_vcpus_flags_args args;
+ struct private_data *priv = domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ make_nonnull_domain (&args.dom, domain);
+ args.nvcpus = nvcpus;
+ args.flags = flags;
+
+ if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS,
+ (xdrproc_t) xdr_remote_domain_set_vcpus_flags_args,
+ (char *) &args,
+ (xdrproc_t) xdr_void, (char *) NULL) == -1)
+ goto done;
+
+ rv = 0;
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
+static int
+remoteDomainGetVcpusFlags (virDomainPtr domain, unsigned int flags)
+{
+ int rv = -1;
+ remote_domain_get_vcpus_flags_args args;
+ remote_domain_get_vcpus_flags_ret ret;
+ struct private_data *priv = domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ make_nonnull_domain (&args.dom, domain);
+ args.flags = flags;
+
+ memset (&ret, 0, sizeof ret);
+ if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS,
+ (xdrproc_t) xdr_remote_domain_get_vcpus_flags_args, (char *) &args,
+ (xdrproc_t) xdr_remote_domain_get_vcpus_flags_ret, (char *) &ret) == -1)
+ goto done;
+
+ rv = ret.num;
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
+static int
remoteDomainPinVcpu (virDomainPtr domain,
unsigned int vcpu,
unsigned char *cpumap,
@@ -10468,8 +10521,8 @@ static virDriver remote_driver = {
remoteDomainRestore, /* domainRestore */
remoteDomainCoreDump, /* domainCoreDump */
remoteDomainSetVcpus, /* domainSetVcpus */
- NULL, /* domainSetVcpusFlags */
- NULL, /* domainGetVcpusFlags */
+ remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */
+ remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */
remoteDomainPinVcpu, /* domainPinVcpu */
remoteDomainGetVcpus, /* domainGetVcpus */
remoteDomainGetMaxVcpus, /* domainGetMaxVcpus */
diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c
index 5c55713..38ea050 100644
--- a/src/remote/remote_protocol.c
+++ b/src/remote/remote_protocol.c
@@ -1355,6 +1355,39 @@ xdr_remote_domain_set_vcpus_args (XDR *xdrs, remote_domain_set_vcpus_args *objp)
}
bool_t
+xdr_remote_domain_set_vcpus_flags_args (XDR *xdrs, remote_domain_set_vcpus_flags_args *objp)
+{
+
+ if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+ return FALSE;
+ if (!xdr_u_int (xdrs, &objp->nvcpus))
+ return FALSE;
+ if (!xdr_u_int (xdrs, &objp->flags))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_get_vcpus_flags_args (XDR *xdrs, remote_domain_get_vcpus_flags_args *objp)
+{
+
+ if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+ return FALSE;
+ if (!xdr_u_int (xdrs, &objp->flags))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_get_vcpus_flags_ret (XDR *xdrs, remote_domain_get_vcpus_flags_ret *objp)
+{
+
+ if (!xdr_int (xdrs, &objp->num))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
xdr_remote_domain_pin_vcpu_args (XDR *xdrs, remote_domain_pin_vcpu_args *objp)
{
char **objp_cpp0 = (char **) (void *) &objp->cpumap.cpumap_val;
diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h
index 756da11..d75e76c 100644
--- a/src/remote/remote_protocol.h
+++ b/src/remote/remote_protocol.h
@@ -750,6 +750,24 @@ struct remote_domain_set_vcpus_args {
};
typedef struct remote_domain_set_vcpus_args remote_domain_set_vcpus_args;
+struct remote_domain_set_vcpus_flags_args {
+ remote_nonnull_domain dom;
+ u_int nvcpus;
+ u_int flags;
+};
+typedef struct remote_domain_set_vcpus_flags_args remote_domain_set_vcpus_flags_args;
+
+struct remote_domain_get_vcpus_flags_args {
+ remote_nonnull_domain dom;
+ u_int flags;
+};
+typedef struct remote_domain_get_vcpus_flags_args remote_domain_get_vcpus_flags_args;
+
+struct remote_domain_get_vcpus_flags_ret {
+ int num;
+};
+typedef struct remote_domain_get_vcpus_flags_ret remote_domain_get_vcpus_flags_ret;
+
struct remote_domain_pin_vcpu_args {
remote_nonnull_domain dom;
int vcpu;
@@ -2281,6 +2299,8 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_CREATE_WITH_FLAGS = 196,
REMOTE_PROC_DOMAIN_SET_MEMORY_PARAMETERS = 197,
REMOTE_PROC_DOMAIN_GET_MEMORY_PARAMETERS = 198,
+ REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS = 199,
+ REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS = 200,
};
typedef enum remote_procedure remote_procedure;
@@ -2422,6 +2442,9 @@ extern bool_t xdr_remote_domain_define_xml_args (XDR *, remote_domain_define_xm
extern bool_t xdr_remote_domain_define_xml_ret (XDR *, remote_domain_define_xml_ret*);
extern bool_t xdr_remote_domain_undefine_args (XDR *, remote_domain_undefine_args*);
extern bool_t xdr_remote_domain_set_vcpus_args (XDR *, remote_domain_set_vcpus_args*);
+extern bool_t xdr_remote_domain_set_vcpus_flags_args (XDR *, remote_domain_set_vcpus_flags_args*);
+extern bool_t xdr_remote_domain_get_vcpus_flags_args (XDR *, remote_domain_get_vcpus_flags_args*);
+extern bool_t xdr_remote_domain_get_vcpus_flags_ret (XDR *, remote_domain_get_vcpus_flags_ret*);
extern bool_t xdr_remote_domain_pin_vcpu_args (XDR *, remote_domain_pin_vcpu_args*);
extern bool_t xdr_remote_domain_get_vcpus_args (XDR *, remote_domain_get_vcpus_args*);
extern bool_t xdr_remote_domain_get_vcpus_ret (XDR *, remote_domain_get_vcpus_ret*);
@@ -2762,6 +2785,9 @@ extern bool_t xdr_remote_domain_define_xml_args ();
extern bool_t xdr_remote_domain_define_xml_ret ();
extern bool_t xdr_remote_domain_undefine_args ();
extern bool_t xdr_remote_domain_set_vcpus_args ();
+extern bool_t xdr_remote_domain_set_vcpus_flags_args ();
+extern bool_t xdr_remote_domain_get_vcpus_flags_args ();
+extern bool_t xdr_remote_domain_get_vcpus_flags_ret ();
extern bool_t xdr_remote_domain_pin_vcpu_args ();
extern bool_t xdr_remote_domain_get_vcpus_args ();
extern bool_t xdr_remote_domain_get_vcpus_ret ();
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index e80fb5f..d57e6d0 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -768,6 +768,21 @@ struct remote_domain_set_vcpus_args {
int nvcpus;
};
+struct remote_domain_set_vcpus_flags_args {
+ remote_nonnull_domain dom;
+ unsigned int nvcpus;
+ unsigned int flags;
+};
+
+struct remote_domain_get_vcpus_flags_args {
+ remote_nonnull_domain dom;
+ unsigned int flags;
+};
+
+struct remote_domain_get_vcpus_flags_ret {
+ int num;
+};
+
struct remote_domain_pin_vcpu_args {
remote_nonnull_domain dom;
int vcpu;
@@ -2062,7 +2077,9 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON = 195,
REMOTE_PROC_DOMAIN_CREATE_WITH_FLAGS = 196,
REMOTE_PROC_DOMAIN_SET_MEMORY_PARAMETERS = 197,
- REMOTE_PROC_DOMAIN_GET_MEMORY_PARAMETERS = 198
+ REMOTE_PROC_DOMAIN_GET_MEMORY_PARAMETERS = 198,
+ REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS = 199,
+ REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS = 200
/*
* Notice how the entries are grouped in sets of 10 ?
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 838423e..d505886 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -461,6 +461,18 @@ struct remote_domain_set_vcpus_args {
remote_nonnull_domain dom;
int nvcpus;
};
+struct remote_domain_set_vcpus_flags_args {
+ remote_nonnull_domain dom;
+ u_int nvcpus;
+ u_int flags;
+};
+struct remote_domain_get_vcpus_flags_args {
+ remote_nonnull_domain dom;
+ u_int flags;
+};
+struct remote_domain_get_vcpus_flags_ret {
+ int num;
+};
struct remote_domain_pin_vcpu_args {
remote_nonnull_domain dom;
int vcpu;
--
1.7.2.3

View File

@ -0,0 +1,735 @@
From 50c51f13e2af04afac46e181c4ed62581545a488 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Mon, 27 Sep 2010 16:37:53 -0600
Subject: [PATCH 06/15] vcpu: make old API trivially wrap to new API
Note - this wrapping is completely mechanical; the old API will
function identically, since the new API validates that the exact
same flags are provided by the old API. On a per-driver basis,
it may make sense to have the old API pass a different set of flags,
but that should be done in the per-driver patch that implements
the full range of flag support in the new API.
* src/esx/esx_driver.c (esxDomainSetVcpus, escDomainGetMaxVpcus):
Move guts...
(esxDomainSetVcpusFlags, esxDomainGetVcpusFlags): ...to new
functions.
(esxDriver): Trivially support the new API.
* src/openvz/openvz_driver.c (openvzDomainSetVcpus)
(openvzDomainSetVcpusFlags, openvzDomainGetMaxVcpus)
(openvzDomainGetVcpusFlags, openvzDriver): Likewise.
* src/phyp/phyp_driver.c (phypDomainSetCPU)
(phypDomainSetVcpusFlags, phypGetLparCPUMAX)
(phypDomainGetVcpusFlags, phypDriver): Likewise.
* src/qemu/qemu_driver.c (qemudDomainSetVcpus)
(qemudDomainSetVcpusFlags, qemudDomainGetMaxVcpus)
(qemudDomainGetVcpusFlags, qemuDriver): Likewise.
* src/test/test_driver.c (testSetVcpus, testDomainSetVcpusFlags)
(testDomainGetMaxVcpus, testDomainGetVcpusFlags, testDriver):
Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainSetVcpus)
(vboxDomainSetVcpusFlags, virDomainGetMaxVcpus)
(virDomainGetVcpusFlags, virDriver): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainSetVcpus)
(xenUnifiedDomainSetVcpusFlags, xenUnifiedDomainGetMaxVcpus)
(xenUnifiedDomainGetVcpusFlags, xenUnifiedDriver): Likewise.
* src/xenapi/xenapi_driver.c (xenapiDomainSetVcpus)
(xenapiDomainSetVcpusFlags, xenapiDomainGetMaxVcpus)
(xenapiDomainGetVcpusFlags, xenapiDriver): Likewise.
(xenapiError): New helper macro.
---
src/esx/esx_driver.c | 32 +++++++++++++++++++---
src/openvz/openvz_driver.c | 34 +++++++++++++++++++++---
src/phyp/phyp_driver.c | 32 ++++++++++++++++++++---
src/qemu/qemu_driver.c | 38 +++++++++++++++++++++++++---
src/test/test_driver.c | 36 ++++++++++++++++++++++---
src/vbox/vbox_tmpl.c | 36 +++++++++++++++++++++++---
src/xen/xen_driver.c | 34 ++++++++++++++++++++++---
src/xenapi/xenapi_driver.c | 60 ++++++++++++++++++++++++++++++++++++++------
8 files changed, 263 insertions(+), 39 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 2a32374..b3e1284 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -2384,7 +2384,8 @@ esxDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
static int
-esxDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus)
+esxDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus,
+ unsigned int flags)
{
int result = -1;
esxPrivate *priv = domain->conn->privateData;
@@ -2394,6 +2395,11 @@ esxDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus)
esxVI_ManagedObjectReference *task = NULL;
esxVI_TaskInfoState taskInfoState;
+ if (flags != VIR_DOMAIN_VCPU_LIVE) {
+ ESX_ERROR(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
+ return -1;
+ }
+
if (nvcpus < 1) {
ESX_ERROR(VIR_ERR_INVALID_ARG, "%s",
_("Requested number of virtual CPUs must at least be 1"));
@@ -2453,15 +2459,26 @@ esxDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus)
}
+static int
+esxDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus)
+{
+ return esxDomainSetVcpusFlags(domain, nvcpus, VIR_DOMAIN_VCPU_LIVE);
+}
+
static int
-esxDomainGetMaxVcpus(virDomainPtr domain)
+esxDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
{
esxPrivate *priv = domain->conn->privateData;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *hostSystem = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
+ if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
+ ESX_ERROR(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
+ return -1;
+ }
+
if (priv->maxVcpus > 0) {
return priv->maxVcpus;
}
@@ -2507,7 +2524,12 @@ esxDomainGetMaxVcpus(virDomainPtr domain)
return priv->maxVcpus;
}
-
+static int
+esxDomainGetMaxVcpus(virDomainPtr domain)
+{
+ return esxDomainGetVcpusFlags(domain, (VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_MAXIMUM));
+}
static char *
esxDomainDumpXML(virDomainPtr domain, int flags)
@@ -4160,8 +4182,8 @@ static virDriver esxDriver = {
NULL, /* domainRestore */
NULL, /* domainCoreDump */
esxDomainSetVcpus, /* domainSetVcpus */
- NULL, /* domainSetVcpusFlags */
- NULL, /* domainGetVcpusFlags */
+ esxDomainSetVcpusFlags, /* domainSetVcpusFlags */
+ esxDomainGetVcpusFlags, /* domainGetVcpusFlags */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
esxDomainGetMaxVcpus, /* domainGetMaxVcpus */
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index 9d19aeb..0f3cfdf 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -67,7 +67,6 @@
static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid);
static int openvzGetMaxVCPUs(virConnectPtr conn, const char *type);
static int openvzDomainGetMaxVcpus(virDomainPtr dom);
-static int openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus);
static int openvzDomainSetVcpusInternal(virDomainObjPtr vm,
unsigned int nvcpus);
static int openvzDomainSetMemoryInternal(virDomainObjPtr vm,
@@ -1211,11 +1210,24 @@ static int openvzGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED,
return -1;
}
+static int
+openvzDomainGetVcpusFlags(virDomainPtr dom ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
+ openvzError(VIR_ERR_INVALID_ARG, _("unsupported flags (0x%x)"), flags);
+ return -1;
+ }
-static int openvzDomainGetMaxVcpus(virDomainPtr dom ATTRIBUTE_UNUSED) {
return openvzGetMaxVCPUs(NULL, "openvz");
}
+static int openvzDomainGetMaxVcpus(virDomainPtr dom)
+{
+ return openvzDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_MAXIMUM));
+}
+
static int openvzDomainSetVcpusInternal(virDomainObjPtr vm,
unsigned int nvcpus)
{
@@ -1241,12 +1253,18 @@ static int openvzDomainSetVcpusInternal(virDomainObjPtr vm,
return 0;
}
-static int openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
+static int openvzDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
+ unsigned int flags)
{
virDomainObjPtr vm;
struct openvz_driver *driver = dom->conn->privateData;
int ret = -1;
+ if (flags != VIR_DOMAIN_VCPU_LIVE) {
+ openvzError(VIR_ERR_INVALID_ARG, _("unsupported flags (0x%x)"), flags);
+ return -1;
+ }
+
openvzDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
openvzDriverUnlock(driver);
@@ -1272,6 +1290,12 @@ cleanup:
return ret;
}
+static int
+openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
+{
+ return openvzDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
+}
+
static virDrvOpenStatus openvzOpen(virConnectPtr conn,
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
int flags ATTRIBUTE_UNUSED)
@@ -1590,8 +1614,8 @@ static virDriver openvzDriver = {
NULL, /* domainRestore */
NULL, /* domainCoreDump */
openvzDomainSetVcpus, /* domainSetVcpus */
- NULL, /* domainSetVcpusFlags */
- NULL, /* domainGetVcpusFlags */
+ openvzDomainSetVcpusFlags, /* domainSetVcpusFlags */
+ openvzDomainGetVcpusFlags, /* domainGetVcpusFlags */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
index 6e0a5e9..e284ae0 100644
--- a/src/phyp/phyp_driver.c
+++ b/src/phyp/phyp_driver.c
@@ -1497,15 +1497,27 @@ phypGetLparCPU(virConnectPtr conn, const char *managed_system, int lpar_id)
}
static int
-phypGetLparCPUMAX(virDomainPtr dom)
+phypDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
{
phyp_driverPtr phyp_driver = dom->conn->privateData;
char *managed_system = phyp_driver->managed_system;
+ if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
+ PHYP_ERROR(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
+ return -1;
+ }
+
return phypGetLparCPUGeneric(dom->conn, managed_system, dom->id, 1);
}
static int
+phypGetLparCPUMAX(virDomainPtr dom)
+{
+ return phypDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_MAXIMUM));
+}
+
+static int
phypGetRemoteSlot(virConnectPtr conn, const char *managed_system,
const char *lpar_name)
{
@@ -3831,7 +3843,8 @@ phypConnectGetCapabilities(virConnectPtr conn)
}
static int
-phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus)
+phypDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
+ unsigned int flags)
{
ConnectionData *connection_data = dom->conn->networkPrivateData;
phyp_driverPtr phyp_driver = dom->conn->privateData;
@@ -3846,6 +3859,11 @@ phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus)
unsigned int amount = 0;
virBuffer buf = VIR_BUFFER_INITIALIZER;
+ if (flags != VIR_DOMAIN_VCPU_LIVE) {
+ PHYP_ERROR(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
+ return -1;
+ }
+
if ((ncpus = phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0)
return 0;
@@ -3891,6 +3909,12 @@ phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus)
}
+static int
+phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus)
+{
+ return phypDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
+}
+
static virDrvOpenStatus
phypVIOSDriverOpen(virConnectPtr conn,
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
@@ -3941,8 +3965,8 @@ static virDriver phypDriver = {
NULL, /* domainRestore */
NULL, /* domainCoreDump */
phypDomainSetCPU, /* domainSetVcpus */
- NULL, /* domainSetVcpusFlags */
- NULL, /* domainGetVcpusFlags */
+ phypDomainSetVcpusFlags, /* domainSetVcpusFlags */
+ phypDomainGetVcpusFlags, /* domainGetVcpusFlags */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
phypGetLparCPUMAX, /* domainGetMaxVcpus */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 3d17e04..7a2ea8f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5934,13 +5934,22 @@ unsupported:
}
-static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
+static int
+qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
+ unsigned int flags)
+{
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
const char * type;
int max;
int ret = -1;
+ if (flags != VIR_DOMAIN_VCPU_LIVE) {
+ qemuReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
+ flags);
+ return -1;
+ }
+
qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
qemuDriverUnlock(driver);
@@ -5994,6 +6003,12 @@ cleanup:
return ret;
}
+static int
+qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
+{
+ return qemudDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
+}
+
static int
qemudDomainPinVcpu(virDomainPtr dom,
@@ -6150,12 +6165,20 @@ cleanup:
}
-static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
+static int
+qemudDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
+{
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
const char *type;
int ret = -1;
+ if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
+ qemuReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
+ flags);
+ return -1;
+ }
+
qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
qemuDriverUnlock(driver);
@@ -6183,6 +6206,13 @@ cleanup:
return ret;
}
+static int
+qemudDomainGetMaxVcpus(virDomainPtr dom)
+{
+ return qemudDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_MAXIMUM));
+}
+
static int qemudDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
{
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
@@ -12938,8 +12968,8 @@ static virDriver qemuDriver = {
qemudDomainRestore, /* domainRestore */
qemudDomainCoreDump, /* domainCoreDump */
qemudDomainSetVcpus, /* domainSetVcpus */
- NULL, /* domainSetVcpusFlags */
- NULL, /* domainGetVcpusFlags */
+ qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */
+ qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */
qemudDomainPinVcpu, /* domainPinVcpu */
qemudDomainGetVcpus, /* domainGetVcpus */
qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 6a00558..b70c80d 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -2029,17 +2029,37 @@ cleanup:
return ret;
}
-static int testDomainGetMaxVcpus(virDomainPtr domain)
+static int
+testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
{
+ if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
+ testError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
+ return -1;
+ }
+
return testGetMaxVCPUs(domain->conn, "test");
}
-static int testSetVcpus(virDomainPtr domain,
- unsigned int nrCpus) {
+static int
+testDomainGetMaxVcpus(virDomainPtr domain)
+{
+ return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_MAXIMUM));
+}
+
+static int
+testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
+ unsigned int flags)
+{
testConnPtr privconn = domain->conn->privateData;
virDomainObjPtr privdom = NULL;
int ret = -1, maxvcpus;
+ if (flags != VIR_DOMAIN_VCPU_LIVE) {
+ testError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
+ return -1;
+ }
+
/* Do this first before locking */
maxvcpus = testDomainGetMaxVcpus(domain);
if (maxvcpus < 0)
@@ -2082,6 +2102,12 @@ cleanup:
return ret;
}
+static int
+testSetVcpus(virDomainPtr domain, unsigned int nrCpus)
+{
+ return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_VCPU_LIVE);
+}
+
static int testDomainGetVcpus(virDomainPtr domain,
virVcpuInfoPtr info,
int maxinfo,
@@ -5260,8 +5286,8 @@ static virDriver testDriver = {
testDomainRestore, /* domainRestore */
testDomainCoreDump, /* domainCoreDump */
testSetVcpus, /* domainSetVcpus */
- NULL, /* domainSetVcpusFlags */
- NULL, /* domainGetVcpusFlags */
+ testDomainSetVcpusFlags, /* domainSetVcpusFlags */
+ testDomainGetVcpusFlags, /* domainGetVcpusFlags */
testDomainPinVcpu, /* domainPinVcpu */
testDomainGetVcpus, /* domainGetVcpus */
testDomainGetMaxVcpus, /* domainGetMaxVcpus */
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index cb9193a..0cbe8b3 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -1839,13 +1839,21 @@ cleanup:
return ret;
}
-static int vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
+static int
+vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
+ unsigned int flags)
+{
VBOX_OBJECT_CHECK(dom->conn, int, -1);
IMachine *machine = NULL;
vboxIID *iid = NULL;
PRUint32 CPUCount = nvcpus;
nsresult rc;
+ if (flags != VIR_DOMAIN_VCPU_LIVE) {
+ vboxError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
+ return -1;
+ }
+
#if VBOX_API_VERSION == 2002
if (VIR_ALLOC(iid) < 0) {
virReportOOMError();
@@ -1887,11 +1895,24 @@ cleanup:
return ret;
}
-static int vboxDomainGetMaxVcpus(virDomainPtr dom) {
+static int
+vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
+{
+ return vboxDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
+}
+
+static int
+vboxDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
+{
VBOX_OBJECT_CHECK(dom->conn, int, -1);
ISystemProperties *systemProperties = NULL;
PRUint32 maxCPUCount = 0;
+ if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
+ vboxError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
+ return -1;
+ }
+
/* Currently every domain supports the same number of max cpus
* as that supported by vbox and thus take it directly from
* the systemproperties.
@@ -1909,6 +1930,13 @@ static int vboxDomainGetMaxVcpus(virDomainPtr dom) {
return ret;
}
+static int
+vboxDomainGetMaxVcpus(virDomainPtr dom)
+{
+ return vboxDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_MAXIMUM));
+}
+
static char *vboxDomainDumpXML(virDomainPtr dom, int flags) {
VBOX_OBJECT_CHECK(dom->conn, char *, NULL);
virDomainDefPtr def = NULL;
@@ -8267,8 +8295,8 @@ virDriver NAME(Driver) = {
NULL, /* domainRestore */
NULL, /* domainCoreDump */
vboxDomainSetVcpus, /* domainSetVcpus */
- NULL, /* domainSetVcpusFlags */
- NULL, /* domainGetVcpusFlags */
+ vboxDomainSetVcpusFlags, /* domainSetVcpusFlags */
+ vboxDomainGetVcpusFlags, /* domainGetVcpusFlags */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
vboxDomainGetMaxVcpus, /* domainGetMaxVcpus */
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c
index 7d67ced..d6c9c57 100644
--- a/src/xen/xen_driver.c
+++ b/src/xen/xen_driver.c
@@ -1069,11 +1069,18 @@ xenUnifiedDomainCoreDump (virDomainPtr dom, const char *to, int flags)
}
static int
-xenUnifiedDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus)
+xenUnifiedDomainSetVcpusFlags (virDomainPtr dom, unsigned int nvcpus,
+ unsigned int flags)
{
GET_PRIVATE(dom->conn);
int i;
+ if (flags != VIR_DOMAIN_VCPU_LIVE) {
+ xenUnifiedError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
+ flags);
+ return -1;
+ }
+
/* Try non-hypervisor methods first, then hypervisor direct method
* as a last resort.
*/
@@ -1093,6 +1100,12 @@ xenUnifiedDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus)
}
static int
+xenUnifiedDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus)
+{
+ return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
+}
+
+static int
xenUnifiedDomainPinVcpu (virDomainPtr dom, unsigned int vcpu,
unsigned char *cpumap, int maplen)
{
@@ -1126,11 +1139,17 @@ xenUnifiedDomainGetVcpus (virDomainPtr dom,
}
static int
-xenUnifiedDomainGetMaxVcpus (virDomainPtr dom)
+xenUnifiedDomainGetVcpusFlags (virDomainPtr dom, unsigned int flags)
{
GET_PRIVATE(dom->conn);
int i, ret;
+ if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
+ xenUnifiedError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
+ flags);
+ return -1;
+ }
+
for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
if (priv->opened[i] && drivers[i]->domainGetMaxVcpus) {
ret = drivers[i]->domainGetMaxVcpus (dom);
@@ -1140,6 +1159,13 @@ xenUnifiedDomainGetMaxVcpus (virDomainPtr dom)
return -1;
}
+static int
+xenUnifiedDomainGetMaxVcpus (virDomainPtr dom)
+{
+ return xenUnifiedDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_MAXIMUM));
+}
+
static char *
xenUnifiedDomainDumpXML (virDomainPtr dom, int flags)
{
@@ -1951,8 +1977,8 @@ static virDriver xenUnifiedDriver = {
xenUnifiedDomainRestore, /* domainRestore */
xenUnifiedDomainCoreDump, /* domainCoreDump */
xenUnifiedDomainSetVcpus, /* domainSetVcpus */
- NULL, /* domainSetVcpusFlags */
- NULL, /* domainGetVcpusFlags */
+ xenUnifiedDomainSetVcpusFlags, /* domainSetVcpusFlags */
+ xenUnifiedDomainGetVcpusFlags, /* domainGetVcpusFlags */
xenUnifiedDomainPinVcpu, /* domainPinVcpu */
xenUnifiedDomainGetVcpus, /* domainGetVcpus */
xenUnifiedDomainGetMaxVcpus, /* domainGetMaxVcpus */
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
index 753169c..7d4ab8d 100644
--- a/src/xenapi/xenapi_driver.c
+++ b/src/xenapi/xenapi_driver.c
@@ -40,6 +40,11 @@
#include "xenapi_driver_private.h"
#include "xenapi_utils.h"
+#define VIR_FROM_THIS VIR_FROM_XENAPI
+
+#define xenapiError(code, ...) \
+ virReportErrorHelper(NULL, VIR_FROM_THIS, code, __FILE__, \
+ __FUNCTION__, __LINE__, __VA_ARGS__)
/*
* getCapsObject
@@ -987,19 +992,26 @@ xenapiDomainGetInfo (virDomainPtr dom, virDomainInfoPtr info)
/*
- * xenapiDomainSetVcpus
+ * xenapiDomainSetVcpusFlags
*
* Sets the VCPUs on the domain
* Return 0 on success or -1 in case of error
*/
static int
-xenapiDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus)
+xenapiDomainSetVcpusFlags (virDomainPtr dom, unsigned int nvcpus,
+ unsigned int flags)
{
-
/* vm.set_vcpus_max */
xen_vm vm;
xen_vm_set *vms;
xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+
+ if (flags != VIR_DOMAIN_VCPU_LIVE) {
+ xenapiError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
+ flags);
+ return -1;
+ }
+
if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
if (vms->size != 1) {
xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,
@@ -1019,6 +1031,18 @@ xenapiDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus)
}
/*
+ * xenapiDomainSetVcpus
+ *
+ * Sets the VCPUs on the domain
+ * Return 0 on success or -1 in case of error
+ */
+static int
+xenapiDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus)
+{
+ return xenapiDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
+}
+
+/*
* xenapiDomainPinVcpu
*
* Dynamically change the real CPUs which can be allocated to a virtual CPU
@@ -1140,19 +1164,26 @@ xenapiDomainGetVcpus (virDomainPtr dom,
}
/*
- * xenapiDomainGetMaxVcpus
+ * xenapiDomainGetVcpusFlags
*
*
- * Returns maximum number of Vcpus on success or -1 in case of error
+ * Returns Vcpus count on success or -1 in case of error
*/
static int
-xenapiDomainGetMaxVcpus (virDomainPtr dom)
+xenapiDomainGetVcpusFlags (virDomainPtr dom, unsigned int flags)
{
xen_vm vm;
xen_vm_set *vms;
int64_t maxvcpu = 0;
enum xen_vm_power_state state;
xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+
+ if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
+ xenapiError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
+ flags);
+ return -1;
+ }
+
if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
if (vms->size != 1) {
xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,
@@ -1176,6 +1207,19 @@ xenapiDomainGetMaxVcpus (virDomainPtr dom)
}
/*
+ * xenapiDomainGetMaxVcpus
+ *
+ *
+ * Returns maximum number of Vcpus on success or -1 in case of error
+ */
+static int
+xenapiDomainGetMaxVcpus (virDomainPtr dom)
+{
+ return xenapiDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_MAXIMUM));
+}
+
+/*
* xenapiDomainDumpXML
*
*
@@ -1754,8 +1798,8 @@ static virDriver xenapiDriver = {
NULL, /* domainRestore */
NULL, /* domainCoreDump */
xenapiDomainSetVcpus, /* domainSetVcpus */
- NULL, /* domainSetVcpusFlags */
- NULL, /* domainGetVcpusFlags */
+ xenapiDomainSetVcpusFlags, /* domainSetVcpusFlags */
+ xenapiDomainGetVcpusFlags, /* domainGetVcpusFlags */
xenapiDomainPinVcpu, /* domainPinVcpu */
xenapiDomainGetVcpus, /* domainGetVcpus */
xenapiDomainGetMaxVcpus, /* domainGetMaxVcpus */
--
1.7.2.3

View File

@ -0,0 +1,388 @@
From bf945ee97b72d3b0c4fc2da04530f5294f529d66 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Wed, 29 Sep 2010 15:20:23 -0600
Subject: [PATCH 08/15] vcpu: add virsh support
* tools/virsh.c (cmdSetvcpus): Add new flags. Let invalid
commands through to driver, to ease testing of hypervisor argument
validation.
(cmdMaxvcpus, cmdVcpucount): New commands.
(commands): Add new commands.
* tools/virsh.pod (setvcpus, vcpucount, maxvcpus): Document new
behavior.
---
tools/virsh.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
tools/virsh.pod | 38 ++++++++-
2 files changed, 262 insertions(+), 23 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 4f8c495..7fb7fbd 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -2281,10 +2281,216 @@ cmdFreecell(vshControl *ctl, const vshCmd *cmd)
}
/*
+ * "maxvcpus" command
+ */
+static const vshCmdInfo info_maxvcpus[] = {
+ {"help", N_("connection vcpu maximum")},
+ {"desc", N_("Show maximum number of virtual CPUs for guests on this connection.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_maxvcpus[] = {
+ {"type", VSH_OT_STRING, 0, N_("domain type")},
+ {NULL, 0, 0, NULL}
+};
+
+static int
+cmdMaxvcpus(vshControl *ctl, const vshCmd *cmd)
+{
+ char *type;
+ int vcpus;
+
+ type = vshCommandOptString(cmd, "type", NULL);
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return FALSE;
+
+ vcpus = virConnectGetMaxVcpus(ctl->conn, type);
+ if (vcpus < 0)
+ return FALSE;
+ vshPrint(ctl, "%d\n", vcpus);
+
+ return TRUE;
+}
+
+/*
+ * "vcpucount" command
+ */
+static const vshCmdInfo info_vcpucount[] = {
+ {"help", N_("domain vcpu counts")},
+ {"desc", N_("Returns the number of virtual CPUs used by the domain.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vcpucount[] = {
+ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+ {"maximum", VSH_OT_BOOL, 0, N_("get maximum cap on vcpus")},
+ {"current", VSH_OT_BOOL, 0, N_("get current vcpu usage")},
+ {"config", VSH_OT_BOOL, 0, N_("get value to be used on next boot")},
+ {"live", VSH_OT_BOOL, 0, N_("get value from running domain")},
+ {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVcpucount(vshControl *ctl, const vshCmd *cmd)
+{
+ virDomainPtr dom;
+ int ret = TRUE;
+ int maximum = vshCommandOptBool(cmd, "maximum");
+ int current = vshCommandOptBool(cmd, "current");
+ int config = vshCommandOptBool(cmd, "config");
+ int live = vshCommandOptBool(cmd, "live");
+ bool all = maximum + current + config + live == 0;
+ int count;
+
+ if (maximum && current) {
+ vshError(ctl, "%s",
+ _("--maximum and --current cannot both be specified"));
+ return FALSE;
+ }
+ if (config && live) {
+ vshError(ctl, "%s",
+ _("--config and --live cannot both be specified"));
+ return FALSE;
+ }
+ /* We want one of each pair of mutually exclusive options; that
+ * is, use of flags requires exactly two options. */
+ if (maximum + current + config + live == 1) {
+ vshError(ctl,
+ _("when using --%s, either --%s or --%s must be specified"),
+ (maximum ? "maximum" : current ? "current"
+ : config ? "config" : "live"),
+ maximum + current ? "config" : "maximum",
+ maximum + current ? "live" : "current");
+ return FALSE;
+ }
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return FALSE;
+
+ if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ return FALSE;
+
+ /* In all cases, try the new API first; if it fails because we are
+ * talking to an older client, try a fallback API before giving
+ * up. */
+ if (all || (maximum && config)) {
+ count = virDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_MAXIMUM |
+ VIR_DOMAIN_VCPU_CONFIG));
+ if (count < 0 && (last_error->code == VIR_ERR_NO_SUPPORT
+ || last_error->code == VIR_ERR_INVALID_ARG)) {
+ char *tmp;
+ char *xml = virDomainGetXMLDesc(dom, VIR_DOMAIN_XML_INACTIVE);
+ if (xml && (tmp = strstr(xml, "<vcpu"))) {
+ tmp = strchr(tmp, '>');
+ if (!tmp || virStrToLong_i(tmp + 1, &tmp, 10, &count) < 0)
+ count = -1;
+ }
+ VIR_FREE(xml);
+ }
+
+ if (count < 0) {
+ virshReportError(ctl);
+ ret = FALSE;
+ } else if (all) {
+ vshPrint(ctl, "%-12s %-12s %3d\n", _("maximum"), _("config"),
+ count);
+ } else {
+ vshPrint(ctl, "%d\n", count);
+ }
+ virFreeError(last_error);
+ last_error = NULL;
+ }
+
+ if (all || (maximum && live)) {
+ count = virDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_MAXIMUM |
+ VIR_DOMAIN_VCPU_LIVE));
+ if (count < 0 && (last_error->code == VIR_ERR_NO_SUPPORT
+ || last_error->code == VIR_ERR_INVALID_ARG)) {
+ count = virDomainGetMaxVcpus(dom);
+ }
+
+ if (count < 0) {
+ virshReportError(ctl);
+ ret = FALSE;
+ } else if (all) {
+ vshPrint(ctl, "%-12s %-12s %3d\n", _("maximum"), _("live"),
+ count);
+ } else {
+ vshPrint(ctl, "%d\n", count);
+ }
+ virFreeError(last_error);
+ last_error = NULL;
+ }
+
+ if (all || (current && config)) {
+ count = virDomainGetVcpusFlags(dom, VIR_DOMAIN_VCPU_CONFIG);
+ if (count < 0 && (last_error->code == VIR_ERR_NO_SUPPORT
+ || last_error->code == VIR_ERR_INVALID_ARG)) {
+ char *tmp, *end;
+ char *xml = virDomainGetXMLDesc(dom, VIR_DOMAIN_XML_INACTIVE);
+ if (xml && (tmp = strstr(xml, "<vcpu"))) {
+ end = strchr(tmp, '>');
+ if (end) {
+ *end = '\0';
+ tmp = strstr(tmp, "current=");
+ if (!tmp)
+ tmp = end + 1;
+ else {
+ tmp += strlen("current=");
+ tmp += *tmp == '\'' || *tmp == '"';
+ }
+ }
+ if (!tmp || virStrToLong_i(tmp, &tmp, 10, &count) < 0)
+ count = -1;
+ }
+ VIR_FREE(xml);
+ }
+
+ if (count < 0) {
+ virshReportError(ctl);
+ ret = FALSE;
+ } else if (all) {
+ vshPrint(ctl, "%-12s %-12s %3d\n", _("current"), _("config"),
+ count);
+ } else {
+ vshPrint(ctl, "%d\n", count);
+ }
+ virFreeError(last_error);
+ last_error = NULL;
+ }
+
+ if (all || (current && live)) {
+ count = virDomainGetVcpusFlags(dom, VIR_DOMAIN_VCPU_LIVE);
+ if (count < 0 && (last_error->code == VIR_ERR_NO_SUPPORT
+ || last_error->code == VIR_ERR_INVALID_ARG)) {
+ virDomainInfo info;
+ if (virDomainGetInfo(dom, &info) == 0)
+ count = info.nrVirtCpu;
+ }
+
+ if (count < 0) {
+ virshReportError(ctl);
+ ret = FALSE;
+ } else if (all) {
+ vshPrint(ctl, "%-12s %-12s %3d\n", _("current"), _("live"),
+ count);
+ } else {
+ vshPrint(ctl, "%d\n", count);
+ }
+ virFreeError(last_error);
+ last_error = NULL;
+ }
+
+ virDomainFree(dom);
+ return ret;
+}
+
+/*
* "vcpuinfo" command
*/
static const vshCmdInfo info_vcpuinfo[] = {
- {"help", N_("domain vcpu information")},
+ {"help", N_("detailed domain vcpu information")},
{"desc", N_("Returns basic information about the domain virtual CPUs.")},
{NULL, NULL}
};
@@ -2514,6 +2720,9 @@ static const vshCmdInfo info_setvcpus[] = {
static const vshCmdOptDef opts_setvcpus[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"count", VSH_OT_DATA, VSH_OFLAG_REQ, N_("number of virtual CPUs")},
+ {"maximum", VSH_OT_BOOL, 0, N_("set maximum limit on next boot")},
+ {"config", VSH_OT_BOOL, 0, N_("affect next boot")},
+ {"live", VSH_OT_BOOL, 0, N_("affect running domain")},
{NULL, 0, 0, NULL}
};
@@ -2522,8 +2731,13 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
int count;
- int maxcpu;
int ret = TRUE;
+ int maximum = vshCommandOptBool(cmd, "maximum");
+ int config = vshCommandOptBool(cmd, "config");
+ int live = vshCommandOptBool(cmd, "live");
+ int flags = ((maximum ? VIR_DOMAIN_VCPU_MAXIMUM : 0) |
+ (config ? VIR_DOMAIN_VCPU_CONFIG : 0) |
+ (live ? VIR_DOMAIN_VCPU_LIVE : 0));
if (!vshConnectionUsability(ctl, ctl->conn))
return FALSE;
@@ -2532,26 +2746,15 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd)
return FALSE;
count = vshCommandOptInt(cmd, "count", &count);
- if (count <= 0) {
- vshError(ctl, "%s", _("Invalid number of virtual CPUs."));
- virDomainFree(dom);
- return FALSE;
- }
-
- maxcpu = virDomainGetMaxVcpus(dom);
- if (maxcpu <= 0) {
- virDomainFree(dom);
- return FALSE;
- }
-
- if (count > maxcpu) {
- vshError(ctl, "%s", _("Too many virtual CPUs."));
- virDomainFree(dom);
- return FALSE;
- }
- if (virDomainSetVcpus(dom, count) != 0) {
- ret = FALSE;
+ if (!flags) {
+ if (virDomainSetVcpus(dom, count) != 0) {
+ ret = FALSE;
+ }
+ } else {
+ if (virDomainSetVcpusFlags(dom, count, flags) < 0) {
+ ret = FALSE;
+ }
}
virDomainFree(dom);
@@ -9642,6 +9845,7 @@ static const vshCmdDef commands[] = {
{"freecell", cmdFreecell, opts_freecell, info_freecell},
{"hostname", cmdHostname, NULL, info_hostname},
{"list", cmdList, opts_list, info_list},
+ {"maxvcpus", cmdMaxvcpus, opts_maxvcpus, info_maxvcpus},
{"migrate", cmdMigrate, opts_migrate, info_migrate},
{"migrate-setmaxdowntime", cmdMigrateSetMaxDowntime, opts_migrate_setmaxdowntime, info_migrate_setmaxdowntime},
@@ -9748,6 +9952,7 @@ static const vshCmdDef commands[] = {
{"vol-name", cmdVolName, opts_vol_name, info_vol_name},
{"vol-key", cmdVolKey, opts_vol_key, info_vol_key},
+ {"vcpucount", cmdVcpucount, opts_vcpucount, info_vcpucount},
{"vcpuinfo", cmdVcpuinfo, opts_vcpuinfo, info_vcpuinfo},
{"vcpupin", cmdVcpupin, opts_vcpupin, info_vcpupin},
{"version", cmdVersion, NULL, info_version},
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 943a563..dbcc680 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -443,7 +443,14 @@ Remove the managed save file for a domain if it exists. The next time the
domain is started it will not restore to its previous state but instead will
do a full boot.
-=item B<migrate> optional I<--live> I<--suspend> I<domain-id> I<desturi> I<migrateuri>
+=item B<maxvcpus> optional I<type>
+
+Provide the maximum number of virtual CPUs supported for a guest VM on
+this connection. If provided, the I<type> parameter must be a valid
+type attribute for the <domain> element of XML.
+
+=item B<migrate> optional I<--live> I<--suspend> I<domain-id> I<desturi>
+I<migrateuri>
Migrate domain to another host. Add --live for live migration; --suspend
leaves the domain paused on the destination host. The I<desturi> is the
@@ -521,7 +528,8 @@ Displays the domain memory parameters.
Allows you to set the domain memory parameters. LXC and QEMU/KVM supports these parameters.
-=item B<setvcpus> I<domain-id> I<count>
+=item B<setvcpus> I<domain-id> I<count> optional I<--maximum> I<--config>
+I<--live>
Change the number of virtual CPUs active in the guest domain. Note that
I<count> may be limited by host, hypervisor or limit coming from the
@@ -530,6 +538,17 @@ original description of domain.
For Xen, you can only adjust the virtual CPUs of a running domain if
the domain is paravirtualized.
+If I<--config> is specified, the change will only affect the next
+boot of a domain. If I<--live> is specified, the domain must be
+running, and the change takes place immediately. Both flags may be
+specified, if supported by the hypervisor. If neither flag is given,
+then I<--live> is implied and it is up to the hypervisor whether
+I<--config> is also implied.
+
+If I<--maximum> is specified, then you must use I<--config> and
+avoid I<--live>; this flag controls the maximum limit of vcpus that
+can be hot-plugged the next time the domain is booted.
+
=item B<shutdown> I<domain-id>
Gracefully shuts down a domain. This coordinates with the domain OS
@@ -568,6 +587,21 @@ is not available the processes will provide an exit code of 1.
Undefine the configuration for an inactive domain. Since it's not running
the domain name or UUID must be used as the I<domain-id>.
+=item B<vcpucount> I<domain-id> optional I<--maximum> I<--current>
+I<--config> I<--live>
+
+Print information about the virtual cpu counts of the given
+I<domain-id>. If no flags are specified, all possible counts are
+listed in a table; otherwise, the output is limited to just the
+numeric value requested.
+
+I<--maximum> requests information on the maximum cap of vcpus that a
+domain can add via B<setvcpus>, while I<--current> shows the current
+usage; these two flags cannot both be specified. I<--config>
+requests information regarding the next time the domain will be
+booted, while I<--live> requires a running domain and lists current
+values; these two flags cannot both be specified.
+
=item B<vcpuinfo> I<domain-id>
Returns basic information about the domain virtual CPUs, like the number of
--
1.7.2.3

View File

@ -0,0 +1,519 @@
From 4617eedfaeee2b187a1f14691d25746ba3ff31b6 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Wed, 29 Sep 2010 10:20:07 -0600
Subject: [PATCH 07/15] vcpu: support maxvcpu in domain_conf
Although this patch adds a distinction between maximum vcpus and
current vcpus in the XML, the values should be identical for all
drivers at this point. Only in subsequent per-driver patches will
a distinction be made.
In general, virDomainGetInfo should prefer the current vcpus.
* src/conf/domain_conf.h (_virDomainDef): Adjust vcpus to unsigned
short, to match virDomainGetInfo limit. Add maxvcpus member.
* src/conf/domain_conf.c (virDomainDefParseXML)
(virDomainDefFormat): parse and print out vcpu details.
* src/xen/xend_internal.c (xenDaemonParseSxpr)
(xenDaemonFormatSxpr): Manage both vcpu numbers, and require them
to be equal for now.
* src/xen/xm_internal.c (xenXMDomainConfigParse)
(xenXMDomainConfigFormat): Likewise.
* src/phyp/phyp_driver.c (phypDomainDumpXML): Likewise.
* src/openvz/openvz_conf.c (openvzLoadDomains): Likewise.
* src/openvz/openvz_driver.c (openvzDomainDefineXML)
(openvzDomainCreateXML, openvzDomainSetVcpusInternal): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainDumpXML, vboxDomainDefineXML):
Likewise.
* src/xenapi/xenapi_driver.c (xenapiDomainDumpXML): Likewise.
* src/xenapi/xenapi_utils.c (createVMRecordFromXml): Likewise.
* src/esx/esx_vmx.c (esxVMX_ParseConfig, esxVMX_FormatConfig):
Likewise.
* src/qemu/qemu_conf.c (qemuBuildSmpArgStr)
(qemuParseCommandLineSmp, qemuParseCommandLine): Likewise.
* src/qemu/qemu_driver.c (qemudDomainHotplugVcpus): Likewise.
* src/opennebula/one_conf.c (xmlOneTemplate): Likewise.
---
src/conf/domain_conf.c | 45 +++++++++++++++++++++++++++++++++++++------
src/conf/domain_conf.h | 3 +-
src/esx/esx_vmx.c | 24 ++++++++++++++--------
src/opennebula/one_conf.c | 9 +++++--
src/openvz/openvz_conf.c | 7 +++--
src/openvz/openvz_driver.c | 15 +++++++++----
src/phyp/phyp_driver.c | 2 +-
src/qemu/qemu_conf.c | 14 +++++++++++-
src/qemu/qemu_driver.c | 5 ++-
src/vbox/vbox_tmpl.c | 12 +++++++---
src/xen/xend_internal.c | 9 ++++---
src/xen/xm_internal.c | 11 ++++++---
src/xenapi/xenapi_driver.c | 2 +-
src/xenapi/xenapi_utils.c | 4 +-
14 files changed, 114 insertions(+), 48 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 78d7a6a..a997e06 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4203,6 +4203,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
int i, n;
long id = -1;
virDomainDefPtr def;
+ unsigned long count;
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
@@ -4287,8 +4288,37 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
&def->mem.swap_hard_limit) < 0)
def->mem.swap_hard_limit = 0;
- if (virXPathULong("string(./vcpu[1])", ctxt, &def->vcpus) < 0)
- def->vcpus = 1;
+ n = virXPathULong("string(./vcpu[1])", ctxt, &count);
+ if (n == -2) {
+ virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+ _("maximum vcpus must be an integer"));
+ goto error;
+ } else if (n < 0) {
+ def->maxvcpus = 1;
+ } else {
+ def->maxvcpus = count;
+ if (def->maxvcpus != count || count == 0) {
+ virDomainReportError(VIR_ERR_XML_ERROR,
+ _("invalid maxvcpus %lu"), count);
+ goto error;
+ }
+ }
+
+ n = virXPathULong("string(./vcpu[1]/@current)", ctxt, &count);
+ if (n == -2) {
+ virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+ _("current vcpus must be an integer"));
+ goto error;
+ } else if (n < 0) {
+ def->vcpus = def->maxvcpus;
+ } else {
+ def->vcpus = count;
+ if (def->vcpus != count || count == 0 || def->maxvcpus < count) {
+ virDomainReportError(VIR_ERR_XML_ERROR,
+ _("invalid current vcpus %lu"), count);
+ goto error;
+ }
+ }
tmp = virXPathString("string(./vcpu[1]/@cpuset)", ctxt);
if (tmp) {
@@ -6462,17 +6492,18 @@ char *virDomainDefFormat(virDomainDefPtr def,
if (def->cpumask[n] != 1)
allones = 0;
- if (allones) {
- virBufferAsprintf(&buf, " <vcpu>%lu</vcpu>\n", def->vcpus);
- } else {
+ virBufferAddLit(&buf, " <vcpu");
+ if (!allones) {
char *cpumask = NULL;
if ((cpumask =
virDomainCpuSetFormat(def->cpumask, def->cpumasklen)) == NULL)
goto cleanup;
- virBufferAsprintf(&buf, " <vcpu cpuset='%s'>%lu</vcpu>\n",
- cpumask, def->vcpus);
+ virBufferAsprintf(&buf, " cpuset='%s'", cpumask);
VIR_FREE(cpumask);
}
+ if (def->vcpus != def->maxvcpus)
+ virBufferAsprintf(&buf, " current='%u'", def->vcpus);
+ virBufferAsprintf(&buf, ">%u</vcpu>\n", def->maxvcpus);
if (def->os.bootloader) {
virBufferEscapeString(&buf, " <bootloader>%s</bootloader>\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index db09c23..5499f28 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -885,7 +885,8 @@ struct _virDomainDef {
unsigned long min_guarantee;
unsigned long swap_hard_limit;
} mem;
- unsigned long vcpus;
+ unsigned short vcpus;
+ unsigned short maxvcpus;
int cpumasklen;
char *cpumask;
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
index 7ec8c0e..0a26614 100644
--- a/src/esx/esx_vmx.c
+++ b/src/esx/esx_vmx.c
@@ -50,7 +50,7 @@ def->uuid = <value> <=> uuid.bios = "<value>"
def->name = <value> <=> displayName = "<value>"
def->mem.max_balloon = <value kilobyte> <=> memsize = "<value megabyte>" # must be a multiple of 4, defaults to 32
def->mem.cur_balloon = <value kilobyte> <=> sched.mem.max = "<value megabyte>" # defaults to "unlimited" -> def->mem.cur_balloon = def->mem.max_balloon
-def->vcpus = <value> <=> numvcpus = "<value>" # must be 1 or a multiple of 2, defaults to 1
+def->maxvcpus = <value> <=> numvcpus = "<value>" # must be 1 or a multiple of 2, defaults to 1
def->cpumask = <uint list> <=> sched.cpu.affinity = "<uint list>"
@@ -1075,7 +1075,7 @@ esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char *vmx,
goto cleanup;
}
- def->vcpus = numvcpus;
+ def->maxvcpus = def->vcpus = numvcpus;
/* vmx:sched.cpu.affinity -> def:cpumask */
// VirtualMachine:config.cpuAffinity.affinitySet
@@ -2609,16 +2609,22 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
(int)(def->mem.cur_balloon / 1024));
}
- /* def:vcpus -> vmx:numvcpus */
- if (def->vcpus <= 0 || (def->vcpus % 2 != 0 && def->vcpus != 1)) {
+ /* def:maxvcpus -> vmx:numvcpus */
+ if (def->vcpus != def->maxvcpus) {
+ ESX_ERROR(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("No support for domain XML entry 'vcpu' attribute "
+ "'current'"));
+ goto cleanup;
+ }
+ if (def->maxvcpus <= 0 || (def->maxvcpus % 2 != 0 && def->maxvcpus != 1)) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting domain XML entry 'vcpu' to be an unsigned "
"integer (1 or a multiple of 2) but found %d"),
- (int)def->vcpus);
+ def->maxvcpus);
goto cleanup;
}
- virBufferAsprintf(&buffer, "numvcpus = \"%d\"\n", (int)def->vcpus);
+ virBufferAsprintf(&buffer, "numvcpus = \"%d\"\n", def->maxvcpus);
/* def:cpumask -> vmx:sched.cpu.affinity */
if (def->cpumasklen > 0) {
@@ -2632,11 +2638,11 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
}
}
- if (sched_cpu_affinity_length < def->vcpus) {
+ if (sched_cpu_affinity_length < def->maxvcpus) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting domain XML attribute 'cpuset' of entry "
- "'vcpu' to contains at least %d CPU(s)"),
- (int)def->vcpus);
+ "'vcpu' to contain at least %d CPU(s)"),
+ def->maxvcpus);
goto cleanup;
}
diff --git a/src/opennebula/one_conf.c b/src/opennebula/one_conf.c
index 44e28dc..2079c51 100644
--- a/src/opennebula/one_conf.c
+++ b/src/opennebula/one_conf.c
@@ -1,5 +1,7 @@
/*----------------------------------------------------------------------------------*/
-/* Copyright 2002-2009, Distributed Systems Architecture Group, Universidad
+/*
+ * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright 2002-2009, Distributed Systems Architecture Group, Universidad
* Complutense de Madrid (dsa-research.org)
*
* This library is free software; you can redistribute it and/or
@@ -169,9 +171,10 @@ char* xmlOneTemplate(virDomainDefPtr def)
{
int i;
virBuffer buf= VIR_BUFFER_INITIALIZER;
- virBufferAsprintf(&buf,"#OpenNebula Template automatically generated by libvirt\nNAME = %s\nCPU = %ld\nMEMORY = %ld\n",
+ virBufferAsprintf(&buf,"#OpenNebula Template automatically generated "
+ "by libvirt\nNAME = %s\nCPU = %d\nMEMORY = %ld\n",
def->name,
- def->vcpus,
+ def->maxvcpus,
(def->mem.max_balloon)/1024);
/*Optional Booting OpenNebula Information:*/
diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c
index ec11bbc..c84a6f3 100644
--- a/src/openvz/openvz_conf.c
+++ b/src/openvz/openvz_conf.c
@@ -507,11 +507,12 @@ int openvzLoadDomains(struct openvz_driver *driver) {
veid);
goto cleanup;
} else if (ret > 0) {
- dom->def->vcpus = strtoI(temp);
+ dom->def->maxvcpus = strtoI(temp);
}
- if (ret == 0 || dom->def->vcpus == 0)
- dom->def->vcpus = openvzGetNodeCPUs();
+ if (ret == 0 || dom->def->maxvcpus == 0)
+ dom->def->maxvcpus = openvzGetNodeCPUs();
+ dom->def->vcpus = dom->def->maxvcpus;
/* XXX load rest of VM config data .... */
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index 0f3cfdf..b7c2754 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -925,8 +925,13 @@ openvzDomainDefineXML(virConnectPtr conn, const char *xml)
if (openvzDomainSetNetworkConfig(conn, vm->def) < 0)
goto cleanup;
- if (vm->def->vcpus > 0) {
- if (openvzDomainSetVcpusInternal(vm, vm->def->vcpus) < 0) {
+ if (vm->def->vcpus != vm->def->maxvcpus) {
+ openvzError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("current vcpu count must equal maximum"));
+ goto cleanup;
+ }
+ if (vm->def->maxvcpus > 0) {
+ if (openvzDomainSetVcpusInternal(vm, vm->def->maxvcpus) < 0) {
openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not set number of virtual cpu"));
goto cleanup;
@@ -1019,8 +1024,8 @@ openvzDomainCreateXML(virConnectPtr conn, const char *xml,
vm->def->id = vm->pid;
vm->state = VIR_DOMAIN_RUNNING;
- if (vm->def->vcpus > 0) {
- if (openvzDomainSetVcpusInternal(vm, vm->def->vcpus) < 0) {
+ if (vm->def->maxvcpus > 0) {
+ if (openvzDomainSetVcpusInternal(vm, vm->def->maxvcpus) < 0) {
openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not set number of virtual cpu"));
goto cleanup;
@@ -1249,7 +1254,7 @@ static int openvzDomainSetVcpusInternal(virDomainObjPtr vm,
return -1;
}
- vm->def->vcpus = nvcpus;
+ vm->def->maxvcpus = vm->def->vcpus = nvcpus;
return 0;
}
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
index e284ae0..3d0ed11 100644
--- a/src/phyp/phyp_driver.c
+++ b/src/phyp/phyp_driver.c
@@ -3540,7 +3540,7 @@ phypDomainDumpXML(virDomainPtr dom, int flags)
goto err;
}
- if ((def.vcpus =
+ if ((def.maxvcpus = def.vcpus =
phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0) {
VIR_ERROR0(_("Unable to determine domain's CPU."));
goto err;
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 83c0f83..38c8351 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -3711,7 +3711,7 @@ qemuBuildSmpArgStr(const virDomainDefPtr def,
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
- virBufferAsprintf(&buf, "%lu", def->vcpus);
+ virBufferAsprintf(&buf, "%u", def->vcpus);
if ((qemuCmdFlags & QEMUD_CMD_FLAG_SMP_TOPOLOGY)) {
/* sockets, cores, and threads are either all zero
@@ -3722,11 +3722,18 @@ qemuBuildSmpArgStr(const virDomainDefPtr def,
virBufferAsprintf(&buf, ",threads=%u", def->cpu->threads);
}
else {
- virBufferAsprintf(&buf, ",sockets=%lu", def->vcpus);
+ virBufferAsprintf(&buf, ",sockets=%u", def->maxvcpus);
virBufferAsprintf(&buf, ",cores=%u", 1);
virBufferAsprintf(&buf, ",threads=%u", 1);
}
}
+ if (def->vcpus != def->maxvcpus) {
+ virBufferFreeAndReset(&buf);
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("setting current vcpu count less than maximum is "
+ "not supported yet"));
+ return NULL;
+ }
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
@@ -6178,6 +6185,8 @@ qemuParseCommandLineSmp(virDomainDefPtr dom,
}
}
+ dom->maxvcpus = dom->vcpus;
+
if (sockets && cores && threads) {
virCPUDefPtr cpu;
@@ -6247,6 +6256,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
def->id = -1;
def->mem.cur_balloon = def->mem.max_balloon = 64 * 1024;
+ def->maxvcpus = 1;
def->vcpus = 1;
def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC;
def->features = (1 << VIR_DOMAIN_FEATURE_ACPI)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 7a2ea8f..c66dc04 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2425,8 +2425,9 @@ qemuDetectVcpuPIDs(struct qemud_driver *driver,
if (ncpupids != vm->def->vcpus) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
- _("got wrong number of vCPU pids from QEMU monitor. got %d, wanted %d"),
- ncpupids, (int)vm->def->vcpus);
+ _("got wrong number of vCPU pids from QEMU monitor. "
+ "got %d, wanted %d"),
+ ncpupids, vm->def->vcpus);
VIR_FREE(cpupids);
return -1;
}
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 0cbe8b3..5a859a4 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -2028,7 +2028,7 @@ static char *vboxDomainDumpXML(virDomainPtr dom, int flags) {
def->mem.max_balloon = memorySize * 1024;
machine->vtbl->GetCPUCount(machine, &CPUCount);
- def->vcpus = CPUCount;
+ def->maxvcpus = def->vcpus = CPUCount;
/* Skip cpumasklen, cpumask, onReboot, onPoweroff, onCrash */
@@ -4598,11 +4598,15 @@ static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml) {
def->mem.cur_balloon, (unsigned)rc);
}
- rc = machine->vtbl->SetCPUCount(machine, def->vcpus);
+ if (def->vcpus != def->maxvcpus) {
+ vboxError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("current vcpu count must equal maximum"));
+ }
+ rc = machine->vtbl->SetCPUCount(machine, def->maxvcpus);
if (NS_FAILED(rc)) {
vboxError(VIR_ERR_INTERNAL_ERROR,
- _("could not set the number of virtual CPUs to: %lu, rc=%08x"),
- def->vcpus, (unsigned)rc);
+ _("could not set the number of virtual CPUs to: %u, rc=%08x"),
+ def->maxvcpus, (unsigned)rc);
}
#if VBOX_API_VERSION < 3001
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index 5ffc3c8..456b477 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -2190,7 +2190,8 @@ xenDaemonParseSxpr(virConnectPtr conn,
}
}
- def->vcpus = sexpr_int(root, "domain/vcpus");
+ def->maxvcpus = sexpr_int(root, "domain/vcpus");
+ def->vcpus = def->maxvcpus;
tmp = sexpr_node(root, "domain/on_poweroff");
if (tmp != NULL) {
@@ -5649,7 +5650,7 @@ xenDaemonFormatSxprInput(virDomainInputDefPtr input,
*
* Generate an SEXPR representing the domain configuration.
*
- * Returns the 0 terminatedi S-Expr string or NULL in case of error.
+ * Returns the 0 terminated S-Expr string or NULL in case of error.
* the caller must free() the returned value.
*/
char *
@@ -5666,7 +5667,7 @@ xenDaemonFormatSxpr(virConnectPtr conn,
virBufferAsprintf(&buf, "(name '%s')", def->name);
virBufferAsprintf(&buf, "(memory %lu)(maxmem %lu)",
def->mem.cur_balloon/1024, def->mem.max_balloon/1024);
- virBufferAsprintf(&buf, "(vcpus %lu)", def->vcpus);
+ virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus);
if (def->cpumask) {
char *ranges = virDomainCpuSetFormat(def->cpumask, def->cpumasklen);
@@ -5761,7 +5762,7 @@ xenDaemonFormatSxpr(virConnectPtr conn,
else
virBufferAsprintf(&buf, "(kernel '%s')", def->os.loader);
- virBufferAsprintf(&buf, "(vcpus %lu)", def->vcpus);
+ virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus);
for (i = 0 ; i < def->os.nBootDevs ; i++) {
switch (def->os.bootDevs[i]) {
diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
index 8e42a1c..bf20a64 100644
--- a/src/xen/xm_internal.c
+++ b/src/xen/xm_internal.c
@@ -678,6 +678,7 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
int i;
const char *defaultArch, *defaultMachine;
int vmlocaltime = 0;
+ unsigned long count;
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
@@ -770,9 +771,11 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
def->mem.cur_balloon *= 1024;
def->mem.max_balloon *= 1024;
-
- if (xenXMConfigGetULong(conf, "vcpus", &def->vcpus, 1) < 0)
+ if (xenXMConfigGetULong(conf, "vcpus", &count, 1) < 0 ||
+ (unsigned short) count != count)
goto cleanup;
+ def->maxvcpus = count;
+ def->vcpus = def->maxvcpus;
if (xenXMConfigGetString(conf, "cpus", &str, NULL) < 0)
goto cleanup;
@@ -1650,7 +1653,7 @@ int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus) {
if (!(entry = virHashLookup(priv->configCache, filename)))
goto cleanup;
- entry->def->vcpus = vcpus;
+ entry->def->maxvcpus = entry->def->vcpus = vcpus;
/* If this fails, should we try to undo our changes to the
* in-memory representation of the config file. I say not!
@@ -2241,7 +2244,7 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn,
if (xenXMConfigSetInt(conf, "memory", def->mem.cur_balloon / 1024) < 0)
goto no_memory;
- if (xenXMConfigSetInt(conf, "vcpus", def->vcpus) < 0)
+ if (xenXMConfigSetInt(conf, "vcpus", def->maxvcpus) < 0)
goto no_memory;
if ((def->cpumask != NULL) &&
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
index 7d4ab8d..5ccdede 100644
--- a/src/xenapi/xenapi_driver.c
+++ b/src/xenapi/xenapi_driver.c
@@ -1335,7 +1335,7 @@ xenapiDomainDumpXML (virDomainPtr dom, int flags ATTRIBUTE_UNUSED)
} else {
defPtr->mem.cur_balloon = memory;
}
- defPtr->vcpus = xenapiDomainGetMaxVcpus(dom);
+ defPtr->maxvcpus = defPtr->vcpus = xenapiDomainGetMaxVcpus(dom);
enum xen_on_normal_exit action;
if (xen_vm_get_actions_after_shutdown(session, &action, vm)) {
defPtr->onPoweroff = xenapiNormalExitEnum2virDomainLifecycle(action);
diff --git a/src/xenapi/xenapi_utils.c b/src/xenapi/xenapi_utils.c
index be55491..a7e2a4b 100644
--- a/src/xenapi/xenapi_utils.c
+++ b/src/xenapi/xenapi_utils.c
@@ -510,8 +510,8 @@ createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr def,
else
(*record)->memory_dynamic_max = (*record)->memory_static_max;
- if (def->vcpus) {
- (*record)->vcpus_max = (int64_t) def->vcpus;
+ if (def->maxvcpus) {
+ (*record)->vcpus_max = (int64_t) def->maxvcpus;
(*record)->vcpus_at_startup = (int64_t) def->vcpus;
}
if (def->onPoweroff)
--
1.7.2.3

View File

@ -0,0 +1,197 @@
From 6c9e6b956453d0f0c4ff542ef8a184d663a39266 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Mon, 4 Oct 2010 17:01:12 -0600
Subject: [PATCH 09/15] vcpu: support all flags in test driver
* src/test/test_driver.c (testDomainGetVcpusFlags)
(testDomainSetVcpusFlags): Support all flags.
(testDomainUpdateVCPUs): Update cpu count here.
---
src/test/test_driver.c | 128 ++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 109 insertions(+), 19 deletions(-)
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index b70c80d..a9d3d89 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -450,6 +450,7 @@ testDomainUpdateVCPUs(virConnectPtr conn,
goto cleanup;
}
+ dom->def->vcpus = nvcpus;
ret = 0;
cleanup:
return ret;
@@ -2032,12 +2033,51 @@ cleanup:
static int
testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
{
- if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
- testError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
+ testConnPtr privconn = domain->conn->privateData;
+ virDomainObjPtr vm;
+ virDomainDefPtr def;
+ int ret = -1;
+
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_CONFIG |
+ VIR_DOMAIN_VCPU_MAXIMUM, -1);
+
+ /* Exactly one of LIVE or CONFIG must be set. */
+ if (!(flags & VIR_DOMAIN_VCPU_LIVE) == !(flags & VIR_DOMAIN_VCPU_CONFIG)) {
+ testError(VIR_ERR_INVALID_ARG,
+ _("invalid flag combination: (0x%x)"), flags);
return -1;
}
- return testGetMaxVCPUs(domain->conn, "test");
+ testDriverLock(privconn);
+ vm = virDomainFindByUUID(&privconn->domains, domain->uuid);
+ testDriverUnlock(privconn);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(domain->uuid, uuidstr);
+ testError(VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
+ goto cleanup;
+ }
+
+ if (flags & VIR_DOMAIN_VCPU_LIVE) {
+ if (!virDomainObjIsActive(vm)) {
+ testError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain not active"));
+ goto cleanup;
+ }
+ def = vm->def;
+ } else {
+ def = vm->newDef ? vm->newDef : vm->def;
+ }
+
+ ret = (flags & VIR_DOMAIN_VCPU_MAXIMUM) ? def->maxvcpus : def->vcpus;
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ return ret;
}
static int
@@ -2053,21 +2093,30 @@ testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
{
testConnPtr privconn = domain->conn->privateData;
virDomainObjPtr privdom = NULL;
+ virDomainDefPtr def;
int ret = -1, maxvcpus;
- if (flags != VIR_DOMAIN_VCPU_LIVE) {
- testError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_CONFIG |
+ VIR_DOMAIN_VCPU_MAXIMUM, -1);
+
+ /* At least one of LIVE or CONFIG must be set. MAXIMUM cannot be
+ * mixed with LIVE. */
+ if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0 ||
+ (flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) ==
+ (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) {
+ testError(VIR_ERR_INVALID_ARG,
+ _("invalid flag combination: (0x%x)"), flags);
+ return -1;
+ }
+ if (!nrCpus || (maxvcpus = testGetMaxVCPUs(domain->conn, NULL)) < nrCpus) {
+ testError(VIR_ERR_INVALID_ARG,
+ _("argument out of range: %d"), nrCpus);
return -1;
}
-
- /* Do this first before locking */
- maxvcpus = testDomainGetMaxVcpus(domain);
- if (maxvcpus < 0)
- goto cleanup;
testDriverLock(privconn);
- privdom = virDomainFindByName(&privconn->domains,
- domain->name);
+ privdom = virDomainFindByUUID(&privconn->domains, domain->uuid);
testDriverUnlock(privconn);
if (privdom == NULL) {
@@ -2075,13 +2124,17 @@ testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
goto cleanup;
}
- if (!virDomainObjIsActive(privdom)) {
+ if (!virDomainObjIsActive(privdom) && (flags & VIR_DOMAIN_VCPU_LIVE)) {
testError(VIR_ERR_OPERATION_INVALID,
"%s", _("cannot hotplug vcpus for an inactive domain"));
goto cleanup;
}
- /* We allow more cpus in guest than host */
+ /* We allow more cpus in guest than host, but not more than the
+ * domain's starting limit. */
+ if ((flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) ==
+ VIR_DOMAIN_VCPU_LIVE && privdom->def->maxvcpus < maxvcpus)
+ maxvcpus = privdom->def->maxvcpus;
if (nrCpus > maxvcpus) {
testError(VIR_ERR_INVALID_ARG,
"requested cpu amount exceeds maximum (%d > %d)",
@@ -2089,12 +2142,49 @@ testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
goto cleanup;
}
- /* Update VCPU state for the running domain */
- if (testDomainUpdateVCPUs(domain->conn, privdom, nrCpus, 0) < 0)
- goto cleanup;
+ switch (flags) {
+ case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_CONFIG:
+ def = privdom->def;
+ if (virDomainObjIsActive(privdom)) {
+ if (privdom->newDef)
+ def = privdom->newDef;
+ else {
+ testError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("no persistent state"));
+ goto cleanup;
+ }
+ }
+ def->maxvcpus = nrCpus;
+ if (nrCpus < def->vcpus)
+ def->vcpus = nrCpus;
+ ret = 0;
+ break;
- privdom->def->vcpus = nrCpus;
- ret = 0;
+ case VIR_DOMAIN_VCPU_CONFIG:
+ def = privdom->def;
+ if (virDomainObjIsActive(privdom)) {
+ if (privdom->newDef)
+ def = privdom->newDef;
+ else {
+ testError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("no persistent state"));
+ goto cleanup;
+ }
+ }
+ def->vcpus = nrCpus;
+ ret = 0;
+ break;
+
+ case VIR_DOMAIN_VCPU_LIVE:
+ ret = testDomainUpdateVCPUs(domain->conn, privdom, nrCpus, 0);
+ break;
+
+ case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
+ ret = testDomainUpdateVCPUs(domain->conn, privdom, nrCpus, 0);
+ if (ret == 0 && privdom->newDef)
+ privdom->newDef->vcpus = nrCpus;
+ break;
+ }
cleanup:
if (privdom)
--
1.7.2.3

View File

@ -0,0 +1,122 @@
From d67c189e80e6aef7adf13e5763365555cfc1a02a Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Wed, 29 Sep 2010 15:58:47 -0600
Subject: [PATCH 10/15] vcpu: improve vcpu support in qemu command line
* src/qemu/qemu_conf.c (qemuParseCommandLineSmp): Distinguish
between vcpus and maxvcpus, for new enough qemu.
* tests/qemuargv2xmltest.c (mymain): Add new test.
* tests/qemuxml2argvtest.c (mymain): Likewise.
* tests/qemuxml2xmltest.c (mymain): Likewise.
* tests/qemuxml2argvdata/qemuxml2argv-smp.args: New file.
---
src/qemu/qemu_conf.c | 13 +++++++++----
tests/qemuargv2xmltest.c | 2 ++
tests/qemuxml2argvdata/qemuxml2argv-smp.args | 1 +
tests/qemuxml2argvtest.c | 2 ++
tests/qemuxml2xmltest.c | 2 ++
5 files changed, 16 insertions(+), 4 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smp.args
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 38c8351..ffe184b 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -3714,6 +3714,8 @@ qemuBuildSmpArgStr(const virDomainDefPtr def,
virBufferAsprintf(&buf, "%u", def->vcpus);
if ((qemuCmdFlags & QEMUD_CMD_FLAG_SMP_TOPOLOGY)) {
+ if (def->vcpus != def->maxvcpus)
+ virBufferAsprintf(&buf, ",maxcpus=%u", def->maxvcpus);
/* sockets, cores, and threads are either all zero
* or all non-zero, thus checking one of them is enough */
if (def->cpu && def->cpu->sockets) {
@@ -3726,12 +3728,12 @@ qemuBuildSmpArgStr(const virDomainDefPtr def,
virBufferAsprintf(&buf, ",cores=%u", 1);
virBufferAsprintf(&buf, ",threads=%u", 1);
}
- }
- if (def->vcpus != def->maxvcpus) {
+ } else if (def->vcpus != def->maxvcpus) {
virBufferFreeAndReset(&buf);
+ /* FIXME - consider hot-unplugging cpus after boot for older qemu */
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("setting current vcpu count less than maximum is "
- "not supported yet"));
+ "not supported with this QEMU binary"));
return NULL;
}
@@ -6153,6 +6155,7 @@ qemuParseCommandLineSmp(virDomainDefPtr dom,
unsigned int sockets = 0;
unsigned int cores = 0;
unsigned int threads = 0;
+ unsigned int maxcpus = 0;
int i;
int nkws;
char **kws;
@@ -6180,12 +6183,14 @@ qemuParseCommandLineSmp(virDomainDefPtr dom,
cores = n;
else if (STREQ(kws[i], "threads"))
threads = n;
+ else if (STREQ(kws[i], "maxcpus"))
+ maxcpus = n;
else
goto syntax;
}
}
- dom->maxvcpus = dom->vcpus;
+ dom->maxvcpus = maxcpus ? maxcpus : dom->vcpus;
if (sockets && cores && threads) {
virCPUDefPtr cpu;
diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c
index 4f9ec84..d941b0b 100644
--- a/tests/qemuargv2xmltest.c
+++ b/tests/qemuargv2xmltest.c
@@ -221,6 +221,8 @@ mymain(int argc, char **argv)
DO_TEST("hostdev-pci-address");
+ DO_TEST("smp");
+
DO_TEST_FULL("restore-v1", 0, "stdio");
DO_TEST_FULL("restore-v2", 0, "stdio");
DO_TEST_FULL("restore-v2", 0, "exec:cat");
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smp.args b/tests/qemuxml2argvdata/qemuxml2argv-smp.args
new file mode 100644
index 0000000..3ec8f15
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-smp.args
@@ -0,0 +1 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1,maxcpus=2,sockets=2,cores=1,threads=1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 92d5b18..551d6c4 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -385,6 +385,8 @@ mymain(int argc, char **argv)
DO_TEST("qemu-ns", 0);
+ DO_TEST("smp", QEMUD_CMD_FLAG_SMP_TOPOLOGY);
+
free(driver.stateDir);
virCapabilitiesFree(driver.caps);
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index a33d435..cdc4390 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -180,6 +180,8 @@ mymain(int argc, char **argv)
DO_TEST("encrypted-disk");
DO_TEST("memtune");
+ DO_TEST("smp");
+
/* These tests generate different XML */
DO_TEST_DIFFERENT("balloon-device-auto");
DO_TEST_DIFFERENT("channel-virtio-auto");
--
1.7.2.3

View File

@ -0,0 +1,169 @@
From 28a3605906385cba43df77051dc26e865f237b09 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Wed, 29 Sep 2010 17:40:45 -0600
Subject: [PATCH 11/15] vcpu: complete vcpu support in qemu driver
* src/qemu/qemu_driver.c (qemudDomainSetVcpusFlags)
(qemudDomainGetVcpusFlags): Support all feasible flag
combinations.
---
src/qemu/qemu_driver.c | 100 ++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 85 insertions(+), 15 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index c66dc04..a9e057f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5941,13 +5941,27 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
{
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
+ virDomainDefPtr def;
const char * type;
int max;
int ret = -1;
- if (flags != VIR_DOMAIN_VCPU_LIVE) {
- qemuReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
- flags);
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_CONFIG |
+ VIR_DOMAIN_VCPU_MAXIMUM, -1);
+
+ /* At least one of LIVE or CONFIG must be set. MAXIMUM cannot be
+ * mixed with LIVE. */
+ if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0 ||
+ (flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) ==
+ (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) {
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("invalid flag combination: (0x%x)"), flags);
+ return -1;
+ }
+ if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("argument out of range: %d"), nvcpus);
return -1;
}
@@ -5966,7 +5980,7 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
if (qemuDomainObjBeginJob(vm) < 0)
goto cleanup;
- if (!virDomainObjIsActive(vm)) {
+ if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_VCPU_LIVE)) {
qemuReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not running"));
goto endjob;
@@ -5985,6 +5999,11 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
goto endjob;
}
+ if ((flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) ==
+ VIR_DOMAIN_VCPU_LIVE && vm->def->maxvcpus < max) {
+ max = vm->def->maxvcpus;
+ }
+
if (nvcpus > max) {
qemuReportError(VIR_ERR_INVALID_ARG,
_("requested vcpus is greater than max allowable"
@@ -5992,7 +6011,49 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
goto endjob;
}
- ret = qemudDomainHotplugVcpus(vm, nvcpus);
+ switch (flags) {
+ case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_CONFIG:
+ def = vm->def;
+ if (virDomainObjIsActive(vm)) {
+ if (vm->newDef)
+ def = vm->newDef;
+ else{
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("no persistent state"));
+ goto endjob;
+ }
+ }
+ def->maxvcpus = nvcpus;
+ if (nvcpus < vm->newDef->vcpus)
+ def->vcpus = nvcpus;
+ ret = 0;
+ break;
+
+ case VIR_DOMAIN_VCPU_CONFIG:
+ def = vm->def;
+ if (virDomainObjIsActive(vm)) {
+ if (vm->newDef)
+ def = vm->newDef;
+ else {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("no persistent state"));
+ goto endjob;
+ }
+ }
+ def->vcpus = nvcpus;
+ ret = 0;
+ break;
+
+ case VIR_DOMAIN_VCPU_LIVE:
+ ret = qemudDomainHotplugVcpus(vm, nvcpus);
+ break;
+
+ case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
+ ret = qemudDomainHotplugVcpus(vm, nvcpus);
+ if (ret == 0 && vm->newDef)
+ vm->newDef->vcpus = nvcpus;
+ break;
+ }
endjob:
if (qemuDomainObjEndJob(vm) == 0)
@@ -6171,12 +6232,17 @@ qemudDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
{
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
- const char *type;
+ virDomainDefPtr def;
int ret = -1;
- if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
- qemuReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
- flags);
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_CONFIG |
+ VIR_DOMAIN_VCPU_MAXIMUM, -1);
+
+ /* Exactly one of LIVE or CONFIG must be set. */
+ if (!(flags & VIR_DOMAIN_VCPU_LIVE) == !(flags & VIR_DOMAIN_VCPU_CONFIG)) {
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("invalid flag combination: (0x%x)"), flags);
return -1;
}
@@ -6192,14 +6258,18 @@ qemudDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
goto cleanup;
}
- if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
- qemuReportError(VIR_ERR_INTERNAL_ERROR,
- _("unknown virt type in domain definition '%d'"),
- vm->def->virtType);
- goto cleanup;
+ if (flags & VIR_DOMAIN_VCPU_LIVE) {
+ if (!virDomainObjIsActive(vm)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain not active"));
+ goto cleanup;
+ }
+ def = vm->def;
+ } else {
+ def = vm->newDef ? vm->newDef : vm->def;
}
- ret = qemudGetMaxVCPUs(NULL, type);
+ ret = (flags & VIR_DOMAIN_VCPU_MAXIMUM) ? def->maxvcpus : def->vcpus;
cleanup:
if (vm)
--
1.7.2.3

View File

@ -0,0 +1,294 @@
From 0fab10e5ed971ab4f960a53e9640b0672f4b8ac3 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Tue, 5 Oct 2010 08:18:52 -0600
Subject: [PATCH 12/15] vcpu: improve vcpu support in xen command line
This patch series focuses on xendConfigVersion 2 (xm_internal) and 3
(xend_internal), but leaves out changes for xenapi drivers.
See this link for more details about vcpu_avail for xm usage.
http://lists.xensource.com/archives/html/xen-devel/2009-11/msg01061.html
This relies on the fact that def->maxvcpus can be at most 32 with xen.
* src/xen/xend_internal.c (xenDaemonParseSxpr)
(sexpr_to_xend_domain_info, xenDaemonFormatSxpr): Use vcpu_avail
when current vcpus is less than maximum.
* src/xen/xm_internal.c (xenXMDomainConfigParse)
(xenXMDomainConfigFormat): Likewise.
* tests/xml2sexprdata/xml2sexpr-pv-vcpus.sexpr: New file.
* tests/sexpr2xmldata/sexpr2xml-pv-vcpus.sexpr: Likewise.
* tests/sexpr2xmldata/sexpr2xml-pv-vcpus.xml: Likewise.
* tests/xmconfigdata/test-paravirt-vcpu.cfg: Likewise.
* tests/xmconfigdata/test-paravirt-vcpu.xml: Likewise.
* tests/xml2sexprtest.c (mymain): New test.
* tests/sexpr2xmltest.c (mymain): Likewise.
* tests/xmconfigtest.c (mymain): Likewise.
---
src/xen/xend_internal.c | 19 +++++++++++++--
src/xen/xm_internal.c | 10 ++++++-
tests/sexpr2xmldata/sexpr2xml-pv-vcpus.sexpr | 1 +
tests/sexpr2xmldata/sexpr2xml-pv-vcpus.xml | 27 +++++++++++++++++++++
tests/sexpr2xmltest.c | 1 +
tests/xmconfigdata/test-paravirt-vcpu.cfg | 17 +++++++++++++
tests/xmconfigdata/test-paravirt-vcpu.xml | 32 ++++++++++++++++++++++++++
tests/xmconfigtest.c | 1 +
tests/xml2sexprdata/xml2sexpr-pv-vcpus.sexpr | 1 +
tests/xml2sexprtest.c | 1 +
10 files changed, 105 insertions(+), 5 deletions(-)
create mode 100644 tests/sexpr2xmldata/sexpr2xml-pv-vcpus.sexpr
create mode 100644 tests/sexpr2xmldata/sexpr2xml-pv-vcpus.xml
create mode 100644 tests/xmconfigdata/test-paravirt-vcpu.cfg
create mode 100644 tests/xmconfigdata/test-paravirt-vcpu.xml
create mode 100644 tests/xml2sexprdata/xml2sexpr-pv-vcpus.sexpr
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index 456b477..dfc6415 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -44,6 +44,7 @@
#include "xen_hypervisor.h"
#include "xs_internal.h" /* To extract VNC port & Serial console TTY */
#include "memory.h"
+#include "count-one-bits.h"
/* required for cpumap_t */
#include <xen/dom0_ops.h>
@@ -2191,7 +2192,9 @@ xenDaemonParseSxpr(virConnectPtr conn,
}
def->maxvcpus = sexpr_int(root, "domain/vcpus");
- def->vcpus = def->maxvcpus;
+ def->vcpus = count_one_bits(sexpr_int(root, "domain/vcpu_avail"));
+ if (!def->vcpus || def->maxvcpus < def->vcpus)
+ def->vcpus = def->maxvcpus;
tmp = sexpr_node(root, "domain/on_poweroff");
if (tmp != NULL) {
@@ -2433,7 +2436,7 @@ sexpr_to_xend_domain_info(virDomainPtr domain, const struct sexpr *root,
virDomainInfoPtr info)
{
const char *flags;
-
+ int vcpus;
if ((root == NULL) || (info == NULL))
return (-1);
@@ -2464,7 +2467,11 @@ sexpr_to_xend_domain_info(virDomainPtr domain, const struct sexpr *root,
info->state = VIR_DOMAIN_NOSTATE;
}
info->cpuTime = sexpr_float(root, "domain/cpu_time") * 1000000000;
- info->nrVirtCpu = sexpr_int(root, "domain/vcpus");
+ vcpus = sexpr_int(root, "domain/vcpus");
+ info->nrVirtCpu = count_one_bits(sexpr_int(root, "domain/vcpu_avail"));
+ if (!info->nrVirtCpu || vcpus < info->nrVirtCpu)
+ info->nrVirtCpu = vcpus;
+
return (0);
}
@@ -5668,6 +5675,9 @@ xenDaemonFormatSxpr(virConnectPtr conn,
virBufferAsprintf(&buf, "(memory %lu)(maxmem %lu)",
def->mem.cur_balloon/1024, def->mem.max_balloon/1024);
virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus);
+ /* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is 32. */
+ if (def->vcpus < def->maxvcpus)
+ virBufferAsprintf(&buf, "(vcpu_avail %u)", (1U << def->vcpus) - 1);
if (def->cpumask) {
char *ranges = virDomainCpuSetFormat(def->cpumask, def->cpumasklen);
@@ -5763,6 +5773,9 @@ xenDaemonFormatSxpr(virConnectPtr conn,
virBufferAsprintf(&buf, "(kernel '%s')", def->os.loader);
virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus);
+ if (def->vcpus < def->maxvcpus)
+ virBufferAsprintf(&buf, "(vcpu_avail %u)",
+ (1U << def->vcpus) - 1);
for (i = 0 ; i < def->os.nBootDevs ; i++) {
switch (def->os.bootDevs[i]) {
diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
index bf20a64..f7121ab 100644
--- a/src/xen/xm_internal.c
+++ b/src/xen/xm_internal.c
@@ -46,6 +46,7 @@
#include "util.h"
#include "memory.h"
#include "logging.h"
+#include "count-one-bits.h"
#define VIR_FROM_THIS VIR_FROM_XENXM
@@ -772,10 +773,12 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
def->mem.max_balloon *= 1024;
if (xenXMConfigGetULong(conf, "vcpus", &count, 1) < 0 ||
- (unsigned short) count != count)
+ MAX_VIRT_CPUS < count)
goto cleanup;
def->maxvcpus = count;
- def->vcpus = def->maxvcpus;
+ if (xenXMConfigGetULong(conf, "vcpu_avail", &count, -1) < 0)
+ goto cleanup;
+ def->vcpus = MIN(count_one_bits(count), def->maxvcpus);
if (xenXMConfigGetString(conf, "cpus", &str, NULL) < 0)
goto cleanup;
@@ -2246,6 +2249,9 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn,
if (xenXMConfigSetInt(conf, "vcpus", def->maxvcpus) < 0)
goto no_memory;
+ if (def->vcpus < def->maxvcpus &&
+ xenXMConfigSetInt(conf, "vcpu_avail", (1U << def->vcpus) - 1) < 0)
+ goto no_memory;
if ((def->cpumask != NULL) &&
((cpus = virDomainCpuSetFormat(def->cpumask,
diff --git a/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.sexpr b/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.sexpr
new file mode 100644
index 0000000..2be6822
--- /dev/null
+++ b/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.sexpr
@@ -0,0 +1 @@
+(domain (domid 6)(name 'pvtest')(memory 420)(maxmem 420)(vcpus 4)(vcpu_avail 3)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
diff --git a/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.xml b/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.xml
new file mode 100644
index 0000000..0d6bf11
--- /dev/null
+++ b/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.xml
@@ -0,0 +1,27 @@
+<domain type='xen' id='6'>
+ <name>pvtest</name>
+ <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid>
+ <memory>430080</memory>
+ <currentMemory>430080</currentMemory>
+ <vcpu current='2'>4</vcpu>
+ <os>
+ <type>linux</type>
+ <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel>
+ <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd>
+ <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os </cmdline>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>destroy</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <disk type='file' device='disk'>
+ <driver name='file'/>
+ <source file='/root/some.img'/>
+ <target dev='xvda' bus='xen'/>
+ </disk>
+ <console type='pty'>
+ <target type='xen' port='0'/>
+ </console>
+ </devices>
+</domain>
diff --git a/tests/sexpr2xmltest.c b/tests/sexpr2xmltest.c
index d62b44f..f100dd8 100644
--- a/tests/sexpr2xmltest.c
+++ b/tests/sexpr2xmltest.c
@@ -132,6 +132,7 @@ mymain(int argc, char **argv)
DO_TEST("pv-vfb-type-crash", "pv-vfb-type-crash", 3);
DO_TEST("fv-autoport", "fv-autoport", 3);
DO_TEST("pv-bootloader", "pv-bootloader", 1);
+ DO_TEST("pv-vcpus", "pv-vcpus", 1);
DO_TEST("disk-file", "disk-file", 2);
DO_TEST("disk-block", "disk-block", 2);
diff --git a/tests/xmconfigdata/test-paravirt-vcpu.cfg b/tests/xmconfigdata/test-paravirt-vcpu.cfg
new file mode 100644
index 0000000..24c78f4
--- /dev/null
+++ b/tests/xmconfigdata/test-paravirt-vcpu.cfg
@@ -0,0 +1,17 @@
+name = "XenGuest1"
+uuid = "c7a5fdb0-cdaf-9455-926a-d65c16db1809"
+maxmem = 579
+memory = 394
+vcpus = 4
+vcpu_avail = 3
+bootloader = "/usr/bin/pygrub"
+on_poweroff = "destroy"
+on_reboot = "restart"
+on_crash = "restart"
+sdl = 0
+vnc = 1
+vncunused = 1
+vnclisten = "127.0.0.1"
+vncpasswd = "123poi"
+disk = [ "phy:/dev/HostVG/XenGuest1,xvda,w" ]
+vif = [ "mac=00:16:3e:66:94:9c,bridge=br0,script=vif-bridge" ]
diff --git a/tests/xmconfigdata/test-paravirt-vcpu.xml b/tests/xmconfigdata/test-paravirt-vcpu.xml
new file mode 100644
index 0000000..0be9456
--- /dev/null
+++ b/tests/xmconfigdata/test-paravirt-vcpu.xml
@@ -0,0 +1,32 @@
+<domain type='xen'>
+ <name>XenGuest1</name>
+ <uuid>c7a5fdb0-cdaf-9455-926a-d65c16db1809</uuid>
+ <memory>592896</memory>
+ <currentMemory>403456</currentMemory>
+ <vcpu current='2'>4</vcpu>
+ <bootloader>/usr/bin/pygrub</bootloader>
+ <os>
+ <type arch='i686' machine='xenpv'>linux</type>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <disk type='block' device='disk'>
+ <driver name='phy'/>
+ <source dev='/dev/HostVG/XenGuest1'/>
+ <target dev='xvda' bus='xen'/>
+ </disk>
+ <interface type='bridge'>
+ <mac address='00:16:3e:66:94:9c'/>
+ <source bridge='br0'/>
+ <script path='vif-bridge'/>
+ </interface>
+ <console type='pty'>
+ <target type='xen' port='0'/>
+ </console>
+ <input type='mouse' bus='xen'/>
+ <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/>
+ </devices>
+</domain>
diff --git a/tests/xmconfigtest.c b/tests/xmconfigtest.c
index 221b322..ea00747 100644
--- a/tests/xmconfigtest.c
+++ b/tests/xmconfigtest.c
@@ -210,6 +210,7 @@ mymain(int argc, char **argv)
DO_TEST("paravirt-new-pvfb-vncdisplay", 3);
DO_TEST("paravirt-net-e1000", 3);
DO_TEST("paravirt-net-vifname", 3);
+ DO_TEST("paravirt-vcpu", 2);
DO_TEST("fullvirt-old-cdrom", 1);
DO_TEST("fullvirt-new-cdrom", 2);
DO_TEST("fullvirt-utc", 2);
diff --git a/tests/xml2sexprdata/xml2sexpr-pv-vcpus.sexpr b/tests/xml2sexprdata/xml2sexpr-pv-vcpus.sexpr
new file mode 100644
index 0000000..e886545
--- /dev/null
+++ b/tests/xml2sexprdata/xml2sexpr-pv-vcpus.sexpr
@@ -0,0 +1 @@
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 4)(vcpu_avail 3)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
\ No newline at end of file
diff --git a/tests/xml2sexprtest.c b/tests/xml2sexprtest.c
index 77cf760..9cf8d39 100644
--- a/tests/xml2sexprtest.c
+++ b/tests/xml2sexprtest.c
@@ -118,6 +118,7 @@ mymain(int argc, char **argv)
DO_TEST("pv-vfb-new", "pv-vfb-new", "pvtest", 3);
DO_TEST("pv-vfb-new-auto", "pv-vfb-new-auto", "pvtest", 3);
DO_TEST("pv-bootloader", "pv-bootloader", "pvtest", 1);
+ DO_TEST("pv-vcpus", "pv-vcpus", "pvtest", 1);
DO_TEST("disk-file", "disk-file", "pvtest", 2);
DO_TEST("disk-block", "disk-block", "pvtest", 2);
--
1.7.2.3

View File

@ -0,0 +1,216 @@
From 290ea33111be7bdf1f1381b90de33eb0e67c1a15 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Wed, 6 Oct 2010 17:54:41 -0600
Subject: [PATCH 13/15] vcpu: improve support for getting xen vcpu counts
* src/xen/xen_driver.c (xenUnifiedDomainGetVcpusFlags): Support
more flags.
* src/xen/xend_internal.h (xenDaemonDomainGetVcpusFlags): New
prototype.
* src/xen/xm_internal.h (xenXMDomainGetVcpusFlags): Likewise.
* src/xen/xend_internal.c (virDomainGetVcpusFlags): New function.
* src/xen/xm_internal.c (xenXMDomainGetVcpusFlags): Likewise.
---
src/xen/xen_driver.c | 31 +++++++++++++++++++--------
src/xen/xend_internal.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++
src/xen/xend_internal.h | 2 +
src/xen/xm_internal.c | 47 ++++++++++++++++++++++++++++++++++++++++++
src/xen/xm_internal.h | 1 +
5 files changed, 124 insertions(+), 9 deletions(-)
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c
index d6c9c57..fe2ff86 100644
--- a/src/xen/xen_driver.c
+++ b/src/xen/xen_driver.c
@@ -1142,20 +1142,33 @@ static int
xenUnifiedDomainGetVcpusFlags (virDomainPtr dom, unsigned int flags)
{
GET_PRIVATE(dom->conn);
- int i, ret;
+ int ret;
- if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
- xenUnifiedError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
- flags);
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_CONFIG |
+ VIR_DOMAIN_VCPU_MAXIMUM, -1);
+
+ /* Exactly one of LIVE or CONFIG must be set. */
+ if (!(flags & VIR_DOMAIN_VCPU_LIVE) == !(flags & VIR_DOMAIN_VCPU_CONFIG)) {
+ xenUnifiedError(VIR_ERR_INVALID_ARG,
+ _("invalid flag combination: (0x%x)"), flags);
return -1;
}
- for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
- if (priv->opened[i] && drivers[i]->domainGetMaxVcpus) {
- ret = drivers[i]->domainGetMaxVcpus (dom);
- if (ret != 0) return ret;
- }
+ if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
+ ret = xenDaemonDomainGetVcpusFlags(dom, flags);
+ if (ret != -2)
+ return ret;
+ }
+ if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
+ ret = xenXMDomainGetVcpusFlags(dom, flags);
+ if (ret != -2)
+ return ret;
+ }
+ if (flags == (VIR_DOMAIN_VCPU_CONFIG | VIR_DOMAIN_VCPU_MAXIMUM))
+ return xenHypervisorGetVcpuMax(dom);
+ xenUnifiedError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
return -1;
}
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index dfc6415..3642296 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -3620,6 +3620,58 @@ xenDaemonDomainPinVcpu(virDomainPtr domain, unsigned int vcpu,
}
/**
+ * xenDaemonDomainGetVcpusFlags:
+ * @domain: pointer to domain object
+ * @flags: bitwise-ORd from virDomainVcpuFlags
+ *
+ * Extract information about virtual CPUs of domain according to flags.
+ *
+ * Returns the number of vcpus on success, -1 if an error message was
+ * issued, and -2 if the unified driver should keep trying.
+
+ */
+int
+xenDaemonDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
+{
+ struct sexpr *root;
+ int ret;
+ xenUnifiedPrivatePtr priv;
+
+ if (domain == NULL || domain->conn == NULL || domain->name == NULL) {
+ virXendError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return -1;
+ }
+
+ priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+ /* If xendConfigVersion is 2, then we can only report _LIVE (and
+ * xm_internal reports _CONFIG). If it is 3, then _LIVE and
+ * _CONFIG are always in sync for a running system. */
+ if (domain->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
+ return -2;
+ if (domain->id < 0 && (flags & VIR_DOMAIN_VCPU_LIVE)) {
+ virXendError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain not active"));
+ return -1;
+ }
+
+ root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
+ if (root == NULL)
+ return -1;
+
+ ret = sexpr_int(root, "domain/vcpus");
+ if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM)) {
+ int vcpus = count_one_bits(sexpr_int(root, "domain/vcpu_avail"));
+ if (vcpus)
+ ret = MIN(vcpus, ret);
+ }
+ if (!ret)
+ ret = -2;
+ sexpr_free(root);
+ return ret;
+}
+
+/**
* virDomainGetVcpus:
* @domain: pointer to domain object, or NULL for Domain0
* @info: pointer to an array of virVcpuInfo structures (OUT)
diff --git a/src/xen/xend_internal.h b/src/xen/xend_internal.h
index c757716..923cebd 100644
--- a/src/xen/xend_internal.h
+++ b/src/xen/xend_internal.h
@@ -155,6 +155,8 @@ int xenDaemonDomainPinVcpu (virDomainPtr domain,
unsigned int vcpu,
unsigned char *cpumap,
int maplen);
+int xenDaemonDomainGetVcpusFlags (virDomainPtr domain,
+ unsigned int flags);
int xenDaemonDomainGetVcpus (virDomainPtr domain,
virVcpuInfoPtr info,
int maxinfo,
diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
index f7121ab..4ea4245 100644
--- a/src/xen/xm_internal.c
+++ b/src/xen/xm_internal.c
@@ -1671,6 +1671,53 @@ cleanup:
}
/**
+ * xenXMDomainGetVcpusFlags:
+ * @domain: pointer to domain object
+ * @flags: bitwise-ORd from virDomainVcpuFlags
+ *
+ * Extract information about virtual CPUs of domain according to flags.
+ *
+ * Returns the number of vcpus on success, -1 if an error message was
+ * issued, and -2 if the unified driver should keep trying.
+ */
+int
+xenXMDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
+{
+ xenUnifiedPrivatePtr priv;
+ const char *filename;
+ xenXMConfCachePtr entry;
+ int ret = -2;
+
+ if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+ xenXMError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return -1;
+ }
+
+ if (domain->id != -1)
+ return -2;
+ if (flags & VIR_DOMAIN_VCPU_LIVE) {
+ xenXMError(VIR_ERR_OPERATION_FAILED, "%s", _("domain not active"));
+ return -1;
+ }
+
+ priv = domain->conn->privateData;
+ xenUnifiedLock(priv);
+
+ if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
+ goto cleanup;
+
+ if (!(entry = virHashLookup(priv->configCache, filename)))
+ goto cleanup;
+
+ ret = ((flags & VIR_DOMAIN_VCPU_MAXIMUM) ? entry->def->maxvcpus
+ : entry->def->vcpus);
+
+cleanup:
+ xenUnifiedUnlock(priv);
+ return ret;
+}
+
+/**
* xenXMDomainPinVcpu:
* @domain: pointer to domain object
* @vcpu: virtual CPU number (reserved)
diff --git a/src/xen/xm_internal.h b/src/xen/xm_internal.h
index 3ad3456..3295fbd 100644
--- a/src/xen/xm_internal.h
+++ b/src/xen/xm_internal.h
@@ -45,6 +45,7 @@ int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory);
int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory);
unsigned long xenXMDomainGetMaxMemory(virDomainPtr domain);
int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus);
+int xenXMDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags);
int xenXMDomainPinVcpu(virDomainPtr domain, unsigned int vcpu,
unsigned char *cpumap, int maplen);
virDomainPtr xenXMDomainLookupByName(virConnectPtr conn, const char *domname);
--
1.7.2.3

View File

@ -0,0 +1,342 @@
From e443a003129a172a7332f3cb6e40b3c39363ed5e Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Thu, 14 Oct 2010 16:17:18 -0600
Subject: [PATCH 14/15] vcpu: improve support for setting xen vcpu counts
Tested with RHEL 5.6 (xendConfigVersion 2, where xend_internal
controls live domains and xm_internal controls inactive domains).
Hopefully this works with xendConfigVersion 3 (where xend_internal
controls everything).
* src/xen/xen_driver.c (xenUnifiedDomainSetVcpusFlags): Support
more flags.
(xenUnifiedGetMaxVcpus): Export.
* src/xen/xm_internal.h (xenXMDomainSetVcpusFlags): New prototype.
* src/xen/xend_internal.h (xenDaemonDomainSetVcpusFlags): Likewise.
* src/xen/xen_driver.h (xenUnifiedGetMaxVcpus): Likewise.
* src/xen/xm_internal.c (xenXMDomainSetVcpusFlags): New function.
* src/xen/xend_internal.c (xenDaemonDomainSetVcpusFlags): Likewise.
---
src/xen/xen_driver.c | 60 ++++++++++++++++++++++++---------
src/xen/xen_driver.h | 1 +
src/xen/xend_internal.c | 76 +++++++++++++++++++++++++++++++++++++++++++
src/xen/xend_internal.h | 3 ++
src/xen/xm_internal.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++
src/xen/xm_internal.h | 2 +
6 files changed, 208 insertions(+), 17 deletions(-)
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c
index fe2ff86..66e8518 100644
--- a/src/xen/xen_driver.c
+++ b/src/xen/xen_driver.c
@@ -508,7 +508,7 @@ xenUnifiedIsSecure(virConnectPtr conn)
return ret;
}
-static int
+int
xenUnifiedGetMaxVcpus (virConnectPtr conn, const char *type)
{
GET_PRIVATE(conn);
@@ -1073,36 +1073,62 @@ xenUnifiedDomainSetVcpusFlags (virDomainPtr dom, unsigned int nvcpus,
unsigned int flags)
{
GET_PRIVATE(dom->conn);
- int i;
+ int ret;
+
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_CONFIG |
+ VIR_DOMAIN_VCPU_MAXIMUM, -1);
- if (flags != VIR_DOMAIN_VCPU_LIVE) {
- xenUnifiedError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
- flags);
+ /* At least one of LIVE or CONFIG must be set. MAXIMUM cannot be
+ * mixed with LIVE. */
+ if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0 ||
+ (flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) ==
+ (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) {
+ xenUnifiedError(VIR_ERR_INVALID_ARG,
+ _("invalid flag combination: (0x%x)"), flags);
+ return -1;
+ }
+ if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
+ xenUnifiedError(VIR_ERR_INVALID_ARG,
+ _("argument out of range: %d"), nvcpus);
return -1;
}
/* Try non-hypervisor methods first, then hypervisor direct method
* as a last resort.
*/
- for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
- if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
- priv->opened[i] &&
- drivers[i]->domainSetVcpus &&
- drivers[i]->domainSetVcpus (dom, nvcpus) == 0)
- return 0;
-
- if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
- drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSetVcpus &&
- drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSetVcpus (dom, nvcpus) == 0)
- return 0;
+ if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
+ ret = xenDaemonDomainSetVcpusFlags(dom, nvcpus, flags);
+ if (ret != -2)
+ return ret;
+ }
+ if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
+ ret = xenXMDomainSetVcpusFlags(dom, nvcpus, flags);
+ if (ret != -2)
+ return ret;
+ }
+ if (flags == VIR_DOMAIN_VCPU_LIVE)
+ return xenHypervisorSetVcpus(dom, nvcpus);
+ xenUnifiedError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
return -1;
}
static int
xenUnifiedDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus)
{
- return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
+ unsigned int flags = VIR_DOMAIN_VCPU_LIVE;
+ xenUnifiedPrivatePtr priv;
+
+ /* Per the documented API, it is hypervisor-dependent whether this
+ * affects just _LIVE or _LIVE|_CONFIG; in xen's case, that
+ * depends on xendConfigVersion. */
+ if (dom) {
+ priv = dom->conn->privateData;
+ if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
+ flags |= VIR_DOMAIN_VCPU_CONFIG;
+ }
+ return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, flags);
}
static int
diff --git a/src/xen/xen_driver.h b/src/xen/xen_driver.h
index 3e7c1d0..115a26a 100644
--- a/src/xen/xen_driver.h
+++ b/src/xen/xen_driver.h
@@ -220,6 +220,7 @@ int xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr info,
void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
virDomainEventPtr event);
unsigned long xenUnifiedVersion(void);
+int xenUnifiedGetMaxVcpus(virConnectPtr conn, const char *type);
# ifndef PROXY
void xenUnifiedLock(xenUnifiedPrivatePtr priv);
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index 3642296..55c2cc4 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -3535,6 +3535,82 @@ xenDaemonLookupByID(virConnectPtr conn, int id) {
}
/**
+ * xenDaemonDomainSetVcpusFlags:
+ * @domain: pointer to domain object
+ * @nvcpus: the new number of virtual CPUs for this domain
+ * @flags: bitwise-ORd from virDomainVcpuFlags
+ *
+ * Change virtual CPUs allocation of domain according to flags.
+ *
+ * Returns 0 on success, -1 if an error message was issued, and -2 if
+ * the unified driver should keep trying.
+ */
+int
+xenDaemonDomainSetVcpusFlags(virDomainPtr domain, unsigned int vcpus,
+ unsigned int flags)
+{
+ char buf[VIR_UUID_BUFLEN];
+ xenUnifiedPrivatePtr priv;
+ int max;
+
+ if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
+ || (vcpus < 1)) {
+ virXendError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return (-1);
+ }
+
+ priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+ if ((domain->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ||
+ (flags & VIR_DOMAIN_VCPU_MAXIMUM))
+ return -2;
+
+ /* With xendConfigVersion 2, only _LIVE is supported. With
+ * xendConfigVersion 3, only _LIVE|_CONFIG is supported for
+ * running domains, or _CONFIG for inactive domains. */
+ if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
+ if (flags & VIR_DOMAIN_VCPU_CONFIG) {
+ virXendError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("Xend version does not support modifying "
+ "persistent config"));
+ return -1;
+ }
+ } else if (domain->id < 0) {
+ if (flags & VIR_DOMAIN_VCPU_LIVE) {
+ virXendError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain not running"));
+ return -1;
+ }
+ } else {
+ if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) !=
+ (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) {
+ virXendError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("Xend only supports modifying both live and "
+ "persistent config"));
+ }
+ }
+
+ /* Unfortunately, xend_op does not validate whether this exceeds
+ * the maximum. */
+ flags |= VIR_DOMAIN_VCPU_MAXIMUM;
+ if ((max = xenDaemonDomainGetVcpusFlags(domain, flags)) < 0) {
+ virXendError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("could not determin max vcpus for the domain"));
+ return -1;
+ }
+ if (vcpus > max) {
+ virXendError(VIR_ERR_INVALID_ARG,
+ _("requested vcpus is greater than max allowable"
+ " vcpus for the domain: %d > %d"), vcpus, max);
+ return -1;
+ }
+
+ snprintf(buf, sizeof(buf), "%d", vcpus);
+ return xend_op(domain->conn, domain->name, "op", "set_vcpus", "vcpus",
+ buf, NULL);
+}
+
+/**
* xenDaemonDomainSetVcpus:
* @domain: pointer to domain object
* @nvcpus: the new number of virtual CPUs for this domain
diff --git a/src/xen/xend_internal.h b/src/xen/xend_internal.h
index 923cebd..53f5d2c 100644
--- a/src/xen/xend_internal.h
+++ b/src/xen/xend_internal.h
@@ -151,6 +151,9 @@ int xenDaemonDomainUndefine(virDomainPtr domain);
int xenDaemonDomainSetVcpus (virDomainPtr domain,
unsigned int vcpus);
+int xenDaemonDomainSetVcpusFlags (virDomainPtr domain,
+ unsigned int vcpus,
+ unsigned int flags);
int xenDaemonDomainPinVcpu (virDomainPtr domain,
unsigned int vcpu,
unsigned char *cpumap,
diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
index 4ea4245..2b8e51e 100644
--- a/src/xen/xm_internal.c
+++ b/src/xen/xm_internal.c
@@ -1670,6 +1670,89 @@ cleanup:
return ret;
}
+/*
+ * xenXMDomainSetVcpusFlags:
+ * @domain: pointer to domain object
+ * @nvcpus: number of vcpus
+ * @flags: bitwise-ORd from virDomainVcpuFlags
+ *
+ * Change virtual CPUs allocation of domain according to flags.
+ *
+ * Returns 0 on success, -1 if an error message was issued, and -2 if
+ * the unified driver should keep trying.
+ */
+int
+xenXMDomainSetVcpusFlags(virDomainPtr domain, unsigned int vcpus,
+ unsigned int flags)
+{
+ xenUnifiedPrivatePtr priv;
+ const char *filename;
+ xenXMConfCachePtr entry;
+ int ret = -1;
+ int max;
+
+ if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+ xenXMError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return -1;
+ }
+ if (domain->conn->flags & VIR_CONNECT_RO) {
+ xenXMError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ return -1;
+ }
+ if (domain->id != -1)
+ return -2;
+ if (flags & VIR_DOMAIN_VCPU_LIVE) {
+ xenXMError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain is not running"));
+ return -1;
+ }
+
+ priv = domain->conn->privateData;
+ xenUnifiedLock(priv);
+
+ if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
+ goto cleanup;
+
+ if (!(entry = virHashLookup(priv->configCache, filename)))
+ goto cleanup;
+
+ /* Hypervisor maximum. */
+ if ((max = xenUnifiedGetMaxVcpus(domain->conn, NULL)) < 0) {
+ xenXMError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("could not determin max vcpus for the domain"));
+ goto cleanup;
+ }
+ /* Can't specify a current larger than stored maximum; but
+ * reducing maximum can silently reduce current. */
+ if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM))
+ max = entry->def->maxvcpus;
+ if (vcpus > max) {
+ xenXMError(VIR_ERR_INVALID_ARG,
+ _("requested vcpus is greater than max allowable"
+ " vcpus for the domain: %d > %d"), vcpus, max);
+ goto cleanup;
+ }
+
+ if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
+ entry->def->maxvcpus = vcpus;
+ if (entry->def->vcpus > vcpus)
+ entry->def->vcpus = vcpus;
+ } else {
+ entry->def->vcpus = vcpus;
+ }
+
+ /* If this fails, should we try to undo our changes to the
+ * in-memory representation of the config file. I say not!
+ */
+ if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
+ goto cleanup;
+ ret = 0;
+
+cleanup:
+ xenUnifiedUnlock(priv);
+ return ret;
+}
+
/**
* xenXMDomainGetVcpusFlags:
* @domain: pointer to domain object
diff --git a/src/xen/xm_internal.h b/src/xen/xm_internal.h
index 3295fbd..a46e1a2 100644
--- a/src/xen/xm_internal.h
+++ b/src/xen/xm_internal.h
@@ -45,6 +45,8 @@ int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory);
int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory);
unsigned long xenXMDomainGetMaxMemory(virDomainPtr domain);
int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus);
+int xenXMDomainSetVcpusFlags(virDomainPtr domain, unsigned int vcpus,
+ unsigned int flags);
int xenXMDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags);
int xenXMDomainPinVcpu(virDomainPtr domain, unsigned int vcpu,
unsigned char *cpumap, int maplen);
--
1.7.2.3

View File

@ -0,0 +1,228 @@
From b013788742183afec9aa5068d3cfd185a3b5c62e Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Thu, 7 Oct 2010 08:59:27 -0600
Subject: [PATCH 15/15] vcpu: remove dead xen code
* src/xen/xen_driver.h (xenUnifiedDriver): Remove now-unused
domainGetMaxVcpus, domainSetVcpus.
* src/xen/proxy_internal.c (xenProxyDriver): Likewise.
* src/xen/xen_hypervisor.c (xenHypervisorDriver): Likewise.
* src/xen/xen_inotify.c (xenInotifyDriver): Likewise.
* src/xen/xend_internal.c (xenDaemonDriver)
(xenDaemonDomainSetVcpus): Likewise.
* src/xen/xm_internal.c (xenXMDriver, xenXMDomainSetVcpus):
Likewise.
* src/xen/xs_internal.c (xenStoreDriver): Likewise.
---
src/xen/proxy_internal.c | 2 --
src/xen/xen_driver.h | 4 +---
src/xen/xen_hypervisor.c | 2 --
src/xen/xen_inotify.c | 2 --
src/xen/xend_internal.c | 33 ---------------------------------
src/xen/xm_internal.c | 43 -------------------------------------------
src/xen/xs_internal.c | 2 --
7 files changed, 1 insertions(+), 87 deletions(-)
diff --git a/src/xen/proxy_internal.c b/src/xen/proxy_internal.c
index 335dfc4..4033727 100644
--- a/src/xen/proxy_internal.c
+++ b/src/xen/proxy_internal.c
@@ -67,10 +67,8 @@ struct xenUnifiedDriver xenProxyDriver = {
NULL, /* domainSave */
NULL, /* domainRestore */
NULL, /* domainCoreDump */
- NULL, /* domainSetVcpus */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
- NULL, /* domainGetMaxVcpus */
NULL, /* listDefinedDomains */
NULL, /* numOfDefinedDomains */
NULL, /* domainCreate */
diff --git a/src/xen/xen_driver.h b/src/xen/xen_driver.h
index 115a26a..53f97d4 100644
--- a/src/xen/xen_driver.h
+++ b/src/xen/xen_driver.h
@@ -1,7 +1,7 @@
/*
* xen_unified.c: Unified Xen driver.
*
- * Copyright (C) 2007 Red Hat, Inc.
+ * Copyright (C) 2007, 2010 Red Hat, Inc.
*
* See COPYING.LIB for the License of this software
*
@@ -84,10 +84,8 @@ struct xenUnifiedDriver {
virDrvDomainSave domainSave;
virDrvDomainRestore domainRestore;
virDrvDomainCoreDump domainCoreDump;
- virDrvDomainSetVcpus domainSetVcpus;
virDrvDomainPinVcpu domainPinVcpu;
virDrvDomainGetVcpus domainGetVcpus;
- virDrvDomainGetMaxVcpus domainGetMaxVcpus;
virDrvListDefinedDomains listDefinedDomains;
virDrvNumOfDefinedDomains numOfDefinedDomains;
virDrvDomainCreate domainCreate;
diff --git a/src/xen/xen_hypervisor.c b/src/xen/xen_hypervisor.c
index 6246513..3797865 100644
--- a/src/xen/xen_hypervisor.c
+++ b/src/xen/xen_hypervisor.c
@@ -784,10 +784,8 @@ struct xenUnifiedDriver xenHypervisorDriver = {
NULL, /* domainSave */
NULL, /* domainRestore */
NULL, /* domainCoreDump */
- xenHypervisorSetVcpus, /* domainSetVcpus */
xenHypervisorPinVcpu, /* domainPinVcpu */
xenHypervisorGetVcpus, /* domainGetVcpus */
- xenHypervisorGetVcpuMax, /* domainGetMaxVcpus */
NULL, /* listDefinedDomains */
NULL, /* numOfDefinedDomains */
NULL, /* domainCreate */
diff --git a/src/xen/xen_inotify.c b/src/xen/xen_inotify.c
index d24b20f..9507061 100644
--- a/src/xen/xen_inotify.c
+++ b/src/xen/xen_inotify.c
@@ -71,10 +71,8 @@ struct xenUnifiedDriver xenInotifyDriver = {
NULL, /* domainSave */
NULL, /* domainRestore */
NULL, /* domainCoreDump */
- NULL, /* domainSetVcpus */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
- NULL, /* domainGetMaxVcpus */
NULL, /* listDefinedDomains */
NULL, /* numOfDefinedDomains */
NULL, /* domainCreate */
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index 55c2cc4..b90c331 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -3611,37 +3611,6 @@ xenDaemonDomainSetVcpusFlags(virDomainPtr domain, unsigned int vcpus,
}
/**
- * xenDaemonDomainSetVcpus:
- * @domain: pointer to domain object
- * @nvcpus: the new number of virtual CPUs for this domain
- *
- * Dynamically change the number of virtual CPUs used by the domain.
- *
- * Returns 0 for success; -1 (with errno) on error
- */
-int
-xenDaemonDomainSetVcpus(virDomainPtr domain, unsigned int vcpus)
-{
- char buf[VIR_UUID_BUFLEN];
- xenUnifiedPrivatePtr priv;
-
- if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
- || (vcpus < 1)) {
- virXendError(VIR_ERR_INVALID_ARG, __FUNCTION__);
- return (-1);
- }
-
- priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
- if (domain->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
- return(-1);
-
- snprintf(buf, sizeof(buf), "%d", vcpus);
- return(xend_op(domain->conn, domain->name, "op", "set_vcpus", "vcpus",
- buf, NULL));
-}
-
-/**
* xenDaemonDomainPinCpu:
* @domain: pointer to domain object
* @vcpu: virtual CPU number
@@ -5213,10 +5182,8 @@ struct xenUnifiedDriver xenDaemonDriver = {
xenDaemonDomainSave, /* domainSave */
xenDaemonDomainRestore, /* domainRestore */
xenDaemonDomainCoreDump, /* domainCoreDump */
- xenDaemonDomainSetVcpus, /* domainSetVcpus */
xenDaemonDomainPinVcpu, /* domainPinVcpu */
xenDaemonDomainGetVcpus, /* domainGetVcpus */
- NULL, /* domainGetMaxVcpus */
xenDaemonListDefinedDomains, /* listDefinedDomains */
xenDaemonNumOfDefinedDomains,/* numOfDefinedDomains */
xenDaemonDomainCreate, /* domainCreate */
diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
index 2b8e51e..430d40b 100644
--- a/src/xen/xm_internal.c
+++ b/src/xen/xm_internal.c
@@ -103,10 +103,8 @@ struct xenUnifiedDriver xenXMDriver = {
NULL, /* domainSave */
NULL, /* domainRestore */
NULL, /* domainCoreDump */
- xenXMDomainSetVcpus, /* domainSetVcpus */
xenXMDomainPinVcpu, /* domainPinVcpu */
NULL, /* domainGetVcpus */
- NULL, /* domainGetMaxVcpus */
xenXMListDefinedDomains, /* listDefinedDomains */
xenXMNumOfDefinedDomains, /* numOfDefinedDomains */
xenXMDomainCreate, /* domainCreate */
@@ -1630,47 +1628,6 @@ cleanup:
}
/*
- * Set the VCPU count in config
- */
-int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus) {
- xenUnifiedPrivatePtr priv;
- const char *filename;
- xenXMConfCachePtr entry;
- int ret = -1;
-
- if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
- xenXMError(VIR_ERR_INVALID_ARG, __FUNCTION__);
- return (-1);
- }
- if (domain->conn->flags & VIR_CONNECT_RO)
- return (-1);
- if (domain->id != -1)
- return (-1);
-
- priv = domain->conn->privateData;
- xenUnifiedLock(priv);
-
- if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
- goto cleanup;
-
- if (!(entry = virHashLookup(priv->configCache, filename)))
- goto cleanup;
-
- entry->def->maxvcpus = entry->def->vcpus = vcpus;
-
- /* If this fails, should we try to undo our changes to the
- * in-memory representation of the config file. I say not!
- */
- if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
- goto cleanup;
- ret = 0;
-
-cleanup:
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-/*
* xenXMDomainSetVcpusFlags:
* @domain: pointer to domain object
* @nvcpus: number of vcpus
diff --git a/src/xen/xs_internal.c b/src/xen/xs_internal.c
index 9296f25..a9817b1 100644
--- a/src/xen/xs_internal.c
+++ b/src/xen/xs_internal.c
@@ -67,10 +67,8 @@ struct xenUnifiedDriver xenStoreDriver = {
NULL, /* domainSave */
NULL, /* domainRestore */
NULL, /* domainCoreDump */
- NULL, /* domainSetVcpus */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
- NULL, /* domainGetMaxVcpus */
NULL, /* listDefinedDomains */
NULL, /* numOfDefinedDomains */
NULL, /* domainCreate */
--
1.7.2.3

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,8 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<html>
<body>
<h1>Applications using libvirt</h1>
<h1>Applications using <strong>libvirt</strong></h1>
<p>
This page provides an illustration of the wide variety of
@ -11,7 +9,7 @@
<ul id="toc"></ul>
<h2><a id="add">Add an application</a></h2>
<h2><a name="add">Add an application</a></h2>
<p>
To add an application not listed on this page, send a message
@ -19,18 +17,15 @@
be added here, or simply send a patch against the documentation
in the libvirt.git docs subdirectory.
If your application uses libvirt as its API,
the following graphics are available for your website to advertise
the following graphic is available for your website to advertise
support for libvirt:
</p>
<p class="image">
<img src="logos/logo-square-powered-96.png" alt="libvirt powered"/>
<img src="logos/logo-square-powered-128.png" alt="libvirt powered"/>
<img src="logos/logo-square-powered-192.png" alt="libvirt powered"/>
<img src="logos/logo-square-powered-256.png" alt="libvirt powered"/>
<img src="madeWith.png" alt="Made with libvirt"/>
</p>
<h2><a id="clientserver">Client/Server applications</a></h2>
<h2><a name="clientserver">Client/Server applications</a></h2>
<dl>
<dt><a href="http://archipelproject.org">Archipel</a></dt>
@ -50,7 +45,7 @@
</dd>
</dl>
<h2><a id="command">Command line tools</a></h2>
<h2><a name="command">Command line tools</a></h2>
<dl>
<dt><a href="http://libguestfs.org">guestfish</a></dt>
@ -65,21 +60,21 @@
management tasks on all libvirt managed domains, networks and
storage. This is part of the libvirt core distribution.
</dd>
<dt><a href="https://virt-manager.org/">virt-clone</a></dt>
<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="https://people.redhat.com/rjones/virt-df/">virt-df</a></dt>
<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="https://virt-manager.org/">virt-image</a></dt>
<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
@ -87,41 +82,28 @@
into the domain XML format for execution under any libvirt
hypervisor meeting the pre-requisites.
</dd>
<dt><a href="https://virt-manager.org/">virt-install</a></dt>
<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="https://people.redhat.com/rjones/virt-top/">virt-top</a></dt>
<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>
<dt>
<a href="https://people.redhat.com/~rjones/virt-what/">virt-what</a>
<a href="http://people.redhat.com/~rjones/virt-what/">virt-what</a>
</dt>
<dd>
virt-what is a shell script for detecting if the program is running
in a virtual machine. It prints out a list of facts about the
virtual machine, derived from heuristics.
</dd>
<dt><a href="https://sourceware.org/systemtap/">stap</a></dt>
<dd>
SystemTap is a tool used to gather rich information about a running
system through the use of scripts. Starting from v2.4, the front-end
application stap can use libvirt to gather data within virtual
machines.
</dd>
<dt><a href="https://github.com/pradels/vagrant-libvirt/">vagrant-libvirt</a></dt>
<dd>
Vagrant-Libvirt is a Vagrant plugin that uses libvirt to manage virtual
machines. It is a command line tool for developers that makes it very
fast and easy to deploy and re-deploy an environment of vm's.
</dd>
</dl>
<h2><a id="configmgmt">Configuration Management</a></h2>
<h2><a name="configmgmt">Configuration Management</a></h2>
<dl>
<dt><a href="https://wiki.lcfg.org/bin/view/LCFG/LcfgLibvirt">LCFG</a></dt>
@ -139,10 +121,10 @@
</dd>
</dl>
<h2><a id="continuousintegration">Continuous Integration</a></h2>
<h2><a name="continuousintegration">Continuous Integration</a></h2>
<dl>
<dt><a href="https://buildbot.net/buildbot/docs/current/Libvirt.html">BuildBot</a></dt>
<dt><a href="http://buildbot.net/buildbot/docs/current/Libvirt.html">BuildBot</a></dt>
<dd>
BuildBot is a system to automate the compile/test cycle required
by most software projects. CVS commits trigger new builds, run on
@ -152,7 +134,7 @@
</dl>
<dl>
<dt><a href="https://wiki.jenkins-ci.org/display/JENKINS/Libvirt+Slaves+Plugin">Jenkins</a></dt>
<dt><a href="http://wiki.jenkins-ci.org/display/JENKINS/Libvirt+Slaves+Plugin">Jenkins</a></dt>
<dd>
This plugin for Jenkins adds a way to control guest domains hosted
on Xen or QEMU/KVM. You configure a Jenkins Slave,
@ -163,24 +145,28 @@
</dd>
</dl>
<h2><a id="conversion">Conversion</a></h2>
<h2><a name="conversion">Conversion</a></h2>
<dl>
<dt><a href="http://libguestfs.org/virt-p2v.1.html">virt-p2v</a></dt>
<dt><a href="https://rwmj.wordpress.com/2009/10/13/poor-mans-p2v/">Poor mans p2v</a></dt>
<dd>
Convert a physical machine to run on KVM. It is a LiveCD
which is booted on the machine to be converted. It collects a
little information from the user, then copies the disks over
to a remote machine and defines the XML for a domain to run
the guest. (Note this tool is included with libguestfs)
A simple approach for converting a physical machine to a virtual
machine, using a rescue CD.
</dd>
<dt><a href="http://libguestfs.org/virt-v2v.1.html">virt-v2v</a></dt>
<dt><a href="http://et.redhat.com/~rjones/virt-p2v/">virt-p2v</a></dt>
<dd>
virt-v2v converts guests from a foreign hypervisor to run on
KVM, managed by libvirt. It can convert guests from VMware or
Xen to run on OpenStack, oVirt (RHEV-M), or local libvirt. It
An older 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, then
copies the disks over to a remote machine and defines the XML for a
domain to run the guest.
</dd>
<dt><a href="http://git.fedorahosted.org/git/?p=virt-v2v.git;a=summary">virt-v2v</a></dt>
<dd>
virt-v2v converts guests from a foreign hypervisor to run on KVM,
managed by libvirt. It can currently convert Red Hat Enterprise
Linux (RHEL) and Fedora guests running on Xen and VMware ESX. It
will enable VirtIO drivers in the converted guest if possible.
(Note this tool is included with libguestfs)
</dd>
<dd>
For RHEL customers of Red Hat, conversion of Windows guests is also
@ -194,47 +180,39 @@
</dd>
</dl>
<h2><a id="desktop">Desktop applications</a></h2>
<h2><a name="desktop">Desktop applications</a></h2>
<dl>
<dt><a href="https://virt-manager.org/">virt-manager</a></dt>
<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
up to managing 10-20 hosts and their VMs.
</dd>
<dt><a href="https://virt-manager.org/">virt-viewer</a></dt>
<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>
<dt><a href="https://f1ash.github.io/qt-virt-manager">qt-virt-manager</a></dt>
<dd>
The Qt GUI for create and control VMs and another virtual entities
(aka networks, storages, interfaces, secrets, network filters).
Contains integrated LXC/SPICE/VNC viewer for accessing the graphical or
text console associated with a virtual machine or container.
</dd>
<dt><a href="https://f1ash.github.io/qt-virt-manager/#virtual-machines-viewer">qt-remote-viewer</a></dt>
<dd>
The Qt VNC/SPICE viewer for access to remote desktops or VMs.
</dd>
</dl>
<h2><a id="iaas">Infrastructure as a Service (IaaS)</a></h2>
<h2><a name="iaas">Infrastructure as a Service (IaaS)</a></h2>
<dl>
<dt><a href="http://cc1.ifj.edu.pl">Cracow Cloud One</a></dt>
<dd>The CC1 system provides a complete solution for Private
Cloud Computing. An intuitive web access interface with an
administration module and simple installation procedure make
it easy to benefit from private Cloud Computing technology.
<dt><a href="http://www.emotivecloud.net">EMOTIVE Cloud</a></dt>
<dd>The EMOTIVE (Elastic Management Of Tasks In Virtualized
Environments) middleware allows executing tasks and providing
virtualized environments to the users with Xen, KVM or
VirtualBox hypervisor. EMOTIVE's main feature is VM management
with different scheduling policies. It can be also used as a
cloud provider and is very easy to extend thanks to its
modular Web Services architecture.
</dd>
<dt><a href="https://github.com/eucalyptus/eucalyptus">Eucalyptus</a></dt>
<dt><a href="http://www.eucalyptus.com">Eucalyptus</a></dt>
<dd>
Eucalyptus is an on-premise Infrastructure as a Service cloud
software platform that is open source and
@ -257,38 +235,9 @@
integrates libvirt for VM monitoring, live migration, and life-cycle
management.
</dd>
<dt><a href="https://www.openstack.org">OpenStack</a></dt>
<dd>
OpenStack is a "cloud operating system" usable for both public
and private clouds. Its various parts take care of compute,
storage and networking resources and interface with the user
using a dashboard. Compute part uses libvirt to manage VM
life-cycle, monitoring and so on.
</dd>
<dt><a href="https://github.com/gustavfranssonnyvell/cherrypop">Cherrypop</a></dt>
<dd>
A cloud software with no masters or central points. Nodes
autodetect other nodes and autodistribute virtual
machines and autodivide up the workload. Also there is no
minimum limit for hosts, well, one might be nice. It's
perfect for setting up low-end servers in a cloud or a
cloud where you want the most bang for the bucks.
</dd>
<dt><a href="http://en.zstack.io/">ZStack</a></dt>
<dd>
ZStack is an open source IaaS software that aims to automate the
management of all resources (compute, storage, networking, etc.) in a
datacenter by using APIs, thus conforming to the principles of a
software-defined datacenter. The key strengths of ZStack in terms of
management are scalability, performance, and a fast, user-friendly
deployment.
</dd>
</dl>
<h2><a id="libraries">Libraries</a></h2>
<h2><a name="libraries">Libraries</a></h2>
<dl>
<dt><a href="http://libguestfs.org">libguestfs</a></dt>
@ -303,28 +252,23 @@
host, and there is a subproject to allow merging changes into the
Windows Registry in Windows guests.
</dd>
<dt><a href="https://sandbox.libvirt.org">libvirt-sandbox</a></dt>
<dd>
A library and command line tools for simplifying the creation of
application sandboxes using virtualization technology. It currently
supports either KVM, QEMU or LXC as backends. Integration with
systemd facilitates sandboxing of system services like apache.
</dd>
<dt><a href="https://github.com/ohadlevy/virt#readme">Ruby
Libvirt Object bindings</a></dt>
<dd>
Allows using simple ruby objects to manipulate
hypervisors, guests, storage, network etc. It is
based on top of
the <a href="https://libvirt.org/ruby">native ruby bindings</a>.
</dd>
</dl>
<h2><a id="livecd">LiveCD / Appliances</a></h2>
<dl>
<dt><a href="https://github.com/ohadlevy/virt#readme">Ruby
Libvirt Object bindings</a></dt>
<dd>
Allows using simple ruby objects to manipulate
hypervisors, guests, storage, network etc. It is
based on top of
the <a href="http://libvirt.org/ruby">native ruby
bindings</a>.
</dd>
</dl>
<h2><a name="livecd">LiveCD / Appliances</a></h2>
<dl>
<dt><a href="http://libguestfs.org/virt-v2v/">virt-p2v</a></dt>
<dt><a href="http://et.redhat.com/~rjones/virt-p2v/">virt-p2v</a></dt>
<dd>
An older tool for converting a physical machine into a virtual
machine. It is a LiveCD which is booted on the machine to be
@ -334,9 +278,9 @@
</dd>
</dl>
<h2><a id="monitoring">Monitoring</a></h2>
<h2><a name="monitoring">Monitoring</a></h2>
<dl>
<dt><a href="https://collectd.org/plugins/libvirt.shtml">collectd</a></dt>
<dt><a href="http://collectd.org/plugins/libvirt.shtml">collectd</a></dt>
<dd>
The libvirt-plugin is part of <a href="http://collectd.org/">collectd</a>
and gathers statistics about virtualized guests on a system. This
@ -345,19 +289,13 @@
For a full description, please refer to the libvirt section in the
collectd.conf(5) manual page.
</dd>
<dt><a href="http://www.sflow.net/">Host sFlow</a></dt>
<dt><a href="http://honk.sigxcpu.org/projects/libvirt/#munin">Munin</a></dt>
<dd>
Host sFlow is a lightweight agent running on KVM hypervisors that
links to libvirt library and exports standardized cpu, memory, network
and disk metrics for all virtual machines.
</dd>
<dt><a href="https://honk.sigxcpu.org/projects/libvirt/#munin">Munin</a></dt>
<dd>
The plugins provided by Guido Günther allow to monitor various things
The plugins provided by Guido G&uuml;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://people.redhat.com/rjones/nagios-virt/">Nagios-virt</a></dt>
<dt><a href="http://et.redhat.com/~rjones/nagios-virt/">Nagios-virt</a></dt>
<dd>
Nagios-virt is a configuration tool to add monitoring of your
virtualised domains to <a href="http://www.nagios.org/">Nagios</a>.
@ -365,15 +303,7 @@
your Xen or QEMU/KVM guests, or to integrate with your existing Nagios
installation.
</dd>
<dt><a href="http://www.pcp.io/man/man1/pmdalibvirt.1.html">PCP</a></dt>
<dd>
The PCP libvirt PMDA (plugin) is part of the
<a href="http://pcp.io/">PCP</a> toolkit and provides
hypervisor and guest information and complete set of guest performance
metrics. It supports pCPU, vCPU, memory, block device, network interface,
and performance event metrics for each virtual guest.
</dd>
<dt><a href="https://community.zenoss.org/docs/DOC-4687">Zenoss</a></dt>
<dt><a href="http://community.zenoss.org/docs/DOC-4687">Zenoss</a></dt>
<dd>
The Zenoss libvirt Zenpack adds support for monitoring virtualization
servers. It has been tested with KVM, QEMU, VMware ESX, and VMware
@ -381,10 +311,10 @@
</dd>
</dl>
<h2><a id="provisioning">Provisioning</a></h2>
<h2><a name="provisioning">Provisioning</a></h2>
<dl>
<dt><a href="https://www.ibm.com/developerworks/community/wikis/home?lang=en#!/wiki/Tivoli+Provisioning+Manager">Tivoli Provisioning Manager</a></dt>
<dt><a href="http://www.ibm.com/software/tivoli/products/prov-mgr/">Tivoli Provisioning Manager</a></dt>
<dd>
Part of the IBM Tivoli family, Tivoli Provisioning Manager (TPM) is
an IT lifecycle automation product. It
@ -394,7 +324,7 @@
</dl>
<dl>
<dt><a href="https://theforeman.org">Foreman</a></dt>
<dt><a href="http://theforeman.org">Foreman</a></dt>
<dd>
Foreman is an open source web based application aimed to be a
Single Address For All Machines Life Cycle Management. Foreman:
@ -410,15 +340,14 @@
<li>Shows you Systems Inventory (based on Facter) and
provides real time information about hosts status based on
Puppet reports.</li>
</ul>
</dd>
</dl>
<h2><a id="web">Web applications</a></h2>
<h2><a name="web">Web applications</a></h2>
<dl>
<dt><a href="http://www.abiquo.com/">AbiCloud</a></dt>
<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
@ -426,64 +355,16 @@
infrastructure. You can deploy a new service just dragging and
dropping a VM.
</dd>
<dt><a href="https://kimchi-project.github.io/kimchi/">Kimchi</a></dt>
<dd>
Kimchi is an HTML5 based management tool for KVM. It is designed to
make it as easy as possible to get started with KVM and create your first guest.
Kimchi manages KVM guests through libvirt. The management interface is accessed
over the web using a browser that supports HTML5.
</dd>
<dt><a href="https://ovirt.org/">oVirt</a></dt>
<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="https://ispsystem.com/en/software/vmmanager">VMmanager</a></dt>
<dd>
VMmanager is a software solution for virtualization management
that can be used both for hosting virtual machines and
building a cloud. VMmanager can manage not only one server,
but a large cluster of hypervisors. It delivers a number of
functions, such as live migration that allows for load
balancing between cluster nodes, monitoring CPU, memory.
</dd>
<dt><a href="https://mist.io/">mist.io</a></dt>
<dd>
Mist.io is an open source project and a service that can assist you in
managing your virtual machines on a unified way, providing a simple
interface for all of your infrastructure (multiple public cloud
providers, OpenStack based public/private clouds, Docker servers, bare
metal servers and now KVM hypervisors).
</dd>
<dt><a href="https://ravada.upc.edu/">Ravada</a></dt>
<dd>
Ravada is an open source tool for managing Virtual Desktop
Infrastructure (VDI). It is very easy to install and use. Following
the documentation, you'll be ready to deploy virtual machines in
minutes. The only requirements for the users are a Web browser and
a lightweight remote viewer.
</dd>
<dt><a href="https://github.com/cutelyst/Virtlyst">Virtlyst</a></dt>
<dd>
Virtlyst is an open source web application built with C++11, Cutelyst and Qt.
It features:
<ul>
<li>Low memory usage (around 5 MiB of RAM)</li>
<li>Look and feel easily customized with HTML templates that use the Django syntax</li>
<li>VNC/Spice console directly in the browser using websockets on the same HTTP port</li>
<li>Host and Domain statistics graphs (CPU, Memory, IO, Network)</li>
<li>Connect to multiple libvirtd instances (over local Unix domain socket, SSH, TCP and TLS)</li>
<li>Manage Storage Pools, Storage Volumes, Networks, Interfaces, and Secrets</li>
<li>Create and launch VMs</li>
<li>Configure VMs with easy panels or go pro and edit the VM's XML</li>
</ul>
</dd>
</dl>
<h2><a id="mobile">Mobile applications</a></h2>
<h2><a name="mobile">Mobile applications</a></h2>
<dl>
<dt><a href="https://market.android.com/details?id=vm.manager">VM Manager</a></dt>
@ -494,19 +375,5 @@
</dd>
</dl>
<h2><a id="other">Other</a></h2>
<dl>
<dt><a href="https://cuckoosandbox.org/">Cuckoo Sandbox</a></dt>
<dd>
Cuckoo Sandbox is a malware analysis system. You can throw
any suspicious file at it and in a matter of seconds Cuckoo
will provide you back some detailed results outlining what
such file did when executed inside an isolated environment.
And libvirt is one of the backends that can be used for the
isolated environment.
</dd>
</dl>
</body>
</html>

5
docs/archdomain.html.in Normal file
View File

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

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<?xml version="1.0"?>
<html>
<body>
<h1 >libvirt architecture</h1>
@ -13,38 +12,54 @@
<ul id="toc"></ul>
<h2><a id="Xen">Xen support</a></h2>
<h2><a name="Xen">Xen support</a></h2>
<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 backend drivers, any running domains, and libxl (aka libxenlight).
libxl provides a set of APIs for creating and managing domains, which can be used
by applications such as the xl tool provided by Xen or libvirt. The hypervisor,
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 will interact with libxl for all management operations
on a Xen system.</p>
<p>Note that the libvirt libxl driver only supports root access.</p>
<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>
<h2><a id="QEMU">QEMU and KVM support</a></h2>
<h2><a name="QEmu">QEmu and KVM support</a></h2>
<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
<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
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
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
<p>The code controlling the QEmu process is available in the
<code>qemud/</code> directory.</p>
<h2><a id="drivers">Driver based architecture</a></h2>
<h2><a name="drivers">Driver based architecture</a></h2>
<p>As the previous section explains, libvirt can communicate using different
channels with the current hypervisor, and should also be able to use
@ -67,9 +82,9 @@ drivers present in driver.h:</p>
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
<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>
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>

53
docs/archnetwork.html.in Normal file
View File

@ -0,0 +1,53 @@
<?xml version="1.0"?>
<html>
<body>
<h1>Network management architecture</h1>
<ul id="toc"></ul>
<h2><a name="architecture">Architecture illustration</a></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><a name="logical">Logical diagram</a></h3>
<p class="image">
<img src="libvirt-net-logical.png" alt="Logical network architecture"/>
</p>
<h3><a name="physical">Physical diagram</a></h3>
<p class="image">
<img src="libvirt-net-physical.png" alt="Physical network architecture"/>
</p>
</body>
</html>

5
docs/archnode.html.in Normal file
View File

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

30
docs/archstorage.html.in Normal file
View File

@ -0,0 +1,30 @@
<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,375 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<h1>Audit log</h1>
<ul id="toc"></ul>
<h2><a id="intro">Introduction</a></h2>
<p>
A number of the libvirt virtualization drivers (QEMU/KVM and LXC) include
support for logging details of important operations to the host's audit
subsystem. This provides administrators / auditors with a canonical historical
record of changes to virtual machines' / containers' lifecycle states and
their configuration. On hosts which are running the Linux audit daemon,
the logs will usually end up in <code>/var/log/audit/audit.log</code>
</p>
<h2><a id="config">Configuration</a></h2>
<p>
The libvirt audit integration is enabled by default on any host which has
the Linux audit subsystem active, and disabled otherwise. It is possible
to alter this behaviour in the <code>/etc/libvirt/libvirtd.conf</code>
configuration file, via the <code>audit_level</code> parameter
</p>
<ul>
<li><code>audit_level=0</code> - libvirt auditing is disabled regardless
of host audit subsystem enablement.</li>
<li><code>audit_level=1</code> - libvirt auditing is enabled if the host
audit subsystem is enabled, otherwise it is disabled. This is the
default behaviour.</li>
<li><code>audit_level=2</code> - libvirt auditing is enabled regardless
of host audit subsystem enablement. If the host audit subsystem is
disabled, then libvirtd will refuse to complete startup and exit with
an error.</li>
</ul>
<p>
In addition to have formal messages sent to the audit subsystem it is
possible to tell libvirt to inject messages into its own logging
layer. This will result in messages ending up in the systemd journal
or <code>/var/log/libvirt/libivrtd.log</code> on non-systemd hosts.
This is disabled by default, but can be requested by setting the
<code>audit_logging=1</code> configuration parameter in the same file
mentioned above.
</p>
<h2><a id="types">Message types</a></h2>
<p>
Libvirt defines three core audit message types each of which will
be described below. There are a number of common fields that will
be reported for all message types.
</p>
<dl>
<dt><code>pid</code></dt>
<dd>Process ID of the libvirtd daemon generating the audit record.</dd>
<dt><code>uid</code></dt>
<dd>User ID of the libvirtd daemon process generating the audit record.</dd>
<dt><code>subj</code></dt>
<dd>Security context of the libvirtd daemon process generating the audit record.</dd>
<dt><code>msg</code></dt>
<dd>String containing a list of key=value pairs specific to the type of audit record being reported.</dd>
</dl>
<p>
Some fields in the <code>msg</code> string are common to audit records
</p>
<dl>
<dt><code>virt</code></dt>
<dd>Type of virtualization driver used. One of <code>qemu</code> or <code>lxc</code></dd>
<dt><code>vm</code></dt>
<dd>Host driver unique name of the guest</dd>
<dt><code>uuid</code></dt>
<dd>Globally unique identifier for the guest</dd>
<dt><code>exe</code></dt>
<dd>Path of the libvirtd daemon</dd>
<dt><code>hostname</code></dt>
<dd>Currently unused</dd>
<dt><code>addr</code></dt>
<dd>Currently unused</dd>
<dt><code>terminal</code></dt>
<dd>Currently unused</dd>
<dt><code>res</code></dt>
<dd>Result of the action, either <code>success</code> or <code>failed</code></dd>
</dl>
<h3><a id="typecontrol">VIRT_CONTROL</a></h3>
<p>
Reports change in the lifecycle state of a virtual machine. The <code>msg</code>
field will include the following sub-fields
</p>
<dl>
<dt><code>op</code></dt>
<dd>Type of operation performed. One of <code>start</code>, <code>stop</code> or <code>init</code></dd>
<dt><code>reason</code></dt>
<dd>The reason which caused the operation to happen</dd>
<dt><code>vm-pid</code></dt>
<dd>ID of the primary/leading process associated with the guest</dd>
<dt><code>init-pid</code></dt>
<dd>ID of the <code>init</code> process in a container. Only if <code>op=init</code> and <code>virt=lxc</code></dd>
<dt><code>pid-ns</code></dt>
<dd>Namespace ID of the <code>init</code> process in a container. Only if <code>op=init</code> and <code>virt=lxc</code></dd>
</dl>
<h3><a id="typemachine">VIRT_MACHINE_ID</a></h3>
<p>
Reports the association of a security context with a guest. The <code>msg</code>
field will include the following sub-fields
</p>
<dl>
<dt><code>model</code></dt>
<dd>The security driver type. One of <code>selinux</code> or <code>apparmor</code></dd>
<dt><code>vm-ctx</code></dt>
<dd>Security context for the guest process</dd>
<dt><code>img-ctx</code></dt>
<dd>Security context for the guest disk images and other assigned host resources</dd>
</dl>
<h3><a id="typeresource">VIRT_RESOURCE</a></h3>
<p>
Reports the usage of a host resource by a guest. The fields include will
vary according to the type of device being reported. When the guest is
initially booted records will be generated for all assigned resources.
If any changes are made to the running guest configuration, for example
hotplug devices, or adjust resources allocation, further records will
be generated.
</p>
<h4><a id="typeresourcevcpu">Virtual CPU</a></h4>
<p>
The <code>msg</code> field will include the following sub-fields
</p>
<dl>
<dt><code>reason</code></dt>
<dd>The reason which caused the resource to be assigned to happen</dd>
<dt><code>resrc</code></dt>
<dd>The type of resource assigned. Set to <code>vcpu</code></dd>
<dt><code>old-vcpu</code></dt>
<dd>Original vCPU count, or 0</dd>
<dt><code>new-vcpu</code></dt>
<dd>Updated vCPU count</dd>
</dl>
<h4><a id="typeresourcemem">Memory</a></h4>
<p>
The <code>msg</code> field will include the following sub-fields
</p>
<dl>
<dt><code>reason</code></dt>
<dd>The reason which caused the resource to be assigned to happen</dd>
<dt><code>resrc</code></dt>
<dd>The type of resource assigned. Set to <code>mem</code></dd>
<dt><code>old-mem</code></dt>
<dd>Original memory size in bytes, or 0</dd>
<dt><code>new-mem</code></dt>
<dd>Updated memory size in bytes</dd>
</dl>
<h4><a id="typeresourcedisk">Disk</a></h4>
<p>
The <code>msg</code> field will include the following sub-fields
</p>
<dl>
<dt><code>reason</code></dt>
<dd>The reason which caused the resource to be assigned to happen</dd>
<dt><code>resrc</code></dt>
<dd>The type of resource assigned. Set to <code>disk</code></dd>
<dt><code>old-disk</code></dt>
<dd>Original host file or device path acting as the disk backing file</dd>
<dt><code>new-disk</code></dt>
<dd>Updated host file or device path acting as the disk backing file</dd>
</dl>
<h4><a id="typeresourcenic">Network interface</a></h4>
<p>
The <code>msg</code> field will include the following sub-fields
</p>
<dl>
<dt><code>reason</code></dt>
<dd>The reason which caused the resource to be assigned to happen</dd>
<dt><code>resrc</code></dt>
<dd>The type of resource assigned. Set to <code>net</code></dd>
<dt><code>old-net</code></dt>
<dd>Original MAC address of the guest network interface</dd>
<dt><code>new-net</code></dt>
<dd>Updated MAC address of the guest network interface</dd>
</dl>
<p>
If there is a host network interface associated with the guest NIC then
further records may be generated
</p>
<dl>
<dt><code>reason</code></dt>
<dd>The reason which caused the resource to be assigned to happen</dd>
<dt><code>resrc</code></dt>
<dd>The type of resource assigned. Set to <code>net</code></dd>
<dt><code>net</code></dt>
<dd>MAC address of the host network interface</dd>
<dt><code>rdev</code></dt>
<dd>Name of the host network interface</dd>
</dl>
<h4><a id="typeresourcefs">Filesystem</a></h4>
<p>
The <code>msg</code> field will include the following sub-fields
</p>
<dl>
<dt><code>reason</code></dt>
<dd>The reason which caused the resource to be assigned to happen</dd>
<dt><code>resrc</code></dt>
<dd>The type of resource assigned. Set to <code>fs</code></dd>
<dt><code>old-fs</code></dt>
<dd>Original host directory, file or device path backing the filesystem </dd>
<dt><code>new-fs</code></dt>
<dd>Updated host directory, file or device path backing the filesystem</dd>
</dl>
<h4><a id="typeresourcehost">Host device</a></h4>
<p>
The <code>msg</code> field will include the following sub-fields
</p>
<dl>
<dt><code>reason</code></dt>
<dd>The reason which caused the resource to be assigned to happen</dd>
<dt><code>resrc</code></dt>
<dd>The type of resource assigned. Set to <code>hostdev</code> or <code>dev</code></dd>
<dt><code>dev</code></dt>
<dd>The unique bus identifier of the USB, PCI or SCSI device, if <code>resrc=dev</code></dd>
<dt><code>disk</code></dt>
<dd>The path of the block device assigned to the guest, if <code>resrc=hostdev</code></dd>
<dt><code>chardev</code></dt>
<dd>The path of the character device assigned to the guest, if <code>resrc=hostdev</code></dd>
</dl>
<h4><a id="typeresourcetpm">TPM</a></h4>
<p>
The <code>msg</code> field will include the following sub-fields
</p>
<dl>
<dt><code>reason</code></dt>
<dd>The reason which caused the resource to be assigned to happen</dd>
<dt><code>resrc</code></dt>
<dd>The type of resource assigned. Set to <code>tpm</code> or <code>tpm-emulator</code></dd>
<dt><code>device</code></dt>
<dd>The path of the host TPM device assigned to the guest</dd>
</dl>
<h4><a id="typeresourcerng">RNG</a></h4>
<p>
The <code>msg</code> field will include the following sub-fields
</p>
<dl>
<dt><code>reason</code></dt>
<dd>The reason which caused the resource to be assigned to happen</dd>
<dt><code>resrc</code></dt>
<dd>The type of resource assigned. Set to <code>rng</code></dd>
<dt><code>old-rng</code></dt>
<dd>Original path of the host entropy source for the RNG</dd>
<dt><code>new-rng</code></dt>
<dd>Updated path of the host entropy source for the RNG</dd>
</dl>
<h4><a id="typeresourcechardev">console/serial/parallel/channel</a></h4>
<p>
The <code>msg</code> field will include the following sub-fields
</p>
<dl>
<dt><code>reason</code></dt>
<dd>The reason which caused the resource to be assigned to happen</dd>
<dt><code>resrc</code></dt>
<dd>The type of resource assigned. Set to <code>chardev</code></dd>
<dt><code>old-chardev</code></dt>
<dd>Original path of the backing character device for given emulated device</dd>
<dt><code>new-chardev</code></dt>
<dd>Updated path of the backing character device for given emulated device</dd>
</dl>
<h4><a id="typeresourcesmartcard">smartcard</a></h4>
<p>
The <code>msg</code> field will include the following sub-fields
</p>
<dl>
<dt><code>reason</code></dt>
<dd>The reason which caused the resource to be assigned to happen</dd>
<dt><code>resrc</code></dt>
<dd>The type of resource assigned. Set to <code>smartcard</code></dd>
<dt><code>old-smartcard</code></dt>
<dd>Original path of the backing character device, certificate store or
"nss-smartcard-device" for host smartcard passthrough.
</dd>
<dt><code>new-smartcard</code></dt>
<dd>Updated path of the backing character device, certificate store or
"nss-smartcard-device" for host smartcard passthrough.
</dd>
</dl>
<h4><a id="typeresourceredir">Redirected device</a></h4>
<p>
The <code>msg</code> field will include the following sub-fields
</p>
<dl>
<dt><code>reason</code></dt>
<dd>The reason which caused the resource to be assigned to happen</dd>
<dt><code>resrc</code></dt>
<dd>The type of resource assigned. Set to <code>redir</code></dd>
<dt><code>bus</code></dt>
<dd>The bus type, only <code>usb</code> allowed</dd>
<dt><code>device</code></dt>
<dd>The device type, only <code>USB redir</code> allowed</dd>
</dl>
<h4><a id="typeresourcecgroup">Control group</a></h4>
<p>
The <code>msg</code> field will include the following sub-fields
</p>
<dl>
<dt><code>reason</code></dt>
<dd>The reason which caused the resource to be assigned to happen</dd>
<dt><code>resrc</code></dt>
<dd>The type of resource assigned. Set to <code>cgroup</code></dd>
<dt><code>cgroup</code></dt>
<dd>The name of the cgroup controller</dd>
</dl>
<h4><a id="typeresourceshmem">Shared memory</a></h4>
<p>
The <code>msg</code> field will include the following sub-fields
</p>
<dl>
<dt><code>resrc</code></dt>
<dd>The type of resource assigned. Set to <code>shmem</code></dd>
<dt><code>reason</code></dt>
<dd>The reason which caused the resource to be assigned to happen</dd>
<dt><code>size</code></dt>
<dd>The size of the shared memory region</dd>
<dt><code>shmem</code></dt>
<dd>Name of the shared memory region</dd>
<dt><code>source</code></dt>
<dd>Path of the backing character device for given emulated device</dd>
</dl>
</body>
</html>

View File

@ -1,20 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<?xml version="1.0"?>
<html>
<body>
<h1>Connection authentication</h1>
<h1 >Authentication &amp; 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. Once authenticated, libvirt can apply
fine grained <a href="acl.html">access control</a> to the operations
performed by a client.
of applications using libvirt.
</p>
<ul id="toc"></ul>
<h2><a id="Auth_client_config">Client configuration</a></h2>
<h2><a name="Auth_client_config">Client configuration</a></h2>
<p>
When connecting to a remote hypervisor which requires authentication,
@ -76,11 +73,7 @@ password=letmein
[credentials-dev]
username=joe
password=hello
[credentials-defgrp]
username=defuser
password=defpw</pre>
password=hello</pre>
<p>
The second set of groups provide mappings of credentials to
@ -94,8 +87,7 @@ credentials=$CREDENTIALS</pre>
<p>
For example, following the previous example, here is how to
map some machines. For convenience libvirt supports a default
mapping of credentials to machines:
list some machines
</p>
<pre>
@ -111,15 +103,8 @@ credentials=test
[auth-libvirt-prod1.example.com]
credentials=prod
[auth-libvirt-default]
credentials=defgrp
[auth-esx-dev1.example.com]
credentials=dev
[auth-esx-default]
credentials=defgrp</pre>
credentials=dev</pre>
<p>
The following service types are known to libvirt
@ -142,7 +127,7 @@ credentials=defgrp</pre>
to storage VNC or SPICE login credentials
</p>
<h2><a id="ACL_server_config">Server configuration</a></h2>
<h2><a name="ACL_server_config">Server configuration</a></h2>
<p>
The libvirt daemon allows the administrator to choose the authentication
mechanisms used for client connections on each network socket independently.
@ -153,7 +138,7 @@ currently a choice of <code>none</code>, <code>polkit</code>, and <code>sasl</co
The SASL scheme can be further configured to choose between a large
number of different mechanisms.
</p>
<h2><a id="ACL_server_unix_perms">UNIX socket permissions/group</a></h2>
<h2><a name="ACL_server_unix_perms">UNIX socket permissions/group</a></h2>
<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
@ -170,10 +155,10 @@ 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>
<h2><a id="ACL_server_polkit">UNIX socket PolicyKit auth</a></h2>
<h2><a name="ACL_server_polkit">UNIX socket PolicyKit auth</a></h2>
<p>
If libvirt contains support for PolicyKit, then access control options are
more advanced. The <code>auth_unix_rw</code> parameter will default to
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
@ -204,72 +189,16 @@ ResultActive=yes</pre>
Further examples of PolicyKit setup can be found on the
<a href="http://wiki.libvirt.org/page/SSHPolicyKitSetup">wiki page</a>.
</p>
<h2><a id="ACL_server_sasl">SASL pluggable authentication</a></h2>
<h2><a name="ACL_server_username">Username/password auth</a></h2>
<p>
Libvirt integrates with the cyrus-sasl library to provide a pluggable authentication
system using the SASL protocol. SASL can be used in combination with libvirtd's TLS
or TCP socket listeners. When used with the TCP listener, the SASL mechanism is
rqeuired to provide session encryption in addition to authentication. Only a very
few SASL mechanisms are able to do this, and of those that can do it, only the
GSSAPI plugin is considered acceptably secure by modern standards:
</p>
<dl>
<dt>GSSAPI</dt>
<dd><strong>This is the current default mechanism to use with libvirtd</strong>.
It uses the Kerberos v5 authentication protocol underneath, and assuming
the Kerberos client/server are configured with modern ciphers (AES),
it provides strong session encryption capabilities.</dd>
<dt>DIGEST-MD5</dt>
<dd>This was previously set as the default mechanism to use with libvirtd.
It provides a simple username/password based authentication mechanism
that includes session encryption.
<a href="https://tools.ietf.org/html/rfc6331">RFC 6331</a>, however,
documents a number of serious security flaws with DIGEST-MD5 and as a
result marks it as <code>OBSOLETE</code>. Specific concerns are that
it is vulnerable to MITM attacks and the MD5 hash can be brute-forced
to reveal the password. A replacement is provided via the SCRAM mechanism,
however, note that this does not provide encryption, so the SCRAM
mechanism can only be used on the libvirtd TLS listener.
</dd>
<dt>PASSDSS-3DES-1</dt>
<dd>This provides a simple username/password based authentication
mechanism that includes session encryption. The current cyrus-sasl
implementation does not provide a way to validate the server's
public key identity, thus it is susceptible to a MITM attacker
impersonating the server. It is also not enabled in many OS
distros when building SASL libraries.</dd>
<dt>KERBEROS_V4</dt>
<dd>This uses the obsolete Kerberos v4 protocol to provide both authentication
and session encryption. Kerberos v4 protocol has been obsolete since the
early 1990's and has known security vulnerabilities so this will never be
used in practice.</dd>
</dl>
<p>
Other SASL mechanisms, not listed above, can only be used when the libvirtd
TLS or UNIX socket listeners.
</p>
<h3><a id="ACL_server_username">Username/password auth</a></h3>
<p>
As noted above, the DIGEST-MD5 mechanism is considered obsolete and should
not be used anymore. To provide a simple username/password auth scheme on
the libvirt UNIX socket or TLS listeners, however, it is possible to use
the SCRAM mechanism. The <code>auth_unix_ro</code>, <code>auth_unix_rw</code>,
<code>auth_tls</code> config params in <code>libvirt.conf</code> can be used
to turn on SASL auth in these listeners.
</p>
<p>
Since the libvirt SASL config file defaults to using GSSAPI (Kerberos), a
config change is rquired to enable plain password auth. This is done by
editting <code>/etc/sasl2/libvirt.conf</code> to set the <code>mech_list</code>
parameter to <code>scram-sha-1</code>.
</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>
@ -297,13 +226,17 @@ again:
<pre>
# saslpasswd2 -a libvirt -d fred
</pre>
<h3><a id="ACL_server_kerberos">GSSAPI/Kerberos auth</a></h3>
<h2><a name="ACL_server_kerberos">Kerberos auth</a></h2>
<p>
The plain TCP listener of the libvirt daemon defaults to using SASL for authentication.
The libvirt SASL config also defaults to GSSAPI, so there is no need to edit the
SASL config when using GSSAPI. If the libvirtd TLS or UNIX listeners are used,
then the Kerberos session encryption will be disabled since it is not required
in these scenarios - only the plain TCP listener needs encryption
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>, and keytab should be set to
<code>/etc/libvirt/krb5.tab</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

View File

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<?xml version="1.0"?>
<html>
<body>
<h1 >Bindings for other languages and integration API modules</h1>
<h1 >Bindings for other languages</h1>
<p>
Libvirt supports C and C++ directly, and has bindings available
@ -14,17 +13,13 @@
<strong>C#</strong>: Arnaud Champion develops
<a href="csharp.html">C# bindings</a>.
</li>
<li>
<strong>Go</strong>: Daniel Berrange develops
<a href="https://godoc.org/github.com/libvirt/libvirt-go">Go bindings</a>.
</li>
<li>
<strong>Java</strong>: Daniel Veillard develops
<a href="java.html">Java bindings</a>.
</li>
<li>
<strong>OCaml</strong>: Richard Jones develops
<a href="https://libvirt.org/ocaml/">OCaml bindings</a>.
<a href="http://libvirt.org/ocaml/">OCaml bindings</a>.
</li>
<li>
<strong>Perl</strong>: Daniel Berrange develops
@ -33,7 +28,7 @@
<li>
<p>
<strong>PHP</strong>: Radek Hladik started developing
<a href="https://libvirt.org/php">PHP bindings</a> in 2010.
<a href="http://libvirt.org/php">PHP bindings</a> in 2010.
</p>
<p>
In February 2011 the binding development has been moved to the libvirt.org website as
@ -43,15 +38,13 @@
The project is now maintained by Michal Novotny and it's heavily based
on Radek's version. For more information, including
information on posting patches to libvirt-php, please refer
to the <a href="https://libvirt.org/php">PHP bindings</a> site.
to the <a href="http://libvirt.org/php">PHP bindings</a> site.
</p>
</li>
<li>
<p>
<strong>Python</strong>: Libvirt's python bindings are split to a
separate <a href="https://libvirt.org/git/?p=libvirt-python.git">package</a>
since version 1.2.0, older versions came with direct support for the
Python language.
<strong>Python</strong>: Libvirt comes with direct support for
the Python language.
</p>
<p>
If your libvirt is installed as packages, rather than compiled
@ -70,18 +63,7 @@
</li>
<li>
<strong>Ruby</strong>: Chris Lalancette develops
<a href="https://libvirt.org/ruby/">Ruby bindings</a>.
</li>
</ul>
<p>
Integration API modules:
</p>
<ul>
<li>
<strong>D-Bus</strong>: Pavel Hrdina develops
<a href="dbus.html">D-Bus API</a>.
<a href="http://libvirt.org/ruby/">Ruby bindings</a>.
</li>
</ul>

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#b91d47</TileColor>
</tile>
</msapplication>
</browserconfig>

View File

@ -1,25 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<?xml version="1.0"?>
<html>
<body>
<h1>Bug reporting</h1>
<ul id="toc"></ul>
<h2><a id="security">Security Issues</a></h2>
<p>
If you think that an issue with libvirt may have security
implications, <strong>please do not</strong> publicly
report it in the bug tracker, mailing lists, or irc. Libvirt
has <a href="securityprocess.html">a dedicated process for handling (potential) security issues</a>
that should be used instead. So if your issue has security
implications, ignore the rest of this page and follow the
<a href="securityprocess.html">security process</a> instead.
</p>
<h2><a id="bugzilla">Bug Tracking</a></h2>
<h2><a name="bugzilla">Bug Tracking</a></h2>
<p>
If you are using libvirt binaries from a Linux distribution
@ -27,7 +14,7 @@
first.
</p>
<h2><a id="general">General libvirt bug reports</a></h2>
<h2><a name="general">General libvirt bug reports</a></h2>
<p>
The <a href="http://bugzilla.redhat.com">Red Hat Bugzilla Server</a>
@ -69,7 +56,7 @@
<li><a href="http://bugzilla.redhat.com/bugzilla/enter_bug.cgi?product=Virtualization%20Tools&amp;component=libvirt">New libvirt ticket</a></li>
</ul>
<h2><a id="distribution">Linux Distribution specific bug reports</a></h2>
<h2><a name="distribution">Linux Distribution specific bug reports</a></h2>
<ul>
<li>
If you are using binaries from <strong>Fedora</strong>, enter
@ -107,7 +94,7 @@
</ul>
<h2><a id="quality">How to file high quality bug reports</a></h2>
<h2><a name="quality">How to file high quality bug reports</a></h2>
<p>
To increase the likelihood of your bug report being addressed it is
@ -122,8 +109,7 @@
<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 domain logfiles from /var/log/xen and
/var/log/libvirt/libxl</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>
@ -133,7 +119,7 @@
crash, the simplest is to run the program under gdb, reproduce the
steps leading to the crash and then issue a gdb "bt -a" command to
get the stack trace, attach it to the bug. Note that for the
data to be really useful libvirt debug information must be present
data to be really useful libvirt debug informations must be present
for example by installing libvirt debuginfo package on Fedora or
Red Hat Enterprise Linux (with debuginfo-install libvirt) prior
to running gdb.</p>
@ -148,11 +134,11 @@
<pre> # ps -o etime,pid `pgrep libvirt`
... note the process id from the output
# gdb /usr/sbin/libvirtd
.... some information about gdb and loading debug data
(gdb) attach $the_daemon_process_id
.... some informations about gdb and loading debug data
(gdb) attach $the_damon_process_id
....
(gdb) thread apply all bt
.... information to attach to the bug
.... informations to attach to the bug
(gdb)
</pre>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<h1>Control Groups Resource Management</h1>
@ -11,7 +11,7 @@
for applying resource management to their virtual machines and containers.
</p>
<h2><a id="requiredControllers">Required controllers</a></h2>
<h2><a name="requiredControllers">Required controllers</a></h2>
<p>
The control groups filesystem supports multiple "controllers". By default
@ -23,148 +23,41 @@
<p>
The QEMU driver is capable of using the <code>cpuset</code>,
<code>cpu</code>, <code>cpuacct</code>, <code>memory</code>,
<code>blkio</code> and <code>devices</code> controllers.
None of them are compulsory. If any controller is not mounted,
the resource management APIs which use it will cease to operate.
It is possible to explicitly turn off use of a controller,
even when mounted, via the <code>/etc/libvirt/qemu.conf</code>
configuration file.
<code>cpu</code>, <code>memory</code>, <code>blkio</code> and
<code>devices</code> controllers. None of them are compulsory.
If any controller is not mounted, the resource management APIs
which use it will cease to operate. It is possible to explicitly
turn off use of a controller, even when mounted, via the
<code>/etc/libvirt/qemu.conf</code> configuration file.
</p>
<p>
The LXC driver is capable of using the <code>cpuset</code>,
<code>cpu</code>, <code>cpuacct</code>, <code>freezer</code>,
<code>cpu</code>, <code>cpuset</code>, <code>freezer</code>,
<code>memory</code>, <code>blkio</code> and <code>devices</code>
controllers. The <code>cpuacct</code>, <code>devices</code>
controllers. The <code>cpuset</code>, <code>devices</code>
and <code>memory</code> controllers are compulsory. Without
them mounted, no containers can be started. If any of the
other controllers are not mounted, the resource management APIs
which use them will cease to operate.
</p>
<h2><a id="currentLayout">Current cgroups layout</a></h2>
<h2><a name="currentLayout">Current cgroups layout</a></h2>
<p>
As of libvirt 1.0.5 or later, the cgroups layout created by libvirt has been
simplified, in order to facilitate the setup of resource control policies by
administrators / management applications. The new layout is based on the concepts
of "partitions" and "consumers". A "consumer" is a cgroup which holds the
processes for a single virtual machine or container. A "partition" is a cgroup
which does not contain any processes, but can have resource controls applied.
A "partition" will have zero or more child directories which may be either
"consumer" or "partition".
</p>
<p>
As of libvirt 1.1.1 or later, the cgroups layout will have some slight
differences when running on a host with systemd 205 or later. The overall
tree structure is the same, but there are some differences in the naming
conventions for the cgroup directories. Thus the following docs split
in two, one describing systemd hosts and the other non-systemd hosts.
</p>
<h3><a id="currentLayoutSystemd">Systemd cgroups integration</a></h3>
<p>
On hosts which use systemd, each consumer maps to a systemd scope unit,
while partitions map to a system slice unit.
</p>
<h4><a id="systemdScope">Systemd scope naming</a></h4>
<p>
The systemd convention is for the scope name of virtual machines / containers
to be of the general format <code>machine-$NAME.scope</code>. Libvirt forms the
<code>$NAME</code> part of this by concatenating the driver type with the id
and truncated name of the guest, and then escaping any systemd reserved
characters.
So for a guest <code>demo</code> running under the <code>lxc</code> driver,
we get a <code>$NAME</code> of <code>lxc-12345-demo</code> which when escaped
is <code>lxc\x2d12345\x2ddemo</code>. So the complete scope name is
<code>machine-lxc\x2d12345\x2ddemo.scope</code>.
The scope names map directly to the cgroup directory names.
</p>
<h4><a id="systemdSlice">Systemd slice naming</a></h4>
<p>
The systemd convention for slice naming is that a slice should include the
name of all of its parents prepended on its own name. So for a libvirt
partition <code>/machine/engineering/testing</code>, the slice name will
be <code>machine-engineering-testing.slice</code>. Again the slice names
map directly to the cgroup directory names. Systemd creates three top level
slices by default, <code>system.slice</code> <code>user.slice</code> and
<code>machine.slice</code>. All virtual machines or containers created
by libvirt will be associated with <code>machine.slice</code> by default.
</p>
<h4><a id="systemdLayout">Systemd cgroup layout</a></h4>
<p>
Given this, a possible systemd cgroups layout involving 3 qemu guests,
3 lxc containers and 3 custom child slices, would be:
</p>
<pre>
$ROOT
|
+- system.slice
| |
| +- libvirtd.service
|
+- machine.slice
|
+- machine-qemu\x2d1\x2dvm1.scope
| |
| +- emulator
| +- vcpu0
| +- vcpu1
|
+- machine-qemu\x2d2\x2dvm2.scope
| |
| +- emulator
| +- vcpu0
| +- vcpu1
|
+- machine-qemu\x2d3\x2dvm3.scope
| |
| +- emulator
| +- vcpu0
| +- vcpu1
|
+- machine-engineering.slice
| |
| +- machine-engineering-testing.slice
| | |
| | +- machine-lxc\x2d11111\x2dcontainer1.scope
| |
| +- machine-engineering-production.slice
| |
| +- machine-lxc\x2d22222\x2dcontainer2.scope
|
+- machine-marketing.slice
|
+- machine-lxc\x2d33333\x2dcontainer3.scope
</pre>
<h3><a id="currentLayoutGeneric">Non-systemd cgroups layout</a></h3>
<p>
On hosts which do not use systemd, each consumer has a corresponding cgroup
named <code>$VMNAME.libvirt-{qemu,lxc}</code>. Each consumer is associated
with exactly one partition, which also have a corresponding cgroup usually
named <code>$PARTNAME.partition</code>. The exceptions to this naming rule
are the three top level default partitions, named <code>/system</code> (for
system services), <code>/user</code> (for user login sessions) and
<code>/machine</code> (for virtual machines and containers). By default
every consumer will of course be associated with the <code>/machine</code>
partition.
</p>
<p>
Given this, a possible systemd cgroups layout involving 3 qemu guests,
3 lxc containers and 2 custom child slices, would be:
administrators / management applications. The layout is based on the concepts of
"partitions" and "consumers". Each virtual machine or container is a consumer,
and has a corresponding cgroup named <code>$VMNAME.libvirt-{qemu,lxc}</code>.
Each consumer is associated with exactly one partition, which also have a
corresponding cgroup usually named <code>$PARTNAME.partition</code>. The
exceptions to this naming rule are the three top level default partitions,
named <code>/system</code> (for system services), <code>/user</code> (for
user login sessions) and <code>/machine</code> (for virtual machines and
containers). By default every consumer will of course be associated with
the <code>/machine</code> partition. This leads to a hierarchy that looks
like
</p>
<pre>
@ -176,40 +69,42 @@ $ROOT
|
+- machine
|
+- qemu-1-vm1.libvirt-qemu
+- vm1.libvirt-qemu
| |
| +- emulator
| +- vcpu0
| +- vcpu1
|
+- qeme-2-vm2.libvirt-qemu
+- vm2.libvirt-qemu
| |
| +- emulator
| +- vcpu0
| +- vcpu1
|
+- qemu-3-vm3.libvirt-qemu
+- vm3.libvirt-qemu
| |
| +- emulator
| +- vcpu0
| +- vcpu1
|
+- engineering.partition
| |
| +- testing.partition
| | |
| | +- lxc-11111-container1.libvirt-lxc
| |
| +- production.partition
| |
| +- lxc-22222-container2.libvirt-lxc
+- container1.libvirt-lxc
|
+- marketing.partition
|
+- lxc-33333-container3.libvirt-lxc
+- container2.libvirt-lxc
|
+- container3.libvirt-lxc
</pre>
<h2><a id="customPartiton">Using custom partitions</a></h2>
<p>
The default cgroups layout ensures that, when there is contention for
CPU time, it is shared equally between system services, user sessions
and virtual machines / containers. This prevents virtual machines from
locking the administrator out of the host, or impacting execution of
system services. Conversely, when there is no contention from
system services / user sessions, it is possible for virtual machines
to fully utilize the host CPUs.
</p>
<h2><a name="customPartiton">Using custom partitions</a></h2>
<p>
If there is a need to apply resource constraints to groups of
@ -224,62 +119,20 @@ $ROOT
</p>
<pre>
...
&lt;resource&gt;
&lt;partition&gt;/machine/production&lt;/partition&gt;
&lt;/resource&gt;
...
...
&lt;resource&gt;
&lt;partition&gt;/machine/production&lt;/partition&gt;
&lt;/resource&gt;
...
</pre>
<p>
Note that the partition names in the guest XML are using a
generic naming format, not the low level naming convention
required by the underlying host OS. That is, you should not include
any of the <code>.partition</code> or <code>.slice</code>
suffixes in the XML config. Given a partition name
<code>/machine/production</code>, libvirt will automatically
apply the platform specific translation required to get
<code>/machine/production.partition</code> (non-systemd)
or <code>/machine.slice/machine-production.slice</code>
(systemd) as the underlying cgroup name
</p>
<p>
Libvirt will not auto-create the cgroups directory to back
this partition. In the future, libvirt / virsh will provide
APIs / commands to create custom partitions, but currently
this is left as an exercise for the administrator.
</p>
<p>
<strong>Note:</strong> the ability to place guests in custom
partitions is only available with libvirt &gt;= 1.0.5, using
the new cgroup layout. The legacy cgroups layout described
later in this document did not support customization per guest.
</p>
<h3><a id="createSystemd">Creating custom partitions (systemd)</a></h3>
<p>
Given the XML config above, the admin on a systemd based host would
need to create a unit file <code>/etc/systemd/system/machine-production.slice</code>
</p>
<pre>
# cat &gt; /etc/systemd/system/machine-testing.slice &lt;&lt;EOF
[Unit]
Description=VM testing slice
Before=slices.target
Wants=machine.slice
EOF
# systemctl start machine-testing.slice
</pre>
<h3><a id="createNonSystemd">Creating custom partitions (non-systemd)</a></h3>
<p>
Given the XML config above, the admin on a non-systemd based host
would need to create a cgroup named '/machine/production.partition'
this is left as an exercise for the administrator. For
example, given the XML config above, the admin would need
to create a cgroup named '/machine/production.partition'
</p>
<pre>
@ -294,7 +147,19 @@ EOF
done
</pre>
<h2><a id="resourceAPIs">Resource management APIs/commands</a></h2>
<p>
<strong>Note:</strong> the cgroups directory created as a ".partition"
suffix, but the XML config does not require this suffix.
</p>
<p>
<strong>Note:</strong> the ability to place guests in custom
partitions is only available with libvirt &gt;= 1.0.5, using
the new cgroup layout. The legacy cgroups layout described
later did not support customization per guest.
</p>
<h2><a name="resourceAPIs">Resource management APIs/commands</a></h2>
<p>
Since libvirt aims to provide an API which is portable across
@ -357,7 +222,7 @@ swap_hard_limit: unlimited
network interfaces.
</p>
<h2><a id="legacyLayout">Legacy cgroups layout</a></h2>
<h2><a name="legacyLayout">Legacy cgroups layout</a></h2>
<p>
Prior to libvirt 1.0.5, the cgroups layout created by libvirt was different

View File

@ -1,21 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<?xml version="1.0"?>
<html>
<body>
<h1><a id="installation">libvirt Installation</a></h1>
<h1><a name="installation">libvirt Installation</a></h1>
<ul id="toc"></ul>
<h2><a id="compiling">Compiling a release tarball</a></h2>
<h2><a name="compiling">Compiling a release tarball</a></h2>
<p>
libvirt uses the standard configure/make/install steps:
</p>
<pre>
$ xz -c libvirt-x.x.x.tar.xz | tar xvf -
$ cd libvirt-x.x.x
$ ./configure</pre>
$ gunzip -c libvirt-x.x.x.tar.gz | tar xvf -
$ cd libvirt-x.x.x
$ ./configure</pre>
<p>
The <i>configure</i> script can be given options to change its default
@ -28,7 +27,7 @@ $ ./configure</pre>
</p>
<pre>
$ ./configure <i>--help</i></pre>
$ ./configure <i>--help</i></pre>
<p>
When you have determined which options you want to use (if any),
@ -49,16 +48,16 @@ $ ./configure <i>--help</i></pre>
</p>
<pre>
$ ./configure <i>[possible options]</i>
$ make
$ <b>sudo</b> <i>make install</i></pre>
$ ./configure <i>[possible options]</i>
$ make
$ <b>sudo</b> <i>make install</i></pre>
<p>
At this point you <b>may</b> have to run ldconfig or a similar utility
to update your list of installed shared libs.
</p>
<h2><a id="building">Building from a GIT checkout</a></h2>
<h2><a name="building">Building from a GIT checkout</a></h2>
<p>
The libvirt build process uses GNU autotools, so after obtaining a
@ -91,7 +90,7 @@ $ <b>sudo</b> <i>make install</i></pre>
drive or manual download, and run this any time libvirt.git
updates the commit stored in the .gnulib submodule:</p>
<pre>
$ GNULIB_SRCDIR=/path/to/gnulib ./autogen.sh --no-git
$ GNULIB_SRCDIR=/path/to/gnulib ./autogen.sh --no-git
</pre>
<p>To build &amp; install libvirt to your home
@ -99,9 +98,9 @@ $ GNULIB_SRCDIR=/path/to/gnulib ./autogen.sh --no-git
</p>
<pre>
$ ./autogen.sh --prefix=$HOME/usr
$ make
$ <b>sudo</b> make install</pre>
$ ./autogen.sh --prefix=$HOME/usr
$ make
$ <b>sudo</b> make install</pre>
<p>
Be aware though, that binaries built with a custom prefix will not
@ -111,8 +110,8 @@ $ <b>sudo</b> make install</pre>
</p>
<pre>
$ ./autogen.sh --system
$ make
$ ./autogen.sh --system
$ make
</pre>
<p>
@ -123,9 +122,9 @@ $ make
</p>
<pre>
$ su -
# service libvirtd stop (or systemctl stop libvirtd.service)
# /home/to/your/checkout/src/libvirtd
$ su -
# service libvirtd stop (or systemctl stop libvirtd.service)
# /home/to/your/checkout/daemon/libvirtd
</pre>
<p>
@ -134,7 +133,7 @@ $ su -
</p>
<pre>
$ ./run ./tools/virsh ....
$ ./run ./tools/virsh ....
</pre>
</body>
</html>

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