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

Compare commits

..

40 Commits

Author SHA1 Message Date
Cole Robinson
1a06da1fa2 Prep for release 1.2.9.1 2014-11-15 18:44:37 -05:00
Jiri Denemark
c2dd9c69fc qemu: Don't try to parse -help for new QEMU
Since QEMU 1.2.0, we switched to QMP probing instead of parsing -help
(and other commands, such as -cpu ?) output. However, if QMP probing
failed, we still tried starting QEMU with various options and parsing
the output, which was guaranteed to fail because the output changed.
Let's just refuse parsing -help for QEMU >= 1.2.0.

https://bugzilla.redhat.com/show_bug.cgi?id=1160318
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
(cherry picked from commit ae3e29e6e7)

Conflicts:
	tests/qemuhelptest.c
2014-11-15 16:02:10 -05:00
Jiri Denemark
6cdd9a76a5 qemu: Always set migration capabilities
We used to set migration capabilities only when a user asked for them in
flags. This is fine when migration succeeds since the QEMU process is
killed in the end but in case migration fails or if it's cancelled, some
capabilities may remain turned on with no way to turn them off. To fix
that, migration capabilities have to be turned on if requested but
explicitly turned off in case they were not requested but QEMU supports
them.

https://bugzilla.redhat.com/show_bug.cgi?id=1163953
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
(cherry picked from commit ab393383c8)
2014-11-15 16:02:10 -05:00
Pavel Hrdina
26a87687c7 nwfilter: fix deadlock caused updating network device and nwfilter
Commit 6e5c79a1 tried to fix deadlock between nwfilter{Define,Undefine}
and starting of guest, but this same deadlock exists for
updating/attaching network device to domain.

The deadlock was introduced by removing global QEMU driver lock because
nwfilter was counting on this lock and ensure that all driver locks are
locked inside of nwfilter{Define,Undefine}.

This patch extends usage of virNWFilterReadLockFilterUpdates to prevent
the deadlock for all possible paths in QEMU driver. LXC and UML drivers
still have global lock.

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

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit 41127244fb)
2014-11-15 16:02:10 -05:00
Michal Privoznik
c9ab47ad44 qemuPrepareNVRAM: Save domain conf only if domain's persistent
In one of my previous patches (3a3c3780b) I've tried to fix the
problem of nvram path disappearing on a domain that's been
started and shut down again. I fixed this by explicitly saving
domain's config file.  However, I did a bit of clumsy without
realizing we have a transient domains for which we don't save the
config file. Hence, any domain using UEFI became persistent.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 54ddc08ddb)
2014-11-15 16:02:09 -05:00
Ján Tomko
40f8708e9a Do not crash on gluster snapshots with no host name
virStorageFileBackendGlusterInit did not check nhosts.

https://bugzilla.redhat.com/show_bug.cgi?id=1162974
(cherry picked from commit b66288faab)
2014-11-15 16:02:09 -05:00
Ján Tomko
1aeac2af00 Display nicer error message for unsupported chardev hotplug
Use the device type name if we know it instead of its number,
even if we can't hotplug it:
qemuMonitorJSONAttachCharDevCommand:6094 : operation failed: Unsupported
char device type '10'

(cherry picked from commit cce8e5f739)
2014-11-15 16:02:09 -05:00
Ján Tomko
35b06cebd4 Fix virDomainChrEquals for spicevmc
virDomainChrSourceDefIsEqual should return 'true' for
identical SPICEVMC chardevs, and those that have no source
specification.

After this change, a failed hotplug no longer leaves a stale
pointer in the domain definition.

https://bugzilla.redhat.com/show_bug.cgi?id=1162097
(cherry picked from commit b987684ff6)
2014-11-15 16:02:09 -05:00
Michal Privoznik
d937f1f939 qemu: Update fsfreeze status on domain state transitions
https://bugzilla.redhat.com/show_bug.cgi?id=1160084

As of b6d4dad1 (1.2.5) libvirt keeps track if domain disks have been
frozen. However, this falls into that set of information which don't
survive domain restart. Therefore, we need to clear the flag upon some
state transitions. Moreover, once we clear the flag we must update the
status file too.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 6ea54769ba)
2014-11-15 16:02:08 -05:00
Luyao Huang
6d25ed4895 network: fix call virNetworkEventLifecycleNew when networkStartNetwork fail
When start a network fail, libvirt still call virNetworkEventLifecycleNew
to send a event.

Signed-off-by: Luyao Huang <lhuang@redhat.com>
(cherry picked from commit 45d9ea5cdd)
2014-11-15 16:02:08 -05:00
Ján Tomko
d54460f2eb Require at least one console for LXC domain
A domain without a console quietly dies soon after start,
because we try to set /dev/null as a controlling TTY
2014-10-30 15:10:59.705+0000: 1: error : lxcContainerSetupFDs:283 :
ioctl(TIOCSCTTY) failed: Inappropriate ioctl for device

Report an error early instead of trying to start it.

https://bugzilla.redhat.com/show_bug.cgi?id=1155410
(cherry picked from commit 44686f6523)
2014-11-15 16:02:08 -05:00
Ján Tomko
bc43f8cbfe Do not probe for power mgmt capabilities in lxc emulator
It fails after 30 seconds with this error:
error : virDBusCall:1429 : error from service: CanSuspend:
Did not receive a reply. Possible causes include: the remote
application did not send a reply, the message bus security
policy blocked the reply, the reply timeout expired, or the
network connection was broken.

Only probe for the power mgmt capabilities when driver is non-NULL.
This speeds up domain startup by 30 seconds.

https://bugzilla.redhat.com/show_bug.cgi?id=1159227
(cherry picked from commit 7ead1a5d91)
2014-11-15 16:02:08 -05:00
Martin Kletzander
d2cebf0b05 util: fix releasing pidfile in cleanup
Coverity found out the very obvious problem in the code.  That is that
virPidFileReleasePath() was called only if
virPidFileAcquirePath() returned 0.  But virPidFileAcquirePath() doesn't
return only 0 on success, but the FD that needs to be closed.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
(cherry picked from commit 3f43bb8326)
2014-11-15 16:02:07 -05:00
Weiwei Li
dbc11c4f97 qemu: stop NBD server after successful migration
In qemuMigrationFinish mig->nbd can not be initialized by
qemuMigrationEatCookie without the QEMU_MIGRATION_COOKIE_NBD flag.
That causes qemuMigrationStopNBDServer to return early without
stopping the NBD server properly.

Signed-off-by: Weiwei Li <nuonuoli@tencent.com>
Signed-off-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit c3012a023f)
2014-11-15 16:02:07 -05:00
Martin Kletzander
963d0bb5e6 qemu: make sure capability probing process can start
When daemon is killed right in the middle of probing a qemu binary for
its capabilities, the qemu process is left running.  Next time the
daemon is starting, it cannot start the probing qemu process because the
one that's already running does have the pidfile flock()'d.

Reported-by: Wang Yufei <james.wangyufei@huawei.com>

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
(cherry picked from commit 0ed1b55b20)
2014-11-15 16:02:07 -05:00
Martin Kletzander
595a1c8836 util: Introduce virPidFileForceCleanupPath
This function is used to cleanup a pidfile doing whatever it takes, even
killing the owning process.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
(cherry picked from commit d1fd086eb4)
2014-11-15 16:02:07 -05:00
Martin Kletzander
08182c7fd8 qemu: make advice from numad available when building commandline
Particularly in qemuBuildNumaArgStr(), there was a need for the advice
due to memory backing, which needs to know the nodeset it will be pinned
to.  With newer qemu this caused the following error when starting
domain:

  error: internal error: Advice from numad is needed in case of
  automatic numa placement

even when starting perfectly valid domain, e.g.:

  ...
  <vcpu placement='auto'>4</vcpu>
  <numatune>
    <memory mode='strict' placement='auto'/>
  </numatune>
  <cpu>
    <numa>
      <cell id='0' cpus='0' memory='524288'/>
      <cell id='1' cpus='1' memory='524288'/>
    </numa>
  </cpu>
  ...

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

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
(cherry picked from commit 11a48758a7)
2014-11-15 16:02:06 -05:00
weiwei li
65599f2777 qemu: Release nbd port from migrationPorts instead of remotePorts
commit 3e1e16aa8d (Use a port from the
migration range for NBD as well) changed ndb port allocation from
remotePorts to migrationPorts, but did not change the port releasing
process, which makes an error when migrating several times (above 64):
error: internal error: Unable to find an unused port in range
'migration' (49152-49215)

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

Signed-off-by: Weiwei Li <nuonuoli@tencent.com>
Signed-off-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit be598c5ff8)
2014-11-15 16:02:06 -05:00
Eric Blake
ecfdfb15cc qemu: better error message when block job can't succeed
https://bugzilla.redhat.com/show_bug.cgi?id=1140981 reports that
the qemu-kvm shipped as part of RHEL 7.0 intentionally[1] cripples
block jobs by removing the 'block-stream' QMP command, while still
leaving 'block-job-cancel' as an unusable no-op.  Meanwhile, we
already had existing code that checked whether block jobs were
completely missing (such as qemu 0.15), old style (cancel is
synchronous, and all commands spelled with '_'), or new style
(cancel is asynchronous, and all commands spelled with '-'), and
used that three-way probe to give decent error messages.  At the
time that code was added, all existing qemu versions fell in one
of three buckets, and the code was using the presence of
'block-job-cancel' as the witness of which of the three buckets.
But now that RHEL qemu has shipped with intentionally crippled
'block-stream', we have a fourth bucket, which results in ugly
error messages when trying 'virsh blockpull':

 error: Requested operation is not valid: Command 'block-stream' is not found

In reality, the fourth bucket should be treated the same as the
first bucket (no block job support); we can do that by realizing
that no existing build of qemu has working block-stream while
lacking block-job-cancel, so it is easiest to change our witness
to the command that starts a job rather than ends one.  We still
act correctly regarding command spelling and whether cancel is
asynchronous.  And on crippled RHEL builds, we now get the desired:

 error: unsupported configuration: block jobs not supported with this qemu binary

[1] The intentional cripple is limited to qemu-kvm of RHEL; when using
qemu-kvm-rhev of RHEV, block job functionality is supported.  Don't ask
me to explain the "why" behind it all - I'm just dealing with fallout
from someone else's decision.

* src/qemu/qemu_capabilities.h (QEMU_CAPS_BLOCKJOB_SYNC): Tweak comment.
* src/qemu/qemu_capabilities.c (virQEMUCapsCommands): Look for stream
rather than cancel when determining the flavor of block jobs supported.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 00331bfbc9)
2014-11-15 16:02:06 -05:00
Peter Krempa
28a3732d87 test: Add test to verify helpers used for backing file name parsing
Add two test cases to verify that the helpers split and parse the
backing store components properly.

(cherry picked from commit 95a5683592)
2014-11-15 16:02:06 -05:00
Peter Krempa
b8bf1188eb storage: Fix crash when parsing backing store URI with schema
The code that parses the schema from the URI touches the "hosts[0]"
member of the storage file source structure in case the URI contains a
schema. The hosts array was not yet allocated at the point in the code
where the transport protocol was parsed and set. This lead to a crash of
libvirtd.

Fix the code by allocating the "hosts" array upfront and add a test case
to verify this scenario. (Unfortunately this requires shuffling the test
case numbers too).

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1156288
(cherry picked from commit 98784369fd)
2014-11-15 16:02:05 -05:00
Jincheng Miao
052432765d remote: fix jump depends on uninitialised value
Currently remote driver only initializes partial fields of
remote_connect_get_all_domain_stats_args. But xdr_array()
will check the uninitialised field 'doms_val'.
For safty reason, memset all fields of args is better.

Fix the following error from valgrind, like:
==30515== 1 errors in context 1 of 3:
==30515== Conditional jump or move depends on uninitialised value(s)
==30515==    at 0x85E9402: xdr_array (xdr_array.c:88)
==30515==    by 0x4FD8FC9: xdr_remote_connect_get_all_domain_stats_args (remote_protocol.c:6473)
==30515==    by 0x4FE72F2: virNetMessageEncodePayload (virnetmessage.c:350)
==30515==    by 0x4FDD21C: virNetClientProgramCall (virnetclientprogram.c:326)
==30515==    by 0x4FB4D01: callFull.isra.2 (remote_driver.c:6667)
==30515==    by 0x4FCBD45: call (remote_driver.c:6689)
==30515==    by 0x4FCBD45: remoteConnectGetAllDomainStats (remote_driver.c:7793)
==30515==    by 0x4FA0E75: virConnectGetAllDomainStats (libvirt.c:21678)
==30515==    by 0x147FD1: cmdDomstats (virsh-domain-monitor.c:2148)
==30515==    by 0x13006B: vshCommandRun (virsh.c:1915)
==30515==    by 0x12A9E1: main (virsh.c:3699)

Signed-off-by: Jincheng Miao <jmiao@redhat.com>
(cherry picked from commit 28b7601dc7)
2014-11-15 16:02:05 -05:00
Michal Privoznik
b6366531a5 qemu_agent: Produce more readable error messages
Not every error message from qemu-ga has to have the 'class' field
filled out. For instance, I've seen this error message lately:

  qemuAgentCheckError:1047 : unable to execute QEMU agent command \
  {"execute":"guest-set-time"}: \
  {"error":{"desc":"Invalid parameter type, expected: integer"}}

However, this got translated into rather generic error message:

  internal error: unable to execute QEMU agent command
  'guest-set-time': unknown QEMU command error

So we've dropped better error message in favor of a generic one.
This is due to our code which expects 'class' which is not
present here.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit b7fe5a6555)
2014-11-15 16:02:05 -05:00
Eric Blake
3b4b9aee83 qemu: forbid snapshot-delete --children-only on external snapshot
https://bugzilla.redhat.com/show_bug.cgi?id=956506 documents that
given a domain where an internal snapshot parent has an external
snapshot child, we lacked a safety check when trying to use the
--children-only option to snapshot-delete:

$ virsh start dom
$ virsh snapshot-create-as dom internal
$ virsh snapshot-create-as dom external --disk-only
$ virsh snapshot-delete dom external
error: Failed to delete snapshot external
error: unsupported configuration: deletion of 1 external disk snapshots not supported yet
$ virsh snapshot-delete dom internal --children
error: Failed to delete snapshot internal
error: unsupported configuration: deletion of 1 external disk snapshots not supported yet
$ virsh snapshot-delete dom internal --children-only
Domain snapshot internal children deleted

While I'd still like to see patches that actually do proper external
snapshot deletion, we should at least fix the inconsistency in the
meantime.  With this patch:

$ virsh snapshot-delete dom internal --children-only
error: Failed to delete snapshot internal
error: unsupported configuration: deletion of 1 external disk snapshots not supported yet

* src/qemu/qemu_driver.c (qemuDomainSnapshotDelete): Fix condition.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 2086a9905a)
2014-11-15 16:02:05 -05:00
Julio Faracco
0940208b52 tests: Add SELINUX_LIBS to fix viridentitytest linker bug
In a clean build system (Ubuntu 14.04), the viridentitytest failed to compile.
Even if all the SELINUX libraries and depedencies are installed. See the error
message below:

[...]
  CC       viridentitytest.o
  CCLD     viridentitytest
/usr/bin/ld: viridentitytest.o: undefined reference to symbol
                                                       'security_disable'
//lib/x86_64-linux-gnu/libselinux.so.1: error adding symbols: DSO missing
                                                           from command line
collect2: error: ld returned 1 exit status
make: *** [viridentitytest] Error 1

Simply adding the variable SELINUX_LIBS in viridentitytest rules of
Makefile.am to include SELINUX libraries into viridentitytest solved that
compilation issue.

Signed-off-by: Julio Faracco <jcfaracco@gmail.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit f2a2d0e9ab)
2014-11-15 16:02:04 -05:00
Peter Krempa
a70d93e226 qemu: migration: Make check for empty hook XML robust
Also consider whitespace only strings returned from the hook as empty
result.

(cherry picked from commit 19b1ee42b4)
2014-11-15 16:02:04 -05:00
Peter Krempa
3d52d5e6d5 qemu: restore: Fix restoring of VM when the restore hook returns empty XML
The documentation for the restore hook states that returning an empty
XML is equivalent with copying the input. There was a bug in the code
checking the returned string by checking the string instead of the
contents. Use the new helper to check if the string is empty.

(cherry picked from commit e386779937)
2014-11-15 16:02:04 -05:00
Peter Krempa
1bcf7e10ab util: string: Add helper to check whether string is empty
The helper checks whether a string contains only whitespace or is NULL.
This will be helpful to skip cases where a user string is optional, but
may be provided empty with the same meaning.

(cherry picked from commit 0eeafeedeb)
2014-11-15 16:02:04 -05:00
Peter Krempa
5d02a123ab virsh: domain: Use global constant for XML file size limit
Few places still used hardcoded limit for maximum XML size for commands
that accept XML files. The hardcoded limits ranged from 8k to 1M. Use
VSH_MAX_XML_FILE to express this limit in a unified way. This will bump
the limit for the commands that used hardcoded string lengths to 10M.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1152427
(cherry picked from commit 4d1852c485)
2014-11-15 15:27:50 -05:00
John Ferlan
e1a3efdac7 qemu: Fix hot unplug of SCSI_HOST device
https://bugzilla.redhat.com/show_bug.cgi?id=1141732

Introduced by commit id '8f76ad99' the logic to detach a scsi_host
device (SCSI or iSCSI) fails when attempting to remove the 'drive'
because as I found in my investigation - the DelDevice takes care of
that for us.

The investigation turned up commits to adjust the logic for the
qemuMonitorDelDevice and qemuMonitorDriveDel processing for interfaces
(commit id '81f76598'), disk bus=VIRTIO,SCSI,USB (commit id '0635785b'),
and chr devices (commit id '55b21f9b'), but nothing with the host devices.

This commit uses the model for the previous set of changes and applies
it to the hostdev path. The call to qemuDomainDetachHostSCSIDevice will
return to qemuDomainDetachThisHostDevice handling either the audit of
the failure or the wait for the removal and then call into
qemuDomainRemoveHostDevice for the event, removal from the domain hostdev
list, and audit of the removal similar to other paths.

NOTE: For now the 'conn' param to +qemuDomainDetachHostSCSIDevice is left
as ATTRIBUTE_UNUSED.  Removing requires a cascade of other changes to be
left for a future patch.

(cherry picked from commit d2774e54cd)
2014-11-15 15:26:20 -05:00
Martin Kletzander
86d26c425d qemu: unref cfg after TerminateMachine has been called
Commit 4882618ed1 added the code that
requests driver cfg, but forgot to unref it.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
(cherry picked from commit 9661ac2f46)
2014-11-15 15:25:02 -05:00
Ján Tomko
a91a960f0e Add virCgroupTerminateMachine stub
Fix the build on FreeBSD, broken by commit 4882618.

Signed-off-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit 99b2b4571d)
2014-11-15 15:24:32 -05:00
Guido Günther
870ea74ed5 qemu: use systemd's TerminateMachine to kill all processes
If we don't properly clean up all processes in the
machine-<vmname>.scope systemd won't remove the cgroup and subsequent vm
starts fail with

  'CreateMachine: File exists'

Additional processes can e.g. be added via

  echo $PID > /sys/fs/cgroup/systemd/machine.slice/machine-${VMNAME}.scope/tasks

but there are other cases like

  http://bugs.debian.org/761521

Invoke TerminateMachine to be on the safe side since systemd tracks the
cgroup anyway. This is a noop if all processes have terminated already.

(cherry picked from commit 4882618ed1)
2014-11-15 15:24:11 -05:00
Martin Kletzander
3d021408c5 util: Prepare URI formatting for libxml2 >= 2.9.2
Since commit 8eb55d782a2b9afacc7938694891cc6fad7b42a5 libxml2 removes
two slashes from the URI when there is no server part.  This is fixed
with beb7281055dbf0ed4d041022a67c6c5cfd126f25, but only if the calling
application calls xmlSaveUri() on URI that xmlURIParse() parsed.  And
that is not the case in virURIFormat().  virURIFormat() accepts
virURIPtr that can be created without parsing it and we do that when we
format network storage paths for gluster for example.  Even though
virStorageSourceParseBackingURI() uses virURIParse(), it throws that data
structure right away.

Since we want to format URIs as URIs and not absolute URIs or opaque
URIs (see RFC 3986), we can specify that with a special hack thanks to
commit beb7281055dbf0ed4d041022a67c6c5cfd126f25, by setting port to -1.

This fixes qemuxml2argvtest test where the disk-drive-network-gluster
case was failing.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
(cherry picked from commit 8f17d0eaae)
2014-11-15 15:20:42 -05:00
Michal Privoznik
d72e79ed27 security_selinux: Don't relabel /dev/net/tun
https://bugzilla.redhat.com/show_bug.cgi?id=1147057

The code for relabelling the TAP FD is there due to a race. When
libvirt creates a /dev/tapN device it's labeled as
'system_u:object_r:device_t:s0' by default. Later, when
udev/systemd reacts to this device, it's relabelled to the
expected label 'system_u:object_r:tun_tap_device_t:s0'. Hence, we
have a code that relabels the device, to cut the race down. For
more info see ae368ebfcc.

But the problem is, the relabel function is called on all TUN/TAP
devices. Yes, on /dev/net/tun too. This is however a special kind
of device - other processes uses it too. We shouldn't touch it's
label then.

Ideally, there would an API in SELinux that would label just the
passed FD and not the underlying path. That way, we wouldn't need
to care as we would be not labeling /dev/net/tun but the FD
passed to the domain. Unfortunately, there's no such API so we
have to workaround until then.

Tested-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit ebc0526396)
2014-11-15 15:20:42 -05:00
Laine Stump
7caed3d4c5 util: eliminate "use after free" in callers of virNetDevLinkDump
virNetDevLinkDump() gets a message from netlink into "resp", then
calls nlmsg_parse() to fill the table "tb" with pointers into resp. It
then returns tb to its caller, but not before freeing the buffer at
resp. That means that all the callers of virNetDevLinkDump() are
examining memory that has already been freed. This can be verified by
filling the buffer at resp with garbage prior to freeing it (or, I
suppose, just running libvirtd under valgrind) then performing some
operation that calls virNetDevLinkDump().

The upstream commit log incorrectly states that the code has been like
this ever since virNetDevLinkDump() was written. In reality, the
problem was introduced with commit e95de74d, first in libvirt-1.0.5,
which was attempting to eliminate a typecast that caused compiler
warnings. It has only been pure luck (or maybe a lack of heavy load,
and/or maybe an allocation algorithm in malloc() that delays re-use of
just-freed memory) that has kept this from causing errors, for example
when configuring a PCI passthrough or macvtap passthrough network
interface.

The solution taken in this patch is the simplest - just return resp to
the caller along with tb, then have the caller free it after they are
finished using the data (pointers) in tb. I alternately could have
made a cleaner interface by creating a new struct that put tb and resp
together along with a vir*Free() function for it, but this function is
only used in a couple places, and I'm not sure there will be
additional new uses of virNetDevLinkDump(), so the value of adding a
new type, extra APIs, etc. is dubious.

(cherry picked from commit f9f9699f40)
2014-11-12 13:54:23 -05:00
Eric Blake
744ddb15e0 CVE-2014-7823: dumpxml: security hole with migratable flag
Commit 28f8dfd (v1.0.0) introduced a security hole: in at least
the qemu implementation of virDomainGetXMLDesc, the use of the
flag VIR_DOMAIN_XML_MIGRATABLE (which is usable from a read-only
connection) triggers the implicit use of VIR_DOMAIN_XML_SECURE
prior to calling qemuDomainFormatXML.  However, the use of
VIR_DOMAIN_XML_SECURE is supposed to be restricted to read-write
clients only.  This patch treats the migratable flag as requiring
the same permissions, rather than analyzing what might break if
migratable xml no longer includes secret information.

Fortunately, the information leak is low-risk: all that is gated
by the VIR_DOMAIN_XML_SECURE flag is the VNC connection password;
but VNC passwords are already weak (FIPS forbids their use, and
on a non-FIPS machine, anyone stupid enough to trust a max-8-byte
password sent in plaintext over the network deserves what they
get).  SPICE offers better security than VNC, and all other
secrets are properly protected by use of virSecret associations
rather than direct output in domain XML.

* src/remote/remote_protocol.x (REMOTE_PROC_DOMAIN_GET_XML_DESC):
Tighten rules on use of migratable flag.
* src/libvirt-domain.c (virDomainGetXMLDesc): Likewise.

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

Conflicts:
	src/libvirt-domain.c - file split from older src/libvirt.c
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-11-06 17:19:49 +01:00
Lubomir Rintel
cd1b72fdd8 qemu: x86_64 is good enough for i686
virt-manager on Fedora sets up i686 hosts with "/usr/bin/qemu-kvm" emulator,
which in turn unconditionally execs qemu-system-x86_64 querying capabilities
then fails:

Error launching details: invalid argument: architecture from emulator 'x86_64' doesn't match given architecture 'i686'

Traceback (most recent call last):
  File "/usr/share/virt-manager/virtManager/engine.py", line 748, in _show_vm_helper
    details = self._get_details_dialog(uri, vm.get_connkey())
  File "/usr/share/virt-manager/virtManager/engine.py", line 726, in _get_details_dialog
    obj = vmmDetails(conn.get_vm(connkey))
  File "/usr/share/virt-manager/virtManager/details.py", line 399, in __init__
    self.init_details()
  File "/usr/share/virt-manager/virtManager/details.py", line 784, in init_details
    domcaps = self.vm.get_domain_capabilities()
  File "/usr/share/virt-manager/virtManager/domain.py", line 518, in get_domain_capabilities
    self.get_xmlobj().os.machine, self.get_xmlobj().type)
  File "/usr/lib/python2.7/site-packages/libvirt.py", line 3492, in getDomainCapabilities
    if ret is None: raise libvirtError ('virConnectGetDomainCapabilities() failed', conn=self)
libvirtError: invalid argument: architecture from emulator 'x86_64' doesn't match given architecture 'i686'

Journal:

Oct 16 21:08:26 goatlord.localdomain libvirtd[1530]: invalid argument: architecture from emulator 'x86_64' doesn't match given architecture 'i686'

(cherry picked from commit afe8f4200f)
2014-10-30 10:17:13 -04:00
Cole Robinson
e9bf19a4b2 qemu: Don't compare CPU against host for TCG
Right now when building the qemu command line, we try to do various
unconditional validations of the guest CPU against the host CPU. However
this checks are overly applied. The only time we should use the checks
are:

- The user requests host-model/host-passthrough, or

- When KVM is requsted. CPU features requested in TCG mode are always
  emulated by qemu and are independent of the host CPU, so no host CPU
  checks should be performed.

Right now if trying to specify a CPU for arm on an x86 host, it attempts
to do non-sensical validation and falls over.

Switch all the test cases that were intending to test CPU validation to
use KVM, so they continue to test the intended code.

Amend some aarch64 XML tests with a CPU model, to ensure things work
correctly.

(cherry picked from commit cf7fce8f2fd1c930f357fd4ff93ac35f38eb30c6)
2014-10-30 10:15:53 -04:00
Cole Robinson
74e27d1c0e qemu_command: Split qemuBuildCpuArgStr
Move the CPU mode/model handling to its own function. This is just
code movement and re-indentation.

(cherry picked from commit e1d872dc77c80d43036f928f83f560f2e9286148)
2014-10-30 10:15:48 -04:00
11437 changed files with 3351206 additions and 2061876 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

1
.ctags
View File

@@ -3,4 +3,3 @@
--exclude=*.html
--exclude=*.html.in
--langmap=c:+.h.in
--c-kinds=+p

View File

@@ -1 +0,0 @@
../.ctags

View File

@@ -1,21 +0,0 @@
# EditorConfig is a file format and collection of text editor plugins
# for maintaining consistent coding styles between different editors
# and IDEs. Most popular editors support this either natively or via
# plugin.
#
# Check https://editorconfig.org for details.
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
[*.c]
indent_style = space
indent_size = 4
[*.{rng,xml}]
indent_style = space
indent_size = 2

211
.gitignore vendored
View File

@@ -1,44 +1,195 @@
# vim related ignores
*.swp
.lvimrc
# emacs related ignores
*#*#
*.#*#
.#*
# autotools related ignores
!/m4/virt-*.m4
*.a
*.cov
*.exe
*.exe.manifest
*.gcda
*.gcno
*.gcov
*.html
*.i
*.la
*.lo
*.loT
*.o
*.orig
*.pem
*.pyc
*.rej
*.s
*~
.#*
.deps
.dirstamp
.gdb_history
.git
.git-module-status
.libs
.lvimrc
.memdump
.sc-start-sc_*
/ABOUT-NLS
/AUTHORS
/ChangeLog
/GNUmakefile
/INSTALL
/NEWS
/aclocal.m4
/autom4te.cache
/build-aux/.gitignore
/build-aux/compile
/build-aux/depcomp
/build-aux/missing
/build-aux/test-driver
/build-aux
/build-aux/
/build/
/config.cache
/config.guess
/config.h
/config.h.in
/config.log
/config.rpath
/config.status
/config.sub
/configure
/m4/*
Makefile.in
# gnulib related ignores
!/gnulib/lib/Makefile.am
!/gnulib/tests/Makefile.am
*.rej
*~
/configure.lineno
/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/libvirtd.socket
/daemon/test_libvirtd.aug
/docs/aclperms.htmlinc
/docs/apibuild.py.stamp
/docs/devhelp/libvirt.devhelp
/docs/hvsupport.html.in
/docs/libvirt-api.xml
/docs/libvirt-lxc-*.xml
/docs/libvirt-qemu-*.xml
/docs/libvirt-refs.xml
/docs/search.php
/docs/todo.html.in
/examples/object-events/event-test
/examples/dominfo/info1
/examples/domsuspend/suspend
/examples/dommigrate/dommigrate
/examples/domtop/domtop
/examples/hellolibvirt/hellolibvirt
/examples/openauth/openauth
/gnulib/lib/*
/gnulib/m4/*
/gnulib/tests/*
# git related ignores
*.orig
.git-module-status
# libvirt related ignores
/build/
/ci/scratch/
/include/libvirt/libvirt.h
/libtool
/libvirt-*.tar.gz
/libvirt-[0-9]*
/libvirt*.pc
/libvirt.spec
/ltconfig
/ltmain.sh
/m4/*
/maint.mk
/mingw-libvirt.spec
/mkinstalldirs
/po/*
/proxy/
/python/
/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/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_*.stp
/src/libvirt_*helper
/src/libvirt_*probes.h
/src/libvirt_lxc
/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/lxc/lxc_controller_dispatch.h
/src/lxc/lxc_monitor_dispatch.h
/src/lxc/lxc_monitor_protocol.c
/src/lxc/lxc_monitor_protocol.h
/src/lxc/lxc_protocol.[ch]
/src/lxc/test_libvirtd_lxc.aug
/src/qemu/test_libvirtd_qemu.aug
/src/remote/*_client_bodies.h
/src/remote/*_protocol.[ch]
/src/rpc/virkeepaliveprotocol.[ch]
/src/rpc/virnetprotocol.[ch]
/src/test_libvirt*.aug
/src/test_virtlockd.aug
/src/util/virkeymaps.h
/src/virt-aa-helper
/src/virtlockd
/src/virtlockd.8
/src/virtlockd.8.in
/src/virtlockd.init
/tests/*.log
/tests/*.pid
/tests/*.trs
/tests/commandhelper
/tests/*test
!/tests/*schematest
!/tests/virt-aa-helper-test
/tests/objectlocking
/tests/objectlocking-files.txt
/tests/objectlocking.cm[ix]
/tests/reconnect
/tests/ssh
/tests/test_conf
/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-*-validate
/tools/virt-sanlock-cleanup
/tools/wireshark/src/plugin.c
/tools/wireshark/src/libvirt
/update.log
GPATH
GRTAGS
GTAGS
Makefile
Makefile.in
TAGS
coverage
cscope.files
cscope.in.out
cscope.out
cscope.po.out
results.log
stamp-h
stamp-h.in
stamp-h1
tags
!/gnulib/lib/Makefile.am
!/gnulib/tests/Makefile.am
!/m4/virt-*.m4
!/po/*.po
!/po/POTFILES.in
!/po/libvirt.pot

View File

@@ -1,46 +0,0 @@
.job_template: &job_definition
script:
- mkdir build
- cd build
- ../autogen.sh $CONFIGURE_OPTS || (cat config.log && exit 1)
- make -j $(getconf _NPROCESSORS_ONLN)
# We could run every arch on every versions, but it is a little
# overkill. Instead we split jobs evenly across 9, 10 and sid
# to achieve reasonable cross-coverage.
debian-9-cross-armv6l:
<<: *job_definition
image: quay.io/libvirt/buildenv-libvirt-debian-9-cross-armv6l:latest
debian-9-cross-mips64el:
<<: *job_definition
image: quay.io/libvirt/buildenv-libvirt-debian-9-cross-mips64el:latest
debian-9-cross-mips:
<<: *job_definition
image: quay.io/libvirt/buildenv-libvirt-debian-9-cross-mips:latest
debian-10-cross-aarch64:
<<: *job_definition
image: quay.io/libvirt/buildenv-libvirt-debian-10-cross-aarch64:latest
debian-10-cross-ppc64le:
<<: *job_definition
image: quay.io/libvirt/buildenv-libvirt-debian-10-cross-ppc64le:latest
debian-10-cross-s390x:
<<: *job_definition
image: quay.io/libvirt/buildenv-libvirt-debian-10-cross-s390x:latest
debian-sid-cross-armv7l:
<<: *job_definition
image: quay.io/libvirt/buildenv-libvirt-debian-sid-cross-armv7l:latest
debian-sid-cross-i686:
<<: *job_definition
image: quay.io/libvirt/buildenv-libvirt-debian-sid-cross-i686:latest
debian-sid-cross-mipsel:
<<: *job_definition
image: quay.io/libvirt/buildenv-libvirt-debian-sid-cross-mipsel:latest

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: 7d06937892...9565c3be73

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,15 +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>
<intrigeri@boum.org> <intrigeri+libvirt@boum.org>
<fidencio@redhat.com> <fabiano@fidencio.org>
<shi_lei@massclouds.com> <shilei.massclouds@gmx.com>
<adrian.brzezinski@eo.pl> <redhat@adrb.pl>
# Name consolidation:
# Preferred author spelling <preferred email>
@@ -64,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,118 +0,0 @@
sudo: required
language: generic
branches:
except:
- /^.*-maint$/
addons:
homebrew:
update: true
packages:
- ccache
- rpcgen
- xz
- yajl
- glib
- docutils
matrix:
include:
- services:
- docker
env:
- IMAGE="ubuntu-1804"
- MAKE_ARGS="syntax-check distcheck"
script:
- make -C ci/ ci-build@$IMAGE CI_MAKE_ARGS="$MAKE_ARGS"
- services:
- docker
env:
- IMAGE="centos-7"
- MAKE_ARGS="syntax-check distcheck"
script:
- make -C ci/ ci-build@$IMAGE CI_MAKE_ARGS="$MAKE_ARGS"
- services:
- docker
env:
- IMAGE="debian-9"
- MAKE_ARGS="syntax-check distcheck"
script:
- make -C ci/ ci-build@$IMAGE CI_MAKE_ARGS="$MAKE_ARGS"
- services:
- docker
env:
- IMAGE="fedora-31"
- MAKE_ARGS="syntax-check distcheck"
script:
- make -C ci/ ci-build@$IMAGE CI_MAKE_ARGS="$MAKE_ARGS"
- services:
- docker
env:
- IMAGE="fedora-rawhide"
- MAKE_ARGS="syntax-check distcheck"
script:
- make -C ci/ ci-build@$IMAGE CI_MAKE_ARGS="$MAKE_ARGS"
- services:
- docker
env:
- IMAGE="fedora-30"
- MINGW="mingw32"
script:
- make -C ci/ ci-build@$IMAGE CI_CONFIGURE="$MINGW-configure"
- services:
- docker
env:
- IMAGE="fedora-30"
- MINGW="mingw64"
script:
- make -C ci/ ci-build@$IMAGE CI_CONFIGURE="$MINGW-configure"
- compiler: clang
language: c
os: osx
osx_image: xcode10.3
env:
- PATH="/usr/local/opt/gettext/bin:/usr/local/opt/ccache/libexec:/usr/local/opt/rpcgen/bin:$PATH"
- PKG_CONFIG_PATH="/usr/local/opt/libxml2/lib/pkgconfig"
before_script:
# Hack to blow away py2
- brew link --overwrite python
script:
# We can't run 'distcheck' or 'syntax-check' because they fail on
# macOS, but doing 'install' and 'dist' gives us some useful coverage
- mkdir build && cd build
- ../autogen.sh --prefix=$(pwd)/install-root && make -j3 && make -j3 install && make -j3 dist
- compiler: clang
language: c
os: osx
osx_image: xcode11.3
env:
- PATH="/usr/local/opt/gettext/bin:/usr/local/opt/ccache/libexec:/usr/local/opt/rpcgen/bin:$PATH"
- PKG_CONFIG_PATH="/usr/local/opt/libxml2/lib/pkgconfig"
before_script:
# Hack to blow away py2
- brew link --overwrite python
script:
# We can't run 'distcheck' or 'syntax-check' because they fail on
# macOS, but doing 'install' and 'dist' gives us some useful coverage
- mkdir build && cd build
- ../autogen.sh --prefix=$(pwd)/install-root && make -j3 && make -j3 install && make -j3 dist
git:
submodules: true
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,32 +8,32 @@ 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>
Anthony Liguori <aliguori@us.ibm.com>
Cédric Bosdonnat <cbosdonnat@suse.com>
Christian Ehrhardt <christian.ehrhardt@canonical.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>
Fabiano Fidêncio <fidencio@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>
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>
Osier Yang <jyang@redhat.com>
Pavel Hrdina <phrdina@redhat.com>
Peter Krempa <pkrempa@redhat.com>
Richard W.M. Jones <rjones@redhat.com>
@@ -43,19 +43,11 @@ 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:
@@ -64,6 +56,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>
@@ -92,7 +85,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

View File

@@ -55,7 +55,7 @@ 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
@@ -111,7 +111,7 @@ 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
@@ -158,7 +158,7 @@ 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
@@ -216,7 +216,7 @@ 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.
@@ -267,7 +267,7 @@ Library will still fall under Section 6.)
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
@@ -329,7 +329,7 @@ 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
@@ -370,7 +370,7 @@ 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
@@ -422,7 +422,7 @@ 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
@@ -456,7 +456,7 @@ 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

View File

@@ -1,15 +0,0 @@
libvirt ChangeLog
=================
The libvirt project doesn't include a detailed ChangeLog in its release
archives.
If you're interested in the full list of changes made to libvirt since
the project was started, you can clone the git repository from
https://libvirt.org/git/libvirt.git
and browse them locally using your favorite git history viewer or,
alternatively, browse them online at
https://libvirt.org/git/?p=libvirt.git;a=log

16699
ChangeLog-old Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,74 +0,0 @@
# Having a separate GNUmakefile lets me 'include' the dynamically
# generated rules created via cfg.mk (package-local configuration)
# as well as maint.mk (generic maintainer rules).
# This makefile is used only if you run GNU Make.
# It is necessary if you want to build targets usually of interest
# only to the maintainer.
# Copyright (C) 2001, 2003, 2006-2019 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
_build-aux ?= build-aux
_autoreconf ?= autoreconf -v
# If the user runs GNU make but has not yet run ./configure,
# give them a diagnostic.
_gl-Makefile := $(wildcard [M]akefile)
ifneq ($(_gl-Makefile),)
# Make tar archive easier to reproduce.
export TAR_OPTIONS = --owner=0 --group=0 --numeric-owner
# Allow the user to add to this in the Makefile.
ALL_RECURSIVE_TARGETS =
include Makefile
include $(srcdir)/$(_build-aux)/syntax-check.mk
else
.DEFAULT_GOAL := abort-due-to-no-makefile
srcdir = .
# The package can override .DEFAULT_GOAL to run actions like autoreconf.
include $(srcdir)/$(_build-aux)/syntax-check.mk
ifeq ($(.DEFAULT_GOAL),abort-due-to-no-makefile)
$(MAKECMDGOALS): abort-due-to-no-makefile
endif
abort-due-to-no-makefile:
@echo There seems to be no Makefile in this directory. 1>&2
@echo "You must run ./configure before running 'make'." 1>&2
@exit 1
endif
# Tell version 3.79 and up of GNU make to not build goals in this
# directory in parallel, in case someone tries to build multiple
# targets, and one of them can cause a recursive target to be invoked.
# Only set this if Automake doesn't provide it.
AM_RECURSIVE_TARGETS ?= $(RECURSIVE_TARGETS:-recursive=) \
$(RECURSIVE_CLEAN_TARGETS:-recursive=) \
dist distcheck tags ctags
ALL_RECURSIVE_TARGETS += $(AM_RECURSIVE_TARGETS)
ifneq ($(word 2, $(MAKECMDGOALS)), )
ifneq ($(filter $(ALL_RECURSIVE_TARGETS), $(MAKECMDGOALS)), )
.NOTPARALLEL:
endif
endif

985
HACKING Normal file
View File

@@ -0,0 +1,985 @@
-*- 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 installation 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.
Some tests are skipped by default in a development environment, based on the
time they take in comparison to the likelihood that those tests will turn up
problems during incremental builds. These tests default to being run when
building from a tarball or with the configure option --enable-expensive-tests;
you can also force a one-time toggle of these tests by setting
VIR_TEST_EXPENSIVE to 0 or 1 at make time, as in:
make check VIR_TEST_EXPENSIVE=1
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
When debugging failures during development, it is possible to focus in on just
the failing subtests by using TESTS and VIR_TEST_RANGE:
make check VIR_TEST_DEBUG=1 VIR_TEST_RANGE=3-5 TESTS=qemuxml2argvtest
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 acceptable 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://people.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, the project includes a file .dir-locals.el that sets up the
preferred indentation. 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,L3
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
Commas
======
Commas should always be followed by a space or end of line, and never have
leading space; this is enforced during 'make syntax-check'.
call(a,b ,c);// Bad
call(a, b, c); // Good
When declaring an enum or using a struct initializer that occupies more than
one line, use a trailing comma. That way, future edits to extend the list only
have to add a line, rather than modify an existing line to add the
intermediate comma. Any sentinel enumerator value with a name ending in _LAST
is exempt, since you would extend such an enum before the _LAST element.
Another reason to favor trailing commas is that it requires less effort to
produce via code generators. Note that the syntax checker is unable to enforce
a style of trailing commas, so there are counterexamples in existing code
which do not use it; also, while C99 allows trailing commas, remember that
JSON and XDR do not.
enum {
VALUE_ONE,
VALUE_TWO // Bad
};
enum {
VALUE_THREE,
VALUE_FOUR, // Good
};
Semicolons
==========
Semicolons should never have a space beforehand. Inside the condition of a
"for" loop, there should always be a space or line break after each semicolon,
except for the special case of an infinite loop (although more infinite loops
use "while"). While not enforced, loop counters generally use post-increment.
for (i = 0 ;i < limit ; ++i) { // Bad
for (i = 0; i < limit; i++) { // Good
for (;;) { // ok
while (1) { // Better
Empty loop bodies are better represented with curly braces and a comment,
although use of a semicolon is not currently rejected.
while ((rc = waitpid(pid, &st, 0) == -1) &&
errno == EINTR); // ok
while ((rc = waitpid(pid, &st, 0) == -1) &&
errno == EINTR) { // Better
/* nothing */
}
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;
}
Use hanging braces for compound statements: the opening brace of a compound
statement should be on the same line as the condition being tested. Only
top-level function bodies, nested scopes, and compound structure declarations
should ever have { on a line by itself.
void
foo(int a, int b)
{ // correct - function body
int 2d[][] = {
{ // correct - complex initialization
1, 2,
},
};
if (a)
{ // BAD: compound brace on its own line
do_stuff();
}
{ // correct - nested scope
int tmp;
if (a < b) { // correct - hanging brace
tmp = b;
b = a;
a = tmp;
}
}
}
Preprocessor
============
Macros defined with an ALL_CAPS name should generally be assumed to be unsafe
with regards to arguments with side-effects (that is, MAX(a++, b--) might
increment a or decrement b too many or too few times). Exceptions to this rule
are explicitly documented for macros in viralloc.h and virstring.h.
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 viralloc.h.
- To allocate a single object:
virDomainPtr domain;
if (VIR_ALLOC(domain) < 0)
return NULL;
- To allocate an array of objects:
virDomainPtr domains;
size_t ndomains = 10;
if (VIR_ALLOC_N(domains, ndomains) < 0)
return NULL;
- To allocate an array of object pointers:
virDomainPtr *domains;
size_t ndomains = 10;
if (VIR_ALLOC_N(domains, ndomains) < 0)
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)
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)
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)).
VIR_STRDUP(char *dst, const char *src);
VIR_STRNDUP(char *dst, const char *src, size_t n);
You should avoid using strdup or strndup directly as they do not report
out-of-memory error, and do not allow a NULL source. Use VIR_STRDUP or
VIR_STRNDUP macros instead, which return 0 for NULL source, 1 for successful
copy, and -1 for allocation failure with the error already reported. In very
specific cases, when you don't want to report the out-of-memory error, you can
use VIR_STRDUP_QUIET or VIR_STRNDUP_QUIET, but such usage is very rare and
usually considered a flaw.
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 virbuffer.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 (virBufferCheckError(&buf) < 0)
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)
Top-level labels should be indented by one space (putting them on the
beginning of the line confuses function context detection in git):
int foo()
{
/* ... do stuff ... */
cleanup:
/* ... do other stuff ... */
}
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

@@ -19,104 +19,66 @@
LCOV = lcov
GENHTML = genhtml
# when building from tarball -Werror isn't auto enabled
# so force it explicitly
DISTCHECK_CONFIGURE_FLAGS = --enable-werror
SUBDIRS = . gnulib/lib include/libvirt src tools docs gnulib/tests \
tests po examples
XZ_OPT ?= -v -T0
export XZ_OPT
SUBDIRS = . gnulib/lib include src daemon tools docs gnulib/tests \
tests po examples/object-events examples/hellolibvirt \
examples/dominfo examples/domsuspend examples/apparmor \
examples/xml/nwfilter examples/openauth examples/systemtap \
tools/wireshark examples/dommigrate \
examples/lxcconvert examples/domtop
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 \
GNUmakefile \
cfg.mk \
run.in \
README.md \
AUTHORS.in \
scripts/apibuild.py \
scripts/augeas-gentest.py \
build-aux/check-spacing.pl \
scripts/check-aclperms.py \
scripts/check-aclrules.py \
scripts/check-drivername.py \
scripts/check-driverimpls.py \
scripts/check-file-access.py \
scripts/check-remote-protocol.py \
scripts/check-symfile.py \
scripts/check-symsorting.py \
scripts/dtrace2systemtap.py \
scripts/esx_vi_generator.py \
scripts/genaclperms.py \
scripts/genpolkit.py \
scripts/gensystemtap.py \
scripts/group-qemu-caps.py \
scripts/header-ifdef.py \
scripts/hvsupport.py \
scripts/hyperv_wmi_generator.py \
scripts/minimize-po.py \
scripts/mock-noinline.py \
scripts/prohibit-duplicate-header.py \
scripts/reformat-news.py \
scripts/test-wrap-argv.py \
build-aux/syntax-check.mk \
build-aux/useless-if-before-free \
build-aux/vc-list-files \
ci/Makefile \
ci/build.sh \
ci/list-images.sh \
ci/prepare.sh \
$(NULL)
$(XML_EXAMPLES)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libvirt.pc libvirt-qemu.pc libvirt-lxc.pc libvirt-admin.pc
pkgconfig_DATA = libvirt.pc libvirt-qemu.pc libvirt-lxc.pc
NEWS: \
$(srcdir)/docs/news.xml \
$(srcdir)/docs/news-ascii.xsl \
$(top_srcdir)/scripts/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; }; \
$(RUNUTF8) $(PYTHON) $(top_srcdir)/scripts/reformat-news.py $@-tmp >$@ \
|| { rm -f $@-tmp; exit 1; }; \
rm -f $@-tmp; \
fi
EXTRA_DIST += \
$(srcdir)/docs/news.xml \
$(srcdir)/docs/news-ascii.xsl \
$(NULL)
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: all
@($(MAKE) $(AM_MAKEFLAGS) -C tests check-access)
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
@@ -129,28 +91,28 @@ clean-cov:
MAINTAINERCLEANFILES = .git-module-status
distclean-local: clean-GNUmakefile
clean-GNUmakefile:
test '$(srcdir)' = . || rm -f $(top_builddir)/GNUmakefile
# disable this check
distuninstallcheck:
dist-hook: gen-AUTHORS
dist-hook: gen-ChangeLog gen-AUTHORS
# Generate the ChangeLog file (with all entries since the switch to git)
# and insert it into the directory we're about to use to create a tarball.
gen_start_date = 2009-07-04
.PHONY: gen-ChangeLog
gen-ChangeLog:
$(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
ci-%:
$(MAKE) -C $(srcdir)/ci/ $@

View File

@@ -15,9 +15,9 @@
## <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 +43,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 +72,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 +95,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 +113,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
@@ -11,7 +10,7 @@ We've opted to keep only the highest-level sources in the GIT repository.
This eases our maintenance burden, (fewer merges etc.), but imposes more
requirements on anyone wishing to build from the just-checked-out sources.
Note the requirements to build the released archive are much less and
are just the requirements of the standard configure && make procedure.
are just the requirements of the standard ./configure && make procedure.
Specific development tools and versions will be checked for and listed by
the bootstrap script.
@@ -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
@@ -34,14 +33,10 @@ reduce download time and disk space requirements:
$ export GNULIB_SRCDIR=/path/to/gnulib
We require to have the build directory different than the source directory:
$ mkdir build && cd build
The next step is to get all required pieces from gnulib,
to run autoreconf, and to invoke ../autogen.sh:
to run autoreconf, and to invoke ./configure:
$ ../autogen.sh
$ ./autogen.sh
And there you are! Just
@@ -51,7 +46,6 @@ And there you are! Just
At this point, there should be no difference between your local copy,
and the GIT master copy:
$ cd ..
$ git diff
should output no difference.

View File

@@ -1,86 +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.0 (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, however, we mandate to have the
build directory different than the source directory. For example, to build
in a manner that is suitable for installing as root, use:
```
$ mkdir build && cd build
$ ../configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
$ make
$ sudo make install
```
While to build & install as an unprivileged user
```
$ mkdir build && cd build
$ ../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

122
autobuild.sh Executable file
View File

@@ -0,0 +1,122 @@
#!/bin/sh
set -e
set -v
# Make things clean.
test -n "$1" && RESULTS=$1 || RESULTS=results.log
: ${AUTOBUILD_INSTALL_ROOT=$HOME/builder}
# If run under the autobuilder, we must use --nodeps with rpmbuild;
# but this can lead to odd error diagnosis for normal development.
nodeps=
if test "${AUTOBUILD_COUNTER+set}"; then
nodeps=--nodeps
fi
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-expensive-tests \
--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_LIBDIR="/usr/i686-w64-mingw32/sys-root/mingw/lib/pkgconfig:/usr/i686-w64-mingw32/sys-root/mingw/share/pkgconfig" \
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-expensive-tests \
--enable-werror
make
make install
fi
# Test mingw64 cross-compile
if test -x /usr/bin/x86_64-w64-mingw32-gcc ; then
make distclean
PKG_CONFIG_LIBDIR="/usr/x86_64-w64-mingw32/sys-root/mingw/lib/pkgconfig:/usr/x86_64-w64-mingw32/sys-root/mingw/share/pkgconfig" \
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-expensive-tests \
--enable-werror
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
# 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 || 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
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."
}

372
bootstrap
View File

@@ -1,10 +1,10 @@
#! /bin/sh
# Print a version string.
scriptversion=2019-01-04.17; # UTC
scriptversion=2013-12-05.23; # UTC
# Bootstrap this package from checked-out sources.
# Copyright (C) 2003-2020 Free Software Foundation, Inc.
# Copyright (C) 2003-2014 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 -nv -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=
@@ -247,17 +210,7 @@ bootstrap_sync=false
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
($1 --version </dev/null) >/dev/null 2>&1
test $? -lt 126
}
@@ -298,18 +251,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.
@@ -446,30 +405,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 +446,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 +463,11 @@ 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
if ! check_exists $app; then
warn_ "Error: '$app' not found"
ret=1
fi
@@ -640,101 +585,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"
}
@@ -824,9 +762,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 +870,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 +991,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
@@ -10,121 +10,135 @@
# 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 Lesser General Public License for more details.
# GNU 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/>.
# gnulib modules used by this package.
gnulib_modules='
accept
areadlink
autobuild
base64
bind
bitrotate
byteswap
c-ctype
c-strcase
c-strcasestr
calloc-posix
canonicalize-lgpl
chown
clock-time
close
connect
configmake
count-one-bits
crypto/md5
crypto/sha256
dirname-lgpl
environ
execinfo
fclose
fcntl
fcntl-h
fdatasync
ffs
ffsl
fnmatch
fsync
func
getaddrinfo
getcwd-lgpl
gethostname
getpass
getpeername
getsockname
gettext-h
gettimeofday
gitlog-to-changelog
gnumakefile
ignore-value
inet_pton
intprops
ioctl
isatty
largefile
ldexp
listen
localeconv
maintainer-makefile
manywarnings
mgetgroups
mkdtemp
mkostemp
mkostemps
mktempd
net_if
netdb
nonblocking
openpty
passfd
perror
physmem
pipe-posix
pipe2
poll
posix-shell
pthread
pthread_sigmask
recv
regex
random_r
sched
secure_getenv
send
setenv
setsockopt
sigaction
sigpipe
snprintf
socket
stat-time
stdarg
stpcpy
strchrnul
strdup-posix
strndup
strerror
strerror_r-posix
strptime
strsep
strtok_r
sys_stat
sys_wait
termios
time_r
timegm
ttyname_r
uname
useless-if-before-free
usleep
vasprintf
verify
vc-list-files
vsnprintf
waitpid
warnings
'
# NB the GSocket conversion is non-trivial due to the
# different FD vs HANDLE usage in gnulib vs glib. Need
# to find a way to duplicate a socket HANDLE before
# turning it into a FD, since closing an FD also closes
# the original HANDLE.
# -> GSocket
gnulib_modules="$gnulib_modules accept"
# -> GSocket
gnulib_modules="$gnulib_modules bind"
# -> conditional build to avoid Win32
gnulib_modules="$gnulib_modules chown"
# -> GSocket
gnulib_modules="$gnulib_modules close"
# -> GSocket
gnulib_modules="$gnulib_modules connect"
# -> Meson
gnulib_modules="$gnulib_modules configmake"
# -> eliminate usage in some manner
gnulib_modules="$gnulib_modules environ"
# -> GSocket
gnulib_modules="$gnulib_modules fcntl"
# -> conditional build avoid win32
gnulib_modules="$gnulib_modules fcntl-h"
# -> GSocket
gnulib_modules="$gnulib_modules getaddrinfo"
# -> copy gnuliub win32 impl
gnulib_modules="$gnulib_modules getpass"
# -> GSocket
gnulib_modules="$gnulib_modules getpeername"
# -> GSocket
gnulib_modules="$gnulib_modules getsockname"
# -> copy gnulib STRBUFLEN macro
gnulib_modules="$gnulib_modules intprops"
# -> GSocket
gnulib_modules="$gnulib_modules ioctl"
# -> Meson
gnulib_modules="$gnulib_modules largefile"
# -> GSocket
gnulib_modules="$gnulib_modules listen"
# -> custom configure check
gnulib_modules="$gnulib_modules localeconv"
# -> Meson
gnulib_modules="$gnulib_modules manywarnings"
# -> painful copy gnulib
gnulib_modules="$gnulib_modules mgetgroups"
# -> GSocket
gnulib_modules="$gnulib_modules net_if"
# -> GSocket
gnulib_modules="$gnulib_modules netdb"
# -> GSocket
gnulib_modules="$gnulib_modules nonblocking"
# -> Just add -lutil to cli
gnulib_modules="$gnulib_modules openpty"
# -> GSocket
gnulib_modules="$gnulib_modules passfd"
# -> open code / copy gnulib code
gnulib_modules="$gnulib_modules physmem"
# -> open code / conditional comp
gnulib_modules="$gnulib_modules pipe-posix"
# -> open code / conditional comp
gnulib_modules="$gnulib_modules pipe2"
# -> GMainLoop
gnulib_modules="$gnulib_modules poll"
# -> Meson
gnulib_modules="$gnulib_modules posix-shell"
# -> open code conditional logic
gnulib_modules="$gnulib_modules pthread_sigmask"
# -> GSocket
gnulib_modules="$gnulib_modules recv"
# -> GSocket
gnulib_modules="$gnulib_modules send"
# -> GSocket
gnulib_modules="$gnulib_modules setsockopt"
# -> open code conditional logic
gnulib_modules="$gnulib_modules sigaction"
# -> open code conditional logic
gnulib_modules="$gnulib_modules sigpipe"
# -> GSocket
gnulib_modules="$gnulib_modules socket"
# -> open code conditional or use GIO GFileInfo
gnulib_modules="$gnulib_modules stat-time"
# -> remove use or open-code it. possibly add to glib
gnulib_modules="$gnulib_modules strchrnul"
# -> g_strsplit
gnulib_modules="$gnulib_modules strtok_r"
# -> remove sys/stat.h include from any win32 code paths
gnulib_modules="$gnulib_modules sys_stat"
# -> remove sys/wait.h include from any win32 code paths
gnulib_modules="$gnulib_modules sys_wait"
# -> remove from any win32 code paths
gnulib_modules="$gnulib_modules termios"
# -> GDateTime ?
gnulib_modules="$gnulib_modules time_r"
# -> obsolete - exists on Linux, MacOS >= ?? & FreeBSD >= 6
gnulib_modules="$gnulib_modules ttyname_r"
# -> g_get_os_info in GLib 2.64 but can't use that yet
gnulib_modules="$gnulib_modules uname"
# -> G_STATIC_ASSERT
gnulib_modules="$gnulib_modules verify"
# -> remove from Win32 code paths
gnulib_modules="$gnulib_modules waitpid"
# -> Meson
gnulib_modules="$gnulib_modules warnings"
# -> open code impl
gnulib_modules="$gnulib_modules 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
@@ -133,6 +147,31 @@ 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+
@@ -156,24 +195,37 @@ local_gl_dir=gnulib/local
# 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 AUTHORS exist.
touch AUTHORS || exit 1
# Automake requires that ChangeLog and AUTHORS exist.
touch AUTHORS ChangeLog || exit 1
# Override bootstrap's list - we don't use mdate-sh or texinfo.tex.
gnulib_extra_files="
@@ -193,9 +245,3 @@ bootstrap_post_import_hook()
sed 's,\.\./\.\./\.\.,../..,g; s/^TESTS /GNULIB_TESTS /' $m > $m-t
mv -f $m-t $m
}
bootstrap_epilogue()
{
echo "$0: done. Now you can run 'mkdir build && cd build && ../configure'."
exit 0
}

71
build-aux/augeas-gentest.pl Executable file
View File

@@ -0,0 +1,71 @@
#!/usr/bin/perl
#
# augeas-gentest.pl: Generate an augeas test file, from an
# example config file + test file template
#
# 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;
die "syntax: $0 CONFIG TEMPLATE AUGTEST\n" unless @ARGV == 3;
my $config = shift @ARGV;
my $template = shift @ARGV;
my $augtest = shift @ARGV;
open AUGTEST, ">", $augtest or die "cannot create $augtest: $!";
$SIG{__DIE__} = sub {
unlink $augtest;
};
open CONFIG, "<", $config or die "cannot read $config: $!";
open TEMPLATE, "<", $template or die "cannot read $template: $!";
my $group = 0;
while (<TEMPLATE>) {
if (/::CONFIG::/) {
my $group = 0;
print AUGTEST " let conf = \"";
while (<CONFIG>) {
if (/^#\w/) {
s/^#//;
s/\"/\\\"/g;
print AUGTEST $_;
$group = /\[\s$/;
} elsif ($group) {
s/\"/\\\"/g;
if (/#\s*\]/) {
$group = 0;
}
if (/^#/) {
s/^#//;
print AUGTEST $_;
}
}
}
print AUGTEST "\"\n";
} else {
print AUGTEST $_;
}
}
close TEMPLATE;
close CONFIG;
close AUGTEST or die "cannot save $augtest: $!";

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

@@ -0,0 +1,161 @@
#!/usr/bin/perl
#
# bracket-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/>.
#
# 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 , ; = or "
$data =~ s/'[";,=]'/'X'/g;
# Kill any quoted strings
$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 =~ /\b(if|for|while|switch|return)\(/ ||
$data =~ /\b(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;
}
# 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)
# ;
#
while ($data =~ /[^;\s]\s+[;,]/) {
print "$file:$.: $line";
$ret = 1;
last;
}
# Require EOL, macro line continuation, or whitespace after ";".
# Allow "for (;;)" as an exception.
while ($data =~ /;[^ \\\n;)]/) {
print "$file:$.: $line";
$ret = 1;
last;
}
# Require EOL, space, or enum/struct end after comma.
while ($data =~ /,[^ \\\n)}]/) {
print "$file:$.: $line";
$ret = 1;
last;
}
# Require spaces around assignment '=', compounds and '=='
# with the exception of virAssertCmpInt()
$data =~ s/(virAssertCmpInt\(.* ).?=,/$1op,/;
while ($data =~ /[^ ]\b[!<>&|\-+*\/%\^=]?=[^=]/ ||
$data =~ /=[^= \\\n]/) {
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;

File diff suppressed because it is too large Load Diff

View File

@@ -1,226 +0,0 @@
#!/bin/sh
#! -*-perl-*-
# Detect instances of "if (p) free (p);".
# Likewise "if (p != 0)", "if (0 != p)", or with NULL; and with braces.
# Copyright (C) 2008-2019 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# Written by Jim Meyering
# This is a prologue that allows to run a perl script as an executable
# on systems that are compliant to a POSIX version before POSIX:2017.
# On such systems, the usual invocation of an executable through execlp()
# or execvp() fails with ENOEXEC if it is a script that does not start
# with a #! line. The script interpreter mentioned in the #! line has
# to be /bin/sh, because on GuixSD systems that is the only program that
# has a fixed file name. The second line is essential for perl and is
# also useful for editing this file in Emacs. The next two lines below
# are valid code in both sh and perl. When executed by sh, they re-execute
# the script through the perl program found in $PATH. The '-x' option
# is essential as well; without it, perl would re-execute the script
# through /bin/sh. When executed by perl, the next two lines are a no-op.
eval 'exec perl -wSx "$0" "$@"'
if 0;
my $VERSION = '2018-03-07 03:47'; # UTC
# The definition above must lie within the first 8 lines in order
# for the Emacs time-stamp write hook (at end) to update it.
# If you change this file with Emacs, please let the write hook
# do its job. Otherwise, update this string manually.
use strict;
use warnings;
use Getopt::Long;
(my $ME = $0) =~ s|.*/||;
# use File::Coda; # https://meyering.net/code/Coda/
END {
defined fileno STDOUT or return;
close STDOUT and return;
warn "$ME: failed to close standard output: $!\n";
$? ||= 1;
}
sub usage ($)
{
my ($exit_code) = @_;
my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
if ($exit_code != 0)
{
print $STREAM "Try '$ME --help' for more information.\n";
}
else
{
print $STREAM <<EOF;
Usage: $ME [OPTIONS] FILE...
Detect any instance in FILE of a useless "if" test before a free call, e.g.,
"if (p) free (p);". Any such test may be safely removed without affecting
the semantics of the C code in FILE. Use --name=FOO --name=BAR to also
detect free-like functions named FOO and BAR.
OPTIONS:
--list print only the name of each matching FILE (\\0-terminated)
--name=N add name N to the list of \'free\'-like functions to detect;
may be repeated
--help display this help and exit
--version output version information and exit
Exit status:
0 one or more matches
1 no match
2 an error
EXAMPLE:
For example, this command prints all removable "if" tests before "free"
and "kfree" calls in the linux kernel sources:
git ls-files -z |xargs -0 $ME --name=kfree
EOF
}
exit $exit_code;
}
sub is_NULL ($)
{
my ($expr) = @_;
return ($expr eq 'NULL' || $expr eq '0');
}
{
sub EXIT_MATCH {0}
sub EXIT_NO_MATCH {1}
sub EXIT_ERROR {2}
my $err = EXIT_NO_MATCH;
my $list;
my @name = qw(free);
GetOptions
(
help => sub { usage 0 },
version => sub { print "$ME version $VERSION\n"; exit },
list => \$list,
'name=s@' => \@name,
) or usage 1;
# Make sure we have the right number of non-option arguments.
# Always tell the user why we fail.
@ARGV < 1
and (warn "$ME: missing FILE argument\n"), usage EXIT_ERROR;
my $or = join '|', @name;
my $regexp = qr/(?:$or)/;
# Set the input record separator.
# Note: this makes it impractical to print line numbers.
$/ = '"';
my $found_match = 0;
FILE:
foreach my $file (@ARGV)
{
open FH, '<', $file
or (warn "$ME: can't open '$file' for reading: $!\n"),
$err = EXIT_ERROR, next;
while (defined (my $line = <FH>))
{
# Skip non-matching lines early to save time
$line =~ /\bif\b/
or next;
while ($line =~
/\b(if\s*\(\s*([^)]+?)(?:\s*!=\s*([^)]+?))?\s*\)
# 1 2 3
(?: \s*$regexp\s*\((?:\s*\([^)]+\))?\s*([^)]+)\)\s*;|
\s*\{\s*$regexp\s*\((?:\s*\([^)]+\))?\s*([^)]+)\)\s*;\s*\}))/sxg)
{
my $all = $1;
my ($lhs, $rhs) = ($2, $3);
my ($free_opnd, $braced_free_opnd) = ($4, $5);
my $non_NULL;
if (!defined $rhs) { $non_NULL = $lhs }
elsif (is_NULL $rhs) { $non_NULL = $lhs }
elsif (is_NULL $lhs) { $non_NULL = $rhs }
else { next }
# Compare the non-NULL part of the "if" expression and the
# free'd expression, without regard to white space.
$non_NULL =~ tr/ \t//d;
my $e2 = defined $free_opnd ? $free_opnd : $braced_free_opnd;
$e2 =~ tr/ \t//d;
if ($non_NULL eq $e2)
{
$found_match = 1;
$list
and (print "$file\0"), next FILE;
print "$file: $all\n";
}
}
}
}
continue
{
close FH;
}
$found_match && $err == EXIT_NO_MATCH
and $err = EXIT_MATCH;
exit $err;
}
my $foo = <<'EOF';
# The above is to *find* them.
# This adjusts them, removing the unnecessary "if (p)" part.
# FIXME: do something like this as an option (doesn't do braces):
free=xfree
git grep -l -z "$free *(" \
| xargs -0 useless-if-before-free -l --name="$free" \
| xargs -0 perl -0x3b -pi -e \
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*(?:0|NULL))?\s*\)\s+('"$free"'\s*\((?:\s*\([^)]+\))?\s*\1\s*\)\s*;)/$2/s'
# Use the following to remove redundant uses of kfree inside braces.
# Note that -0777 puts perl in slurp-whole-file mode;
# but we have plenty of memory, these days...
free=kfree
git grep -l -z "$free *(" \
| xargs -0 useless-if-before-free -l --name="$free" \
| xargs -0 perl -0777 -pi -e \
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*(?:0|NULL))?\s*\)\s*\{\s*('"$free"'\s*\((?:\s*\([^)]+\))?\s*\1\s*\);)\s*\}[^\n]*$/$2/gms'
Be careful that the result of the above transformation is valid.
If the matched string is followed by "else", then obviously, it won't be.
When modifying files, refuse to process anything other than a regular file.
EOF
## Local Variables:
## mode: perl
## indent-tabs-mode: nil
## eval: (add-hook 'before-save-hook 'time-stamp)
## time-stamp-line-limit: 50
## time-stamp-start: "my $VERSION = '"
## time-stamp-format: "%:y-%02m-%02d %02H:%02M"
## time-stamp-time-zone: "UTC0"
## time-stamp-end: "'; # UTC"
## End:

View File

@@ -1,113 +0,0 @@
#!/bin/sh
# List version-controlled file names.
# Print a version string.
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 2006-2019 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# List the specified version-controlled files.
# With no argument, list them all. With a single DIRECTORY argument,
# list the version-controlled files in that directory.
# If there's an argument, it must be a single, "."-relative directory name.
# cvsu is part of the cvsutils package: http://www.red-bean.com/cvsutils/
postprocess=
case $1 in
--help) cat <<EOF
Usage: $0 [-C SRCDIR] [DIR...]
Output a list of version-controlled files in DIR (default .), relative to
SRCDIR (default .). SRCDIR must be the top directory of a checkout.
Options:
--help print this help, then exit
--version print version number, then exit
-C SRCDIR change directory to SRCDIR before generating list
Report bugs and patches to <bug-gnulib@gnu.org>.
EOF
exit ;;
--version)
year=`echo "$scriptversion" | sed 's/[^0-9].*//'`
cat <<EOF
vc-list-files $scriptversion
Copyright (C) $year Free Software Foundation, Inc,
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
EOF
exit ;;
-C)
test "$2" = . || postprocess="| sed 's|^|$2/|'"
cd "$2" || exit 1
shift; shift ;;
esac
test $# = 0 && set .
for dir
do
if test -d .git || test -f .git; then
test "x$dir" = x. \
&& dir= sed_esc= \
|| { dir="$dir/"; sed_esc=`echo "$dir"|env sed 's,\([\\/]\),\\\\\1,g'`; }
# Ignore git symlinks - either they point into the tree, in which case
# we don't need to visit the target twice, or they point somewhere
# else (often into a submodule), in which case the content does not
# belong to this package.
eval exec git ls-tree -r 'HEAD:"$dir"' \
\| sed -n '"s/^100[^ ]*./$sed_esc/p"' $postprocess
elif test -d .hg; then
eval exec hg locate '"$dir/*"' $postprocess
elif test -d .bzr; then
test "$postprocess" = '' && postprocess="| sed 's|^\./||'"
eval exec bzr ls -R --versioned '"$dir"' $postprocess
elif test -d CVS; then
test "$postprocess" = '' && postprocess="| sed 's|^\./||'"
if test -x build-aux/cvsu; then
eval build-aux/cvsu --find --types=AFGM '"$dir"' $postprocess
elif (cvsu --help) >/dev/null 2>&1; then
eval cvsu --find --types=AFGM '"$dir"' $postprocess
else
eval awk -F/ \''{ \
if (!$1 && $3 !~ /^-/) { \
f=FILENAME; \
if (f ~ /CVS\/Entries$/) \
f = substr(f, 1, length(f)-11); \
print f $2; \
}}'\'' \
`find "$dir" -name Entries -print` /dev/null' $postprocess
fi
elif test -d .svn; then
eval exec svn list -R '"$dir"' $postprocess
else
echo "$0: Failed to determine type of version control used in `pwd`" 1>&2
exit 1
fi
done
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

1148
cfg.mk Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,268 +0,0 @@
# -*- makefile -*-
# vim: filetype=make
# The root directory of the libvirt.git checkout
CI_GIT_ROOT = $(shell git rev-parse --show-toplevel)
# The root directory for all CI-related contents
CI_ROOTDIR = $(CI_GIT_ROOT)/ci
# The directory holding content on the host that we will
# expose to the container.
CI_SCRATCHDIR = $(CI_ROOTDIR)/scratch
# The directory holding the clone of the git repo that
# we will expose to the container
CI_HOST_SRCDIR = $(CI_SCRATCHDIR)/src
# The directory holding the source inside the
# container, i.e. where we want to expose
# the $(CI_HOST_SRCDIR) directory from the host
CI_CONT_SRCDIR = $(CI_USER_HOME)/libvirt
# Relative directory to perform the build in. This
# defaults to using a separate build dir, but can be
# set to empty string for an in-source tree build.
CI_VPATH = build
# The directory holding the build output inside the
# container.
CI_CONT_BUILDDIR = $(CI_CONT_SRCDIR)/$(CI_VPATH)
# Can be overridden with mingw{32,64}-configure if desired
CI_CONFIGURE = $(CI_CONT_SRCDIR)/configure
# Default to using all possible CPUs
CI_SMP = $(shell getconf _NPROCESSORS_ONLN)
# Any extra arguments to pass to make
CI_MAKE_ARGS =
# Any extra arguments to pass to configure
CI_CONFIGURE_ARGS =
# Script containing environment preparation steps
CI_PREPARE_SCRIPT = $(CI_ROOTDIR)/prepare.sh
# Script containing build instructions
CI_BUILD_SCRIPT = $(CI_ROOTDIR)/build.sh
# Location of the container images we're going to pull
# Can be useful to overridde to use a locally built
# image instead
CI_IMAGE_PREFIX = quay.io/libvirt/buildenv-libvirt-
# The default tag is ':latest' but if the container
# repo above uses different conventions this can override it
CI_IMAGE_TAG = :latest
# We delete the virtual root after completion, set
# to 0 if you need to keep it around for debugging
CI_CLEAN = 1
# We'll always freshly clone the virtual root each
# time in case it was not cleaned up before. Set
# to 1 if you want to try restarting a previously
# preserved env
CI_REUSE = 0
# We need the container process to run with current host IDs
# so that it can access the passed in build directory
CI_UID = $(shell id -u)
CI_GID = $(shell id -g)
# We also need the user's login and home directory to prepare the
# environment the way some programs expect it
CI_USER_LOGIN = $(shell echo "$$USER")
CI_USER_HOME = $(shell echo "$$HOME")
CI_ENGINE = auto
# Container engine we are going to use, can be overridden per make
# invocation, if it is not we try podman and then default to docker.
ifeq ($(CI_ENGINE),auto)
override CI_ENGINE = $(shell podman version >/dev/null 2>&1 && echo podman || echo docker)
endif
# IDs you run as do not need to exist in
# the container's /etc/passwd & /etc/group files, but
# if they do not, then libvirt's 'make check' will fail
# many tests.
# We do not directly mount /etc/{passwd,group} as Docker
# is liable to mess with SELinux labelling which will
# then prevent the host accessing them. And podman cannot
# relabel the files due to it running rootless. So
# copying them first is safer and less error-prone.
CI_PWDB_MOUNTS = \
--volume $(CI_SCRATCHDIR)/group:/etc/group:ro,z \
--volume $(CI_SCRATCHDIR)/passwd:/etc/passwd:ro,z \
$(NULL)
CI_HOME_MOUNTS = \
--volume $(CI_SCRATCHDIR)/home:$(CI_USER_HOME):z \
$(NULL)
CI_SCRIPT_MOUNTS = \
--volume $(CI_SCRATCHDIR)/prepare:$(CI_USER_HOME)/prepare:z \
--volume $(CI_SCRATCHDIR)/build:$(CI_USER_HOME)/build:z \
$(NULL)
# Docker containers can have very large ulimits
# for nofiles - as much as 1048576. This makes
# libvirt very slow at exec'ing programs.
CI_ULIMIT_FILES = 1024
ifeq ($(CI_ENGINE),podman)
# Podman cannot reuse host namespace when running non-root
# containers. Until support for --keep-uid is added we can
# just create another mapping that will do that for us.
# Beware, that in {uid,git}map=container_id:host_id:range, the
# host_id does actually refer to the uid in the first mapping
# where 0 (root) is mapped to the current user and rest is
# offset.
#
# In order to set up this mapping, we need to keep all the
# user IDs to prevent possible errors as some images might
# expect UIDs up to 90000 (looking at you fedora), so we don't
# want the overflowuid to be used for them. For mapping all
# the other users properly, some math needs to be done.
# Don't worry, it's just addition and subtraction.
#
# 65536 ought to be enough (tm), but for really rare cases the
# maximums might need to be higher, but that only happens when
# your /etc/sub{u,g}id allow users to have more IDs. Unless
# --keep-uid is supported, let's do this in a way that should
# work for everyone.
CI_MAX_UID = $(shell sed -n "s/^$(CI_USER_LOGIN):[^:]\+://p" /etc/subuid)
CI_MAX_GID = $(shell sed -n "s/^$(CI_USER_LOGIN):[^:]\+://p" /etc/subgid)
ifeq ($(CI_MAX_UID),)
CI_MAX_UID = 65536
endif
ifeq ($(CI_MAX_GID),)
CI_MAX_GID = 65536
endif
CI_UID_OTHER = $(shell echo $$(($(CI_UID)+1)))
CI_GID_OTHER = $(shell echo $$(($(CI_GID)+1)))
CI_UID_OTHER_RANGE = $(shell echo $$(($(CI_MAX_UID)-$(CI_UID))))
CI_GID_OTHER_RANGE = $(shell echo $$(($(CI_MAX_GID)-$(CI_GID))))
CI_PODMAN_ARGS = \
--uidmap 0:1:$(CI_UID) \
--uidmap $(CI_UID):0:1 \
--uidmap $(CI_UID_OTHER):$(CI_UID_OTHER):$(CI_UID_OTHER_RANGE) \
--gidmap 0:1:$(CI_GID) \
--gidmap $(CI_GID):0:1 \
--gidmap $(CI_GID_OTHER):$(CI_GID_OTHER):$(CI_GID_OTHER_RANGE) \
$(NULL)
endif
# Args to use when cloning a git repo.
# -c stop it complaining about checking out a random hash
# -q stop it displaying progress info for local clone
# --local ensure we don't actually copy files
CI_GIT_ARGS = \
-c advice.detachedHead=false \
-q \
--local \
$(NULL)
# Args to use when running the container
# --rm stop inactive containers getting left behind
# --user we execute as the same user & group account
# as dev so that file ownership matches host
# instead of root:root
# --volume to pass in the cloned git repo & config
# --ulimit lower files limit for performance reasons
# --interactive
# --tty Ensure we have ability to Ctrl-C the build
CI_ENGINE_ARGS = \
--rm \
--interactive \
--tty \
$(CI_PODMAN_ARGS) \
$(CI_PWDB_MOUNTS) \
$(CI_HOME_MOUNTS) \
$(CI_SCRIPT_MOUNTS) \
--volume $(CI_HOST_SRCDIR):$(CI_CONT_SRCDIR):z \
--ulimit nofile=$(CI_ULIMIT_FILES):$(CI_ULIMIT_FILES) \
--cap-add=SYS_PTRACE \
$(NULL)
ci-check-engine:
@echo -n "Checking if $(CI_ENGINE) is available..." && \
$(CI_ENGINE) version 1>/dev/null && echo "yes"
ci-prepare-tree: ci-check-engine
@test "$(CI_REUSE)" != "1" && rm -rf $(CI_SCRATCHDIR) || :
@if ! test -d $(CI_SCRATCHDIR) ; then \
mkdir -p $(CI_SCRATCHDIR); \
cp /etc/passwd $(CI_SCRATCHDIR); \
cp /etc/group $(CI_SCRATCHDIR); \
mkdir -p $(CI_SCRATCHDIR)/home; \
cp "$(CI_PREPARE_SCRIPT)" $(CI_SCRATCHDIR)/prepare; \
cp "$(CI_BUILD_SCRIPT)" $(CI_SCRATCHDIR)/build; \
chmod +x "$(CI_SCRATCHDIR)/prepare" "$(CI_SCRATCHDIR)/build"; \
echo "Cloning $(CI_GIT_ROOT) to $(CI_HOST_SRCDIR)"; \
git clone $(CI_GIT_ARGS) $(CI_GIT_ROOT) $(CI_HOST_SRCDIR) || exit 1; \
for mod in $$(git submodule | awk '{ print $$2 }' | sed -E 's,^../,,g') ; \
do \
test -f $(CI_GIT_ROOT)/$$mod/.git || continue ; \
echo "Cloning $(CI_GIT_ROOT)/$$mod to $(CI_HOST_SRCDIR)/$$mod"; \
git clone $(CI_GIT_ARGS) $(CI_GIT_ROOT)/$$mod $(CI_HOST_SRCDIR)/$$mod || exit 1; \
done ; \
fi
ci-run-command@%: ci-prepare-tree
$(CI_ENGINE) run $(CI_ENGINE_ARGS) $(CI_IMAGE_PREFIX)$*$(CI_IMAGE_TAG) \
/bin/bash -c ' \
$(CI_USER_HOME)/prepare || exit 1; \
sudo \
--login \
--user="#$(CI_UID)" \
--group="#$(CI_GID)" \
CI_CONT_SRCDIR="$(CI_CONT_SRCDIR)" \
CI_CONT_BUILDDIR="$(CI_CONT_BUILDDIR)" \
CI_SMP="$(CI_SMP)" \
CI_CONFIGURE="$(CI_CONFIGURE)" \
CI_CONFIGURE_ARGS="$(CI_CONFIGURE_ARGS)" \
CI_MAKE_ARGS="$(CI_MAKE_ARGS)" \
$(CI_COMMAND) || exit 1'
@test "$(CI_CLEAN)" = "1" && rm -rf $(CI_SCRATCHDIR) || :
ci-shell@%:
$(MAKE) -C $(CI_ROOTDIR) ci-run-command@$* CI_COMMAND="/bin/bash"
ci-build@%:
$(MAKE) -C $(CI_ROOTDIR) ci-run-command@$* CI_COMMAND="$(CI_USER_HOME)/build"
ci-check@%:
$(MAKE) -C $(CI_ROOTDIR) ci-build@$* CI_MAKE_ARGS="check"
ci-list-images:
@echo
@echo "Available x86 container images:"
@echo
@sh list-images.sh "$(CI_ENGINE)" "$(CI_IMAGE_PREFIX)" | grep -v cross
@echo
@echo "Available cross-compiler container images:"
@echo
@sh list-images.sh "$(CI_ENGINE)" "$(CI_IMAGE_PREFIX)" | grep cross
@echo
ci-help:
@echo "Build libvirt inside containers used for CI"
@echo
@echo "Available targets:"
@echo
@echo " ci-build@\$$IMAGE - run a default 'make'"
@echo " ci-check@\$$IMAGE - run a 'make check'"
@echo " ci-shell@\$$IMAGE - run an interactive shell"
@echo " ci-list-images - list available images"
@echo " ci-help - show this help message"
@echo
@echo "Available make variables:"
@echo
@echo " CI_CLEAN=0 - do not delete '$(CI_SCRATCHDIR)' after completion"
@echo " CI_REUSE=1 - re-use existing '$(CI_SCRATCHDIR)' content"
@echo " CI_ENGINE=auto - container engine to use (podman, docker)"
@echo

View File

@@ -1,40 +0,0 @@
# This script is used to build libvirt inside the container.
#
# You can customize it to your liking, or alternatively use a
# completely different script by passing
#
# CI_BUILD_SCRIPT=/path/to/your/build/script
#
# to make.
mkdir -p "$CI_CONT_BUILDDIR" || exit 1
cd "$CI_CONT_BUILDDIR"
export VIR_TEST_DEBUG=1
NOCONFIGURE=1 "$CI_CONT_SRCDIR/autogen.sh" || exit 1
# $CONFIGURE_OPTS is a env that can optionally be set in the container,
# populated at build time from the Dockerfile. A typical use case would
# be to pass --host/--target args to trigger cross-compilation
#
# This can be augmented by make local args in $CI_CONFIGURE_ARGS
"$CI_CONFIGURE" $CONFIGURE_OPTS $CI_CONFIGURE_ARGS
if test $? != 0; then
test -f config.log && cat config.log
exit 1
fi
find -name test-suite.log -delete
# gl_public_submodule_commit= to disable gnulib's submodule check
# which breaks due to way we clone the submodules
make -j"$CI_SMP" gl_public_submodule_commit= $CI_MAKE_ARGS
if test $? != 0; then \
LOGS=$(find -name test-suite.log)
if test "$LOGS"; then
echo "=== LOG FILE(S) START ==="
cat $LOGS
echo "=== LOG FILE(S) END ==="
fi
exit 1
fi

View File

@@ -1,26 +0,0 @@
#!/bin/sh
engine="$1"
prefix="$2"
do_podman() {
# Podman freaks out if the search term ends with a dash, which ours
# by default does, so let's strip it. The repository name is the
# second field in the output, and it already starts with the registry
podman search --limit 100 "${prefix%-}" | while read _ repo _; do
echo "$repo"
done
}
do_docker() {
# Docker doesn't include the registry name in the output, so we have
# to add it. The repository name is the first field in the output
registry="${prefix%%/*}"
docker search --limit 100 "$prefix" | while read repo _; do
echo "$registry/$repo"
done
}
"do_$engine" | grep "^$prefix" | sed "s,^$prefix,,g" | while read repo; do
echo " $repo"
done | sort -u

View File

@@ -1,13 +0,0 @@
# This script is used to prepare the environment that will be used
# to build libvirt inside the container.
#
# You can customize it to your liking, or alternatively use a
# completely different script by passing
#
# CI_PREPARE_SCRIPT=/path/to/your/prepare/script
#
# to make.
#
# Note that this script will have root privileges inside the
# container, so it can be used for things like installing additional
# packages.

View File

@@ -16,46 +16,30 @@
* <http://www.gnu.org/licenses/>.
*/
#ifndef __GNUC__
# error "Libvirt requires GCC >= 4.8, 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.
* 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 __atttribute__((constructor)).
* The only way avoid 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 :-(
*/
#ifndef __GNUC_PREREQ
# define __GNUC_PREREQ(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
#ifdef LIBVIRT_SETUID_RPC_CLIENT
# undef HAVE_LIBDEVMAPPER_H
# undef HAVE_LIBNL
# undef HAVE_LIBNL3
# undef HAVE_LIBSASL2
# undef WITH_CAPNG
# undef WITH_CURL
# undef WITH_DTRACE_PROBES
# undef WITH_GNUTLS
# undef WITH_GNUTLS_GCRYPT
# undef WITH_MACVTAP
# undef WITH_NUMACTL
# undef WITH_SASL
# undef WITH_SSH2
# undef WITH_VIRTUALPORT
# undef WITH_YAJL
# undef WITH_YAJL2
#endif
#if defined(__clang_major__) && defined(__clang_minor__)
# ifdef __apple_build_version__
# if __clang_major__ < 5 || (__clang_major__ == 5 && __clang_minor__ < 1)
# error You need at least XCode Clang v5.1 to compile QEMU
# endif
# else
# if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 4)
# error You need at least Clang v3.4 to compile QEMU
# endif
# endif
#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
# error You need at least GCC v4.8 to compile QEMU
# endif
#else
# error You either need at least GCC 4.8 or Clang 3.4 or XCode Clang 5.1 to compile libvirt
#endif
/* Ask for warnings for anything that was marked deprecated in
* the defined version, or before. It is a candidate for rewrite.
*/
#define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_48
/* Ask for warnings if code tries to use function that did not
* exist in the defined version. These risk breaking builds
*/
#define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_48

File diff suppressed because it is too large Load Diff

481
daemon/Makefile.am Normal file
View File

@@ -0,0 +1,481 @@
## Process this file with automake to produce Makefile.in
## Copyright (C) 2005-2014 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/>.
INCLUDES = \
-I$(top_builddir)/gnulib/lib -I$(top_srcdir)/gnulib/lib \
-I$(top_srcdir) \
-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 \
-I$(top_srcdir)/src/access \
$(GETTEXT_CPPFLAGS)
CLEANFILES =
DAEMON_GENERATED = \
remote_dispatch.h \
lxc_dispatch.h \
qemu_dispatch.h \
$(NULL)
DAEMON_SOURCES = \
libvirtd.c libvirtd.h \
remote.c remote.h \
stream.c stream.h \
$(DAEMON_GENERATED)
LIBVIRTD_CONF_SOURCES = libvirtd-config.c libvirtd-config.h
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.socket.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) \
$(LIBVIRTD_CONF_SOURCES) \
$(NULL)
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
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)/remote_dispatch.h
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)/lxc_dispatch.h
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) \
> $(srcdir)/qemu_dispatch.h
if WITH_LIBVIRTD
# Build a convenience library, for reuse in tests/libvirtdconftest
noinst_LTLIBRARIES = libvirtd_conf.la
libvirtd_conf_la_SOURCES = $(LIBVIRTD_CONF_SOURCES)
libvirtd_conf_la_CFLAGS = \
$(LIBXML_CFLAGS) \
$(XDR_CFLAGS) \
$(WARN_CFLAGS) $(PIE_CFLAGS) \
$(COVERAGE_CFLAGS) \
$(NULL)
libvirtd_conf_la_LDFLAGS = \
$(RELRO_LDFLAGS) \
$(PIE_LDFLAGS) \
$(COVERAGE_LDFLAGS) \
$(NO_INDIRECT_LDFLAGS) \
$(NULL)
libvirtd_conf_la_LIBADD = $(LIBXML_LIBS)
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) $(DBUS_CFLAGS) $(LIBNL_CFLAGS) \
$(WARN_CFLAGS) $(PIE_CFLAGS) \
$(COVERAGE_CFLAGS) \
-DQEMUD_PID_FILE="\"$(QEMUD_PID_FILE)\""
libvirtd_LDFLAGS = \
$(RELRO_LDFLAGS) \
$(PIE_LDFLAGS) \
$(COVERAGE_LDFLAGS) \
$(NO_INDIRECT_LDFLAGS) \
$(NULL)
libvirtd_LDADD = \
$(LIBXML_LIBS) \
$(GNUTLS_LIBS) \
$(SASL_LIBS) \
$(DBUS_LIBS) \
$(LIBNL_LIBS)
if WITH_DTRACE_PROBES
libvirtd_LDADD += ../src/libvirt_probes.lo
endif WITH_DTRACE_PROBES
libvirtd_LDADD += \
libvirtd_conf.la \
../src/libvirt-lxc.la \
../src/libvirt-qemu.la \
../src/libvirt_driver_remote.la \
$(NULL)
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 WITH_DTRACE_PROBES
endif WITH_QEMU
if WITH_LXC
libvirtd_LDADD += ../src/libvirt_driver_lxc.la
endif WITH_LXC
if WITH_XEN
libvirtd_LDADD += ../src/libvirt_driver_xen.la
endif WITH_XEN
if WITH_LIBXL
libvirtd_LDADD += ../src/libvirt_driver_libxl.la
endif WITH_LIBXL
if WITH_UML
libvirtd_LDADD += ../src/libvirt_driver_uml.la
endif WITH_UML
if WITH_VBOX
libvirtd_LDADD += ../src/libvirt_driver_vbox.la
endif WITH_VBOX
if WITH_STORAGE
libvirtd_LDADD += ../src/libvirt_driver_storage.la
endif WITH_STORAGE
if WITH_NETWORK
libvirtd_LDADD += ../src/libvirt_driver_network.la
endif WITH_NETWORK
if WITH_INTERFACE
libvirtd_LDADD += ../src/libvirt_driver_interface.la
endif WITH_INTERFACE
if WITH_NODE_DEVICES
libvirtd_LDADD += ../src/libvirt_driver_nodedev.la
endif WITH_NODE_DEVICES
if WITH_SECRETS
libvirtd_LDADD += ../src/libvirt_driver_secret.la
endif WITH_SECRETS
if WITH_NWFILTER
libvirtd_LDADD += ../src/libvirt_driver_nwfilter.la
endif WITH_NWFILTER
endif ! WITH_DRIVER_MODULES
libvirtd_LDADD += ../src/libvirt.la
if WITH_POLKIT
if WITH_POLKIT0
policydir = $(datadir)/PolicyKit/policy
policyauth = auth_admin_keep_session
else ! WITH_POLKIT0
policydir = $(datadir)/polkit-1/actions
policyauth = auth_admin_keep
endif ! WITH_POLKIT0
endif WITH_POLKIT
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 ! WITH_POLKIT
install-data-polkit::
uninstall-data-polkit::
endif ! WITH_POLKIT
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 ! WITH_SYSCTL
install-sysctl:
uninstall-sysctl:
endif ! WITH_SYSCTL
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 ! LIBVIRT_INIT_SCRIPT_RED_HAT
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 ! LIBVIRT_INIT_SCRIPT_UPSTART
install-init-upstart:
uninstall-init-upstart:
endif ! LIBVIRT_INIT_SCRIPT_UPSTART
if LIBVIRT_INIT_SCRIPT_SYSTEMD
SYSTEMD_UNIT_DIR = $(prefix)/lib/systemd/system
BUILT_SOURCES += libvirtd.service libvirtd.socket
install-init-systemd: install-sysconfig libvirtd.service libvirtd.socket
$(MKDIR_P) $(DESTDIR)$(SYSTEMD_UNIT_DIR)
$(INSTALL_DATA) libvirtd.service \
$(DESTDIR)$(SYSTEMD_UNIT_DIR)/libvirtd.service
$(INSTALL_DATA) libvirtd.socket \
$(DESTDIR)$(SYSTEMD_UNIT_DIR)/libvirtd.socket
uninstall-init-systemd: uninstall-sysconfig
rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/libvirtd.service
rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/libvirtd.socket
rmdir $(DESTDIR)$(SYSTEMD_UNIT_DIR) || :
else ! LIBVIRT_INIT_SCRIPT_SYSTEMD
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 $@
libvirtd.socket: libvirtd.socket.in $(top_builddir)/config.status
$(AM_V_GEN)sed \
-e 's|[@]runstatedir[@]|$(runstatedir)|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 ! WITH_SASL
install-data-sasl:
uninstall-data-sasl:
endif ! WITH_SASL
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

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

@@ -0,0 +1,490 @@
/*
* libvirtd-config.c: daemon start of day, guest process & i/o management
*
* Copyright (C) 2006-2012, 2014 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"
#include "virstring.h"
#include "virutil.h"
#define VIR_FROM_THIS VIR_FROM_CONF
VIR_LOG_INIT("daemon.libvirtd-config");
/* 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;
}
if (VIR_STRDUP(list[0], p->str) < 0) {
VIR_FREE(list);
return -1;
}
list[1] = NULL;
break;
case VIR_CONF_LIST: {
int len = 0;
size_t i;
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;
}
if (VIR_STRDUP(list[i], pp->str) < 0) {
size_t j;
for (j = 0; j < i; j++)
VIR_FREE(list[j]);
VIR_FREE(list);
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 VIR_STRDUP succeeds,
store the result in var_name. Otherwise, (i.e. invalid type, or VIR_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 (VIR_STRDUP(data->var_name, p->str) < 0) \
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 (VIR_STRDUP(*configfile, SYSCONFDIR "/libvirt/libvirtd.conf") < 0)
goto error;
} else {
char *configdir = NULL;
if (!(configdir = virGetUserConfigDirectory()))
goto error;
if (virAsprintf(configfile, "%s/libvirtd.conf", configdir) < 0) {
VIR_FREE(configdir);
goto error;
}
VIR_FREE(configdir);
}
return 0;
error:
return -1;
}
struct daemonConfig*
daemonConfigNew(bool privileged ATTRIBUTE_UNUSED)
{
struct daemonConfig *data;
char *localhost;
int ret;
if (VIR_ALLOC(data) < 0)
return NULL;
data->listen_tls = 1;
data->listen_tcp = 0;
if (VIR_STRDUP(data->tls_port, LIBVIRTD_TLS_PORT) < 0 ||
VIR_STRDUP(data->tcp_port, LIBVIRTD_TCP_PORT) < 0)
goto error;
/* 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 (VIR_STRDUP(data->unix_sock_rw_perms,
data->auth_unix_rw == REMOTE_AUTH_POLKIT ? "0777" : "0700") < 0 ||
VIR_STRDUP(data->unix_sock_ro_perms, "0777") < 0)
goto error;
#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 = 5000;
data->max_anonymous_clients = 20;
data->prio_workers = 5;
data->max_requests = 20;
data->max_client_requests = 5;
data->audit_level = 1;
data->audit_logging = 0;
data->keepalive_interval = 5;
data->keepalive_count = 5;
data->keepalive_required = 0;
localhost = virGetHostname();
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 = VIR_STRDUP(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 error;
return data;
error:
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);
tmp = data->access_drivers;
while (tmp && *tmp) {
VIR_FREE(*tmp);
tmp++;
}
VIR_FREE(data->access_drivers);
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 (VIR_STRDUP(data->unix_sock_rw_perms, "0777") < 0)
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;
if (remoteConfigGetStringList(conf, "access_drivers",
&data->access_drivers, 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, max_queued_clients);
GET_CONF_INT(conf, filename, max_anonymous_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, 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;
}

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

@@ -0,0 +1,97 @@
/*
* libvirtd-config.h: 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;
char **access_drivers;
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 max_queued_clients;
int max_anonymous_clients;
int prio_workers;
int max_requests;
int max_client_requests;
int log_level;
char *log_filters;
char *log_outputs;
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__ */

100
daemon/libvirtd.aug Normal file
View File

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

1548
daemon/libvirtd.c Normal file

File diff suppressed because it is too large Load Diff

429
daemon/libvirtd.conf Normal file
View File

@@ -0,0 +1,429 @@
# 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
#
# If the libvirtd service is started in parallel with network
# startup (e.g. with systemd), binding to addresses other than
# the wildcards (0.0.0.0/::) might not be available yet.
#
#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 substituted for the short hostname of the machine (without domain)
#
#mdns_name = "Virtualization Host Joe Demo"
#################################################################
#
# UNIX socket access controls
#
# Beware that if you are changing *any* of these options, and you use
# socket activation with systemd, you need to adjust the settings in
# the libvirtd.socket file as well since it could impose a security
# risk if you rely on file permission checking only.
# 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, you may want to
# restrict this too.
#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 too.
#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"
# Change the API access control scheme
#
# By default an authenticated user is allowed access
# to all APIs. Access drivers can place restrictions
# on this. By default the 'nop' driver is enabled,
# meaning no access control checks are done once a
# client has authenticated with libvirtd
#
#access_drivers = [ "polkit" ]
#################################################################
#
# 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 = 5000
# The maximum length of queue of connections waiting to be
# accepted by the daemon. Note, that some protocols supporting
# retransmission may obey this so that a later reattempt at
# connection succeeds.
#max_queued_clients = 1000
# The maximum length of queue of accepted but not yet not
# authenticated clients. The default value is zero, meaning
# the feature is disabled.
#max_anonymous_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 are 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 impacts
# 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
# Note: Journald may employ rate limiting of the messages logged
# and thus lock up the libvirt daemon. To use the debug level with
# journald you have to specify it explicitly in 'log_outputs', otherwise
# only information level messages will be logged.
#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 filters 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
# x:journald
# output to journald logging system
# In all case the x prefix is the minimal level, acting as a filter
# 1: DEBUG
# 2: INFO
# 3: WARNING
# 4: ERROR
#
# Multiple outputs 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:
#
# This configuration option is no longer used, since the global
# log buffer functionality has been removed. Please configure
# suitable log_outputs/log_filters settings to obtain logs.
#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 clients. 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 daemon 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

80
daemon/libvirtd.h Normal file
View File

@@ -0,0 +1,80 @@
/*
* libvirtd.h: daemon data structure definitions
*
* Copyright (C) 2006-2014 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 <rpc/types.h>
# include <rpc/xdr.h>
# include "remote_protocol.h"
# include "lxc_protocol.h"
# include "qemu_protocol.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;
typedef struct daemonClientEventCallback daemonClientEventCallback;
typedef daemonClientEventCallback *daemonClientEventCallbackPtr;
/* Stores the per-client connection state */
struct daemonClientPrivate {
/* Hold while accessing any data except conn */
virMutex lock;
daemonClientEventCallbackPtr *domainEventCallbacks;
size_t ndomainEventCallbacks;
daemonClientEventCallbackPtr *networkEventCallbacks;
size_t nnetworkEventCallbacks;
daemonClientEventCallbackPtr *qemuEventCallbacks;
size_t nqemuEventCallbacks;
# 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

125
daemon/libvirtd.init.in Normal file
View File

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

View File

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

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

@@ -0,0 +1,208 @@
=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<-h, --help>
Display command line help usage then exit.
=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

@@ -0,0 +1,9 @@
@localstatedir@/log/libvirt/qemu/*.log {
weekly
missingok
rotate 4
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 -f [sasldb_path]' to browse it
sasldb_path: /etc/libvirt/passwd.db

View File

@@ -0,0 +1,22 @@
[Unit]
Description=Virtualization daemon
Before=libvirt-guests.service
After=network.target
After=dbus.service
After=iscsid.service
After=apparmor.service
Documentation=man:libvirtd(8)
Documentation=http://libvirt.org
[Service]
Type=notify
EnvironmentFile=-/etc/sysconfig/libvirtd
ExecStart=@sbindir@/libvirtd $LIBVIRTD_ARGS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
# Override the maximum number of opened files
#LimitNOFILE=2048
[Install]
WantedBy=multi-user.target

11
daemon/libvirtd.socket.in Normal file
View File

@@ -0,0 +1,11 @@
[Socket]
ListenStream=@runstatedir@/libvirt/libvirt-sock
ListenStream=@runstatedir@/libvirt/libvirt-sock-ro
; The following settings must match libvirtd.conf file in order to
; work as expected because libvirtd can't change them later.
; SocketMode=0777 is safe only if authentication on the socket is set
; up. For further information, please see the libvirtd.conf file.
SocketMode=0777
SocketUser=root
SocketGroup=root

33
daemon/libvirtd.sysconf Normal file
View File

@@ -0,0 +1,33 @@
# 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.
# This only works with traditional init scripts.
# In the systemd world, the limit can only be changed by overriding
# LimitNOFILE for libvirtd.service. To do that, just create a *.conf
# file in /etc/systemd/system/libvirtd.service.d/ (for example
# /etc/systemd/system/libvirtd.service.d/openfiles.conf) and write
# the following two lines in it:
# [Service]
# LimitNOFILE=2048
#
#LIBVIRTD_NOFILES_LIMIT=2048

View File

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

47
daemon/libvirtd.upstart Normal file
View File

@@ -0,0 +1,47 @@
# libvirtd upstart job
#
# XXX wait for rc to get all dependent initscripts started
# from sysv libvirtd initscript: Required-Start: $network messagebus
start on stopped rc RUNLEVEL=[345]
stop on runlevel [!345]
respawn
script
LIBVIRTD_CONFIG=
LIBVIRTD_ARGS=
KRB5_KTNAME=/etc/libvirt/krb5.tab
if [ -f /etc/sysconfig/libvirtd ]; then
. /etc/sysconfig/libvirtd
fi
export QEMU_AUDIO_DRV
export SDL_AUDIODRIVER
export KRB5_KTNAME
LIBVIRTD_CONFIG_ARGS=
if [ -n "$LIBVIRTD_CONFIG" ]; then
LIBVIRTD_CONFIG_ARGS="--config $LIBVIRTD_CONFIG"
fi
# DAEMON_COREFILE_LIMIT from /etc/sysconfig/libvirtd is not handled
# automatically
if [ -n "$DAEMON_COREFILE_LIMIT" ]; then
ulimit -c "$DAEMON_COREFILE_LIMIT"
fi
# LIBVIRTD_NOFILES_LIMIT from /etc/sysconfig/libvirtd is not handled
# automatically
if [ -n "$LIBVIRTD_NOFILES_LIMIT" ]; then
ulimit -n "$LIBVIRTD_NOFILES_LIMIT"
fi
mkdir -p /var/cache/libvirt
rm -rf /var/cache/libvirt/*
exec /usr/sbin/libvirtd $LIBVIRTD_CONFIG_ARGS $LIBVIRTD_ARGS
end script
post-stop script
rm -rf /var/cache/libvirt/*
end script

6507
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-2014 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
VIR_LOG_INIT("daemon.stream");
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)
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_LEGACY_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,54 @@
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" }
{ "access_drivers"
{ "1" = "polkit" }
}
{ "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" = "5000" }
{ "max_queued_clients" = "1000" }
{ "max_anonymous_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,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>404 page not found</h1>
@@ -9,11 +9,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,6 +1,6 @@
## Process this file with automake to produce Makefile.in
## Copyright (C) 2005-2016 Red Hat, Inc.
## 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
@@ -16,151 +16,62 @@
## License along with this library. If not, see
## <http://www.gnu.org/licenses/>.
HTML_DIR = $(docdir)/html
SUBDIRS= schemas
modules = \
libvirt-common \
libvirt-domain \
libvirt-domain-checkpoint \
libvirt-domain-snapshot \
libvirt-event \
libvirt-host \
libvirt-interface \
libvirt-network \
libvirt-nodedev \
libvirt-nwfilter \
libvirt-secret \
libvirt-storage \
libvirt-stream \
virterror \
$(NULL)
PERL = perl
modules_admin = libvirt-admin
modules_qemu = libvirt-qemu
modules_lxc = libvirt-lxc
# The directory containing the source code (if it contains documentation).
DOC_SOURCE_DIR=../src
all: vpathhack
DEVHELP_DIR=$(datadir)/gtk-doc/html/libvirt
# This hack enables us to view the web pages
# from within the uninstalled build tree
vpathhack:
@for dir in fonts js logos; \
do \
test -e $$dir || ln -s $(srcdir)/$$dir $$dir ; \
done
@for file in $(css); \
do \
test -e $$file || ln -s $(srcdir)/$$file $$file ; \
done
apihtml = \
html/index.html \
html/libvirt-libvirt.html \
html/libvirt-virterror.html
clean-local:
for dir in fonts js logos; \
do \
rm -f $$dir ; \
done
for file in $(css); \
do \
rm -f $$file ; \
done
apihtml = \
html/index.html \
$(apihtml_generated)
apihtml_generated = \
$(addprefix html/libvirt-,$(addsuffix .html,$(modules))) \
$(NULL)
apiadminhtml = \
html/index-admin.html \
$(apiadminhtml_generated)
apiadminhtml_generated = \
$(addprefix html/libvirt-,$(addsuffix .html,$(modules_admin))) \
$(NULL)
apiqemuhtml = \
html/index-qemu.html \
$(apiqemuhtml_generated)
apiqemuhtml_generated = \
$(addprefix html/libvirt-,$(addsuffix .html,$(modules_qemu))) \
$(NULL)
apilxchtml = \
html/index-lxc.html \
$(apilxchtml_generated)
apilxchtml_generated = \
$(addprefix html/libvirt-,$(addsuffix .html,$(modules_lxc))) \
$(NULL)
apipng = \
html/left.png \
html/up.png \
html/home.png \
apipng = \
html/left.png \
html/up.png \
html/home.png \
html/right.png
apirefdir = $(HTML_DIR)/html
apiref_DATA = $(apihtml) $(apiadminhtml) $(apiqemuhtml) $(apilxchtml) $(apipng)
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
javascript = \
js/main.js \
$(NULL)
devhelppng = \
devhelp/home.png \
devhelp/left.png \
devhelp/right.png \
devhelp/up.png
javascriptdir = $(HTML_DIR)/js
javascript_DATA = $(javascript)
devhelpcss = devhelp/style.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
fontsdir = $(HTML_DIR)/fonts
fonts_DATA = $(fonts)
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
logofilesdir = $(HTML_DIR)/logos
logofiles_DATA = $(logofiles)
devhelpxsl = devhelp/devhelp.xsl devhelp/html.xsl
png = \
32favicon.png \
footer_corner.png \
footer_pattern.png \
libvirt-header-bg.png \
libvirt-header-logo.png \
libvirtLogo.png \
libvirt-net-logical.png \
libvirt-net-physical.png \
libvirt-daemon-arch.png \
libvirt-driver-arch.png \
libvirt-object-model.png \
madeWith.png \
et.png \
migration-managed-direct.png \
migration-managed-p2p.png \
migration-native.png \
@@ -171,166 +82,46 @@ gif = \
architecture.gif \
node.gif
internals_html_in = \
$(patsubst $(srcdir)/%,%,$(wildcard $(srcdir)/internals/*.html.in))
internals_rst = \
$(patsubst $(srcdir)/%,%,$(wildcard $(srcdir)/internals/*.rst))
internals_rst_html_in = \
$(internals_rst:%.rst=%.html.in)
internals_html = \
$(internals_html_in:%.html.in=%.html) \
$(internals_rst_html_in:%.html.in=%.html)
internals_html = $(internals_html_in:%.html.in=%.html)
internalsdir = $(HTML_DIR)/internals
internals_DATA = $(internals_html)
# todo.html is special - it is shipped in the tarball, but we
# have a dedicated 'todo' target to rebuild it from a proper
# config file, all other users are able to build it locally.
# For all other files, since we ship pre-built html in the
# tarball, we must also ship the sources, even when those
# sources are themselves generated.
dot_html_in = $(notdir $(wildcard $(srcdir)/*.html.in)) \
todo.html.in \
hvsupport.html.in
dot_html = $(dot_html_in:%.html.in=%.html)
kbase_html_in = \
$(patsubst $(srcdir)/%,%,$(wildcard $(srcdir)/kbase/*.html.in))
kbase_rst = \
$(patsubst $(srcdir)/%,%,$(wildcard $(srcdir)/kbase/*.rst))
kbase_rst_html_in = \
$(kbase_rst:%.rst=%.html.in)
kbase_html = \
$(kbase_html_in:%.html.in=%.html) \
$(kbase_rst_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)
kbasedir = $(HTML_DIR)/kbase
kbase_DATA = $(kbase_html)
patches = $(patsubst $(srcdir)/%,%,$(wildcard $(srcdir)/api_extension/*.patch))
# Sync with src/util/
KEYCODES = linux osx atset1 atset2 atset3 xtkbd usb win32 qnum
KEYNAMES = linux osx win32
xml = \
libvirt-api.xml \
libvirt-refs.xml
manpages_rst = \
manpages/index.rst \
$(NULL)
manpages1_rst = \
manpages/virt-pki-validate.rst \
manpages/virt-xml-validate.rst \
manpages/virt-admin.rst \
manpages/virsh.rst \
$(NULL)
manpages7_rst = \
$(KEYCODES:%=manpages/virkeycode-%.rst) \
$(KEYNAMES:%=manpages/virkeyname-%.rst) \
$(NULL)
manpages8_rst = $(NULL)
manpages_rst += \
$(manpages1_rst) \
$(manpages7_rst) \
$(manpages8_rst) \
$(NULL)
if WITH_LIBVIRTD
manpages8_rst += \
manpages/libvirtd.rst \
manpages/virtlockd.rst \
manpages/virtlogd.rst \
$(NULL)
else ! WITH_LIBVIRTD
manpages_rst += \
manpages/libvirtd.rst \
manpages/virtlockd.rst \
manpages/virtlogd.rst \
$(NULL)
endif ! WITH_LIBVIRTD
if WITH_HOST_VALIDATE
manpages1_rst += manpages/virt-host-validate.rst
else ! WITH_HOST_VALIDATE
manpages_rst += manpages/virt-host-validate.rst
endif ! WITH_HOST_VALIDATE
if WITH_LOGIN_SHELL
manpages1_rst += manpages/virt-login-shell.rst
else ! WITH_LOGIN_SHELL
manpages_rst += manpages/virt-login-shell.rst
endif ! WITH_LOGIN_SHELL
if WITH_SANLOCK
manpages8_rst += manpages/virt-sanlock-cleanup.rst
else ! WITH_SANLOCK
manpages_rst += manpages/virt-sanlock-cleanup.rst
endif ! WITH_SANLOCK
manpages_rst_html_in = \
$(manpages_rst:%.rst=%.html.in)
manpages_html = \
$(manpages_rst_html_in:%.html.in=%.html)
qemu_xml = \
libvirt-qemu-api.xml \
libvirt-qemu-refs.xml
man1_MANS = $(manpages1_rst:%.rst=%.1)
man7_MANS = $(manpages7_rst:%.rst=%.7)
man8_MANS = $(manpages8_rst:%.rst=%.8)
%.1: %.rst
$(AM_V_GEN)$(MKDIR_P) `dirname $@` && \
grep -v '^\.\. contents::' < $< | \
sed -e 's|SYSCONFDIR|$(sysconfdir)|g' \
-e 's|RUNSTATEDIR|$(runstatedir)|g' | \
$(RST2MAN) > $@ || { rm $@ && exit 1; }
%.7: %.rst
$(AM_V_GEN)$(MKDIR_P) `dirname $@` && \
grep -v '^\.\. contents::' < $< | \
sed -e 's|SYSCONFDIR|$(sysconfdir)|g' \
-e 's|RUNSTATEDIR|$(runstatedir)|g' | \
$(RST2MAN) > $@ || { rm $@ && exit 1; }
%.8: %.rst
$(AM_V_GEN)$(MKDIR_P) `dirname $@` && \
grep -v '^\.\. contents::' < $< | \
sed -e 's|SYSCONFDIR|$(sysconfdir)|g' \
-e 's|RUNSTATEDIR|$(runstatedir)|g' | \
$(RST2MAN) > $@ || { rm $@ && exit 1; }
manpages/virkeycode-%.rst: $(top_srcdir)/src/keycodemapdb/data/keymaps.csv \
$(top_srcdir)/src/keycodemapdb/tools/keymap-gen Makefile.am
$(AM_V_GEN)export NAME=`echo $@ | \
sed -e 's,manpages/virkeycode-,,' -e 's,\.rst,,'` && \
$(MKDIR_P) manpages/ && \
$(RUNUTF8) $(PYTHON) $(top_srcdir)/src/keycodemapdb/tools/keymap-gen \
code-docs \
--lang rst \
--title "virkeycode-$$NAME" \
--subtitle "Key code values for $$NAME" \
$(top_srcdir)/src/keycodemapdb/data/keymaps.csv $$NAME > $@
manpages/virkeyname-%.rst: $(top_srcdir)/src/keycodemapdb/data/keymaps.csv \
$(top_srcdir)/src/keycodemapdb/tools/keymap-gen Makefile.am
$(AM_V_GEN)export NAME=`echo $@ | \
sed -e 's,manpages/virkeyname-,,' -e 's,\.rst,,'` && \
$(MKDIR_P) manpages/ && \
$(RUNUTF8) $(PYTHON) $(top_srcdir)/src/keycodemapdb/tools/keymap-gen \
name-docs \
--lang rst \
--title "virkeyname-$$NAME" \
--subtitle "Key name values for $$NAME" \
$(top_srcdir)/src/keycodemapdb/data/keymaps.csv $$NAME > $@
manpagesdir = $(HTML_DIR)/manpages
manpages_DATA = $(manpages_html)
# Generate hvsupport.html and news.html first, since they take one extra step.
dot_html_generated_in = \
hvsupport.html.in \
news.html.in
dot_html_in = \
$(notdir $(wildcard $(srcdir)/*.html.in))
dot_rst = \
$(notdir $(wildcard $(srcdir)/*.rst))
dot_rst_html_in = \
$(dot_rst:%.rst=%.html)
dot_html = \
$(dot_html_generated_in:%.html.in=%.html) \
$(dot_html_in:%.html.in=%.html) \
$(dot_rst_html_in:%.html.in=%.html)
htmldir = $(HTML_DIR)
html_DATA = $(css) $(png) $(gif) $(dot_html)
lxc_xml = \
libvirt-lxc-api.xml \
libvirt-lxc-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 \
@@ -340,182 +131,202 @@ 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 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) $(fig) $(png) $(css) \
$(patches) $(dot_php_in) $(dot_php_code_in) $(dot_php)\
$(internals_html_in) $(internals_html) \
sitemap.html.in aclperms.htmlinc \
todo.pl hvsupport.pl todo.cfg-example
EXTRA_DIST= \
site.xsl subsite.xsl newapi.xsl page.xsl \
wrapstring.xsl \
$(dot_html_in) $(dot_rst) $(gif) $(apipng) \
$(fig) $(png) $(css) \
$(javascript) $(logofiles) \
$(internals_html_in) $(internals_rst) $(fonts) \
$(kbase_html_in) $(kbase_rst) \
$(manpages_rst) \
aclperms.htmlinc \
$(schema_DATA)
acl.html:: $(srcdir)/aclperms.htmlinc
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 $< > $@
aclperms.htmlinc: $(top_srcdir)/src/access/viraccessperm.h \
$(top_srcdir)/scripts/genaclperms.py Makefile.am
$(AM_V_GEN)$(RUNUTF8) $(PYTHON) $(top_srcdir)/scripts/genaclperms.py $< > $@
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
CLEANFILES = \
$(dot_html) \
$(apihtml) \
$(apiadminhtml) \
$(apiqemuhtml) \
$(apilxchtml) \
$(internals_html) \
$(kbase_html) \
$(manpages_html) \
$(man1_MANS) \
$(man7_MANS) \
$(manpages7_rst) \
$(man8_MANS) \
$(api_DATA) \
$(dot_html_generated_in) \
aclperms.htmlinc
all-am: web
timestamp="$(shell if test -n "$$SOURCE_DATE_EPOCH"; \
then \
date -u --date="@$$SOURCE_DATE_EPOCH"; \
else \
date -u; \
fi)"
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
hvsupport.html: hvsupport.html.in
web: $(dot_html) $(internals_html) html/index.html devhelp/index.html \
$(dot_php)
hvsupport.html.in: $(top_srcdir)/scripts/hvsupport.py $(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)$(RUNUTF8) $(PYTHON) $(top_srcdir)/scripts/hvsupport.py \
$(top_srcdir) $(top_builddir) > $@ || { rm $@ && exit 1; }
todo.html.in: todo.pl
if [ -f todo.cfg ]; then \
echo "Generating $@"; \
$(PERL) $< > $@ \
|| { rm $@ && exit 1; }; \
else \
echo "Stubbing $@"; \
printf "%s\n" \
"<html xmlns=\"http://www.w3.org/1999/xhtml\">" \
"<body>" \
"<h1>Todo list unavailable: no config file</h1>" \
"</body></html>" > $@ ; \
fi
news.html.in: \
$(srcdir)/news.xml \
$(srcdir)/news-html.xsl
$(AM_V_GEN)$(XSLTPROC) --nonet \
$(srcdir)/news-html.xsl \
$(srcdir)/news.xml \
>$@ \
|| { rm -f $@; exit 1; };
EXTRA_DIST += \
$(srcdir)/news.xml \
$(srcdir)/news.rng \
$(srcdir)/news-html.xsl
todo:
rm -f todo.html.in
$(MAKE) todo.html
hvsupport.html:: $(srcdir)/hvsupport.html.in
$(srcdir)/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 $< $@
manpages/%.html.in: manpages/%.rst
$(AM_V_GEN)$(MKDIR_P) `dirname $@` && \
grep -v '^:Manual ' < $< | \
sed -e 's|SYSCONFDIR|$(sysconfdir)|g' \
-e 's|RUNSTATEDIR|$(runstatedir)|g' | \
$(RST2HTML) > $@ || { 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 \
$(top_srcdir)/docs/subsite.xsl $< > $@ \
|| { rm $@ && exit 1; }; fi
%.html.in: %.rst
$(AM_V_GEN)$(MKDIR_P) `dirname $@` && \
$(RST2HTML) $< > $@ || { rm $@ && exit 1; }
%.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 builddir '$(abs_top_builddir)' \
--stringparam timestamp $(timestamp) --nonet \
$(top_srcdir)/docs/$$style $< > $@ \
|| { rm $@ && exit 1; }
%.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 \
$(top_srcdir)/docs/site.xsl $< > $@ \
|| { rm $@ && exit 1; }; fi
%.html: %.html.tmp
$(AM_V_GEN)$(XMLLINT) --nonet --format $< > $@ \
|| { rm $@ && 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
$(apihtml_generated): html/index.html
$(apiadminhtml_generated): html/index-admin.html
$(apiqemuhtml_generated): html/index-qemu.html
$(apilxchtml_generated): html/index-lxc.html
%.php.tmp: %.php.in site.xsl page.xsl sitemap.html.in
@if [ -x $(XSLTPROC) ] ; then \
echo "Generating $@"; \
$(XSLTPROC) --stringparam pagename $(@:.tmp=) --nonet \
$(top_srcdir)/docs/site.xsl $< > $@ \
|| { rm $@ && exit 1; }; fi
html/index.html: libvirt-api.xml newapi.xsl page.xsl $(APIBUILD_STAMP)
$(AM_V_GEN)$(XSLTPROC) --nonet -o ./ \
%.php: %.php.tmp %.php.code.in
@if [ -x $(XSLTPROC) ] ; then \
echo "Scripting $@"; \
sed -e '/<span id="php_placeholder"><\/span>/r '"$(srcdir)/$@.code.in" \
-e /php_placeholder/d < $@.tmp > $(srcdir)/$@ \
|| { rm $(srcdir)/$@ && exit 1; }; fi
html/index.html: libvirt-api.xml newapi.xsl page.xsl sitemap.html.in
$(AM_V_GEN)if [ -x $(XSLTPROC) ] ; then \
$(XSLTPROC) --nonet -o $(srcdir)/ \
--stringparam builddir '$(abs_top_builddir)' \
--stringparam timestamp $(timestamp) \
$(srcdir)/newapi.xsl libvirt-api.xml
$(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
html/index-%.html: libvirt-%-api.xml newapi.xsl page.xsl $(APIBUILD_STAMP)
$(AM_V_GEN)$(XSLTPROC) --nonet -o ./ \
--stringparam builddir '$(abs_top_builddir)' \
--stringparam timestamp $(timestamp) \
--stringparam indexfile $(@:html/%=%) \
$(srcdir)/newapi.xsl $<
$(addprefix $(srcdir)/,$(devhelphtml)): $(srcdir)/libvirt-api.xml $(devhelpxsl)
$(AM_V_GEN)if [ -x $(XSLTPROC) ] ; then \
$(XSLTPROC) --nonet -o $(srcdir)/devhelp/ \
$(top_srcdir)/docs/devhelp/devhelp.xsl $(srcdir)/libvirt-api.xml ; fi
check-html:
$(XMLLINT) --nonet --noout html/*.html
check-local: check-html
python_generated_files = \
html/libvirt-libvirt-lxc.html \
html/libvirt-libvirt-qemu.html \
html/libvirt-libvirt-admin.html \
html/libvirt-virterror.html \
$(api_DATA) \
$(srcdir)/html/libvirt-libvirt.html \
$(srcdir)/html/libvirt-libvirt-lxc.html \
$(srcdir)/html/libvirt-libvirt-qemu.html \
$(srcdir)/html/libvirt-virterror.html \
$(srcdir)/libvirt-api.xml \
$(srcdir)/libvirt-refs.xml \
$(srcdir)/libvirt-lxc-api.xml \
$(srcdir)/libvirt-lxc-refs.xml \
$(srcdir)/libvirt-qemu-api.xml \
$(srcdir)/libvirt-qemu-refs.xml \
$(NULL)
APIBUILD=$(top_srcdir)/scripts/apibuild.py
APIBUILD_STAMP=apibuild.py.stamp
CLEANFILES += $(APIBUILD_STAMP)
APIBUILD=$(srcdir)/apibuild.py
APIBUILD_STAMP=$(APIBUILD).stamp
EXTRA_DIST += $(APIBUILD_STAMP)
$(python_generated_files): $(APIBUILD_STAMP)
$(APIBUILD_STAMP): $(top_srcdir)/scripts/apibuild.py \
$(top_srcdir)/include/libvirt/libvirt.h \
$(top_srcdir)/include/libvirt/libvirt-common.h.in \
$(top_srcdir)/include/libvirt/libvirt-domain-checkpoint.h \
$(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-checkpoint.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/admin/libvirt-admin.c \
$(top_srcdir)/src/util/virerror.c \
$(top_srcdir)/src/util/virevent.c \
$(top_srcdir)/src/util/virtypedparam-public.c
$(AM_V_GEN)srcdir=$(srcdir) builddir=$(builddir) \
$(RUNUTF8) $(PYTHON) $(APIBUILD)
$(APIBUILD_STAMP): $(srcdir)/apibuild.py \
$(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
maintainer-clean-local: clean-local
rm -rf $(srcdir)/libvirt-api.xml $(srcdir)/libvirt-refs.xml \
todo.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 $(APIBUILD_STAMP)
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)/html
for h in $(apihtml); do \
$(INSTALL) -m 0644 $(srcdir)/$$h $(DESTDIR)$(HTML_DIR)/html; done
for p in $(apipng); do \
$(INSTALL) -m 0644 $(srcdir)/$$p $(DESTDIR)$(HTML_DIR)/html; done
$(mkinstalldirs) $(DESTDIR)$(HTML_DIR)/internals
for f in $(internals_html); do \
$(INSTALL) -m 0644 $(srcdir)/$$f $(DESTDIR)$(HTML_DIR)/internals; done
$(mkinstalldirs) $(DESTDIR)$(DEVHELP_DIR)
for file in $(devhelphtml) $(devhelppng) $(devhelpcss); do \
$(INSTALL) -m 0644 $(srcdir)/$${file} $(DESTDIR)$(DEVHELP_DIR) ; \
done
$(INSTALL_DATA) $(srcdir)/libvirtLogo.png $(DESTDIR)$(pkgdatadir)
uninstall-local:
for h in $(apihtml); do rm $(DESTDIR)$(HTML_DIR)/$$h; done
for p in $(apipng); do rm $(DESTDIR)$(HTML_DIR)/$$p; done
for f in $(devhelphtml) $(devhelppng) $(devhelpcss); do \
rm $(DESTDIR)$(DEVHELP_DIR)/$$(basename $$f); \
done

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>Client access control</h1>
@@ -12,7 +12,7 @@
<ul id="toc"></ul>
<h2><a id="intro">Access control introduction</a></h2>
<h2><a name="intro">Access control introduction</a></h2>
<p>
In a default configuration, the libvirtd daemon has three levels
@@ -42,7 +42,7 @@
<code>getattr</code> permission.
</p>
<h2><a id="drivers">Access control drivers</a></h2>
<h2><a name="drivers">Access control drivers</a></h2>
<p>
The access control framework is designed as a pluggable
@@ -83,14 +83,14 @@
the libvirtd daemon be restarted.
</p>
<h2><a id="perms">Objects and permissions</a></h2>
<h2><a name="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>
<a href="html/libvirt-libvirt.html">API reference manual</a>
documentation for the API in question.
</p>

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>Polkit access control</h1>
@@ -14,7 +14,7 @@
<ul id="toc"></ul>
<h2><a id="intro">Introduction</a></h2>
<h2><a name="intro">Introduction</a></h2>
<p>
A default install of libvirt will typically use
@@ -27,7 +27,7 @@
object.
</p>
<h2><a id="perms">Permission names</a></h2>
<h2><a name="perms">Permission names</a></h2>
<p>
The libvirt <a href="acl.html#perms">object names and permission names</a>
@@ -53,7 +53,7 @@
permissions default to deny access.
</p>
<h2><a id="attrs">Object identity attributes</a></h2>
<h2><a name="attrs">Object identity attributes</a></h2>
<p>
To allow polkit authorization rules to be written to match
@@ -63,8 +63,8 @@
of object being checked
</p>
<h3><a id="object_connect">virConnectPtr</a></h3>
<table>
<h3><a name="object_connect">virConnectPtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
@@ -79,8 +79,8 @@
</tbody>
</table>
<h3><a id="object_domain">virDomainPtr</a></h3>
<table>
<h3><a name="object_domain">virDomainPtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
@@ -103,8 +103,8 @@
</tbody>
</table>
<h3><a id="object_interface">virInterfacePtr</a></h3>
<table>
<h3><a name="object_interface">virInterfacePtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
@@ -121,14 +121,14 @@
<td>Name of the network interface, unique to the local host</td>
</tr>
<tr>
<td>interface_macaddr</td>
<td>interface_mac</td>
<td>MAC address of the network interface, not unique</td>
</tr>
</tbody>
</table>
<h3><a id="object_network">virNetworkPtr</a></h3>
<table>
<h3><a name="object_network">virNetworkPtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
@@ -151,8 +151,8 @@
</tbody>
</table>
<h3><a id="object_node_device">virNodeDevicePtr</a></h3>
<table>
<h3><a name="object_node_device">virNodeDevicePtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
@@ -171,8 +171,8 @@
</tbody>
</table>
<h3><a id="object_nwfilter">virNWFilterPtr</a></h3>
<table>
<h3><a name="object_nwfilter">virNWFilterPtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
@@ -195,8 +195,8 @@
</tbody>
</table>
<h3><a id="object_secret">virSecretPtr</a></h3>
<table>
<h3><a name="object_secret">virSecretPtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
@@ -224,15 +224,11 @@
<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>
<h3><a name="object_storage_pool">virStoragePoolPtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
@@ -255,8 +251,8 @@
</tbody>
</table>
<h3><a id="object_storage_vol">virStorageVolPtr</a></h3>
<table>
<h3><a name="object_storage_vol">virStorageVolPtr</a></h3>
<table class="acl">
<thead>
<tr>
<th>Attribute</th>
@@ -287,113 +283,8 @@
</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>
<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>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>
</tbody>
</table>
<h2><a id="user">User identity attributes</a></h2>
<h2><a name="user">User identity attributes</a></h2>
<p>
At this point in time, the only attribute provided by
@@ -412,7 +303,7 @@
</p>
<h2><a id="checks">Writing access control policies</a></h2>
<h2><a name="checks">Writing access control policies</a></h2>
<p>
If using versions of polkit prior to 0.106 then it is only
@@ -439,9 +330,9 @@
</p>
<pre>
polkit.addRule(function(action, subject) {
....logic to check 'action' and 'subject'...
});
polkit.addRule(function(action, subject) {
....logic to check 'action' and 'subject'...
});
</pre>
<p>
@@ -457,13 +348,7 @@ polkit.addRule(function(action, subject) {
<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>
<h3><a name="exconnect">Example: restricting ability to connect to drivers</a></h3>
<p>
Consider a local user <code>berrange</code>
@@ -491,7 +376,7 @@ polkit.addRule(function(action, subject) {
});
</pre>
<h3><a id="exdomain">Example: restricting access to a single domain</a></h3>
<h3><a name="exdomain">Example: restricting access to a single domain</a></h3>
<p>
Consider a local user <code>berrange</code>
@@ -501,7 +386,7 @@ polkit.addRule(function(action, subject) {
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
attribute is <code>demo</code>, and match on a action
name of <code>org.libvirt.api.domain.getattr</code>. Using
the javascript rules format, this ends up written as
</p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

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>The libvirt API concepts</h1>
@@ -9,14 +9,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 +26,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 +38,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 +90,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 +101,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,46 +144,18 @@
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>
@@ -297,15 +166,11 @@
<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 +190,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,
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>

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>Implementing a new API in Libvirt</h1>
@@ -8,9 +8,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 +27,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 +44,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 +81,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,14 +101,16 @@
separately.
</p>
<h2><a id='publicapi'>Defining the public API</a></h2>
<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
involves an XML extension, you have to enhance the RelaxNG
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 +120,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,7 +133,11 @@
rework it as you go through the process of implementing it.
</p>
<h2><a id='internalapi'>Defining the internal API</a></h2>
<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>
Each public API call is associated with a driver, such as a host
@@ -137,7 +155,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,7 +164,9 @@
provide a <code>NULL</code> stub for the new function.
</p>
<h2><a id='implpublic'>Implementing the public API</a></h2>
<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>
Implementing the public API is largely a formality in which we wire up
@@ -177,17 +197,23 @@
<p>The public API calls are implemented in:</p>
<p><code>src/libvirt-$MODULE.c</code></p>
<p><code>src/libvirt.c</code></p>
<h2><a id='remoteproto'>Implementing the remote protocol</a></h2>
<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>
<h3><a id='wireproto'>Defining the wire protocol format</a></h3>
<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>
Defining the wire protocol involves making additions to:
@@ -219,21 +245,21 @@
</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>
<h3><a id='rpcclient'>Implement the RPC client</a></h3>
<h3><a name='rpcclient'>Implement the RPC client</a></h3>
<p>
Implementing the RPC client uses the rpcgen generated .h files.
The remote method calls go in:
Implementing the uses the rpcgen generated .h files. The remote
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 +273,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 +282,7 @@
The server side dispatchers are implemented in:
</p>
<p><code>src/remote/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 +298,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 +312,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 +339,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 +356,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 +371,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 +384,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

2572
docs/apibuild.py Executable file

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,8 @@
<?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>Applications using libvirt</h1>
<h1>Applications using <strong>libvirt</strong></h1>
<p>
This page provides an illustration of the wide variety of
@@ -11,7 +11,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 +19,35 @@
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="command">Command line tools</a></h2>
<h2><a name="clientserver">Client/Server applications</a></h2>
<dl>
<dt><a href="http://archipelproject.org">Archipel</a></dt>
<dd>
Archipel is a libvirt-based solution to manage and supervise virtual
machines. It uses XMPP for all communication. There is no web
service or custom protocol. You just need at least one XMPP server,
like eJabberd, to start playing with it. This allows Archipel to
work completely real time. You never have to refresh the user
interface, you'll be notified as soon as something happens. You can
even use your favorite chat clients to command your infrastructure.
</dd>
<dd>
Isn't it great to be able to open a chat conversation with your
virtual machine and say things like "How are you today?" or "Hey,
please reboot"?
</dd>
</dl>
<h2><a name="command">Command line tools</a></h2>
<dl>
<dt><a href="http://libguestfs.org">guestfish</a></dt>
@@ -45,21 +62,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
@@ -67,26 +84,26 @@
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>
<dt><a href="http://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
@@ -99,15 +116,9 @@
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>
<dt><a href="https://github.com/virt-lightning/virt-lightning">virt-lightning</a></dt>
<dd>
Virt-Lightning uses libvirt, cloud-init and libguestfs to allow anyone
to quickly start a new VM. Very much like a container CLI, but with a
virtual machine.
</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>
@@ -125,10 +136,10 @@
</dd>
</dl>
<h2><a id="continuousintegration">Continuous Integration</a></h2>
<h2><a name="continuousintegration">Continuous Integration</a></h2>
<dl>
<dt><a href="http://docs.buildbot.net/latest/manual/configuration/workers-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
@@ -138,7 +149,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,
@@ -149,24 +160,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
@@ -180,37 +195,26 @@
</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>
@@ -220,7 +224,17 @@
it easy to benefit from private Cloud Computing technology.
</dd>
<dt><a href="https://github.com/eucalyptus/eucalyptus">Eucalyptus</a></dt>
<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="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
@@ -244,7 +258,7 @@
management.
</dd>
<dt><a href="https://www.openstack.org">OpenStack</a></dt>
<dt><a href="http://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,
@@ -252,29 +266,9 @@
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>
@@ -290,7 +284,7 @@
Windows Registry in Windows guests.
</dd>
<dt><a href="https://sandbox.libvirt.org">libvirt-sandbox</a></dt>
<dt><a href="http://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
@@ -303,14 +297,14 @@
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>.
the <a href="http://libvirt.org/ruby">native ruby bindings</a>.
</dd>
</dl>
<h2><a id="livecd">LiveCD / Appliances</a></h2>
<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
@@ -320,9 +314,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
@@ -331,19 +325,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>.
@@ -351,20 +339,18 @@
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>
<dt><a href="http://community.zenoss.org/docs/DOC-4687">Zenoss</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.
The Zenoss libvirt Zenpack adds support for monitoring virtualization
servers. It has been tested with KVM, QEMU, VMware ESX, and VMware
GSX.
</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
@@ -374,7 +360,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:
@@ -395,10 +381,10 @@
</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
@@ -406,22 +392,14 @@
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>
<dt><a href="http://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
@@ -430,50 +408,16 @@
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="other">Other</a></h2>
<h2><a name="mobile">Mobile applications</a></h2>
<dl>
<dt><a href="https://cuckoosandbox.org/">Cuckoo Sandbox</a></dt>
<dt><a href="https://market.android.com/details?id=vm.manager">VM Manager</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.
VM Manager is VM (libvirt) manager (over SSH) application. VM Manager
is an application for libvirt VM / Domain management over SSH.
Please keep in mind that this software is under heavy development.
</dd>
</dl>

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

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!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>Domain management architecture</h1>
</body>
</html>

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 >libvirt architecture</h1>
@@ -13,38 +13,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 +83,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>

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

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<!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>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>

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

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!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>Node device management architecture</h1>
</body>
</html>

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

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!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>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>

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