2010-12-16 16:10:54 +00:00
|
|
|
/*
|
2014-03-07 13:38:51 +00:00
|
|
|
* qemu_hotplug.c: QEMU device hotplug management
|
2010-12-16 16:10:54 +00:00
|
|
|
*
|
2016-04-01 14:40:23 +00:00
|
|
|
* Copyright (C) 2006-2016 Red Hat, Inc.
|
2010-12-16 16:10:54 +00:00
|
|
|
* 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
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2010-12-16 16:10:54 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "qemu_hotplug.h"
|
2016-02-16 15:24:35 +00:00
|
|
|
#include "qemu_alias.h"
|
2010-12-16 16:10:54 +00:00
|
|
|
#include "qemu_capabilities.h"
|
|
|
|
#include "qemu_domain.h"
|
2016-02-15 18:08:02 +00:00
|
|
|
#include "qemu_domain_address.h"
|
2020-07-20 14:18:57 +00:00
|
|
|
#include "qemu_namespace.h"
|
2010-12-16 16:10:54 +00:00
|
|
|
#include "qemu_command.h"
|
|
|
|
#include "qemu_hostdev.h"
|
2014-09-16 20:50:53 +00:00
|
|
|
#include "qemu_interface.h"
|
2016-04-06 13:57:57 +00:00
|
|
|
#include "qemu_process.h"
|
2016-11-15 15:53:04 +00:00
|
|
|
#include "qemu_security.h"
|
2018-05-16 11:39:22 +00:00
|
|
|
#include "qemu_block.h"
|
2021-05-13 11:05:27 +00:00
|
|
|
#include "qemu_snapshot.h"
|
Move qemu_audit.h helpers into shared code
The LXC and UML drivers can both make use of auditing. Move
the qemu_audit.{c,h} files to src/conf/domain_audit.{c,h}
* src/conf/domain_audit.c: Rename from src/qemu/qemu_audit.c
* src/conf/domain_audit.h: Rename from src/qemu/qemu_audit.h
* src/Makefile.am: Remove qemu_audit.{c,h}, add domain_audit.{c,h}
* src/qemu/qemu_audit.h, src/qemu/qemu_cgroup.c,
src/qemu/qemu_command.c, src/qemu/qemu_driver.c,
src/qemu/qemu_hotplug.c, src/qemu/qemu_migration.c,
src/qemu/qemu_process.c: Update for changed audit API names
2011-07-04 10:56:13 +00:00
|
|
|
#include "domain_audit.h"
|
2014-11-18 23:55:48 +00:00
|
|
|
#include "netdev_bandwidth_conf.h"
|
2010-12-16 16:10:54 +00:00
|
|
|
#include "domain_nwfilter.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
#include "datatypes.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-13 14:52:25 +00:00
|
|
|
#include "virpci.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2013-04-25 16:45:55 +00:00
|
|
|
#include "virprocess.h"
|
2010-12-16 16:10:54 +00:00
|
|
|
#include "qemu_cgroup.h"
|
2010-10-26 14:04:46 +00:00
|
|
|
#include "locking/domain_lock.h"
|
2012-03-28 19:11:09 +00:00
|
|
|
#include "virnetdev.h"
|
|
|
|
#include "virnetdevbridge.h"
|
2012-02-10 21:09:00 +00:00
|
|
|
#include "virnetdevtap.h"
|
2015-03-17 17:46:44 +00:00
|
|
|
#include "virnetdevopenvswitch.h"
|
2015-02-23 20:54:56 +00:00
|
|
|
#include "virnetdevmidonet.h"
|
2012-08-16 15:41:06 +00:00
|
|
|
#include "device_conf.h"
|
2021-01-22 09:36:21 +00:00
|
|
|
#include "storage_source.h"
|
2021-01-21 14:44:53 +00:00
|
|
|
#include "storage_source_conf.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2013-07-11 15:11:02 +00:00
|
|
|
#include "virtime.h"
|
2020-05-14 20:50:59 +00:00
|
|
|
#include "virqemu.h"
|
2010-12-16 16:10:54 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_QEMU
|
2014-02-28 12:16:17 +00:00
|
|
|
|
|
|
|
VIR_LOG_INIT("qemu.qemu_hotplug");
|
|
|
|
|
2015-06-29 14:19:44 +00:00
|
|
|
#define CHANGE_MEDIA_TIMEOUT 5000
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2020-07-09 04:42:21 +00:00
|
|
|
/* Timeout in milliseconds for device removal. PPC64 domains
|
2019-10-18 18:36:32 +00:00
|
|
|
* can experience a bigger delay in unplug operations during
|
|
|
|
* heavy guest activity (vcpu being the most notable case), thus
|
|
|
|
* the timeout for PPC64 is also bigger. */
|
|
|
|
#define QEMU_UNPLUG_TIMEOUT 1000ull * 5
|
|
|
|
#define QEMU_UNPLUG_TIMEOUT_PPC64 1000ull * 10
|
|
|
|
|
2013-07-26 10:18:01 +00:00
|
|
|
|
qemu_hotplug: Fix a rare race condition when detaching a device twice
https://bugzilla.redhat.com/show_bug.cgi?id=1623389
If a device is detached twice from the same domain the following
race condition may happen:
1) The first DetachDevice() call will issue "device_del" on qemu
monitor, but since the DEVICE_DELETED event did not arrive in
time, the API ends claiming "Device detach request sent
successfully".
2) The second DetachDevice() therefore still find the device in
the domain and thus proceeds to detaching it again. It calls
EnterMonitor() and qemuMonitorSend() trying to issue "device_del"
command again. This gets both domain lock and monitor lock
released.
3) At this point, qemu sends us the DEVICE_DELETED event which is
going to be handled by the event loop which ends up calling
qemuDomainSignalDeviceRemoval() to determine who is going to
remove the device from domain definition. Whether it is the
caller that marked the device for removal or whether it is going
to be the event processing thread.
4) Because the device was marked for removal,
qemuDomainSignalDeviceRemoval() returns true, which means the
event is to be processed by the thread that has marked the device
for removal (and is currently still trying to issue "device_del"
command)
5) The thread finally issues the "device_del" command, which
fails (obviously) and therefore it calls
qemuDomainResetDeviceRemoval() to reset the device marking and
quits immediately after, NOT removing any device from the domain
definition.
At this point, the device is still present in the domain
definition but doesn't exist in qemu anymore. Worse, there is no
way to remove it from the domain definition.
Solution is to note down that we've seen the event and if the
second "device_del" fails, not take it as a failure but carry on
with the usual execution.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-14 10:02:52 +00:00
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainResetDeviceRemoval(virDomainObj *vm);
|
qemu_hotplug: Fix a rare race condition when detaching a device twice
https://bugzilla.redhat.com/show_bug.cgi?id=1623389
If a device is detached twice from the same domain the following
race condition may happen:
1) The first DetachDevice() call will issue "device_del" on qemu
monitor, but since the DEVICE_DELETED event did not arrive in
time, the API ends claiming "Device detach request sent
successfully".
2) The second DetachDevice() therefore still find the device in
the domain and thus proceeds to detaching it again. It calls
EnterMonitor() and qemuMonitorSend() trying to issue "device_del"
command again. This gets both domain lock and monitor lock
released.
3) At this point, qemu sends us the DEVICE_DELETED event which is
going to be handled by the event loop which ends up calling
qemuDomainSignalDeviceRemoval() to determine who is going to
remove the device from domain definition. Whether it is the
caller that marked the device for removal or whether it is going
to be the event processing thread.
4) Because the device was marked for removal,
qemuDomainSignalDeviceRemoval() returns true, which means the
event is to be processed by the thread that has marked the device
for removal (and is currently still trying to issue "device_del"
command)
5) The thread finally issues the "device_del" command, which
fails (obviously) and therefore it calls
qemuDomainResetDeviceRemoval() to reset the device marking and
quits immediately after, NOT removing any device from the domain
definition.
At this point, the device is still present in the domain
definition but doesn't exist in qemu anymore. Worse, there is no
way to remove it from the domain definition.
Solution is to note down that we've seen the event and if the
second "device_del" fails, not take it as a failure but carry on
with the usual execution.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-14 10:02:52 +00:00
|
|
|
|
2019-03-12 12:49:24 +00:00
|
|
|
/**
|
|
|
|
* qemuDomainDeleteDevice:
|
|
|
|
* @vm: domain object
|
|
|
|
* @alias: device to remove
|
|
|
|
*
|
|
|
|
* This is a wrapper over qemuMonitorDelDevice() plus enter/exit
|
|
|
|
* monitor calls. This function MUST be used instead of plain
|
|
|
|
* qemuMonitorDelDevice() in all places where @alias represents a
|
|
|
|
* device from domain XML, i.e. caller marks the device for
|
|
|
|
* removal and then calls qemuDomainWaitForDeviceRemoval()
|
|
|
|
* followed by qemuDomainRemove*Device().
|
|
|
|
*
|
|
|
|
* For collateral devices (e.g. extension devices like zPCI) it
|
|
|
|
* is safe to use plain qemuMonitorDelDevice().
|
|
|
|
*
|
|
|
|
* Upon entry, @vm must be locked.
|
|
|
|
*
|
|
|
|
* Returns: 0 on success,
|
|
|
|
* -1 otherwise.
|
|
|
|
*/
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDeleteDevice(virDomainObj *vm,
|
2019-03-12 12:49:24 +00:00
|
|
|
const char *alias)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
|
|
|
virQEMUDriver *driver = priv->driver;
|
2019-03-12 12:49:24 +00:00
|
|
|
int rc;
|
|
|
|
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
|
|
|
|
rc = qemuMonitorDelDevice(priv->mon, alias);
|
|
|
|
|
qemu_hotplug: Fix a rare race condition when detaching a device twice
https://bugzilla.redhat.com/show_bug.cgi?id=1623389
If a device is detached twice from the same domain the following
race condition may happen:
1) The first DetachDevice() call will issue "device_del" on qemu
monitor, but since the DEVICE_DELETED event did not arrive in
time, the API ends claiming "Device detach request sent
successfully".
2) The second DetachDevice() therefore still find the device in
the domain and thus proceeds to detaching it again. It calls
EnterMonitor() and qemuMonitorSend() trying to issue "device_del"
command again. This gets both domain lock and monitor lock
released.
3) At this point, qemu sends us the DEVICE_DELETED event which is
going to be handled by the event loop which ends up calling
qemuDomainSignalDeviceRemoval() to determine who is going to
remove the device from domain definition. Whether it is the
caller that marked the device for removal or whether it is going
to be the event processing thread.
4) Because the device was marked for removal,
qemuDomainSignalDeviceRemoval() returns true, which means the
event is to be processed by the thread that has marked the device
for removal (and is currently still trying to issue "device_del"
command)
5) The thread finally issues the "device_del" command, which
fails (obviously) and therefore it calls
qemuDomainResetDeviceRemoval() to reset the device marking and
quits immediately after, NOT removing any device from the domain
definition.
At this point, the device is still present in the domain
definition but doesn't exist in qemu anymore. Worse, there is no
way to remove it from the domain definition.
Solution is to note down that we've seen the event and if the
second "device_del" fails, not take it as a failure but carry on
with the usual execution.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-14 10:02:52 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
|
|
/* Domain is no longer running. No cleanup needed. */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rc < 0) {
|
|
|
|
/* Deleting device failed. Let's check if DEVICE_DELETED
|
|
|
|
* even arrived. If it did, we need to claim success to
|
|
|
|
* make the caller remove device from domain XML. */
|
|
|
|
|
|
|
|
if (priv->unplug.eventSeen) {
|
|
|
|
/* The event arrived. Return success. */
|
|
|
|
VIR_DEBUG("Detaching of device %s failed, but event arrived", alias);
|
|
|
|
qemuDomainResetDeviceRemoval(vm);
|
|
|
|
rc = 0;
|
|
|
|
} else if (rc == -2) {
|
|
|
|
/* The device does not exist in qemu, but it still
|
|
|
|
* exists in libvirt. Claim success to make caller
|
|
|
|
* qemuDomainWaitForDeviceRemoval(). Otherwise if
|
|
|
|
* domain XML is queried right after detach API the
|
|
|
|
* device would still be there. */
|
|
|
|
VIR_DEBUG("Detaching of device %s failed and no event arrived", alias);
|
|
|
|
rc = 0;
|
|
|
|
}
|
|
|
|
}
|
2019-03-12 12:49:24 +00:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-11-08 11:00:30 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachZPCIDevice(qemuMonitor *mon,
|
|
|
|
virDomainDeviceInfo *info)
|
2018-11-08 11:00:30 +00:00
|
|
|
{
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *devstr_zpci = NULL;
|
2018-11-08 11:00:30 +00:00
|
|
|
|
|
|
|
if (!(devstr_zpci = qemuBuildZPCIDevStr(info)))
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2018-11-08 11:00:30 +00:00
|
|
|
|
|
|
|
if (qemuMonitorAddDevice(mon, devstr_zpci) < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2018-11-08 11:00:30 +00:00
|
|
|
|
2019-09-18 19:53:06 +00:00
|
|
|
return 0;
|
2018-11-08 11:00:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachZPCIDevice(qemuMonitor *mon,
|
|
|
|
virDomainDeviceInfo *info)
|
2018-11-08 11:00:30 +00:00
|
|
|
{
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *zpciAlias = NULL;
|
2018-11-08 11:00:30 +00:00
|
|
|
|
conf: fix zPCI address auto-generation on s390
Let us fix the issues with zPCI address validation and auto-generation
on s390.
Currently, there are two issues with handling the ZPCI address
extension. Firstly, when the uid is to be auto-generated with a
specified fid, .i.e.:
...
<address type='pci'>
<zpci fid='0x0000001f'/>
</address>
...
we expect uid='0x0001' (or the next available uid for the domain).
However, we get a parsing error:
$ virsh define zpci.xml
error: XML error: Invalid PCI address uid='0x0000', must be > 0x0000
and <= 0xffff
Secondly, when the uid is specified explicitly with the invalid
numerical value '0x0000', we actually expect the parsing error above.
However, the domain is being defined and the uid value is silently
changed to a valid value.
The first issue is a bug and the second one is undesired behaviour, and
both issues are related to how we (in-band) signal invalid values for
uid and fid. So let's fix the XML parsing to do validation based on what
is actually specified in the XML.
The first issue is also related to the current code behaviour, which
is, if either uid or fid is specified by the user, it is incorrectly
assumed that both uid and fid are specified. This bug is fixed by
identifying when the user specified ZPCI address is incomplete and
auto-generating the missing ZPCI address.
Signed-off-by: Bjoern Walk <bwalk@linux.ibm.com>
Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Signed-off-by: Shalini Chellathurai Saroja <shalini@linux.ibm.com>
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
2020-06-18 08:25:15 +00:00
|
|
|
zpciAlias = g_strdup_printf("zpci%d", info->addr.pci.zpci.uid.value);
|
2018-11-08 11:00:30 +00:00
|
|
|
|
|
|
|
if (qemuMonitorDelDevice(mon, zpciAlias) < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2018-11-08 11:00:30 +00:00
|
|
|
|
2019-09-18 19:53:06 +00:00
|
|
|
return 0;
|
2018-11-08 11:00:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachExtensionDevice(qemuMonitor *mon,
|
|
|
|
virDomainDeviceInfo *info)
|
2018-11-08 11:00:30 +00:00
|
|
|
{
|
|
|
|
if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
|
|
|
|
info->addr.pci.extFlags == VIR_PCI_ADDRESS_EXTENSION_NONE) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI)
|
|
|
|
return qemuDomainAttachZPCIDevice(mon, info);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachExtensionDevice(qemuMonitor *mon,
|
|
|
|
virDomainDeviceInfo *info)
|
2018-11-08 11:00:30 +00:00
|
|
|
{
|
|
|
|
if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
|
|
|
|
info->addr.pci.extFlags == VIR_PCI_ADDRESS_EXTENSION_NONE) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI)
|
|
|
|
return qemuDomainDetachZPCIDevice(mon, info);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-23 12:50:17 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuHotplugWaitForTrayEject(virDomainObj *vm,
|
|
|
|
virDomainDiskDef *disk)
|
2016-05-23 12:50:17 +00:00
|
|
|
{
|
|
|
|
unsigned long long now;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (virTimeMillisNow(&now) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
while (disk->tray_status != VIR_DOMAIN_DISK_TRAY_OPEN) {
|
|
|
|
if ((rc = virDomainObjWaitUntil(vm, now + CHANGE_MEDIA_TIMEOUT)) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (rc > 0) {
|
2016-05-23 14:32:06 +00:00
|
|
|
/* the caller called qemuMonitorEjectMedia which usually reports an
|
|
|
|
* error. Report the failure in an off-chance that it didn't. */
|
2018-05-05 12:04:21 +00:00
|
|
|
if (virGetLastErrorCode() == VIR_ERR_OK) {
|
2018-07-13 15:55:59 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("timed out waiting to open tray of '%s'"),
|
|
|
|
disk->dst);
|
2016-05-23 14:32:06 +00:00
|
|
|
}
|
2016-05-23 12:50:17 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-08 08:55:30 +00:00
|
|
|
/**
|
2018-07-13 15:44:32 +00:00
|
|
|
* qemuDomainChangeMediaLegacy:
|
2014-08-08 08:55:30 +00:00
|
|
|
* @driver: qemu driver structure
|
|
|
|
* @vm: domain definition
|
|
|
|
* @disk: disk definition to change the source of
|
|
|
|
* @newsrc: new disk source to change to
|
|
|
|
* @force: force the change of media
|
|
|
|
*
|
|
|
|
* Change the media in an ejectable device to the one described by
|
|
|
|
* @newsrc. This function also removes the old source from the
|
|
|
|
* shared device table if appropriate. Note that newsrc is consumed
|
|
|
|
* on success and the old source is freed on success.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error and reports libvirt error
|
|
|
|
*/
|
2018-07-13 15:44:32 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainChangeMediaLegacy(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainDiskDef *disk,
|
|
|
|
virStorageSource *newsrc,
|
2018-07-13 15:44:32 +00:00
|
|
|
bool force)
|
2010-12-16 16:10:54 +00:00
|
|
|
{
|
2019-09-05 12:47:10 +00:00
|
|
|
int rc;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *driveAlias = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
|
|
|
qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
|
2014-08-05 11:43:57 +00:00
|
|
|
const char *format = NULL;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *sourcestr = NULL;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2014-08-05 11:43:57 +00:00
|
|
|
if (!disk->info.alias) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2014-08-05 11:43:57 +00:00
|
|
|
_("missing disk device alias name for %s"), disk->dst);
|
2019-09-05 12:47:10 +00:00
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
|
2018-05-31 09:55:24 +00:00
|
|
|
if (!(driveAlias = qemuAliasDiskDriveFromDisk(disk)))
|
2019-09-05 12:47:10 +00:00
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2016-05-23 12:50:17 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
rc = qemuMonitorEjectMedia(priv->mon, driveAlias, force);
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
2019-09-05 12:47:10 +00:00
|
|
|
return -1;
|
2014-05-19 13:48:43 +00:00
|
|
|
|
2019-02-07 11:17:51 +00:00
|
|
|
/* If the tray is present wait for it to open. */
|
|
|
|
if (!force && diskPriv->tray) {
|
2018-07-13 15:55:59 +00:00
|
|
|
rc = qemuHotplugWaitForTrayEject(vm, disk);
|
2016-07-08 10:30:26 +00:00
|
|
|
if (rc < 0)
|
2019-09-05 12:47:10 +00:00
|
|
|
return -1;
|
2018-07-13 15:55:59 +00:00
|
|
|
|
|
|
|
/* re-issue ejection command to pop out the media */
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
rc = qemuMonitorEjectMedia(priv->mon, driveAlias, false);
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
|
2019-09-05 12:47:10 +00:00
|
|
|
return -1;
|
2018-07-13 15:55:59 +00:00
|
|
|
|
2016-05-23 12:50:17 +00:00
|
|
|
} else {
|
2020-01-24 20:30:04 +00:00
|
|
|
/* otherwise report possible errors from the attempt to eject the media */
|
2016-05-23 12:50:17 +00:00
|
|
|
if (rc < 0)
|
2019-09-05 12:47:10 +00:00
|
|
|
return -1;
|
2016-05-23 12:50:17 +00:00
|
|
|
}
|
2013-05-28 14:23:00 +00:00
|
|
|
|
2015-03-12 15:57:56 +00:00
|
|
|
if (!virStorageSourceIsEmpty(newsrc)) {
|
2018-10-04 12:34:01 +00:00
|
|
|
if (qemuGetDriveSourceString(newsrc, NULL, &sourcestr) < 0)
|
2019-09-05 12:47:10 +00:00
|
|
|
return -1;
|
2014-08-08 08:16:32 +00:00
|
|
|
|
2018-10-04 13:32:37 +00:00
|
|
|
if (virStorageSourceGetActualType(newsrc) != VIR_STORAGE_TYPE_DIR)
|
|
|
|
format = virStorageFileFormatTypeToString(newsrc->format);
|
|
|
|
|
2013-05-20 17:26:14 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2015-06-29 14:19:44 +00:00
|
|
|
rc = qemuMonitorChangeMedia(priv->mon,
|
|
|
|
driveAlias,
|
|
|
|
sourcestr,
|
|
|
|
format);
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
2019-09-05 12:47:10 +00:00
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
2014-08-05 12:09:44 +00:00
|
|
|
|
2015-06-29 14:19:44 +00:00
|
|
|
if (rc < 0)
|
2019-09-05 12:47:10 +00:00
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2019-09-05 12:47:10 +00:00
|
|
|
return 0;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
|
2011-09-13 13:49:50 +00:00
|
|
|
|
2020-02-25 09:55:11 +00:00
|
|
|
/**
|
|
|
|
* qemuHotplugAttachDBusVMState:
|
|
|
|
* @driver: QEMU driver object
|
|
|
|
* @vm: domain object
|
|
|
|
* @asyncJob: asynchronous job identifier
|
|
|
|
*
|
|
|
|
* Add -object dbus-vmstate if necessary.
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error.
|
|
|
|
*/
|
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuHotplugAttachDBusVMState(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
2020-02-25 09:55:11 +00:00
|
|
|
qemuDomainAsyncJob asyncJob)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2020-02-25 09:55:11 +00:00
|
|
|
g_autoptr(virJSONValue) props = NULL;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (priv->dbusVMState)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DBUS_VMSTATE)) {
|
|
|
|
VIR_DEBUG("dbus-vmstate object is not supported by this QEMU binary");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(props = qemuBuildDBusVMStateInfoProps(driver, vm)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
ret = qemuMonitorAddObject(priv->mon, &props, NULL);
|
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
priv->dbusVMState = true;
|
|
|
|
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* qemuHotplugRemoveDBusVMState:
|
|
|
|
* @driver: QEMU driver object
|
|
|
|
* @vm: domain object
|
|
|
|
* @asyncJob: asynchronous job identifier
|
|
|
|
*
|
|
|
|
* Remove -object dbus-vmstate from @vm if the configuration does not require
|
|
|
|
* it any more.
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error.
|
|
|
|
*/
|
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuHotplugRemoveDBusVMState(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
2020-02-25 09:55:11 +00:00
|
|
|
qemuDomainAsyncJob asyncJob)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2020-02-25 09:55:11 +00:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!priv->dbusVMState)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
ret = qemuMonitorDelObject(priv->mon, qemuDomainGetDBusVMStateAlias(), true);
|
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
priv->dbusVMState = false;
|
|
|
|
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-04-23 11:21:03 +00:00
|
|
|
/**
|
2018-07-13 12:14:17 +00:00
|
|
|
* qemuHotplugAttachManagedPR:
|
|
|
|
* @driver: QEMU driver object
|
2018-04-23 11:21:03 +00:00
|
|
|
* @vm: domain object
|
2018-07-13 12:14:17 +00:00
|
|
|
* @src: new disk source to be attached to @vm
|
|
|
|
* @asyncJob: asynchronous job identifier
|
2018-04-23 11:21:03 +00:00
|
|
|
*
|
2018-05-31 11:56:35 +00:00
|
|
|
* Checks if it's needed to start qemu-pr-helper and add the corresponding
|
|
|
|
* pr-manager-helper object.
|
2018-04-23 11:21:03 +00:00
|
|
|
*
|
2018-07-13 12:14:17 +00:00
|
|
|
* Returns: 0 on success, -1 on error.
|
2018-04-23 11:21:03 +00:00
|
|
|
*/
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuHotplugAttachManagedPR(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virStorageSource *src,
|
2018-07-13 12:14:17 +00:00
|
|
|
qemuDomainAsyncJob asyncJob)
|
2018-04-23 11:21:03 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
|
|
|
virJSONValue *props = NULL;
|
2018-07-13 12:14:17 +00:00
|
|
|
bool daemonStarted = false;
|
2018-05-31 11:56:35 +00:00
|
|
|
int ret = -1;
|
2018-07-13 12:14:17 +00:00
|
|
|
int rc;
|
2018-04-23 11:21:03 +00:00
|
|
|
|
2018-05-31 11:56:35 +00:00
|
|
|
if (priv->prDaemonRunning ||
|
2018-07-13 12:14:17 +00:00
|
|
|
!virStorageSourceChainHasManagedPR(src))
|
2018-04-23 11:21:03 +00:00
|
|
|
return 0;
|
|
|
|
|
2018-05-31 11:56:35 +00:00
|
|
|
if (!(props = qemuBuildPRManagedManagerInfoProps(priv)))
|
2018-04-23 11:21:03 +00:00
|
|
|
return -1;
|
|
|
|
|
2018-05-31 11:56:35 +00:00
|
|
|
if (qemuProcessStartManagedPRDaemon(vm) < 0)
|
|
|
|
goto cleanup;
|
2018-04-23 11:21:03 +00:00
|
|
|
|
2018-07-13 12:14:17 +00:00
|
|
|
daemonStarted = true;
|
|
|
|
|
|
|
|
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
rc = qemuMonitorAddObject(priv->mon, &props, NULL);
|
|
|
|
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-05-31 11:56:35 +00:00
|
|
|
ret = 0;
|
2018-05-31 11:29:45 +00:00
|
|
|
|
2018-05-31 11:56:35 +00:00
|
|
|
cleanup:
|
2018-07-13 12:14:17 +00:00
|
|
|
if (ret < 0 && daemonStarted)
|
|
|
|
qemuProcessKillManagedPRDaemon(vm);
|
2018-05-31 11:56:35 +00:00
|
|
|
virJSONValueFree(props);
|
|
|
|
return ret;
|
2018-04-23 11:21:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-11 12:24:49 +00:00
|
|
|
/**
|
|
|
|
* qemuHotplugRemoveManagedPR:
|
|
|
|
* @driver: QEMU driver object
|
|
|
|
* @vm: domain object
|
|
|
|
* @asyncJob: asynchronous job identifier
|
|
|
|
*
|
|
|
|
* Removes the managed PR object from @vm if the configuration does not require
|
|
|
|
* it any more.
|
|
|
|
*/
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuHotplugRemoveManagedPR(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
2018-07-11 12:24:49 +00:00
|
|
|
qemuDomainAsyncJob asyncJob)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2018-07-11 12:24:49 +00:00
|
|
|
virErrorPtr orig_err;
|
2018-07-23 13:38:02 +00:00
|
|
|
int ret = -1;
|
2018-07-11 12:24:49 +00:00
|
|
|
|
2019-03-21 12:54:20 +00:00
|
|
|
if (qemuDomainDefHasManagedPR(vm))
|
2018-07-11 12:24:49 +00:00
|
|
|
return 0;
|
|
|
|
|
2018-07-23 13:38:02 +00:00
|
|
|
virErrorPreserveLast(&orig_err);
|
|
|
|
|
2018-07-11 12:24:49 +00:00
|
|
|
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
2018-07-23 13:38:02 +00:00
|
|
|
goto cleanup;
|
2020-03-18 11:24:40 +00:00
|
|
|
ignore_value(qemuMonitorDelObject(priv->mon, qemuDomainGetManagedPRAlias(),
|
|
|
|
false));
|
2018-07-11 12:24:49 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
2018-07-23 13:38:02 +00:00
|
|
|
goto cleanup;
|
2018-07-11 12:24:49 +00:00
|
|
|
|
|
|
|
qemuProcessKillManagedPRDaemon(vm);
|
|
|
|
|
2018-07-23 13:38:02 +00:00
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virErrorRestore(&orig_err);
|
|
|
|
return ret;
|
2018-07-11 12:24:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-13 16:06:09 +00:00
|
|
|
/**
|
|
|
|
* qemuDomainChangeMediaBlockdev:
|
|
|
|
* @driver: qemu driver structure
|
|
|
|
* @vm: domain definition
|
|
|
|
* @disk: disk definition to change the source of
|
2018-10-04 15:56:46 +00:00
|
|
|
* @oldsrc: old source definition
|
2018-07-13 16:06:09 +00:00
|
|
|
* @newsrc: new disk source to change to
|
|
|
|
* @force: force the change of media
|
|
|
|
*
|
|
|
|
* Change the media in an ejectable device to the one described by
|
|
|
|
* @newsrc. This function also removes the old source from the
|
|
|
|
* shared device table if appropriate. Note that newsrc is consumed
|
|
|
|
* on success and the old source is freed on success.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error and reports libvirt error
|
|
|
|
*/
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainChangeMediaBlockdev(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainDiskDef *disk,
|
|
|
|
virStorageSource *oldsrc,
|
|
|
|
virStorageSource *newsrc,
|
2018-07-13 16:06:09 +00:00
|
|
|
bool force)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
|
|
|
qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(qemuBlockStorageSourceChainData) newbackend = NULL;
|
|
|
|
g_autoptr(qemuBlockStorageSourceChainData) oldbackend = NULL;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *nodename = NULL;
|
2018-07-13 16:06:09 +00:00
|
|
|
int rc;
|
|
|
|
|
2018-10-04 15:56:46 +00:00
|
|
|
if (!virStorageSourceIsEmpty(oldsrc) &&
|
2019-04-05 11:54:48 +00:00
|
|
|
!(oldbackend = qemuBlockStorageSourceChainDetachPrepareBlockdev(oldsrc)))
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2018-07-13 16:06:09 +00:00
|
|
|
|
2018-10-04 15:56:46 +00:00
|
|
|
if (!virStorageSourceIsEmpty(newsrc)) {
|
2019-04-05 11:54:48 +00:00
|
|
|
if (!(newbackend = qemuBuildStorageSourceChainAttachPrepareBlockdev(newsrc,
|
|
|
|
priv->qemuCaps)))
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2018-07-13 16:06:09 +00:00
|
|
|
|
|
|
|
if (qemuDomainDiskGetBackendAlias(disk, priv->qemuCaps, &nodename) < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2018-07-13 16:06:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (diskPriv->tray && disk->tray_status != VIR_DOMAIN_DISK_TRAY_OPEN) {
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
rc = qemuMonitorBlockdevTrayOpen(priv->mon, diskPriv->qomName, force);
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2018-07-13 16:06:09 +00:00
|
|
|
|
|
|
|
if (!force && qemuHotplugWaitForTrayEject(vm, disk) < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2018-07-13 16:06:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
|
|
|
|
rc = qemuMonitorBlockdevMediumRemove(priv->mon, diskPriv->qomName);
|
|
|
|
|
|
|
|
if (rc == 0 && oldbackend)
|
2019-04-05 11:54:48 +00:00
|
|
|
qemuBlockStorageSourceChainDetach(priv->mon, oldbackend);
|
2018-07-13 16:06:09 +00:00
|
|
|
|
|
|
|
if (newbackend && nodename) {
|
|
|
|
if (rc == 0)
|
2019-04-05 11:54:48 +00:00
|
|
|
rc = qemuBlockStorageSourceChainAttach(priv->mon, newbackend);
|
2018-07-13 16:06:09 +00:00
|
|
|
|
|
|
|
if (rc == 0)
|
|
|
|
rc = qemuMonitorBlockdevMediumInsert(priv->mon, diskPriv->qomName,
|
|
|
|
nodename);
|
|
|
|
}
|
|
|
|
|
2021-01-05 11:06:32 +00:00
|
|
|
/* set throttling for the new image */
|
|
|
|
if (rc == 0 &&
|
|
|
|
!virStorageSourceIsEmpty(newsrc) &&
|
|
|
|
qemuDiskConfigBlkdeviotuneEnabled(disk)) {
|
|
|
|
rc = qemuMonitorSetBlockIoThrottle(priv->mon, NULL,
|
|
|
|
diskPriv->qomName,
|
|
|
|
&disk->blkdeviotune,
|
|
|
|
true, true, true);
|
|
|
|
}
|
|
|
|
|
2018-07-13 16:06:09 +00:00
|
|
|
if (rc == 0)
|
|
|
|
rc = qemuMonitorBlockdevTrayClose(priv->mon, diskPriv->qomName);
|
|
|
|
|
2019-03-28 14:59:38 +00:00
|
|
|
if (rc < 0 && newbackend)
|
|
|
|
qemuBlockStorageSourceChainDetach(priv->mon, newbackend);
|
|
|
|
|
2018-07-13 16:06:09 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2018-07-13 16:06:09 +00:00
|
|
|
|
2019-09-18 19:53:06 +00:00
|
|
|
return 0;
|
2018-07-13 16:06:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-13 15:44:32 +00:00
|
|
|
/**
|
|
|
|
* qemuDomainChangeEjectableMedia:
|
|
|
|
* @driver: qemu driver structure
|
|
|
|
* @vm: domain definition
|
|
|
|
* @disk: disk definition to change the source of
|
|
|
|
* @newsrc: new disk source to change to
|
|
|
|
* @force: force the change of media
|
|
|
|
*
|
|
|
|
* Change the media in an ejectable device to the one described by
|
|
|
|
* @newsrc. This function also removes the old source from the
|
|
|
|
* shared device table if appropriate. Note that newsrc is consumed
|
|
|
|
* on success and the old source is freed on success.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error and reports libvirt error
|
|
|
|
*/
|
2018-09-25 12:21:27 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainChangeEjectableMedia(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainDiskDef *disk,
|
|
|
|
virStorageSource *newsrc,
|
2018-07-13 15:44:32 +00:00
|
|
|
bool force)
|
|
|
|
{
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
|
|
|
virStorageSource *oldsrc = disk->src;
|
|
|
|
qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
|
2018-09-25 12:47:36 +00:00
|
|
|
bool sharedAdded = false;
|
2020-03-18 10:44:01 +00:00
|
|
|
bool managedpr = virStorageSourceChainHasManagedPR(oldsrc) ||
|
|
|
|
virStorageSourceChainHasManagedPR(newsrc);
|
2018-07-13 15:44:32 +00:00
|
|
|
int ret = -1;
|
|
|
|
int rc;
|
|
|
|
|
2019-03-28 11:23:43 +00:00
|
|
|
if (diskPriv->blockjob && qemuBlockJobIsRunning(diskPriv->blockjob)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("can't change media while a block job is running on the device"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-09-27 14:50:55 +00:00
|
|
|
disk->src = newsrc;
|
|
|
|
|
2018-09-25 12:47:36 +00:00
|
|
|
if (virDomainDiskTranslateSourcePool(disk) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuAddSharedDisk(driver, disk, vm->def->name) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
sharedAdded = true;
|
|
|
|
|
2019-01-16 14:33:07 +00:00
|
|
|
if (qemuDomainDetermineDiskChain(driver, vm, disk, NULL, true) < 0)
|
2018-09-25 12:47:36 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2018-09-27 14:50:55 +00:00
|
|
|
if (qemuDomainPrepareDiskSource(disk, priv, cfg) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2019-04-18 08:18:51 +00:00
|
|
|
if (qemuDomainStorageSourceChainAccessAllow(driver, vm, newsrc) < 0)
|
2018-07-13 15:44:32 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2018-07-13 16:37:43 +00:00
|
|
|
if (qemuHotplugAttachManagedPR(driver, vm, newsrc, QEMU_ASYNC_JOB_NONE) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-07-13 16:06:09 +00:00
|
|
|
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV))
|
2018-09-27 14:50:55 +00:00
|
|
|
rc = qemuDomainChangeMediaBlockdev(driver, vm, disk, oldsrc, newsrc, force);
|
2018-07-13 16:06:09 +00:00
|
|
|
else
|
|
|
|
rc = qemuDomainChangeMediaLegacy(driver, vm, disk, newsrc, force);
|
2018-07-13 15:44:32 +00:00
|
|
|
|
2018-09-27 14:50:55 +00:00
|
|
|
virDomainAuditDisk(vm, oldsrc, newsrc, "update", rc >= 0);
|
2018-07-13 15:44:32 +00:00
|
|
|
|
2018-09-25 12:47:36 +00:00
|
|
|
if (rc < 0)
|
2018-07-13 15:44:32 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* remove the old source from shared device list */
|
2018-09-27 14:50:55 +00:00
|
|
|
disk->src = oldsrc;
|
2018-07-13 15:44:32 +00:00
|
|
|
ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name));
|
2019-04-18 08:18:51 +00:00
|
|
|
ignore_value(qemuDomainStorageSourceChainAccessRevoke(driver, vm, oldsrc));
|
2018-07-13 15:44:32 +00:00
|
|
|
|
2018-09-27 14:50:55 +00:00
|
|
|
/* media was changed, so we can remove the old media definition now */
|
2019-02-15 12:03:58 +00:00
|
|
|
virObjectUnref(oldsrc);
|
2018-09-27 14:50:55 +00:00
|
|
|
oldsrc = NULL;
|
|
|
|
disk->src = newsrc;
|
2018-07-13 16:37:43 +00:00
|
|
|
|
2018-07-13 15:44:32 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2018-09-25 12:47:36 +00:00
|
|
|
/* undo changes to the new disk */
|
|
|
|
if (ret < 0) {
|
|
|
|
if (sharedAdded)
|
|
|
|
ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name));
|
|
|
|
|
2019-04-18 08:18:51 +00:00
|
|
|
ignore_value(qemuDomainStorageSourceChainAccessRevoke(driver, vm, newsrc));
|
2018-09-25 12:47:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* remove PR manager object if unneeded */
|
2020-03-18 10:44:01 +00:00
|
|
|
if (managedpr)
|
|
|
|
ignore_value(qemuHotplugRemoveManagedPR(driver, vm, QEMU_ASYNC_JOB_NONE));
|
2018-09-25 12:47:36 +00:00
|
|
|
|
|
|
|
/* revert old image do the disk definition */
|
2018-09-27 14:50:55 +00:00
|
|
|
if (oldsrc)
|
|
|
|
disk->src = oldsrc;
|
|
|
|
|
2018-07-13 15:44:32 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-13 11:05:27 +00:00
|
|
|
static qemuSnapshotDiskContext *
|
|
|
|
qemuDomainAttachDiskGenericTransient(virDomainObj *vm,
|
|
|
|
virDomainDiskDef *disk,
|
2021-05-18 14:18:53 +00:00
|
|
|
GHashTable *blockNamedNodeData,
|
|
|
|
qemuDomainAsyncJob asyncJob)
|
2021-05-13 11:05:27 +00:00
|
|
|
{
|
|
|
|
g_autoptr(qemuSnapshotDiskContext) snapctxt = NULL;
|
|
|
|
g_autoptr(virDomainSnapshotDiskDef) snapdiskdef = NULL;
|
|
|
|
|
2021-05-26 20:19:22 +00:00
|
|
|
if (!(snapdiskdef = qemuSnapshotGetTransientDiskDef(disk, vm->def->name)))
|
|
|
|
return NULL;
|
|
|
|
|
2021-05-18 14:18:53 +00:00
|
|
|
snapctxt = qemuSnapshotDiskContextNew(1, vm, asyncJob);
|
2021-05-13 11:05:27 +00:00
|
|
|
|
|
|
|
if (qemuSnapshotDiskPrepareOne(snapctxt, disk, snapdiskdef,
|
|
|
|
blockNamedNodeData, false, false) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return g_steal_pointer(&snapctxt);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-18 15:17:45 +00:00
|
|
|
/**
|
|
|
|
* qemuDomainAttachDiskGeneric:
|
|
|
|
*
|
|
|
|
* Attaches disk to a VM. This function aggregates common code for all bus types.
|
|
|
|
* In cases when the VM crashed while adding the disk, -2 is returned. */
|
2021-05-18 14:19:52 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachDiskGeneric(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
2021-05-18 14:18:53 +00:00
|
|
|
virDomainDiskDef *disk,
|
|
|
|
qemuDomainAsyncJob asyncJob)
|
2010-12-16 16:10:54 +00:00
|
|
|
{
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(qemuBlockStorageSourceChainData) data = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *devstr = NULL;
|
2019-09-05 13:09:50 +00:00
|
|
|
bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
|
2021-05-12 11:10:49 +00:00
|
|
|
bool extensionDeviceAttached = false;
|
|
|
|
int rc;
|
2021-05-13 11:05:27 +00:00
|
|
|
g_autoptr(qemuSnapshotDiskContext) transientDiskSnapshotCtxt = NULL;
|
|
|
|
bool origReadonly = disk->src->readonly;
|
|
|
|
|
|
|
|
if (disk->transient)
|
|
|
|
disk->src->readonly = true;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2021-02-01 11:00:35 +00:00
|
|
|
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
|
|
|
if (!(data = qemuBuildStorageSourceChainAttachPrepareChardev(disk)))
|
2021-05-20 15:16:39 +00:00
|
|
|
return -1;
|
2021-02-01 11:00:35 +00:00
|
|
|
} else if (blockdev) {
|
2021-05-07 12:50:23 +00:00
|
|
|
if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdev(disk->src,
|
|
|
|
priv->qemuCaps)))
|
2021-05-20 15:16:39 +00:00
|
|
|
return -1;
|
2021-05-07 12:50:23 +00:00
|
|
|
|
2020-02-06 11:14:32 +00:00
|
|
|
if (disk->copy_on_read == VIR_TRISTATE_SWITCH_ON) {
|
2021-05-07 12:50:23 +00:00
|
|
|
if (!(data->copyOnReadProps = qemuBlockStorageGetCopyOnReadProps(disk)))
|
2021-05-20 15:16:39 +00:00
|
|
|
return -1;
|
2020-02-06 11:14:32 +00:00
|
|
|
|
2021-05-07 12:50:23 +00:00
|
|
|
data->copyOnReadNodename = g_strdup(QEMU_DOMAIN_DISK_PRIVATE(disk)->nodeCopyOnRead);
|
2020-02-06 11:14:32 +00:00
|
|
|
}
|
2019-03-28 15:04:55 +00:00
|
|
|
|
2019-04-04 15:10:27 +00:00
|
|
|
} else {
|
2020-05-04 17:21:55 +00:00
|
|
|
if (!(data = qemuBuildStorageSourceChainAttachPrepareDrive(disk,
|
2019-04-04 15:10:27 +00:00
|
|
|
priv->qemuCaps)))
|
2021-05-20 15:16:39 +00:00
|
|
|
return -1;
|
2019-04-04 15:10:27 +00:00
|
|
|
}
|
2016-04-26 11:51:41 +00:00
|
|
|
|
2021-05-13 11:05:27 +00:00
|
|
|
disk->src->readonly = origReadonly;
|
|
|
|
|
2021-05-18 14:18:53 +00:00
|
|
|
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
|
|
|
return -1;
|
2018-05-31 11:56:35 +00:00
|
|
|
|
2021-05-12 11:10:49 +00:00
|
|
|
rc = qemuBlockStorageSourceChainAttach(priv->mon, data);
|
2016-04-11 13:16:54 +00:00
|
|
|
|
2021-05-21 08:34:55 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
return -2;
|
|
|
|
|
|
|
|
if (rc < 0)
|
|
|
|
goto rollback;
|
|
|
|
|
2021-05-13 11:05:27 +00:00
|
|
|
if (disk->transient) {
|
|
|
|
g_autoptr(qemuBlockStorageSourceAttachData) backend = NULL;
|
|
|
|
g_autoptr(GHashTable) blockNamedNodeData = NULL;
|
|
|
|
|
2021-05-18 14:18:53 +00:00
|
|
|
if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, asyncJob)))
|
2021-05-13 11:05:27 +00:00
|
|
|
goto rollback;
|
|
|
|
|
2021-05-18 14:18:53 +00:00
|
|
|
if (!(transientDiskSnapshotCtxt = qemuDomainAttachDiskGenericTransient(vm, disk, blockNamedNodeData, asyncJob)))
|
2021-05-13 11:05:27 +00:00
|
|
|
goto rollback;
|
|
|
|
|
|
|
|
|
|
|
|
if (qemuSnapshotDiskCreate(transientDiskSnapshotCtxt) < 0)
|
|
|
|
goto rollback;
|
|
|
|
|
|
|
|
QEMU_DOMAIN_DISK_PRIVATE(disk)->transientOverlayCreated = true;
|
|
|
|
backend = qemuBlockStorageSourceDetachPrepare(disk->src, NULL);
|
|
|
|
ignore_value(VIR_INSERT_ELEMENT(data->srcdata, 0, data->nsrcdata, backend));
|
|
|
|
}
|
|
|
|
|
2021-05-21 08:34:55 +00:00
|
|
|
if (!(devstr = qemuBuildDiskDeviceStr(vm->def, disk, priv->qemuCaps)))
|
|
|
|
goto rollback;
|
|
|
|
|
2021-05-18 14:18:53 +00:00
|
|
|
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
|
|
|
goto rollback;
|
2021-05-21 08:34:55 +00:00
|
|
|
|
|
|
|
if ((rc = qemuDomainAttachExtensionDevice(priv->mon, &disk->info)) == 0)
|
2021-05-12 11:10:49 +00:00
|
|
|
extensionDeviceAttached = true;
|
2018-11-08 11:00:30 +00:00
|
|
|
|
2021-05-12 11:10:49 +00:00
|
|
|
if (rc == 0)
|
|
|
|
rc = qemuMonitorAddDevice(priv->mon, devstr);
|
2016-04-11 13:16:54 +00:00
|
|
|
|
2019-09-05 13:09:50 +00:00
|
|
|
/* Setup throttling of disk via block_set_io_throttle QMP command. This
|
|
|
|
* is a hack until the 'throttle' blockdev driver will support modification
|
|
|
|
* of the trhottle group. See also qemuProcessSetupDiskThrottlingBlockdev.
|
|
|
|
* As there isn't anything sane to do if this fails, let's just return
|
|
|
|
* success.
|
|
|
|
*/
|
2021-05-12 11:10:49 +00:00
|
|
|
if (blockdev && rc == 0 &&
|
2019-09-05 13:09:50 +00:00
|
|
|
qemuDiskConfigBlkdeviotuneEnabled(disk)) {
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
|
2019-09-05 13:09:50 +00:00
|
|
|
if (qemuMonitorSetBlockIoThrottle(priv->mon, NULL, diskPriv->qomName,
|
|
|
|
&disk->blkdeviotune,
|
|
|
|
true, true, true) < 0)
|
|
|
|
VIR_WARN("failed to set blkdeviotune for '%s' of '%s'", disk->dst, vm->def->name);
|
|
|
|
}
|
|
|
|
|
2021-05-20 15:16:39 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
return -2;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2021-05-12 11:10:49 +00:00
|
|
|
if (rc < 0)
|
|
|
|
goto rollback;
|
|
|
|
|
2021-05-20 15:16:39 +00:00
|
|
|
return 0;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2021-05-12 11:10:49 +00:00
|
|
|
rollback:
|
2021-05-18 14:18:53 +00:00
|
|
|
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
|
|
|
return -1;
|
2021-05-12 11:10:49 +00:00
|
|
|
|
|
|
|
if (extensionDeviceAttached)
|
|
|
|
ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &disk->info));
|
|
|
|
|
2019-04-04 15:10:27 +00:00
|
|
|
qemuBlockStorageSourceChainDetach(priv->mon, data);
|
2018-05-16 11:39:22 +00:00
|
|
|
|
2017-02-22 17:39:17 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
2021-05-20 15:16:39 +00:00
|
|
|
return -2;
|
2019-06-18 13:28:26 +00:00
|
|
|
|
2021-05-20 15:16:39 +00:00
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
int qemuDomainAttachControllerDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainControllerDef *controller)
|
2010-12-16 16:10:54 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
const char* type = virDomainControllerTypeToString(controller->type);
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *devstr = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2016-09-07 16:29:30 +00:00
|
|
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_CONTROLLER,
|
|
|
|
{ .controller = controller } };
|
2011-04-26 03:40:01 +00:00
|
|
|
bool releaseaddr = false;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2015-12-09 16:27:12 +00:00
|
|
|
if (controller->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("'%s' controller cannot be hot plugged."),
|
|
|
|
virDomainControllerTypeToString(controller->type));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-05-10 17:14:32 +00:00
|
|
|
/* default idx would normally be set by virDomainDefPostParse(),
|
|
|
|
* which isn't called in the case of live attach of a single
|
|
|
|
* device.
|
|
|
|
*/
|
|
|
|
if (controller->idx == -1)
|
|
|
|
controller->idx = virDomainControllerFindUnusedIndex(vm->def,
|
|
|
|
controller->type);
|
|
|
|
|
2013-09-24 08:03:15 +00:00
|
|
|
if (virDomainControllerFind(vm->def, controller->type, controller->idx) >= 0) {
|
2012-07-23 08:18:57 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("target %s:%d already exists"),
|
|
|
|
type, controller->idx);
|
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
|
2021-06-11 14:25:48 +00:00
|
|
|
if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev) < 0)
|
2017-10-12 12:53:27 +00:00
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2021-03-30 14:35:45 +00:00
|
|
|
if (qemuAssignDeviceControllerAlias(vm->def, controller) < 0)
|
2016-04-26 13:15:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2019-01-15 15:31:54 +00:00
|
|
|
if (qemuBuildControllerDevStr(vm->def, controller, priv->qemuCaps, &devstr) < 0)
|
2017-02-28 09:46:30 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!devstr)
|
2016-04-26 13:15:03 +00:00
|
|
|
goto cleanup;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2021-03-19 23:37:05 +00:00
|
|
|
VIR_REALLOC_N(vm->def->controllers, vm->def->ncontrollers+1);
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2013-02-06 18:17:20 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2018-11-08 11:00:30 +00:00
|
|
|
|
|
|
|
if ((ret = qemuDomainAttachExtensionDevice(priv->mon,
|
|
|
|
&controller->info)) < 0) {
|
|
|
|
goto exit_monitor;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ret = qemuMonitorAddDevice(priv->mon, devstr)) < 0)
|
|
|
|
ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &controller->info));
|
|
|
|
|
|
|
|
exit_monitor:
|
2015-01-07 12:12:18 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
|
|
releaseaddr = false;
|
|
|
|
ret = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2017-10-12 13:06:56 +00:00
|
|
|
if (ret == 0)
|
2010-12-16 16:10:54 +00:00
|
|
|
virDomainControllerInsertPreAlloced(vm->def, controller);
|
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
cleanup:
|
2013-07-09 20:30:57 +00:00
|
|
|
if (ret != 0 && releaseaddr)
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &controller->info);
|
2010-12-16 16:10:54 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static virDomainControllerDef *
|
|
|
|
qemuDomainFindOrCreateSCSIDiskController(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
2011-05-04 12:09:09 +00:00
|
|
|
int controller)
|
2010-12-16 16:10:54 +00:00
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/qemu files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainControllerDef *cont;
|
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2017-12-04 19:33:30 +00:00
|
|
|
int model = -1;
|
2011-05-04 12:09:09 +00:00
|
|
|
|
2013-05-21 07:21:20 +00:00
|
|
|
for (i = 0; i < vm->def->ncontrollers; i++) {
|
2010-12-16 16:10:54 +00:00
|
|
|
cont = vm->def->controllers[i];
|
|
|
|
|
|
|
|
if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (cont->idx == controller)
|
|
|
|
return cont;
|
2017-12-04 19:33:30 +00:00
|
|
|
|
|
|
|
/* Because virDomainHostdevAssignAddress called during
|
|
|
|
* virDomainHostdevDefPostParse cannot add a new controller
|
|
|
|
* it will assign a controller index to a controller that doesn't
|
|
|
|
* exist leaving this code to perform the magic of adding the
|
|
|
|
* controller. Because that code would be attempting to add a
|
|
|
|
* SCSI disk to an existing controller, let's save the model
|
|
|
|
* of the "last" SCSI controller we find so that if we end up
|
|
|
|
* creating a controller below it uses the same controller model. */
|
|
|
|
model = cont->model;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* No SCSI controller present, for backward compatibility we
|
|
|
|
* now hotplug a controller */
|
2020-10-05 10:28:26 +00:00
|
|
|
cont = g_new0(virDomainControllerDef, 1);
|
2010-12-16 16:10:54 +00:00
|
|
|
cont->type = VIR_DOMAIN_CONTROLLER_TYPE_SCSI;
|
2011-01-31 07:55:40 +00:00
|
|
|
cont->idx = controller;
|
2018-02-14 10:51:26 +00:00
|
|
|
if (model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DEFAULT)
|
2018-01-30 22:29:48 +00:00
|
|
|
cont->model = qemuDomainGetSCSIControllerModel(vm->def, cont, priv->qemuCaps);
|
|
|
|
else
|
|
|
|
cont->model = model;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2017-12-04 19:33:30 +00:00
|
|
|
VIR_INFO("No SCSI controller present, hotplugging one model=%s",
|
2018-01-30 22:29:48 +00:00
|
|
|
virDomainControllerModelSCSITypeToString(cont->model));
|
2017-12-04 19:33:30 +00:00
|
|
|
if (qemuDomainAttachControllerDevice(driver, vm, cont) < 0) {
|
2010-12-16 16:10:54 +00:00
|
|
|
VIR_FREE(cont);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("guest unexpectedly quit"));
|
2010-12-16 16:10:54 +00:00
|
|
|
/* cont doesn't need freeing here, since the reference
|
|
|
|
* now held in def->controllers */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return cont;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-25 12:23:08 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainDeviceDef *dev)
|
2013-07-18 08:58:01 +00:00
|
|
|
{
|
2021-05-18 13:50:06 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
2021-05-18 13:10:22 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2016-02-03 09:09:24 +00:00
|
|
|
size_t i;
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainDiskDef *disk = dev->data.disk;
|
2021-05-18 13:10:22 +00:00
|
|
|
bool releaseUSB = false;
|
2021-05-18 13:10:22 +00:00
|
|
|
bool releaseVirtio = false;
|
2021-05-18 13:50:06 +00:00
|
|
|
bool releaseSeclabel = false;
|
2013-07-18 08:58:01 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
2018-09-25 12:47:36 +00:00
|
|
|
if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
|
|
|
|
disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("cdrom/floppy device hotplug isn't supported"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-02-09 16:06:43 +00:00
|
|
|
if (virDomainDiskTranslateSourcePool(disk) < 0)
|
2016-02-02 13:59:24 +00:00
|
|
|
goto cleanup;
|
2013-07-18 08:58:01 +00:00
|
|
|
|
|
|
|
if (qemuAddSharedDevice(driver, dev, vm->def->name) < 0)
|
2016-02-02 13:59:24 +00:00
|
|
|
goto cleanup;
|
2013-07-18 08:58:01 +00:00
|
|
|
|
|
|
|
if (qemuSetUnprivSGIO(dev) < 0)
|
2016-02-02 13:59:24 +00:00
|
|
|
goto cleanup;
|
2013-07-18 08:58:01 +00:00
|
|
|
|
2019-01-16 14:33:07 +00:00
|
|
|
if (qemuDomainDetermineDiskChain(driver, vm, disk, NULL, true) < 0)
|
2016-02-02 13:59:24 +00:00
|
|
|
goto cleanup;
|
2013-07-18 08:58:01 +00:00
|
|
|
|
2018-09-25 13:07:01 +00:00
|
|
|
for (i = 0; i < vm->def->ndisks; i++) {
|
|
|
|
if (virDomainDiskDefCheckDuplicateInfo(vm->def->disks[i], disk) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2016-02-02 09:09:33 +00:00
|
|
|
|
2018-09-25 13:07:01 +00:00
|
|
|
switch ((virDomainDiskBus) disk->bus) {
|
|
|
|
case VIR_DOMAIN_DISK_BUS_USB:
|
|
|
|
if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("disk device='lun' is not supported for usb bus"));
|
2016-02-02 09:09:33 +00:00
|
|
|
break;
|
2013-07-18 08:58:01 +00:00
|
|
|
}
|
2021-05-18 13:10:22 +00:00
|
|
|
|
|
|
|
if (virDomainUSBAddressEnsure(priv->usbaddrs, &disk->info) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
releaseUSB = true;
|
2013-07-18 08:58:01 +00:00
|
|
|
break;
|
2016-02-02 08:43:36 +00:00
|
|
|
|
2018-09-25 13:07:01 +00:00
|
|
|
case VIR_DOMAIN_DISK_BUS_VIRTIO:
|
2021-06-11 14:25:48 +00:00
|
|
|
if (qemuDomainEnsureVirtioAddress(&releaseVirtio, vm, dev) < 0)
|
2021-05-18 13:10:22 +00:00
|
|
|
goto cleanup;
|
2013-07-18 08:58:01 +00:00
|
|
|
break;
|
2018-09-25 13:07:01 +00:00
|
|
|
|
|
|
|
case VIR_DOMAIN_DISK_BUS_SCSI:
|
2021-05-18 13:10:22 +00:00
|
|
|
/* We should have an address already, so make sure */
|
|
|
|
if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected disk address type %s"),
|
|
|
|
virDomainDeviceAddressTypeToString(disk->info.type));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainSCSIDriveAddressIsUsed(vm->def, &disk->info.addr.drive)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Domain already contains a disk with that address"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Let's make sure the disk has a controller defined and loaded before
|
|
|
|
* trying to add it. The controller used by the disk must exist before a
|
|
|
|
* qemu command line string is generated.
|
|
|
|
*
|
|
|
|
* Ensure that the given controller and all controllers with a smaller index
|
|
|
|
* exist; there must not be any missing index in between.
|
|
|
|
*/
|
|
|
|
for (i = 0; i <= disk->info.addr.drive.controller; i++) {
|
|
|
|
if (!qemuDomainFindOrCreateSCSIDiskController(driver, vm, i))
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2018-09-25 13:07:01 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_DISK_BUS_IDE:
|
|
|
|
case VIR_DOMAIN_DISK_BUS_FDC:
|
|
|
|
case VIR_DOMAIN_DISK_BUS_XEN:
|
|
|
|
case VIR_DOMAIN_DISK_BUS_UML:
|
|
|
|
case VIR_DOMAIN_DISK_BUS_SATA:
|
|
|
|
case VIR_DOMAIN_DISK_BUS_SD:
|
|
|
|
/* Note that SD card hotplug support should be added only once
|
|
|
|
* they support '-device' (don't require -drive only).
|
2020-05-04 13:44:43 +00:00
|
|
|
* See also: qemuDiskBusIsSD */
|
2021-04-15 14:58:19 +00:00
|
|
|
case VIR_DOMAIN_DISK_BUS_NONE:
|
2018-09-25 13:07:01 +00:00
|
|
|
case VIR_DOMAIN_DISK_BUS_LAST:
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("disk bus '%s' cannot be hotplugged."),
|
|
|
|
virDomainDiskBusTypeToString(disk->bus));
|
2013-07-18 08:58:01 +00:00
|
|
|
}
|
|
|
|
|
2021-05-18 13:50:06 +00:00
|
|
|
if (qemuDomainStorageSourceChainAccessAllow(driver, vm, disk->src) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
releaseSeclabel = true;
|
|
|
|
|
|
|
|
if (qemuAssignDeviceDiskAlias(vm->def, disk, priv->qemuCaps) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuDomainPrepareDiskSource(disk, priv, cfg) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2021-05-21 08:37:36 +00:00
|
|
|
if (qemuHotplugAttachManagedPR(driver, vm, disk->src, QEMU_ASYNC_JOB_NONE) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2021-05-18 14:18:53 +00:00
|
|
|
ret = qemuDomainAttachDiskGeneric(driver, vm, disk, QEMU_ASYNC_JOB_NONE);
|
2021-05-18 13:18:01 +00:00
|
|
|
|
2021-05-18 14:11:52 +00:00
|
|
|
virDomainAuditDisk(vm, NULL, disk->src, "attach", ret == 0);
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
virDomainDiskInsert(vm->def, disk);
|
|
|
|
|
2016-02-02 13:59:24 +00:00
|
|
|
cleanup:
|
2021-05-18 13:10:22 +00:00
|
|
|
if (ret < 0) {
|
2013-07-18 08:58:01 +00:00
|
|
|
ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name));
|
2021-05-18 13:10:22 +00:00
|
|
|
|
|
|
|
if (releaseUSB)
|
|
|
|
virDomainUSBAddressRelease(priv->usbaddrs, &disk->info);
|
2021-05-18 13:10:22 +00:00
|
|
|
|
|
|
|
if (releaseVirtio && ret == -1)
|
|
|
|
qemuDomainReleaseDeviceAddress(vm, &disk->info);
|
2021-05-18 13:50:06 +00:00
|
|
|
|
|
|
|
if (releaseSeclabel)
|
|
|
|
ignore_value(qemuDomainStorageSourceChainAccessRevoke(driver, vm, disk->src));
|
2021-05-21 08:37:36 +00:00
|
|
|
|
|
|
|
if (virStorageSourceChainHasManagedPR(disk->src))
|
|
|
|
ignore_value(qemuHotplugRemoveManagedPR(driver, vm, QEMU_ASYNC_JOB_NONE));
|
2021-05-18 13:10:22 +00:00
|
|
|
}
|
2021-05-18 13:50:06 +00:00
|
|
|
qemuDomainSecretDiskDestroy(disk);
|
2021-05-18 13:10:22 +00:00
|
|
|
|
2013-07-18 08:58:01 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-25 12:23:08 +00:00
|
|
|
/**
|
|
|
|
* qemuDomainAttachDeviceDiskLive:
|
|
|
|
* @driver: qemu driver struct
|
|
|
|
* @vm: domain object
|
|
|
|
* @dev: device to attach (expected type is DISK)
|
|
|
|
*
|
|
|
|
* Attach a new disk or in case of cdroms/floppies change the media in the drive.
|
|
|
|
* This function handles all the necessary steps to attach a new storage source
|
|
|
|
* to the VM.
|
|
|
|
*/
|
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachDeviceDiskLive(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainDeviceDef *dev)
|
2018-09-25 12:23:08 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainDiskDef *disk = dev->data.disk;
|
|
|
|
virDomainDiskDef *orig_disk = NULL;
|
2018-09-25 12:47:36 +00:00
|
|
|
|
|
|
|
/* this API overloads media change semantics on disk hotplug
|
|
|
|
* for devices supporting media changes */
|
|
|
|
if ((disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
|
|
|
|
disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) &&
|
2019-10-14 15:17:16 +00:00
|
|
|
(orig_disk = virDomainDiskByTarget(vm->def, disk->dst))) {
|
2018-09-25 12:47:36 +00:00
|
|
|
if (qemuDomainChangeEjectableMedia(driver, vm, orig_disk,
|
|
|
|
disk->src, false) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
disk->src = NULL;
|
2020-07-13 19:24:04 +00:00
|
|
|
virDomainDiskDefFree(disk);
|
2018-09-25 12:47:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-09-25 12:23:08 +00:00
|
|
|
return qemuDomainAttachDeviceDiskLiveInternal(driver, vm, dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-06-28 10:56:47 +00:00
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainNetDeviceVportRemove(virDomainNetDef *net)
|
2017-06-28 10:56:47 +00:00
|
|
|
{
|
2019-10-01 17:56:35 +00:00
|
|
|
const virNetDevVPortProfile *vport = virDomainNetGetActualVirtPortProfile(net);
|
2017-06-28 10:56:47 +00:00
|
|
|
const char *brname;
|
|
|
|
|
|
|
|
if (!vport)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_MIDONET) {
|
|
|
|
ignore_value(virNetDevMidonetUnbindPort(vport));
|
|
|
|
} else if (vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) {
|
|
|
|
brname = virDomainNetGetActualBridgeName(net);
|
|
|
|
ignore_value(virNetDevOpenvswitchRemovePort(brname, net->ifname));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-06 14:41:33 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachNetDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainNetDef *net)
|
2010-12-16 16:10:54 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2016-09-07 16:29:30 +00:00
|
|
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_NET, { .net = net } };
|
2016-10-25 10:16:36 +00:00
|
|
|
virErrorPtr originalError = NULL;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *slirpfdName = NULL;
|
2019-08-08 14:55:13 +00:00
|
|
|
int slirpfd = -1;
|
2020-10-14 17:08:29 +00:00
|
|
|
g_autofree char *vdpafdName = NULL;
|
|
|
|
int vdpafd = -1;
|
2013-05-21 13:50:09 +00:00
|
|
|
char **tapfdName = NULL;
|
|
|
|
int *tapfd = NULL;
|
2014-11-12 15:42:02 +00:00
|
|
|
size_t tapfdSize = 0;
|
2013-05-21 13:50:09 +00:00
|
|
|
char **vhostfdName = NULL;
|
|
|
|
int *vhostfd = NULL;
|
2014-11-12 15:42:02 +00:00
|
|
|
size_t vhostfdSize = 0;
|
2016-12-01 06:01:18 +00:00
|
|
|
size_t queueSize = 0;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *nicstr = NULL;
|
2020-05-14 20:50:59 +00:00
|
|
|
g_autoptr(virJSONValue) netprops = NULL;
|
2010-12-16 16:10:54 +00:00
|
|
|
int ret = -1;
|
2011-04-26 03:40:01 +00:00
|
|
|
bool releaseaddr = false;
|
2011-07-04 06:27:12 +00:00
|
|
|
bool iface_connected = false;
|
2021-05-21 18:51:05 +00:00
|
|
|
bool adjustmemlock = false;
|
2016-09-23 15:04:53 +00:00
|
|
|
virDomainNetType actualType;
|
2019-10-01 16:52:03 +00:00
|
|
|
const virNetDevBandwidth *actualBandwidth;
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainCCWAddressSet *ccwaddrs = NULL;
|
Convert 'int i' to 'size_t i' in src/qemu files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *charDevAlias = NULL;
|
2016-08-15 16:01:55 +00:00
|
|
|
bool charDevPlugged = false;
|
|
|
|
bool netdevPlugged = false;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *netdev_name = NULL;
|
2019-10-17 15:44:01 +00:00
|
|
|
g_autoptr(virConnect) conn = NULL;
|
2019-04-30 14:17:14 +00:00
|
|
|
virErrorPtr save_err = NULL;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2011-07-04 06:27:12 +00:00
|
|
|
/* If appropriate, grab a physical device from the configured
|
|
|
|
* network's pool of devices, or resolve bridge device name
|
|
|
|
* to the one defined in the network definition.
|
|
|
|
*/
|
2018-07-26 14:32:04 +00:00
|
|
|
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
|
|
|
if (!(conn = virGetConnectNetwork()))
|
|
|
|
goto cleanup;
|
|
|
|
if (virDomainNetAllocateActualDevice(conn, vm->def, net) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-07-04 06:27:12 +00:00
|
|
|
|
2019-09-13 01:22:30 +00:00
|
|
|
/* final validation now that we have full info on the type */
|
|
|
|
if (qemuDomainValidateActualNetDef(net, priv->qemuCaps) < 0)
|
2021-05-21 17:03:17 +00:00
|
|
|
goto cleanup;
|
2013-04-18 08:47:01 +00:00
|
|
|
|
2019-09-13 01:22:30 +00:00
|
|
|
actualType = virDomainNetGetActualType(net);
|
2015-08-10 06:05:29 +00:00
|
|
|
|
2016-08-15 16:01:55 +00:00
|
|
|
if (qemuAssignDeviceNetAlias(vm->def, net, -1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2019-10-19 05:58:07 +00:00
|
|
|
if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
|
|
|
|
/* This is really a "smart hostdev", so it should be attached
|
|
|
|
* as a hostdev (the hostdev code will reach over into the
|
|
|
|
* netdev-specific code as appropriate), then also added to
|
2021-06-17 05:14:27 +00:00
|
|
|
* the nets list if successful.
|
2019-10-19 05:58:07 +00:00
|
|
|
*/
|
2021-06-17 05:14:27 +00:00
|
|
|
if (qemuDomainAttachHostDevice(driver, vm,
|
|
|
|
virDomainNetGetActualHostdev(net)) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2021-08-03 12:14:20 +00:00
|
|
|
VIR_APPEND_ELEMENT_COPY(vm->def->nets, vm->def->nnets, net);
|
2021-06-17 05:14:27 +00:00
|
|
|
|
|
|
|
/* the rest of the setup doesn't apply to hostdev interfaces, so
|
|
|
|
* we can skip straight to the cleanup (nothing there applies to
|
|
|
|
* hostdev interfaces either, but it might in the future, so we
|
|
|
|
* may as well be consistent)
|
|
|
|
*/
|
|
|
|
ret = 0;
|
2019-10-19 05:58:07 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2018-12-17 11:30:34 +00:00
|
|
|
if (qemuDomainIsS390CCW(vm->def) &&
|
|
|
|
net->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
|
|
|
|
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CCW)) {
|
|
|
|
net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW;
|
|
|
|
if (!(ccwaddrs = virDomainCCWAddressSetCreateFromDomain(vm->def)))
|
|
|
|
goto cleanup;
|
|
|
|
if (virDomainCCWAddressAssign(&net->info, ccwaddrs,
|
|
|
|
!net->info.addr.ccw.assigned) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
} else if (qemuDomainEnsurePCIAddress(vm, &dev, driver) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
releaseaddr = true;
|
|
|
|
|
qemu_hotplug.c: add net devices to the domain list earlier
An upcoming patch will be checking if the addition of a new net device
requires adjusting the domain locked memory limit, which must be done
prior to sending the command to qemu to add the new device. But
qemuDomainAdjustMaxMemLock() checks all (and only) the devices that
are currently in the domain definition, and currently we are adding
new net devices to the domain definition only at the very end of the
hotplug operation, after qemu has already executed the device_add
command.
In order for the upcoming patch to work, this patch changes
qemuDomainAttachNetDevice() to add the device to the domain nets list
at an earlier time. It can't be added until after PCI address and
alias name have been determined (because both of those examine
existing devices in the domain to figure out a unique value for the
new device), but must be done before making the qemu monitor call.
Since the device has been added to the list earlier, we need to
potentially remove it on failure. This is done by replacing the
existing call to virDomainNetRemoveHostdev() (which checks if this is
a hostdev net device, and if so removes it from the hostdevs list,
since it could have already been added to that list) with a call to
the new virDomainNetRemoveByObj(), which looks for the device on both
nets and hostdevs lists, and removes it where it finds it.
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2021-05-21 18:32:00 +00:00
|
|
|
/* We've completed all examinations of the full domain definition
|
|
|
|
* that require the new device to *not* be present (e.g. PCI
|
|
|
|
* address allocation and alias name assignment) so it is now safe
|
|
|
|
* to add the new device to the domain's nets list (in order for
|
|
|
|
* it to be in place for checks that *do* need it present in the
|
|
|
|
* domain definition, e.g. checking if we need to adjust the
|
|
|
|
* locked memory limit). This means we will need to remove it if
|
|
|
|
* there is a failure.
|
|
|
|
*/
|
2021-08-03 12:14:20 +00:00
|
|
|
VIR_APPEND_ELEMENT_COPY(vm->def->nets, vm->def->nnets, net);
|
qemu_hotplug.c: add net devices to the domain list earlier
An upcoming patch will be checking if the addition of a new net device
requires adjusting the domain locked memory limit, which must be done
prior to sending the command to qemu to add the new device. But
qemuDomainAdjustMaxMemLock() checks all (and only) the devices that
are currently in the domain definition, and currently we are adding
new net devices to the domain definition only at the very end of the
hotplug operation, after qemu has already executed the device_add
command.
In order for the upcoming patch to work, this patch changes
qemuDomainAttachNetDevice() to add the device to the domain nets list
at an earlier time. It can't be added until after PCI address and
alias name have been determined (because both of those examine
existing devices in the domain to figure out a unique value for the
new device), but must be done before making the qemu monitor call.
Since the device has been added to the list earlier, we need to
potentially remove it on failure. This is done by replacing the
existing call to virDomainNetRemoveHostdev() (which checks if this is
a hostdev net device, and if so removes it from the hostdevs list,
since it could have already been added to that list) with a call to
the new virDomainNetRemoveByObj(), which looks for the device on both
nets and hostdevs lists, and removes it where it finds it.
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2021-05-21 18:32:00 +00:00
|
|
|
|
2016-09-26 09:53:58 +00:00
|
|
|
switch (actualType) {
|
|
|
|
case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
2019-04-30 12:26:25 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_NETWORK:
|
2013-04-18 08:47:01 +00:00
|
|
|
tapfdSize = vhostfdSize = net->driver.virtio.queues;
|
|
|
|
if (!tapfdSize)
|
|
|
|
tapfdSize = vhostfdSize = 1;
|
2016-12-01 06:01:18 +00:00
|
|
|
queueSize = tapfdSize;
|
2020-10-05 10:28:26 +00:00
|
|
|
tapfd = g_new0(int, tapfdSize);
|
2014-03-10 22:47:19 +00:00
|
|
|
memset(tapfd, -1, sizeof(*tapfd) * tapfdSize);
|
2020-10-05 10:28:26 +00:00
|
|
|
vhostfd = g_new0(int, vhostfdSize);
|
2014-03-10 22:47:19 +00:00
|
|
|
memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
|
2016-02-15 15:52:50 +00:00
|
|
|
if (qemuInterfaceBridgeConnect(vm->def, driver, net,
|
2017-05-18 18:16:27 +00:00
|
|
|
tapfd, &tapfdSize) < 0)
|
2013-04-20 09:11:25 +00:00
|
|
|
goto cleanup;
|
|
|
|
iface_connected = true;
|
2018-03-29 10:51:55 +00:00
|
|
|
if (qemuInterfaceOpenVhostNet(vm->def, net, vhostfd, &vhostfdSize) < 0)
|
2013-04-20 09:11:25 +00:00
|
|
|
goto cleanup;
|
2016-09-26 09:53:58 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_NET_TYPE_DIRECT:
|
2015-12-04 10:47:22 +00:00
|
|
|
tapfdSize = vhostfdSize = net->driver.virtio.queues;
|
|
|
|
if (!tapfdSize)
|
|
|
|
tapfdSize = vhostfdSize = 1;
|
2016-12-01 06:01:18 +00:00
|
|
|
queueSize = tapfdSize;
|
2020-10-05 10:28:26 +00:00
|
|
|
tapfd = g_new0(int, tapfdSize);
|
2015-12-04 10:47:22 +00:00
|
|
|
memset(tapfd, -1, sizeof(*tapfd) * tapfdSize);
|
2020-10-05 10:28:26 +00:00
|
|
|
vhostfd = g_new0(int, vhostfdSize);
|
2015-12-04 10:47:22 +00:00
|
|
|
memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
|
2016-02-15 15:26:40 +00:00
|
|
|
if (qemuInterfaceDirectConnect(vm->def, driver, net,
|
|
|
|
tapfd, tapfdSize,
|
|
|
|
VIR_NETDEV_VPORT_PROFILE_OP_CREATE) < 0)
|
2011-07-04 06:27:12 +00:00
|
|
|
goto cleanup;
|
|
|
|
iface_connected = true;
|
2018-03-29 10:51:55 +00:00
|
|
|
if (qemuInterfaceOpenVhostNet(vm->def, net, vhostfd, &vhostfdSize) < 0)
|
2011-03-09 04:43:33 +00:00
|
|
|
goto cleanup;
|
2016-09-26 09:53:58 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_NET_TYPE_ETHERNET:
|
2016-03-23 11:37:59 +00:00
|
|
|
tapfdSize = vhostfdSize = net->driver.virtio.queues;
|
|
|
|
if (!tapfdSize)
|
|
|
|
tapfdSize = vhostfdSize = 1;
|
2016-12-01 06:01:18 +00:00
|
|
|
queueSize = tapfdSize;
|
2020-10-05 10:28:26 +00:00
|
|
|
tapfd = g_new0(int, tapfdSize);
|
2016-03-23 11:37:59 +00:00
|
|
|
memset(tapfd, -1, sizeof(*tapfd) * tapfdSize);
|
2020-10-05 10:28:26 +00:00
|
|
|
vhostfd = g_new0(int, vhostfdSize);
|
2016-03-23 11:37:59 +00:00
|
|
|
memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
|
|
|
|
if (qemuInterfaceEthernetConnect(vm->def, driver, net,
|
2016-09-26 09:53:58 +00:00
|
|
|
tapfd, tapfdSize) < 0)
|
2016-03-23 11:37:59 +00:00
|
|
|
goto cleanup;
|
|
|
|
iface_connected = true;
|
2018-03-29 10:51:55 +00:00
|
|
|
if (qemuInterfaceOpenVhostNet(vm->def, net, vhostfd, &vhostfdSize) < 0)
|
2013-02-08 17:19:09 +00:00
|
|
|
goto cleanup;
|
2016-09-26 09:53:58 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
2016-12-01 06:01:18 +00:00
|
|
|
queueSize = net->driver.virtio.queues;
|
|
|
|
if (!queueSize)
|
|
|
|
queueSize = 1;
|
2018-03-28 23:36:20 +00:00
|
|
|
if (!qemuDomainSupportsNicdev(vm->def, net)) {
|
2016-08-15 16:01:55 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2018-03-28 23:36:20 +00:00
|
|
|
"%s", _("Nicdev support unavailable"));
|
2016-08-15 16:01:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-10-18 14:37:23 +00:00
|
|
|
if (!(charDevAlias = qemuAliasChardevFromDevAlias(net->info.alias)))
|
2016-08-15 16:01:55 +00:00
|
|
|
goto cleanup;
|
2018-09-18 08:59:05 +00:00
|
|
|
|
|
|
|
if (virNetDevOpenvswitchGetVhostuserIfname(net->data.vhostuser->data.nix.path,
|
2019-11-06 10:59:22 +00:00
|
|
|
net->data.vhostuser->data.nix.listen,
|
2018-09-18 08:59:05 +00:00
|
|
|
&net->ifname) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-08-15 16:01:55 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_NET_TYPE_USER:
|
2019-08-08 14:55:13 +00:00
|
|
|
if (!priv->disableSlirp &&
|
2019-09-10 08:12:24 +00:00
|
|
|
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DBUS_VMSTATE)) {
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuSlirp *slirp = NULL;
|
2020-10-15 11:12:15 +00:00
|
|
|
int rv = qemuInterfacePrepareSlirp(driver, net, &slirp);
|
2019-08-08 14:55:13 +00:00
|
|
|
|
2020-10-15 11:12:15 +00:00
|
|
|
if (rv == -1)
|
2021-05-21 17:03:17 +00:00
|
|
|
goto cleanup;
|
2020-10-15 11:12:15 +00:00
|
|
|
if (rv == 0)
|
2019-08-08 14:55:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp = slirp;
|
|
|
|
|
|
|
|
if (qemuSlirpOpen(slirp, driver, vm->def) < 0 ||
|
2020-02-25 09:55:05 +00:00
|
|
|
qemuSlirpStart(slirp, vm, driver, net, NULL) < 0) {
|
2019-08-08 14:55:13 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("Failed to start slirp"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
slirpfd = qemuSlirpGetFD(slirp);
|
2019-10-22 13:26:14 +00:00
|
|
|
slirpfdName = g_strdup_printf("slirpfd-%s", net->info.alias);
|
2019-08-08 14:55:13 +00:00
|
|
|
}
|
2017-02-28 16:49:49 +00:00
|
|
|
break;
|
|
|
|
|
2019-10-19 05:58:07 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
|
|
|
|
/* hostdev interfaces were handled earlier in this function */
|
|
|
|
break;
|
|
|
|
|
2020-10-14 17:08:29 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_VDPA:
|
2021-05-21 18:51:05 +00:00
|
|
|
if (qemuDomainAdjustMaxMemLock(vm, false) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
adjustmemlock = true;
|
|
|
|
|
2020-10-14 17:08:29 +00:00
|
|
|
if ((vdpafd = qemuInterfaceVDPAConnect(net)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
break;
|
|
|
|
|
2016-09-26 09:53:58 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_SERVER:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_CLIENT:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_MCAST:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_INTERNAL:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_UDP:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_LAST:
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("hotplug of interface type of %s is not implemented yet"),
|
|
|
|
virDomainNetTypeToString(actualType));
|
|
|
|
goto cleanup;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
|
2014-09-16 20:50:53 +00:00
|
|
|
/* Set device online immediately */
|
|
|
|
if (qemuInterfaceStartDevice(net) < 0)
|
2015-01-06 09:20:30 +00:00
|
|
|
goto cleanup;
|
2014-09-16 20:50:53 +00:00
|
|
|
|
2020-12-04 12:02:53 +00:00
|
|
|
qemuDomainInterfaceSetDefaultQDisc(driver, net);
|
|
|
|
|
2015-01-07 14:52:21 +00:00
|
|
|
/* Set bandwidth or warn if requested and not supported. */
|
|
|
|
actualBandwidth = virDomainNetGetActualBandwidth(net);
|
|
|
|
if (actualBandwidth) {
|
2020-02-17 17:17:23 +00:00
|
|
|
if (virNetDevSupportsBandwidth(actualType)) {
|
2021-07-07 09:18:19 +00:00
|
|
|
if (virDomainNetDefIsOvsport(net)) {
|
|
|
|
if (virNetDevOpenvswitchInterfaceSetQos(net->ifname, actualBandwidth,
|
|
|
|
vm->def->uuid,
|
|
|
|
!virDomainNetTypeSharesHostView(net)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
} else if (virNetDevBandwidthSet(net->ifname, actualBandwidth, false,
|
|
|
|
!virDomainNetTypeSharesHostView(net)) < 0) {
|
2015-01-07 14:52:21 +00:00
|
|
|
goto cleanup;
|
2021-07-07 09:18:19 +00:00
|
|
|
}
|
2015-01-07 14:52:21 +00:00
|
|
|
} else {
|
|
|
|
VIR_WARN("setting bandwidth on interfaces of "
|
|
|
|
"type '%s' is not implemented yet",
|
|
|
|
virDomainNetTypeToString(actualType));
|
|
|
|
}
|
|
|
|
}
|
2014-11-18 23:55:48 +00:00
|
|
|
|
2021-01-12 19:10:05 +00:00
|
|
|
if (net->mtu && net->managed_tap != VIR_TRISTATE_BOOL_NO &&
|
2017-06-08 08:14:36 +00:00
|
|
|
virNetDevSetMTU(net->ifname, net->mtu) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-08-13 14:08:03 +00:00
|
|
|
for (i = 0; i < tapfdSize; i++) {
|
2017-02-13 13:36:53 +00:00
|
|
|
if (qemuSecuritySetTapFDLabel(driver->securityManager,
|
|
|
|
vm->def, tapfd[i]) < 0)
|
2014-08-13 14:08:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2020-10-05 10:28:26 +00:00
|
|
|
tapfdName = g_new0(char *, tapfdSize);
|
|
|
|
vhostfdName = g_new0(char *, vhostfdSize);
|
2013-05-21 13:50:09 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
for (i = 0; i < tapfdSize; i++)
|
|
|
|
tapfdName[i] = g_strdup_printf("fd-%s%zu", net->info.alias, i);
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
for (i = 0; i < vhostfdSize; i++)
|
|
|
|
vhostfdName[i] = g_strdup_printf("vhostfd-%s%zu", net->info.alias, i);
|
2011-03-09 04:43:33 +00:00
|
|
|
|
2020-10-14 17:08:29 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
|
|
|
|
if (vdpafd > 0) {
|
|
|
|
/* vhost-vdpa only accepts a filename. We can pass an open fd by
|
|
|
|
* filename if we add the fd to an fdset and then pass a filename of
|
|
|
|
* /dev/fdset/$FDSETID. */
|
|
|
|
qemuMonitorAddFdInfo fdinfo;
|
|
|
|
if (qemuMonitorAddFileHandleToSet(priv->mon, vdpafd, -1,
|
|
|
|
net->data.vdpa.devicepath,
|
|
|
|
&fdinfo) < 0) {
|
|
|
|
ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
vdpafdName = g_strdup_printf("/dev/fdset/%d", fdinfo.fdset);
|
|
|
|
}
|
|
|
|
|
2020-05-14 20:50:59 +00:00
|
|
|
if (!(netprops = qemuBuildHostNetStr(net,
|
|
|
|
tapfdName, tapfdSize,
|
|
|
|
vhostfdName, vhostfdSize,
|
2020-10-14 17:08:29 +00:00
|
|
|
slirpfdName, vdpafdName))) {
|
|
|
|
ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
2020-05-14 20:50:59 +00:00
|
|
|
goto cleanup;
|
2020-10-14 17:08:29 +00:00
|
|
|
}
|
2016-08-15 16:01:55 +00:00
|
|
|
|
|
|
|
if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
|
|
|
|
if (qemuMonitorAttachCharDev(priv->mon, charDevAlias, net->data.vhostuser) < 0) {
|
|
|
|
ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
|
|
|
virDomainAuditNet(vm, NULL, net, "attach", false);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
charDevPlugged = true;
|
|
|
|
}
|
|
|
|
|
2020-05-15 09:36:28 +00:00
|
|
|
if (qemuMonitorAddNetdev(priv->mon, &netprops,
|
2018-03-28 21:36:13 +00:00
|
|
|
tapfd, tapfdName, tapfdSize,
|
2019-08-08 14:55:13 +00:00
|
|
|
vhostfd, vhostfdName, vhostfdSize,
|
|
|
|
slirpfd, slirpfdName) < 0) {
|
2018-03-28 21:36:13 +00:00
|
|
|
ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
|
|
|
virDomainAuditNet(vm, NULL, net, "attach", false);
|
|
|
|
goto try_remove;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
2018-03-28 21:36:13 +00:00
|
|
|
netdevPlugged = true;
|
2016-08-15 16:01:55 +00:00
|
|
|
|
2014-12-16 09:40:58 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
goto cleanup;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2013-05-21 13:50:09 +00:00
|
|
|
for (i = 0; i < tapfdSize; i++)
|
|
|
|
VIR_FORCE_CLOSE(tapfd[i]);
|
|
|
|
for (i = 0; i < vhostfdSize; i++)
|
|
|
|
VIR_FORCE_CLOSE(vhostfd[i]);
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2018-06-19 15:42:37 +00:00
|
|
|
if (!(nicstr = qemuBuildNicDevStr(vm->def, net, 0,
|
2017-05-18 18:16:27 +00:00
|
|
|
queueSize, priv->qemuCaps)))
|
2016-04-26 12:04:49 +00:00
|
|
|
goto try_remove;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2013-02-06 18:17:20 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2018-11-08 11:00:30 +00:00
|
|
|
|
|
|
|
if (qemuDomainAttachExtensionDevice(priv->mon, &net->info) < 0) {
|
|
|
|
ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
|
|
|
virDomainAuditNet(vm, NULL, net, "attach", false);
|
|
|
|
goto try_remove;
|
|
|
|
}
|
|
|
|
|
2016-04-26 12:04:49 +00:00
|
|
|
if (qemuMonitorAddDevice(priv->mon, nicstr) < 0) {
|
2018-11-08 11:00:30 +00:00
|
|
|
ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &net->info));
|
2016-04-26 12:04:49 +00:00
|
|
|
ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
|
|
|
virDomainAuditNet(vm, NULL, net, "attach", false);
|
|
|
|
goto try_remove;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
2014-12-16 09:40:58 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
goto cleanup;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2011-09-06 08:23:47 +00:00
|
|
|
/* set link state */
|
|
|
|
if (net->linkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN) {
|
|
|
|
if (!net->info.alias) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
|
_("device alias not found: cannot set link state to down"));
|
2011-09-06 08:23:47 +00:00
|
|
|
} else {
|
2013-02-06 18:17:20 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2011-09-06 08:23:47 +00:00
|
|
|
|
2018-03-28 21:36:13 +00:00
|
|
|
if (qemuMonitorSetLink(priv->mon, net->info.alias, VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN) < 0) {
|
|
|
|
ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
|
|
|
virDomainAuditNet(vm, NULL, net, "attach", false);
|
|
|
|
goto try_remove;
|
2011-09-06 08:23:47 +00:00
|
|
|
}
|
|
|
|
|
2014-12-16 09:40:58 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
goto cleanup;
|
2011-09-06 08:23:47 +00:00
|
|
|
}
|
|
|
|
/* link set to down */
|
|
|
|
}
|
|
|
|
|
Move qemu_audit.h helpers into shared code
The LXC and UML drivers can both make use of auditing. Move
the qemu_audit.{c,h} files to src/conf/domain_audit.{c,h}
* src/conf/domain_audit.c: Rename from src/qemu/qemu_audit.c
* src/conf/domain_audit.h: Rename from src/qemu/qemu_audit.h
* src/Makefile.am: Remove qemu_audit.{c,h}, add domain_audit.{c,h}
* src/qemu/qemu_audit.h, src/qemu/qemu_cgroup.c,
src/qemu/qemu_command.c, src/qemu/qemu_driver.c,
src/qemu/qemu_hotplug.c, src/qemu/qemu_migration.c,
src/qemu/qemu_process.c: Update for changed audit API names
2011-07-04 10:56:13 +00:00
|
|
|
virDomainAuditNet(vm, NULL, net, "attach", true);
|
2010-12-16 16:10:54 +00:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
cleanup:
|
qemu_hotplug.c: add net devices to the domain list earlier
An upcoming patch will be checking if the addition of a new net device
requires adjusting the domain locked memory limit, which must be done
prior to sending the command to qemu to add the new device. But
qemuDomainAdjustMaxMemLock() checks all (and only) the devices that
are currently in the domain definition, and currently we are adding
new net devices to the domain definition only at the very end of the
hotplug operation, after qemu has already executed the device_add
command.
In order for the upcoming patch to work, this patch changes
qemuDomainAttachNetDevice() to add the device to the domain nets list
at an earlier time. It can't be added until after PCI address and
alias name have been determined (because both of those examine
existing devices in the domain to figure out a unique value for the
new device), but must be done before making the qemu monitor call.
Since the device has been added to the list earlier, we need to
potentially remove it on failure. This is done by replacing the
existing call to virDomainNetRemoveHostdev() (which checks if this is
a hostdev net device, and if so removes it from the hostdevs list,
since it could have already been added to that list) with a call to
the new virDomainNetRemoveByObj(), which looks for the device on both
nets and hostdevs lists, and removes it where it finds it.
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2021-05-21 18:32:00 +00:00
|
|
|
if (ret < 0) {
|
2019-04-30 14:17:14 +00:00
|
|
|
virErrorPreserveLast(&save_err);
|
2013-07-09 20:30:57 +00:00
|
|
|
if (releaseaddr)
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &net->info);
|
2011-07-04 06:27:12 +00:00
|
|
|
|
2012-02-28 03:43:23 +00:00
|
|
|
if (iface_connected) {
|
2018-08-21 13:28:18 +00:00
|
|
|
virErrorPreserveLast(&originalError);
|
2011-07-04 06:27:12 +00:00
|
|
|
virDomainConfNWFilterTeardown(net);
|
2018-08-21 13:28:18 +00:00
|
|
|
virErrorRestore(&originalError);
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2013-07-01 15:04:57 +00:00
|
|
|
if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
|
|
|
ignore_value(virNetDevMacVLanDeleteWithVPortProfile(
|
|
|
|
net->ifname, &net->mac,
|
|
|
|
virDomainNetGetActualDirectDev(net),
|
|
|
|
virDomainNetGetActualDirectMode(net),
|
|
|
|
virDomainNetGetActualVirtPortProfile(net),
|
|
|
|
cfg->stateDir));
|
|
|
|
}
|
|
|
|
|
2017-06-28 10:56:47 +00:00
|
|
|
qemuDomainNetDeviceVportRemove(net);
|
2012-02-28 03:43:23 +00:00
|
|
|
}
|
2012-02-10 21:09:00 +00:00
|
|
|
|
qemu_hotplug.c: add net devices to the domain list earlier
An upcoming patch will be checking if the addition of a new net device
requires adjusting the domain locked memory limit, which must be done
prior to sending the command to qemu to add the new device. But
qemuDomainAdjustMaxMemLock() checks all (and only) the devices that
are currently in the domain definition, and currently we are adding
new net devices to the domain definition only at the very end of the
hotplug operation, after qemu has already executed the device_add
command.
In order for the upcoming patch to work, this patch changes
qemuDomainAttachNetDevice() to add the device to the domain nets list
at an earlier time. It can't be added until after PCI address and
alias name have been determined (because both of those examine
existing devices in the domain to figure out a unique value for the
new device), but must be done before making the qemu monitor call.
Since the device has been added to the list earlier, we need to
potentially remove it on failure. This is done by replacing the
existing call to virDomainNetRemoveHostdev() (which checks if this is
a hostdev net device, and if so removes it from the hostdevs list,
since it could have already been added to that list) with a call to
the new virDomainNetRemoveByObj(), which looks for the device on both
nets and hostdevs lists, and removes it where it finds it.
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2021-05-21 18:32:00 +00:00
|
|
|
/* we had potentially pre-added the device to the domain
|
|
|
|
* device lists, if so we need to remove it (from def->nets
|
|
|
|
* and/or def->hostdevs) on failure
|
|
|
|
*/
|
|
|
|
virDomainNetRemoveByObj(vm->def, net);
|
2013-08-27 17:06:18 +00:00
|
|
|
|
2021-05-21 18:51:05 +00:00
|
|
|
/* if we adjusted the memlock limit (for a vDPA device) then
|
|
|
|
* we need to re-adjust since we won't be using the device
|
|
|
|
* after all
|
|
|
|
*/
|
|
|
|
if (adjustmemlock)
|
|
|
|
qemuDomainAdjustMaxMemLock(vm, false);
|
|
|
|
|
2018-07-26 14:32:04 +00:00
|
|
|
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
|
|
|
if (conn)
|
|
|
|
virDomainNetReleaseActualDevice(conn, vm->def, net);
|
|
|
|
else
|
|
|
|
VIR_WARN("Unable to release network device '%s'", NULLSTR(net->ifname));
|
|
|
|
}
|
2019-04-30 14:17:14 +00:00
|
|
|
virErrorRestore(&save_err);
|
2011-07-04 06:27:12 +00:00
|
|
|
}
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2013-04-18 08:47:01 +00:00
|
|
|
for (i = 0; tapfd && i < tapfdSize; i++) {
|
2013-05-21 13:50:09 +00:00
|
|
|
VIR_FORCE_CLOSE(tapfd[i]);
|
2013-04-18 08:47:01 +00:00
|
|
|
if (tapfdName)
|
|
|
|
VIR_FREE(tapfdName[i]);
|
2013-05-21 13:50:09 +00:00
|
|
|
}
|
|
|
|
VIR_FREE(tapfd);
|
|
|
|
VIR_FREE(tapfdName);
|
2013-04-18 08:47:01 +00:00
|
|
|
for (i = 0; vhostfd && i < vhostfdSize; i++) {
|
2013-05-21 13:50:09 +00:00
|
|
|
VIR_FORCE_CLOSE(vhostfd[i]);
|
2013-04-18 08:47:01 +00:00
|
|
|
if (vhostfdName)
|
|
|
|
VIR_FREE(vhostfdName[i]);
|
2013-05-21 13:50:09 +00:00
|
|
|
}
|
|
|
|
VIR_FREE(vhostfd);
|
|
|
|
VIR_FREE(vhostfdName);
|
2016-07-23 01:47:10 +00:00
|
|
|
virDomainCCWAddressSetFree(ccwaddrs);
|
2019-08-08 14:55:13 +00:00
|
|
|
VIR_FORCE_CLOSE(slirpfd);
|
2020-10-14 17:08:29 +00:00
|
|
|
VIR_FORCE_CLOSE(vdpafd);
|
2010-12-16 16:10:54 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
try_remove:
|
2010-12-16 16:10:54 +00:00
|
|
|
if (!virDomainObjIsActive(vm))
|
|
|
|
goto cleanup;
|
|
|
|
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorPreserveLast(&originalError);
|
2019-10-22 13:26:14 +00:00
|
|
|
netdev_name = g_strdup_printf("host%s", net->info.alias);
|
|
|
|
if (QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp)
|
2020-02-25 09:55:05 +00:00
|
|
|
qemuSlirpStop(QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp, vm, driver, net);
|
2019-10-22 13:26:14 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
if (charDevPlugged &&
|
|
|
|
qemuMonitorDetachCharDev(priv->mon, charDevAlias) < 0)
|
|
|
|
VIR_WARN("Failed to remove associated chardev %s", charDevAlias);
|
|
|
|
if (netdevPlugged &&
|
|
|
|
qemuMonitorRemoveNetdev(priv->mon, netdev_name) < 0)
|
|
|
|
VIR_WARN("Failed to remove network backend for netdev %s",
|
|
|
|
netdev_name);
|
|
|
|
ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorRestore(&originalError);
|
2010-12-16 16:10:54 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-05 18:09:04 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachHostPCIDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2010-12-16 16:10:54 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2016-09-07 16:29:30 +00:00
|
|
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV,
|
|
|
|
{ .hostdev = hostdev } };
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainDeviceInfo *info = hostdev->info;
|
2010-12-16 16:10:54 +00:00
|
|
|
int ret;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *devstr = NULL;
|
2011-04-26 03:40:01 +00:00
|
|
|
bool releaseaddr = false;
|
2013-11-14 11:02:40 +00:00
|
|
|
bool teardowncgroup = false;
|
2013-12-05 19:54:41 +00:00
|
|
|
bool teardownlabel = false;
|
2016-11-16 14:27:47 +00:00
|
|
|
bool teardowndevice = false;
|
2019-09-03 20:09:47 +00:00
|
|
|
bool teardownmemlock = false;
|
2014-02-04 11:12:47 +00:00
|
|
|
int backend;
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
2014-03-05 10:56:26 +00:00
|
|
|
unsigned int flags = 0;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2021-03-19 23:37:05 +00:00
|
|
|
VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1);
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2014-03-05 10:56:26 +00:00
|
|
|
if (!cfg->relaxedACS)
|
|
|
|
flags |= VIR_HOSTDEV_STRICT_ACS_CHECK;
|
2015-10-20 12:10:16 +00:00
|
|
|
if (qemuHostdevPreparePCIDevices(driver, vm->def->name, vm->def->uuid,
|
2014-03-05 10:56:26 +00:00
|
|
|
&hostdev, 1, priv->qemuCaps, flags) < 0)
|
2019-10-17 15:44:02 +00:00
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2015-10-20 12:10:16 +00:00
|
|
|
/* this could have been changed by qemuHostdevPreparePCIDevices */
|
2014-02-04 11:12:47 +00:00
|
|
|
backend = hostdev->source.subsys.u.pci.backend;
|
|
|
|
|
2018-04-25 12:42:34 +00:00
|
|
|
switch ((virDomainHostdevSubsysPCIBackendType)backend) {
|
2013-09-19 14:48:23 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
|
2013-04-25 16:45:55 +00:00
|
|
|
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("VFIO PCI device assignment is not "
|
|
|
|
"supported by this version of qemu"));
|
|
|
|
goto error;
|
|
|
|
}
|
2013-09-19 14:48:23 +00:00
|
|
|
break;
|
|
|
|
|
2016-04-26 12:18:04 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
|
|
|
|
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN:
|
|
|
|
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("QEMU does not support device assignment mode '%s'"),
|
|
|
|
virDomainHostdevSubsysPCIBackendTypeToString(backend));
|
|
|
|
goto error;
|
2013-09-19 14:48:23 +00:00
|
|
|
break;
|
2013-04-25 11:58:37 +00:00
|
|
|
}
|
|
|
|
|
2019-09-03 20:09:46 +00:00
|
|
|
if (qemuDomainAdjustMaxMemLockHostdev(vm, hostdev) < 0)
|
2015-11-23 16:57:40 +00:00
|
|
|
goto error;
|
2019-09-03 20:09:47 +00:00
|
|
|
teardownmemlock = true;
|
2015-11-18 11:10:33 +00:00
|
|
|
|
2021-07-14 14:46:54 +00:00
|
|
|
if (qemuDomainNamespaceSetupHostdev(vm, hostdev, &teardowndevice) < 0)
|
2016-11-16 14:27:47 +00:00
|
|
|
goto error;
|
|
|
|
|
2015-11-19 13:35:46 +00:00
|
|
|
if (qemuSetupHostdevCgroup(vm, hostdev) < 0)
|
2013-11-14 11:02:40 +00:00
|
|
|
goto error;
|
|
|
|
teardowncgroup = true;
|
|
|
|
|
2016-11-16 14:27:47 +00:00
|
|
|
if (qemuSecuritySetHostdevLabel(driver, vm, hostdev) < 0)
|
2013-12-05 19:54:41 +00:00
|
|
|
goto error;
|
2016-02-05 19:07:50 +00:00
|
|
|
if (backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO)
|
|
|
|
teardownlabel = true;
|
2013-12-05 19:54:41 +00:00
|
|
|
|
2017-06-05 13:29:40 +00:00
|
|
|
if (qemuAssignDeviceHostdevAlias(vm->def, &info->alias, -1) < 0)
|
2016-04-26 12:23:12 +00:00
|
|
|
goto error;
|
2017-06-02 13:19:04 +00:00
|
|
|
|
2020-01-09 18:33:48 +00:00
|
|
|
if (qemuDomainIsPSeries(vm->def))
|
2017-06-02 13:19:04 +00:00
|
|
|
/* Isolation groups are only relevant for pSeries guests */
|
2020-01-09 18:33:48 +00:00
|
|
|
qemuDomainFillDeviceIsolationGroup(vm->def, &dev);
|
2017-06-02 13:19:04 +00:00
|
|
|
|
2016-11-03 20:33:32 +00:00
|
|
|
if (qemuDomainEnsurePCIAddress(vm, &dev, driver) < 0)
|
2016-04-26 12:23:12 +00:00
|
|
|
goto error;
|
|
|
|
releaseaddr = true;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2016-04-26 12:23:12 +00:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("guest unexpectedly quit during hotplug"));
|
|
|
|
goto error;
|
|
|
|
}
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2019-05-03 13:25:07 +00:00
|
|
|
if (!(devstr = qemuBuildPCIHostdevDevStr(vm->def, hostdev, 0, priv->qemuCaps)))
|
2016-04-26 12:23:12 +00:00
|
|
|
goto error;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2016-04-26 12:23:12 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2018-11-08 11:00:30 +00:00
|
|
|
|
|
|
|
if ((ret = qemuDomainAttachExtensionDevice(priv->mon, hostdev->info)) < 0)
|
|
|
|
goto exit_monitor;
|
|
|
|
|
2019-05-03 13:25:07 +00:00
|
|
|
if ((ret = qemuMonitorAddDevice(priv->mon, devstr)) < 0)
|
2018-11-08 11:00:30 +00:00
|
|
|
ignore_value(qemuDomainDetachExtensionDevice(priv->mon, hostdev->info));
|
|
|
|
|
|
|
|
exit_monitor:
|
2016-04-26 12:23:12 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
goto error;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
Move qemu_audit.h helpers into shared code
The LXC and UML drivers can both make use of auditing. Move
the qemu_audit.{c,h} files to src/conf/domain_audit.{c,h}
* src/conf/domain_audit.c: Rename from src/qemu/qemu_audit.c
* src/conf/domain_audit.h: Rename from src/qemu/qemu_audit.h
* src/Makefile.am: Remove qemu_audit.{c,h}, add domain_audit.{c,h}
* src/qemu/qemu_audit.h, src/qemu/qemu_cgroup.c,
src/qemu/qemu_command.c, src/qemu/qemu_driver.c,
src/qemu/qemu_hotplug.c, src/qemu/qemu_migration.c,
src/qemu/qemu_process.c: Update for changed audit API names
2011-07-04 10:56:13 +00:00
|
|
|
virDomainAuditHostdev(vm, hostdev, "attach", ret == 0);
|
2010-12-16 16:10:54 +00:00
|
|
|
if (ret < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
error:
|
2013-11-14 11:02:40 +00:00
|
|
|
if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
|
|
|
|
VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
|
2013-12-05 19:54:41 +00:00
|
|
|
if (teardownlabel &&
|
2016-11-16 14:27:47 +00:00
|
|
|
qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
|
2013-12-05 19:54:41 +00:00
|
|
|
VIR_WARN("Unable to restore host device labelling on hotplug fail");
|
2016-11-16 14:27:47 +00:00
|
|
|
if (teardowndevice &&
|
2017-11-24 16:52:15 +00:00
|
|
|
qemuDomainNamespaceTeardownHostdev(vm, hostdev) < 0)
|
2016-11-16 14:27:47 +00:00
|
|
|
VIR_WARN("Unable to remove host device from /dev");
|
2019-09-26 11:15:47 +00:00
|
|
|
if (teardownmemlock && qemuDomainAdjustMaxMemLock(vm, false) < 0)
|
2019-09-03 20:09:47 +00:00
|
|
|
VIR_WARN("Unable to reset maximum locked memory on hotplug fail");
|
2013-11-14 11:02:40 +00:00
|
|
|
|
2013-07-09 20:30:57 +00:00
|
|
|
if (releaseaddr)
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, info);
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2015-10-20 12:12:48 +00:00
|
|
|
qemuHostdevReAttachPCIDevices(driver, vm->def->name, &hostdev, 1);
|
2010-12-16 16:10:54 +00:00
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-16 15:33:35 +00:00
|
|
|
void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDelTLSObjects(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
2017-03-09 14:20:27 +00:00
|
|
|
qemuDomainAsyncJob asyncJob,
|
2017-02-16 15:33:35 +00:00
|
|
|
const char *secAlias,
|
|
|
|
const char *tlsAlias)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2017-02-16 15:33:35 +00:00
|
|
|
virErrorPtr orig_err;
|
|
|
|
|
|
|
|
if (!tlsAlias && !secAlias)
|
|
|
|
return;
|
|
|
|
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorPreserveLast(&orig_err);
|
2017-02-16 15:33:35 +00:00
|
|
|
|
2017-03-09 14:20:27 +00:00
|
|
|
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
|
|
|
goto cleanup;
|
2017-02-16 15:33:35 +00:00
|
|
|
|
|
|
|
if (tlsAlias)
|
2020-03-18 11:24:40 +00:00
|
|
|
ignore_value(qemuMonitorDelObject(priv->mon, tlsAlias, false));
|
2017-02-16 15:33:35 +00:00
|
|
|
|
|
|
|
if (secAlias)
|
2020-03-18 11:24:40 +00:00
|
|
|
ignore_value(qemuMonitorDelObject(priv->mon, secAlias, false));
|
2017-02-16 15:33:35 +00:00
|
|
|
|
|
|
|
ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
|
|
|
|
2017-03-09 14:20:27 +00:00
|
|
|
cleanup:
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorRestore(&orig_err);
|
2017-02-16 15:33:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAddTLSObjects(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
2017-03-09 14:20:27 +00:00
|
|
|
qemuDomainAsyncJob asyncJob,
|
2021-03-11 07:16:13 +00:00
|
|
|
virJSONValue **secProps,
|
|
|
|
virJSONValue **tlsProps)
|
2017-02-16 15:33:35 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2017-02-16 15:33:35 +00:00
|
|
|
virErrorPtr orig_err;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *secAlias = NULL;
|
2017-02-16 15:33:35 +00:00
|
|
|
|
2018-05-22 05:38:22 +00:00
|
|
|
if (!tlsProps && !secProps)
|
2017-02-16 15:33:35 +00:00
|
|
|
return 0;
|
|
|
|
|
2017-03-09 14:20:27 +00:00
|
|
|
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
|
|
|
return -1;
|
2017-02-16 15:33:35 +00:00
|
|
|
|
2018-07-04 14:28:58 +00:00
|
|
|
if (secProps && *secProps &&
|
2018-05-22 05:38:22 +00:00
|
|
|
qemuMonitorAddObject(priv->mon, secProps, &secAlias) < 0)
|
|
|
|
goto error;
|
2017-02-16 15:33:35 +00:00
|
|
|
|
2018-05-22 05:38:22 +00:00
|
|
|
if (tlsProps &&
|
|
|
|
qemuMonitorAddObject(priv->mon, tlsProps, NULL) < 0)
|
|
|
|
goto error;
|
2017-02-16 15:33:35 +00:00
|
|
|
|
|
|
|
return qemuDomainObjExitMonitor(driver, vm);
|
|
|
|
|
|
|
|
error:
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorPreserveLast(&orig_err);
|
2017-02-16 15:33:35 +00:00
|
|
|
ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorRestore(&orig_err);
|
2018-05-22 05:38:22 +00:00
|
|
|
qemuDomainDelTLSObjects(driver, vm, asyncJob, secAlias, NULL);
|
2017-02-16 15:33:35 +00:00
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-17 15:06:14 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainGetTLSObjects(virQEMUCaps *qemuCaps,
|
|
|
|
qemuDomainSecretInfo *secinfo,
|
2017-02-17 15:06:14 +00:00
|
|
|
const char *tlsCertdir,
|
|
|
|
bool tlsListen,
|
|
|
|
bool tlsVerify,
|
2018-05-22 05:38:22 +00:00
|
|
|
const char *alias,
|
2021-03-11 07:16:13 +00:00
|
|
|
virJSONValue **tlsProps,
|
|
|
|
virJSONValue **secProps)
|
2016-10-21 13:38:18 +00:00
|
|
|
{
|
2018-05-29 18:17:04 +00:00
|
|
|
const char *secAlias = NULL;
|
|
|
|
|
2017-02-17 15:06:14 +00:00
|
|
|
if (secinfo) {
|
|
|
|
if (qemuBuildSecretInfoProps(secinfo, secProps) < 0)
|
2016-06-17 13:44:30 +00:00
|
|
|
return -1;
|
|
|
|
|
2018-05-29 18:17:04 +00:00
|
|
|
secAlias = secinfo->s.aes.alias;
|
2016-06-17 13:44:30 +00:00
|
|
|
}
|
|
|
|
|
2017-02-17 15:06:14 +00:00
|
|
|
if (qemuBuildTLSx509BackendProps(tlsCertdir, tlsListen, tlsVerify,
|
2018-05-22 05:38:22 +00:00
|
|
|
alias, secAlias, qemuCaps, tlsProps) < 0)
|
2016-10-21 13:38:18 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-22 17:54:10 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAddChardevTLSObjects(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainChrSourceDef *dev,
|
2017-02-17 14:37:34 +00:00
|
|
|
char *devAlias,
|
2017-02-22 17:54:10 +00:00
|
|
|
char *charAlias,
|
|
|
|
char **tlsAlias,
|
2018-05-29 18:03:07 +00:00
|
|
|
const char **secAlias)
|
2017-02-22 17:54:10 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
|
|
|
qemuDomainChrSourcePrivate *chrSourcePriv;
|
|
|
|
qemuDomainSecretInfo *secinfo = NULL;
|
|
|
|
virJSONValue *tlsProps = NULL;
|
|
|
|
virJSONValue *secProps = NULL;
|
2017-02-22 17:54:10 +00:00
|
|
|
|
2017-02-17 14:46:16 +00:00
|
|
|
/* NB: This may alter haveTLS based on cfg */
|
|
|
|
qemuDomainPrepareChardevSourceTLS(dev, cfg);
|
|
|
|
|
2017-02-22 17:54:10 +00:00
|
|
|
if (dev->type != VIR_DOMAIN_CHR_TYPE_TCP ||
|
2017-02-17 14:46:16 +00:00
|
|
|
dev->data.tcp.haveTLS != VIR_TRISTATE_BOOL_YES) {
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2017-02-22 17:54:10 +00:00
|
|
|
|
2018-02-09 16:14:41 +00:00
|
|
|
if (qemuDomainSecretChardevPrepare(cfg, priv, devAlias, dev) < 0)
|
2017-02-17 14:37:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-02-17 15:06:14 +00:00
|
|
|
if ((chrSourcePriv = QEMU_DOMAIN_CHR_SOURCE_PRIVATE(dev)))
|
|
|
|
secinfo = chrSourcePriv->secinfo;
|
|
|
|
|
2018-05-29 18:03:07 +00:00
|
|
|
if (secinfo)
|
|
|
|
*secAlias = secinfo->s.aes.alias;
|
|
|
|
|
2018-05-30 07:24:35 +00:00
|
|
|
if (!(*tlsAlias = qemuAliasTLSObjFromSrcAlias(charAlias)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2017-02-17 15:06:14 +00:00
|
|
|
if (qemuDomainGetTLSObjects(priv->qemuCaps, secinfo,
|
|
|
|
cfg->chardevTLSx509certdir,
|
|
|
|
dev->data.tcp.listen,
|
|
|
|
cfg->chardevTLSx509verify,
|
2018-05-22 05:38:22 +00:00
|
|
|
*tlsAlias, &tlsProps, &secProps) < 0)
|
2017-02-22 17:54:10 +00:00
|
|
|
goto cleanup;
|
2017-02-17 15:06:14 +00:00
|
|
|
dev->data.tcp.tlscreds = true;
|
2017-02-22 17:54:10 +00:00
|
|
|
|
2017-03-09 14:20:27 +00:00
|
|
|
if (qemuDomainAddTLSObjects(driver, vm, QEMU_ASYNC_JOB_NONE,
|
2018-05-22 05:38:22 +00:00
|
|
|
&secProps, &tlsProps) < 0)
|
2017-02-22 17:54:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virJSONValueFree(tlsProps);
|
|
|
|
virJSONValueFree(secProps);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-19 22:46:41 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDelChardevTLSObjects(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainChrSourceDef *dev,
|
2017-12-19 22:46:41 +00:00
|
|
|
const char *inAlias)
|
|
|
|
{
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *tlsAlias = NULL;
|
|
|
|
g_autofree char *secAlias = NULL;
|
2017-12-19 22:46:41 +00:00
|
|
|
|
2017-12-20 11:36:26 +00:00
|
|
|
if (dev->type != VIR_DOMAIN_CHR_TYPE_TCP ||
|
|
|
|
dev->data.tcp.haveTLS != VIR_TRISTATE_BOOL_YES) {
|
2019-09-18 19:53:06 +00:00
|
|
|
return 0;
|
2017-12-20 11:36:26 +00:00
|
|
|
}
|
|
|
|
|
2017-12-19 22:46:41 +00:00
|
|
|
if (!(tlsAlias = qemuAliasTLSObjFromSrcAlias(inAlias)))
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2017-12-19 22:46:41 +00:00
|
|
|
|
|
|
|
/* Best shot at this as the secinfo is destroyed after process launch
|
|
|
|
* and this path does not recreate it. Thus, if the config has the
|
|
|
|
* secret UUID and we have a serial TCP chardev, then formulate a
|
|
|
|
* secAlias which we'll attempt to destroy. */
|
|
|
|
if (cfg->chardevTLSx509secretUUID &&
|
2020-03-09 07:03:34 +00:00
|
|
|
!(secAlias = qemuAliasForSecret(inAlias, NULL)))
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2017-12-19 22:46:41 +00:00
|
|
|
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
|
2020-03-18 11:24:40 +00:00
|
|
|
ignore_value(qemuMonitorDelObject(priv->mon, tlsAlias, false));
|
2017-12-19 22:46:41 +00:00
|
|
|
if (secAlias)
|
2020-03-18 11:24:40 +00:00
|
|
|
ignore_value(qemuMonitorDelObject(priv->mon, secAlias, false));
|
2017-12-19 22:46:41 +00:00
|
|
|
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2017-12-19 22:46:41 +00:00
|
|
|
|
2019-09-18 19:53:06 +00:00
|
|
|
return 0;
|
2017-12-19 22:46:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
int qemuDomainAttachRedirdevDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainRedirdevDef *redirdev)
|
2011-09-02 15:09:14 +00:00
|
|
|
{
|
2016-02-22 16:44:09 +00:00
|
|
|
int ret = -1;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
|
|
|
virDomainDef *def = vm->def;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *charAlias = NULL;
|
|
|
|
g_autofree char *devstr = NULL;
|
2016-10-21 13:53:30 +00:00
|
|
|
bool chardevAdded = false;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *tlsAlias = NULL;
|
2018-05-29 18:03:07 +00:00
|
|
|
const char *secAlias = NULL;
|
2016-10-21 13:53:30 +00:00
|
|
|
virErrorPtr orig_err;
|
2011-09-02 15:09:14 +00:00
|
|
|
|
2016-06-19 12:46:40 +00:00
|
|
|
if (qemuAssignDeviceRedirdevAlias(def, redirdev, -1) < 0)
|
2021-02-03 06:18:34 +00:00
|
|
|
return -1;
|
2016-02-22 16:44:09 +00:00
|
|
|
|
2016-10-18 14:37:23 +00:00
|
|
|
if (!(charAlias = qemuAliasChardevFromDevAlias(redirdev->info.alias)))
|
2021-02-03 06:18:34 +00:00
|
|
|
return -1;
|
2016-02-22 16:44:09 +00:00
|
|
|
|
2017-05-30 11:22:17 +00:00
|
|
|
if ((virDomainUSBAddressEnsure(priv->usbaddrs, &redirdev->info)) < 0)
|
2021-02-03 06:18:34 +00:00
|
|
|
return -1;
|
2017-01-27 14:26:13 +00:00
|
|
|
|
2014-12-16 15:29:00 +00:00
|
|
|
if (!(devstr = qemuBuildRedirdevDevStr(def, redirdev, priv->qemuCaps)))
|
2016-02-22 16:44:09 +00:00
|
|
|
goto cleanup;
|
2014-12-16 15:29:00 +00:00
|
|
|
|
2021-03-19 23:37:05 +00:00
|
|
|
VIR_REALLOC_N(def->redirdevs, def->nredirdevs+1);
|
2011-09-02 15:09:14 +00:00
|
|
|
|
2018-02-09 16:14:41 +00:00
|
|
|
if (qemuDomainAddChardevTLSObjects(driver, vm, redirdev->source,
|
2017-02-17 14:37:34 +00:00
|
|
|
redirdev->info.alias, charAlias,
|
|
|
|
&tlsAlias, &secAlias) < 0)
|
2017-02-16 15:33:35 +00:00
|
|
|
goto audit;
|
2016-06-17 13:44:30 +00:00
|
|
|
|
2017-02-16 15:33:35 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2016-10-21 13:59:53 +00:00
|
|
|
|
2016-02-22 16:44:09 +00:00
|
|
|
if (qemuMonitorAttachCharDev(priv->mon,
|
|
|
|
charAlias,
|
2016-10-24 12:24:51 +00:00
|
|
|
redirdev->source) < 0)
|
2016-10-21 13:53:30 +00:00
|
|
|
goto exit_monitor;
|
|
|
|
chardevAdded = true;
|
2015-01-07 12:12:18 +00:00
|
|
|
|
2016-10-21 13:53:30 +00:00
|
|
|
if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
|
|
|
|
goto exit_monitor;
|
2011-09-02 15:09:14 +00:00
|
|
|
|
2016-02-22 16:44:09 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
goto audit;
|
2011-09-02 15:09:14 +00:00
|
|
|
|
2016-06-19 12:46:40 +00:00
|
|
|
def->redirdevs[def->nredirdevs++] = redirdev;
|
2016-02-22 16:44:09 +00:00
|
|
|
ret = 0;
|
|
|
|
audit:
|
|
|
|
virDomainAuditRedirdev(vm, redirdev, "attach", ret == 0);
|
|
|
|
cleanup:
|
2021-02-03 06:18:34 +00:00
|
|
|
if (ret < 0)
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &redirdev->info);
|
2016-02-22 16:44:09 +00:00
|
|
|
return ret;
|
2016-10-21 13:53:30 +00:00
|
|
|
|
|
|
|
exit_monitor:
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorPreserveLast(&orig_err);
|
2016-10-21 13:53:30 +00:00
|
|
|
/* detach associated chardev on error */
|
|
|
|
if (chardevAdded)
|
|
|
|
ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias));
|
2017-02-22 17:39:17 +00:00
|
|
|
ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorRestore(&orig_err);
|
2017-03-09 14:20:27 +00:00
|
|
|
qemuDomainDelTLSObjects(driver, vm, QEMU_ASYNC_JOB_NONE,
|
|
|
|
secAlias, tlsAlias);
|
2016-10-21 13:53:30 +00:00
|
|
|
goto audit;
|
2011-09-02 15:09:14 +00:00
|
|
|
}
|
|
|
|
|
2015-01-27 17:30:15 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainChrPreInsert(virDomainDef *vmdef,
|
|
|
|
virDomainChrDef *chr)
|
2013-03-12 14:59:25 +00:00
|
|
|
{
|
|
|
|
if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
|
|
|
|
chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("attaching serial console is not supported"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainChrFind(vmdef, chr)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("chardev already exists"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-01-27 17:30:15 +00:00
|
|
|
if (virDomainChrPreAlloc(vmdef, chr) < 0)
|
2013-03-12 14:59:25 +00:00
|
|
|
return -1;
|
|
|
|
|
2017-05-29 10:58:34 +00:00
|
|
|
/* Due to historical reasons, the first console is an alias to the
|
|
|
|
* first serial device (if such exists). If this is the case, we need to
|
|
|
|
* create an object for the first console as well.
|
|
|
|
*/
|
2015-01-27 17:30:15 +00:00
|
|
|
if (vmdef->nserials == 0 && vmdef->nconsoles == 0 &&
|
|
|
|
chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
|
2020-10-05 10:28:26 +00:00
|
|
|
if (!vmdef->consoles)
|
2021-03-11 07:16:13 +00:00
|
|
|
vmdef->consoles = g_new0(virDomainChrDef *, 1);
|
2015-01-27 17:30:15 +00:00
|
|
|
|
2017-05-29 10:58:34 +00:00
|
|
|
/* We'll be dealing with serials[0] directly, so NULL is fine here. */
|
|
|
|
if (!(vmdef->consoles[0] = virDomainChrDefNew(NULL))) {
|
2015-01-27 17:30:15 +00:00
|
|
|
VIR_FREE(vmdef->consoles);
|
2013-03-12 14:59:25 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2015-01-27 17:30:15 +00:00
|
|
|
vmdef->nconsoles++;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainChrInsertPreAlloced(virDomainDef *vmdef,
|
|
|
|
virDomainChrDef *chr)
|
2015-01-27 17:30:15 +00:00
|
|
|
{
|
|
|
|
virDomainChrInsertPreAlloced(vmdef, chr);
|
|
|
|
if (vmdef->nserials == 1 && vmdef->nconsoles == 0 &&
|
|
|
|
chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
|
2013-03-12 14:59:25 +00:00
|
|
|
vmdef->nconsoles = 1;
|
|
|
|
|
|
|
|
/* Create an console alias for the serial port */
|
|
|
|
vmdef->consoles[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
|
|
|
|
vmdef->consoles[0]->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
|
|
|
|
}
|
2015-01-27 17:30:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainChrInsertPreAllocCleanup(virDomainDef *vmdef,
|
|
|
|
virDomainChrDef *chr)
|
2015-01-27 17:30:15 +00:00
|
|
|
{
|
|
|
|
/* Remove the stub console added by qemuDomainChrPreInsert */
|
|
|
|
if (vmdef->nserials == 0 && vmdef->nconsoles == 1 &&
|
|
|
|
chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
|
2017-05-29 10:58:34 +00:00
|
|
|
virDomainChrDefFree(vmdef->consoles[0]);
|
2015-01-27 17:30:15 +00:00
|
|
|
VIR_FREE(vmdef->consoles);
|
|
|
|
vmdef->nconsoles = 0;
|
|
|
|
}
|
|
|
|
}
|
2013-03-12 14:59:25 +00:00
|
|
|
|
2015-01-27 17:30:15 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainChrInsert(virDomainDef *vmdef,
|
|
|
|
virDomainChrDef *chr)
|
2015-01-27 17:30:15 +00:00
|
|
|
{
|
|
|
|
if (qemuDomainChrPreInsert(vmdef, chr) < 0) {
|
|
|
|
qemuDomainChrInsertPreAllocCleanup(vmdef, chr);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
qemuDomainChrInsertPreAlloced(vmdef, chr);
|
2013-03-12 14:59:25 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainChrDef *
|
|
|
|
qemuDomainChrRemove(virDomainDef *vmdef,
|
|
|
|
virDomainChrDef *chr)
|
2013-03-12 14:59:25 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainChrDef *ret;
|
2013-03-12 14:59:25 +00:00
|
|
|
bool removeCompat;
|
|
|
|
|
|
|
|
if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
|
|
|
|
chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("detaching serial console is not supported"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Due to some crazy backcompat stuff, the first serial device is an alias
|
|
|
|
* to the first console too. If this is the case, the definition must be
|
|
|
|
* duplicated as first console device. */
|
|
|
|
removeCompat = vmdef->nserials && vmdef->nconsoles &&
|
|
|
|
vmdef->consoles[0]->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
|
|
|
|
vmdef->consoles[0]->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL &&
|
|
|
|
virDomainChrEquals(vmdef->serials[0], chr);
|
|
|
|
|
|
|
|
if (!(ret = virDomainChrRemove(vmdef, chr))) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("device not present in domain configuration"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (removeCompat)
|
|
|
|
VIR_DELETE_ELEMENT(vmdef->consoles, 0, vmdef->nconsoles);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2013-03-13 10:08:55 +00:00
|
|
|
|
2016-10-21 12:18:54 +00:00
|
|
|
/* Returns 1 if the address will need to be released later,
|
|
|
|
* -1 on error
|
|
|
|
* 0 otherwise
|
|
|
|
*/
|
2015-06-10 14:49:37 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachChrDeviceAssignAddr(virDomainObj *vm,
|
|
|
|
virDomainChrDef *chr,
|
|
|
|
virQEMUDriver *driver)
|
2015-06-10 14:49:37 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainDef *def = vm->def;
|
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2016-09-07 16:29:30 +00:00
|
|
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_CHR, { .chr = chr } };
|
2016-07-23 01:47:07 +00:00
|
|
|
|
2015-06-10 14:49:37 +00:00
|
|
|
if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
|
|
|
|
chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) {
|
2016-10-21 11:09:36 +00:00
|
|
|
if (virDomainVirtioSerialAddrAutoAssign(def, &chr->info, true) < 0)
|
2016-10-21 12:17:31 +00:00
|
|
|
return -1;
|
2016-10-21 12:18:54 +00:00
|
|
|
return 0;
|
2015-06-10 14:49:37 +00:00
|
|
|
|
|
|
|
} else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
|
|
|
|
chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI) {
|
2016-11-03 20:33:32 +00:00
|
|
|
if (qemuDomainEnsurePCIAddress(vm, &dev, driver) < 0)
|
2016-10-21 12:17:31 +00:00
|
|
|
return -1;
|
|
|
|
return 1;
|
2015-06-10 14:49:37 +00:00
|
|
|
|
2017-10-20 11:28:21 +00:00
|
|
|
} else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
|
2015-08-12 14:52:19 +00:00
|
|
|
chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB) {
|
|
|
|
if (virDomainUSBAddressEnsure(priv->usbaddrs, &chr->info) < 0)
|
2016-10-21 12:17:31 +00:00
|
|
|
return -1;
|
|
|
|
return 1;
|
2015-08-12 14:52:19 +00:00
|
|
|
|
2015-06-10 14:49:37 +00:00
|
|
|
} else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
|
|
|
|
chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) {
|
2016-10-21 11:09:36 +00:00
|
|
|
if (virDomainVirtioSerialAddrAutoAssign(def, &chr->info, false) < 0)
|
2016-10-21 12:17:31 +00:00
|
|
|
return -1;
|
2016-10-21 12:18:54 +00:00
|
|
|
return 0;
|
2015-06-10 14:49:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (chr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL ||
|
|
|
|
chr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Unsupported address type for character device"));
|
2016-10-21 12:17:31 +00:00
|
|
|
return -1;
|
2015-06-10 14:49:37 +00:00
|
|
|
}
|
|
|
|
|
2016-10-21 12:17:31 +00:00
|
|
|
return 0;
|
2015-06-10 14:49:37 +00:00
|
|
|
}
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
int qemuDomainAttachChrDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainChrDef *chr)
|
2013-03-13 10:08:55 +00:00
|
|
|
{
|
2015-06-10 14:49:37 +00:00
|
|
|
int ret = -1, rc;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2016-07-14 21:55:05 +00:00
|
|
|
virErrorPtr orig_err;
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainDef *vmdef = vm->def;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *devstr = NULL;
|
2020-05-15 07:46:08 +00:00
|
|
|
g_autoptr(virJSONValue) netdevprops = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainChrSourceDef *dev = chr->source;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *charAlias = NULL;
|
2016-07-14 21:55:05 +00:00
|
|
|
bool chardevAttached = false;
|
2016-11-18 10:45:44 +00:00
|
|
|
bool teardowncgroup = false;
|
2016-11-18 13:53:27 +00:00
|
|
|
bool teardowndevice = false;
|
2017-12-01 12:10:35 +00:00
|
|
|
bool teardownlabel = false;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *tlsAlias = NULL;
|
2018-05-29 18:03:07 +00:00
|
|
|
const char *secAlias = NULL;
|
2015-03-02 09:59:52 +00:00
|
|
|
bool need_release = false;
|
2019-02-11 15:05:37 +00:00
|
|
|
bool guestfwd = false;
|
2013-03-13 10:08:55 +00:00
|
|
|
|
2019-02-11 15:05:37 +00:00
|
|
|
if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL) {
|
|
|
|
guestfwd = chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD;
|
|
|
|
|
|
|
|
if (qemuDomainPrepareChannel(chr, priv->channelTargetDir) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2016-03-30 14:43:28 +00:00
|
|
|
|
2013-03-13 10:08:55 +00:00
|
|
|
if (qemuAssignDeviceChrAlias(vmdef, chr, -1) < 0)
|
2015-01-27 17:44:30 +00:00
|
|
|
goto cleanup;
|
2013-03-13 10:08:55 +00:00
|
|
|
|
2016-11-03 20:33:32 +00:00
|
|
|
if ((rc = qemuDomainAttachChrDeviceAssignAddr(vm, chr, driver)) < 0)
|
2015-06-10 14:49:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
if (rc == 1)
|
|
|
|
need_release = true;
|
2015-03-02 09:59:52 +00:00
|
|
|
|
2021-07-14 14:46:54 +00:00
|
|
|
if (qemuDomainNamespaceSetupChardev(vm, chr, &teardowndevice) < 0)
|
2016-11-18 13:53:27 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-12-01 12:10:35 +00:00
|
|
|
if (qemuSecuritySetChardevLabel(driver, vm, chr) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
teardownlabel = true;
|
|
|
|
|
2016-11-18 10:45:44 +00:00
|
|
|
if (qemuSetupChardevCgroup(vm, chr) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
teardowncgroup = true;
|
|
|
|
|
2020-05-14 11:01:59 +00:00
|
|
|
if (guestfwd) {
|
2020-05-15 07:46:08 +00:00
|
|
|
if (!(netdevprops = qemuBuildChannelGuestfwdNetdevProps(chr)))
|
|
|
|
goto cleanup;
|
2020-05-14 11:01:59 +00:00
|
|
|
} else {
|
|
|
|
if (qemuBuildChrDeviceStr(&devstr, vmdef, chr, priv->qemuCaps) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-03-13 10:08:55 +00:00
|
|
|
|
2016-10-18 14:37:23 +00:00
|
|
|
if (!(charAlias = qemuAliasChardevFromDevAlias(chr->info.alias)))
|
2013-03-13 10:08:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-01-27 17:44:30 +00:00
|
|
|
if (qemuDomainChrPreInsert(vmdef, chr) < 0)
|
2013-03-13 10:08:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2018-02-09 16:14:41 +00:00
|
|
|
if (qemuDomainAddChardevTLSObjects(driver, vm, dev,
|
2017-02-17 14:37:34 +00:00
|
|
|
chr->info.alias, charAlias,
|
2017-02-22 17:54:10 +00:00
|
|
|
&tlsAlias, &secAlias) < 0)
|
2017-02-16 15:33:35 +00:00
|
|
|
goto audit;
|
2016-06-17 13:44:30 +00:00
|
|
|
|
2017-02-16 15:33:35 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2016-06-13 16:30:34 +00:00
|
|
|
|
2016-10-21 11:45:54 +00:00
|
|
|
if (qemuMonitorAttachCharDev(priv->mon, charAlias, chr->source) < 0)
|
2016-07-14 21:55:05 +00:00
|
|
|
goto exit_monitor;
|
|
|
|
chardevAttached = true;
|
2016-06-13 16:57:15 +00:00
|
|
|
|
2020-05-15 09:36:28 +00:00
|
|
|
if (netdevprops) {
|
|
|
|
if (qemuMonitorAddNetdev(priv->mon, &netdevprops,
|
2019-08-08 14:55:13 +00:00
|
|
|
NULL, NULL, 0, NULL, NULL, 0, -1, NULL) < 0)
|
2019-02-11 15:05:37 +00:00
|
|
|
goto exit_monitor;
|
2020-05-14 11:01:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (devstr) {
|
2019-02-11 15:05:37 +00:00
|
|
|
if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
|
|
|
|
goto exit_monitor;
|
|
|
|
}
|
2013-03-13 10:08:55 +00:00
|
|
|
|
2015-01-27 17:44:30 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
goto audit;
|
2013-03-13 10:08:55 +00:00
|
|
|
|
2016-06-19 12:46:40 +00:00
|
|
|
qemuDomainChrInsertPreAlloced(vmdef, chr);
|
2013-03-13 10:08:55 +00:00
|
|
|
ret = 0;
|
2014-07-03 08:59:58 +00:00
|
|
|
audit:
|
|
|
|
virDomainAuditChardev(vm, NULL, chr, "attach", ret == 0);
|
2014-03-25 06:49:44 +00:00
|
|
|
cleanup:
|
2016-11-18 10:45:44 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
if (virDomainObjIsActive(vm))
|
|
|
|
qemuDomainChrInsertPreAllocCleanup(vmdef, chr);
|
|
|
|
if (need_release)
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &chr->info);
|
2016-11-18 10:45:44 +00:00
|
|
|
if (teardowncgroup && qemuTeardownChardevCgroup(vm, chr) < 0)
|
|
|
|
VIR_WARN("Unable to remove chr device cgroup ACL on hotplug fail");
|
2017-12-01 12:10:35 +00:00
|
|
|
if (teardownlabel && qemuSecurityRestoreChardevLabel(driver, vm, chr) < 0)
|
|
|
|
VIR_WARN("Unable to restore security label on char device");
|
2017-11-24 16:52:15 +00:00
|
|
|
if (teardowndevice && qemuDomainNamespaceTeardownChardev(vm, chr) < 0)
|
2016-11-18 13:53:27 +00:00
|
|
|
VIR_WARN("Unable to remove chr device from /dev");
|
2016-11-18 10:45:44 +00:00
|
|
|
}
|
2013-03-13 10:08:55 +00:00
|
|
|
return ret;
|
2016-06-13 16:57:15 +00:00
|
|
|
|
2016-07-14 21:55:05 +00:00
|
|
|
exit_monitor:
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorPreserveLast(&orig_err);
|
2016-06-13 16:57:15 +00:00
|
|
|
/* detach associated chardev on error */
|
2016-07-14 21:55:05 +00:00
|
|
|
if (chardevAttached)
|
|
|
|
qemuMonitorDetachCharDev(priv->mon, charAlias);
|
2017-02-22 17:39:17 +00:00
|
|
|
ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorRestore(&orig_err);
|
2016-07-14 21:55:05 +00:00
|
|
|
|
2017-03-09 14:20:27 +00:00
|
|
|
qemuDomainDelTLSObjects(driver, vm, QEMU_ASYNC_JOB_NONE,
|
|
|
|
secAlias, tlsAlias);
|
2016-06-13 16:57:15 +00:00
|
|
|
goto audit;
|
2013-03-13 10:08:55 +00:00
|
|
|
}
|
|
|
|
|
2015-01-17 05:09:37 +00:00
|
|
|
|
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachRNGDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainRNGDef *rng)
|
2015-01-17 05:09:37 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2016-09-07 16:29:30 +00:00
|
|
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_RNG, { .rng = rng } };
|
2016-07-14 22:13:50 +00:00
|
|
|
virErrorPtr orig_err;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *devstr = NULL;
|
|
|
|
g_autofree char *charAlias = NULL;
|
|
|
|
g_autofree char *objAlias = NULL;
|
|
|
|
g_autofree char *tlsAlias = NULL;
|
2018-05-29 18:03:07 +00:00
|
|
|
const char *secAlias = NULL;
|
2016-07-14 22:13:50 +00:00
|
|
|
bool releaseaddr = false;
|
2016-11-18 10:17:51 +00:00
|
|
|
bool teardowncgroup = false;
|
2016-11-18 14:19:12 +00:00
|
|
|
bool teardowndevice = false;
|
2016-07-14 22:13:50 +00:00
|
|
|
bool chardevAdded = false;
|
2021-03-11 07:16:13 +00:00
|
|
|
virJSONValue *props = NULL;
|
2015-01-17 05:09:37 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
2016-04-06 15:32:12 +00:00
|
|
|
if (qemuAssignDeviceRNGAlias(vm->def, rng) < 0)
|
2016-10-21 14:06:50 +00:00
|
|
|
goto cleanup;
|
2015-01-17 05:09:37 +00:00
|
|
|
|
|
|
|
/* preallocate space for the device definition */
|
2021-03-19 23:37:05 +00:00
|
|
|
VIR_REALLOC_N(vm->def->rngs, vm->def->nrngs + 1);
|
2015-01-17 05:09:37 +00:00
|
|
|
|
2021-06-11 14:25:48 +00:00
|
|
|
if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev) < 0)
|
2017-10-12 12:53:27 +00:00
|
|
|
return -1;
|
2015-01-17 05:09:37 +00:00
|
|
|
|
2021-07-14 14:46:54 +00:00
|
|
|
if (qemuDomainNamespaceSetupRNG(vm, rng, &teardowndevice) < 0)
|
2016-11-18 14:19:12 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-11-18 10:17:51 +00:00
|
|
|
if (qemuSetupRNGCgroup(vm, rng) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
teardowncgroup = true;
|
|
|
|
|
2015-01-17 05:09:37 +00:00
|
|
|
/* build required metadata */
|
|
|
|
if (!(devstr = qemuBuildRNGDevStr(vm->def, rng, priv->qemuCaps)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2020-10-09 18:18:53 +00:00
|
|
|
if (qemuBuildRNGBackendProps(rng, &props) < 0)
|
2015-01-17 05:09:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-10-18 14:37:23 +00:00
|
|
|
if (!(charAlias = qemuAliasChardevFromDevAlias(rng->info.alias)))
|
2015-01-17 05:09:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-06-17 13:44:30 +00:00
|
|
|
if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD) {
|
2018-02-09 16:14:41 +00:00
|
|
|
if (qemuDomainAddChardevTLSObjects(driver, vm,
|
2017-02-17 14:37:34 +00:00
|
|
|
rng->source.chardev,
|
|
|
|
rng->info.alias, charAlias,
|
|
|
|
&tlsAlias, &secAlias) < 0)
|
2017-02-16 15:33:35 +00:00
|
|
|
goto audit;
|
2016-06-17 13:44:30 +00:00
|
|
|
}
|
|
|
|
|
2017-02-16 15:33:35 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2016-10-21 14:06:50 +00:00
|
|
|
|
2015-01-17 05:09:37 +00:00
|
|
|
if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD &&
|
|
|
|
qemuMonitorAttachCharDev(priv->mon, charAlias,
|
|
|
|
rng->source.chardev) < 0)
|
2016-07-14 22:13:50 +00:00
|
|
|
goto exit_monitor;
|
|
|
|
chardevAdded = true;
|
2015-01-17 05:09:37 +00:00
|
|
|
|
2018-05-18 12:48:22 +00:00
|
|
|
if (qemuMonitorAddObject(priv->mon, &props, &objAlias) < 0)
|
2016-07-14 22:13:50 +00:00
|
|
|
goto exit_monitor;
|
2015-01-17 05:09:37 +00:00
|
|
|
|
2018-11-08 11:00:30 +00:00
|
|
|
if (qemuDomainAttachExtensionDevice(priv->mon, &rng->info) < 0)
|
2016-07-14 22:13:50 +00:00
|
|
|
goto exit_monitor;
|
2015-01-17 05:09:37 +00:00
|
|
|
|
2018-11-08 11:00:30 +00:00
|
|
|
if (qemuMonitorAddDevice(priv->mon, devstr) < 0) {
|
|
|
|
ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &rng->info));
|
|
|
|
goto exit_monitor;
|
|
|
|
}
|
|
|
|
|
2015-01-17 05:09:37 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
2016-07-14 22:13:50 +00:00
|
|
|
releaseaddr = false;
|
2015-01-17 05:09:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-05-17 10:59:43 +00:00
|
|
|
VIR_APPEND_ELEMENT_INPLACE(vm->def->rngs, vm->def->nrngs, rng);
|
2015-01-17 05:09:37 +00:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
audit:
|
|
|
|
virDomainAuditRNG(vm, NULL, rng, "attach", ret == 0);
|
|
|
|
cleanup:
|
2016-04-11 14:00:32 +00:00
|
|
|
virJSONValueFree(props);
|
2016-11-18 10:17:51 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
if (releaseaddr)
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &rng->info);
|
2016-11-18 10:17:51 +00:00
|
|
|
if (teardowncgroup && qemuTeardownRNGCgroup(vm, rng) < 0)
|
|
|
|
VIR_WARN("Unable to remove RNG device cgroup ACL on hotplug fail");
|
2017-11-24 16:52:15 +00:00
|
|
|
if (teardowndevice && qemuDomainNamespaceTeardownRNG(vm, rng) < 0)
|
2016-11-18 14:19:12 +00:00
|
|
|
VIR_WARN("Unable to remove chr device from /dev");
|
2016-11-18 10:17:51 +00:00
|
|
|
}
|
|
|
|
|
2015-01-17 05:09:37 +00:00
|
|
|
return ret;
|
|
|
|
|
2016-07-14 22:13:50 +00:00
|
|
|
exit_monitor:
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorPreserveLast(&orig_err);
|
2018-05-18 12:48:22 +00:00
|
|
|
if (objAlias)
|
2020-03-18 11:24:40 +00:00
|
|
|
ignore_value(qemuMonitorDelObject(priv->mon, objAlias, false));
|
2016-07-14 22:13:50 +00:00
|
|
|
if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD && chardevAdded)
|
2015-01-17 05:09:37 +00:00
|
|
|
ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias));
|
2017-02-22 17:39:17 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
releaseaddr = false;
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorRestore(&orig_err);
|
2015-01-17 05:09:37 +00:00
|
|
|
|
2017-03-09 14:20:27 +00:00
|
|
|
qemuDomainDelTLSObjects(driver, vm, QEMU_ASYNC_JOB_NONE,
|
|
|
|
secAlias, tlsAlias);
|
2015-01-17 05:09:37 +00:00
|
|
|
goto audit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-12 22:28:58 +00:00
|
|
|
/**
|
|
|
|
* qemuDomainAttachMemory:
|
|
|
|
* @driver: qemu driver data
|
|
|
|
* @vm: VM object
|
|
|
|
* @mem: Definition of the memory device to be attached. @mem is always consumed
|
|
|
|
*
|
|
|
|
* Attaches memory device described by @mem to domain @vm.
|
|
|
|
*
|
|
|
|
* Returns 0 on success -1 on error.
|
|
|
|
*/
|
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachMemory(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainMemoryDef *mem)
|
2014-10-12 22:28:58 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2016-07-15 11:27:48 +00:00
|
|
|
virErrorPtr orig_err;
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
2016-06-15 13:34:04 +00:00
|
|
|
unsigned long long oldmem = virDomainDefGetMemoryTotal(vm->def);
|
2015-08-13 14:15:27 +00:00
|
|
|
unsigned long long newmem = oldmem + mem->size;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *devstr = NULL;
|
|
|
|
g_autofree char *objalias = NULL;
|
2016-07-15 11:27:48 +00:00
|
|
|
bool objAdded = false;
|
2021-02-08 14:21:16 +00:00
|
|
|
bool releaseaddr = false;
|
2016-08-04 13:26:09 +00:00
|
|
|
bool teardownlabel = false;
|
2017-02-22 15:33:12 +00:00
|
|
|
bool teardowncgroup = false;
|
2017-02-22 16:37:39 +00:00
|
|
|
bool teardowndevice = false;
|
2021-03-11 07:16:13 +00:00
|
|
|
virJSONValue *props = NULL;
|
|
|
|
virObjectEvent *event;
|
2014-10-12 22:28:58 +00:00
|
|
|
int id;
|
|
|
|
int ret = -1;
|
|
|
|
|
2020-09-15 02:42:56 +00:00
|
|
|
if (qemuDomainMemoryDeviceAlignSize(vm->def, mem) < 0)
|
|
|
|
goto cleanup;
|
2015-10-08 04:06:15 +00:00
|
|
|
|
2020-12-04 13:50:48 +00:00
|
|
|
if (qemuDomainDefValidateMemoryHotplug(vm->def, mem) < 0)
|
2015-04-28 15:33:54 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2020-12-07 14:24:17 +00:00
|
|
|
if (qemuDomainAssignMemoryDeviceSlot(driver, vm, mem) < 0)
|
2016-11-01 05:07:09 +00:00
|
|
|
goto cleanup;
|
2021-02-08 14:21:16 +00:00
|
|
|
releaseaddr = true;
|
2016-11-01 05:07:09 +00:00
|
|
|
|
2016-11-01 05:21:36 +00:00
|
|
|
/* in cases where we are using a VM with aliases generated according to the
|
|
|
|
* index of the memory device we need to keep continue using that scheme */
|
|
|
|
if (qemuAssignDeviceMemoryAlias(vm->def, mem, priv->memAliasOrderMismatch) < 0)
|
2014-10-12 22:28:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
objalias = g_strdup_printf("mem%s", mem->info.alias);
|
2014-10-12 22:28:58 +00:00
|
|
|
|
2020-11-03 16:31:27 +00:00
|
|
|
if (!(devstr = qemuBuildMemoryDeviceStr(vm->def, mem, priv->qemuCaps)))
|
2014-10-12 22:28:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2018-05-18 12:48:22 +00:00
|
|
|
if (qemuBuildMemoryBackendProps(&props, objalias, cfg,
|
2021-01-08 15:35:26 +00:00
|
|
|
priv, vm->def, mem, true, false) < 0)
|
2014-10-12 22:28:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-11-07 14:19:43 +00:00
|
|
|
if (qemuProcessBuildDestroyMemoryPaths(driver, vm, mem, true) < 0)
|
2017-06-07 12:47:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2021-07-14 14:46:54 +00:00
|
|
|
if (qemuDomainNamespaceSetupMemory(vm, mem, &teardowndevice) < 0)
|
2017-02-22 16:37:39 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-02-22 15:33:12 +00:00
|
|
|
if (qemuSetupMemoryDevicesCgroup(vm, mem) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
teardowncgroup = true;
|
|
|
|
|
2016-08-04 13:26:09 +00:00
|
|
|
if (qemuSecuritySetMemoryLabel(driver, vm, mem) < 0)
|
2014-10-12 22:28:58 +00:00
|
|
|
goto cleanup;
|
2016-08-04 13:26:09 +00:00
|
|
|
teardownlabel = true;
|
2014-10-12 22:28:58 +00:00
|
|
|
|
2016-08-04 13:26:09 +00:00
|
|
|
if (virDomainMemoryInsert(vm->def, mem) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2019-09-26 11:15:47 +00:00
|
|
|
if (qemuDomainAdjustMaxMemLock(vm, false) < 0)
|
2015-11-06 15:39:31 +00:00
|
|
|
goto removedef;
|
|
|
|
|
2014-10-12 22:28:58 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2018-05-18 12:48:22 +00:00
|
|
|
if (qemuMonitorAddObject(priv->mon, &props, NULL) < 0)
|
2015-11-06 15:39:31 +00:00
|
|
|
goto exit_monitor;
|
2016-07-15 11:27:48 +00:00
|
|
|
objAdded = true;
|
2014-10-12 22:28:58 +00:00
|
|
|
|
2016-07-15 11:27:48 +00:00
|
|
|
if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
|
2015-11-06 15:39:31 +00:00
|
|
|
goto exit_monitor;
|
2014-10-12 22:28:58 +00:00
|
|
|
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
|
|
/* we shouldn't touch mem now, as the def might be freed */
|
|
|
|
mem = NULL;
|
2015-08-13 14:15:27 +00:00
|
|
|
goto audit;
|
2014-10-12 22:28:58 +00:00
|
|
|
}
|
|
|
|
|
2015-03-30 18:08:47 +00:00
|
|
|
event = virDomainEventDeviceAddedNewFromObj(vm, objalias);
|
2018-06-12 17:33:02 +00:00
|
|
|
virObjectEventStateQueue(driver->domainEventState, event);
|
2015-03-30 18:08:47 +00:00
|
|
|
|
2016-04-06 13:57:57 +00:00
|
|
|
/* fix the balloon size */
|
|
|
|
ignore_value(qemuProcessRefreshBalloonState(driver, vm, QEMU_ASYNC_JOB_NONE));
|
2015-04-30 16:03:41 +00:00
|
|
|
|
2014-10-12 22:28:58 +00:00
|
|
|
/* mem is consumed by vm->def */
|
|
|
|
mem = NULL;
|
|
|
|
|
|
|
|
/* this step is best effort, removing the device would be so much trouble */
|
|
|
|
ignore_value(qemuDomainUpdateMemoryDeviceInfo(driver, vm,
|
|
|
|
QEMU_ASYNC_JOB_NONE));
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2015-08-13 14:15:27 +00:00
|
|
|
audit:
|
|
|
|
virDomainAuditMemory(vm, oldmem, newmem, "update", ret == 0);
|
2014-10-12 22:28:58 +00:00
|
|
|
cleanup:
|
2016-08-04 13:26:09 +00:00
|
|
|
if (mem && ret < 0) {
|
2017-02-22 15:33:12 +00:00
|
|
|
if (teardowncgroup && qemuTeardownMemoryDevicesCgroup(vm, mem) < 0)
|
|
|
|
VIR_WARN("Unable to remove memory device cgroup ACL on hotplug fail");
|
2016-08-04 13:26:09 +00:00
|
|
|
if (teardownlabel && qemuSecurityRestoreMemoryLabel(driver, vm, mem) < 0)
|
|
|
|
VIR_WARN("Unable to restore security label on memdev");
|
2017-02-22 16:37:39 +00:00
|
|
|
if (teardowndevice &&
|
2017-11-24 16:52:15 +00:00
|
|
|
qemuDomainNamespaceTeardownMemory(vm, mem) < 0)
|
2017-02-22 16:37:39 +00:00
|
|
|
VIR_WARN("Unable to remove memory device from /dev");
|
2021-02-08 14:21:16 +00:00
|
|
|
if (releaseaddr)
|
|
|
|
qemuDomainReleaseMemoryDeviceSlot(vm, mem);
|
2016-08-04 13:26:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virJSONValueFree(props);
|
2014-10-12 22:28:58 +00:00
|
|
|
virDomainMemoryDefFree(mem);
|
|
|
|
return ret;
|
|
|
|
|
2015-11-06 15:39:31 +00:00
|
|
|
exit_monitor:
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorPreserveLast(&orig_err);
|
2016-07-15 11:27:48 +00:00
|
|
|
if (objAdded)
|
2020-03-18 11:24:40 +00:00
|
|
|
ignore_value(qemuMonitorDelObject(priv->mon, objalias, false));
|
2017-02-22 17:39:17 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
mem = NULL;
|
2018-03-13 17:19:39 +00:00
|
|
|
|
|
|
|
if (objAdded && mem)
|
|
|
|
ignore_value(qemuProcessDestroyMemoryBackingPath(driver, vm, mem));
|
|
|
|
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorRestore(&orig_err);
|
2017-02-22 17:39:17 +00:00
|
|
|
if (!mem)
|
2015-08-13 14:15:27 +00:00
|
|
|
goto audit;
|
2014-10-12 22:28:58 +00:00
|
|
|
|
2015-11-06 15:39:31 +00:00
|
|
|
removedef:
|
2014-10-12 22:28:58 +00:00
|
|
|
if ((id = virDomainMemoryFindByDef(vm->def, mem)) >= 0)
|
|
|
|
mem = virDomainMemoryRemove(vm->def, id);
|
|
|
|
else
|
|
|
|
mem = NULL;
|
|
|
|
|
2015-11-06 15:39:31 +00:00
|
|
|
/* reset the mlock limit */
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorPreserveLast(&orig_err);
|
2019-09-26 11:15:47 +00:00
|
|
|
ignore_value(qemuDomainAdjustMaxMemLock(vm, false));
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorRestore(&orig_err);
|
2015-11-06 15:39:31 +00:00
|
|
|
|
2015-08-13 14:15:27 +00:00
|
|
|
goto audit;
|
2014-10-12 22:28:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-05 18:09:04 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachHostUSBDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2010-12-16 16:10:54 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *devstr = NULL;
|
2013-05-03 18:07:30 +00:00
|
|
|
bool added = false;
|
2013-11-14 11:02:40 +00:00
|
|
|
bool teardowncgroup = false;
|
2013-12-05 19:54:41 +00:00
|
|
|
bool teardownlabel = false;
|
2016-11-16 14:27:47 +00:00
|
|
|
bool teardowndevice = false;
|
2013-05-03 18:07:30 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
2017-10-20 11:28:21 +00:00
|
|
|
if (virDomainUSBAddressEnsure(priv->usbaddrs, hostdev->info) < 0)
|
|
|
|
return -1;
|
2015-08-12 14:52:19 +00:00
|
|
|
|
2015-10-20 12:10:16 +00:00
|
|
|
if (qemuHostdevPrepareUSBDevices(driver, vm->def->name, &hostdev, 1, 0) < 0)
|
2013-05-03 18:07:30 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
added = true;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2021-07-14 14:46:54 +00:00
|
|
|
if (qemuDomainNamespaceSetupHostdev(vm, hostdev, &teardowndevice) < 0)
|
2016-11-16 14:27:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-11-19 13:35:46 +00:00
|
|
|
if (qemuSetupHostdevCgroup(vm, hostdev) < 0)
|
2013-11-14 11:02:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
teardowncgroup = true;
|
|
|
|
|
2016-11-16 14:27:47 +00:00
|
|
|
if (qemuSecuritySetHostdevLabel(driver, vm, hostdev) < 0)
|
2013-12-05 19:54:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
teardownlabel = true;
|
|
|
|
|
2016-04-26 11:40:34 +00:00
|
|
|
if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (!(devstr = qemuBuildUSBHostdevDevStr(vm->def, hostdev, priv->qemuCaps)))
|
|
|
|
goto cleanup;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2021-03-19 23:37:05 +00:00
|
|
|
VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1);
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2013-02-06 18:17:20 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2016-04-26 11:40:34 +00:00
|
|
|
ret = qemuMonitorAddDevice(priv->mon, devstr);
|
2015-01-07 12:12:18 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
|
|
ret = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
Move qemu_audit.h helpers into shared code
The LXC and UML drivers can both make use of auditing. Move
the qemu_audit.{c,h} files to src/conf/domain_audit.{c,h}
* src/conf/domain_audit.c: Rename from src/qemu/qemu_audit.c
* src/conf/domain_audit.h: Rename from src/qemu/qemu_audit.h
* src/Makefile.am: Remove qemu_audit.{c,h}, add domain_audit.{c,h}
* src/qemu/qemu_audit.h, src/qemu/qemu_cgroup.c,
src/qemu/qemu_command.c, src/qemu/qemu_driver.c,
src/qemu/qemu_hotplug.c, src/qemu/qemu_migration.c,
src/qemu/qemu_process.c: Update for changed audit API names
2011-07-04 10:56:13 +00:00
|
|
|
virDomainAuditHostdev(vm, hostdev, "attach", ret == 0);
|
2010-12-16 16:10:54 +00:00
|
|
|
if (ret < 0)
|
2013-05-03 18:07:30 +00:00
|
|
|
goto cleanup;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
|
|
|
vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
|
|
|
|
|
2013-05-03 18:07:30 +00:00
|
|
|
ret = 0;
|
2014-03-25 06:49:44 +00:00
|
|
|
cleanup:
|
2013-12-05 19:54:41 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
|
|
|
|
VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
|
|
|
|
if (teardownlabel &&
|
2016-11-16 14:27:47 +00:00
|
|
|
qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
|
2013-12-05 19:54:41 +00:00
|
|
|
VIR_WARN("Unable to restore host device labelling on hotplug fail");
|
2016-11-16 14:27:47 +00:00
|
|
|
if (teardowndevice &&
|
2017-11-24 16:52:15 +00:00
|
|
|
qemuDomainNamespaceTeardownHostdev(vm, hostdev) < 0)
|
2016-11-16 14:27:47 +00:00
|
|
|
VIR_WARN("Unable to remove host device from /dev");
|
2013-12-05 19:59:05 +00:00
|
|
|
if (added)
|
2015-10-20 12:12:48 +00:00
|
|
|
qemuHostdevReAttachUSBDevices(driver, vm->def->name, &hostdev, 1);
|
2017-10-20 11:24:49 +00:00
|
|
|
virDomainUSBAddressRelease(priv->usbaddrs, hostdev->info);
|
2013-12-05 19:54:41 +00:00
|
|
|
}
|
2013-05-03 18:07:30 +00:00
|
|
|
return ret;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
|
2016-04-06 14:41:33 +00:00
|
|
|
|
2013-05-03 18:07:31 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachHostSCSIDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2013-05-03 18:07:31 +00:00
|
|
|
{
|
2016-06-27 14:43:47 +00:00
|
|
|
size_t i;
|
2013-05-03 18:07:31 +00:00
|
|
|
int ret = -1;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2016-04-11 17:32:12 +00:00
|
|
|
virErrorPtr orig_err;
|
2020-06-19 14:44:23 +00:00
|
|
|
g_autoptr(qemuBlockStorageSourceAttachData) data = NULL;
|
|
|
|
const char *backendalias = NULL;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *devstr = NULL;
|
2013-11-14 11:02:40 +00:00
|
|
|
bool teardowncgroup = false;
|
2013-12-05 19:54:41 +00:00
|
|
|
bool teardownlabel = false;
|
2016-11-16 14:27:47 +00:00
|
|
|
bool teardowndevice = false;
|
2013-05-03 18:07:31 +00:00
|
|
|
|
2016-06-27 14:43:47 +00:00
|
|
|
/* Let's make sure the disk has a controller defined and loaded before
|
|
|
|
* trying to add it. The controller used by the disk must exist before a
|
|
|
|
* qemu command line string is generated.
|
|
|
|
*
|
|
|
|
* Ensure that the given controller and all controllers with a smaller index
|
|
|
|
* exist; there must not be any missing index in between.
|
|
|
|
*/
|
|
|
|
for (i = 0; i <= hostdev->info->addr.drive.controller; i++) {
|
|
|
|
if (!qemuDomainFindOrCreateSCSIDiskController(driver, vm, i))
|
|
|
|
return -1;
|
|
|
|
}
|
2013-11-21 03:36:27 +00:00
|
|
|
|
2017-04-26 21:10:00 +00:00
|
|
|
if (qemuHostdevPrepareSCSIDevices(driver, vm->def->name, &hostdev, 1) < 0)
|
2013-05-03 18:07:31 +00:00
|
|
|
return -1;
|
|
|
|
|
2021-07-14 14:46:54 +00:00
|
|
|
if (qemuDomainNamespaceSetupHostdev(vm, hostdev, &teardowndevice) < 0)
|
2016-11-16 14:27:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-11-19 13:35:46 +00:00
|
|
|
if (qemuSetupHostdevCgroup(vm, hostdev) < 0)
|
2013-11-14 11:02:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
teardowncgroup = true;
|
|
|
|
|
2016-11-16 14:27:47 +00:00
|
|
|
if (qemuSecuritySetHostdevLabel(driver, vm, hostdev) < 0)
|
2013-12-05 19:54:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
teardownlabel = true;
|
|
|
|
|
2016-04-01 14:40:23 +00:00
|
|
|
if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1) < 0)
|
2013-05-03 18:07:31 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2020-09-10 10:32:04 +00:00
|
|
|
if (qemuDomainPrepareHostdev(hostdev, priv) < 0)
|
2020-10-15 13:06:01 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuProcessPrepareHostHostdev(hostdev) < 0)
|
2016-04-06 14:41:33 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2020-06-19 14:44:23 +00:00
|
|
|
if (!(data = qemuBuildHostdevSCSIAttachPrepare(hostdev, &backendalias,
|
|
|
|
priv->qemuCaps)))
|
2013-05-03 18:07:31 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2020-06-19 14:44:23 +00:00
|
|
|
if (!(devstr = qemuBuildSCSIHostdevDevStr(vm->def, hostdev, backendalias)))
|
2013-05-03 18:07:31 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2021-03-19 23:37:05 +00:00
|
|
|
VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1);
|
2013-05-03 18:07:31 +00:00
|
|
|
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
|
2020-06-19 14:44:23 +00:00
|
|
|
if (qemuBlockStorageSourceAttachApply(priv->mon, data) < 0)
|
2018-05-22 05:38:22 +00:00
|
|
|
goto exit_monitor;
|
2017-09-15 17:17:59 +00:00
|
|
|
|
2016-04-11 17:32:12 +00:00
|
|
|
if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
|
2016-07-14 21:15:10 +00:00
|
|
|
goto exit_monitor;
|
2016-04-11 17:32:12 +00:00
|
|
|
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
2016-07-14 21:15:10 +00:00
|
|
|
goto cleanup;
|
2016-04-11 17:32:12 +00:00
|
|
|
|
|
|
|
virDomainAuditHostdev(vm, hostdev, "attach", true);
|
2013-05-03 18:07:31 +00:00
|
|
|
|
|
|
|
vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
|
|
|
|
|
|
|
|
ret = 0;
|
2016-04-11 17:32:12 +00:00
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
cleanup:
|
2013-11-14 11:02:40 +00:00
|
|
|
if (ret < 0) {
|
2015-10-20 12:12:48 +00:00
|
|
|
qemuHostdevReAttachSCSIDevices(driver, vm->def->name, &hostdev, 1);
|
2013-11-14 11:02:40 +00:00
|
|
|
if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
|
|
|
|
VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
|
2013-12-05 19:54:41 +00:00
|
|
|
if (teardownlabel &&
|
2016-11-16 14:27:47 +00:00
|
|
|
qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
|
2013-12-05 19:54:41 +00:00
|
|
|
VIR_WARN("Unable to restore host device labelling on hotplug fail");
|
2016-11-16 14:27:47 +00:00
|
|
|
if (teardowndevice &&
|
2017-11-24 16:52:15 +00:00
|
|
|
qemuDomainNamespaceTeardownHostdev(vm, hostdev) < 0)
|
2016-11-16 14:27:47 +00:00
|
|
|
VIR_WARN("Unable to remove host device from /dev");
|
2013-11-14 11:02:40 +00:00
|
|
|
}
|
2017-09-15 17:17:59 +00:00
|
|
|
qemuDomainSecretHostdevDestroy(hostdev);
|
2013-05-03 18:07:31 +00:00
|
|
|
return ret;
|
2016-04-11 17:32:12 +00:00
|
|
|
|
2016-07-14 21:15:10 +00:00
|
|
|
exit_monitor:
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorPreserveLast(&orig_err);
|
2020-06-19 14:44:23 +00:00
|
|
|
qemuBlockStorageSourceAttachRollback(priv->mon, data);
|
2017-02-22 17:39:17 +00:00
|
|
|
ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorRestore(&orig_err);
|
2016-04-11 17:32:12 +00:00
|
|
|
|
|
|
|
virDomainAuditHostdev(vm, hostdev, "attach", false);
|
|
|
|
|
|
|
|
goto cleanup;
|
2013-05-03 18:07:31 +00:00
|
|
|
}
|
|
|
|
|
2016-11-22 03:58:19 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachSCSIVHostDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2016-11-22 03:58:19 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2016-11-22 03:58:19 +00:00
|
|
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV,
|
|
|
|
{ .hostdev = hostdev } };
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainCCWAddressSet *ccwaddrs = NULL;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *vhostfdName = NULL;
|
2016-11-22 03:58:19 +00:00
|
|
|
int vhostfd = -1;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *devstr = NULL;
|
2016-11-22 03:58:19 +00:00
|
|
|
bool teardowncgroup = false;
|
|
|
|
bool teardownlabel = false;
|
2017-02-04 17:54:10 +00:00
|
|
|
bool teardowndevice = false;
|
2016-11-22 03:58:19 +00:00
|
|
|
bool releaseaddr = false;
|
|
|
|
|
2017-04-26 21:10:01 +00:00
|
|
|
if (qemuHostdevPrepareSCSIVHostDevices(driver, vm->def->name, &hostdev, 1) < 0)
|
2016-11-22 03:58:19 +00:00
|
|
|
return -1;
|
|
|
|
|
2021-07-14 14:46:54 +00:00
|
|
|
if (qemuDomainNamespaceSetupHostdev(vm, hostdev, &teardowndevice) < 0)
|
2017-02-04 17:54:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-11-22 03:58:19 +00:00
|
|
|
if (qemuSetupHostdevCgroup(vm, hostdev) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
teardowncgroup = true;
|
|
|
|
|
2017-02-07 14:56:23 +00:00
|
|
|
if (qemuSecuritySetHostdevLabel(driver, vm, hostdev) < 0)
|
2016-11-22 03:58:19 +00:00
|
|
|
goto cleanup;
|
|
|
|
teardownlabel = true;
|
|
|
|
|
|
|
|
if (virSCSIVHostOpenVhostSCSI(&vhostfd) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
vhostfdName = g_strdup_printf("vhostfd-%d", vhostfd);
|
2016-11-22 03:58:19 +00:00
|
|
|
|
|
|
|
if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
|
2017-04-18 10:43:58 +00:00
|
|
|
if (qemuDomainIsS390CCW(vm->def) &&
|
2018-05-07 14:41:11 +00:00
|
|
|
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CCW))
|
2016-11-22 03:58:19 +00:00
|
|
|
hostdev->info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
|
|
|
|
hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
|
2016-11-03 20:33:32 +00:00
|
|
|
if (qemuDomainEnsurePCIAddress(vm, &dev, driver) < 0)
|
2016-11-22 03:58:19 +00:00
|
|
|
goto cleanup;
|
|
|
|
} else if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
|
2018-07-03 15:25:28 +00:00
|
|
|
if (!(ccwaddrs = virDomainCCWAddressSetCreateFromDomain(vm->def)))
|
2016-11-22 03:58:19 +00:00
|
|
|
goto cleanup;
|
|
|
|
if (virDomainCCWAddressAssign(hostdev->info, ccwaddrs,
|
|
|
|
!hostdev->info->addr.ccw.assigned) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
releaseaddr = true;
|
|
|
|
|
|
|
|
if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(devstr = qemuBuildSCSIVHostHostdevDevStr(vm->def,
|
|
|
|
hostdev,
|
|
|
|
priv->qemuCaps,
|
|
|
|
vhostfdName)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2021-03-19 23:37:05 +00:00
|
|
|
VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1);
|
2016-11-22 03:58:19 +00:00
|
|
|
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
|
2018-11-08 11:00:30 +00:00
|
|
|
if ((ret = qemuDomainAttachExtensionDevice(priv->mon, hostdev->info)) < 0)
|
|
|
|
goto exit_monitor;
|
|
|
|
|
|
|
|
if ((ret = qemuMonitorAddDeviceWithFd(priv->mon, devstr, vhostfd,
|
|
|
|
vhostfdName)) < 0) {
|
|
|
|
ignore_value(qemuDomainDetachExtensionDevice(priv->mon, hostdev->info));
|
|
|
|
goto exit_monitor;
|
|
|
|
}
|
2016-11-22 03:58:19 +00:00
|
|
|
|
2018-11-08 11:00:30 +00:00
|
|
|
exit_monitor:
|
2016-11-22 03:58:19 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0 || ret < 0)
|
|
|
|
goto audit;
|
|
|
|
|
|
|
|
vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
audit:
|
|
|
|
virDomainAuditHostdev(vm, hostdev, "attach", (ret == 0));
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (ret < 0) {
|
|
|
|
if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
|
|
|
|
VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
|
|
|
|
if (teardownlabel &&
|
2017-02-07 14:56:23 +00:00
|
|
|
qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
|
2016-11-22 03:58:19 +00:00
|
|
|
VIR_WARN("Unable to restore host device labelling on hotplug fail");
|
2017-02-04 17:54:10 +00:00
|
|
|
if (teardowndevice &&
|
2017-11-24 16:52:15 +00:00
|
|
|
qemuDomainNamespaceTeardownHostdev(vm, hostdev) < 0)
|
2017-02-04 17:54:10 +00:00
|
|
|
VIR_WARN("Unable to remove host device from /dev");
|
2016-11-22 03:58:19 +00:00
|
|
|
if (releaseaddr)
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, hostdev->info);
|
2016-11-22 03:58:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virDomainCCWAddressSetFree(ccwaddrs);
|
|
|
|
|
|
|
|
VIR_FORCE_CLOSE(vhostfd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-04-06 14:41:33 +00:00
|
|
|
|
2018-03-26 07:38:47 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachMediatedDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2018-03-26 07:38:47 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *devstr = NULL;
|
2018-03-26 07:38:47 +00:00
|
|
|
bool added = false;
|
|
|
|
bool teardowncgroup = false;
|
|
|
|
bool teardownlabel = false;
|
|
|
|
bool teardowndevice = false;
|
2019-09-03 20:09:48 +00:00
|
|
|
bool teardownmemlock = false;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2018-03-26 07:38:47 +00:00
|
|
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV,
|
|
|
|
{ .hostdev = hostdev } };
|
|
|
|
|
2018-06-26 11:47:39 +00:00
|
|
|
switch (hostdev->source.subsys.u.mdev.model) {
|
|
|
|
case VIR_MDEV_MODEL_TYPE_VFIO_PCI:
|
|
|
|
if (qemuDomainEnsurePCIAddress(vm, &dev, driver) < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
2019-10-28 08:06:13 +00:00
|
|
|
case VIR_MDEV_MODEL_TYPE_VFIO_CCW: {
|
|
|
|
bool releaseaddr = false;
|
|
|
|
|
2021-06-11 14:25:48 +00:00
|
|
|
if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev) < 0)
|
2019-10-28 08:06:13 +00:00
|
|
|
return -1;
|
|
|
|
} break;
|
2018-06-26 11:47:39 +00:00
|
|
|
case VIR_MDEV_MODEL_TYPE_LAST:
|
|
|
|
break;
|
|
|
|
}
|
2018-03-26 07:38:47 +00:00
|
|
|
|
|
|
|
if (qemuHostdevPrepareMediatedDevices(driver,
|
|
|
|
vm->def->name,
|
|
|
|
&hostdev,
|
|
|
|
1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
added = true;
|
|
|
|
|
2021-07-14 14:46:54 +00:00
|
|
|
if (qemuDomainNamespaceSetupHostdev(vm, hostdev, &teardowndevice) < 0)
|
2018-03-26 07:38:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuSetupHostdevCgroup(vm, hostdev) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
teardowncgroup = true;
|
|
|
|
|
|
|
|
if (qemuSecuritySetHostdevLabel(driver, vm, hostdev) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
teardownlabel = true;
|
|
|
|
|
|
|
|
if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(devstr = qemuBuildHostdevMediatedDevStr(vm->def, hostdev,
|
|
|
|
priv->qemuCaps)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2021-03-19 23:37:05 +00:00
|
|
|
VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1);
|
2018-03-26 07:38:47 +00:00
|
|
|
|
2019-09-03 20:09:48 +00:00
|
|
|
if (qemuDomainAdjustMaxMemLockHostdev(vm, hostdev) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
teardownmemlock = true;
|
|
|
|
|
2018-03-26 07:38:47 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
ret = qemuMonitorAddDevice(priv->mon, devstr);
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
|
|
ret = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainAuditHostdev(vm, hostdev, "attach", ret == 0);
|
|
|
|
if (ret < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
VIR_APPEND_ELEMENT_INPLACE(vm->def->hostdevs, vm->def->nhostdevs, hostdev);
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
if (ret < 0) {
|
2019-09-26 11:15:47 +00:00
|
|
|
if (teardownmemlock && qemuDomainAdjustMaxMemLock(vm, false) < 0)
|
2019-09-03 20:09:48 +00:00
|
|
|
VIR_WARN("Unable to reset maximum locked memory on hotplug fail");
|
2018-03-26 07:38:47 +00:00
|
|
|
if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
|
|
|
|
VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
|
|
|
|
if (teardownlabel &&
|
|
|
|
qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
|
|
|
|
VIR_WARN("Unable to restore host device labelling on hotplug fail");
|
|
|
|
if (teardowndevice &&
|
|
|
|
qemuDomainNamespaceTeardownHostdev(vm, hostdev) < 0)
|
|
|
|
VIR_WARN("Unable to remove host device from /dev");
|
|
|
|
if (added)
|
|
|
|
qemuHostdevReAttachMediatedDevices(driver,
|
|
|
|
vm->def->name,
|
|
|
|
&hostdev,
|
|
|
|
1);
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, hostdev->info);
|
2018-03-26 07:38:47 +00:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-06 14:41:33 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachHostDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2010-12-16 16:10:54 +00:00
|
|
|
{
|
|
|
|
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2017-05-11 13:26:47 +00:00
|
|
|
_("hotplug is not supported for hostdev mode '%s'"),
|
2012-07-18 15:22:03 +00:00
|
|
|
virDomainHostdevModeTypeToString(hostdev->mode));
|
2010-12-16 16:10:54 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (hostdev->source.subsys.type) {
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
|
2014-03-06 07:35:03 +00:00
|
|
|
if (qemuDomainAttachHostPCIDevice(driver, vm,
|
2011-05-04 12:09:09 +00:00
|
|
|
hostdev) < 0)
|
2020-01-06 21:57:40 +00:00
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
|
2014-03-06 07:35:03 +00:00
|
|
|
if (qemuDomainAttachHostUSBDevice(driver, vm,
|
2011-05-04 12:09:09 +00:00
|
|
|
hostdev) < 0)
|
2020-01-06 21:57:40 +00:00
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
break;
|
|
|
|
|
2013-05-03 18:07:31 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
|
2018-02-09 16:14:41 +00:00
|
|
|
if (qemuDomainAttachHostSCSIDevice(driver, vm,
|
2013-05-03 18:07:31 +00:00
|
|
|
hostdev) < 0)
|
2020-01-06 21:57:40 +00:00
|
|
|
return -1;
|
2013-05-03 18:07:31 +00:00
|
|
|
break;
|
|
|
|
|
2016-11-22 03:58:19 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
|
|
|
|
if (qemuDomainAttachSCSIVHostDevice(driver, vm, hostdev) < 0)
|
2020-01-06 21:57:40 +00:00
|
|
|
return -1;
|
2016-11-22 03:58:19 +00:00
|
|
|
break;
|
2018-03-26 07:38:47 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
|
|
|
|
if (qemuDomainAttachMediatedDevice(driver, vm, hostdev) < 0)
|
2020-01-06 21:57:40 +00:00
|
|
|
return -1;
|
2018-03-26 07:38:47 +00:00
|
|
|
break;
|
2016-11-22 03:58:19 +00:00
|
|
|
|
2010-12-16 16:10:54 +00:00
|
|
|
default:
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2017-05-11 13:26:47 +00:00
|
|
|
_("hotplug is not supported for hostdev subsys type '%s'"),
|
2012-07-18 15:22:03 +00:00
|
|
|
virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
|
2020-01-06 21:57:40 +00:00
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-12 13:40:48 +00:00
|
|
|
|
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachShmemDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainShmemDef *shmem)
|
2016-09-12 13:40:48 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *shmstr = NULL;
|
|
|
|
g_autofree char *charAlias = NULL;
|
|
|
|
g_autofree char *memAlias = NULL;
|
2016-09-12 13:40:48 +00:00
|
|
|
bool release_backing = false;
|
|
|
|
bool release_address = true;
|
|
|
|
virErrorPtr orig_err = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
virJSONValue *props = NULL;
|
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2016-09-07 16:29:30 +00:00
|
|
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_SHMEM, { .shmem = shmem } };
|
2016-09-12 13:40:48 +00:00
|
|
|
|
2021-04-27 15:04:36 +00:00
|
|
|
switch (shmem->model) {
|
2016-09-12 13:40:48 +00:00
|
|
|
case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_PLAIN:
|
|
|
|
case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_DOORBELL:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM:
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("live attach of shmem model '%s' is not supported"),
|
|
|
|
virDomainShmemModelTypeToString(shmem->model));
|
2019-10-15 11:38:21 +00:00
|
|
|
G_GNUC_FALLTHROUGH;
|
2016-09-12 13:40:48 +00:00
|
|
|
case VIR_DOMAIN_SHMEM_MODEL_LAST:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qemuAssignDeviceShmemAlias(vm->def, shmem, -1) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
qemuDomainPrepareShmemChardev(shmem);
|
2016-09-12 13:40:48 +00:00
|
|
|
|
2021-03-19 23:37:05 +00:00
|
|
|
VIR_REALLOC_N(vm->def->shmems, vm->def->nshmems + 1);
|
2016-09-12 13:40:48 +00:00
|
|
|
|
|
|
|
if ((shmem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
|
|
|
|
shmem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
|
2016-11-03 20:33:32 +00:00
|
|
|
(qemuDomainEnsurePCIAddress(vm, &dev, driver) < 0))
|
2016-09-12 13:40:48 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!(shmstr = qemuBuildShmemDevStr(vm->def, shmem, priv->qemuCaps)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (shmem->server.enabled) {
|
2019-10-22 13:26:14 +00:00
|
|
|
charAlias = g_strdup_printf("char%s", shmem->info.alias);
|
2016-09-12 13:40:48 +00:00
|
|
|
} else {
|
|
|
|
if (!(props = qemuBuildShmemBackendMemProps(shmem)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
|
|
|
|
if (shmem->server.enabled) {
|
|
|
|
if (qemuMonitorAttachCharDev(priv->mon, charAlias,
|
|
|
|
&shmem->server.chr) < 0)
|
|
|
|
goto exit_monitor;
|
|
|
|
} else {
|
2018-05-18 12:48:22 +00:00
|
|
|
if (qemuMonitorAddObject(priv->mon, &props, &memAlias) < 0)
|
2016-09-12 13:40:48 +00:00
|
|
|
goto exit_monitor;
|
|
|
|
}
|
|
|
|
|
|
|
|
release_backing = true;
|
|
|
|
|
2018-11-08 11:00:30 +00:00
|
|
|
if (qemuDomainAttachExtensionDevice(priv->mon, &shmem->info) < 0)
|
|
|
|
goto exit_monitor;
|
|
|
|
|
|
|
|
if (qemuMonitorAddDevice(priv->mon, shmstr) < 0) {
|
|
|
|
ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &shmem->info));
|
2016-09-12 13:40:48 +00:00
|
|
|
goto exit_monitor;
|
2018-11-08 11:00:30 +00:00
|
|
|
}
|
2016-09-12 13:40:48 +00:00
|
|
|
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
|
|
release_address = false;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Doing a copy here just so the pointer doesn't get nullified
|
|
|
|
* because we need it in the audit function */
|
|
|
|
VIR_APPEND_ELEMENT_COPY_INPLACE(vm->def->shmems, vm->def->nshmems, shmem);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
release_address = false;
|
|
|
|
|
|
|
|
audit:
|
|
|
|
virDomainAuditShmem(vm, shmem, "attach", ret == 0);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (release_address)
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &shmem->info);
|
2016-09-12 13:40:48 +00:00
|
|
|
|
|
|
|
virJSONValueFree(props);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
exit_monitor:
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorPreserveLast(&orig_err);
|
2016-09-12 13:40:48 +00:00
|
|
|
if (release_backing) {
|
|
|
|
if (shmem->server.enabled)
|
|
|
|
ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias));
|
|
|
|
else
|
2020-03-18 11:24:40 +00:00
|
|
|
ignore_value(qemuMonitorDelObject(priv->mon, memAlias, false));
|
2016-09-12 13:40:48 +00:00
|
|
|
}
|
|
|
|
|
2017-02-22 17:39:17 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
release_address = false;
|
|
|
|
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorRestore(&orig_err);
|
2016-09-12 13:40:48 +00:00
|
|
|
|
|
|
|
goto audit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-09-01 11:39:15 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachWatchdog(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainWatchdogDef *watchdog)
|
2017-09-01 11:39:15 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2017-09-01 11:39:15 +00:00
|
|
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_WATCHDOG, { .watchdog = watchdog } };
|
|
|
|
virDomainWatchdogAction actualAction = watchdog->action;
|
|
|
|
const char *actionStr = NULL;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *watchdogstr = NULL;
|
2017-09-01 11:39:15 +00:00
|
|
|
bool releaseAddress = false;
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
if (vm->def->watchdog) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("domain already has a watchdog"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qemuAssignDeviceWatchdogAlias(watchdog) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (watchdog->model == VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB) {
|
|
|
|
if (qemuDomainEnsurePCIAddress(vm, &dev, driver) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
releaseAddress = true;
|
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("hotplug of watchdog of model %s is not supported"),
|
|
|
|
virDomainWatchdogModelTypeToString(watchdog->model));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
qemu: fix i6300esb watchdog hotplug on Q35
When commit 361c8dc17 added support for hotplugging the i6300esb
watchdog device (first in libvirt-3.9.0), it accidentally contstructed
the commandline for the device_add command before allocating a PCI
address for the device. With no PCI address specified in the command,
the watchdog would simply be placed at the lowest unused PCI slot.
On a 440fx guest, this doesn't cause a problem, because libvirt's PCI
address allocation algorithm would most likely give the same address
anyway (usually a slot on pci-root), so nobody noticed the omission of
address from the command.
But on a Q35 guest, the lowest unused PCI slot is on pcie-root, which
doesn't support hotplug; libvirt knows enough to assign a PCI address
that is on a pcie-to-pci-bridge (because its slots *do* support
hotplug), but qemu doesn't, so if there is no PCI address in the
command, qemu just tries to plug the new device into pcie-root, and
fails because it doesn't support hotplug, e.g.:
error: Failed to attach device from watchdog.xml
error: internal error: unable to execute QEMU command 'device_add':
Bus 'pcie.0' does not support hotplugging
The solution is simply to build the command string after assigning a
PCI address, not before.
Resolves: https://bugzilla.redhat.com/1666559
Signed-off-by: Laine Stump <laine@laine.org>
Reviewed-by: John Ferlan <jferlan@redhat.com>
2019-01-17 20:05:54 +00:00
|
|
|
if (!(watchdogstr = qemuBuildWatchdogDevStr(vm->def, watchdog, priv->qemuCaps)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2017-09-01 11:39:15 +00:00
|
|
|
/* QEMU doesn't have a 'dump' action; we tell qemu to 'pause', then
|
|
|
|
libvirt listens for the watchdog event, and we perform the dump
|
|
|
|
ourselves. so convert 'dump' to 'pause' for the qemu cli */
|
|
|
|
if (actualAction == VIR_DOMAIN_WATCHDOG_ACTION_DUMP)
|
|
|
|
actualAction = VIR_DOMAIN_WATCHDOG_ACTION_PAUSE;
|
|
|
|
|
|
|
|
actionStr = virDomainWatchdogActionTypeToString(actualAction);
|
|
|
|
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
|
|
|
|
rv = qemuMonitorSetWatchdogAction(priv->mon, actionStr);
|
|
|
|
|
|
|
|
if (rv >= 0)
|
|
|
|
rv = qemuMonitorAddDevice(priv->mon, watchdogstr);
|
|
|
|
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
|
|
releaseAddress = false;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rv < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
releaseAddress = false;
|
|
|
|
vm->def->watchdog = watchdog;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (releaseAddress)
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &watchdog->info);
|
2017-09-01 11:39:15 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-04 09:09:27 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachInputDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainInputDef *input)
|
2017-10-04 09:09:27 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *devstr = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2017-10-04 09:09:27 +00:00
|
|
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_INPUT,
|
|
|
|
{ .input = input } };
|
2017-11-21 12:56:37 +00:00
|
|
|
virErrorPtr originalError = NULL;
|
2017-10-04 09:09:27 +00:00
|
|
|
bool releaseaddr = false;
|
2017-11-21 12:56:37 +00:00
|
|
|
bool teardowndevice = false;
|
|
|
|
bool teardownlabel = false;
|
|
|
|
bool teardowncgroup = false;
|
2017-10-04 09:09:27 +00:00
|
|
|
|
|
|
|
if (input->bus != VIR_DOMAIN_INPUT_BUS_USB &&
|
|
|
|
input->bus != VIR_DOMAIN_INPUT_BUS_VIRTIO) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("input device on bus '%s' cannot be hot plugged."),
|
|
|
|
virDomainInputBusTypeToString(input->bus));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (input->bus == VIR_DOMAIN_INPUT_BUS_VIRTIO) {
|
2021-06-11 14:25:48 +00:00
|
|
|
if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev) < 0)
|
2017-10-04 09:09:27 +00:00
|
|
|
return -1;
|
|
|
|
} else if (input->bus == VIR_DOMAIN_INPUT_BUS_USB) {
|
2017-10-20 11:28:21 +00:00
|
|
|
if (virDomainUSBAddressEnsure(priv->usbaddrs, &input->info) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
releaseaddr = true;
|
2017-10-04 09:09:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (qemuAssignDeviceInputAlias(vm->def, input, -1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuBuildInputDevStr(&devstr, vm->def, input, priv->qemuCaps) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2021-07-14 14:46:54 +00:00
|
|
|
if (qemuDomainNamespaceSetupInput(vm, input, &teardowndevice) < 0)
|
2017-11-21 12:56:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuSetupInputCgroup(vm, input) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
teardowncgroup = true;
|
|
|
|
|
|
|
|
if (qemuSecuritySetInputLabel(vm, input) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
teardownlabel = true;
|
|
|
|
|
2021-03-19 23:37:05 +00:00
|
|
|
VIR_REALLOC_N(vm->def->inputs, vm->def->ninputs + 1);
|
2017-10-04 09:09:27 +00:00
|
|
|
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2018-11-08 11:00:30 +00:00
|
|
|
|
|
|
|
if (qemuDomainAttachExtensionDevice(priv->mon, &input->info) < 0)
|
2017-10-04 09:09:27 +00:00
|
|
|
goto exit_monitor;
|
|
|
|
|
2018-11-08 11:00:30 +00:00
|
|
|
if (qemuMonitorAddDevice(priv->mon, devstr) < 0) {
|
|
|
|
ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &input->info));
|
|
|
|
goto exit_monitor;
|
|
|
|
}
|
|
|
|
|
2017-10-04 09:09:27 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
|
|
releaseaddr = false;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_APPEND_ELEMENT_COPY_INPLACE(vm->def->inputs, vm->def->ninputs, input);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
audit:
|
|
|
|
virDomainAuditInput(vm, input, "attach", ret == 0);
|
|
|
|
|
|
|
|
cleanup:
|
2017-11-21 12:56:37 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
virErrorPreserveLast(&originalError);
|
|
|
|
if (teardownlabel)
|
|
|
|
qemuSecurityRestoreInputLabel(vm, input);
|
|
|
|
if (teardowncgroup)
|
|
|
|
qemuTeardownInputCgroup(vm, input);
|
|
|
|
if (teardowndevice)
|
|
|
|
qemuDomainNamespaceTeardownInput(vm, input);
|
|
|
|
if (releaseaddr)
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &input->info);
|
2017-11-21 12:56:37 +00:00
|
|
|
virErrorRestore(&originalError);
|
|
|
|
}
|
2017-10-04 09:09:27 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
exit_monitor:
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
|
|
releaseaddr = false;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
goto audit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-05-30 11:53:52 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachVsockDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainVsockDef *vsock)
|
2018-05-30 11:53:52 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainVsockPrivate *vsockPriv = (qemuDomainVsockPrivate *)vsock->privateData;
|
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2018-05-30 11:53:52 +00:00
|
|
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_VSOCK,
|
|
|
|
{ .vsock = vsock } };
|
|
|
|
virErrorPtr originalError = NULL;
|
|
|
|
const char *fdprefix = "vsockfd";
|
|
|
|
bool releaseaddr = false;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *fdname = NULL;
|
|
|
|
g_autofree char *devstr = NULL;
|
2018-05-30 11:53:52 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (vm->def->vsock) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("the domain already has a vsock device"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-06-11 14:25:48 +00:00
|
|
|
if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev) < 0)
|
2018-05-30 11:53:52 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuAssignDeviceVsockAlias(vsock) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuProcessOpenVhostVsock(vsock) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
fdname = g_strdup_printf("%s%u", fdprefix, vsockPriv->vhostfd);
|
2018-05-30 11:53:52 +00:00
|
|
|
|
|
|
|
if (!(devstr = qemuBuildVsockDevStr(vm->def, vsock, priv->qemuCaps, fdprefix)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2018-11-08 11:00:30 +00:00
|
|
|
|
|
|
|
if (qemuDomainAttachExtensionDevice(priv->mon, &vsock->info) < 0)
|
|
|
|
goto exit_monitor;
|
|
|
|
|
|
|
|
if (qemuMonitorAddDeviceWithFd(priv->mon, devstr, vsockPriv->vhostfd, fdname) < 0) {
|
|
|
|
ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &vsock->info));
|
2018-05-30 11:53:52 +00:00
|
|
|
goto exit_monitor;
|
2018-11-08 11:00:30 +00:00
|
|
|
}
|
2018-05-30 11:53:52 +00:00
|
|
|
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
|
|
releaseaddr = false;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-10-16 11:43:18 +00:00
|
|
|
vm->def->vsock = g_steal_pointer(&vsock);
|
2018-05-30 11:53:52 +00:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (ret < 0) {
|
|
|
|
virErrorPreserveLast(&originalError);
|
|
|
|
if (releaseaddr)
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &vsock->info);
|
2018-05-30 11:53:52 +00:00
|
|
|
virErrorRestore(&originalError);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
exit_monitor:
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
releaseaddr = false;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-19 17:42:55 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainAttachLease(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainLeaseDef *lease)
|
2019-03-19 17:42:55 +00:00
|
|
|
{
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
2019-03-19 17:42:55 +00:00
|
|
|
|
2020-11-06 03:33:00 +00:00
|
|
|
virDomainLeaseInsertPreAlloc(vm->def);
|
2019-03-19 17:42:55 +00:00
|
|
|
|
|
|
|
if (virDomainLockLeaseAttach(driver->lockManager, cfg->uri,
|
|
|
|
vm, lease) < 0) {
|
|
|
|
virDomainLeaseInsertPreAlloced(vm->def, NULL);
|
2019-10-17 15:44:02 +00:00
|
|
|
return -1;
|
2019-03-19 17:42:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virDomainLeaseInsertPreAlloced(vm->def, lease);
|
2019-10-17 15:44:02 +00:00
|
|
|
return 0;
|
2019-03-19 17:42:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainChangeNetBridge(virDomainObj *vm,
|
|
|
|
virDomainNetDef *olddev,
|
|
|
|
virDomainNetDef *newdev)
|
2012-03-28 19:11:09 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2014-11-21 17:51:13 +00:00
|
|
|
const char *oldbridge = virDomainNetGetActualBridgeName(olddev);
|
|
|
|
const char *newbridge = virDomainNetGetActualBridgeName(newdev);
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
|
2014-11-21 17:51:13 +00:00
|
|
|
if (!oldbridge || !newbridge) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing bridge name"));
|
2019-11-12 20:46:27 +00:00
|
|
|
return -1;
|
2014-11-21 17:51:13 +00:00
|
|
|
}
|
2012-03-28 19:11:09 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Change bridge for interface %s: %s -> %s",
|
|
|
|
olddev->ifname, oldbridge, newbridge);
|
|
|
|
|
|
|
|
if (virNetDevExists(newbridge) != 1) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("bridge %s doesn't exist"), newbridge);
|
2019-11-12 20:46:27 +00:00
|
|
|
return -1;
|
2012-03-28 19:11:09 +00:00
|
|
|
}
|
|
|
|
|
2019-02-27 14:03:10 +00:00
|
|
|
ret = virNetDevBridgeRemovePort(oldbridge, olddev->ifname);
|
|
|
|
virDomainAuditNet(vm, olddev, NULL, "detach", ret == 0);
|
|
|
|
if (ret < 0) {
|
|
|
|
/* warn but continue - possibly the old network
|
|
|
|
* had been destroyed and reconstructed, leaving the
|
|
|
|
* tap device orphaned.
|
|
|
|
*/
|
|
|
|
VIR_WARN("Unable to detach device %s from bridge %s",
|
|
|
|
olddev->ifname, oldbridge);
|
2012-03-28 19:11:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = virNetDevBridgeAddPort(newbridge, olddev->ifname);
|
2020-02-13 17:57:47 +00:00
|
|
|
if (ret == 0 &&
|
|
|
|
virDomainNetGetActualPortOptionsIsolated(newdev) == VIR_TRISTATE_BOOL_YES) {
|
|
|
|
|
|
|
|
ret = virNetDevBridgePortSetIsolated(newbridge, olddev->ifname, true);
|
|
|
|
if (ret < 0) {
|
|
|
|
virErrorPtr err;
|
|
|
|
|
|
|
|
virErrorPreserveLast(&err);
|
|
|
|
ignore_value(virNetDevBridgeRemovePort(newbridge, olddev->ifname));
|
|
|
|
virErrorRestore(&err);
|
|
|
|
}
|
|
|
|
}
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
virDomainAuditNet(vm, NULL, newdev, "attach", ret == 0);
|
2012-03-28 19:11:09 +00:00
|
|
|
if (ret < 0) {
|
2020-02-13 16:57:43 +00:00
|
|
|
virErrorPtr err;
|
|
|
|
|
|
|
|
virErrorPreserveLast(&err);
|
2012-03-28 19:11:09 +00:00
|
|
|
ret = virNetDevBridgeAddPort(oldbridge, olddev->ifname);
|
2020-02-13 17:57:47 +00:00
|
|
|
if (ret == 0 &&
|
|
|
|
virDomainNetGetActualPortOptionsIsolated(olddev) == VIR_TRISTATE_BOOL_YES) {
|
|
|
|
ignore_value(virNetDevBridgePortSetIsolated(newbridge, olddev->ifname, true));
|
|
|
|
}
|
2012-03-28 19:11:09 +00:00
|
|
|
virDomainAuditNet(vm, NULL, olddev, "attach", ret == 0);
|
2020-02-13 16:57:43 +00:00
|
|
|
virErrorRestore(&err);
|
|
|
|
return -1;
|
2012-03-28 19:11:09 +00:00
|
|
|
}
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
/* caller will replace entire olddev with newdev in domain nets list */
|
2019-10-17 15:44:02 +00:00
|
|
|
return 0;
|
2012-03-28 19:11:09 +00:00
|
|
|
}
|
|
|
|
|
2012-11-12 16:21:10 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainChangeNetFilter(virDomainObj *vm,
|
|
|
|
virDomainNetDef *olddev,
|
|
|
|
virDomainNetDef *newdev)
|
2012-11-12 16:21:10 +00:00
|
|
|
{
|
|
|
|
/* make sure this type of device supports filters. */
|
|
|
|
switch (virDomainNetGetActualType(newdev)) {
|
|
|
|
case VIR_DOMAIN_NET_TYPE_ETHERNET:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
2018-08-08 15:27:53 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_NETWORK:
|
2019-04-30 12:26:25 +00:00
|
|
|
break;
|
2018-02-14 09:43:59 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_USER:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_SERVER:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_CLIENT:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_MCAST:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_INTERNAL:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_DIRECT:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_UDP:
|
2020-10-14 17:08:25 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_VDPA:
|
2012-11-12 16:21:10 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("filters not supported on interfaces of type %s"),
|
|
|
|
virDomainNetTypeToString(virDomainNetGetActualType(newdev)));
|
|
|
|
return -1;
|
2018-02-14 09:43:59 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_LAST:
|
|
|
|
default:
|
|
|
|
virReportEnumRangeError(virDomainNetType,
|
|
|
|
virDomainNetGetActualType(newdev));
|
|
|
|
return -1;
|
2012-11-12 16:21:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virDomainConfNWFilterTeardown(olddev);
|
|
|
|
|
2014-05-01 08:40:41 +00:00
|
|
|
if (newdev->filter &&
|
2018-04-27 13:28:11 +00:00
|
|
|
virDomainConfNWFilterInstantiate(vm->def->name,
|
2018-05-11 17:39:27 +00:00
|
|
|
vm->def->uuid, newdev, false) < 0) {
|
2012-11-12 16:21:10 +00:00
|
|
|
virErrorPtr errobj;
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("failed to add new filter rules to '%s' "
|
|
|
|
"- attempting to restore old rules"),
|
|
|
|
olddev->ifname);
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorPreserveLast(&errobj);
|
2018-04-27 13:28:11 +00:00
|
|
|
ignore_value(virDomainConfNWFilterInstantiate(vm->def->name,
|
2018-05-11 17:39:27 +00:00
|
|
|
vm->def->uuid, olddev, false));
|
2017-09-12 08:32:27 +00:00
|
|
|
virErrorRestore(&errobj);
|
2012-11-12 16:21:10 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
int qemuDomainChangeNetLinkState(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainNetDef *dev,
|
2011-09-06 08:23:47 +00:00
|
|
|
int linkstate)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2011-09-06 08:23:47 +00:00
|
|
|
|
|
|
|
if (!dev->info.alias) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
|
_("can't change link state: device alias not found"));
|
2011-09-06 08:23:47 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-09-24 12:30:09 +00:00
|
|
|
VIR_DEBUG("dev: %s, state: %d", dev->info.alias, linkstate);
|
|
|
|
|
2013-02-06 18:17:20 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2011-09-06 08:23:47 +00:00
|
|
|
|
|
|
|
ret = qemuMonitorSetLink(priv->mon, dev->info.alias, linkstate);
|
|
|
|
if (ret < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* modify the device configuration */
|
|
|
|
dev->linkstate = linkstate;
|
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
cleanup:
|
2015-01-07 12:12:18 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
return -1;
|
2011-09-06 08:23:47 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainChangeNet(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainDeviceDef *dev)
|
2011-09-06 08:23:47 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
|
|
|
virDomainNetDef *newdev = dev->data.net;
|
|
|
|
virDomainNetDef **devslot = NULL;
|
|
|
|
virDomainNetDef *olddev;
|
2016-09-23 15:04:53 +00:00
|
|
|
virDomainNetType oldType, newType;
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
bool needReconnect = false;
|
|
|
|
bool needBridgeChange = false;
|
2012-11-12 16:21:10 +00:00
|
|
|
bool needFilterChange = false;
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
bool needLinkStateChange = false;
|
|
|
|
bool needReplaceDevDef = false;
|
2013-10-01 13:04:48 +00:00
|
|
|
bool needBandwidthSet = false;
|
2017-06-15 12:22:26 +00:00
|
|
|
bool needCoalesceChange = false;
|
2017-07-17 15:49:00 +00:00
|
|
|
bool needVlanUpdate = false;
|
2020-02-14 18:51:31 +00:00
|
|
|
bool needIsolatedPortChange = false;
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
int ret = -1;
|
2015-06-08 08:25:10 +00:00
|
|
|
int changeidx = -1;
|
2019-10-17 15:44:01 +00:00
|
|
|
g_autoptr(virConnect) conn = NULL;
|
2019-04-30 14:17:14 +00:00
|
|
|
virErrorPtr save_err = NULL;
|
2015-06-08 08:25:10 +00:00
|
|
|
|
|
|
|
if ((changeidx = virDomainNetFindIdx(vm->def, newdev)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
devslot = &vm->def->nets[changeidx];
|
2018-02-22 12:24:58 +00:00
|
|
|
olddev = *devslot;
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
|
|
|
|
oldType = virDomainNetGetActualType(olddev);
|
2020-10-14 17:08:27 +00:00
|
|
|
if (oldType == VIR_DOMAIN_NET_TYPE_HOSTDEV ||
|
|
|
|
oldType == VIR_DOMAIN_NET_TYPE_VDPA) {
|
|
|
|
/* no changes are possible to a type='hostdev' or type='vdpa' interface */
|
2013-03-20 15:57:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
2020-10-14 17:08:27 +00:00
|
|
|
_("cannot change config of '%s' network interface type"),
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
virDomainNetTypeToString(oldType));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check individual attributes for changes that can't be done to a
|
|
|
|
* live netdev. These checks *mostly* go in order of the
|
|
|
|
* declarations in virDomainNetDef in order to assure nothing is
|
|
|
|
* omitted. (exceptiong where noted in comments - in particular,
|
|
|
|
* some things require that a new "actual device" be allocated
|
|
|
|
* from the network driver first, but we delay doing that until
|
|
|
|
* after we've made as many other checks as possible)
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* type: this can change (with some restrictions), but the actual
|
|
|
|
* type of the new device connection isn't known until after we
|
|
|
|
* allocate the "actual" device.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (virMacAddrCmp(&olddev->mac, &newdev->mac)) {
|
|
|
|
char oldmac[VIR_MAC_STRING_BUFLEN], newmac[VIR_MAC_STRING_BUFLEN];
|
|
|
|
|
2013-03-20 15:57:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
_("cannot change network interface mac address "
|
|
|
|
"from %s to %s"),
|
|
|
|
virMacAddrFormat(&olddev->mac, oldmac),
|
|
|
|
virMacAddrFormat(&newdev->mac, newmac));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-01-17 22:06:28 +00:00
|
|
|
if (STRNEQ_NULLABLE(virDomainNetGetModelString(olddev),
|
|
|
|
virDomainNetGetModelString(newdev))) {
|
2013-03-20 15:57:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
_("cannot modify network device model from %s to %s"),
|
2019-01-17 22:06:28 +00:00
|
|
|
NULLSTR(virDomainNetGetModelString(olddev)),
|
|
|
|
NULLSTR(virDomainNetGetModelString(newdev)));
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
goto cleanup;
|
2011-09-06 08:23:47 +00:00
|
|
|
}
|
|
|
|
|
2019-01-18 00:12:27 +00:00
|
|
|
if (olddev->model != newdev->model) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("cannot modify network device model from %s to %s"),
|
|
|
|
virDomainNetModelTypeToString(olddev->model),
|
|
|
|
virDomainNetModelTypeToString(newdev->model));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-01-21 22:59:02 +00:00
|
|
|
if (virDomainNetIsVirtioModel(olddev) &&
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
(olddev->driver.virtio.name != newdev->driver.virtio.name ||
|
|
|
|
olddev->driver.virtio.txmode != newdev->driver.virtio.txmode ||
|
|
|
|
olddev->driver.virtio.ioeventfd != newdev->driver.virtio.ioeventfd ||
|
2013-12-03 10:40:38 +00:00
|
|
|
olddev->driver.virtio.event_idx != newdev->driver.virtio.event_idx ||
|
2014-10-30 12:32:00 +00:00
|
|
|
olddev->driver.virtio.queues != newdev->driver.virtio.queues ||
|
2017-08-31 09:33:06 +00:00
|
|
|
olddev->driver.virtio.rx_queue_size != newdev->driver.virtio.rx_queue_size ||
|
|
|
|
olddev->driver.virtio.tx_queue_size != newdev->driver.virtio.tx_queue_size ||
|
2014-10-30 12:32:00 +00:00
|
|
|
olddev->driver.virtio.host.csum != newdev->driver.virtio.host.csum ||
|
|
|
|
olddev->driver.virtio.host.gso != newdev->driver.virtio.host.gso ||
|
|
|
|
olddev->driver.virtio.host.tso4 != newdev->driver.virtio.host.tso4 ||
|
|
|
|
olddev->driver.virtio.host.tso6 != newdev->driver.virtio.host.tso6 ||
|
|
|
|
olddev->driver.virtio.host.ecn != newdev->driver.virtio.host.ecn ||
|
|
|
|
olddev->driver.virtio.host.ufo != newdev->driver.virtio.host.ufo ||
|
2015-02-06 14:40:19 +00:00
|
|
|
olddev->driver.virtio.host.mrg_rxbuf != newdev->driver.virtio.host.mrg_rxbuf ||
|
2014-10-30 12:32:00 +00:00
|
|
|
olddev->driver.virtio.guest.csum != newdev->driver.virtio.guest.csum ||
|
|
|
|
olddev->driver.virtio.guest.tso4 != newdev->driver.virtio.guest.tso4 ||
|
|
|
|
olddev->driver.virtio.guest.tso6 != newdev->driver.virtio.guest.tso6 ||
|
|
|
|
olddev->driver.virtio.guest.ecn != newdev->driver.virtio.guest.ecn ||
|
|
|
|
olddev->driver.virtio.guest.ufo != newdev->driver.virtio.guest.ufo)) {
|
2013-03-20 15:57:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
_("cannot modify virtio network device driver attributes"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2021-01-06 11:12:40 +00:00
|
|
|
if (!!olddev->virtio != !!newdev->virtio ||
|
|
|
|
(olddev->virtio && newdev->virtio &&
|
|
|
|
(olddev->virtio->iommu != newdev->virtio->iommu ||
|
|
|
|
olddev->virtio->ats != newdev->virtio->ats ||
|
|
|
|
olddev->virtio->packed != newdev->virtio->packed))) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("cannot modify virtio network device driver options"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
/* data: this union will be examined later, after allocating new actualdev */
|
|
|
|
/* virtPortProfile: will be examined later, after allocating new actualdev */
|
|
|
|
|
|
|
|
if (olddev->tune.sndbuf_specified != newdev->tune.sndbuf_specified ||
|
|
|
|
olddev->tune.sndbuf != newdev->tune.sndbuf) {
|
|
|
|
needReconnect = true;
|
2011-09-06 08:23:47 +00:00
|
|
|
}
|
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
if (STRNEQ_NULLABLE(olddev->script, newdev->script)) {
|
2013-03-20 15:57:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
_("cannot modify network device script attribute"));
|
|
|
|
goto cleanup;
|
2012-07-30 06:03:25 +00:00
|
|
|
}
|
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
/* ifname: check if it's set in newdev. If not, retain the autogenerated one */
|
2019-10-18 13:08:21 +00:00
|
|
|
if (!newdev->ifname)
|
|
|
|
newdev->ifname = g_strdup(olddev->ifname);
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
if (STRNEQ_NULLABLE(olddev->ifname, newdev->ifname)) {
|
2013-03-20 15:57:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
_("cannot modify network device tap name"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-09-06 08:23:47 +00:00
|
|
|
|
2018-08-24 10:28:41 +00:00
|
|
|
/* info: Nothing is allowed to change. First fill the missing newdev->info
|
|
|
|
* from olddev and then check for changes.
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
*/
|
2018-08-24 10:28:41 +00:00
|
|
|
/* if pci addr is missing or is invalid we overwrite it from olddev */
|
|
|
|
if (newdev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
|
|
|
|
!virDomainDeviceAddressIsValid(&newdev->info,
|
|
|
|
newdev->info.type)) {
|
|
|
|
newdev->info.type = olddev->info.type;
|
|
|
|
newdev->info.addr = olddev->info.addr;
|
|
|
|
}
|
|
|
|
if (olddev->info.type != newdev->info.type) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("cannot modify network device address type"));
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
}
|
2016-04-03 18:16:51 +00:00
|
|
|
if (!virPCIDeviceAddressEqual(&olddev->info.addr.pci,
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
&newdev->info.addr.pci)) {
|
2013-03-20 15:57:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
_("cannot modify network device guest PCI address"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
/* grab alias from olddev if not set in newdev */
|
2019-10-18 13:08:21 +00:00
|
|
|
if (!newdev->info.alias)
|
|
|
|
newdev->info.alias = g_strdup(olddev->info.alias);
|
2018-06-12 14:05:10 +00:00
|
|
|
|
|
|
|
/* device alias is checked already in virDomainDefCompatibleDevice */
|
|
|
|
|
2021-04-07 11:48:30 +00:00
|
|
|
if (newdev->info.rombar == VIR_TRISTATE_SWITCH_ABSENT)
|
2018-08-24 10:28:41 +00:00
|
|
|
newdev->info.rombar = olddev->info.rombar;
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
if (olddev->info.rombar != newdev->info.rombar) {
|
2013-03-20 15:57:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
_("cannot modify network device rom bar setting"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2018-08-24 10:28:41 +00:00
|
|
|
|
2019-10-18 13:08:21 +00:00
|
|
|
if (!newdev->info.romfile)
|
|
|
|
newdev->info.romfile = g_strdup(olddev->info.romfile);
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
if (STRNEQ_NULLABLE(olddev->info.romfile, newdev->info.romfile)) {
|
2013-03-20 15:57:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
_("cannot modify network rom file"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2018-08-24 10:28:41 +00:00
|
|
|
|
|
|
|
if (newdev->info.bootIndex == 0)
|
|
|
|
newdev->info.bootIndex = olddev->info.bootIndex;
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
if (olddev->info.bootIndex != newdev->info.bootIndex) {
|
2013-03-20 15:57:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
_("cannot modify network device boot index setting"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2018-08-24 10:28:41 +00:00
|
|
|
|
|
|
|
if (newdev->info.romenabled == VIR_TRISTATE_BOOL_ABSENT)
|
|
|
|
newdev->info.romenabled = olddev->info.romenabled;
|
2018-07-13 13:07:58 +00:00
|
|
|
if (olddev->info.romenabled != newdev->info.romenabled) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("cannot modify network device rom enabled setting"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
/* (end of device info checks) */
|
2011-09-06 08:23:47 +00:00
|
|
|
|
2012-11-12 16:21:10 +00:00
|
|
|
if (STRNEQ_NULLABLE(olddev->filter, newdev->filter) ||
|
|
|
|
!virNWFilterHashTableEqual(olddev->filterparams, newdev->filterparams)) {
|
|
|
|
needFilterChange = true;
|
|
|
|
}
|
2011-09-06 08:23:47 +00:00
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
/* bandwidth can be modified, and will be checked later */
|
|
|
|
/* vlan can be modified, and will be checked later */
|
|
|
|
/* linkstate can be modified */
|
|
|
|
|
2017-06-08 11:45:31 +00:00
|
|
|
if (olddev->mtu != newdev->mtu) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("cannot modify MTU"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
/* allocate new actual device to compare to old - we will need to
|
|
|
|
* free it if we fail for any reason
|
|
|
|
*/
|
2018-07-26 14:32:04 +00:00
|
|
|
if (newdev->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
|
|
|
if (!(conn = virGetConnectNetwork()))
|
|
|
|
goto cleanup;
|
|
|
|
if (virDomainNetAllocateActualDevice(conn, vm->def, newdev) < 0)
|
|
|
|
goto cleanup;
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
}
|
|
|
|
|
2019-09-13 01:22:30 +00:00
|
|
|
/* final validation now that we have full info on the type */
|
|
|
|
if (qemuDomainValidateActualNetDef(newdev, priv->qemuCaps) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
newType = virDomainNetGetActualType(newdev);
|
|
|
|
|
2020-10-14 17:08:27 +00:00
|
|
|
if (newType == VIR_DOMAIN_NET_TYPE_HOSTDEV ||
|
|
|
|
newType == VIR_DOMAIN_NET_TYPE_VDPA) {
|
|
|
|
/* can't turn it into a type='hostdev' or type='vdpa' interface */
|
2013-03-20 15:57:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
_("cannot change network interface type to '%s'"),
|
|
|
|
virDomainNetTypeToString(newType));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (olddev->type == newdev->type && oldType == newType) {
|
2011-09-06 08:23:47 +00:00
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
/* if type hasn't changed, check the relevant fields for the type */
|
|
|
|
switch (newdev->type) {
|
|
|
|
case VIR_DOMAIN_NET_TYPE_USER:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_NET_TYPE_ETHERNET:
|
conf/openvz: eliminate incorrect/undocumented use of <source dev='blah'/>
When support for <interface type='ethernet'> was added in commit
9a4b705f back in 2010, it erroneously looked at <source dev='blah'/>
for a user-specified guest-side interface name. This was never
documented though. (that attribute already existed at the time in the
data.ethernet union member of virDomainNetDef, but apparently had no
practical use - it was only used as a storage place for a NetDef's
bridge name during qemuDomainXMLToNative(), but even then that was
never used for anything).
When support for similar guest-side device naming was added to the lxc
driver several years later, it was put in a new subelement <guest
dev='blah'/>.
In the intervening years, since there was no validation that
ethernet.dev was NULL in the other drivers that didn't actually use
it, innocent souls who were adding other features assuming they needed
to account for non-NULL ethernet.dev when really they didn't, so
little bits of the usual pointless cargo-cult code showed up.
This patch not only switches the openvz driver to use the documented
<guest dev='blah'/> notation for naming the guest-side device (just in
case anyone is still using the openvz driver), and logs an error if
anyone tries to set <source dev='blah'/> for a type='ethernet'
interface, it also removes the cargo-cult uses of ethernet.dev and
<source dev='blah'/>, and eliminates if from the RNG and from
virDomainNetDef.
NB: I decided on this course of action after mentioning the
inconsistency here:
https://www.redhat.com/archives/libvir-list/2016-May/msg02038.html
and getting encouragement do eliminate it in a later IRC discussion
with danpb.
2016-06-21 19:20:57 +00:00
|
|
|
break;
|
2011-09-06 08:23:47 +00:00
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_SERVER:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_CLIENT:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_MCAST:
|
2015-08-29 20:19:10 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_UDP:
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
if (STRNEQ_NULLABLE(olddev->data.socket.address,
|
|
|
|
newdev->data.socket.address) ||
|
|
|
|
olddev->data.socket.port != newdev->data.socket.port) {
|
|
|
|
needReconnect = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_NET_TYPE_NETWORK:
|
|
|
|
if (STRNEQ(olddev->data.network.name, newdev->data.network.name)) {
|
|
|
|
if (virDomainNetGetActualVirtPortProfile(newdev))
|
|
|
|
needReconnect = true;
|
|
|
|
else
|
|
|
|
needBridgeChange = true;
|
|
|
|
}
|
|
|
|
/* other things handled in common code directly below this switch */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
|
|
|
/* all handled in bridge name checked in common code below */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_NET_TYPE_INTERNAL:
|
|
|
|
if (STRNEQ_NULLABLE(olddev->data.internal.name,
|
|
|
|
newdev->data.internal.name)) {
|
|
|
|
needReconnect = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_NET_TYPE_DIRECT:
|
|
|
|
/* all handled in common code directly below this switch */
|
|
|
|
break;
|
|
|
|
|
2018-02-14 09:43:59 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
|
2020-10-14 17:08:25 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_VDPA:
|
2013-03-20 15:57:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
_("unable to change config on '%s' network type"),
|
|
|
|
virDomainNetTypeToString(newdev->type));
|
2018-02-14 09:43:59 +00:00
|
|
|
goto cleanup;
|
|
|
|
case VIR_DOMAIN_NET_TYPE_LAST:
|
|
|
|
default:
|
|
|
|
virReportEnumRangeError(virDomainNetType, newdev->type);
|
|
|
|
goto cleanup;
|
2011-09-06 08:23:47 +00:00
|
|
|
}
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
} else {
|
|
|
|
/* interface type has changed. There are a few special cases
|
|
|
|
* where this can only require a minor (or even no) change,
|
|
|
|
* but in most cases we need to do a full reconnection.
|
|
|
|
*
|
2020-05-28 22:04:24 +00:00
|
|
|
* As long as both the new and old types use a tap device
|
|
|
|
* connected to a host bridge (ie VIR_DOMAIN_NET_TYPE_NETWORK
|
|
|
|
* or VIR_DOMAIN_NET_TYPE_BRIDGE), we just need to connect to
|
|
|
|
* the new bridge.
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
*/
|
2020-05-28 22:04:24 +00:00
|
|
|
if ((oldType == VIR_DOMAIN_NET_TYPE_NETWORK ||
|
|
|
|
oldType == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
|
|
|
|
(newType == VIR_DOMAIN_NET_TYPE_NETWORK ||
|
|
|
|
newType == VIR_DOMAIN_NET_TYPE_BRIDGE)) {
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
|
|
|
|
needBridgeChange = true;
|
|
|
|
|
|
|
|
} else if (oldType == VIR_DOMAIN_NET_TYPE_DIRECT &&
|
|
|
|
newType == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
|
|
|
|
|
|
|
/* this is the case of switching from type='direct' to
|
|
|
|
* type='network' for a network that itself uses direct
|
|
|
|
* (macvtap) devices. If the physical device and mode are
|
|
|
|
* the same, this doesn't require any actual setup
|
|
|
|
* change. If the physical device or mode *does* change,
|
|
|
|
* that will be caught in the common section below */
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/* for all other combinations, we'll need a full reconnect */
|
|
|
|
needReconnect = true;
|
2011-09-06 08:23:47 +00:00
|
|
|
|
|
|
|
}
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
}
|
2011-09-06 08:23:47 +00:00
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
/* now several things that are in multiple (but not all)
|
|
|
|
* different types, and can be safely compared even for those
|
|
|
|
* cases where they don't apply to a particular type.
|
|
|
|
*/
|
|
|
|
if (STRNEQ_NULLABLE(virDomainNetGetActualBridgeName(olddev),
|
|
|
|
virDomainNetGetActualBridgeName(newdev))) {
|
|
|
|
if (virDomainNetGetActualVirtPortProfile(newdev))
|
|
|
|
needReconnect = true;
|
|
|
|
else
|
|
|
|
needBridgeChange = true;
|
|
|
|
}
|
2011-09-06 08:23:47 +00:00
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
if (STRNEQ_NULLABLE(virDomainNetGetActualDirectDev(olddev),
|
|
|
|
virDomainNetGetActualDirectDev(newdev)) ||
|
2017-04-25 06:16:20 +00:00
|
|
|
virDomainNetGetActualDirectMode(olddev) != virDomainNetGetActualDirectMode(newdev) ||
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
!virNetDevVPortProfileEqual(virDomainNetGetActualVirtPortProfile(olddev),
|
2017-07-17 15:49:00 +00:00
|
|
|
virDomainNetGetActualVirtPortProfile(newdev))) {
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
needReconnect = true;
|
2011-09-06 08:23:47 +00:00
|
|
|
}
|
|
|
|
|
2017-07-17 15:49:00 +00:00
|
|
|
if (!virNetDevVlanEqual(virDomainNetGetActualVlan(olddev),
|
|
|
|
virDomainNetGetActualVlan(newdev))) {
|
|
|
|
needVlanUpdate = true;
|
|
|
|
}
|
|
|
|
|
2020-02-14 18:51:31 +00:00
|
|
|
if (virDomainNetGetActualPortOptionsIsolated(olddev) !=
|
|
|
|
virDomainNetGetActualPortOptionsIsolated(newdev)) {
|
|
|
|
needIsolatedPortChange = true;
|
|
|
|
}
|
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
if (olddev->linkstate != newdev->linkstate)
|
|
|
|
needLinkStateChange = true;
|
|
|
|
|
2013-10-01 13:04:48 +00:00
|
|
|
if (!virNetDevBandwidthEqual(virDomainNetGetActualBandwidth(olddev),
|
|
|
|
virDomainNetGetActualBandwidth(newdev)))
|
|
|
|
needBandwidthSet = true;
|
|
|
|
|
2017-06-15 12:22:26 +00:00
|
|
|
if (!!olddev->coalesce != !!newdev->coalesce ||
|
|
|
|
(olddev->coalesce && newdev->coalesce &&
|
2017-06-21 07:00:58 +00:00
|
|
|
memcmp(olddev->coalesce, newdev->coalesce,
|
|
|
|
sizeof(*olddev->coalesce))))
|
2017-06-15 12:22:26 +00:00
|
|
|
needCoalesceChange = true;
|
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
/* FINALLY - actually perform the required actions */
|
|
|
|
|
|
|
|
if (needReconnect) {
|
2013-03-20 15:57:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
_("unable to change config on '%s' network type"),
|
|
|
|
virDomainNetTypeToString(newdev->type));
|
|
|
|
goto cleanup;
|
2011-09-06 08:23:47 +00:00
|
|
|
}
|
|
|
|
|
2013-10-01 13:04:48 +00:00
|
|
|
if (needBandwidthSet) {
|
2019-10-01 16:52:03 +00:00
|
|
|
const virNetDevBandwidth *newb = virDomainNetGetActualBandwidth(newdev);
|
qemu: delete exist bandwidth restrictions when they are removed from config
When the <bandwidth> of an interface is changed with update-device,
the old settings are cleared with tc, then new settings added with
tc. But if the <bandwidth has been removed, the old settings weren't
being removed, so the bandwidth restrictions would still be active on
the interface although the interface status in libvirt showed that
they had been removed.
This patch fixes it by calling virNetDevBandwidthClear() if the
"modification" to the interface bandwidth was to completely clear
it.
An alternative could have been to modify virNetDevBandwidthSet() to
always clear existing bandwith settings at the beginning of the
function (currently it short circuits in that case, doing nothing),
but that would have led to cases where virNetDevBandwidthClear() was
now being called in cases where it previously wasn't, and while many
of those cases would be NOPs, there could be cases where it would
cause an error. The way this patch works, the ...Clear() function is
only called in cases where the ...Set() function had previously been
called successfully, so the risk of regression is minimized.
Resolves: https://bugzilla.redhat.com/1454709
2017-12-11 19:26:54 +00:00
|
|
|
|
|
|
|
if (newb) {
|
2021-07-07 09:18:19 +00:00
|
|
|
if (virDomainNetDefIsOvsport(newdev)) {
|
|
|
|
if (virNetDevOpenvswitchInterfaceSetQos(newdev->ifname, newb,
|
|
|
|
vm->def->uuid,
|
|
|
|
!virDomainNetTypeSharesHostView(newdev)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
} else if (virNetDevBandwidthSet(newdev->ifname, newb, false,
|
|
|
|
!virDomainNetTypeSharesHostView(newdev)) < 0) {
|
qemu: delete exist bandwidth restrictions when they are removed from config
When the <bandwidth> of an interface is changed with update-device,
the old settings are cleared with tc, then new settings added with
tc. But if the <bandwidth has been removed, the old settings weren't
being removed, so the bandwidth restrictions would still be active on
the interface although the interface status in libvirt showed that
they had been removed.
This patch fixes it by calling virNetDevBandwidthClear() if the
"modification" to the interface bandwidth was to completely clear
it.
An alternative could have been to modify virNetDevBandwidthSet() to
always clear existing bandwith settings at the beginning of the
function (currently it short circuits in that case, doing nothing),
but that would have led to cases where virNetDevBandwidthClear() was
now being called in cases where it previously wasn't, and while many
of those cases would be NOPs, there could be cases where it would
cause an error. The way this patch works, the ...Clear() function is
only called in cases where the ...Set() function had previously been
called successfully, so the risk of regression is minimized.
Resolves: https://bugzilla.redhat.com/1454709
2017-12-11 19:26:54 +00:00
|
|
|
goto cleanup;
|
2021-07-07 09:18:19 +00:00
|
|
|
}
|
qemu: delete exist bandwidth restrictions when they are removed from config
When the <bandwidth> of an interface is changed with update-device,
the old settings are cleared with tc, then new settings added with
tc. But if the <bandwidth has been removed, the old settings weren't
being removed, so the bandwidth restrictions would still be active on
the interface although the interface status in libvirt showed that
they had been removed.
This patch fixes it by calling virNetDevBandwidthClear() if the
"modification" to the interface bandwidth was to completely clear
it.
An alternative could have been to modify virNetDevBandwidthSet() to
always clear existing bandwith settings at the beginning of the
function (currently it short circuits in that case, doing nothing),
but that would have led to cases where virNetDevBandwidthClear() was
now being called in cases where it previously wasn't, and while many
of those cases would be NOPs, there could be cases where it would
cause an error. The way this patch works, the ...Clear() function is
only called in cases where the ...Set() function had previously been
called successfully, so the risk of regression is minimized.
Resolves: https://bugzilla.redhat.com/1454709
2017-12-11 19:26:54 +00:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* virNetDevBandwidthSet() doesn't clear any existing
|
|
|
|
* setting unless something new is being set.
|
|
|
|
*/
|
|
|
|
virNetDevBandwidthClear(newdev->ifname);
|
|
|
|
}
|
2020-12-04 11:50:58 +00:00
|
|
|
|
|
|
|
/* If the old bandwidth was cleared out, restore qdisc. */
|
|
|
|
if (virDomainNetTypeSharesHostView(newdev)) {
|
2021-02-15 17:30:41 +00:00
|
|
|
if (!newb || !newb->out || newb->out->average == 0)
|
2020-12-04 11:50:58 +00:00
|
|
|
qemuDomainInterfaceSetDefaultQDisc(driver, newdev);
|
|
|
|
} else {
|
2021-02-15 17:30:41 +00:00
|
|
|
if (!newb || !newb->in || newb->in->average == 0)
|
2020-12-04 11:50:58 +00:00
|
|
|
qemuDomainInterfaceSetDefaultQDisc(driver, newdev);
|
|
|
|
}
|
2013-10-01 13:04:48 +00:00
|
|
|
needReplaceDevDef = true;
|
|
|
|
}
|
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
if (needBridgeChange) {
|
2014-11-21 17:51:13 +00:00
|
|
|
if (qemuDomainChangeNetBridge(vm, olddev, newdev) < 0)
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
goto cleanup;
|
|
|
|
/* we successfully switched to the new bridge, and we've
|
|
|
|
* determined that the rest of newdev is equivalent to olddev,
|
2012-11-12 16:21:10 +00:00
|
|
|
* so move newdev into place */
|
|
|
|
needReplaceDevDef = true;
|
2020-02-14 18:51:31 +00:00
|
|
|
|
|
|
|
/* this is already updated as a part of reconnecting the bridge */
|
|
|
|
needIsolatedPortChange = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (needIsolatedPortChange) {
|
|
|
|
const char *bridge = virDomainNetGetActualBridgeName(newdev);
|
|
|
|
bool isolatedOn = (virDomainNetGetActualPortOptionsIsolated(newdev) ==
|
|
|
|
VIR_TRISTATE_BOOL_YES);
|
|
|
|
|
|
|
|
if (virNetDevBridgePortSetIsolated(bridge, newdev->ifname, isolatedOn) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
needReplaceDevDef = true;
|
2012-11-12 16:21:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (needFilterChange) {
|
2014-11-07 10:37:37 +00:00
|
|
|
if (qemuDomainChangeNetFilter(vm, olddev, newdev) < 0)
|
2012-11-12 16:21:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
/* we successfully switched to the new filter, and we've
|
|
|
|
* determined that the rest of newdev is equivalent to olddev,
|
|
|
|
* so move newdev into place */
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
needReplaceDevDef = true;
|
2011-09-06 08:23:47 +00:00
|
|
|
}
|
|
|
|
|
2017-06-15 12:22:26 +00:00
|
|
|
if (needCoalesceChange) {
|
|
|
|
if (virNetDevSetCoalesce(newdev->ifname, newdev->coalesce, true) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
needReplaceDevDef = true;
|
|
|
|
}
|
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
if (needLinkStateChange &&
|
|
|
|
qemuDomainChangeNetLinkState(driver, vm, olddev, newdev->linkstate) < 0) {
|
|
|
|
goto cleanup;
|
2012-03-28 19:11:09 +00:00
|
|
|
}
|
|
|
|
|
2017-07-17 15:49:00 +00:00
|
|
|
if (needVlanUpdate) {
|
|
|
|
if (virNetDevOpenvswitchUpdateVlan(newdev->ifname, &newdev->vlan) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
needReplaceDevDef = true;
|
|
|
|
}
|
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
if (needReplaceDevDef) {
|
|
|
|
/* the changes above warrant replacing olddev with newdev in
|
|
|
|
* the domain's nets list.
|
|
|
|
*/
|
2013-08-27 17:06:18 +00:00
|
|
|
|
|
|
|
/* this function doesn't work with HOSTDEV networks yet, thus
|
|
|
|
* no need to change the pointer in the hostdev structure */
|
2018-07-26 14:32:04 +00:00
|
|
|
if (olddev->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
|
|
|
if (conn || (conn = virGetConnectNetwork()))
|
|
|
|
virDomainNetReleaseActualDevice(conn, vm->def, olddev);
|
|
|
|
else
|
|
|
|
VIR_WARN("Unable to release network device '%s'", NULLSTR(olddev->ifname));
|
|
|
|
}
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
virDomainNetDefFree(olddev);
|
|
|
|
/* move newdev into the nets list, and NULL it out from the
|
|
|
|
* virDomainDeviceDef that we were given so that the caller
|
|
|
|
* won't delete it on return.
|
|
|
|
*/
|
|
|
|
*devslot = newdev;
|
|
|
|
newdev = dev->data.net = NULL;
|
|
|
|
dev->type = VIR_DOMAIN_DEVICE_NONE;
|
2011-09-06 08:23:47 +00:00
|
|
|
}
|
|
|
|
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
ret = 0;
|
2014-03-25 06:49:44 +00:00
|
|
|
cleanup:
|
2019-04-30 14:17:14 +00:00
|
|
|
virErrorPreserveLast(&save_err);
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
/* When we get here, we will be in one of these two states:
|
|
|
|
*
|
|
|
|
* 1) newdev has been moved into the domain's list of nets and
|
|
|
|
* newdev set to NULL, and dev->data.net will be NULL (and
|
|
|
|
* dev->type is NONE). olddev will have been completely
|
|
|
|
* released and freed. (aka success) In this case no extra
|
|
|
|
* cleanup is needed.
|
|
|
|
*
|
|
|
|
* 2) newdev has *not* been moved into the domain's list of nets,
|
|
|
|
* and dev->data.net == newdev (and dev->type == NET). In this *
|
|
|
|
* case, we need to at least release the "actual device" from *
|
|
|
|
* newdev (the caller will free dev->data.net a.k.a. newdev, and
|
|
|
|
* the original olddev is still in used)
|
|
|
|
*
|
|
|
|
* Note that case (2) isn't necessarily a failure. It may just be
|
|
|
|
* that the changes were minor enough that we didn't need to
|
|
|
|
* replace the entire device object.
|
|
|
|
*/
|
2018-07-26 14:32:04 +00:00
|
|
|
if (newdev && newdev->type == VIR_DOMAIN_NET_TYPE_NETWORK && conn)
|
|
|
|
virDomainNetReleaseActualDevice(conn, vm->def, newdev);
|
2019-04-30 14:17:14 +00:00
|
|
|
virErrorRestore(&save_err);
|
qemu: reorganize qemuDomainChangeNet and qemuDomainChangeNetBridge
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
2012-10-10 19:38:00 +00:00
|
|
|
|
2011-09-06 08:23:47 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static virDomainGraphicsDef *
|
|
|
|
qemuDomainFindGraphics(virDomainObj *vm,
|
|
|
|
virDomainGraphicsDef *dev)
|
2010-12-16 16:10:54 +00:00
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/qemu files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2013-05-21 07:21:20 +00:00
|
|
|
for (i = 0; i < vm->def->ngraphics; i++) {
|
2010-12-16 16:10:54 +00:00
|
|
|
if (vm->def->graphics[i]->type == dev->type)
|
|
|
|
return vm->def->graphics[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-12-08 13:48:33 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainFindGraphicsIndex(virDomainDef *def,
|
|
|
|
virDomainGraphicsDef *dev)
|
2014-12-08 13:48:33 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < def->ngraphics; i++) {
|
|
|
|
if (def->graphics[i]->type == dev->type)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-03-19 17:35:31 +00:00
|
|
|
|
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainChangeGraphicsPasswords(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
2019-03-19 17:35:31 +00:00
|
|
|
int type,
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainGraphicsAuthDef *auth,
|
2019-03-19 17:35:31 +00:00
|
|
|
const char *defaultPasswd,
|
|
|
|
int asyncJob)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2019-03-19 17:35:31 +00:00
|
|
|
time_t now = time(NULL);
|
|
|
|
const char *expire;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *validTo = NULL;
|
2019-03-19 17:35:31 +00:00
|
|
|
const char *connected = NULL;
|
|
|
|
const char *password;
|
|
|
|
int ret = -1;
|
|
|
|
|
2019-09-18 19:53:06 +00:00
|
|
|
if (!auth->passwd && !defaultPasswd)
|
|
|
|
return 0;
|
|
|
|
|
2019-03-19 17:35:31 +00:00
|
|
|
password = auth->passwd ? auth->passwd : defaultPasswd;
|
|
|
|
|
|
|
|
if (auth->connected)
|
|
|
|
connected = virDomainGraphicsAuthConnectedTypeToString(auth->connected);
|
|
|
|
|
|
|
|
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return ret;
|
2019-03-19 17:35:31 +00:00
|
|
|
ret = qemuMonitorSetPassword(priv->mon, type, password, connected);
|
|
|
|
|
|
|
|
if (ret != 0)
|
|
|
|
goto end_job;
|
|
|
|
|
|
|
|
if (password[0] == '\0' ||
|
|
|
|
(auth->expires && auth->validTo <= now)) {
|
|
|
|
expire = "now";
|
|
|
|
} else if (auth->expires) {
|
2019-10-22 13:26:14 +00:00
|
|
|
validTo = g_strdup_printf("%lu", (unsigned long)auth->validTo);
|
2019-03-19 17:35:31 +00:00
|
|
|
expire = validTo;
|
|
|
|
} else {
|
|
|
|
expire = "never";
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = qemuMonitorExpirePassword(priv->mon, type, expire);
|
|
|
|
|
|
|
|
end_job:
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
ret = -1;
|
2019-09-18 19:53:06 +00:00
|
|
|
|
2019-03-19 17:35:31 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-16 16:10:54 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainChangeGraphics(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainGraphicsDef *dev)
|
2010-12-16 16:10:54 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainGraphicsDef *olddev = qemuDomainFindGraphics(vm, dev);
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
2016-04-25 13:36:28 +00:00
|
|
|
const char *type = virDomainGraphicsTypeToString(dev->type);
|
qemuDomainChangeGraphics: Check listen address change by listen type
Currently, we have a bug when updating a graphics device. A graphics device can
have a listen address set. This address is either defined by user (in which case
it's type is VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) or it can be inherited
from a network (in which case it's type is
VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK). However, in both cases we have a
listen address to process (e.g. during migration, as I've tried to fix in
7f15ebc7).
Later, when a user tries to update the graphics device (e.g. set a password),
we check if listen addresses match the original as qemu doesn't know how to
change listen address yet. Hence, users are required to not change the listen
address. The implementation then just dumps listen addresses and compare them.
Previously, while dumping the listen addresses, NULL was returned for NETWORK.
After my patch, this is no longer true, and we get a listen address for olddev
even if it is a type of NETWORK. So we have a real string on one side, the NULL
from user's XML on the other side and hence we think user wants to change the
listen address and we refuse it.
Therefore, we must take the type of listen address into account as well.
2013-06-20 16:27:35 +00:00
|
|
|
size_t i;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
|
|
|
if (!olddev) {
|
2018-01-23 04:24:44 +00:00
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING,
|
2018-01-23 04:24:42 +00:00
|
|
|
_("cannot find existing graphics device to modify of "
|
|
|
|
"type '%s'"), type);
|
2019-11-12 20:46:27 +00:00
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
|
qemuDomainChangeGraphics: Check listen address change by listen type
Currently, we have a bug when updating a graphics device. A graphics device can
have a listen address set. This address is either defined by user (in which case
it's type is VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) or it can be inherited
from a network (in which case it's type is
VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK). However, in both cases we have a
listen address to process (e.g. during migration, as I've tried to fix in
7f15ebc7).
Later, when a user tries to update the graphics device (e.g. set a password),
we check if listen addresses match the original as qemu doesn't know how to
change listen address yet. Hence, users are required to not change the listen
address. The implementation then just dumps listen addresses and compare them.
Previously, while dumping the listen addresses, NULL was returned for NETWORK.
After my patch, this is no longer true, and we get a listen address for olddev
even if it is a type of NETWORK. So we have a real string on one side, the NULL
from user's XML on the other side and hence we think user wants to change the
listen address and we refuse it.
Therefore, we must take the type of listen address into account as well.
2013-06-20 16:27:35 +00:00
|
|
|
if (dev->nListens != olddev->nListens) {
|
2016-04-25 13:36:28 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("cannot change the number of listen addresses "
|
|
|
|
"on '%s' graphics"), type);
|
2019-11-12 20:46:27 +00:00
|
|
|
return -1;
|
qemuDomainChangeGraphics: Check listen address change by listen type
Currently, we have a bug when updating a graphics device. A graphics device can
have a listen address set. This address is either defined by user (in which case
it's type is VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) or it can be inherited
from a network (in which case it's type is
VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK). However, in both cases we have a
listen address to process (e.g. during migration, as I've tried to fix in
7f15ebc7).
Later, when a user tries to update the graphics device (e.g. set a password),
we check if listen addresses match the original as qemu doesn't know how to
change listen address yet. Hence, users are required to not change the listen
address. The implementation then just dumps listen addresses and compare them.
Previously, while dumping the listen addresses, NULL was returned for NETWORK.
After my patch, this is no longer true, and we get a listen address for olddev
even if it is a type of NETWORK. So we have a real string on one side, the NULL
from user's XML on the other side and hence we think user wants to change the
listen address and we refuse it.
Therefore, we must take the type of listen address into account as well.
2013-06-20 16:27:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < dev->nListens; i++) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainGraphicsListenDef *newlisten = &dev->listens[i];
|
|
|
|
virDomainGraphicsListenDef *oldlisten = &olddev->listens[i];
|
qemuDomainChangeGraphics: Check listen address change by listen type
Currently, we have a bug when updating a graphics device. A graphics device can
have a listen address set. This address is either defined by user (in which case
it's type is VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) or it can be inherited
from a network (in which case it's type is
VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK). However, in both cases we have a
listen address to process (e.g. during migration, as I've tried to fix in
7f15ebc7).
Later, when a user tries to update the graphics device (e.g. set a password),
we check if listen addresses match the original as qemu doesn't know how to
change listen address yet. Hence, users are required to not change the listen
address. The implementation then just dumps listen addresses and compare them.
Previously, while dumping the listen addresses, NULL was returned for NETWORK.
After my patch, this is no longer true, and we get a listen address for olddev
even if it is a type of NETWORK. So we have a real string on one side, the NULL
from user's XML on the other side and hence we think user wants to change the
listen address and we refuse it.
Therefore, we must take the type of listen address into account as well.
2013-06-20 16:27:35 +00:00
|
|
|
|
2013-06-20 18:55:00 +00:00
|
|
|
if (newlisten->type != oldlisten->type) {
|
2016-04-25 13:36:28 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("cannot change the type of listen address "
|
|
|
|
"on '%s' graphics"), type);
|
2019-11-12 20:46:27 +00:00
|
|
|
return -1;
|
qemuDomainChangeGraphics: Check listen address change by listen type
Currently, we have a bug when updating a graphics device. A graphics device can
have a listen address set. This address is either defined by user (in which case
it's type is VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) or it can be inherited
from a network (in which case it's type is
VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK). However, in both cases we have a
listen address to process (e.g. during migration, as I've tried to fix in
7f15ebc7).
Later, when a user tries to update the graphics device (e.g. set a password),
we check if listen addresses match the original as qemu doesn't know how to
change listen address yet. Hence, users are required to not change the listen
address. The implementation then just dumps listen addresses and compare them.
Previously, while dumping the listen addresses, NULL was returned for NETWORK.
After my patch, this is no longer true, and we get a listen address for olddev
even if it is a type of NETWORK. So we have a real string on one side, the NULL
from user's XML on the other side and hence we think user wants to change the
listen address and we refuse it.
Therefore, we must take the type of listen address into account as well.
2013-06-20 16:27:35 +00:00
|
|
|
}
|
|
|
|
|
2016-05-02 15:45:23 +00:00
|
|
|
switch (newlisten->type) {
|
qemuDomainChangeGraphics: Check listen address change by listen type
Currently, we have a bug when updating a graphics device. A graphics device can
have a listen address set. This address is either defined by user (in which case
it's type is VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) or it can be inherited
from a network (in which case it's type is
VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK). However, in both cases we have a
listen address to process (e.g. during migration, as I've tried to fix in
7f15ebc7).
Later, when a user tries to update the graphics device (e.g. set a password),
we check if listen addresses match the original as qemu doesn't know how to
change listen address yet. Hence, users are required to not change the listen
address. The implementation then just dumps listen addresses and compare them.
Previously, while dumping the listen addresses, NULL was returned for NETWORK.
After my patch, this is no longer true, and we get a listen address for olddev
even if it is a type of NETWORK. So we have a real string on one side, the NULL
from user's XML on the other side and hence we think user wants to change the
listen address and we refuse it.
Therefore, we must take the type of listen address into account as well.
2013-06-20 16:27:35 +00:00
|
|
|
case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS:
|
2013-06-20 18:55:00 +00:00
|
|
|
if (STRNEQ_NULLABLE(newlisten->address, oldlisten->address)) {
|
2016-04-25 13:36:28 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("cannot change listen address setting "
|
|
|
|
"on '%s' graphics"), type);
|
2019-11-12 20:46:27 +00:00
|
|
|
return -1;
|
qemuDomainChangeGraphics: Check listen address change by listen type
Currently, we have a bug when updating a graphics device. A graphics device can
have a listen address set. This address is either defined by user (in which case
it's type is VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) or it can be inherited
from a network (in which case it's type is
VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK). However, in both cases we have a
listen address to process (e.g. during migration, as I've tried to fix in
7f15ebc7).
Later, when a user tries to update the graphics device (e.g. set a password),
we check if listen addresses match the original as qemu doesn't know how to
change listen address yet. Hence, users are required to not change the listen
address. The implementation then just dumps listen addresses and compare them.
Previously, while dumping the listen addresses, NULL was returned for NETWORK.
After my patch, this is no longer true, and we get a listen address for olddev
even if it is a type of NETWORK. So we have a real string on one side, the NULL
from user's XML on the other side and hence we think user wants to change the
listen address and we refuse it.
Therefore, we must take the type of listen address into account as well.
2013-06-20 16:27:35 +00:00
|
|
|
}
|
2016-04-25 13:36:28 +00:00
|
|
|
|
qemuDomainChangeGraphics: Check listen address change by listen type
Currently, we have a bug when updating a graphics device. A graphics device can
have a listen address set. This address is either defined by user (in which case
it's type is VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) or it can be inherited
from a network (in which case it's type is
VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK). However, in both cases we have a
listen address to process (e.g. during migration, as I've tried to fix in
7f15ebc7).
Later, when a user tries to update the graphics device (e.g. set a password),
we check if listen addresses match the original as qemu doesn't know how to
change listen address yet. Hence, users are required to not change the listen
address. The implementation then just dumps listen addresses and compare them.
Previously, while dumping the listen addresses, NULL was returned for NETWORK.
After my patch, this is no longer true, and we get a listen address for olddev
even if it is a type of NETWORK. So we have a real string on one side, the NULL
from user's XML on the other side and hence we think user wants to change the
listen address and we refuse it.
Therefore, we must take the type of listen address into account as well.
2013-06-20 16:27:35 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK:
|
2013-06-20 18:55:00 +00:00
|
|
|
if (STRNEQ_NULLABLE(newlisten->network, oldlisten->network)) {
|
2016-04-25 13:36:28 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("cannot change listen address setting "
|
|
|
|
"on '%s' graphics"), type);
|
2019-11-12 20:46:27 +00:00
|
|
|
return -1;
|
qemuDomainChangeGraphics: Check listen address change by listen type
Currently, we have a bug when updating a graphics device. A graphics device can
have a listen address set. This address is either defined by user (in which case
it's type is VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) or it can be inherited
from a network (in which case it's type is
VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK). However, in both cases we have a
listen address to process (e.g. during migration, as I've tried to fix in
7f15ebc7).
Later, when a user tries to update the graphics device (e.g. set a password),
we check if listen addresses match the original as qemu doesn't know how to
change listen address yet. Hence, users are required to not change the listen
address. The implementation then just dumps listen addresses and compare them.
Previously, while dumping the listen addresses, NULL was returned for NETWORK.
After my patch, this is no longer true, and we get a listen address for olddev
even if it is a type of NETWORK. So we have a real string on one side, the NULL
from user's XML on the other side and hence we think user wants to change the
listen address and we refuse it.
Therefore, we must take the type of listen address into account as well.
2013-06-20 16:27:35 +00:00
|
|
|
}
|
2016-04-25 13:36:28 +00:00
|
|
|
|
qemuDomainChangeGraphics: Check listen address change by listen type
Currently, we have a bug when updating a graphics device. A graphics device can
have a listen address set. This address is either defined by user (in which case
it's type is VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) or it can be inherited
from a network (in which case it's type is
VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK). However, in both cases we have a
listen address to process (e.g. during migration, as I've tried to fix in
7f15ebc7).
Later, when a user tries to update the graphics device (e.g. set a password),
we check if listen addresses match the original as qemu doesn't know how to
change listen address yet. Hence, users are required to not change the listen
address. The implementation then just dumps listen addresses and compare them.
Previously, while dumping the listen addresses, NULL was returned for NETWORK.
After my patch, this is no longer true, and we get a listen address for olddev
even if it is a type of NETWORK. So we have a real string on one side, the NULL
from user's XML on the other side and hence we think user wants to change the
listen address and we refuse it.
Therefore, we must take the type of listen address into account as well.
2013-06-20 16:27:35 +00:00
|
|
|
break;
|
|
|
|
|
2016-06-08 08:35:37 +00:00
|
|
|
case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET:
|
|
|
|
if (STRNEQ_NULLABLE(newlisten->socket, oldlisten->socket)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("cannot change listen socket setting "
|
|
|
|
"on '%s' graphics"), type);
|
2019-11-12 20:46:27 +00:00
|
|
|
return -1;
|
2016-06-08 08:35:37 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
qemuDomainChangeGraphics: Check listen address change by listen type
Currently, we have a bug when updating a graphics device. A graphics device can
have a listen address set. This address is either defined by user (in which case
it's type is VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) or it can be inherited
from a network (in which case it's type is
VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK). However, in both cases we have a
listen address to process (e.g. during migration, as I've tried to fix in
7f15ebc7).
Later, when a user tries to update the graphics device (e.g. set a password),
we check if listen addresses match the original as qemu doesn't know how to
change listen address yet. Hence, users are required to not change the listen
address. The implementation then just dumps listen addresses and compare them.
Previously, while dumping the listen addresses, NULL was returned for NETWORK.
After my patch, this is no longer true, and we get a listen address for olddev
even if it is a type of NETWORK. So we have a real string on one side, the NULL
from user's XML on the other side and hence we think user wants to change the
listen address and we refuse it.
Therefore, we must take the type of listen address into account as well.
2013-06-20 16:27:35 +00:00
|
|
|
case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE:
|
|
|
|
case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST:
|
|
|
|
/* nada */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
conf: add <listen> subelement to domain <graphics> element
Once it's plugged in, the <listen> element will be an optional
replacement for the "listen" attribute that graphics elements already
have. If the <listen> element is type='address', it will have an
attribute called 'address' which will contain an IP address or dns
name that the guest's display server should listen on. If, however,
type='network', the <listen> element should have an attribute called
'network' that will be set to the name of a network configuration to
get the IP address from.
* docs/schemas/domain.rng: updated to allow the <listen> element
* docs/formatdomain.html.in: document the <listen> element and its
attributes.
* src/conf/domain_conf.[hc]:
1) The domain parser, formatter, and data structure are modified to
support 0 or more <listen> subelements to each <graphics>
element. The old style "legacy" listen attribute is also still
accepted, and will be stored internally just as if it were a
separate <listen> element. On output (i.e. format), the address
attribute of the first <listen> element of type 'address' will be
duplicated in the legacy "listen" attribute of the <graphic>
element.
2) The "listenAddr" attribute has been removed from the unions in
virDomainGRaphicsDef for graphics types vnc, rdp, and spice.
This attribute is now in the <listen> subelement (aka
virDomainGraphicsListenDef)
3) Helper functions were written to provide simple access
(both Get and Set) to the listen elements and their attributes.
* src/libvirt_private.syms: export the listen helper functions
* src/qemu/qemu_command.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/vbox/vbox_tmpl.c,
src/vmx/vmx.c, src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c
Modify all these files to use the listen helper functions rather
than directly referencing the (now missing) listenAddr
attribute. There can be multiple <listen> elements to a single
<graphics>, but the drivers all currently only support one, so all
replacements of direct access with a helper function indicate index
"0".
* tests/* - only 3 of these are new files added explicitly to test the
new <listen> element. All the others have been modified to reflect
the fact that any legacy "listen" attributes passed in to the domain
parse will be saved in a <listen> element (i.e. one of the
virDomainGraphicsListenDefs), and during the domain format function,
both the <listen> element as well as the legacy attributes will be
output.
2011-07-07 04:20:28 +00:00
|
|
|
|
2010-12-16 16:10:54 +00:00
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
|
2016-05-16 10:59:12 +00:00
|
|
|
if ((olddev->data.vnc.autoport != dev->data.vnc.autoport) ||
|
|
|
|
(!dev->data.vnc.autoport &&
|
|
|
|
(olddev->data.vnc.port != dev->data.vnc.port))) {
|
2014-12-08 13:48:31 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
2012-07-18 15:22:03 +00:00
|
|
|
_("cannot change port settings on vnc graphics"));
|
2019-11-12 20:46:27 +00:00
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
if (STRNEQ_NULLABLE(olddev->data.vnc.keymap, dev->data.vnc.keymap)) {
|
2014-12-08 13:48:31 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
2012-07-18 15:22:03 +00:00
|
|
|
_("cannot change keymap setting on vnc graphics"));
|
2019-11-12 20:46:27 +00:00
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
|
2011-05-26 14:15:54 +00:00
|
|
|
/* If a password lifetime was, or is set, or action if connected has
|
|
|
|
* changed, then we must always run, even if new password matches
|
|
|
|
* old password */
|
Use the new set_password monitor command to set password.
We try to use that command first when setting a VNC/SPICE password. If
that doesn't work we fallback to the legacy VNC only password
Allow an expiry time to be set, if that doesn't work, throw an error
if they try to use SPICE.
Change since v1:
- moved qemuInitGraphicsPasswords to qemu_hotplug, renamed
to qemuDomainChangeGraphicsPasswords.
- updated what looks like a typo (that appears to work anyway) in
initial patch from Daniel:
- ret = qemuInitGraphicsPasswords(driver, vm,
- VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
- &vm->def->graphics[0]->data.vnc.auth,
- driver->vncPassword);
+ ret = qemuInitGraphicsPasswords(driver, vm,
+ VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
+ &vm->def->graphics[0]->data.spice.auth,
+ driver->spicePassword);
Based on patch by Daniel P. Berrange <berrange@redhat.com>.
2011-01-10 11:12:33 +00:00
|
|
|
if (olddev->data.vnc.auth.expires ||
|
|
|
|
dev->data.vnc.auth.expires ||
|
2011-05-26 14:15:54 +00:00
|
|
|
olddev->data.vnc.auth.connected != dev->data.vnc.auth.connected ||
|
2011-06-06 19:35:41 +00:00
|
|
|
STRNEQ_NULLABLE(olddev->data.vnc.auth.passwd,
|
|
|
|
dev->data.vnc.auth.passwd)) {
|
|
|
|
VIR_DEBUG("Updating password on VNC server %p %p",
|
2013-01-10 21:03:14 +00:00
|
|
|
dev->data.vnc.auth.passwd, cfg->vncPassword);
|
2019-11-12 20:46:27 +00:00
|
|
|
if (qemuDomainChangeGraphicsPasswords(driver, vm,
|
|
|
|
VIR_DOMAIN_GRAPHICS_TYPE_VNC,
|
|
|
|
&dev->data.vnc.auth,
|
|
|
|
cfg->vncPassword,
|
|
|
|
QEMU_ASYNC_JOB_NONE) < 0)
|
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
|
|
|
/* Steal the new dev's char * reference */
|
|
|
|
VIR_FREE(olddev->data.vnc.auth.passwd);
|
|
|
|
olddev->data.vnc.auth.passwd = dev->data.vnc.auth.passwd;
|
|
|
|
dev->data.vnc.auth.passwd = NULL;
|
Use the new set_password monitor command to set password.
We try to use that command first when setting a VNC/SPICE password. If
that doesn't work we fallback to the legacy VNC only password
Allow an expiry time to be set, if that doesn't work, throw an error
if they try to use SPICE.
Change since v1:
- moved qemuInitGraphicsPasswords to qemu_hotplug, renamed
to qemuDomainChangeGraphicsPasswords.
- updated what looks like a typo (that appears to work anyway) in
initial patch from Daniel:
- ret = qemuInitGraphicsPasswords(driver, vm,
- VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
- &vm->def->graphics[0]->data.vnc.auth,
- driver->vncPassword);
+ ret = qemuInitGraphicsPasswords(driver, vm,
+ VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
+ &vm->def->graphics[0]->data.spice.auth,
+ driver->spicePassword);
Based on patch by Daniel P. Berrange <berrange@redhat.com>.
2011-01-10 11:12:33 +00:00
|
|
|
olddev->data.vnc.auth.validTo = dev->data.vnc.auth.validTo;
|
|
|
|
olddev->data.vnc.auth.expires = dev->data.vnc.auth.expires;
|
2011-05-26 14:15:54 +00:00
|
|
|
olddev->data.vnc.auth.connected = dev->data.vnc.auth.connected;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
Use the new set_password monitor command to set password.
We try to use that command first when setting a VNC/SPICE password. If
that doesn't work we fallback to the legacy VNC only password
Allow an expiry time to be set, if that doesn't work, throw an error
if they try to use SPICE.
Change since v1:
- moved qemuInitGraphicsPasswords to qemu_hotplug, renamed
to qemuDomainChangeGraphicsPasswords.
- updated what looks like a typo (that appears to work anyway) in
initial patch from Daniel:
- ret = qemuInitGraphicsPasswords(driver, vm,
- VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
- &vm->def->graphics[0]->data.vnc.auth,
- driver->vncPassword);
+ ret = qemuInitGraphicsPasswords(driver, vm,
+ VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
+ &vm->def->graphics[0]->data.spice.auth,
+ driver->spicePassword);
Based on patch by Daniel P. Berrange <berrange@redhat.com>.
2011-01-10 11:12:33 +00:00
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
|
2016-05-16 10:59:12 +00:00
|
|
|
if ((olddev->data.spice.autoport != dev->data.spice.autoport) ||
|
|
|
|
(!dev->data.spice.autoport &&
|
|
|
|
(olddev->data.spice.port != dev->data.spice.port)) ||
|
|
|
|
(!dev->data.spice.autoport &&
|
|
|
|
(olddev->data.spice.tlsPort != dev->data.spice.tlsPort))) {
|
2014-12-08 13:48:31 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
2012-07-18 15:22:03 +00:00
|
|
|
_("cannot change port settings on spice graphics"));
|
2019-11-12 20:46:27 +00:00
|
|
|
return -1;
|
Use the new set_password monitor command to set password.
We try to use that command first when setting a VNC/SPICE password. If
that doesn't work we fallback to the legacy VNC only password
Allow an expiry time to be set, if that doesn't work, throw an error
if they try to use SPICE.
Change since v1:
- moved qemuInitGraphicsPasswords to qemu_hotplug, renamed
to qemuDomainChangeGraphicsPasswords.
- updated what looks like a typo (that appears to work anyway) in
initial patch from Daniel:
- ret = qemuInitGraphicsPasswords(driver, vm,
- VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
- &vm->def->graphics[0]->data.vnc.auth,
- driver->vncPassword);
+ ret = qemuInitGraphicsPasswords(driver, vm,
+ VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
+ &vm->def->graphics[0]->data.spice.auth,
+ driver->spicePassword);
Based on patch by Daniel P. Berrange <berrange@redhat.com>.
2011-01-10 11:12:33 +00:00
|
|
|
}
|
2011-06-06 19:35:41 +00:00
|
|
|
if (STRNEQ_NULLABLE(olddev->data.spice.keymap,
|
|
|
|
dev->data.spice.keymap)) {
|
2014-12-08 13:48:31 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
Use the new set_password monitor command to set password.
We try to use that command first when setting a VNC/SPICE password. If
that doesn't work we fallback to the legacy VNC only password
Allow an expiry time to be set, if that doesn't work, throw an error
if they try to use SPICE.
Change since v1:
- moved qemuInitGraphicsPasswords to qemu_hotplug, renamed
to qemuDomainChangeGraphicsPasswords.
- updated what looks like a typo (that appears to work anyway) in
initial patch from Daniel:
- ret = qemuInitGraphicsPasswords(driver, vm,
- VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
- &vm->def->graphics[0]->data.vnc.auth,
- driver->vncPassword);
+ ret = qemuInitGraphicsPasswords(driver, vm,
+ VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
+ &vm->def->graphics[0]->data.spice.auth,
+ driver->spicePassword);
Based on patch by Daniel P. Berrange <berrange@redhat.com>.
2011-01-10 11:12:33 +00:00
|
|
|
_("cannot change keymap setting on spice graphics"));
|
2019-11-12 20:46:27 +00:00
|
|
|
return -1;
|
Use the new set_password monitor command to set password.
We try to use that command first when setting a VNC/SPICE password. If
that doesn't work we fallback to the legacy VNC only password
Allow an expiry time to be set, if that doesn't work, throw an error
if they try to use SPICE.
Change since v1:
- moved qemuInitGraphicsPasswords to qemu_hotplug, renamed
to qemuDomainChangeGraphicsPasswords.
- updated what looks like a typo (that appears to work anyway) in
initial patch from Daniel:
- ret = qemuInitGraphicsPasswords(driver, vm,
- VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
- &vm->def->graphics[0]->data.vnc.auth,
- driver->vncPassword);
+ ret = qemuInitGraphicsPasswords(driver, vm,
+ VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
+ &vm->def->graphics[0]->data.spice.auth,
+ driver->spicePassword);
Based on patch by Daniel P. Berrange <berrange@redhat.com>.
2011-01-10 11:12:33 +00:00
|
|
|
}
|
|
|
|
|
2012-06-14 12:48:42 +00:00
|
|
|
/* We must reset the password if it has changed but also if:
|
|
|
|
* - password lifetime is or was set
|
|
|
|
* - the requested action has changed
|
|
|
|
* - the action is "disconnect"
|
|
|
|
*/
|
Use the new set_password monitor command to set password.
We try to use that command first when setting a VNC/SPICE password. If
that doesn't work we fallback to the legacy VNC only password
Allow an expiry time to be set, if that doesn't work, throw an error
if they try to use SPICE.
Change since v1:
- moved qemuInitGraphicsPasswords to qemu_hotplug, renamed
to qemuDomainChangeGraphicsPasswords.
- updated what looks like a typo (that appears to work anyway) in
initial patch from Daniel:
- ret = qemuInitGraphicsPasswords(driver, vm,
- VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
- &vm->def->graphics[0]->data.vnc.auth,
- driver->vncPassword);
+ ret = qemuInitGraphicsPasswords(driver, vm,
+ VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
+ &vm->def->graphics[0]->data.spice.auth,
+ driver->spicePassword);
Based on patch by Daniel P. Berrange <berrange@redhat.com>.
2011-01-10 11:12:33 +00:00
|
|
|
if (olddev->data.spice.auth.expires ||
|
|
|
|
dev->data.spice.auth.expires ||
|
2011-05-26 14:15:54 +00:00
|
|
|
olddev->data.spice.auth.connected != dev->data.spice.auth.connected ||
|
2012-06-14 12:48:42 +00:00
|
|
|
dev->data.spice.auth.connected ==
|
|
|
|
VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_DISCONNECT ||
|
2011-06-06 19:35:41 +00:00
|
|
|
STRNEQ_NULLABLE(olddev->data.spice.auth.passwd,
|
|
|
|
dev->data.spice.auth.passwd)) {
|
|
|
|
VIR_DEBUG("Updating password on SPICE server %p %p",
|
2013-01-10 21:03:14 +00:00
|
|
|
dev->data.spice.auth.passwd, cfg->spicePassword);
|
2019-11-12 20:46:27 +00:00
|
|
|
if (qemuDomainChangeGraphicsPasswords(driver, vm,
|
|
|
|
VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
|
|
|
|
&dev->data.spice.auth,
|
|
|
|
cfg->spicePassword,
|
|
|
|
QEMU_ASYNC_JOB_NONE) < 0)
|
|
|
|
return -1;
|
2012-09-03 14:52:27 +00:00
|
|
|
|
2011-06-06 19:35:41 +00:00
|
|
|
/* Steal the new dev's char * reference */
|
Use the new set_password monitor command to set password.
We try to use that command first when setting a VNC/SPICE password. If
that doesn't work we fallback to the legacy VNC only password
Allow an expiry time to be set, if that doesn't work, throw an error
if they try to use SPICE.
Change since v1:
- moved qemuInitGraphicsPasswords to qemu_hotplug, renamed
to qemuDomainChangeGraphicsPasswords.
- updated what looks like a typo (that appears to work anyway) in
initial patch from Daniel:
- ret = qemuInitGraphicsPasswords(driver, vm,
- VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
- &vm->def->graphics[0]->data.vnc.auth,
- driver->vncPassword);
+ ret = qemuInitGraphicsPasswords(driver, vm,
+ VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
+ &vm->def->graphics[0]->data.spice.auth,
+ driver->spicePassword);
Based on patch by Daniel P. Berrange <berrange@redhat.com>.
2011-01-10 11:12:33 +00:00
|
|
|
VIR_FREE(olddev->data.spice.auth.passwd);
|
|
|
|
olddev->data.spice.auth.passwd = dev->data.spice.auth.passwd;
|
|
|
|
dev->data.spice.auth.passwd = NULL;
|
|
|
|
olddev->data.spice.auth.validTo = dev->data.spice.auth.validTo;
|
|
|
|
olddev->data.spice.auth.expires = dev->data.spice.auth.expires;
|
2011-05-26 14:15:54 +00:00
|
|
|
olddev->data.spice.auth.connected = dev->data.spice.auth.connected;
|
Use the new set_password monitor command to set password.
We try to use that command first when setting a VNC/SPICE password. If
that doesn't work we fallback to the legacy VNC only password
Allow an expiry time to be set, if that doesn't work, throw an error
if they try to use SPICE.
Change since v1:
- moved qemuInitGraphicsPasswords to qemu_hotplug, renamed
to qemuDomainChangeGraphicsPasswords.
- updated what looks like a typo (that appears to work anyway) in
initial patch from Daniel:
- ret = qemuInitGraphicsPasswords(driver, vm,
- VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
- &vm->def->graphics[0]->data.vnc.auth,
- driver->vncPassword);
+ ret = qemuInitGraphicsPasswords(driver, vm,
+ VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
+ &vm->def->graphics[0]->data.spice.auth,
+ driver->spicePassword);
Based on patch by Daniel P. Berrange <berrange@redhat.com>.
2011-01-10 11:12:33 +00:00
|
|
|
} else {
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_DEBUG("Not updating since password didn't change");
|
Use the new set_password monitor command to set password.
We try to use that command first when setting a VNC/SPICE password. If
that doesn't work we fallback to the legacy VNC only password
Allow an expiry time to be set, if that doesn't work, throw an error
if they try to use SPICE.
Change since v1:
- moved qemuInitGraphicsPasswords to qemu_hotplug, renamed
to qemuDomainChangeGraphicsPasswords.
- updated what looks like a typo (that appears to work anyway) in
initial patch from Daniel:
- ret = qemuInitGraphicsPasswords(driver, vm,
- VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
- &vm->def->graphics[0]->data.vnc.auth,
- driver->vncPassword);
+ ret = qemuInitGraphicsPasswords(driver, vm,
+ VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
+ &vm->def->graphics[0]->data.spice.auth,
+ driver->spicePassword);
Based on patch by Daniel P. Berrange <berrange@redhat.com>.
2011-01-10 11:12:33 +00:00
|
|
|
}
|
2011-06-06 19:30:52 +00:00
|
|
|
break;
|
Use the new set_password monitor command to set password.
We try to use that command first when setting a VNC/SPICE password. If
that doesn't work we fallback to the legacy VNC only password
Allow an expiry time to be set, if that doesn't work, throw an error
if they try to use SPICE.
Change since v1:
- moved qemuInitGraphicsPasswords to qemu_hotplug, renamed
to qemuDomainChangeGraphicsPasswords.
- updated what looks like a typo (that appears to work anyway) in
initial patch from Daniel:
- ret = qemuInitGraphicsPasswords(driver, vm,
- VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
- &vm->def->graphics[0]->data.vnc.auth,
- driver->vncPassword);
+ ret = qemuInitGraphicsPasswords(driver, vm,
+ VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
+ &vm->def->graphics[0]->data.spice.auth,
+ driver->spicePassword);
Based on patch by Daniel P. Berrange <berrange@redhat.com>.
2011-01-10 11:12:33 +00:00
|
|
|
|
2018-02-14 09:43:59 +00:00
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
|
2018-06-30 14:23:01 +00:00
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2016-04-25 13:36:28 +00:00
|
|
|
_("unable to change config on '%s' graphics type"), type);
|
2010-12-16 16:10:54 +00:00
|
|
|
break;
|
2018-02-14 09:43:59 +00:00
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
|
|
|
|
default:
|
|
|
|
virReportEnumRangeError(virDomainGraphicsType, dev->type);
|
|
|
|
break;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
|
2019-11-12 20:46:27 +00:00
|
|
|
return 0;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int qemuComparePCIDevice(virDomainDef *def G_GNUC_UNUSED,
|
|
|
|
virDomainDeviceDef *device G_GNUC_UNUSED,
|
|
|
|
virDomainDeviceInfo *info1,
|
2011-05-09 06:59:16 +00:00
|
|
|
void *opaque)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainDeviceInfo *info2 = opaque;
|
2011-05-09 06:59:16 +00:00
|
|
|
|
2012-02-23 17:59:21 +00:00
|
|
|
if (info1->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
|
|
|
|
info2->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
|
2011-05-09 06:59:16 +00:00
|
|
|
return 0;
|
|
|
|
|
2013-04-03 16:09:47 +00:00
|
|
|
if (info1->addr.pci.domain == info2->addr.pci.domain &&
|
|
|
|
info1->addr.pci.bus == info2->addr.pci.bus &&
|
|
|
|
info1->addr.pci.slot == info2->addr.pci.slot &&
|
2012-02-23 17:59:21 +00:00
|
|
|
info1->addr.pci.function != info2->addr.pci.function)
|
2011-05-09 06:59:16 +00:00
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static bool qemuIsMultiFunctionDevice(virDomainDef *def,
|
|
|
|
virDomainDeviceInfo *info)
|
2011-05-09 06:59:16 +00:00
|
|
|
{
|
2019-03-18 18:02:55 +00:00
|
|
|
if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
|
2017-10-18 13:33:45 +00:00
|
|
|
return false;
|
|
|
|
|
2019-03-18 18:02:55 +00:00
|
|
|
if (virDomainDeviceInfoIterate(def, qemuComparePCIDevice, info) < 0)
|
2011-05-09 06:59:16 +00:00
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-12-16 16:10:54 +00:00
|
|
|
|
2014-05-27 10:09:09 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveDiskDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainDiskDef *disk)
|
2013-07-09 21:43:22 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(qemuBlockStorageSourceChainData) diskBackend = NULL;
|
2013-07-09 21:43:22 +00:00
|
|
|
virDomainDeviceDef dev;
|
|
|
|
size_t i;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2019-03-28 15:04:55 +00:00
|
|
|
bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
|
2018-07-13 10:54:26 +00:00
|
|
|
int ret = -1;
|
2013-07-09 21:43:22 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Removing disk %s from domain %p %s",
|
|
|
|
disk->info.alias, vm, vm->def->name);
|
|
|
|
|
2014-05-27 10:09:09 +00:00
|
|
|
|
2021-02-01 11:00:35 +00:00
|
|
|
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
|
|
|
char *chardevAlias = qemuDomainGetVhostUserChrAlias(disk->info.alias);
|
|
|
|
|
|
|
|
if (!(diskBackend = qemuBlockStorageSourceChainDetachPrepareChardev(chardevAlias)))
|
|
|
|
goto cleanup;
|
2021-05-07 12:54:31 +00:00
|
|
|
} else if (blockdev && !qemuDiskBusIsSD(disk->bus)) {
|
2019-03-25 15:30:28 +00:00
|
|
|
if (diskPriv->blockjob) {
|
|
|
|
/* the block job keeps reference to the disk chain */
|
|
|
|
diskPriv->blockjob->disk = NULL;
|
|
|
|
virObjectUnref(diskPriv->blockjob);
|
|
|
|
diskPriv->blockjob = NULL;
|
|
|
|
} else {
|
|
|
|
if (!(diskBackend = qemuBlockStorageSourceChainDetachPrepareBlockdev(disk->src)))
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2021-05-07 12:54:31 +00:00
|
|
|
|
|
|
|
if (diskPriv->nodeCopyOnRead) {
|
|
|
|
if (!diskBackend)
|
|
|
|
diskBackend = g_new0(qemuBlockStorageSourceChainData, 1);
|
|
|
|
diskBackend->copyOnReadNodename = g_strdup(diskPriv->nodeCopyOnRead);
|
|
|
|
diskBackend->copyOnReadAttached = true;
|
|
|
|
}
|
2019-04-05 11:47:44 +00:00
|
|
|
} else {
|
|
|
|
char *driveAlias;
|
|
|
|
|
|
|
|
if (!(driveAlias = qemuAliasDiskDriveFromDisk(disk)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(diskBackend = qemuBlockStorageSourceChainDetachPrepareDrive(disk->src, driveAlias)))
|
|
|
|
goto cleanup;
|
2019-03-28 15:04:55 +00:00
|
|
|
}
|
|
|
|
|
2018-05-31 13:18:20 +00:00
|
|
|
for (i = 0; i < vm->def->ndisks; i++) {
|
|
|
|
if (vm->def->disks[i] == disk) {
|
|
|
|
virDomainDiskRemove(vm->def, i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-27 10:09:09 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2016-06-22 11:07:49 +00:00
|
|
|
|
2019-03-25 15:30:28 +00:00
|
|
|
if (diskBackend)
|
|
|
|
qemuBlockStorageSourceChainDetach(priv->mon, diskBackend);
|
qemu: Add TLS support for Veritas HyperScale (VxHS)
Alter qemu command line generation in order to possibly add TLS for
a suitably configured domain.
Sample TLS args generated by libvirt -
-object tls-creds-x509,id=objvirtio-disk0_tls0,dir=/etc/pki/qemu,\
endpoint=client,verify-peer=yes \
-drive file.driver=vxhs,file.tls-creds=objvirtio-disk0_tls0,\
file.vdisk-id=eb90327c-8302-4725-9e1b-4e85ed4dc251,\
file.server.type=tcp,file.server.host=192.168.0.1,\
file.server.port=9999,format=raw,if=none,\
id=drive-virtio-disk0,cache=none \
-device virtio-blk-pci,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,\
id=virtio-disk0
Update the qemuxml2argvtest with a couple of examples. One for a
simple case and the other a bit more complex where multiple VxHS disks
are added where at least one uses a VxHS that doesn't require TLS
credentials and thus sets the domain disk source attribute "tls = 'no'".
Update the hotplug to be able to handle processing the tlsAlias whether
it's to add the TLS object when hotplugging a disk or to remove the TLS
object when hot unplugging a disk. The hot plug/unplug code is largely
generic, but the addition code does make the VXHS specific checks only
because it needs to grab the correct config directory and generate the
object as the command line would do.
Signed-off-by: Ashish Mittal <Ashish.Mittal@veritas.com>
Signed-off-by: John Ferlan <jferlan@redhat.com>
2017-08-30 15:06:00 +00:00
|
|
|
|
2014-12-16 14:50:20 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
2018-07-13 10:54:26 +00:00
|
|
|
goto cleanup;
|
2014-05-27 10:09:09 +00:00
|
|
|
|
2014-07-03 08:28:12 +00:00
|
|
|
virDomainAuditDisk(vm, disk->src, NULL, "detach", true);
|
2013-07-09 21:43:22 +00:00
|
|
|
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &disk->info);
|
2013-07-09 21:43:22 +00:00
|
|
|
|
2018-07-11 15:21:36 +00:00
|
|
|
/* tear down disk security access */
|
2019-03-25 15:30:28 +00:00
|
|
|
if (diskBackend)
|
|
|
|
qemuDomainStorageSourceChainAccessRevoke(driver, vm, disk->src);
|
2016-11-15 15:53:04 +00:00
|
|
|
|
2013-07-09 21:43:22 +00:00
|
|
|
dev.type = VIR_DOMAIN_DEVICE_DISK;
|
|
|
|
dev.data.disk = disk;
|
|
|
|
ignore_value(qemuRemoveSharedDevice(driver, &dev, vm->def->name));
|
|
|
|
|
2019-06-18 13:28:26 +00:00
|
|
|
if (virStorageSourceChainHasManagedPR(disk->src) &&
|
|
|
|
qemuHotplugRemoveManagedPR(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
|
2018-07-11 12:24:49 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2020-09-22 12:53:57 +00:00
|
|
|
if (disk->transient) {
|
|
|
|
VIR_DEBUG("Removing transient overlay '%s' of disk '%s'",
|
|
|
|
disk->src->path, disk->dst);
|
|
|
|
if (qemuDomainStorageFileInit(driver, vm, disk->src, NULL) >= 0) {
|
2021-01-21 15:46:14 +00:00
|
|
|
virStorageSourceUnlink(disk->src);
|
|
|
|
virStorageSourceDeinit(disk->src);
|
2020-09-22 12:53:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-13 10:54:26 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2013-07-09 21:43:22 +00:00
|
|
|
virDomainDiskDefFree(disk);
|
2018-07-13 10:54:26 +00:00
|
|
|
return ret;
|
2013-07-09 21:43:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-03 08:18:48 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveControllerDevice(virDomainObj *vm,
|
|
|
|
virDomainControllerDef *controller)
|
2013-07-09 22:10:32 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
VIR_DEBUG("Removing controller %s from domain %p %s",
|
|
|
|
controller->info.alias, vm, vm->def->name);
|
|
|
|
|
|
|
|
for (i = 0; i < vm->def->ncontrollers; i++) {
|
|
|
|
if (vm->def->controllers[i] == controller) {
|
|
|
|
virDomainControllerRemove(vm->def, i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &controller->info);
|
2013-07-09 22:10:32 +00:00
|
|
|
virDomainControllerDefFree(controller);
|
2014-06-03 08:18:48 +00:00
|
|
|
return 0;
|
2013-07-09 22:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-21 16:45:54 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveMemoryDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainMemoryDef *mem)
|
2015-01-21 16:45:54 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2016-06-15 13:34:04 +00:00
|
|
|
unsigned long long oldmem = virDomainDefGetMemoryTotal(vm->def);
|
2015-08-13 14:15:28 +00:00
|
|
|
unsigned long long newmem = oldmem - mem->size;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *backendAlias = NULL;
|
2015-01-21 16:45:54 +00:00
|
|
|
int rc;
|
|
|
|
int idx;
|
|
|
|
|
|
|
|
VIR_DEBUG("Removing memory device %s from domain %p %s",
|
|
|
|
mem->info.alias, vm, vm->def->name);
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
backendAlias = g_strdup_printf("mem%s", mem->info.alias);
|
2015-01-21 16:45:54 +00:00
|
|
|
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2020-03-18 11:24:40 +00:00
|
|
|
rc = qemuMonitorDelObject(priv->mon, backendAlias, true);
|
2015-08-13 14:15:28 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
rc = -1;
|
|
|
|
|
|
|
|
virDomainAuditMemory(vm, oldmem, newmem, "update", rc == 0);
|
|
|
|
if (rc < 0)
|
|
|
|
return -1;
|
2015-01-21 16:45:54 +00:00
|
|
|
|
|
|
|
if ((idx = virDomainMemoryFindByDef(vm->def, mem)) >= 0)
|
|
|
|
virDomainMemoryRemove(vm->def, idx);
|
|
|
|
|
2016-08-04 13:26:09 +00:00
|
|
|
if (qemuSecurityRestoreMemoryLabel(driver, vm, mem) < 0)
|
|
|
|
VIR_WARN("Unable to restore security label on memdev");
|
|
|
|
|
2017-02-22 15:33:12 +00:00
|
|
|
if (qemuTeardownMemoryDevicesCgroup(vm, mem) < 0)
|
|
|
|
VIR_WARN("Unable to remove memory device cgroup ACL");
|
|
|
|
|
2017-11-24 16:52:15 +00:00
|
|
|
if (qemuDomainNamespaceTeardownMemory(vm, mem) < 0)
|
2017-02-22 16:37:39 +00:00
|
|
|
VIR_WARN("Unable to remove memory device from /dev");
|
|
|
|
|
2018-01-11 12:02:52 +00:00
|
|
|
if (qemuProcessDestroyMemoryBackingPath(driver, vm, mem) < 0)
|
|
|
|
VIR_WARN("Unable to destroy memory backing path");
|
|
|
|
|
2021-02-08 14:21:16 +00:00
|
|
|
qemuDomainReleaseMemoryDeviceSlot(vm, mem);
|
|
|
|
|
2015-01-21 16:45:54 +00:00
|
|
|
virDomainMemoryDefFree(mem);
|
2015-11-06 15:39:31 +00:00
|
|
|
|
2016-04-06 13:57:57 +00:00
|
|
|
/* fix the balloon size */
|
|
|
|
ignore_value(qemuProcessRefreshBalloonState(driver, vm, QEMU_ASYNC_JOB_NONE));
|
|
|
|
|
2015-11-06 15:39:31 +00:00
|
|
|
/* decrease the mlock limit after memory unplug if necessary */
|
2019-09-26 11:15:47 +00:00
|
|
|
ignore_value(qemuDomainAdjustMaxMemLock(vm, false));
|
2015-11-06 15:39:31 +00:00
|
|
|
|
2015-08-13 14:15:28 +00:00
|
|
|
return 0;
|
2015-01-21 16:45:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-11 09:14:16 +00:00
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemovePCIHostDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2013-07-11 09:14:16 +00:00
|
|
|
{
|
2015-10-20 12:12:48 +00:00
|
|
|
qemuHostdevReAttachPCIDevices(driver, vm->def->name, &hostdev, 1);
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, hostdev->info);
|
2013-07-11 09:14:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveUSBHostDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2013-07-11 09:14:16 +00:00
|
|
|
{
|
2015-10-20 12:12:48 +00:00
|
|
|
qemuHostdevReAttachUSBDevices(driver, vm->def->name, &hostdev, 1);
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, hostdev->info);
|
2013-07-11 09:14:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveSCSIHostDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2013-07-11 09:14:16 +00:00
|
|
|
{
|
2015-10-20 12:12:48 +00:00
|
|
|
qemuHostdevReAttachSCSIDevices(driver, vm->def->name, &hostdev, 1);
|
2013-07-11 09:14:16 +00:00
|
|
|
}
|
|
|
|
|
2016-11-22 03:58:19 +00:00
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveSCSIVHostDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2016-11-22 03:58:19 +00:00
|
|
|
{
|
|
|
|
qemuHostdevReAttachSCSIVHostDevices(driver, vm->def->name, &hostdev, 1);
|
|
|
|
}
|
|
|
|
|
2018-03-26 08:06:07 +00:00
|
|
|
|
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveMediatedDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2018-03-26 08:06:07 +00:00
|
|
|
{
|
|
|
|
qemuHostdevReAttachMediatedDevices(driver, vm->def->name, &hostdev, 1);
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, hostdev->info);
|
2018-03-26 08:06:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-03 08:18:48 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveHostDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2013-07-11 09:14:16 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainNetDef *net = NULL;
|
2013-07-11 09:14:16 +00:00
|
|
|
size_t i;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2013-07-11 09:14:16 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Removing host device %s from domain %p %s",
|
|
|
|
hostdev->info->alias, vm, vm->def->name);
|
|
|
|
|
2014-09-23 22:53:25 +00:00
|
|
|
if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
|
2020-06-19 13:51:06 +00:00
|
|
|
g_autoptr(qemuBlockStorageSourceAttachData) detachscsi = NULL;
|
2017-09-15 17:17:59 +00:00
|
|
|
|
2020-06-19 13:51:06 +00:00
|
|
|
detachscsi = qemuBuildHostdevSCSIDetachPrepare(hostdev, priv->qemuCaps);
|
2017-09-15 17:17:59 +00:00
|
|
|
|
2014-09-23 22:53:25 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2020-06-19 13:51:06 +00:00
|
|
|
qemuBlockStorageSourceAttachRollback(priv->mon, detachscsi);
|
2014-12-16 14:50:20 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2014-09-23 22:53:25 +00:00
|
|
|
}
|
|
|
|
|
2018-07-26 16:24:30 +00:00
|
|
|
if (hostdev->parentnet) {
|
2019-09-13 12:41:29 +00:00
|
|
|
net = hostdev->parentnet;
|
2013-07-11 09:14:16 +00:00
|
|
|
for (i = 0; i < vm->def->nnets; i++) {
|
2018-07-26 16:24:30 +00:00
|
|
|
if (vm->def->nets[i] == hostdev->parentnet) {
|
2013-07-11 09:14:16 +00:00
|
|
|
virDomainNetRemove(vm->def, i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < vm->def->nhostdevs; i++) {
|
|
|
|
if (vm->def->hostdevs[i] == hostdev) {
|
|
|
|
virDomainHostdevRemove(vm->def, i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainAuditHostdev(vm, hostdev, "detach", true);
|
|
|
|
|
2019-08-06 14:25:12 +00:00
|
|
|
if (!virHostdevIsVFIODevice(hostdev) &&
|
2016-11-16 14:27:47 +00:00
|
|
|
qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
|
2016-06-17 11:14:56 +00:00
|
|
|
VIR_WARN("Failed to restore host device labelling");
|
2016-03-28 11:34:03 +00:00
|
|
|
|
2016-03-28 11:40:57 +00:00
|
|
|
if (qemuTeardownHostdevCgroup(vm, hostdev) < 0)
|
|
|
|
VIR_WARN("Failed to remove host device cgroup ACL");
|
|
|
|
|
2017-11-24 16:52:15 +00:00
|
|
|
if (qemuDomainNamespaceTeardownHostdev(vm, hostdev) < 0)
|
2016-11-16 14:27:47 +00:00
|
|
|
VIR_WARN("Unable to remove host device from /dev");
|
|
|
|
|
2018-04-25 12:42:34 +00:00
|
|
|
switch ((virDomainHostdevSubsysType)hostdev->source.subsys.type) {
|
2013-07-11 09:14:16 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
|
|
|
|
qemuDomainRemovePCIHostDevice(driver, vm, hostdev);
|
2015-11-18 12:56:09 +00:00
|
|
|
/* QEMU might no longer need to lock as much memory, eg. we just
|
|
|
|
* detached the last VFIO device, so adjust the limit here */
|
2019-09-26 11:15:47 +00:00
|
|
|
if (qemuDomainAdjustMaxMemLock(vm, false) < 0)
|
2015-11-18 12:56:09 +00:00
|
|
|
VIR_WARN("Failed to adjust locked memory limit");
|
2013-07-11 09:14:16 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
|
|
|
|
qemuDomainRemoveUSBHostDevice(driver, vm, hostdev);
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
|
|
|
|
qemuDomainRemoveSCSIHostDevice(driver, vm, hostdev);
|
|
|
|
break;
|
2016-11-22 03:58:16 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
|
2016-11-22 03:58:19 +00:00
|
|
|
qemuDomainRemoveSCSIVHostDevice(driver, vm, hostdev);
|
2016-11-22 03:58:16 +00:00
|
|
|
break;
|
2017-01-31 16:26:36 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
|
2018-03-26 08:06:07 +00:00
|
|
|
qemuDomainRemoveMediatedDevice(driver, vm, hostdev);
|
2017-01-31 16:26:36 +00:00
|
|
|
break;
|
2013-07-11 09:14:16 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainHostdevDefFree(hostdev);
|
|
|
|
|
|
|
|
if (net) {
|
2018-07-26 14:32:04 +00:00
|
|
|
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
2019-10-17 15:44:01 +00:00
|
|
|
g_autoptr(virConnect) conn = virGetConnectNetwork();
|
|
|
|
if (conn)
|
2018-07-26 14:32:04 +00:00
|
|
|
virDomainNetReleaseActualDevice(conn, vm->def, net);
|
2019-10-17 15:44:01 +00:00
|
|
|
else
|
2018-07-26 14:32:04 +00:00
|
|
|
VIR_WARN("Unable to release network device '%s'", NULLSTR(net->ifname));
|
|
|
|
}
|
2013-07-11 09:14:16 +00:00
|
|
|
virDomainNetDefFree(net);
|
|
|
|
}
|
2015-11-18 12:56:09 +00:00
|
|
|
|
2019-09-18 19:53:06 +00:00
|
|
|
return 0;
|
2013-07-11 09:14:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-27 09:50:41 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveNetDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainNetDef *net)
|
2013-10-18 09:28:40 +00:00
|
|
|
{
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *hostnet_name = NULL;
|
|
|
|
g_autofree char *charDevAlias = NULL;
|
2013-10-18 09:28:40 +00:00
|
|
|
size_t i;
|
2016-08-15 16:01:55 +00:00
|
|
|
int actualType = virDomainNetGetActualType(net);
|
2013-10-18 09:28:40 +00:00
|
|
|
|
2016-08-15 16:01:55 +00:00
|
|
|
if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
|
2013-10-18 09:34:53 +00:00
|
|
|
/* this function handles all hostdev and netdev cleanup */
|
2019-09-18 19:53:06 +00:00
|
|
|
return qemuDomainRemoveHostDevice(driver, vm,
|
|
|
|
virDomainNetGetActualHostdev(net));
|
2013-10-18 09:34:53 +00:00
|
|
|
}
|
|
|
|
|
2013-10-18 09:28:40 +00:00
|
|
|
VIR_DEBUG("Removing network interface %s from domain %p %s",
|
|
|
|
net->info.alias, vm, vm->def->name);
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
hostnet_name = g_strdup_printf("host%s", net->info.alias);
|
|
|
|
if (!(charDevAlias = qemuAliasChardevFromDevAlias(net->info.alias)))
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2014-05-27 09:50:41 +00:00
|
|
|
|
2021-07-07 09:18:19 +00:00
|
|
|
if (virNetDevSupportsBandwidth(virDomainNetGetActualType(net))) {
|
|
|
|
if (virDomainNetDefIsOvsport(net)) {
|
|
|
|
if (virNetDevOpenvswitchInterfaceClearQos(net->ifname, vm->def->uuid) < 0)
|
|
|
|
VIR_WARN("cannot clear bandwidth setting for ovs device : %s",
|
|
|
|
net->ifname);
|
|
|
|
} else if (virNetDevBandwidthClear(net->ifname) < 0) {
|
|
|
|
VIR_WARN("cannot clear bandwidth setting for device : %s",
|
|
|
|
net->ifname);
|
|
|
|
}
|
|
|
|
}
|
2019-03-25 14:46:56 +00:00
|
|
|
|
|
|
|
/* deactivate the tap/macvtap device on the host, which could also
|
|
|
|
* affect the parent device (e.g. macvtap passthrough mode sets
|
|
|
|
* the parent device offline)
|
|
|
|
*/
|
|
|
|
ignore_value(qemuInterfaceStopDevice(net));
|
2016-08-15 16:01:55 +00:00
|
|
|
|
2014-05-27 09:50:41 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2018-03-28 21:36:13 +00:00
|
|
|
if (qemuMonitorRemoveNetdev(priv->mon, hostnet_name) < 0) {
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2018-03-28 21:36:13 +00:00
|
|
|
virDomainAuditNet(vm, net, NULL, "detach", false);
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2014-05-27 09:50:41 +00:00
|
|
|
}
|
2016-08-15 16:01:55 +00:00
|
|
|
|
|
|
|
if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
|
|
|
|
/* vhostuser has a chardev too */
|
|
|
|
if (qemuMonitorDetachCharDev(priv->mon, charDevAlias) < 0) {
|
|
|
|
/* well, this is a messy situation. Guest visible PCI device has
|
|
|
|
* been removed, netdev too but chardev not. The best seems to be
|
|
|
|
* to just ignore the error and carry on.
|
|
|
|
*/
|
|
|
|
}
|
2020-10-14 17:08:29 +00:00
|
|
|
} else if (actualType == VIR_DOMAIN_NET_TYPE_VDPA) {
|
|
|
|
int vdpafdset = -1;
|
|
|
|
g_autoptr(qemuMonitorFdsets) fdsets = NULL;
|
|
|
|
|
|
|
|
/* query qemu for which fdset is associated with the fd that we passed
|
|
|
|
* to qemu via 'add-fd' for this vdpa device. If we don't remove the
|
|
|
|
* fd, qemu will keep it open */
|
|
|
|
if (qemuMonitorQueryFdsets(priv->mon, &fdsets) == 0) {
|
|
|
|
for (i = 0; i < fdsets->nfdsets && vdpafdset < 0; i++) {
|
|
|
|
size_t j;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuMonitorFdsetInfo *set = &fdsets->fdsets[i];
|
2020-10-14 17:08:29 +00:00
|
|
|
|
|
|
|
for (j = 0; j < set->nfds; j++) {
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuMonitorFdsetFdInfo *fdinfo = &set->fds[j];
|
2020-10-14 17:08:29 +00:00
|
|
|
if (STREQ_NULLABLE(fdinfo->opaque, net->data.vdpa.devicepath)) {
|
|
|
|
vdpafdset = set->id;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vdpafdset < 0) {
|
|
|
|
VIR_WARN("Cannot determine fdset for vdpa device");
|
|
|
|
} else {
|
|
|
|
if (qemuMonitorRemoveFdset(priv->mon, vdpafdset) < 0) {
|
|
|
|
/* if it fails, there's not much we can do... just carry on */
|
|
|
|
VIR_WARN("failed to close vdpa device");
|
|
|
|
}
|
|
|
|
}
|
2016-08-15 16:01:55 +00:00
|
|
|
}
|
|
|
|
|
2020-10-14 17:08:29 +00:00
|
|
|
|
2014-12-16 14:50:20 +00:00
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2014-05-27 09:50:41 +00:00
|
|
|
|
2019-08-08 14:55:13 +00:00
|
|
|
if (QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp)
|
2020-02-25 09:55:05 +00:00
|
|
|
qemuSlirpStop(QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp, vm, driver, net);
|
2019-08-08 14:55:13 +00:00
|
|
|
|
2013-10-18 09:28:40 +00:00
|
|
|
virDomainAuditNet(vm, net, NULL, "detach", true);
|
|
|
|
|
|
|
|
for (i = 0; i < vm->def->nnets; i++) {
|
|
|
|
if (vm->def->nets[i] == net) {
|
|
|
|
virDomainNetRemove(vm->def, i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &net->info);
|
2013-10-18 09:28:40 +00:00
|
|
|
virDomainConfNWFilterTeardown(net);
|
|
|
|
|
2014-09-30 10:55:23 +00:00
|
|
|
if (cfg->macFilter && (net->ifname != NULL)) {
|
|
|
|
ignore_value(ebtablesRemoveForwardAllowIn(driver->ebtables,
|
|
|
|
net->ifname,
|
|
|
|
&net->mac));
|
|
|
|
}
|
|
|
|
|
2016-08-15 16:01:55 +00:00
|
|
|
if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
2013-10-18 09:28:40 +00:00
|
|
|
ignore_value(virNetDevMacVLanDeleteWithVPortProfile(
|
|
|
|
net->ifname, &net->mac,
|
|
|
|
virDomainNetGetActualDirectDev(net),
|
|
|
|
virDomainNetGetActualDirectMode(net),
|
|
|
|
virDomainNetGetActualVirtPortProfile(net),
|
|
|
|
cfg->stateDir));
|
|
|
|
}
|
|
|
|
|
2017-06-28 10:56:47 +00:00
|
|
|
qemuDomainNetDeviceVportRemove(net);
|
2013-10-18 09:28:40 +00:00
|
|
|
|
2018-07-26 14:32:04 +00:00
|
|
|
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
2019-10-17 15:44:01 +00:00
|
|
|
g_autoptr(virConnect) conn = virGetConnectNetwork();
|
|
|
|
if (conn)
|
2018-07-26 14:32:04 +00:00
|
|
|
virDomainNetReleaseActualDevice(conn, vm->def, net);
|
2019-10-17 15:44:01 +00:00
|
|
|
else
|
2018-07-26 14:32:04 +00:00
|
|
|
VIR_WARN("Unable to release network device '%s'", NULLSTR(net->ifname));
|
2020-05-26 00:41:00 +00:00
|
|
|
} else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET) {
|
2020-05-29 15:52:24 +00:00
|
|
|
if (net->downscript)
|
|
|
|
virNetDevRunEthernetScript(net->ifname, net->downscript);
|
2018-07-26 14:32:04 +00:00
|
|
|
}
|
2013-10-18 09:28:40 +00:00
|
|
|
virDomainNetDefFree(net);
|
2019-09-18 19:53:06 +00:00
|
|
|
return 0;
|
2013-10-18 09:28:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-27 11:30:04 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveChrDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainChrDef *chr,
|
2019-02-11 13:16:58 +00:00
|
|
|
bool monitor)
|
2013-07-16 19:16:09 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virObjectEvent *event;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *charAlias = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2019-02-11 13:16:58 +00:00
|
|
|
int rc = 0;
|
2013-07-11 15:30:56 +00:00
|
|
|
|
2013-07-16 19:16:09 +00:00
|
|
|
VIR_DEBUG("Removing character device %s from domain %p %s",
|
|
|
|
chr->info.alias, vm, vm->def->name);
|
|
|
|
|
2019-02-14 13:13:08 +00:00
|
|
|
if (!(charAlias = qemuAliasChardevFromDevAlias(chr->info.alias)))
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2014-05-27 11:30:04 +00:00
|
|
|
|
2019-02-14 13:13:08 +00:00
|
|
|
if (monitor) {
|
2019-02-11 13:16:58 +00:00
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
rc = qemuMonitorDetachCharDev(priv->mon, charAlias);
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2019-02-11 13:16:58 +00:00
|
|
|
}
|
2014-05-27 11:30:04 +00:00
|
|
|
|
2017-12-20 11:36:26 +00:00
|
|
|
if (rc == 0 &&
|
|
|
|
qemuDomainDelChardevTLSObjects(driver, vm, chr->source, charAlias) < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2017-12-19 22:46:41 +00:00
|
|
|
|
2014-07-03 08:59:58 +00:00
|
|
|
virDomainAuditChardev(vm, chr, NULL, "detach", rc == 0);
|
|
|
|
|
|
|
|
if (rc < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2014-07-03 08:59:58 +00:00
|
|
|
|
2016-11-18 10:45:44 +00:00
|
|
|
if (qemuTeardownChardevCgroup(vm, chr) < 0)
|
|
|
|
VIR_WARN("Failed to remove chr device cgroup ACL");
|
|
|
|
|
2017-12-01 12:10:35 +00:00
|
|
|
if (qemuSecurityRestoreChardevLabel(driver, vm, chr) < 0)
|
|
|
|
VIR_WARN("Unable to restore security label on char device");
|
|
|
|
|
2017-11-24 16:52:15 +00:00
|
|
|
if (qemuDomainNamespaceTeardownChardev(vm, chr) < 0)
|
2016-11-18 13:53:27 +00:00
|
|
|
VIR_WARN("Unable to remove chr device from /dev");
|
|
|
|
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &chr->info);
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
qemuDomainChrRemove(vm->def, chr);
|
|
|
|
|
|
|
|
/* The caller does not emit the event, so we must do it here. Note
|
|
|
|
* that the event should be reported only after all backend
|
|
|
|
* teardown is completed.
|
|
|
|
*/
|
2013-07-11 15:30:56 +00:00
|
|
|
event = virDomainEventDeviceRemovedNewFromObj(vm, chr->info.alias);
|
2018-06-12 17:33:02 +00:00
|
|
|
virObjectEventStateQueue(driver->domainEventState, event);
|
2013-07-11 15:30:56 +00:00
|
|
|
|
2013-07-16 19:16:09 +00:00
|
|
|
virDomainChrDefFree(chr);
|
2019-09-18 19:53:06 +00:00
|
|
|
return 0;
|
2013-07-16 19:16:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-17 05:09:38 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveRNGDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainRNGDef *rng)
|
2015-01-17 05:09:38 +00:00
|
|
|
{
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *charAlias = NULL;
|
|
|
|
g_autofree char *objAlias = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2015-01-17 05:09:38 +00:00
|
|
|
ssize_t idx;
|
2018-12-04 13:30:37 +00:00
|
|
|
int rc = 0;
|
2015-01-17 05:09:38 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Removing RNG device %s from domain %p %s",
|
|
|
|
rng->info.alias, vm, vm->def->name);
|
|
|
|
|
2016-10-24 19:59:11 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
objAlias = g_strdup_printf("obj%s", rng->info.alias);
|
2015-01-17 05:09:38 +00:00
|
|
|
|
2016-10-18 14:37:23 +00:00
|
|
|
if (!(charAlias = qemuAliasChardevFromDevAlias(rng->info.alias)))
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2015-01-17 05:09:38 +00:00
|
|
|
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
2016-10-24 19:59:11 +00:00
|
|
|
|
2020-08-02 20:57:29 +00:00
|
|
|
if (qemuMonitorDelObject(priv->mon, objAlias, true) < 0)
|
2018-12-04 13:30:37 +00:00
|
|
|
rc = -1;
|
|
|
|
|
|
|
|
if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD &&
|
|
|
|
rc == 0 &&
|
|
|
|
qemuMonitorDetachCharDev(priv->mon, charAlias) < 0)
|
|
|
|
rc = -1;
|
2015-01-17 05:09:38 +00:00
|
|
|
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2015-01-17 05:09:38 +00:00
|
|
|
|
2017-12-19 22:46:41 +00:00
|
|
|
if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD &&
|
|
|
|
rc == 0 &&
|
2017-12-20 11:36:26 +00:00
|
|
|
qemuDomainDelChardevTLSObjects(driver, vm, rng->source.chardev,
|
|
|
|
charAlias) < 0)
|
2018-12-04 13:30:37 +00:00
|
|
|
rc = -1;
|
2017-12-19 22:46:41 +00:00
|
|
|
|
2015-01-17 05:09:38 +00:00
|
|
|
virDomainAuditRNG(vm, rng, NULL, "detach", rc == 0);
|
|
|
|
|
|
|
|
if (rc < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2015-01-17 05:09:38 +00:00
|
|
|
|
2016-11-18 10:17:51 +00:00
|
|
|
if (qemuTeardownRNGCgroup(vm, rng) < 0)
|
|
|
|
VIR_WARN("Failed to remove RNG device cgroup ACL");
|
|
|
|
|
2017-11-24 16:52:15 +00:00
|
|
|
if (qemuDomainNamespaceTeardownRNG(vm, rng) < 0)
|
2016-11-18 14:19:12 +00:00
|
|
|
VIR_WARN("Unable to remove RNG device from /dev");
|
|
|
|
|
2015-01-17 05:09:38 +00:00
|
|
|
if ((idx = virDomainRNGFind(vm->def, rng)) >= 0)
|
|
|
|
virDomainRNGRemove(vm->def, idx);
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &rng->info);
|
2015-01-17 05:09:38 +00:00
|
|
|
virDomainRNGDefFree(rng);
|
2019-09-18 19:53:06 +00:00
|
|
|
return 0;
|
2015-01-17 05:09:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-12 13:40:48 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveShmemDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainShmemDef *shmem)
|
2016-09-12 13:40:48 +00:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
ssize_t idx = -1;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *charAlias = NULL;
|
|
|
|
g_autofree char *memAlias = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2016-09-12 13:40:48 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Removing shmem device %s from domain %p %s",
|
|
|
|
shmem->info.alias, vm, vm->def->name);
|
|
|
|
|
|
|
|
if (shmem->server.enabled) {
|
2019-10-22 13:26:14 +00:00
|
|
|
charAlias = g_strdup_printf("char%s", shmem->info.alias);
|
2016-09-12 13:40:48 +00:00
|
|
|
} else {
|
2019-10-22 13:26:14 +00:00
|
|
|
memAlias = g_strdup_printf("shmmem-%s", shmem->info.alias);
|
2016-09-12 13:40:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
|
|
|
|
if (shmem->server.enabled)
|
|
|
|
rc = qemuMonitorDetachCharDev(priv->mon, charAlias);
|
|
|
|
else
|
2020-03-18 11:24:40 +00:00
|
|
|
rc = qemuMonitorDelObject(priv->mon, memAlias, true);
|
2016-09-12 13:40:48 +00:00
|
|
|
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2016-09-12 13:40:48 +00:00
|
|
|
|
|
|
|
virDomainAuditShmem(vm, shmem, "detach", rc == 0);
|
|
|
|
|
|
|
|
if (rc < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2016-09-12 13:40:48 +00:00
|
|
|
|
|
|
|
if ((idx = virDomainShmemDefFind(vm->def, shmem)) >= 0)
|
|
|
|
virDomainShmemDefRemove(vm->def, idx);
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &shmem->info);
|
2016-09-12 13:40:48 +00:00
|
|
|
virDomainShmemDefFree(shmem);
|
|
|
|
|
2019-09-18 19:53:06 +00:00
|
|
|
return 0;
|
2016-09-12 13:40:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-09-05 09:08:36 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveWatchdog(virDomainObj *vm,
|
|
|
|
virDomainWatchdogDef *watchdog)
|
2017-09-05 09:08:36 +00:00
|
|
|
{
|
|
|
|
VIR_DEBUG("Removing watchdog %s from domain %p %s",
|
|
|
|
watchdog->info.alias, vm, vm->def->name);
|
|
|
|
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &watchdog->info);
|
2017-09-05 09:08:36 +00:00
|
|
|
virDomainWatchdogDefFree(vm->def->watchdog);
|
|
|
|
vm->def->watchdog = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-17 14:44:24 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveInputDevice(virDomainObj *vm,
|
|
|
|
virDomainInputDef *dev)
|
2017-10-17 14:44:24 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
VIR_DEBUG("Removing input device %s from domain %p %s",
|
|
|
|
dev->info.alias, vm, vm->def->name);
|
|
|
|
|
|
|
|
for (i = 0; i < vm->def->ninputs; i++) {
|
|
|
|
if (vm->def->inputs[i] == dev)
|
|
|
|
break;
|
|
|
|
}
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &dev->info);
|
2017-11-21 12:56:37 +00:00
|
|
|
if (qemuSecurityRestoreInputLabel(vm, dev) < 0)
|
|
|
|
VIR_WARN("Unable to restore security label on input device");
|
|
|
|
|
|
|
|
if (qemuTeardownInputCgroup(vm, dev) < 0)
|
|
|
|
VIR_WARN("Unable to remove input device cgroup ACL");
|
|
|
|
|
|
|
|
if (qemuDomainNamespaceTeardownInput(vm, dev) < 0)
|
|
|
|
VIR_WARN("Unable to remove input device from /dev");
|
|
|
|
|
2017-10-17 14:44:24 +00:00
|
|
|
virDomainInputDefFree(vm->def->inputs[i]);
|
|
|
|
VIR_DELETE_ELEMENT(vm->def->inputs, i, vm->def->ninputs);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-05-30 10:49:04 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveVsockDevice(virDomainObj *vm,
|
|
|
|
virDomainVsockDef *dev)
|
2018-05-30 10:49:04 +00:00
|
|
|
{
|
|
|
|
VIR_DEBUG("Removing vsock device %s from domain %p %s",
|
|
|
|
dev->info.alias, vm, vm->def->name);
|
|
|
|
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &dev->info);
|
2018-05-30 10:49:04 +00:00
|
|
|
virDomainVsockDefFree(vm->def->vsock);
|
|
|
|
vm->def->vsock = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-05 02:47:47 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveRedirdevDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainRedirdevDef *dev)
|
2018-01-05 02:47:47 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *charAlias = NULL;
|
2018-01-05 02:47:47 +00:00
|
|
|
ssize_t idx;
|
|
|
|
|
|
|
|
VIR_DEBUG("Removing redirdev device %s from domain %p %s",
|
|
|
|
dev->info.alias, vm, vm->def->name);
|
|
|
|
|
|
|
|
if (!(charAlias = qemuAliasChardevFromDevAlias(dev->info.alias)))
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2018-01-05 02:47:47 +00:00
|
|
|
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
/* DeviceDel from Detach may remove chardev,
|
|
|
|
* so we cannot rely on return status to delete TLS chardevs.
|
|
|
|
*/
|
|
|
|
ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias));
|
|
|
|
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2018-01-05 02:47:47 +00:00
|
|
|
|
|
|
|
if (qemuDomainDelChardevTLSObjects(driver, vm, dev->source, charAlias) < 0)
|
2019-09-18 19:53:06 +00:00
|
|
|
return -1;
|
2018-01-05 02:47:47 +00:00
|
|
|
|
|
|
|
virDomainAuditRedirdev(vm, dev, "detach", true);
|
|
|
|
|
|
|
|
if ((idx = virDomainRedirdevDefFind(vm->def, dev)) >= 0)
|
|
|
|
virDomainRedirdevDefRemove(vm->def, idx);
|
2019-03-28 12:12:32 +00:00
|
|
|
qemuDomainReleaseDeviceAddress(vm, &dev->info);
|
2018-01-05 02:47:47 +00:00
|
|
|
virDomainRedirdevDefFree(dev);
|
|
|
|
|
2019-09-18 19:53:06 +00:00
|
|
|
return 0;
|
2018-01-05 02:47:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveAuditDevice(virDomainObj *vm,
|
|
|
|
virDomainDeviceDef *detach,
|
2019-03-20 23:44:05 +00:00
|
|
|
bool success)
|
|
|
|
{
|
|
|
|
switch ((virDomainDeviceType)detach->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
|
|
|
virDomainAuditDisk(vm, detach->data.disk->src, NULL, "detach", success);
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_NET:
|
|
|
|
virDomainAuditNet(vm, detach->data.net, NULL, "detach", success);
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_HOSTDEV:
|
|
|
|
virDomainAuditHostdev(vm, detach->data.hostdev, "detach", success);
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_INPUT:
|
2019-03-25 14:23:51 +00:00
|
|
|
virDomainAuditInput(vm, detach->data.input, "detach", success);
|
|
|
|
break;
|
2019-03-20 23:44:05 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_CHR:
|
2019-03-25 14:23:51 +00:00
|
|
|
virDomainAuditChardev(vm, detach->data.chr, NULL, "detach", success);
|
|
|
|
break;
|
2019-03-20 23:44:05 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_RNG:
|
2019-03-25 14:23:51 +00:00
|
|
|
virDomainAuditRNG(vm, detach->data.rng, NULL, "detach", success);
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_MEMORY: {
|
|
|
|
unsigned long long oldmem = virDomainDefGetMemoryTotal(vm->def);
|
|
|
|
unsigned long long newmem = oldmem - detach->data.memory->size;
|
|
|
|
|
|
|
|
virDomainAuditMemory(vm, oldmem, newmem, "update", success);
|
|
|
|
break;
|
|
|
|
}
|
2019-03-20 23:44:05 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_SHMEM:
|
2019-03-25 14:23:51 +00:00
|
|
|
virDomainAuditShmem(vm, detach->data.shmem, "detach", success);
|
|
|
|
break;
|
2019-03-20 23:44:05 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_REDIRDEV:
|
2019-03-25 14:23:51 +00:00
|
|
|
virDomainAuditRedirdev(vm, detach->data.redirdev, "detach", success);
|
|
|
|
break;
|
2019-03-20 23:44:05 +00:00
|
|
|
|
|
|
|
case VIR_DOMAIN_DEVICE_LEASE:
|
|
|
|
case VIR_DOMAIN_DEVICE_CONTROLLER:
|
|
|
|
case VIR_DOMAIN_DEVICE_WATCHDOG:
|
|
|
|
case VIR_DOMAIN_DEVICE_VSOCK:
|
|
|
|
/* These devices don't have associated audit logs */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_DEVICE_FS:
|
|
|
|
case VIR_DOMAIN_DEVICE_SOUND:
|
|
|
|
case VIR_DOMAIN_DEVICE_VIDEO:
|
|
|
|
case VIR_DOMAIN_DEVICE_GRAPHICS:
|
|
|
|
case VIR_DOMAIN_DEVICE_HUB:
|
|
|
|
case VIR_DOMAIN_DEVICE_SMARTCARD:
|
|
|
|
case VIR_DOMAIN_DEVICE_MEMBALLOON:
|
|
|
|
case VIR_DOMAIN_DEVICE_NVRAM:
|
|
|
|
case VIR_DOMAIN_DEVICE_NONE:
|
|
|
|
case VIR_DOMAIN_DEVICE_TPM:
|
|
|
|
case VIR_DOMAIN_DEVICE_PANIC:
|
|
|
|
case VIR_DOMAIN_DEVICE_IOMMU:
|
2020-07-18 06:23:57 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_AUDIO:
|
2019-03-20 23:44:05 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_LAST:
|
|
|
|
/* libvirt doesn't yet support detaching these devices */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-16 14:50:20 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveDevice(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainDeviceDef *dev)
|
2013-07-11 15:11:02 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainDeviceInfo *info;
|
|
|
|
virObjectEvent *event;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *alias = NULL;
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* save the alias to use when sending a DEVICE_REMOVED event after
|
|
|
|
* all other teardown is complete
|
|
|
|
*/
|
2019-10-20 11:49:46 +00:00
|
|
|
if ((info = virDomainDeviceGetInfo(dev)))
|
|
|
|
alias = g_strdup(info->alias);
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
info = NULL;
|
|
|
|
|
2018-04-25 12:42:34 +00:00
|
|
|
switch ((virDomainDeviceType)dev->type) {
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_CHR:
|
|
|
|
/* We must return directly after calling
|
|
|
|
* qemuDomainRemoveChrDevice because it is called directly
|
|
|
|
* from other places, so it must be completely self-contained
|
|
|
|
* and can't take advantage of any common code at the end of
|
|
|
|
* qemuDomainRemoveDevice().
|
|
|
|
*/
|
|
|
|
return qemuDomainRemoveChrDevice(driver, vm, dev->data.chr, true);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* all of the following qemuDomainRemove*Device() functions
|
|
|
|
* are (and must be) only called from this function, so any
|
|
|
|
* code that is common to them all can be pulled out and put
|
|
|
|
* into this function.
|
|
|
|
*/
|
2013-07-11 15:11:02 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
if (qemuDomainRemoveDiskDevice(driver, vm, dev->data.disk) < 0)
|
|
|
|
return -1;
|
2013-07-11 15:11:02 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_CONTROLLER:
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
if (qemuDomainRemoveControllerDevice(vm, dev->data.controller) < 0)
|
|
|
|
return -1;
|
2013-07-11 15:11:02 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_NET:
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
if (qemuDomainRemoveNetDevice(driver, vm, dev->data.net) < 0)
|
|
|
|
return -1;
|
2013-07-11 15:11:02 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_HOSTDEV:
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
if (qemuDomainRemoveHostDevice(driver, vm, dev->data.hostdev) < 0)
|
|
|
|
return -1;
|
2013-07-11 15:11:02 +00:00
|
|
|
break;
|
2015-01-17 05:09:38 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_RNG:
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
if (qemuDomainRemoveRNGDevice(driver, vm, dev->data.rng) < 0)
|
|
|
|
return -1;
|
2015-01-17 05:09:38 +00:00
|
|
|
break;
|
2014-09-29 17:02:04 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_MEMORY:
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
if (qemuDomainRemoveMemoryDevice(driver, vm, dev->data.memory) < 0)
|
|
|
|
return -1;
|
2015-01-21 16:45:54 +00:00
|
|
|
break;
|
2016-09-12 13:40:48 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_SHMEM:
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
if (qemuDomainRemoveShmemDevice(driver, vm, dev->data.shmem) < 0)
|
|
|
|
return -1;
|
2016-09-12 13:40:48 +00:00
|
|
|
break;
|
2017-12-14 09:45:31 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_INPUT:
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
if (qemuDomainRemoveInputDevice(vm, dev->data.input) < 0)
|
|
|
|
return -1;
|
2017-12-14 09:45:31 +00:00
|
|
|
break;
|
2018-01-05 02:47:47 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_REDIRDEV:
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
if (qemuDomainRemoveRedirdevDevice(driver, vm, dev->data.redirdev) < 0)
|
|
|
|
return -1;
|
2018-01-05 02:47:47 +00:00
|
|
|
break;
|
2018-03-31 08:12:17 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_WATCHDOG:
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
if (qemuDomainRemoveWatchdog(vm, dev->data.watchdog) < 0)
|
|
|
|
return -1;
|
2018-03-31 08:12:17 +00:00
|
|
|
break;
|
2018-05-30 10:49:04 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_VSOCK:
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
if (qemuDomainRemoveVsockDevice(vm, dev->data.vsock) < 0)
|
|
|
|
return -1;
|
2018-05-30 10:49:04 +00:00
|
|
|
break;
|
|
|
|
|
2013-07-11 15:11:02 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_NONE:
|
|
|
|
case VIR_DOMAIN_DEVICE_LEASE:
|
|
|
|
case VIR_DOMAIN_DEVICE_FS:
|
|
|
|
case VIR_DOMAIN_DEVICE_SOUND:
|
|
|
|
case VIR_DOMAIN_DEVICE_VIDEO:
|
|
|
|
case VIR_DOMAIN_DEVICE_GRAPHICS:
|
|
|
|
case VIR_DOMAIN_DEVICE_HUB:
|
|
|
|
case VIR_DOMAIN_DEVICE_SMARTCARD:
|
|
|
|
case VIR_DOMAIN_DEVICE_MEMBALLOON:
|
|
|
|
case VIR_DOMAIN_DEVICE_NVRAM:
|
2014-11-30 19:54:50 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_TPM:
|
2014-11-30 19:54:50 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_PANIC:
|
2016-06-22 14:28:22 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_IOMMU:
|
2020-07-18 06:23:57 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_AUDIO:
|
2013-07-11 15:11:02 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_LAST:
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("don't know how to remove a %s device"),
|
|
|
|
virDomainDeviceTypeToString(dev->type));
|
|
|
|
break;
|
|
|
|
}
|
qemu_hotplug: delay sending DEVICE_REMOVED event until after *all* teardown
The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has
responded to a device_del command with a DEVICE_DELETED event. Before
queuing the event, *some* of the final teardown of the device's
trappings in libvirt is done, but not *all* of it. As a result, an
application may receive and process the DEVICE_REMOVED event before
libvirt has really finished with it.
Usually this doesn't cause a problem, but it can - in the case of the
bug report referenced below, vdsm is assigning a PCI device to a guest
with managed='no', using livirt's virNodeDeviceDetachFlags() and
virNodeDeviceReAttach() APIs. Immediately after receiving a
DEVICE_REMOVED event from libvirt signalling that the device had been
successfully unplugged, vdsm would cal virNodeDeviceReAttach() to
unbind the device from vfio-pci and rebind it to the host driverm but
because the event was received before libvirt had completely finished
processing the removal, that device was still on the "activeDevs"
list, and so virNodeDeviceReAttach() failed.
Experimentation with additional debug logs proved that libvirt would
always end up dispatching the DEVICE_REMOVED event before it had
removed the device from activeDevs (with a *much* greater difference
with managed='yes', since in that case the re-binding of the device
occurred after queuing the device).
Although the case of hostdev devices is the most extreme (since there
is so much involved in tearing down the device), *all* device types
suffer from the same problem - the DEVICE_REMOVED event is queued very
early in the qemuDomainRemove*Device() function for all of them,
resulting in a possibility of any application receiving the event
before libvirt has really finished with the device.
The solution is to save the device's alias (which is the only piece of
info from the device object that is needed for the event) at the
beginning of processing the device removal, and then queue the event
as a final act before returning. Since all of the
qemuDomainRemove*Device() functions (except
qemuDomainRemoveChrDevice()) are now called exclusively from
qemuDomainRemoveDevice() (which selects which of the subordinates to
call in a switch statement based on the type of device), the shortest
route to a solution is to doing the saving of alias, and later
queueing of the event, in the higher level qemuDomainRemoveDevice(),
and just completely remove the event-related code from all the
subordinate functions.
The single exception to this, as mentioned before, is
qemuDomainRemoveChrDevice(), which is still called from somewhere
other than qemuDomainRemoveDevice() (and has a separate arg used to
trigger different behavior when the chr device has targetType ==
GUESTFWD), so it must keep its original behavior intact, and must be
treated differently by qemuDomainRemoveDevice() (similar to the way
that qemuDomainDetachDeviceLive() treats chr and lease devices
differently from all the others).
Resolves: https://bugzilla.redhat.com/1658198
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 16:54:10 +00:00
|
|
|
|
|
|
|
event = virDomainEventDeviceRemovedNewFromObj(vm, alias);
|
|
|
|
virObjectEventStateQueue(driver->domainEventState, event);
|
|
|
|
|
|
|
|
return 0;
|
2013-07-11 15:11:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainMarkDeviceAliasForRemoval(virDomainObj *vm,
|
2016-08-04 21:53:13 +00:00
|
|
|
const char *alias)
|
2013-07-11 15:11:02 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2013-07-11 15:11:02 +00:00
|
|
|
|
2016-04-04 15:17:43 +00:00
|
|
|
memset(&priv->unplug, 0, sizeof(priv->unplug));
|
|
|
|
|
2016-08-04 21:53:13 +00:00
|
|
|
priv->unplug.alias = alias;
|
2013-07-11 15:11:02 +00:00
|
|
|
}
|
|
|
|
|
2016-08-04 21:53:13 +00:00
|
|
|
|
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainMarkDeviceForRemoval(virDomainObj *vm,
|
|
|
|
virDomainDeviceInfo *info)
|
2016-08-04 21:53:13 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
qemuDomainMarkDeviceAliasForRemoval(vm, info->alias);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-11 15:11:02 +00:00
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainResetDeviceRemoval(virDomainObj *vm)
|
2013-07-11 15:11:02 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2016-04-04 15:17:43 +00:00
|
|
|
priv->unplug.alias = NULL;
|
qemu_hotplug: Fix a rare race condition when detaching a device twice
https://bugzilla.redhat.com/show_bug.cgi?id=1623389
If a device is detached twice from the same domain the following
race condition may happen:
1) The first DetachDevice() call will issue "device_del" on qemu
monitor, but since the DEVICE_DELETED event did not arrive in
time, the API ends claiming "Device detach request sent
successfully".
2) The second DetachDevice() therefore still find the device in
the domain and thus proceeds to detaching it again. It calls
EnterMonitor() and qemuMonitorSend() trying to issue "device_del"
command again. This gets both domain lock and monitor lock
released.
3) At this point, qemu sends us the DEVICE_DELETED event which is
going to be handled by the event loop which ends up calling
qemuDomainSignalDeviceRemoval() to determine who is going to
remove the device from domain definition. Whether it is the
caller that marked the device for removal or whether it is going
to be the event processing thread.
4) Because the device was marked for removal,
qemuDomainSignalDeviceRemoval() returns true, which means the
event is to be processed by the thread that has marked the device
for removal (and is currently still trying to issue "device_del"
command)
5) The thread finally issues the "device_del" command, which
fails (obviously) and therefore it calls
qemuDomainResetDeviceRemoval() to reset the device marking and
quits immediately after, NOT removing any device from the domain
definition.
At this point, the device is still present in the domain
definition but doesn't exist in qemu anymore. Worse, there is no
way to remove it from the domain definition.
Solution is to note down that we've seen the event and if the
second "device_del" fails, not take it as a failure but carry on
with the usual execution.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-14 10:02:52 +00:00
|
|
|
priv->unplug.eventSeen = false;
|
2013-07-11 15:11:02 +00:00
|
|
|
}
|
|
|
|
|
2019-10-18 18:36:32 +00:00
|
|
|
|
2020-04-23 08:30:13 +00:00
|
|
|
unsigned long long G_GNUC_NO_INLINE
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainGetUnplugTimeout(virDomainObj *vm)
|
2019-10-18 18:36:32 +00:00
|
|
|
{
|
|
|
|
if (qemuDomainIsPSeries(vm->def))
|
|
|
|
return QEMU_UNPLUG_TIMEOUT_PPC64;
|
|
|
|
|
|
|
|
return QEMU_UNPLUG_TIMEOUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-11 15:11:02 +00:00
|
|
|
/* Returns:
|
2016-04-04 15:17:43 +00:00
|
|
|
* -1 Unplug of the device failed
|
|
|
|
*
|
2019-02-07 11:08:57 +00:00
|
|
|
* 0 removal of the device did not finish in qemuDomainRemoveDeviceWaitTime
|
2016-04-04 13:08:40 +00:00
|
|
|
*
|
|
|
|
* 1 when the caller is responsible for finishing the device removal:
|
|
|
|
* - DEVICE_DELETED event arrived before the timeout time
|
|
|
|
* - we failed to reliably wait for the event and thus use fallback behavior
|
2013-07-11 15:11:02 +00:00
|
|
|
*/
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainWaitForDeviceRemoval(virDomainObj *vm)
|
2013-07-11 15:11:02 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2013-07-11 15:11:02 +00:00
|
|
|
unsigned long long until;
|
2016-04-04 11:59:48 +00:00
|
|
|
int rc;
|
2013-07-11 15:11:02 +00:00
|
|
|
|
|
|
|
if (virTimeMillisNow(&until) < 0)
|
2016-04-04 13:08:40 +00:00
|
|
|
return 1;
|
2019-10-18 18:36:32 +00:00
|
|
|
until += qemuDomainGetUnplugTimeout(vm);
|
2013-07-11 15:11:02 +00:00
|
|
|
|
2016-04-04 15:17:43 +00:00
|
|
|
while (priv->unplug.alias) {
|
2016-04-04 11:59:48 +00:00
|
|
|
if ((rc = virDomainObjWaitUntil(vm, until)) == 1)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (rc < 0) {
|
|
|
|
VIR_WARN("Failed to wait on unplug condition for domain '%s' "
|
2016-04-04 15:17:43 +00:00
|
|
|
"device '%s'", vm->def->name, priv->unplug.alias);
|
2016-04-04 11:59:48 +00:00
|
|
|
return 1;
|
2013-07-11 15:11:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-04 15:17:43 +00:00
|
|
|
if (priv->unplug.status == QEMU_DOMAIN_UNPLUGGING_DEVICE_STATUS_GUEST_REJECTED) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
|
_("unplug of device was rejected by the guest"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-07-11 15:11:02 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-05-26 15:01:52 +00:00
|
|
|
/* Returns:
|
|
|
|
* true there was a thread waiting for devAlias to be removed and this
|
|
|
|
* thread will take care of finishing the removal
|
|
|
|
* false the thread that started the removal is already gone and delegate
|
|
|
|
* finishing the removal to a new thread
|
|
|
|
*/
|
|
|
|
bool
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainSignalDeviceRemoval(virDomainObj *vm,
|
2016-04-04 15:17:43 +00:00
|
|
|
const char *devAlias,
|
|
|
|
qemuDomainUnpluggingDeviceStatus status)
|
2013-07-11 15:11:02 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
2013-07-11 15:11:02 +00:00
|
|
|
|
2016-04-04 15:17:43 +00:00
|
|
|
if (STREQ_NULLABLE(priv->unplug.alias, devAlias)) {
|
2017-03-03 15:02:01 +00:00
|
|
|
VIR_DEBUG("Removal of device '%s' continues in waiting thread", devAlias);
|
2013-07-11 15:11:02 +00:00
|
|
|
qemuDomainResetDeviceRemoval(vm);
|
2016-04-04 15:17:43 +00:00
|
|
|
priv->unplug.status = status;
|
qemu_hotplug: Fix a rare race condition when detaching a device twice
https://bugzilla.redhat.com/show_bug.cgi?id=1623389
If a device is detached twice from the same domain the following
race condition may happen:
1) The first DetachDevice() call will issue "device_del" on qemu
monitor, but since the DEVICE_DELETED event did not arrive in
time, the API ends claiming "Device detach request sent
successfully".
2) The second DetachDevice() therefore still find the device in
the domain and thus proceeds to detaching it again. It calls
EnterMonitor() and qemuMonitorSend() trying to issue "device_del"
command again. This gets both domain lock and monitor lock
released.
3) At this point, qemu sends us the DEVICE_DELETED event which is
going to be handled by the event loop which ends up calling
qemuDomainSignalDeviceRemoval() to determine who is going to
remove the device from domain definition. Whether it is the
caller that marked the device for removal or whether it is going
to be the event processing thread.
4) Because the device was marked for removal,
qemuDomainSignalDeviceRemoval() returns true, which means the
event is to be processed by the thread that has marked the device
for removal (and is currently still trying to issue "device_del"
command)
5) The thread finally issues the "device_del" command, which
fails (obviously) and therefore it calls
qemuDomainResetDeviceRemoval() to reset the device marking and
quits immediately after, NOT removing any device from the domain
definition.
At this point, the device is still present in the domain
definition but doesn't exist in qemu anymore. Worse, there is no
way to remove it from the domain definition.
Solution is to note down that we've seen the event and if the
second "device_del" fails, not take it as a failure but carry on
with the usual execution.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-14 10:02:52 +00:00
|
|
|
priv->unplug.eventSeen = true;
|
2016-04-04 11:59:48 +00:00
|
|
|
virDomainObjBroadcast(vm);
|
2014-05-26 15:01:52 +00:00
|
|
|
return true;
|
2013-07-11 15:11:02 +00:00
|
|
|
}
|
2014-05-26 15:01:52 +00:00
|
|
|
return false;
|
2013-07-11 15:11:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-18 09:00:13 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuFindDisk(virDomainDef *def, const char *dst)
|
2013-07-18 09:00:13 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < def->ndisks; i++) {
|
2014-11-13 14:25:30 +00:00
|
|
|
if (STREQ(def->disks[i]->dst, dst))
|
2013-07-18 09:00:13 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-03-23 16:29:23 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachPrepDisk(virDomainObj *vm,
|
|
|
|
virDomainDiskDef *match,
|
|
|
|
virDomainDiskDef **detach)
|
2013-07-18 09:00:13 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainDiskDef *disk;
|
2013-07-18 09:00:13 +00:00
|
|
|
int idx;
|
|
|
|
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
if ((idx = qemuFindDisk(vm->def, match->dst)) < 0) {
|
2021-06-14 10:18:37 +00:00
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING,
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
_("disk %s not found"), match->dst);
|
2013-07-18 09:00:13 +00:00
|
|
|
return -1;
|
|
|
|
}
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
*detach = disk = vm->def->disks[idx];
|
2013-07-18 09:00:13 +00:00
|
|
|
|
2019-03-15 13:52:58 +00:00
|
|
|
switch ((virDomainDiskDevice) disk->device) {
|
2013-07-18 09:00:13 +00:00
|
|
|
case VIR_DOMAIN_DISK_DEVICE_DISK:
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_LUN:
|
2019-03-15 14:04:00 +00:00
|
|
|
|
|
|
|
switch ((virDomainDiskBus) disk->bus) {
|
|
|
|
case VIR_DOMAIN_DISK_BUS_VIRTIO:
|
|
|
|
case VIR_DOMAIN_DISK_BUS_USB:
|
|
|
|
case VIR_DOMAIN_DISK_BUS_SCSI:
|
2019-03-18 22:14:11 +00:00
|
|
|
break;
|
2019-03-15 14:04:00 +00:00
|
|
|
|
|
|
|
case VIR_DOMAIN_DISK_BUS_IDE:
|
|
|
|
case VIR_DOMAIN_DISK_BUS_FDC:
|
|
|
|
case VIR_DOMAIN_DISK_BUS_XEN:
|
|
|
|
case VIR_DOMAIN_DISK_BUS_UML:
|
|
|
|
case VIR_DOMAIN_DISK_BUS_SATA:
|
|
|
|
case VIR_DOMAIN_DISK_BUS_SD:
|
2013-07-18 09:00:13 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("This type of disk cannot be hot unplugged"));
|
2019-03-18 22:14:11 +00:00
|
|
|
return -1;
|
2019-03-15 14:04:00 +00:00
|
|
|
|
2021-04-15 14:58:19 +00:00
|
|
|
case VIR_DOMAIN_DISK_BUS_NONE:
|
2019-03-15 14:04:00 +00:00
|
|
|
case VIR_DOMAIN_DISK_BUS_LAST:
|
|
|
|
default:
|
|
|
|
virReportEnumRangeError(virDomainDiskBus, disk->bus);
|
2019-03-18 22:14:11 +00:00
|
|
|
return -1;
|
2019-03-15 14:04:00 +00:00
|
|
|
}
|
2013-07-18 09:00:13 +00:00
|
|
|
break;
|
2019-03-15 13:52:58 +00:00
|
|
|
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_CDROM:
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
|
2013-07-18 09:00:13 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("disk device type '%s' cannot be detached"),
|
|
|
|
virDomainDiskDeviceTypeToString(disk->device));
|
2019-03-18 22:14:11 +00:00
|
|
|
return -1;
|
2019-03-15 13:52:58 +00:00
|
|
|
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_LAST:
|
|
|
|
default:
|
|
|
|
virReportEnumRangeError(virDomainDiskDevice, disk->device);
|
2019-03-18 22:14:11 +00:00
|
|
|
return -1;
|
2013-07-18 09:00:13 +00:00
|
|
|
}
|
|
|
|
|
2019-03-18 22:14:11 +00:00
|
|
|
if (qemuDomainDiskBlockJobIsActive(disk))
|
|
|
|
return -1;
|
|
|
|
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
return 0;
|
2013-07-18 09:00:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-13 12:53:57 +00:00
|
|
|
static bool
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDiskControllerIsBusy(virDomainObj *vm,
|
|
|
|
virDomainControllerDef *detach)
|
2011-02-21 07:35:52 +00:00
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/qemu files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainDiskDef *disk;
|
|
|
|
virDomainHostdevDef *hostdev;
|
2011-02-21 07:35:52 +00:00
|
|
|
|
|
|
|
for (i = 0; i < vm->def->ndisks; i++) {
|
|
|
|
disk = vm->def->disks[i];
|
|
|
|
if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE)
|
|
|
|
/* the disk does not use disk controller */
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* check whether the disk uses this type controller */
|
2020-11-13 13:07:40 +00:00
|
|
|
switch ((virDomainControllerType) detach->type) {
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
|
|
|
|
if (disk->bus != VIR_DOMAIN_DISK_BUS_IDE)
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_FDC:
|
|
|
|
if (disk->bus != VIR_DOMAIN_DISK_BUS_FDC)
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
|
|
|
|
if (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI)
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
|
|
|
|
if (disk->bus != VIR_DOMAIN_DISK_BUS_SATA)
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_XENBUS:
|
|
|
|
/* xenbus is not supported by the qemu driver */
|
2011-02-21 07:35:52 +00:00
|
|
|
continue;
|
2020-11-13 13:07:40 +00:00
|
|
|
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL:
|
|
|
|
/* virtio-serial does not host any disks */
|
2011-02-21 07:35:52 +00:00
|
|
|
continue;
|
2020-11-13 13:07:40 +00:00
|
|
|
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_CCID:
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_USB:
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_ISA:
|
|
|
|
/* These buses have (also) other device types too so they need to
|
|
|
|
* be checked elsewhere */
|
2011-02-21 07:35:52 +00:00
|
|
|
continue;
|
|
|
|
|
2020-11-13 13:07:40 +00:00
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_LAST:
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-02-21 07:35:52 +00:00
|
|
|
if (disk->info.addr.drive.controller == detach->idx)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-11-13 13:15:19 +00:00
|
|
|
if (detach->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
|
|
|
|
for (i = 0; i < vm->def->nhostdevs; i++) {
|
|
|
|
hostdev = vm->def->hostdevs[i];
|
|
|
|
if (!virHostdevIsSCSIDevice(hostdev))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (hostdev->info->addr.drive.controller == detach->idx)
|
|
|
|
return true;
|
|
|
|
}
|
qemu: Prevent detaching SCSI controller used by hostdev
Consider the following XML snippets:
$ cat scsicontroller.xml
<controller type='scsi' model='virtio-scsi' index='0'/>
$ cat scsihostdev.xml
<hostdev mode='subsystem' type='scsi'>
<source>
<adapter name='scsi_host0'/>
<address bus='0' target='8' unit='1074151456'/>
</source>
</hostdev>
If we create a guest that includes the contents of scsihostdev.xml,
but forget the virtio-scsi controller described in scsicontroller.xml,
one is silently created for us. The same holds true when attaching
a hostdev before the matching virtio-scsi controller.
(See qemuDomainFindOrCreateSCSIDiskController for context.)
Detaching the hostdev, followed by the controller, works well and the
guest behaves appropriately.
If we detach the virtio-scsi controller device first, any associated
hostdevs are detached for us by the underlying virtio-scsi code (this
is fine, since the connection is broken). But all is not well, as the
guest is unable to receive new virtio-scsi devices (the attach commands
succeed, but devices never appear within the guest), nor even be
shutdown, after this point.
While this is not libvirt's problem, we can prevent falling into this
scenario by checking if a controller is being used by any hostdev
devices. The same is already done for disk elements today.
Applying this patch and then using the XML snippets from earlier:
$ virsh detach-device guest_01 scsicontroller.xml
error: Failed to detach device from scsicontroller.xml
error: operation failed: device cannot be detached: device is busy
$ virsh detach-device guest_01 scsihostdev.xml
Device detached successfully
$ virsh detach-device guest_01 scsicontroller.xml
Device detached successfully
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com>
Reviewed-by: Bjoern Walk <bwalk@linux.vnet.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy@linux.vnet.ibm.com>
2016-11-29 21:40:16 +00:00
|
|
|
}
|
|
|
|
|
2011-02-21 07:35:52 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-11-13 12:53:57 +00:00
|
|
|
|
|
|
|
static bool
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainControllerIsBusy(virDomainObj *vm,
|
|
|
|
virDomainControllerDef *detach)
|
2011-02-21 07:35:52 +00:00
|
|
|
{
|
2020-11-13 13:16:45 +00:00
|
|
|
switch ((virDomainControllerType) detach->type) {
|
2011-02-21 07:35:52 +00:00
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_FDC:
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
|
2020-11-13 13:16:45 +00:00
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
|
2011-02-21 07:35:52 +00:00
|
|
|
return qemuDomainDiskControllerIsBusy(vm, detach);
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL:
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_CCID:
|
2020-11-13 13:16:45 +00:00
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_USB:
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_ISA:
|
|
|
|
/* detach of the controller types above is not yet supported */
|
|
|
|
return false;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_XENBUS:
|
|
|
|
/* qemu driver doesn't support xenbus */
|
|
|
|
return false;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CONTROLLER_TYPE_LAST:
|
2011-02-21 07:35:52 +00:00
|
|
|
default:
|
2020-11-13 13:16:45 +00:00
|
|
|
return false;
|
2011-02-21 07:35:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-13 12:53:57 +00:00
|
|
|
|
2019-03-23 16:29:23 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachPrepController(virDomainObj *vm,
|
|
|
|
virDomainControllerDef *match,
|
|
|
|
virDomainControllerDef **detach)
|
2010-12-16 16:10:54 +00:00
|
|
|
{
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
int idx;
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainControllerDef *controller = NULL;
|
2010-12-16 16:10:54 +00:00
|
|
|
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
if (match->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
|
2019-03-19 21:37:55 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("'%s' controller cannot be hot unplugged."),
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
virDomainControllerTypeToString(match->type));
|
2019-03-19 21:37:55 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
if ((idx = virDomainControllerFind(vm->def, match->type, match->idx)) < 0) {
|
2018-01-23 04:24:44 +00:00
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING,
|
2013-05-09 09:39:21 +00:00
|
|
|
_("controller %s:%d not found"),
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
virDomainControllerTypeToString(match->type),
|
|
|
|
match->idx);
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
return -1;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
*detach = controller = vm->def->controllers[idx];
|
2012-07-23 08:18:57 +00:00
|
|
|
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
if (qemuDomainControllerIsBusy(vm, controller)) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
|
_("device cannot be detached: device is busy"));
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
return -1;
|
2018-05-23 16:01:16 +00:00
|
|
|
}
|
2010-12-16 16:10:54 +00:00
|
|
|
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
return 0;
|
2010-12-16 16:10:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-27 11:53:19 +00:00
|
|
|
/* search for a hostdev matching dev and detach it */
|
2019-03-23 16:29:23 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachPrepHostdev(virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *match,
|
|
|
|
virDomainHostdevDef **detach)
|
2012-02-27 11:53:19 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainHostdevSubsys *subsys = &match->source.subsys;
|
|
|
|
virDomainHostdevSubsysUSB *usbsrc = &subsys->u.usb;
|
|
|
|
virDomainHostdevSubsysPCI *pcisrc = &subsys->u.pci;
|
|
|
|
virDomainHostdevSubsysSCSI *scsisrc = &subsys->u.scsi;
|
|
|
|
virDomainHostdevSubsysMediatedDev *mdevsrc = &subsys->u.mdev;
|
|
|
|
virDomainHostdevDef *hostdev = NULL;
|
2012-02-27 11:53:19 +00:00
|
|
|
int idx;
|
|
|
|
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
if (match->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2017-05-11 13:26:47 +00:00
|
|
|
_("hot unplug is not supported for hostdev mode '%s'"),
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
virDomainHostdevModeTypeToString(match->mode));
|
2012-02-27 11:53:19 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
idx = virDomainHostdevFind(vm->def, match, &hostdev);
|
|
|
|
*detach = hostdev;
|
2012-02-27 11:53:19 +00:00
|
|
|
|
|
|
|
if (idx < 0) {
|
2012-10-17 09:23:12 +00:00
|
|
|
switch (subsys->type) {
|
2012-02-27 11:53:19 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
|
2018-01-23 04:24:44 +00:00
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING,
|
2019-07-30 12:43:44 +00:00
|
|
|
_("host pci device " VIR_PCI_DEVICE_ADDRESS_FMT
|
|
|
|
" not found"),
|
2014-07-03 20:31:39 +00:00
|
|
|
pcisrc->addr.domain, pcisrc->addr.bus,
|
|
|
|
pcisrc->addr.slot, pcisrc->addr.function);
|
2012-02-27 11:53:19 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
|
2014-07-03 19:43:05 +00:00
|
|
|
if (usbsrc->bus && usbsrc->device) {
|
2018-01-23 04:24:44 +00:00
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING,
|
2012-07-18 15:22:03 +00:00
|
|
|
_("host usb device %03d.%03d not found"),
|
2014-07-03 19:43:05 +00:00
|
|
|
usbsrc->bus, usbsrc->device);
|
2012-02-27 11:53:19 +00:00
|
|
|
} else {
|
2018-01-23 04:24:44 +00:00
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING,
|
2012-07-18 15:22:03 +00:00
|
|
|
_("host usb device vendor=0x%.4x product=0x%.4x not found"),
|
2014-07-03 19:43:05 +00:00
|
|
|
usbsrc->vendor, usbsrc->product);
|
2012-02-27 11:53:19 +00:00
|
|
|
}
|
|
|
|
break;
|
2014-06-20 15:35:46 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
|
2014-07-09 13:31:38 +00:00
|
|
|
if (scsisrc->protocol ==
|
|
|
|
VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainHostdevSubsysSCSIiSCSI *iscsisrc = &scsisrc->u.iscsi;
|
2018-01-23 04:24:44 +00:00
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING,
|
2014-07-09 13:31:38 +00:00
|
|
|
_("host scsi iSCSI path %s not found"),
|
2017-09-22 19:18:22 +00:00
|
|
|
iscsisrc->src->path);
|
2014-07-09 13:31:38 +00:00
|
|
|
} else {
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainHostdevSubsysSCSIHost *scsihostsrc =
|
2014-07-09 13:31:38 +00:00
|
|
|
&scsisrc->u.host;
|
2018-01-23 04:24:44 +00:00
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING,
|
2015-06-17 03:29:53 +00:00
|
|
|
_("host scsi device %s:%u:%u.%llu not found"),
|
2014-07-09 13:31:38 +00:00
|
|
|
scsihostsrc->adapter, scsihostsrc->bus,
|
|
|
|
scsihostsrc->target, scsihostsrc->unit);
|
|
|
|
}
|
2013-05-03 18:07:31 +00:00
|
|
|
break;
|
2014-06-20 15:35:46 +00:00
|
|
|
}
|
2018-03-26 08:06:07 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
|
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING,
|
|
|
|
_("mediated device '%s' not found"),
|
|
|
|
mdevsrc->uuidstr);
|
|
|
|
break;
|
2016-11-22 03:58:19 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
|
|
|
|
break;
|
2012-02-27 11:53:19 +00:00
|
|
|
default:
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected hostdev type %d"), subsys->type);
|
2012-02-27 11:53:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
return 0;
|
2012-02-27 11:53:19 +00:00
|
|
|
}
|
|
|
|
|
2016-09-12 13:40:48 +00:00
|
|
|
|
2019-03-23 16:29:23 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachPrepShmem(virDomainObj *vm,
|
|
|
|
virDomainShmemDef *match,
|
|
|
|
virDomainShmemDef **detach)
|
2016-09-12 13:40:48 +00:00
|
|
|
{
|
|
|
|
ssize_t idx = -1;
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainShmemDef *shmem = NULL;
|
2016-09-12 13:40:48 +00:00
|
|
|
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
if ((idx = virDomainShmemDefFind(vm->def, match)) < 0) {
|
2018-01-23 04:24:44 +00:00
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING,
|
2018-01-23 04:24:42 +00:00
|
|
|
_("model '%s' shmem device not present "
|
|
|
|
"in domain configuration"),
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
virDomainShmemModelTypeToString(match->model));
|
2016-09-12 13:40:48 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
*detach = shmem = vm->def->shmems[idx];
|
2016-09-12 13:40:48 +00:00
|
|
|
|
2021-04-27 15:04:36 +00:00
|
|
|
switch (shmem->model) {
|
2016-09-12 13:40:48 +00:00
|
|
|
case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_PLAIN:
|
|
|
|
case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_DOORBELL:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM:
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("live detach of shmem model '%s' is not supported"),
|
|
|
|
virDomainShmemModelTypeToString(shmem->model));
|
2019-10-15 11:38:21 +00:00
|
|
|
G_GNUC_FALLTHROUGH;
|
2016-09-12 13:40:48 +00:00
|
|
|
case VIR_DOMAIN_SHMEM_MODEL_LAST:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
return 0;
|
2016-09-12 13:40:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-23 16:29:23 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachPrepWatchdog(virDomainObj *vm,
|
|
|
|
virDomainWatchdogDef *match,
|
|
|
|
virDomainWatchdogDef **detach)
|
2017-09-05 09:08:36 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainWatchdogDef *watchdog;
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
|
|
|
|
*detach = watchdog = vm->def->watchdog;
|
2017-09-05 09:08:36 +00:00
|
|
|
|
2018-02-09 13:52:10 +00:00
|
|
|
if (!watchdog) {
|
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING, "%s",
|
|
|
|
_("watchdog device not present in domain configuration"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-09-05 09:08:36 +00:00
|
|
|
/* While domains can have up to one watchdog, the one supplied by the user
|
|
|
|
* doesn't necessarily match the one domain has. Refuse to detach in such
|
|
|
|
* case. */
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
if (!(watchdog->model == match->model &&
|
|
|
|
watchdog->action == match->action &&
|
|
|
|
virDomainDeviceInfoAddressIsEqual(&match->info, &watchdog->info))) {
|
2018-01-23 04:24:44 +00:00
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING,
|
2018-01-23 04:24:42 +00:00
|
|
|
_("model '%s' watchdog device not present "
|
|
|
|
"in domain configuration"),
|
|
|
|
virDomainWatchdogModelTypeToString(watchdog->model));
|
2017-09-05 09:08:36 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (watchdog->model != VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("hot unplug of watchdog of model %s is not supported"),
|
|
|
|
virDomainWatchdogModelTypeToString(watchdog->model));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
return 0;
|
2017-09-05 09:08:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-23 16:29:23 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachPrepRedirdev(virDomainObj *vm,
|
|
|
|
virDomainRedirdevDef *match,
|
|
|
|
virDomainRedirdevDef **detach)
|
2018-01-05 02:47:47 +00:00
|
|
|
{
|
|
|
|
ssize_t idx;
|
|
|
|
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
if ((idx = virDomainRedirdevDefFind(vm->def, match)) < 0) {
|
2018-01-05 02:47:47 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("no matching redirdev was not found"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-10-13 21:14:46 +00:00
|
|
|
*detach = vm->def->redirdevs[idx];
|
2018-01-05 02:47:47 +00:00
|
|
|
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
return 0;
|
2018-01-05 02:47:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-23 16:29:23 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachPrepNet(virDomainObj *vm,
|
|
|
|
virDomainNetDef *match,
|
|
|
|
virDomainNetDef **detach)
|
2012-02-27 12:03:12 +00:00
|
|
|
{
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
int detachidx;
|
2012-02-27 12:03:12 +00:00
|
|
|
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
if ((detachidx = virDomainNetFindIdx(vm->def, match)) < 0)
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
return -1;
|
2014-04-01 13:56:55 +00:00
|
|
|
|
2020-10-13 21:14:46 +00:00
|
|
|
*detach = vm->def->nets[detachidx];
|
2012-02-27 12:03:12 +00:00
|
|
|
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2012-02-27 12:03:12 +00:00
|
|
|
|
2014-10-08 22:55:43 +00:00
|
|
|
|
2019-03-23 16:29:23 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachDeviceChr(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainChrDef *chr,
|
2019-03-23 16:29:23 +00:00
|
|
|
bool async)
|
2013-03-13 10:08:55 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
|
|
|
virDomainDef *vmdef = vm->def;
|
|
|
|
virDomainChrDef *tmpChr;
|
2019-02-11 13:16:58 +00:00
|
|
|
bool guestfwd = false;
|
2013-03-13 10:08:55 +00:00
|
|
|
|
|
|
|
if (!(tmpChr = virDomainChrFind(vmdef, chr))) {
|
2018-01-23 04:24:44 +00:00
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING,
|
2018-01-23 04:24:42 +00:00
|
|
|
_("chr type '%s' device not present "
|
|
|
|
"in domain configuration"),
|
|
|
|
virDomainChrDeviceTypeToString(chr->deviceType));
|
2016-06-13 16:30:34 +00:00
|
|
|
goto cleanup;
|
2013-03-13 10:08:55 +00:00
|
|
|
}
|
|
|
|
|
2019-02-11 13:16:58 +00:00
|
|
|
/* guestfwd channels are not really -device rather than
|
|
|
|
* -netdev. We need to treat them slightly differently. */
|
|
|
|
guestfwd = tmpChr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
|
|
|
|
tmpChr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD;
|
|
|
|
|
|
|
|
if (!async && !guestfwd)
|
2018-05-23 16:01:16 +00:00
|
|
|
qemuDomainMarkDeviceForRemoval(vm, &tmpChr->info);
|
2013-07-11 15:11:02 +00:00
|
|
|
|
2019-02-11 13:16:58 +00:00
|
|
|
if (guestfwd) {
|
2019-03-12 12:49:24 +00:00
|
|
|
int rc;
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
rc = qemuMonitorRemoveNetdev(priv->mon, tmpChr->info.alias);
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
rc = -1;
|
|
|
|
|
|
|
|
if (rc < 0)
|
2019-02-11 13:16:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
} else {
|
2019-03-12 12:49:24 +00:00
|
|
|
if (qemuDomainDeleteDevice(vm, tmpChr->info.alias) < 0)
|
2019-02-11 13:16:58 +00:00
|
|
|
goto cleanup;
|
2016-10-24 19:47:56 +00:00
|
|
|
}
|
2013-03-13 10:08:55 +00:00
|
|
|
|
2019-02-11 13:16:58 +00:00
|
|
|
if (guestfwd) {
|
|
|
|
ret = qemuDomainRemoveChrDevice(driver, vm, tmpChr, false);
|
|
|
|
} else if (async) {
|
2018-05-23 16:01:16 +00:00
|
|
|
ret = 0;
|
|
|
|
} else {
|
|
|
|
if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
|
2019-02-11 13:16:58 +00:00
|
|
|
ret = qemuDomainRemoveChrDevice(driver, vm, tmpChr, true);
|
2018-05-23 16:01:16 +00:00
|
|
|
}
|
2015-03-02 09:59:52 +00:00
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
cleanup:
|
2018-05-23 16:01:16 +00:00
|
|
|
if (!async)
|
|
|
|
qemuDomainResetDeviceRemoval(vm);
|
2013-03-13 10:08:55 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2015-01-17 05:09:38 +00:00
|
|
|
|
|
|
|
|
2019-03-23 16:29:23 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachPrepRNG(virDomainObj *vm,
|
|
|
|
virDomainRNGDef *match,
|
|
|
|
virDomainRNGDef **detach)
|
2015-01-17 05:09:38 +00:00
|
|
|
{
|
|
|
|
ssize_t idx;
|
|
|
|
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
if ((idx = virDomainRNGFind(vm->def, match)) < 0) {
|
2018-01-23 04:24:44 +00:00
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING,
|
2018-01-23 04:24:42 +00:00
|
|
|
_("model '%s' RNG device not present "
|
|
|
|
"in domain configuration"),
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
virDomainRNGBackendTypeToString(match->model));
|
2015-01-17 05:09:38 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-10-13 21:14:46 +00:00
|
|
|
*detach = vm->def->rngs[idx];
|
2015-01-17 05:09:38 +00:00
|
|
|
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
return 0;
|
2015-01-17 05:09:38 +00:00
|
|
|
}
|
2015-01-21 16:45:54 +00:00
|
|
|
|
|
|
|
|
2019-03-23 16:29:23 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachPrepMemory(virDomainObj *vm,
|
|
|
|
virDomainMemoryDef *match,
|
|
|
|
virDomainMemoryDef **detach)
|
2015-01-21 16:45:54 +00:00
|
|
|
{
|
|
|
|
int idx;
|
|
|
|
|
2020-09-15 02:42:56 +00:00
|
|
|
if (qemuDomainMemoryDeviceAlignSize(vm->def, match) < 0)
|
|
|
|
return -1;
|
2015-01-21 16:45:54 +00:00
|
|
|
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
if ((idx = virDomainMemoryFindByDef(vm->def, match)) < 0) {
|
2018-01-23 04:24:44 +00:00
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING,
|
2018-01-23 04:24:42 +00:00
|
|
|
_("model '%s' memory device not present "
|
|
|
|
"in the domain configuration"),
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
virDomainMemoryModelTypeToString(match->model));
|
2015-01-21 16:45:54 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-10-13 21:14:46 +00:00
|
|
|
*detach = vm->def->mems[idx];
|
2015-01-21 16:45:54 +00:00
|
|
|
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
return 0;
|
2015-01-21 16:45:54 +00:00
|
|
|
}
|
2016-08-16 13:02:11 +00:00
|
|
|
|
|
|
|
|
2019-03-23 16:29:23 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachPrepInput(virDomainObj *vm,
|
|
|
|
virDomainInputDef *match,
|
|
|
|
virDomainInputDef **detach)
|
2019-03-19 17:39:07 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainInputDef *input;
|
2019-03-19 17:39:07 +00:00
|
|
|
int idx;
|
|
|
|
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
if ((idx = virDomainInputDefFind(vm->def, match)) < 0) {
|
2021-06-14 10:18:37 +00:00
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING, "%s",
|
2019-03-19 17:39:07 +00:00
|
|
|
_("matching input device not found"));
|
|
|
|
return -1;
|
|
|
|
}
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
*detach = input = vm->def->inputs[idx];
|
2019-03-19 17:39:07 +00:00
|
|
|
|
|
|
|
switch ((virDomainInputBus) input->bus) {
|
|
|
|
case VIR_DOMAIN_INPUT_BUS_PS2:
|
|
|
|
case VIR_DOMAIN_INPUT_BUS_XEN:
|
|
|
|
case VIR_DOMAIN_INPUT_BUS_PARALLELS:
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("input device on bus '%s' cannot be detached"),
|
|
|
|
virDomainInputBusTypeToString(input->bus));
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_INPUT_BUS_LAST:
|
|
|
|
case VIR_DOMAIN_INPUT_BUS_USB:
|
|
|
|
case VIR_DOMAIN_INPUT_BUS_VIRTIO:
|
2021-05-21 11:01:07 +00:00
|
|
|
case VIR_DOMAIN_INPUT_BUS_NONE:
|
2019-03-19 17:39:07 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
return 0;
|
2019-03-19 17:39:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-23 16:29:23 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachPrepVsock(virDomainObj *vm,
|
|
|
|
virDomainVsockDef *match,
|
|
|
|
virDomainVsockDef **detach)
|
2019-03-19 17:39:07 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainVsockDef *vsock;
|
2019-03-19 17:39:07 +00:00
|
|
|
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
*detach = vsock = vm->def->vsock;
|
2019-03-19 17:39:07 +00:00
|
|
|
if (!vsock ||
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
!virDomainVsockDefEquals(match, vsock)) {
|
2021-06-14 10:18:37 +00:00
|
|
|
virReportError(VIR_ERR_DEVICE_MISSING, "%s",
|
2019-03-19 17:39:07 +00:00
|
|
|
_("matching vsock device not found"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
return 0;
|
2019-03-19 17:39:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-23 16:29:23 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachDeviceLease(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainLeaseDef *lease)
|
2019-03-19 17:42:55 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainLeaseDef *det_lease;
|
2019-03-19 17:42:55 +00:00
|
|
|
int idx;
|
|
|
|
|
|
|
|
if ((idx = virDomainLeaseIndex(vm->def, lease)) < 0) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("Lease %s in lockspace %s does not exist"),
|
|
|
|
lease->key, NULLSTR(lease->lockspace));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainLockLeaseDetach(driver->lockManager, vm, lease) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
det_lease = virDomainLeaseRemoveAt(vm->def, idx);
|
|
|
|
virDomainLeaseDefFree(det_lease);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-19 17:55:13 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainDetachDeviceLive(virDomainObj *vm,
|
|
|
|
virDomainDeviceDef *match,
|
|
|
|
virQEMUDriver *driver,
|
2019-03-19 17:55:13 +00:00
|
|
|
bool async)
|
|
|
|
{
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
virDomainDeviceDef detach = { .type = match->type };
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainDeviceInfo *info = NULL;
|
2019-03-19 17:55:13 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
2019-03-19 21:15:00 +00:00
|
|
|
switch ((virDomainDeviceType)match->type) {
|
2019-03-25 00:59:21 +00:00
|
|
|
/*
|
|
|
|
* lease and chr devices don't follow the standard pattern of
|
|
|
|
* the others, so they must have their own self-contained
|
|
|
|
* Detach functions.
|
|
|
|
*/
|
|
|
|
case VIR_DOMAIN_DEVICE_LEASE:
|
2019-03-25 01:29:49 +00:00
|
|
|
return qemuDomainDetachDeviceLease(driver, vm, match->data.lease);
|
2019-03-25 00:59:21 +00:00
|
|
|
|
|
|
|
case VIR_DOMAIN_DEVICE_CHR:
|
2019-03-25 01:29:49 +00:00
|
|
|
return qemuDomainDetachDeviceChr(driver, vm, match->data.chr, async);
|
2019-03-25 00:59:21 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* All the other device types follow a very similar pattern -
|
|
|
|
* First we call type-specific functions to 1) locate the
|
|
|
|
* device we want to detach (based on the prototype device in
|
|
|
|
* match) and 2) do any device-type-specific validation to
|
|
|
|
* assure it is okay to detach the device.
|
|
|
|
*/
|
2019-03-19 17:55:13 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
if (qemuDomainDetachPrepDisk(vm, match->data.disk,
|
|
|
|
&detach.data.disk) < 0) {
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-03-19 17:55:13 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_CONTROLLER:
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
if (qemuDomainDetachPrepController(vm, match->data.controller,
|
|
|
|
&detach.data.controller) < 0) {
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-03-19 17:55:13 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_NET:
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
if (qemuDomainDetachPrepNet(vm, match->data.net,
|
|
|
|
&detach.data.net) < 0) {
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-03-19 17:55:13 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_HOSTDEV:
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
if (qemuDomainDetachPrepHostdev(vm, match->data.hostdev,
|
|
|
|
&detach.data.hostdev) < 0) {
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-03-19 17:55:13 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_RNG:
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
if (qemuDomainDetachPrepRNG(vm, match->data.rng,
|
|
|
|
&detach.data.rng) < 0) {
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-03-19 17:55:13 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_MEMORY:
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
if (qemuDomainDetachPrepMemory(vm, match->data.memory,
|
|
|
|
&detach.data.memory) < 0) {
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-03-19 17:55:13 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_SHMEM:
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
if (qemuDomainDetachPrepShmem(vm, match->data.shmem,
|
|
|
|
&detach.data.shmem) < 0) {
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-03-19 17:55:13 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_WATCHDOG:
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
if (qemuDomainDetachPrepWatchdog(vm, match->data.watchdog,
|
|
|
|
&detach.data.watchdog) < 0) {
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-03-19 17:55:13 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_INPUT:
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
if (qemuDomainDetachPrepInput(vm, match->data.input,
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
&detach.data.input) < 0) {
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-03-19 17:55:13 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_REDIRDEV:
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
if (qemuDomainDetachPrepRedirdev(vm, match->data.redirdev,
|
|
|
|
&detach.data.redirdev) < 0) {
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-03-19 17:55:13 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_VSOCK:
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
if (qemuDomainDetachPrepVsock(vm, match->data.vsock,
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
&detach.data.vsock) < 0) {
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-03-19 17:55:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_DEVICE_FS:
|
|
|
|
case VIR_DOMAIN_DEVICE_SOUND:
|
|
|
|
case VIR_DOMAIN_DEVICE_VIDEO:
|
|
|
|
case VIR_DOMAIN_DEVICE_GRAPHICS:
|
|
|
|
case VIR_DOMAIN_DEVICE_HUB:
|
|
|
|
case VIR_DOMAIN_DEVICE_SMARTCARD:
|
|
|
|
case VIR_DOMAIN_DEVICE_MEMBALLOON:
|
|
|
|
case VIR_DOMAIN_DEVICE_NVRAM:
|
|
|
|
case VIR_DOMAIN_DEVICE_NONE:
|
|
|
|
case VIR_DOMAIN_DEVICE_TPM:
|
|
|
|
case VIR_DOMAIN_DEVICE_PANIC:
|
|
|
|
case VIR_DOMAIN_DEVICE_IOMMU:
|
2020-07-18 06:23:57 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_AUDIO:
|
2019-03-19 17:55:13 +00:00
|
|
|
case VIR_DOMAIN_DEVICE_LAST:
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("live detach of device '%s' is not supported"),
|
2019-03-19 21:15:00 +00:00
|
|
|
virDomainDeviceTypeToString(match->type));
|
2019-03-25 00:59:21 +00:00
|
|
|
return -1;
|
2019-03-19 17:55:13 +00:00
|
|
|
}
|
|
|
|
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
/* "detach" now points to the actual device we want to detach */
|
|
|
|
|
|
|
|
if (!(info = virDomainDeviceGetInfo(&detach))) {
|
|
|
|
/*
|
|
|
|
* This should never happen, since all of the device types in
|
|
|
|
* the switch cases that end with a "break" instead of a
|
|
|
|
* return have a virDeviceInfo in them.
|
|
|
|
*/
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("device of type '%s' has no device info"),
|
|
|
|
virDomainDeviceTypeToString(detach.type));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Make generic validation checks common to all device types */
|
|
|
|
|
|
|
|
if (!info->alias) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Cannot detach %s device with no alias"),
|
|
|
|
virDomainDeviceTypeToString(detach.type));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qemuIsMultiFunctionDevice(vm->def, info)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("cannot hot unplug %s device with multifunction PCI guest address: "
|
2019-07-30 12:43:44 +00:00
|
|
|
VIR_PCI_DEVICE_ADDRESS_FMT),
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
virDomainDeviceTypeToString(detach.type),
|
|
|
|
info->addr.pci.domain, info->addr.pci.bus,
|
|
|
|
info->addr.pci.slot, info->addr.pci.function);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-05-14 18:01:47 +00:00
|
|
|
if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainControllerDef *controller;
|
2020-05-14 18:01:47 +00:00
|
|
|
int controllerIdx = virDomainControllerFind(vm->def,
|
|
|
|
VIR_DOMAIN_CONTROLLER_TYPE_PCI,
|
|
|
|
info->addr.pci.bus);
|
|
|
|
if (controllerIdx < 0) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("cannot hot unplug %s device with PCI guest address: "
|
|
|
|
VIR_PCI_DEVICE_ADDRESS_FMT
|
|
|
|
" - controller not found"),
|
|
|
|
virDomainDeviceTypeToString(detach.type),
|
|
|
|
info->addr.pci.domain, info->addr.pci.bus,
|
|
|
|
info->addr.pci.slot, info->addr.pci.function);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
controller = vm->def->controllers[controllerIdx];
|
|
|
|
if (controller->opts.pciopts.hotplug == VIR_TRISTATE_SWITCH_OFF) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("cannot hot unplug %s device with PCI guest address: "
|
|
|
|
VIR_PCI_DEVICE_ADDRESS_FMT
|
|
|
|
" - not allowed by controller"),
|
|
|
|
virDomainDeviceTypeToString(detach.type),
|
|
|
|
info->addr.pci.domain, info->addr.pci.bus,
|
|
|
|
info->addr.pci.slot, info->addr.pci.function);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
qemu_hotplug: consolidate all common detach code in qemuDomainDetachDeviceLive
Now that all the qemuDomainDetachPrep*() functions look nearly
identical at the end, we can put one copy of that identical code in
qemuDomainDetachDeviceLive() at the point after the individual prep
functions have been called, and remove the duplicated code from all
the prep functions. The code to locate the target "detach" device
based on the "match" device remains, as do all device-type-specific
validations.
Unfortunately there are a few things going on at once in this patch,
which makes it a bit more difficult to follow than the others; it was
just impossible to do the changes in stages and still have a
buildable/testable tree at each step.
The other changes of note:
* The individual prep functions no longer need their driver or async
args, so those are removed, as are the local "ret" variables, since
in all cases the functions just directly return -1 or 0.
* Some of the prep functions were checking for a valid alias and/or
for attempts to detach a multifunction PCI device, but not all. In
fact, both checks are valid (or at least harmless) for *all* device
types, so they are removed from the prep functions, and done a
single time in the common function.
(any attempts to *create* an alias when there isn't one has been
removed, since that is doomed to failure anyway; the only way the
device wouldn't have an alias is if 1) the domain was created by
calling virsh qemu-attach to attach an existing qemu process to
libvirt, and 2) the qemu command that started said process used "old
style" arguments for creating devices that didn't have any device
ids. Even if we constructed a device id for one of these devices,
qemu wouldn't recognize it in the device_del command anyway, so we
may as well fail earlier with "device missing alias" rather than
failing later with "couldn't delete device net0".)
* Only one type of device has shutdown code that must not be called
until after *all* validation of the device is done (including
checking for multifunction PCI and valid alias, which is done in the
toplevel common code). For this reason, the Net function has been
split in two, with the 2nd half (qemuDomainDetachShutdownNet())
called from the common function, right before sending the delete
command to qemu.
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-21 01:44:00 +00:00
|
|
|
/*
|
|
|
|
* Issue the qemu monitor command to delete the device (based on
|
|
|
|
* its alias), and optionally wait a short time in case the
|
|
|
|
* DEVICE_DELETED event arrives from qemu right away.
|
|
|
|
*/
|
|
|
|
if (!async)
|
|
|
|
qemuDomainMarkDeviceForRemoval(vm, info);
|
|
|
|
|
|
|
|
if (qemuDomainDeleteDevice(vm, info->alias) < 0) {
|
|
|
|
if (virDomainObjIsActive(vm))
|
|
|
|
qemuDomainRemoveAuditDevice(vm, &detach, false);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (async) {
|
|
|
|
ret = 0;
|
|
|
|
} else {
|
|
|
|
if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
|
|
|
|
ret = qemuDomainRemoveDevice(driver, vm, &detach);
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (!async)
|
|
|
|
qemuDomainResetDeviceRemoval(vm);
|
qemu_hotplug: standardize the names/args/calling of qemuDomainDetach*()
Most of these functions will soon contain only some setup for
detaching the device, not the detach code proper (since that code is
identical for these devices). Their device specific functions are all
being renamed to qemuDomainDetachPrep*(), where * is the
name of that device's data member in the virDomainDeviceDef
object.
Since there will be other code in qemuDomainDetachDeviceLive() after
the calls to qemuDomainDetachPrep*() that could still fail, we no
longer directly set "ret" with the return code from
qemuDomainDetachPrep*() functions, but simply return -1 on
failure, and wait until the end of qemuDomainDetachDeviceLive() to set
ret = 0.
Along with the rename, qemuDomainDetachPrep*() functions are also
given similar arglists, including an arg called "match" that points to
the proto-object of the device we want to delete, and another arg
"detach" that is used to return a pointer to the actual object that
will be (for now *has been*) detached. To make sure these new args
aren't confused with existing local pointers that sometimes had the
same name (detach), the local pointer to the device is now named after
the device type ("controller", "disk", etc). These point to the same
place as (*detach)->data.blah, it's just easier on the eyes to have,
e.g., "disk->dst" rather than "(*detach)->data.disk-dst".
Signed-off-by: Laine Stump <laine@laine.org>
ACKed-by: Peter Krempa <pkrempa@redhat.com>
2019-03-20 18:32:53 +00:00
|
|
|
|
2019-03-19 17:55:13 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-08-16 13:02:11 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveVcpu(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
2016-08-16 13:02:11 +00:00
|
|
|
unsigned int vcpu)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
|
|
|
virDomainVcpuDef *vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
|
|
|
|
qemuDomainVcpuPrivate *vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
|
2016-08-16 13:02:11 +00:00
|
|
|
int oldvcpus = virDomainDefGetVcpus(vm->def);
|
|
|
|
unsigned int nvcpus = vcpupriv->vcpus;
|
2017-09-25 20:34:44 +00:00
|
|
|
virErrorPtr save_error = NULL;
|
2016-08-16 13:02:11 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (qemuDomainRefreshVcpuInfo(driver, vm, QEMU_ASYNC_JOB_NONE, false) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* validation requires us to set the expected state prior to calling it */
|
|
|
|
for (i = vcpu; i < vcpu + nvcpus; i++) {
|
|
|
|
vcpuinfo = virDomainDefGetVcpu(vm->def, i);
|
|
|
|
vcpuinfo->online = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qemuDomainValidateVcpuInfo(vm) < 0) {
|
|
|
|
/* rollback vcpu count if the setting has failed */
|
|
|
|
virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", false);
|
|
|
|
|
|
|
|
for (i = vcpu; i < vcpu + nvcpus; i++) {
|
|
|
|
vcpuinfo = virDomainDefGetVcpu(vm->def, i);
|
|
|
|
vcpuinfo->online = true;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", true);
|
|
|
|
|
2017-09-25 20:34:44 +00:00
|
|
|
virErrorPreserveLast(&save_error);
|
|
|
|
|
|
|
|
for (i = vcpu; i < vcpu + nvcpus; i++)
|
|
|
|
ignore_value(virCgroupDelThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, i));
|
|
|
|
|
|
|
|
virErrorRestore(&save_error);
|
2016-08-16 13:02:11 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainRemoveVcpuAlias(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
2016-08-16 13:02:11 +00:00
|
|
|
const char *alias)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainVcpuDef *vcpu;
|
|
|
|
qemuDomainVcpuPrivate *vcpupriv;
|
2016-08-16 13:02:11 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
|
|
|
|
vcpu = virDomainDefGetVcpu(vm->def, i);
|
|
|
|
vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
|
|
|
|
|
|
|
|
if (STREQ_NULLABLE(alias, vcpupriv->alias)) {
|
|
|
|
qemuDomainRemoveVcpu(driver, vm, i);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-13 12:12:34 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainHotplugDelVcpu(virQEMUDriver *driver,
|
|
|
|
virQEMUDriverConfig *cfg,
|
|
|
|
virDomainObj *vm,
|
2016-08-16 13:02:11 +00:00
|
|
|
unsigned int vcpu)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainVcpuDef *vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
|
|
|
|
qemuDomainVcpuPrivate *vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
|
2016-08-16 13:02:11 +00:00
|
|
|
int oldvcpus = virDomainDefGetVcpus(vm->def);
|
|
|
|
unsigned int nvcpus = vcpupriv->vcpus;
|
|
|
|
int rc;
|
2017-03-03 15:04:57 +00:00
|
|
|
int ret = -1;
|
2016-08-16 13:02:11 +00:00
|
|
|
|
|
|
|
if (!vcpupriv->alias) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("vcpu '%u' can't be unplugged"), vcpu);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
qemuDomainMarkDeviceAliasForRemoval(vm, vcpupriv->alias);
|
|
|
|
|
2019-03-12 12:49:24 +00:00
|
|
|
if (qemuDomainDeleteDevice(vm, vcpupriv->alias) < 0) {
|
|
|
|
if (virDomainObjIsActive(vm))
|
|
|
|
virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", false);
|
2017-03-03 15:04:57 +00:00
|
|
|
goto cleanup;
|
2016-08-16 13:02:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((rc = qemuDomainWaitForDeviceRemoval(vm)) <= 0) {
|
|
|
|
if (rc == 0)
|
2019-10-18 18:36:34 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_TIMEOUT, "%s",
|
|
|
|
_("vcpu unplug request timed out. Unplug result "
|
|
|
|
"must be manually inspected in the domain"));
|
2016-08-16 13:02:11 +00:00
|
|
|
|
2017-03-03 15:04:57 +00:00
|
|
|
goto cleanup;
|
2016-08-16 13:02:11 +00:00
|
|
|
}
|
|
|
|
|
2017-03-03 15:04:57 +00:00
|
|
|
if (qemuDomainRemoveVcpu(driver, vm, vcpu) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2017-04-13 12:22:16 +00:00
|
|
|
qemuDomainVcpuPersistOrder(vm->def);
|
|
|
|
|
2019-11-27 12:53:10 +00:00
|
|
|
if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
|
2017-04-13 12:22:16 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-03-03 15:04:57 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
qemuDomainResetDeviceRemoval(vm);
|
|
|
|
return ret;
|
2016-08-16 13:02:11 +00:00
|
|
|
}
|
2016-11-24 15:56:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainHotplugAddVcpu(virQEMUDriver *driver,
|
|
|
|
virQEMUDriverConfig *cfg,
|
|
|
|
virDomainObj *vm,
|
2016-11-24 15:56:56 +00:00
|
|
|
unsigned int vcpu)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virJSONValue *vcpuprops = NULL;
|
|
|
|
virDomainVcpuDef *vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
|
|
|
|
qemuDomainVcpuPrivate *vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
|
2016-11-24 15:56:56 +00:00
|
|
|
unsigned int nvcpus = vcpupriv->vcpus;
|
|
|
|
bool newhotplug = qemuDomainSupportsNewVcpuHotplug(vm);
|
|
|
|
int ret = -1;
|
|
|
|
int rc;
|
|
|
|
int oldvcpus = virDomainDefGetVcpus(vm->def);
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (newhotplug) {
|
2019-10-22 13:26:14 +00:00
|
|
|
vcpupriv->alias = g_strdup_printf("vcpu%u", vcpu);
|
2016-11-24 15:56:56 +00:00
|
|
|
|
|
|
|
if (!(vcpuprops = qemuBuildHotpluggableCPUProps(vcpuinfo)))
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
|
|
|
|
if (newhotplug) {
|
|
|
|
rc = qemuMonitorAddDeviceArgs(qemuDomainGetMonitor(vm), vcpuprops);
|
|
|
|
vcpuprops = NULL;
|
|
|
|
} else {
|
|
|
|
rc = qemuMonitorSetCPU(qemuDomainGetMonitor(vm), vcpu, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
virDomainAuditVcpu(vm, oldvcpus, oldvcpus + nvcpus, "update", rc == 0);
|
|
|
|
|
|
|
|
if (rc < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* start outputting of the new XML element to allow keeping unpluggability */
|
|
|
|
if (newhotplug)
|
|
|
|
vm->def->individualvcpus = true;
|
|
|
|
|
|
|
|
if (qemuDomainRefreshVcpuInfo(driver, vm, QEMU_ASYNC_JOB_NONE, false) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* validation requires us to set the expected state prior to calling it */
|
|
|
|
for (i = vcpu; i < vcpu + nvcpus; i++) {
|
|
|
|
vcpuinfo = virDomainDefGetVcpu(vm->def, i);
|
|
|
|
vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
|
|
|
|
|
|
|
|
vcpuinfo->online = true;
|
|
|
|
|
|
|
|
if (vcpupriv->tid > 0 &&
|
|
|
|
qemuProcessSetupVcpu(vm, i) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qemuDomainValidateVcpuInfo(vm) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2017-04-13 12:22:16 +00:00
|
|
|
qemuDomainVcpuPersistOrder(vm->def);
|
|
|
|
|
2019-11-27 12:53:10 +00:00
|
|
|
if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
|
2017-04-13 12:22:16 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-11-24 15:56:56 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virJSONValueFree(vcpuprops);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* qemuDomainSelectHotplugVcpuEntities:
|
|
|
|
*
|
|
|
|
* @def: domain definition
|
|
|
|
* @nvcpus: target vcpu count
|
|
|
|
* @enable: set to true if vcpus should be enabled
|
|
|
|
*
|
|
|
|
* Tries to find which vcpu entities need to be enabled or disabled to reach
|
|
|
|
* @nvcpus. This function works in order of the legacy hotplug but is able to
|
|
|
|
* skip over entries that are added out of order.
|
|
|
|
*
|
|
|
|
* Returns the bitmap of vcpus to modify on success, NULL on error.
|
|
|
|
*/
|
2021-03-11 07:16:13 +00:00
|
|
|
static virBitmap *
|
|
|
|
qemuDomainSelectHotplugVcpuEntities(virDomainDef *def,
|
2016-11-24 15:56:56 +00:00
|
|
|
unsigned int nvcpus,
|
|
|
|
bool *enable)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virBitmap *ret = NULL;
|
|
|
|
virDomainVcpuDef *vcpu;
|
|
|
|
qemuDomainVcpuPrivate *vcpupriv;
|
2016-11-24 15:56:56 +00:00
|
|
|
unsigned int maxvcpus = virDomainDefGetVcpusMax(def);
|
|
|
|
unsigned int curvcpus = virDomainDefGetVcpus(def);
|
|
|
|
ssize_t i;
|
|
|
|
|
2020-10-01 15:42:11 +00:00
|
|
|
ret = virBitmapNew(maxvcpus);
|
2016-11-24 15:56:56 +00:00
|
|
|
|
|
|
|
if (nvcpus > curvcpus) {
|
|
|
|
*enable = true;
|
|
|
|
|
|
|
|
for (i = 0; i < maxvcpus && curvcpus < nvcpus; i++) {
|
|
|
|
vcpu = virDomainDefGetVcpu(def, i);
|
|
|
|
vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
|
|
|
|
|
|
|
|
if (vcpu->online)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (vcpupriv->vcpus == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
curvcpus += vcpupriv->vcpus;
|
|
|
|
|
|
|
|
if (curvcpus > nvcpus) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("target vm vcpu granularity does not allow the "
|
|
|
|
"desired vcpu count"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
ignore_value(virBitmapSetBit(ret, i));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*enable = false;
|
|
|
|
|
|
|
|
for (i = maxvcpus - 1; i >= 0 && curvcpus > nvcpus; i--) {
|
|
|
|
vcpu = virDomainDefGetVcpu(def, i);
|
|
|
|
vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
|
|
|
|
|
|
|
|
if (!vcpu->online)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (vcpupriv->vcpus == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!vcpupriv->alias)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
curvcpus -= vcpupriv->vcpus;
|
|
|
|
|
|
|
|
if (curvcpus < nvcpus) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("target vm vcpu granularity does not allow the "
|
|
|
|
"desired vcpu count"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
ignore_value(virBitmapSetBit(ret, i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (curvcpus != nvcpus) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("failed to find appropriate hotpluggable vcpus to "
|
|
|
|
"reach the desired target vcpu count"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virBitmapFree(ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainSetVcpusLive(virQEMUDriver *driver,
|
|
|
|
virQEMUDriverConfig *cfg,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virBitmap *vcpumap,
|
2016-11-24 15:56:56 +00:00
|
|
|
bool enable)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainObjPrivate *priv = vm->privateData;
|
|
|
|
qemuCgroupEmulatorAllNodesData *emulatorCgroup = NULL;
|
2016-11-24 15:56:56 +00:00
|
|
|
ssize_t nextvcpu = -1;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (qemuCgroupEmulatorAllNodesAllow(priv->cgroup, &emulatorCgroup) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (enable) {
|
|
|
|
while ((nextvcpu = virBitmapNextSetBit(vcpumap, nextvcpu)) != -1) {
|
2017-04-13 12:22:16 +00:00
|
|
|
if (qemuDomainHotplugAddVcpu(driver, cfg, vm, nextvcpu) < 0)
|
|
|
|
goto cleanup;
|
2016-11-24 15:56:56 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (nextvcpu = virDomainDefGetVcpusMax(vm->def) - 1; nextvcpu >= 0; nextvcpu--) {
|
|
|
|
if (!virBitmapIsBitSet(vcpumap, nextvcpu))
|
|
|
|
continue;
|
|
|
|
|
2017-04-13 12:22:16 +00:00
|
|
|
if (qemuDomainHotplugDelVcpu(driver, cfg, vm, nextvcpu) < 0)
|
|
|
|
goto cleanup;
|
2016-11-24 15:56:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
qemuCgroupEmulatorAllNodesRestore(emulatorCgroup);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* qemuDomainSetVcpusConfig:
|
|
|
|
* @def: config/offline definition of a domain
|
|
|
|
* @nvcpus: target vcpu count
|
|
|
|
*
|
|
|
|
* Properly handle cold(un)plug of vcpus:
|
|
|
|
* - plug in inactive vcpus/uplug active rather than rewriting state
|
|
|
|
* - fix hotpluggable state
|
|
|
|
*/
|
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainSetVcpusConfig(virDomainDef *def,
|
2016-11-24 15:56:56 +00:00
|
|
|
unsigned int nvcpus,
|
|
|
|
bool hotpluggable)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainVcpuDef *vcpu;
|
2016-11-24 15:56:56 +00:00
|
|
|
size_t curvcpus = virDomainDefGetVcpus(def);
|
|
|
|
size_t maxvcpus = virDomainDefGetVcpusMax(def);
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
/* ordering information may become invalid, thus clear it */
|
|
|
|
virDomainDefVcpuOrderClear(def);
|
|
|
|
|
|
|
|
if (curvcpus == nvcpus)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (curvcpus < nvcpus) {
|
|
|
|
for (i = 0; i < maxvcpus; i++) {
|
|
|
|
vcpu = virDomainDefGetVcpu(def, i);
|
|
|
|
|
|
|
|
if (!vcpu)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (vcpu->online) {
|
2018-12-04 17:08:14 +00:00
|
|
|
/* non-hotpluggable vcpus need to be clustered at the beginning,
|
2016-11-24 15:56:56 +00:00
|
|
|
* thus we need to force vcpus to be hotpluggable when we find
|
|
|
|
* vcpus that are hotpluggable and online prior to the ones
|
|
|
|
* we are going to add */
|
|
|
|
if (vcpu->hotpluggable == VIR_TRISTATE_BOOL_YES)
|
|
|
|
hotpluggable = true;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
vcpu->online = true;
|
|
|
|
if (hotpluggable) {
|
|
|
|
vcpu->hotpluggable = VIR_TRISTATE_BOOL_YES;
|
|
|
|
def->individualvcpus = true;
|
|
|
|
} else {
|
|
|
|
vcpu->hotpluggable = VIR_TRISTATE_BOOL_NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (++curvcpus == nvcpus)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = maxvcpus; i != 0; i--) {
|
|
|
|
vcpu = virDomainDefGetVcpu(def, i - 1);
|
|
|
|
|
|
|
|
if (!vcpu || !vcpu->online)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
vcpu->online = false;
|
|
|
|
vcpu->hotpluggable = VIR_TRISTATE_BOOL_YES;
|
|
|
|
|
|
|
|
if (--curvcpus == nvcpus)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainSetVcpusInternal(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainDef *def,
|
|
|
|
virDomainDef *persistentDef,
|
2016-11-24 15:56:56 +00:00
|
|
|
unsigned int nvcpus,
|
|
|
|
bool hotpluggable)
|
|
|
|
{
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
2021-03-11 07:16:13 +00:00
|
|
|
virBitmap *vcpumap = NULL;
|
2016-11-24 15:56:56 +00:00
|
|
|
bool enable;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (def && nvcpus > virDomainDefGetVcpusMax(def)) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("requested vcpus is greater than max allowable"
|
|
|
|
" vcpus for the live domain: %u > %u"),
|
|
|
|
nvcpus, virDomainDefGetVcpusMax(def));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (persistentDef && nvcpus > virDomainDefGetVcpusMax(persistentDef)) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("requested vcpus is greater than max allowable"
|
|
|
|
" vcpus for the persistent domain: %u > %u"),
|
|
|
|
nvcpus, virDomainDefGetVcpusMax(persistentDef));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def) {
|
|
|
|
if (!(vcpumap = qemuDomainSelectHotplugVcpuEntities(vm->def, nvcpus,
|
|
|
|
&enable)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuDomainSetVcpusLive(driver, cfg, vm, vcpumap, enable) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (persistentDef) {
|
|
|
|
qemuDomainSetVcpusConfig(persistentDef, nvcpus, hotpluggable);
|
|
|
|
|
2019-11-27 12:53:10 +00:00
|
|
|
if (virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir) < 0)
|
2016-11-24 15:56:56 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virBitmapFree(vcpumap);
|
|
|
|
return ret;
|
|
|
|
}
|
2016-06-21 15:17:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainSetVcpuConfig(virDomainDef *def,
|
|
|
|
virBitmap *map,
|
2016-06-21 15:17:41 +00:00
|
|
|
bool state)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainVcpuDef *vcpu;
|
2016-06-21 15:17:41 +00:00
|
|
|
ssize_t next = -1;
|
|
|
|
|
|
|
|
def->individualvcpus = true;
|
|
|
|
|
2017-03-31 11:05:47 +00:00
|
|
|
/* ordering information may become invalid, thus clear it */
|
|
|
|
virDomainDefVcpuOrderClear(def);
|
|
|
|
|
2017-03-31 11:02:14 +00:00
|
|
|
while ((next = virBitmapNextSetBit(map, next)) >= 0) {
|
2016-06-21 15:17:41 +00:00
|
|
|
if (!(vcpu = virDomainDefGetVcpu(def, next)))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
vcpu->online = state;
|
|
|
|
vcpu->hotpluggable = VIR_TRISTATE_BOOL_YES;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* qemuDomainFilterHotplugVcpuEntities:
|
|
|
|
*
|
|
|
|
* Returns a bitmap of hotpluggable vcpu entities that correspond to the logical
|
|
|
|
* vcpus requested in @vcpus.
|
|
|
|
*/
|
2021-03-11 07:16:13 +00:00
|
|
|
static virBitmap *
|
|
|
|
qemuDomainFilterHotplugVcpuEntities(virDomainDef *def,
|
|
|
|
virBitmap *vcpus,
|
2016-06-21 15:17:41 +00:00
|
|
|
bool state)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainVcpuPrivate *vcpupriv;
|
|
|
|
virDomainVcpuDef *vcpu;
|
2020-10-02 08:39:23 +00:00
|
|
|
g_autoptr(virBitmap) map = virBitmapNewCopy(vcpus);
|
2016-06-21 15:17:41 +00:00
|
|
|
ssize_t next = -1;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
/* make sure that all selected vcpus are in the correct state */
|
2017-03-31 11:02:14 +00:00
|
|
|
while ((next = virBitmapNextSetBit(map, next)) >= 0) {
|
2016-06-21 15:17:41 +00:00
|
|
|
if (!(vcpu = virDomainDefGetVcpu(def, next)))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (vcpu->online == state) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
2017-03-31 11:28:19 +00:00
|
|
|
_("vcpu '%zd' is already in requested state"), next);
|
2020-10-02 08:39:23 +00:00
|
|
|
return NULL;
|
2016-06-21 15:17:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (vcpu->online && !vcpu->hotpluggable) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
2017-03-31 11:28:19 +00:00
|
|
|
_("vcpu '%zd' can't be hotunplugged"), next);
|
2020-10-02 08:39:23 +00:00
|
|
|
return NULL;
|
2016-06-21 15:17:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make sure that all vCPUs belonging to a single hotpluggable entity were
|
|
|
|
* selected and then de-select any sub-threads of it. */
|
|
|
|
next = -1;
|
2017-03-31 11:02:14 +00:00
|
|
|
while ((next = virBitmapNextSetBit(map, next)) >= 0) {
|
2016-06-21 15:17:41 +00:00
|
|
|
if (!(vcpu = virDomainDefGetVcpu(def, next)))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
|
|
|
|
|
|
|
|
if (vcpupriv->vcpus == 0) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
2017-03-31 11:28:19 +00:00
|
|
|
_("vcpu '%zd' belongs to a larger hotpluggable entity, "
|
2016-06-21 15:17:41 +00:00
|
|
|
"but siblings were not selected"), next);
|
2020-10-02 08:39:23 +00:00
|
|
|
return NULL;
|
2016-06-21 15:17:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = next + 1; i < next + vcpupriv->vcpus; i++) {
|
|
|
|
if (!virBitmapIsBitSet(map, i)) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("vcpu '%zu' was not selected but it belongs to "
|
2017-03-31 11:28:19 +00:00
|
|
|
"hotpluggable entity '%zd-%zd' which was "
|
2016-06-21 15:17:41 +00:00
|
|
|
"partially selected"),
|
|
|
|
i, next, next + vcpupriv->vcpus - 1);
|
2020-10-02 08:39:23 +00:00
|
|
|
return NULL;
|
2016-06-21 15:17:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* clear the subthreads */
|
|
|
|
ignore_value(virBitmapClearBit(map, i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-02 08:39:23 +00:00
|
|
|
return g_steal_pointer(&map);
|
2016-06-21 15:17:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-31 11:13:14 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainVcpuValidateConfig(virDomainDef *def,
|
|
|
|
virBitmap *map)
|
2017-03-31 11:13:14 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainVcpuDef *vcpu;
|
2017-03-31 11:34:16 +00:00
|
|
|
size_t maxvcpus = virDomainDefGetVcpusMax(def);
|
|
|
|
ssize_t next;
|
2017-05-12 15:46:31 +00:00
|
|
|
ssize_t firstvcpu = -1;
|
2017-03-31 11:34:16 +00:00
|
|
|
|
2017-06-28 08:42:49 +00:00
|
|
|
/* vcpu 0 can't be modified */
|
|
|
|
if (virBitmapIsBitSet(map, 0)) {
|
2017-03-31 11:13:14 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
2017-06-28 08:42:49 +00:00
|
|
|
_("vCPU '0' can't be modified"));
|
2017-03-31 11:13:14 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-03-17 17:33:31 +00:00
|
|
|
firstvcpu = virBitmapNextSetBit(map, -1);
|
|
|
|
|
2017-03-31 11:34:16 +00:00
|
|
|
/* non-hotpluggable vcpus need to stay clustered starting from vcpu 0 */
|
2020-03-17 17:33:31 +00:00
|
|
|
for (next = firstvcpu + 1; next < maxvcpus; next++) {
|
2017-03-31 11:34:16 +00:00
|
|
|
if (!(vcpu = virDomainDefGetVcpu(def, next)))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* skip vcpus being modified */
|
2020-03-17 17:33:31 +00:00
|
|
|
if (virBitmapIsBitSet(map, next))
|
2017-03-31 11:34:16 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (vcpu->online && vcpu->hotpluggable == VIR_TRISTATE_BOOL_NO) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("vcpu '%zd' can't be modified as it is followed "
|
2017-05-12 15:46:31 +00:00
|
|
|
"by non-hotpluggable online vcpus"), firstvcpu);
|
2017-03-31 11:34:16 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-31 11:13:14 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-21 15:17:41 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuDomainSetVcpuInternal(virQEMUDriver *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainDef *def,
|
|
|
|
virDomainDef *persistentDef,
|
|
|
|
virBitmap *map,
|
2016-06-21 15:17:41 +00:00
|
|
|
bool state)
|
|
|
|
{
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
2021-03-11 07:16:13 +00:00
|
|
|
virBitmap *livevcpus = NULL;
|
2016-06-21 15:17:41 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (def) {
|
|
|
|
if (!qemuDomainSupportsNewVcpuHotplug(vm)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("this qemu version does not support specific "
|
|
|
|
"vCPU hotplug"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(livevcpus = qemuDomainFilterHotplugVcpuEntities(def, map, state)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* Make sure that only one hotpluggable entity is selected.
|
|
|
|
* qemuDomainSetVcpusLive allows setting more at once but error
|
|
|
|
* resolution in case of a partial failure is hard, so don't let users
|
|
|
|
* do so */
|
|
|
|
if (virBitmapCountBits(livevcpus) != 1) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("only one hotpluggable entity can be selected"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-31 11:13:14 +00:00
|
|
|
if (persistentDef) {
|
2017-06-28 08:42:49 +00:00
|
|
|
if (qemuDomainVcpuValidateConfig(persistentDef, map) < 0)
|
2017-03-31 11:13:14 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-06-21 15:17:41 +00:00
|
|
|
if (livevcpus &&
|
|
|
|
qemuDomainSetVcpusLive(driver, cfg, vm, livevcpus, state) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (persistentDef) {
|
|
|
|
qemuDomainSetVcpuConfig(persistentDef, map, state);
|
|
|
|
|
2019-11-27 12:53:10 +00:00
|
|
|
if (virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir) < 0)
|
2016-06-21 15:17:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virBitmapFree(livevcpus);
|
|
|
|
return ret;
|
|
|
|
}
|