[libvirt] FD passing for chardevs and chardev backend multiplexing
by Daniel P. Berrange
Historically libvirt has connected stdout & stderr from QEMU directly to
a plain file (/var/log/libvirt/qemu/$GUESTNAME.log). This has worked
well enough in general, but is susceptible to a guest denial of service
if the guest can cause QEMU to spew messages to stderr. There are enough
places in QEMU and SPICE that still print to stderr that this isn't
very hard to achieve.
So In libvirt 1.3.0 we introduce a new daemon 'virtlogd' which is used
for handling log file writing. When this is used, QEMU's stdout/stderr
will be connected to an anonymous pipe file descriptor, the other end
of which is held by the virtlogd daemon. The virtlogd daemon will only
permit a fixed file size to be created before rotating the log file,
so we no longer have the possibility of unbounded disk usage, which is
nice.
I'm now looking to extend the use of 'virtlogd' to also handle character
devices. OpenStack has historically configured the primary serial port
to log to a file in order to capture kernel boot up messages and later
report them to the user via its API. This serial port file backend is
of course susceptible to the same disk space denial of service. We don't
really want to push file rotation logic into QEMU because that would
involve giving QEMU permission to create / rename files, which is
undesirable from a security POV. We also prefer a solution that ideally
works with existing QEMU builds.
So for this my plan is to stop using the QEMU 'file' backend for char
devs and instead pass across a pre-opened file descriptor, connected
to virtlogd. There is no "officially documented" way to pass in a
file descriptor to QEMU chardevs, but since QEMU uses qemu_open(),
we can make use of the fdset feature to achieve this. eg
eg, consider fd 33 is the write end of a pipe file descriptor
I can (in theory) do
-add-fd set=2,fd=33 -chardev file,id=charserial0,path=/dev/fdset/2
Now in practice this doesn't work, because qmp_chardev_open_file()
passes the O_CREAT|O_TRUNC flags in, which means the qemu_open()
call will fail when using the pipe FD pased in via fdsets.
After more investigation I found it *is* possible to use a socketpair
and a pipe backend though...
-add-fd set=2,fd=33 -chardev pipe,id=charserial0,path=/dev/fdset/2
..because for reasons I don't understand, if QEMU can't open $PATH.in
and $PATH.out, it'll fallback to just opening $PATH in read-write
mode even. AFAICT, this is pretty useless with pipes since they
are unidirectional, but, it works nicely with socketpairs, where
virtlogd has one of the socketpairs and QEMU gets passed the other
via fdset.
I can easily check this works for historical QEMU versions back
to when fdsets support was added to chardevs, but I'm working if
the QEMU maintainers consider this usage acceptable over the long
term, and if so, should we explicitly document it as supported ?
If not, should we introduce a more explicit syntax for passing in
a pre-opened FD for chardevs ? eg
-add-fd set=2,fd=33 -chardev fd,id=charserial0,path=/dev/fdset/2
Or just make -chardev file,id=charserial0,path=/dev/fdset/2 actually
work ?
Or something else ?
OpenStack has a further requirement to allow use of the serial port
as an interactive console, at the same time that it is logging to a
file which is something QEMU can't support at all currently. This
essentially means being able to have multiple chardev backends all
connected to the same serial frontend - specifically we would need
a TCP backend and a file backend concurrently. Again this could be
implemented in QEMU, but we'd prefer something that works with
existing QEMU.
This is not too difficult to achieve with virtlogd really. Instead
of using the QEMU 'tcp' or 'unix' chardev protocol, we'd just always
pass QEMU a pre-opened socketpair, and then leave the TCP/UNIX
socket listening to the virtlogd daemon.
This is portable with existing QEMU versions, but the obvious downside
with this is extra copies in the interactive console path. So might it
be worth exploring the posibility of a chardev multiplexor in QEMU. We
would still pass in a pre-opened socketpair to QEMU for the logging side
of things, but would leave the TCP/UNIX socket listening upto QEMU still.
eg should we make something like this work:
-add-fd set=2,fd=33
-chardev pipe,id=charserial0file,path=/dev/fdset/2
-chardev socket,id=charserial0tcp,host=127.0.0.1,port=9999,telnet,server,nowait
-chardev multiplex,id=charserial0,muxA=charserial0file,muxB=charserial1
-serial isa-serial,chardev=charserial0,id=serial0
Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
9 years
[libvirt] [PATCH v2 00/27] Prepare for specific vcpu hot(un)plug - part 1
by Peter Krempa
This series is getting rather big. The target is to refactor the way libvirt
stores info about vCPUs into a single structure (okay, two structures for the
qemu driver. Part 1 is not yet completely there, well, not even halfway.
Future work will involve fully allocating priv->vcpupids to the maxcpus size
and moving around few other bits of data in cputune and other parts to the new
structure. Yet another follow up work is then to add new APIs for vCPU hotplug,
which will enable adding vCPUs sparsely (useful if you have NUMA).
Since this refactor will result in tracking all vcpu-related data in one struct,
the result will automagically fix a few bugs where we'd end up with invalid
config after vcpu unplug or other operations.
Version 2 does not contain already pushed patches and incorporates feedback from
John's review. Since I've changed quite a few things I'm reposting this.
Peter Krempa (27):
conf: Replace writes to def->maxvcpus with accessor
conf: Use local copy of maxvcpus in virDomainVcpuParse
conf: Extract update of vcpu count if maxvcpus is decreased
conf: Add helper to check whether domain has offline vCPUs
conf: Replace read access to def->maxvcpus with accessor
conf: Replace writes to def->vcpus with accessor
conf: Move vcpu count check into helper
conf: Replace read accesses to def->vcpus with accessor
conf: Turn def->maxvcpus into size_t
qemu: domain: Add helper to access vm->privateData->agent
qemu: Extract vCPU onlining/offlining via agent into a separate
function
qemu: qemuDomainSetVcpusAgent: re-check agent before calling it the
again
qemu: Split up vCPU hotplug and hotunplug
qemu: cpu hotplug: Fix error handling logic
qemu: monitor: Remove weird return values from qemuMonitorSetCPU
qemu: cpu hotplug: Move loops to qemuDomainSetVcpusFlags
qemu: Refactor qemuDomainHotplugVcpus
qemu: refactor qemuDomainHotunplugVcpus
conf: turn def->vcpus into a structure
conf: ABI: Split up and improve vcpu info ABI checking
conf: Add helper to get pointer to a certain vCPU definition
qemu: cgroup: Remove now unreachable check
qemu: Drop checking vcpu threads in emulator bandwidth getter/setter
qemu: Replace checking for vcpu<->pid mapping availability with a
helper
qemu: Add helper to retrieve vCPU pid
qemu: driver: Refactor qemuDomainHelperGetVcpus
qemu: cgroup: Don't use priv->ncpupids to iterate domain vCPUs
src/bhyve/bhyve_command.c | 2 +-
src/bhyve/bhyve_driver.c | 2 +-
src/conf/domain_audit.c | 2 +-
src/conf/domain_conf.c | 190 ++++++++++++---
src/conf/domain_conf.h | 20 +-
src/hyperv/hyperv_driver.c | 10 +-
src/libvirt_private.syms | 6 +
src/libxl/libxl_conf.c | 6 +-
src/libxl/libxl_driver.c | 40 ++--
src/lxc/lxc_controller.c | 2 +-
src/lxc/lxc_driver.c | 2 +-
src/lxc/lxc_native.c | 7 +-
src/openvz/openvz_conf.c | 7 +-
src/openvz/openvz_driver.c | 19 +-
src/phyp/phyp_driver.c | 12 +-
src/qemu/qemu_cgroup.c | 42 ++--
src/qemu/qemu_command.c | 29 ++-
src/qemu/qemu_domain.c | 47 ++++
src/qemu/qemu_domain.h | 4 +
src/qemu/qemu_driver.c | 542 ++++++++++++++++++++++---------------------
src/qemu/qemu_monitor.c | 3 +
src/qemu/qemu_monitor_json.c | 8 -
src/qemu/qemu_monitor_text.c | 23 +-
src/qemu/qemu_process.c | 22 +-
src/test/test_driver.c | 38 +--
src/uml/uml_driver.c | 2 +-
src/vbox/vbox_common.c | 19 +-
src/vmware/vmware_driver.c | 2 +-
src/vmx/vmx.c | 38 +--
src/vz/vz_driver.c | 8 +-
src/vz/vz_sdk.c | 13 +-
src/xen/xm_internal.c | 19 +-
src/xenapi/xenapi_driver.c | 7 +-
src/xenapi/xenapi_utils.c | 6 +-
src/xenconfig/xen_common.c | 16 +-
src/xenconfig/xen_sxpr.c | 27 ++-
36 files changed, 767 insertions(+), 475 deletions(-)
--
2.6.2
9 years
[libvirt] Handling large amount of VF's with intelligent passthrough
by Jan Gutter
Hi,
I've run into a rather interesting problem recently where a weird
interaction between libnl3 and libvirt caused some difficult-to-debug
issues. From libvirt's side, the issue was that a netlink response was
much larger than the pagesize and truncated by libnl3. When
virNetDevLinkDump() calls virNetlinkCommand(), nl_recv() is supposed
to return a rather large structure with information for all the
Virtual Functions. When called in a system where the number of PCIe
Virtual Functions are more than 30 for a given Physical Function, the
netlink response is larger than 4k, meaning that a message is
truncated. Unfortunately libnl3 truncates this silently, meaning that
a cryptic error pops up much later in virNetDevParseVfConfig(),
"missing IFLA_VF_INFO in netlink response".
Aside from the error propagation (which might be fixable in libnl3),
there still remains the need to enable libvirt to function in cases
like this. This can be done in two ways, both in virNetlinkCommand().
1. Message peeking can be enabled. In theory this slows down any
netlink messages by doing a two stage query: query the buffer size,
then allocate the receive buffer and receive the message. This is a
reliability/performance tradeoff, I guess.
This is as simple as adding:
nl_socket_enable_msg_peek(nlhandle);
2. The receive buffer size can also be made larger:
nl_socket_set_msg_buf_size(nlhandle, ARBITRARY_BUFFER_SIZE);
This does not incur a performance penalty, but until libnl3 can
propagate the truncation error, this merely postpones the error for
future generations...
Jan
9 years
[libvirt] [PATCH v3 0/6] Add read error ignore to storage backend vol info APIs
by John Ferlan
v2 here:
http://www.redhat.com/archives/libvir-list/2015-November/thread.html
Based on review and well just the amount of change I figured I'd
generate a v3. The patches were mostly ACK'd, but patch 3 required
removal of some flags which resulted in patch 1 needing updates...
Then I found that what I'd done in patch 3 regarding returning errors
needed to generate a patch 2.5... So I just bit the bullet and am
posting the patches again. Patches 2, 4, and 5 of this series are
unchanged. While patch 1 removes 'readflags' from an API, patch 3
is new, and patch 6 uses the new name.
John Ferlan (6):
storage: Add readflags for backend error processing
storage: Add comments for backend APIs
storage: Set ret = -1 on failures in
virStorageBackendUpdateVolTargetInfo
storage: Handle readflags errors
storage: Add debug message
storage: Ignore block devices that fail format detection
src/storage/storage_backend.c | 83 ++++++++++++++++++++++++++++++-----
src/storage/storage_backend.h | 15 ++++++-
src/storage/storage_backend_disk.c | 5 ++-
src/storage/storage_backend_fs.c | 4 +-
src/storage/storage_backend_logical.c | 2 +-
src/storage/storage_backend_mpath.c | 2 +-
src/storage/storage_backend_scsi.c | 6 ++-
7 files changed, 96 insertions(+), 21 deletions(-)
--
2.5.0
9 years
[libvirt] [PATCH v2] guest-agent-socket: don't generate default path to config XML
by Pavel Hrdina
While we started using for all unix sockets as default one common
directory based on a guest name it introduced several issues, for example
with renaming the guest or cloning it. In general it's not entirely
bad, but in this case it would be best to hide the auto-generated socket
path from user and don't export it in the config XML.
Signed-off-by: Pavel Hrdina <phrdina(a)redhat.com>
---
Version 2:
- removed unnecessary changes
src/qemu/qemu_command.c | 28 ++++++++++++++++++++++++++++
src/qemu/qemu_command.h | 1 +
src/qemu/qemu_domain.c | 16 ----------------
src/qemu/qemu_driver.c | 3 +++
src/qemu/qemu_process.c | 3 +++
tests/qemuhotplugtest.c | 5 +++++
tests/qemuxml2argvtest.c | 5 +++++
7 files changed, 45 insertions(+), 16 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2a9fab5..f1bb621 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1262,6 +1262,34 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
}
+int
+qemuUnixSocketGenerate(virDomainDefPtr def,
+ virQEMUDriverConfigPtr cfg)
+{
+ size_t i;
+
+ for (i = 0; i < def->nchannels; i++) {
+ virDomainChrDefPtr channel = def->channels[i];
+
+ if (channel->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
+ channel->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
+ channel->source.type == VIR_DOMAIN_CHR_TYPE_UNIX &&
+ !channel->source.data.nix.path) {
+ if (virAsprintf(&channel->source.data.nix.path,
+ "%s/domain-%s/%s",
+ cfg->channelTargetDir, def->name,
+ channel->target.name ? channel->target.name
+ : "unknown.sock") < 0)
+ return -1;
+
+ channel->source.data.nix.listen = true;
+ }
+ }
+
+ return 0;
+}
+
+
static void
qemuDomainPrimeVirtioDeviceAddresses(virDomainDefPtr def,
virDomainDeviceAddressType type)
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index bebdd27..0512a23 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -283,6 +283,7 @@ int qemuAssignDevicePCISlots(virDomainDefPtr def,
virDomainPCIAddressSetPtr addrs);
int qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps);
+int qemuUnixSocketGenerate(virDomainDefPtr def, virQEMUDriverConfigPtr cfg);
int qemuDomainNetVLAN(virDomainNetDefPtr def);
int qemuAssignDeviceNetAlias(virDomainDefPtr def, virDomainNetDefPtr net, int idx);
int qemuAssignDeviceDiskAlias(virDomainDefPtr vmdef,
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index ed21245..7e05289 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1329,22 +1329,6 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
ARCH_IS_S390(def->os.arch))
dev->data.controller->model = VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI;
- /* auto generate unix socket path */
- if (dev->type == VIR_DOMAIN_DEVICE_CHR &&
- dev->data.chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
- dev->data.chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
- dev->data.chr->source.type == VIR_DOMAIN_CHR_TYPE_UNIX &&
- !dev->data.chr->source.data.nix.path) {
- if (virAsprintf(&dev->data.chr->source.data.nix.path,
- "%s/domain-%s/%s",
- cfg->channelTargetDir, def->name,
- dev->data.chr->target.name ? dev->data.chr->target.name
- : "unknown.sock") < 0)
- goto cleanup;
-
- dev->data.chr->source.data.nix.listen = true;
- }
-
/* forbid capabilities mode hostdev in this kind of hypervisor */
if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES) {
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ae1d8e7..39f2f03 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7254,6 +7254,9 @@ static char *qemuConnectDomainXMLToNative(virConnectPtr conn,
if (qemuAssignDeviceAliases(def, qemuCaps) < 0)
goto cleanup;
+ if (qemuUnixSocketGenerate(def, cfg) < 0)
+ goto cleanup;
+
if (qemuDomainAssignAddresses(def, qemuCaps, NULL) < 0)
goto cleanup;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 192730c..29cf965 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4663,6 +4663,9 @@ qemuProcessLaunch(virConnectPtr conn,
if (qemuAssignDeviceAliases(vm->def, priv->qemuCaps) < 0)
goto cleanup;
+ if (qemuUnixSocketGenerate(vm->def, cfg) < 0)
+ goto cleanup;
+
/* Get the advisory nodeset from numad if 'placement' of
* either <vcpu> or <numatune> is 'auto'.
*/
diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c
index 102e052..b17cca2 100644
--- a/tests/qemuhotplugtest.c
+++ b/tests/qemuhotplugtest.c
@@ -61,6 +61,7 @@ qemuHotplugCreateObjects(virDomainXMLOptionPtr xmlopt,
{
int ret = -1;
qemuDomainObjPrivatePtr priv = NULL;
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(&driver);
if (!(*vm = virDomainObjNew(xmlopt)))
goto cleanup;
@@ -94,10 +95,14 @@ qemuHotplugCreateObjects(virDomainXMLOptionPtr xmlopt,
if (qemuAssignDeviceAliases((*vm)->def, priv->qemuCaps) < 0)
goto cleanup;
+ if (qemuUnixSocketGenerate((*vm)->def, cfg) < 0)
+ goto cleanup;
+
(*vm)->def->id = QEMU_HOTPLUG_TEST_DOMAIN_ID;
ret = 0;
cleanup:
+ virObjectUnref(cfg);
return ret;
}
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index f7596a0..f6083db 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -262,6 +262,7 @@ static int testCompareXMLToArgvFiles(const char *xml,
virCommandPtr cmd = NULL;
size_t i;
virBitmapPtr nodeset = NULL;
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(&driver);
if (!(conn = virGetConnect()))
goto out;
@@ -324,6 +325,9 @@ static int testCompareXMLToArgvFiles(const char *xml,
if (qemuAssignDeviceAliases(vmdef, extraFlags) < 0)
goto out;
+ if (qemuUnixSocketGenerate(vmdef, cfg) < 0)
+ goto out;
+
for (i = 0; i < vmdef->nhostdevs; i++) {
virDomainHostdevDefPtr hostdev = vmdef->hostdevs[i];
@@ -387,6 +391,7 @@ static int testCompareXMLToArgvFiles(const char *xml,
virCommandFree(cmd);
virDomainDefFree(vmdef);
virObjectUnref(conn);
+ virObjectUnref(cfg);
virBitmapFree(nodeset);
return ret;
}
--
2.6.3
9 years
[libvirt] somtimes libvirtd crashed when fail to start a guest, need help to debug
by Luyao Huang
Dear list,
I met a problem when test with the latest libvirt (build from current master branch), i found sometimes libvirtd crashed when guest fail to start.
the reproduce way is very easy, but hard to meet:
# cat /root/shdo2.sh
#!/bin/sh
while :
do
virsh start rhel7.0-rhel
done
# sh /root/shdo2.sh
...
error: Failed to start domain rhel7.0-rhel
error: internal error: process exited while connecting to monitor: 2015-12-09T06:58:37.785695Z qemu-kvm: -chardev socket,id=charchannel1,path=/var/lib/libvirt/qemu1/rhel7.0-rhel.agent,server,nowait: Failed to bind socket to /var/lib/libvirt/qemu1/rhel7.0-rhel.agent: No such file or directory
error: Failed to start domain rhel7.0-rhel
error: internal error: process exited while connecting to monitor: 2015-12-09T06:58:42.035103Z qemu-kvm: -chardev socket,id=charchannel1,path=/var/lib/libvirt/qemu1/rhel7.0-rhel.agent,server,nowait: Failed to bind socket to /var/lib/libvirt/qemu1/rhel7.0-rhel.agent: No such file or directory
error: Disconnected from qemu:///system due to I/O error
error: Failed to start domain rhel7.0-rhel
error: End of file while reading data: Input/output error
error: One or more references were leaked after disconnect from the hypervisor
error: failed to connect to the hypervisor
error: no valid connection
error: Failed to connect socket to '/var/run/libvirt/libvirt-sock': Connection refused
and here is the bt full output:
http://pastebin.com/sCYHByvP
and here is the valgrind output:
http://pastebin.com/0VXrYTKT
I cannot found what happened, also i am not familiar with virtlogd. could someone please help to debug this ?
Thanks,
Luyao
9 years
[libvirt] [PATCH v2] log: include hostname in initial log message
by Daniel P. Berrange
On the very first log message we send to any output, we include
the libvirt version number and package string. In some bug reports
we have been given libvirtd.log files that came from a different
host than the corresponding /var/log/libvirt/qemu log files. So
extend the initial log message to include the hostname too.
eg on first log message we would now see:
$ libvirtd
2015-12-04 17:35:36.610+0000: 20917: info : libvirt version: 1.3.0
2015-12-04 17:35:36.610+0000: 20917: info : hostname: dhcp-1-180.lcy.redhat.com
2015-12-04 17:35:36.610+0000: 20917: error : qemuMonitorIO:687 : internal error: End of file from monitor
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virlog.c | 72 ++++++++++++++++++++++++++++++++++++------------
src/util/virutil.c | 34 ++++++++++++++++-------
src/util/virutil.h | 1 +
4 files changed, 81 insertions(+), 27 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index dd085c3..f483c4c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2387,6 +2387,7 @@ virGetGroupID;
virGetGroupList;
virGetGroupName;
virGetHostname;
+virGetHostnameQuiet;
virGetListenFDs;
virGetSCSIHostNameByParentaddr;
virGetSCSIHostNumber;
diff --git a/src/util/virlog.c b/src/util/virlog.c
index 627f4cb..7d5a266 100644
--- a/src/util/virlog.c
+++ b/src/util/virlog.c
@@ -94,7 +94,7 @@ static int virLogNbFilters;
* after filtering, multiple output can be used simultaneously
*/
struct _virLogOutput {
- bool logVersion;
+ bool logInitMessage;
void *data;
virLogOutputFunc f;
virLogCloseFunc c;
@@ -402,7 +402,7 @@ virLogDefineOutput(virLogOutputFunc f,
goto cleanup;
}
ret = virLogNbOutputs++;
- virLogOutputs[ret].logVersion = true;
+ virLogOutputs[ret].logInitMessage = true;
virLogOutputs[ret].f = f;
virLogOutputs[ret].c = c;
virLogOutputs[ret].data = data;
@@ -452,6 +452,32 @@ virLogVersionString(const char **rawmsg,
return virLogFormatString(msg, 0, NULL, VIR_LOG_INFO, VIR_LOG_VERSION_STRING);
}
+/* Similar to virGetHostname() but avoids use of error
+ * reporting APIs or logging APIs, to prevent recursion
+ */
+static int
+virLogHostnameString(const char **rawmsg,
+ char **msg)
+{
+ char *hostname = virGetHostnameQuiet();
+ char *hoststr;
+
+ if (!hostname)
+ return -1;
+
+ if (virAsprintfQuiet(&hoststr, "hostname: %s", hostname) < 0) {
+ VIR_FREE(hostname);
+ return -1;
+ }
+
+ if (virLogFormatString(msg, 0, NULL, VIR_LOG_INFO, hoststr) < 0) {
+ VIR_FREE(hoststr);
+ return -1;
+ }
+ *rawmsg = hoststr;
+ return 0;
+}
+
static void
virLogSourceUpdate(virLogSourcePtr source)
@@ -533,7 +559,7 @@ virLogVMessage(virLogSourcePtr source,
const char *fmt,
va_list vargs)
{
- static bool logVersionStderr = true;
+ static bool logInitMessageStderr = true;
char *str = NULL;
char *msg = NULL;
char timestamp[VIR_TIME_STRING_BUFLEN];
@@ -583,16 +609,22 @@ virLogVMessage(virLogSourcePtr source,
*/
for (i = 0; i < virLogNbOutputs; i++) {
if (priority >= virLogOutputs[i].priority) {
- if (virLogOutputs[i].logVersion) {
- const char *rawver;
- char *ver = NULL;
- if (virLogVersionString(&rawver, &ver) >= 0)
+ if (virLogOutputs[i].logInitMessage) {
+ const char *rawinitmsg;
+ char *initmsg = NULL;
+ if (virLogVersionString(&rawinitmsg, &initmsg) >= 0)
+ virLogOutputs[i].f(&virLogSelf, VIR_LOG_INFO,
+ __FILE__, __LINE__, __func__,
+ timestamp, NULL, 0, rawinitmsg, initmsg,
+ virLogOutputs[i].data);
+ VIR_FREE(initmsg);
+ if (virLogHostnameString(&rawinitmsg, &initmsg) >= 0)
virLogOutputs[i].f(&virLogSelf, VIR_LOG_INFO,
__FILE__, __LINE__, __func__,
- timestamp, NULL, 0, rawver, ver,
+ timestamp, NULL, 0, rawinitmsg, initmsg,
virLogOutputs[i].data);
- VIR_FREE(ver);
- virLogOutputs[i].logVersion = false;
+ VIR_FREE(initmsg);
+ virLogOutputs[i].logInitMessage = false;
}
virLogOutputs[i].f(source, priority,
filename, linenr, funcname,
@@ -601,16 +633,22 @@ virLogVMessage(virLogSourcePtr source,
}
}
if (virLogNbOutputs == 0) {
- if (logVersionStderr) {
- const char *rawver;
- char *ver = NULL;
- if (virLogVersionString(&rawver, &ver) >= 0)
+ if (logInitMessageStderr) {
+ const char *rawinitmsg;
+ char *initmsg = NULL;
+ if (virLogVersionString(&rawinitmsg, &initmsg) >= 0)
+ virLogOutputToFd(&virLogSelf, VIR_LOG_INFO,
+ __FILE__, __LINE__, __func__,
+ timestamp, NULL, 0, rawinitmsg, initmsg,
+ (void *) STDERR_FILENO);
+ VIR_FREE(initmsg);
+ if (virLogHostnameString(&rawinitmsg, &initmsg) >= 0)
virLogOutputToFd(&virLogSelf, VIR_LOG_INFO,
__FILE__, __LINE__, __func__,
- timestamp, NULL, 0, rawver, ver,
+ timestamp, NULL, 0, rawinitmsg, initmsg,
(void *) STDERR_FILENO);
- VIR_FREE(ver);
- logVersionStderr = false;
+ VIR_FREE(initmsg);
+ logInitMessageStderr = false;
}
virLogOutputToFd(source, priority,
filename, linenr, funcname,
diff --git a/src/util/virutil.c b/src/util/virutil.c
index fe65faf..e83def1 100644
--- a/src/util/virutil.c
+++ b/src/util/virutil.c
@@ -662,16 +662,17 @@ char *virIndexToDiskName(int idx, const char *prefix)
* we got from getaddrinfo(). Return the value from gethostname()
* and hope for the best.
*/
-char *virGetHostname(void)
+static char *virGetHostnameImpl(bool quiet)
{
int r;
- char hostname[HOST_NAME_MAX+1], *result;
+ char hostname[HOST_NAME_MAX+1], *result = NULL;
struct addrinfo hints, *info;
r = gethostname(hostname, sizeof(hostname));
if (r == -1) {
- virReportSystemError(errno,
- "%s", _("failed to determine host name"));
+ if (!quiet)
+ virReportSystemError(errno,
+ "%s", _("failed to determine host name"));
return NULL;
}
NUL_TERMINATE(hostname);
@@ -683,7 +684,7 @@ char *virGetHostname(void)
* string as-is; it's up to callers to check whether "localhost"
* is allowed.
*/
- ignore_value(VIR_STRDUP(result, hostname));
+ ignore_value(VIR_STRDUP_QUIET(result, hostname));
goto cleanup;
}
@@ -696,9 +697,10 @@ char *virGetHostname(void)
hints.ai_family = AF_UNSPEC;
r = getaddrinfo(hostname, NULL, &hints, &info);
if (r != 0) {
- VIR_WARN("getaddrinfo failed for '%s': %s",
- hostname, gai_strerror(r));
- ignore_value(VIR_STRDUP(result, hostname));
+ if (!quiet)
+ VIR_WARN("getaddrinfo failed for '%s': %s",
+ hostname, gai_strerror(r));
+ ignore_value(VIR_STRDUP_QUIET(result, hostname));
goto cleanup;
}
@@ -711,17 +713,29 @@ char *virGetHostname(void)
* localhost. Ignore the canonicalized name and just return the
* original hostname
*/
- ignore_value(VIR_STRDUP(result, hostname));
+ ignore_value(VIR_STRDUP_QUIET(result, hostname));
else
/* Caller frees this string. */
- ignore_value(VIR_STRDUP(result, info->ai_canonname));
+ ignore_value(VIR_STRDUP_QUIET(result, info->ai_canonname));
freeaddrinfo(info);
cleanup:
+ if (!result) {
+ virReportOOMError();
+ }
return result;
}
+char *virGetHostname(void)
+{
+ return virGetHostnameImpl(false);
+}
+
+char *virGetHostnameQuiet(void)
+{
+ return virGetHostnameImpl(true);
+}
char *
virGetUserDirectory(void)
diff --git a/src/util/virutil.h b/src/util/virutil.h
index 02387e0..535807c 100644
--- a/src/util/virutil.h
+++ b/src/util/virutil.h
@@ -132,6 +132,7 @@ static inline int pthread_sigmask(int how,
# endif
char *virGetHostname(void);
+char *virGetHostnameQuiet(void);
char *virGetUserDirectory(void);
char *virGetUserDirectoryByUID(uid_t uid);
--
2.5.0
9 years
[libvirt] Event after reverting to snapshot
by Dmitry Andreev
Hi,
I'm looking for a way to catch an event about reverting to snapshot.
As I can see in the code there is no lifecycle event if VM state wasn't
changed.
The comment in the code of qemuDomainRevertToSnapshot:
/* We have the following transitions, which create the following
events:
* 1. inactive -> inactive: none
* 2. inactive -> running: EVENT_STARTED
* 3. inactive -> paused: EVENT_STARTED, EVENT_PAUSED
* 4. running -> inactive: EVENT_STOPPED
* 5. running -> running: none
* 6. running -> paused: EVENT_PAUSED
* 7. paused -> inactive: EVENT_STOPPED
* 8. paused -> running: EVENT_RESUMED
* 9. paused -> paused: none
* Also, several transitions occur even if we fail partway through,
* and use of FORCE can cause multiple transitions.
*/
Also there is no VIR_DOMAIN_EVENT_DEFINED event after reverting to
snapshot, even when domain configuration is changed. Isn't that strange?
Checked on stopped VM.
Is there any way to catch event about changes in configuration after
reverting to snapshot.
9 years
[libvirt] [PATCH 0/6] Add multiqueue support for macvtaps
by Michal Privoznik
Some patches are easier to review when showed with --ignore-space-change.
Michal Privoznik (6):
virNetDevMacVLanCreateWithVPortProfile: Turn vnet_hdr into flag
virNetDevMacVLanTapOpen: Slightly rework
virNetDevMacVLanTapOpen: Rework to support multiple FDs
virNetDevMacVLanTapSetup: Rework to support multiple FDs
virNetDevMacVLanCreateWithVPortProfile: Rework to support multiple FDs
qemu: Enable multiqueue for macvtaps
src/lxc/lxc_process.c | 3 +-
src/qemu/qemu_command.c | 61 +++++++++-------
src/qemu/qemu_command.h | 2 +
src/qemu/qemu_hotplug.c | 16 +++--
src/util/virnetdevmacvlan.c | 171 ++++++++++++++++++++++++--------------------
src/util/virnetdevmacvlan.h | 13 ++--
6 files changed, 150 insertions(+), 116 deletions(-)
--
2.4.10
9 years
[libvirt] [PATCH] rpm: explicitly enable & start virlockd/virtlogd sockets on install
by Daniel P. Berrange
When installing the libvirt-daemon RPM, we have a %post rule to
enable the libvirtd.service, virtlockd.socket and virtlogd.socket
files. This is only done, however, when the RPM is first installed,
not when upgrading RPMs.
This adds a separate rule to explicitly enable the virtlockd.socket
and virtlogd.socket units upon RPM upgrade, if libvirtd.service
is marked as enabled. It also adds a rule to start the socket
units if libvirtd.service is running.
The downside with taking this approach is that it is impossible
for a user to have libvirtd.service enabled and disable socket
activation, because we'll re-enable it on every upgrade. Similarly
we'll be starting the socket listeners on every upgrade if libvirtd
is running. This is a pretty nasty thing to have to keep in libvirt
for the long term, given this upgrade problem is a one-time only
pain point.
For this reason I am recommending *NOT* applying this patch to GIT.
Instead, I think we just have to release note the fact that after
upgrading you should enable the virtlockd.socket unit.
---
libvirt.spec.in | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 1f76f24..48e5632 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1703,6 +1703,18 @@ if [ $1 -eq 1 ] ; then
libvirtd.service >/dev/null 2>&1 || :
fi
%endif
+
+# In upgrade scenario we must explicitly enable virtlockd/virtlogd
+# sockets, if libvirtd is already enabled and start them if
+# libvirtd is running, otherwise you'll get failures to start
+# guests
+if [ $1 -ge 1 ] ; then
+ /bin/systemctl is-enabled libvirtd.service 1>/dev/null 2>&1 &&
+ /bin/systemctl enable virtlockd.socket virtlogd.socket
+ /bin/systemctl is-active libvirtd.service 1>/dev/null 2>&1 &&
+ /bin/systemctl start virtlockd.socket virtlogd.socket
+fi
+
%else
%if %{with_cgconfig}
# Starting with Fedora 16/RHEL-7, systemd automounts all cgroups,
--
2.5.0
9 years