mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
Support multiple watchdog devices
This is already possible with qemu, and actually already happening with q35 machines and a specified watchdog since q35 already includes a watchdog we do not include in the XML. In order to express such posibility multiple watchdogs need to be supported. Signed-off-by: Martin Kletzander <mkletzan@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
c5340d5420
commit
1c61bd718a
@ -3899,7 +3899,9 @@ void virDomainDefFree(virDomainDef *def)
|
||||
def->blkio.ndevices);
|
||||
g_free(def->blkio.devices);
|
||||
|
||||
virDomainWatchdogDefFree(def->watchdog);
|
||||
for (i = 0; i < def->nwatchdogs; i++)
|
||||
virDomainWatchdogDefFree(def->watchdogs[i]);
|
||||
g_free(def->watchdogs);
|
||||
|
||||
virDomainMemballoonDefFree(def->memballoon);
|
||||
virDomainNVRAMDefFree(def->nvram);
|
||||
@ -4676,10 +4678,10 @@ virDomainDeviceInfoIterateFlags(virDomainDef *def,
|
||||
if ((rc = cb(def, &device, &def->fss[i]->info, opaque)) != 0)
|
||||
return rc;
|
||||
}
|
||||
if (def->watchdog) {
|
||||
device.type = VIR_DOMAIN_DEVICE_WATCHDOG;
|
||||
device.data.watchdog = def->watchdog;
|
||||
if ((rc = cb(def, &device, &def->watchdog->info, opaque)) != 0)
|
||||
device.type = VIR_DOMAIN_DEVICE_WATCHDOG;
|
||||
for (i = 0; i < def->nwatchdogs; i++) {
|
||||
device.data.watchdog = def->watchdogs[i];
|
||||
if ((rc = cb(def, &device, &def->watchdogs[i]->info, opaque)) != 0)
|
||||
return rc;
|
||||
}
|
||||
if (def->memballoon) {
|
||||
@ -18909,24 +18911,21 @@ virDomainDefParseXML(xmlXPathContextPtr ctxt,
|
||||
VIR_FREE(nodes);
|
||||
|
||||
/* analysis of the watchdog devices */
|
||||
def->watchdog = NULL;
|
||||
if ((n = virXPathNodeSet("./devices/watchdog", ctxt, &nodes)) < 0)
|
||||
n = virXPathNodeSet("./devices/watchdog", ctxt, &nodes);
|
||||
if (n < 0)
|
||||
return NULL;
|
||||
if (n > 1) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("only a single watchdog device is supported"));
|
||||
return NULL;
|
||||
}
|
||||
if (n > 0) {
|
||||
if (n)
|
||||
def->watchdogs = g_new0(virDomainWatchdogDef *, n);
|
||||
for (i = 0; i < n; i++) {
|
||||
virDomainWatchdogDef *watchdog;
|
||||
|
||||
watchdog = virDomainWatchdogDefParseXML(xmlopt, nodes[0], ctxt, flags);
|
||||
watchdog = virDomainWatchdogDefParseXML(xmlopt, nodes[i], ctxt, flags);
|
||||
if (!watchdog)
|
||||
return NULL;
|
||||
|
||||
def->watchdog = watchdog;
|
||||
VIR_FREE(nodes);
|
||||
def->watchdogs[def->nwatchdogs++] = watchdog;
|
||||
}
|
||||
VIR_FREE(nodes);
|
||||
|
||||
/* analysis of the memballoon devices */
|
||||
def->memballoon = NULL;
|
||||
@ -21370,18 +21369,18 @@ virDomainDefCheckABIStabilityFlags(virDomainDef *src,
|
||||
dst->redirfilter))
|
||||
goto error;
|
||||
|
||||
if ((!src->watchdog && dst->watchdog) ||
|
||||
(src->watchdog && !dst->watchdog)) {
|
||||
|
||||
if (src->nwatchdogs != dst->nwatchdogs) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("Target domain watchdog count %d "
|
||||
"does not match source %d"),
|
||||
dst->watchdog ? 1 : 0, src->watchdog ? 1 : 0);
|
||||
_("Target domain watchdog device count %zu does not match source %zu"),
|
||||
dst->nwatchdogs, src->nwatchdogs);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (src->watchdog &&
|
||||
!virDomainWatchdogDefCheckABIStability(src->watchdog, dst->watchdog))
|
||||
goto error;
|
||||
for (i = 0; i < src->nwatchdogs; i++) {
|
||||
if (!virDomainWatchdogDefCheckABIStability(src->watchdogs[i], dst->watchdogs[i]))
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((!src->memballoon && dst->memballoon) ||
|
||||
(src->memballoon && !dst->memballoon)) {
|
||||
@ -27672,8 +27671,8 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (def->watchdog)
|
||||
virDomainWatchdogDefFormat(buf, def->watchdog, flags);
|
||||
for (n = 0; n < def->nwatchdogs; n++)
|
||||
virDomainWatchdogDefFormat(buf, def->watchdogs[n], flags);
|
||||
|
||||
if (def->memballoon)
|
||||
virDomainMemballoonDefFormat(buf, def->memballoon, flags);
|
||||
@ -30736,3 +30735,33 @@ virDomainDefHasSpiceGraphics(const virDomainDef *def)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
virDomainWatchdogDefFind(const virDomainDef *def,
|
||||
const virDomainWatchdogDef *watchdog)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < def->nwatchdogs; i++) {
|
||||
const virDomainWatchdogDef *tmp = def->watchdogs[i];
|
||||
|
||||
if (tmp->model != watchdog->model)
|
||||
continue;
|
||||
|
||||
if (tmp->action != watchdog->action)
|
||||
continue;
|
||||
|
||||
if (watchdog->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
|
||||
!virDomainDeviceInfoAddressIsEqual(&watchdog->info, &tmp->info))
|
||||
continue;
|
||||
|
||||
if (watchdog->info.alias &&
|
||||
STRNEQ_NULLABLE(watchdog->info.alias, tmp->info.alias))
|
||||
continue;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -3092,15 +3092,18 @@ struct _virDomainDef {
|
||||
size_t nsysinfo;
|
||||
virSysinfoDef **sysinfo;
|
||||
|
||||
|
||||
size_t ncryptos;
|
||||
virDomainCryptoDef **cryptos;
|
||||
|
||||
size_t nwatchdogs;
|
||||
virDomainWatchdogDef **watchdogs;
|
||||
|
||||
/* At maximum 2 TPMs on the domain if a TPM Proxy is present. */
|
||||
size_t ntpms;
|
||||
virDomainTPMDef **tpms;
|
||||
|
||||
/* Only 1 */
|
||||
virDomainWatchdogDef *watchdog;
|
||||
virDomainMemballoonDef *memballoon;
|
||||
virDomainNVRAMDef *nvram;
|
||||
virCPUDef *cpu;
|
||||
@ -3562,6 +3565,10 @@ virDomainSoundDef *virDomainSoundDefRemove(virDomainDef *def, size_t idx);
|
||||
void virDomainAudioDefFree(virDomainAudioDef *def);
|
||||
void virDomainMemballoonDefFree(virDomainMemballoonDef *def);
|
||||
void virDomainNVRAMDefFree(virDomainNVRAMDef *def);
|
||||
ssize_t
|
||||
virDomainWatchdogDefFind(const virDomainDef *def,
|
||||
const virDomainWatchdogDef *watchdog)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
|
||||
void virDomainWatchdogDefFree(virDomainWatchdogDef *def);
|
||||
virDomainVideoDef *virDomainVideoDefNew(virDomainXMLOption *xmlopt);
|
||||
void virDomainVideoDefFree(virDomainVideoDef *def);
|
||||
|
@ -6429,9 +6429,9 @@
|
||||
<ref name="crypto"/>
|
||||
</choice>
|
||||
</zeroOrMore>
|
||||
<optional>
|
||||
<zeroOrMore>
|
||||
<ref name="watchdog"/>
|
||||
</optional>
|
||||
</zeroOrMore>
|
||||
<optional>
|
||||
<ref name="memballoon"/>
|
||||
</optional>
|
||||
|
@ -699,6 +699,7 @@ virDomainVsockDefFree;
|
||||
virDomainVsockDefNew;
|
||||
virDomainWatchdogActionTypeFromString;
|
||||
virDomainWatchdogActionTypeToString;
|
||||
virDomainWatchdogDefFind;
|
||||
virDomainWatchdogDefFree;
|
||||
virDomainWatchdogModelTypeFromString;
|
||||
virDomainWatchdogModelTypeToString;
|
||||
|
@ -555,12 +555,26 @@ qemuAssignDeviceShmemAlias(virDomainDef *def,
|
||||
|
||||
|
||||
void
|
||||
qemuAssignDeviceWatchdogAlias(virDomainWatchdogDef *watchdog)
|
||||
qemuAssignDeviceWatchdogAlias(virDomainDef *def,
|
||||
virDomainWatchdogDef *watchdog,
|
||||
int idx)
|
||||
{
|
||||
/* Currently, there's just one watchdog per domain */
|
||||
ssize_t i = 0;
|
||||
|
||||
if (!watchdog->info.alias)
|
||||
watchdog->info.alias = g_strdup("watchdog0");
|
||||
if (watchdog->info.alias)
|
||||
return;
|
||||
|
||||
if (idx == -1) {
|
||||
for (i = 0; i < def->nwatchdogs; i++) {
|
||||
int cur_idx = qemuDomainDeviceAliasIndex(&def->watchdogs[i]->info, "watchdog");
|
||||
if (cur_idx > idx)
|
||||
idx = cur_idx;
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
watchdog->info.alias = g_strdup_printf("watchdog%d", idx);
|
||||
}
|
||||
|
||||
|
||||
@ -686,8 +700,8 @@ qemuAssignDeviceAliases(virDomainDef *def)
|
||||
for (i = 0; i < def->nsmartcards; i++) {
|
||||
qemuAssignDeviceSmartcardAlias(def->smartcards[i], i);
|
||||
}
|
||||
if (def->watchdog) {
|
||||
qemuAssignDeviceWatchdogAlias(def->watchdog);
|
||||
for (i = 0; i < def->nwatchdogs; i++) {
|
||||
qemuAssignDeviceWatchdogAlias(def, def->watchdogs[i], i);
|
||||
}
|
||||
if (def->memballoon &&
|
||||
def->memballoon->model != VIR_DOMAIN_MEMBALLOON_MODEL_NONE) {
|
||||
|
@ -61,7 +61,10 @@ void qemuAssignDeviceShmemAlias(virDomainDef *def,
|
||||
virDomainShmemDef *shmem,
|
||||
int idx);
|
||||
|
||||
void qemuAssignDeviceWatchdogAlias(virDomainWatchdogDef *watchdog);
|
||||
void
|
||||
qemuAssignDeviceWatchdogAlias(virDomainDef *def,
|
||||
virDomainWatchdogDef *watchdog,
|
||||
int idx);
|
||||
|
||||
void qemuAssignDeviceInputAlias(virDomainDef *def,
|
||||
virDomainInputDef *input,
|
||||
|
@ -4050,26 +4050,34 @@ qemuBuildWatchdogCommandLine(virCommand *cmd,
|
||||
const virDomainDef *def,
|
||||
virQEMUCaps *qemuCaps)
|
||||
{
|
||||
virDomainWatchdogDef *watchdog = def->watchdog;
|
||||
g_autoptr(virJSONValue) props = NULL;
|
||||
virDomainWatchdogDef *watchdog = NULL;
|
||||
const char *action;
|
||||
int actualAction;
|
||||
ssize_t i = 0;
|
||||
|
||||
if (!def->watchdog)
|
||||
if (def->nwatchdogs == 0)
|
||||
return 0;
|
||||
|
||||
if (qemuCommandAddExtDevice(cmd, &def->watchdog->info, def, qemuCaps) < 0)
|
||||
return -1;
|
||||
for (i = 0; i < def->nwatchdogs; i++) {
|
||||
g_autoptr(virJSONValue) props = NULL;
|
||||
|
||||
if (!(props = qemuBuildWatchdogDevProps(def, watchdog)))
|
||||
return -1;
|
||||
watchdog = def->watchdogs[i];
|
||||
|
||||
if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCaps))
|
||||
return -1;
|
||||
if (qemuCommandAddExtDevice(cmd, &watchdog->info, def, qemuCaps) < 0)
|
||||
return -1;
|
||||
|
||||
if (!(props = qemuBuildWatchdogDevProps(def, watchdog)))
|
||||
return -1;
|
||||
|
||||
if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCaps))
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
ourselves. so convert 'dump' to 'pause' for the qemu cli. The
|
||||
validator already checked that all watchdogs have the same action.
|
||||
*/
|
||||
actualAction = watchdog->action;
|
||||
if (watchdog->action == VIR_DOMAIN_WATCHDOG_ACTION_DUMP)
|
||||
actualAction = VIR_DOMAIN_WATCHDOG_ACTION_PAUSE;
|
||||
|
@ -2342,10 +2342,10 @@ qemuDomainAssignDevicePCISlots(virDomainDef *def,
|
||||
}
|
||||
|
||||
/* A watchdog - check if it is a PCI device */
|
||||
if (def->watchdog &&
|
||||
def->watchdog->model == VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB &&
|
||||
virDeviceInfoPCIAddressIsWanted(&def->watchdog->info)) {
|
||||
if (qemuDomainPCIAddressReserveNextAddr(addrs, &def->watchdog->info) < 0)
|
||||
for (i = 0; i < def->nwatchdogs; i++) {
|
||||
if (def->watchdogs[i]->model == VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB &&
|
||||
virDeviceInfoPCIAddressIsWanted(&def->watchdogs[i]->info) &&
|
||||
qemuDomainPCIAddressReserveNextAddr(addrs, &def->watchdogs[i]->info) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -7260,12 +7260,13 @@ qemuDomainAttachDeviceConfig(virDomainDef *vmdef,
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_DEVICE_WATCHDOG:
|
||||
if (vmdef->watchdog) {
|
||||
if (virDomainWatchdogDefFind(vmdef, dev->data.watchdog) >= 0) {
|
||||
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||
_("domain already has a watchdog"));
|
||||
_("device is already in the domain configuration"));
|
||||
return -1;
|
||||
}
|
||||
vmdef->watchdog = g_steal_pointer(&dev->data.watchdog);
|
||||
|
||||
VIR_APPEND_ELEMENT(vmdef->watchdogs, vmdef->nwatchdogs, dev->data.watchdog);
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_DEVICE_INPUT:
|
||||
@ -7460,12 +7461,13 @@ qemuDomainDetachDeviceConfig(virDomainDef *vmdef,
|
||||
|
||||
|
||||
case VIR_DOMAIN_DEVICE_WATCHDOG:
|
||||
if (!vmdef->watchdog) {
|
||||
idx = virDomainWatchdogDefFind(vmdef, dev->data.watchdog);
|
||||
if (idx < 0) {
|
||||
virReportError(VIR_ERR_DEVICE_MISSING, "%s",
|
||||
_("domain has no watchdog"));
|
||||
_("no matching watchdog was found"));
|
||||
return -1;
|
||||
}
|
||||
g_clear_pointer(&vmdef->watchdog, virDomainWatchdogDefFree);
|
||||
VIR_DELETE_ELEMENT(vmdef->watchdogs, idx, vmdef->nwatchdogs);
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_DEVICE_INPUT:
|
||||
|
@ -2926,15 +2926,9 @@ qemuDomainAttachWatchdog(virDomainObj *vm,
|
||||
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_WATCHDOG, { .watchdog = watchdog } };
|
||||
g_autoptr(virJSONValue) props = NULL;
|
||||
bool releaseAddress = false;
|
||||
int rv;
|
||||
int rv = 0;
|
||||
|
||||
if (vm->def->watchdog) {
|
||||
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||
_("domain already has a watchdog"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
qemuAssignDeviceWatchdogAlias(watchdog);
|
||||
qemuAssignDeviceWatchdogAlias(vm->def, watchdog, -1);
|
||||
|
||||
if (watchdog->model != VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB) {
|
||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
||||
@ -2952,10 +2946,13 @@ qemuDomainAttachWatchdog(virDomainObj *vm,
|
||||
|
||||
qemuDomainObjEnterMonitor(vm);
|
||||
|
||||
/* 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 (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SET_ACTION)) {
|
||||
if (vm->def->nwatchdogs) {
|
||||
/* Domain already has a watchdog and all must have the same action. */
|
||||
rv = 0;
|
||||
} else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SET_ACTION)) {
|
||||
/* 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 */
|
||||
qemuMonitorActionWatchdog watchdogaction = QEMU_MONITOR_ACTION_WATCHDOG_KEEP;
|
||||
|
||||
switch (watchdog->action) {
|
||||
@ -3013,7 +3010,7 @@ qemuDomainAttachWatchdog(virDomainObj *vm,
|
||||
goto cleanup;
|
||||
|
||||
releaseAddress = false;
|
||||
vm->def->watchdog = watchdog;
|
||||
VIR_APPEND_ELEMENT_COPY(vm->def->watchdogs, vm->def->nwatchdogs, watchdog);
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
@ -4846,11 +4843,20 @@ static int
|
||||
qemuDomainRemoveWatchdog(virDomainObj *vm,
|
||||
virDomainWatchdogDef *watchdog)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
VIR_DEBUG("Removing watchdog %s from domain %p %s",
|
||||
watchdog->info.alias, vm, vm->def->name);
|
||||
|
||||
for (i = 0; i < vm->def->nwatchdogs; i++) {
|
||||
if (vm->def->watchdogs[i] == watchdog)
|
||||
break;
|
||||
}
|
||||
|
||||
qemuDomainReleaseDeviceAddress(vm, &watchdog->info);
|
||||
g_clear_pointer(&vm->def->watchdog, virDomainWatchdogDefFree);
|
||||
virDomainWatchdogDefFree(watchdog);
|
||||
VIR_DELETE_ELEMENT(vm->def->watchdogs, i, vm->def->nwatchdogs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5603,33 +5609,20 @@ qemuDomainDetachPrepWatchdog(virDomainObj *vm,
|
||||
virDomainWatchdogDef *match,
|
||||
virDomainWatchdogDef **detach)
|
||||
{
|
||||
virDomainWatchdogDef *watchdog;
|
||||
ssize_t idx = virDomainWatchdogDefFind(vm->def, match);
|
||||
|
||||
*detach = watchdog = vm->def->watchdog;
|
||||
|
||||
if (!watchdog) {
|
||||
virReportError(VIR_ERR_DEVICE_MISSING, "%s",
|
||||
_("watchdog device not present in domain configuration"));
|
||||
if (idx < 0) {
|
||||
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||
_("no matching watchdog was found"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
if (!(watchdog->model == match->model &&
|
||||
watchdog->action == match->action &&
|
||||
virDomainDeviceInfoAddressIsEqual(&match->info, &watchdog->info))) {
|
||||
virReportError(VIR_ERR_DEVICE_MISSING,
|
||||
_("model '%s' watchdog device not present "
|
||||
"in domain configuration"),
|
||||
virDomainWatchdogModelTypeToString(watchdog->model));
|
||||
return -1;
|
||||
}
|
||||
*detach = vm->def->watchdogs[idx];
|
||||
|
||||
if (watchdog->model != VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB) {
|
||||
if ((*detach)->model != VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB) {
|
||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
||||
_("hot unplug of watchdog of model %s is not supported"),
|
||||
virDomainWatchdogModelTypeToString(watchdog->model));
|
||||
virDomainWatchdogModelTypeToString((*detach)->model));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -804,7 +804,8 @@ qemuProcessHandleWatchdog(qemuMonitor *mon G_GNUC_UNUSED,
|
||||
qemuDomainSaveStatus(vm);
|
||||
}
|
||||
|
||||
if (vm->def->watchdog->action == VIR_DOMAIN_WATCHDOG_ACTION_DUMP) {
|
||||
if (vm->def->nwatchdogs &&
|
||||
vm->def->watchdogs[0]->action == VIR_DOMAIN_WATCHDOG_ACTION_DUMP) {
|
||||
qemuProcessEventSubmit(vm, QEMU_PROCESS_EVENT_WATCHDOG,
|
||||
VIR_DOMAIN_WATCHDOG_ACTION_DUMP, 0, NULL);
|
||||
}
|
||||
|
@ -1188,6 +1188,28 @@ qemuValidateDomainDefTPMs(const virDomainDef *def)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuValidateDomainDefWatchdogs(const virDomainDef *def)
|
||||
{
|
||||
ssize_t i = 0;
|
||||
|
||||
for (i = 1; i < def->nwatchdogs; i++) {
|
||||
/* We could theoretically support different watchdogs having dump and
|
||||
* pause, but let's be honest, we support multiple watchdogs only
|
||||
* because we need to be able to add a second, implicit one, not because
|
||||
* it is a brilliant idea to have multiple watchdogs. */
|
||||
if (def->watchdogs[i]->action != def->watchdogs[0]->action) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("watchdogs with different actions are not supported "
|
||||
"with this QEMU binary"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuValidateLifecycleAction(virDomainLifecycleAction onPoweroff,
|
||||
virDomainLifecycleAction onReboot,
|
||||
@ -1388,6 +1410,9 @@ qemuValidateDomainDef(const virDomainDef *def,
|
||||
if (qemuValidateDomainDefTPMs(def) < 0)
|
||||
return -1;
|
||||
|
||||
if (qemuValidateDomainDefWatchdogs(def) < 0)
|
||||
return -1;
|
||||
|
||||
if (def->sec) {
|
||||
switch ((virDomainLaunchSecurity) def->sec->sectype) {
|
||||
case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
|
||||
|
@ -0,0 +1,39 @@
|
||||
LC_ALL=C \
|
||||
PATH=/bin \
|
||||
HOME=/tmp/lib/domain--1-QEMUGuest1 \
|
||||
USER=test \
|
||||
LOGNAME=test \
|
||||
XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \
|
||||
XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \
|
||||
XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
|
||||
/usr/bin/qemu-system-x86_64 \
|
||||
-name guest=QEMUGuest1,debug-threads=on \
|
||||
-S \
|
||||
-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \
|
||||
-machine q35,usb=off,dump-guest-core=off,memory-backend=pc.ram \
|
||||
-accel tcg \
|
||||
-cpu qemu64 \
|
||||
-m 214 \
|
||||
-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \
|
||||
-overcommit mem-lock=off \
|
||||
-smp 1,sockets=1,cores=1,threads=1 \
|
||||
-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
|
||||
-display none \
|
||||
-no-user-config \
|
||||
-nodefaults \
|
||||
-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
|
||||
-mon chardev=charmonitor,id=monitor,mode=control \
|
||||
-rtc base=utc \
|
||||
-no-shutdown \
|
||||
-no-acpi \
|
||||
-boot strict=on \
|
||||
-device '{"driver":"pcie-root-port","port":8,"chassis":1,"id":"pci.1","bus":"pcie.0","multifunction":true,"addr":"0x1"}' \
|
||||
-device '{"driver":"pcie-pci-bridge","id":"pci.2","bus":"pci.1","addr":"0x0"}' \
|
||||
-device '{"driver":"pcie-root-port","port":9,"chassis":3,"id":"pci.3","bus":"pcie.0","addr":"0x1.0x1"}' \
|
||||
-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.2","addr":"0x1"}' \
|
||||
-audiodev '{"id":"audio1","driver":"none"}' \
|
||||
-device '{"driver":"ib700","id":"watchdog0"}' \
|
||||
-device '{"driver":"i6300esb","id":"watchdog1","bus":"pci.2","addr":"0x2"}' \
|
||||
-watchdog-action poweroff \
|
||||
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
|
||||
-msg timestamp=on
|
25
tests/qemuxml2argvdata/watchdog-q35-multiple.xml
Normal file
25
tests/qemuxml2argvdata/watchdog-q35-multiple.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<domain type='qemu'>
|
||||
<name>QEMUGuest1</name>
|
||||
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||
<memory unit='KiB'>219100</memory>
|
||||
<currentMemory unit='KiB'>219100</currentMemory>
|
||||
<vcpu placement='static'>1</vcpu>
|
||||
<os>
|
||||
<type arch='x86_64' machine='q35'>hvm</type>
|
||||
<boot dev='hd'/>
|
||||
</os>
|
||||
<clock offset='utc'/>
|
||||
<on_poweroff>destroy</on_poweroff>
|
||||
<on_reboot>restart</on_reboot>
|
||||
<on_crash>destroy</on_crash>
|
||||
<devices>
|
||||
<emulator>/usr/bin/qemu-system-x86_64</emulator>
|
||||
<controller type='pci' index='0' model='pcie-root'/>
|
||||
<controller type='usb' index='0'/>
|
||||
<input type='mouse' bus='ps2'/>
|
||||
<input type='keyboard' bus='ps2'/>
|
||||
<watchdog model='ib700' action='poweroff'/>
|
||||
<watchdog model='i6300esb' action='poweroff'/>
|
||||
<memballoon model='none'/>
|
||||
</devices>
|
||||
</domain>
|
@ -1756,6 +1756,7 @@ mymain(void)
|
||||
DO_TEST_CAPS_LATEST("watchdog-device");
|
||||
DO_TEST_CAPS_LATEST("watchdog-dump");
|
||||
DO_TEST_CAPS_LATEST("watchdog-injectnmi");
|
||||
DO_TEST_CAPS_LATEST("watchdog-q35-multiple");
|
||||
DO_TEST_CAPS_ARCH_LATEST("watchdog-diag288", "s390x");
|
||||
DO_TEST_NOCAPS("balloon-device");
|
||||
DO_TEST("balloon-device-deflate",
|
||||
|
@ -0,0 +1,50 @@
|
||||
<domain type='qemu'>
|
||||
<name>QEMUGuest1</name>
|
||||
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||
<memory unit='KiB'>219100</memory>
|
||||
<currentMemory unit='KiB'>219100</currentMemory>
|
||||
<vcpu placement='static'>1</vcpu>
|
||||
<os>
|
||||
<type arch='x86_64' machine='q35'>hvm</type>
|
||||
<boot dev='hd'/>
|
||||
</os>
|
||||
<cpu mode='custom' match='exact' check='none'>
|
||||
<model fallback='forbid'>qemu64</model>
|
||||
</cpu>
|
||||
<clock offset='utc'/>
|
||||
<on_poweroff>destroy</on_poweroff>
|
||||
<on_reboot>restart</on_reboot>
|
||||
<on_crash>destroy</on_crash>
|
||||
<devices>
|
||||
<emulator>/usr/bin/qemu-system-x86_64</emulator>
|
||||
<controller type='pci' index='0' model='pcie-root'/>
|
||||
<controller type='usb' index='0' model='piix3-uhci'>
|
||||
<address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/>
|
||||
</controller>
|
||||
<controller type='sata' index='0'>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
|
||||
</controller>
|
||||
<controller type='pci' index='1' model='pcie-root-port'>
|
||||
<model name='pcie-root-port'/>
|
||||
<target chassis='1' port='0x8'/>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/>
|
||||
</controller>
|
||||
<controller type='pci' index='2' model='pcie-to-pci-bridge'>
|
||||
<model name='pcie-pci-bridge'/>
|
||||
<address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
|
||||
</controller>
|
||||
<controller type='pci' index='3' model='pcie-root-port'>
|
||||
<model name='pcie-root-port'/>
|
||||
<target chassis='3' port='0x9'/>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
|
||||
</controller>
|
||||
<input type='mouse' bus='ps2'/>
|
||||
<input type='keyboard' bus='ps2'/>
|
||||
<audio id='1' type='none'/>
|
||||
<watchdog model='ib700' action='poweroff'/>
|
||||
<watchdog model='i6300esb' action='poweroff'>
|
||||
<address type='pci' domain='0x0000' bus='0x02' slot='0x02' function='0x0'/>
|
||||
</watchdog>
|
||||
<memballoon model='none'/>
|
||||
</devices>
|
||||
</domain>
|
@ -489,6 +489,7 @@ mymain(void)
|
||||
QEMU_CAPS_HDA_DUPLEX,
|
||||
QEMU_CAPS_HDA_OUTPUT);
|
||||
DO_TEST_NOCAPS("watchdog");
|
||||
DO_TEST_CAPS_LATEST("watchdog-q35-multiple");
|
||||
DO_TEST("net-bandwidth", QEMU_CAPS_DEVICE_VGA, QEMU_CAPS_VNC);
|
||||
DO_TEST("net-bandwidth2", QEMU_CAPS_DEVICE_VGA, QEMU_CAPS_VNC);
|
||||
DO_TEST_NOCAPS("net-mtu");
|
||||
|
Loading…
Reference in New Issue
Block a user