Basic qemu NIC hotplug support

Implement basic NIC hotplug support using the 'host_net_add' and
'pci_add' qemu monitor commands.

For now, we don't support 'bridge' or 'network' types.

Also, if pci_add fails, we currently fail to remove the backend
which we added.

Finally, NIC hot-unplug support is missing.

* src/qemu_driver.c: add qemudDomainAttachNetDevice()

* src/qemu_conf.[ch]: export qemuBuildNicStr(), qemuBuildHostNetStr()
  and qemuAssignNames()

* src/libvirt_private.syms: export virDomainNetTypeToString()
This commit is contained in:
Mark McLoughlin 2009-07-17 22:08:34 +01:00
parent 423af1977f
commit 35153940e3
4 changed files with 104 additions and 3 deletions

View File

@ -91,6 +91,7 @@ virDomainLifecycleTypeFromString;
virDomainLifecycleTypeToString;
virDomainLoadAllConfigs;
virDomainNetDefFree;
virDomainNetTypeToString;
virDomainObjFree;
virDomainObjListFree;
virDomainRemoveInactive;

View File

@ -830,7 +830,7 @@ qemuNetTypeToHostNet(int type)
}
}
static int
int
qemuAssignNetNames(virDomainDefPtr def,
virDomainNetDefPtr net)
{
@ -872,7 +872,7 @@ qemuAssignNetNames(virDomainDefPtr def,
return 0;
}
static int
int
qemuBuildNicStr(virConnectPtr conn,
virDomainNetDefPtr net,
const char *prefix,
@ -899,7 +899,7 @@ qemuBuildNicStr(virConnectPtr conn,
return 0;
}
static int
int
qemuBuildHostNetStr(virConnectPtr conn,
virDomainNetDefPtr net,
const char *prefix,

View File

@ -145,6 +145,24 @@ int qemudBuildCommandLine (virConnectPtr conn,
int *ntapfds,
const char *migrateFrom);
int qemuBuildHostNetStr (virConnectPtr conn,
virDomainNetDefPtr net,
const char *prefix,
char type_sep,
int vlan,
int tapfd,
char **str);
int qemuBuildNicStr (virConnectPtr conn,
virDomainNetDefPtr net,
const char *prefix,
char type_sep,
int vlan,
char **str);
int qemuAssignNetNames (virDomainDefPtr def,
virDomainNetDefPtr net);
virDomainDefPtr qemuParseCommandLine(virConnectPtr conn,
virCapsPtr caps,
const char **progenv,

View File

@ -4489,6 +4489,86 @@ static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn,
return 0;
}
static int qemudDomainAttachNetDevice(virConnectPtr conn,
virDomainObjPtr vm,
virDomainDeviceDefPtr dev,
unsigned int qemuCmdFlags)
{
virDomainNetDefPtr net = dev->data.net;
char *cmd, *reply;
int i;
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_HOST_NET_ADD)) {
qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s",
_("installed qemu version does not support host_net_add"));
return -1;
}
if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT,
_("network device type '%s' cannot be attached"),
virDomainNetTypeToString(net->type));
return -1;
}
if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets+1) < 0) {
virReportOOMError(conn);
return -1;
}
if ((qemuCmdFlags & QEMUD_CMD_FLAG_NET_NAME) &&
qemuAssignNetNames(vm->def, net) < 0) {
virReportOOMError(conn);
return -1;
}
/* Choose a vlan value greater than all other values since
* older versions did not store the value in the state file.
*/
net->vlan = vm->def->nnets;
for (i = 0; i < vm->def->nnets; i++)
if (vm->def->nets[i]->vlan >= net->vlan)
net->vlan = vm->def->nets[i]->vlan;
if (qemuBuildHostNetStr(conn, net,
"host_net_add ", ' ', net->vlan, -1, &cmd) < 0)
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(cmd);
return -1;
}
DEBUG("%s: host_net_add reply: %s", vm->def->name, reply);
VIR_FREE(reply);
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;
}
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;
}
VIR_FREE(reply);
VIR_FREE(cmd);
vm->def->nets[vm->def->nnets++] = net;
return 0;
}
static int qemudDomainAttachHostDevice(virConnectPtr conn,
virDomainObjPtr vm,
virDomainDeviceDefPtr dev)
@ -4614,6 +4694,8 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
virDomainDiskDeviceTypeToString(dev->data.disk->device));
goto cleanup;
}
} else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
ret = qemudDomainAttachNetDevice(dom->conn, vm, dev, qemuCmdFlags);
} else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {