If we fail to pci_add a NIC, we should remove the network backend and
leave things the way we found them. To do that, we pre-allocate a
host_net_remove monitor command and issue that if the pci_add fails.
If the remove fails, we just log a warning.
We can only do this if we have a name for the network backend and
we know the vlan number its associated with.
* src/qemu_driver.c: host_net_remove the network backend if the
pci_add fails
---
src/qemu_driver.c | 35 ++++++++++++++++++++++++++++-------
1 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index cde789e..4cc78f5 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -4498,7 +4498,7 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn,
unsigned int qemuCmdFlags)
{
virDomainNetDefPtr net =
dev->data.net;
- char *cmd, *reply;
+ char *cmd, *reply, *remove_cmd;
int i;
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_HOST_NET_ADD)) {
@@ -4538,9 +4538,19 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn,
"host_net_add ", ' ', net->vlan, -1,
&cmd) < 0)
return -1;
+ remove_cmd = NULL;
+ if (net->vlan >= 0 && net->hostnet_name &&
+ virAsprintf(&remove_cmd, "host_net_remove %d %s",
+ net->vlan, net->hostnet_name) < 0) {
+ VIR_FREE(cmd);
+ virReportOOMError(conn);
+ return -1;
+ }
+
if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
_("failed to add network backend with '%s'"),
cmd);
+ VIR_FREE(remove_cmd);
VIR_FREE(cmd);
return -1;
}
@@ -4549,25 +4559,36 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn,
VIR_FREE(cmd);
if (qemuBuildNicStr(conn, net,
- "pci_add pci_addr=auto ", ' ', net->vlan,
&cmd) < 0) {
- /* FIXME: try and remove the backend again */
- return -1;
- }
+ "pci_add pci_addr=auto ", ' ', net->vlan,
&cmd) < 0)
+ goto try_remove;
if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
- /* FIXME: try and remove the backend again */
qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
_("failed to add NIC with '%s'"), cmd);
VIR_FREE(cmd);
- return -1;
+ goto try_remove;
}
VIR_FREE(reply);
VIR_FREE(cmd);
+ VIR_FREE(remove_cmd);
vm->def->nets[vm->def->nnets++] = net;
return 0;
+
+try_remove:
+ reply = NULL;
+
+ if (!remove_cmd)
+ VIR_WARN0(_("Unable to remove network backend\n"));
+ else if (qemudMonitorCommand(vm, remove_cmd, &reply) < 0)
+ VIR_WARN(_("Failed to remove network backend with '%s'\n"),
remove_cmd);
+
+ VIR_FREE(reply);
+ VIR_FREE(remove_cmd);
+
+ return -1;
}
static int qemudDomainAttachHostDevice(virConnectPtr conn,
--
1.6.2.5