On Fri, Apr 17, 2015 at 04:53:06PM +0800, Chen Fan wrote:
via initialize callback to create bond device.
Signed-off-by: Chen Fan <chen.fan.fnst(a)cn.fujitsu.com>
---
src/qemu/qemu_agent.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_agent.h | 10 ++++
src/qemu/qemu_domain.c | 70 ++++++++++++++++++++++++++++
src/qemu/qemu_domain.h | 7 +++
src/qemu/qemu_process.c | 4 ++
5 files changed, 209 insertions(+)
diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index cee0f8b..b8eba01 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -2169,3 +2169,121 @@ qemuAgentGetInterfaces(qemuAgentPtr mon,
goto cleanup;
}
+
+static virDomainInterfacePtr
+findInterfaceByMac(virDomainInterfacePtr *info,
+ size_t len,
+ const char *macstr)
+{
+ size_t i;
+ bool found = false;
+
+ for (i = 0; i < len; i++) {
+ if (info[i]->hwaddr &&
+ STREQ(info[i]->hwaddr, macstr)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ return info[i];
+ }
+
+ return NULL;
+}
+
I think PCI addresses are a better way to identify the devices
for this purpose. This will mean softmac doesn't break this
functionality.
See anything wrong with it?
+/*
+ * qemuAgentSetInterface:
+ */
+int
+qemuAgentCreateBond(qemuAgentPtr mon,
+ virDomainHostdevSubsysPCIPtr pcisrc)
+{
+ int ret = -1;
+ virJSONValuePtr cmd = NULL;
+ virJSONValuePtr reply = NULL;
+ size_t i;
+ char macstr[VIR_MAC_STRING_BUFLEN];
+ virDomainInterfacePtr *interfaceInfo = NULL;
+ virDomainInterfacePtr interface;
+ virJSONValuePtr new_interface = NULL;
+ virJSONValuePtr subInterfaces = NULL;
+ virJSONValuePtr subInterface = NULL;
+ int len;
+
+ if (!(pcisrc->nmac || pcisrc->macs))
+ return ret;
+
+ len = qemuAgentGetInterfaces(mon, &interfaceInfo);
+ if (len < 0)
+ return ret;
+
+ if (!(new_interface = virJSONValueNewObject()))
+ goto cleanup;
+
+ if (virJSONValueObjectAppendString(new_interface, "type",
"bond") < 0)
+ goto cleanup;
+
+ if (virJSONValueObjectAppendString(new_interface, "name",
"bond0") < 0)
+ goto cleanup;
+
+ if (virJSONValueObjectAppendString(new_interface, "onboot",
"onboot") < 0)
+ goto cleanup;
+
+ if (!(subInterfaces = virJSONValueNewArray()))
+ goto cleanup;
+
+ for (i = 0; i < pcisrc->nmac; i++) {
+ virMacAddrFormat(&pcisrc->macs[i], macstr);
+ interface = findInterfaceByMac(interfaceInfo, len, macstr);
+ if (!interface) {
+ goto cleanup;
+ }
+
+ if (!(subInterface = virJSONValueNewObject()))
+ goto cleanup;
+
+ if (virJSONValueObjectAppendString(subInterface, "name",
interface->name) < 0)
+ goto cleanup;
+
+ if (virJSONValueArrayAppend(subInterfaces, subInterface) < 0)
+ goto cleanup;
+
+ subInterface = NULL;
+ }
+
+ if (i && virJSONValueObjectAppend(new_interface, "subInterfaces",
subInterfaces) < 0)
+ goto cleanup;
+
+ cmd = qemuAgentMakeCommand("guest-network-set-interface",
+ "a:interface", new_interface,
+ NULL);
+
+ if (!cmd)
+ goto cleanup;
+
+ subInterfaces = NULL;
+ new_interface = NULL;
+
+ if (qemuAgentCommand(mon, cmd, &reply, true,
+ VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
+ goto cleanup;
+
+ if (virJSONValueObjectGetNumberInt(reply, "return", &ret) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed return value"));
+ }
+
+ cleanup:
+ virJSONValueFree(subInterfaces);
+ virJSONValueFree(subInterface);
+ virJSONValueFree(new_interface);
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ if (interfaceInfo)
+ for (i = 0; i < len; i++)
+ virDomainInterfaceFree(interfaceInfo[i]);
+ VIR_FREE(interfaceInfo);
+ return ret;
+}
diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
index 42414a7..744cb0a 100644
--- a/src/qemu/qemu_agent.h
+++ b/src/qemu/qemu_agent.h
@@ -97,6 +97,13 @@ struct _qemuAgentCPUInfo {
bool offlinable; /* true if the CPU can be offlined */
};
+typedef struct _qemuAgentInterfaceInfo qemuAgentInterfaceInfo;
+typedef qemuAgentInterfaceInfo *qemuAgentInterfaceInfoPtr;
+struct _qemuAgentInterfaceInfo {
+ char *name;
+ char *hardware_address;
+};
+
int qemuAgentGetVCPUs(qemuAgentPtr mon, qemuAgentCPUInfoPtr *info);
int qemuAgentSetVCPUs(qemuAgentPtr mon, qemuAgentCPUInfoPtr cpus, size_t ncpus);
int qemuAgentUpdateCPUInfo(unsigned int nvcpus,
@@ -114,4 +121,7 @@ int qemuAgentSetTime(qemuAgentPtr mon,
int qemuAgentGetInterfaces(qemuAgentPtr mon,
virDomainInterfacePtr **ifaces);
+int qemuAgentCreateBond(qemuAgentPtr mon,
+ virDomainHostdevSubsysPCIPtr pcisrc);
+
#endif /* __QEMU_AGENT_H__ */
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 603360f..584fefb 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2722,6 +2722,46 @@ qemuDomainCleanupRun(virQEMUDriverPtr driver,
priv->ncleanupCallbacks_max = 0;
}
+/*
+ * The vm must be locked when any of the following init functions is
+ * called.
+ */
+int
+qemuDomainInitAdd(virDomainObjPtr vm,
+ qemuDomainInitCallback cb)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ size_t i;
+
+ VIR_DEBUG("vm=%s, cb=%p", vm->def->name, cb);
+
+ for (i = 0; i < priv->nInitCallbacks; i++) {
+ if (priv->initCallbacks[i] == cb)
+ return 0;
+ }
+
+ if (VIR_RESIZE_N(priv->initCallbacks,
+ priv->nInitCallbacks_max,
+ priv->nInitCallbacks, 1) < 0)
+ return -1;
+
+ priv->initCallbacks[priv->nInitCallbacks++] = cb;
+ return 0;
+}
+
+void
+qemuDomainInitCleanup(virDomainObjPtr vm)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+
+ VIR_DEBUG("vm=%s", vm->def->name);
+
+ VIR_FREE(priv->cleanupCallbacks);
+ priv->ncleanupCallbacks = 0;
+ priv->ncleanupCallbacks_max = 0;
+}
+
+
static void
qemuDomainGetImageIds(virQEMUDriverConfigPtr cfg,
virDomainObjPtr vm,
@@ -3083,3 +3123,33 @@ qemuDomainSupportsBlockJobs(virDomainObjPtr vm,
return 0;
}
+
+void
+qemuDomainPrepareHostdevInit(virDomainObjPtr vm)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virDomainDefPtr def = vm->def;
+ int i;
+
+ if (!def->nhostdevs)
+ return;
+
+ if (!qemuDomainAgentAvailable(vm, false))
+ return;
+
+ if (!virDomainObjIsActive(vm))
+ return;
+
+ for (i = 0; i < def->nhostdevs; i++) {
+ virDomainHostdevDefPtr hostdev = def->hostdevs[i];
+ virDomainHostdevSubsysPCIPtr pcisrc = &hostdev->source.subsys.u.pci;
+
+ if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI
&&
+ hostdev->source.subsys.u.pci.backend ==
VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO &&
+ hostdev->source.subsys.u.pci.device ==
VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND) {
+ qemuDomainObjEnterAgent(vm);
+ qemuAgentCreateBond(priv->agent, pcisrc);
+ qemuDomainObjExitAgent(vm);
+ }
+ }
+}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 19f4b27..3244ca0 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -403,6 +403,10 @@ void qemuDomainCleanupRemove(virDomainObjPtr vm,
void qemuDomainCleanupRun(virQEMUDriverPtr driver,
virDomainObjPtr vm);
+int qemuDomainInitAdd(virDomainObjPtr vm,
+ qemuDomainInitCallback cb);
+void qemuDomainInitCleanup(virDomainObjPtr vm);
+
extern virDomainXMLPrivateDataCallbacks virQEMUDriverPrivateDataCallbacks;
extern virDomainXMLNamespace virQEMUDriverDomainXMLNamespace;
extern virDomainDefParserConfig virQEMUDriverDomainDefParserConfig;
@@ -444,4 +448,7 @@ void qemuDomObjEndAPI(virDomainObjPtr *vm);
int qemuDomainAlignMemorySizes(virDomainDefPtr def);
void qemuDomainMemoryDeviceAlignSize(virDomainMemoryDefPtr mem);
+void
+qemuDomainPrepareHostdevInit(virDomainObjPtr vm);
+
#endif /* __QEMU_DOMAIN_H__ */
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index fcc0566..0a72aca 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4444,6 +4444,9 @@ int qemuProcessStart(virConnectPtr conn,
hostdev_flags) < 0)
goto cleanup;
+ if (qemuDomainInitAdd(vm, qemuDomainPrepareHostdevInit))
+ goto cleanup;
+
VIR_DEBUG("Preparing chr devices");
if (virDomainChrDefForeach(vm->def,
true,
@@ -5186,6 +5189,7 @@ void qemuProcessStop(virQEMUDriverPtr driver,
VIR_QEMU_PROCESS_KILL_NOCHECK));
qemuDomainCleanupRun(driver, vm);
+ qemuDomainInitCleanup(vm);
/* Stop autodestroy in case guest is restarted */
qemuProcessAutoDestroyRemove(driver, vm);
--
1.9.3