Adds support for the new API. While starting a qemu link state cannot be set with an command line argument and therefore is done by entering monitor. --- src/qemu/qemu_driver.c | 228 +++++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_process.c | 37 ++++++++ 2 files changed, 265 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 19e749f..a6a76be 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6887,6 +6887,232 @@ qemudDomainInterfaceStats (virDomainPtr dom, #endif static int +qemudDomainInterfaceLinkGetState (virDomainPtr dom, + const char *path, + unsigned int flags) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int i; + int ret = -1; + unsigned char mac[VIR_MAC_BUFLEN]; + virDomainDefPtr def = NULL; + + virCheckFlags(VIR_DOMAIN_AFFECT_CURRENT | + VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + qemuReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + if (virParseMacAddr(path, mac) < 0) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("Couldn't parse MAC address: %s"), path); + goto cleanup; + } + + if (virDomainObjIsActive(vm)) { + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + if (!(def = virDomainObjGetPersistentDef(driver->caps, vm))) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("Couldn't get persistent domain configuration")); + goto cleanup; + } + } else { + def = vm->def; + } + } else { + if (flags & VIR_DOMAIN_AFFECT_LIVE) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto cleanup; + } + if (!(def = virDomainObjGetPersistentDef(driver->caps, vm))) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("Couldn't get persistent domain configuration")); + goto cleanup; + } + } + + /* Check the path is one of the domain's network interfaces. */ + /* Qemu does not support reading the link state, report saved state */ + for (i = 0 ; i < def->nnets ; i++) { + if (memcmp(def->nets[i]->mac, mac, VIR_MAC_BUFLEN) == 0) { + ret = def->nets[i]->linkstate; + break; + } + } + + if (ret < 0) + qemuReportError(VIR_ERR_INVALID_ARG, + _("invalid path, '%s' is not a known interface"), path); + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; + +} + +static int +qemudDomainInterfaceLinkSetState (virDomainPtr dom, + const char *path, + unsigned int state, + unsigned int flags) +{ + struct qemud_driver *driver = dom->conn->privateData; + qemuDomainObjPrivatePtr priv = NULL; + virDomainObjPtr vm; + virDomainDefPtr def = NULL; + virDomainDefPtr persistentDef = NULL; + + bool isActive; + int i; + int ret = -1; + bool found = false; + unsigned char mac[VIR_MAC_BUFLEN]; + + virCheckFlags(VIR_DOMAIN_AFFECT_CURRENT | + VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + qemuReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + priv = vm->privateData; + + if (virParseMacAddr(path, mac) < 0) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("Couldn't parse MAC address: %s"), path); + goto cleanup; + } + + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) + goto cleanup; + + isActive = virDomainObjIsActive(vm); + + if (flags == VIR_DOMAIN_AFFECT_CURRENT) { + if (isActive) + flags |= VIR_DOMAIN_AFFECT_LIVE; + else + flags |= VIR_DOMAIN_AFFECT_CONFIG; + } + + if (!isActive && (flags & VIR_DOMAIN_AFFECT_LIVE)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + _("domain is not running")); + goto endjob; + } + + if (!vm->persistent && (flags & VIR_DOMAIN_AFFECT_CONFIG)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + _("cannot change persistent config of a transient domain")); + goto endjob; + } + + def = vm->def; + if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm))) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("Couldn't get persistent domain configuration")); + goto endjob; + } + + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + for (i = 0; i < persistentDef->nnets; i++) { + if (memcmp(persistentDef->nets[i]->mac, mac, VIR_MAC_BUFLEN) == 0) { + found = true; + persistentDef->nets[i]->linkstate = state; + break; + } + } + + if (!found) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("Interface %s not found"), path); + goto endjob; + } + } + + found = false; + + if (flags & VIR_DOMAIN_AFFECT_LIVE) { + for (i = 0; i < def->nnets; i++) { + if (memcmp(def->nets[i]->mac, mac, VIR_MAC_BUFLEN) == 0) { + if (def->nets[i]->info.alias) { + + if (!qemuCapsGet(priv->qemuCaps, QEMU_CAPS_LINK_SET)) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("This qemu doesn't support setting link state")); + goto endjob; + } + + qemuDomainObjEnterMonitor(driver, vm); + ret = qemuMonitorSetLink(priv->mon, def->nets[i]->info.alias, state); + qemuDomainObjExitMonitor(driver, vm); + } else { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("Device alias not found. (QEMU probably doesn't support device naming)")); + goto endjob; + } + + found = true; + if (ret == 0) + def->nets[i]->linkstate = state; + + break; + } + } + + if (!found) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("Interface %s not found"), path); + goto endjob; + } + + if (ret < 0) + goto endjob; + } + + /* one or both configurations successfuly altered */ + + if ((flags & VIR_DOMAIN_AFFECT_CONFIG) && + virDomainSaveConfig(driver->configDir, persistentDef) < 0) + goto endjob; + + /* everything went well */ + ret = 0; + +endjob: + if (qemuDomainObjEndJob(driver, vm) == 0) + vm = NULL; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + + return ret; +} + +static int qemudDomainMemoryStats (virDomainPtr dom, struct _virDomainMemoryStat *stats, unsigned int nr_stats, @@ -9473,6 +9699,8 @@ static virDriver qemuDriver = { .domainMigratePerform = qemudDomainMigratePerform, /* 0.5.0 */ .domainBlockStats = qemudDomainBlockStats, /* 0.4.1 */ .domainInterfaceStats = qemudDomainInterfaceStats, /* 0.4.1 */ + .domainInterfaceLinkGetState = qemudDomainInterfaceLinkGetState, /* 0.9.5 */ + .domainInterfaceLinkSetState = qemudDomainInterfaceLinkSetState, /* 0.9.5 */ .domainMemoryStats = qemudDomainMemoryStats, /* 0.7.5 */ .domainBlockPeek = qemudDomainBlockPeek, /* 0.4.4 */ .domainMemoryPeek = qemudDomainMemoryPeek, /* 0.4.4 */ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 30c8b28..c0bf30b 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -1441,6 +1441,29 @@ qemuProcessInitCpuAffinity(virDomainObjPtr vm) return 0; } +/* set link states to down on interfaces at qemu start */ +static int +qemuProcessSetLinkStates(virDomainObjPtr vm) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainDefPtr def = vm->def; + int i; + int ret = 0; + + for (i = 0; i < def->nnets; i++) { + if (def->nets[i]->linkstate == VIR_LINK_STATE_DOWN) { + ret = qemuMonitorSetLink(priv->mon, + def->nets[i]->info.alias, + VIR_LINK_STATE_DOWN); + + if (ret != 0) + break; + } + } + + return ret; +} + /* Set CPU affinites for vcpus if vcpupin xml provided. */ static int qemuProcessSetVcpuAffinites(virConnectPtr conn, @@ -2980,6 +3003,20 @@ int qemuProcessStart(virConnectPtr conn, goto cleanup; } + /* set default link states */ + /* qemu doesn't support setting this on the command line, so + * enter the monitor */ + if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_LINK_SET)) { + VIR_DEBUG("Setting network link states"); + qemuDomainObjEnterMonitorWithDriver(driver, vm); + if (qemuProcessSetLinkStates(vm) < 0) { + qemuDomainObjExitMonitorWithDriver(driver, vm); + goto cleanup; + } + + qemuDomainObjExitMonitorWithDriver(driver, vm); + } + /* Technically, qemuProcessStart can be called from inside * QEMU_ASYNC_JOB_MIGRATION_IN, but we are okay treating this like * a sync job since no other job can call into the domain until -- 1.7.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list