[libvirt] [PATCH 3/4] qemu: hot-plug of watchdog

Boris Fiuczynski fiuczy at linux.vnet.ibm.com
Mon Sep 25 14:13:50 UTC 2017


Michal,
the watchdog model diag288 does not support hot-plug and hot-unplug.

On 09/05/2017 01:45 PM, Michal Privoznik wrote:
> 
> Once again, since domain can have at most one watchdog it
> simplifies things a bit. However, since we must be able to set
> the watchdog action as well, new monitor command needs to be
> used.
> 
> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> ---
>   src/qemu/qemu_alias.c                              | 15 ++++-
>   src/qemu/qemu_alias.h                              |  2 +
>   src/qemu/qemu_command.c                            |  2 +-
>   src/qemu/qemu_command.h                            |  3 +
>   src/qemu/qemu_driver.c                             | 10 +++-
>   src/qemu/qemu_hotplug.c                            | 64 ++++++++++++++++++++++
>   src/qemu/qemu_hotplug.h                            |  3 +
>   src/qemu/qemu_monitor.c                            | 12 ++++
>   src/qemu/qemu_monitor.h                            |  2 +
>   src/qemu/qemu_monitor_json.c                       | 28 ++++++++++
>   src/qemu/qemu_monitor_json.h                       |  3 +
>   tests/qemuhotplugtest.c                            |  9 ++-
>   .../qemuhotplug-watchdog.xml                       |  1 +
>   .../qemuhotplug-base-live+watchdog.xml             | 55 +++++++++++++++++++
>   14 files changed, 205 insertions(+), 4 deletions(-)
>   create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-watchdog.xml
>   create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-base-live+watchdog.xml
> 
> diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c
> index 914b2b94d..63f69e80f 100644
> --- a/src/qemu/qemu_alias.c
> +++ b/src/qemu/qemu_alias.c
> @@ -405,6 +405,19 @@ qemuAssignDeviceShmemAlias(virDomainDefPtr def,
>   }
>   
>   
> +int
> +qemuAssignDeviceWatchdogAlias(virDomainWatchdogDefPtr watchdog)
> +{
> +    const int idx = 0;
> +
> +    /* Currently, there's just one watchdog per domain */
> +
> +    if (virAsprintf(&watchdog->info.alias, "watchdog%d", idx) < 0)
> +        return -1;
> +    return 0;
> +}
> +
> +
>   int
>   qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
>   {
> @@ -482,7 +495,7 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
>               return -1;
>       }
>       if (def->watchdog) {
> -        if (virAsprintf(&def->watchdog->info.alias, "watchdog%d", 0) < 0)
> +        if (qemuAssignDeviceWatchdogAlias(def->watchdog) < 0)
>               return -1;
>       }
>       if (def->memballoon) {
> diff --git a/src/qemu/qemu_alias.h b/src/qemu/qemu_alias.h
> index 300fd4de5..652ffea0c 100644
> --- a/src/qemu/qemu_alias.h
> +++ b/src/qemu/qemu_alias.h
> @@ -65,6 +65,8 @@ int qemuAssignDeviceShmemAlias(virDomainDefPtr def,
>                                  virDomainShmemDefPtr shmem,
>                                  int idx);
>   
> +int qemuAssignDeviceWatchdogAlias(virDomainWatchdogDefPtr watchdog);
> +
>   int qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps);
>   
>   int qemuDomainDeviceAliasIndex(const virDomainDeviceInfo *info,
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 9a27987d4..eb9df044b 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -3921,7 +3921,7 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
>   }
>   
>   
> -static char *
> +char *
>   qemuBuildWatchdogDevStr(const virDomainDef *def,
>                           virDomainWatchdogDefPtr dev,
>                           virQEMUCapsPtr qemuCaps)
> diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
> index 6fbfb3e5f..4b504f685 100644
> --- a/src/qemu/qemu_command.h
> +++ b/src/qemu/qemu_command.h
> @@ -206,5 +206,8 @@ char *qemuBuildShmemDevStr(virDomainDefPtr def,
>       ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
>   
>   
> +char * qemuBuildWatchdogDevStr(const virDomainDef *def,
> +                               virDomainWatchdogDefPtr dev,
> +                               virQEMUCapsPtr qemuCaps);
>   
>   #endif /* __QEMU_COMMAND_H__*/
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 85b4be360..626148dba 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -7593,12 +7593,20 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
>           }
>           break;
>   
> +    case VIR_DOMAIN_DEVICE_WATCHDOG:
> +        ret = qemuDomainAttachWatchdog(driver, vm,
> +                                       dev->data.watchdog);
> +        if (!ret) {
> +            alias = dev->data.watchdog->info.alias;
> +            dev->data.watchdog = NULL;
> +        }
> +        break;
> +
>       case VIR_DOMAIN_DEVICE_NONE:
>       case VIR_DOMAIN_DEVICE_FS:
>       case VIR_DOMAIN_DEVICE_INPUT:
>       case VIR_DOMAIN_DEVICE_SOUND:
>       case VIR_DOMAIN_DEVICE_VIDEO:
> -    case VIR_DOMAIN_DEVICE_WATCHDOG:
>       case VIR_DOMAIN_DEVICE_GRAPHICS:
>       case VIR_DOMAIN_DEVICE_HUB:
>       case VIR_DOMAIN_DEVICE_SMARTCARD:
> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
> index b365078ec..989146eb9 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -2866,6 +2866,70 @@ qemuDomainAttachShmemDevice(virQEMUDriverPtr driver,
>   }
>   
>   
> +int
> +qemuDomainAttachWatchdog(virQEMUDriverPtr driver,
> +                         virDomainObjPtr vm,
> +                         virDomainWatchdogDefPtr watchdog)
> +{
> +    int ret = -1;
> +    qemuDomainObjPrivatePtr priv = vm->privateData;
> +    virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_WATCHDOG, { .watchdog = watchdog } };
> +    virDomainWatchdogAction actualAction = watchdog->action;
> +    char *watchdogstr = NULL;
> +    bool releaseAddress = false;
> +    int rv;
> +
> +    if (vm->def->watchdog) {
> +        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
> +                       _("domain already has a watchdog"));
> +        return -1;
> +    }
> +
> +    if (qemuAssignDeviceWatchdogAlias(watchdog) < 0)
> +        return -1;
> +
> +    if (!(watchdogstr = qemuBuildWatchdogDevStr(vm->def, watchdog, priv->qemuCaps)))
> +        return -1;
> +
> +    if (watchdog->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
> +        if (qemuDomainEnsurePCIAddress(vm, &dev, driver) < 0)
> +            goto cleanup;
> +        releaseAddress = true;
> +    }
> +
> +    /* 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 (actualAction == VIR_DOMAIN_WATCHDOG_ACTION_DUMP)
> +        actualAction = VIR_DOMAIN_WATCHDOG_ACTION_PAUSE;
> +
> +    qemuDomainObjEnterMonitor(driver, vm);
> +
> +    rv = qemuMonitorSetWatchdogAction(priv->mon, actualAction);
> +
> +    if (rv >= 0)
> +        rv = qemuMonitorAddDevice(priv->mon, watchdogstr);
> +
> +    if (qemuDomainObjExitMonitor(driver, vm) < 0) {
> +        releaseAddress = false;
> +        goto cleanup;
> +    }
> +
> +    if (rv < 0)
> +        goto cleanup;
> +
> +    releaseAddress = false;
> +    vm->def->watchdog = watchdog;
> +    ret = 0;
> +
> + cleanup:
> +    if (releaseAddress)
> +        qemuDomainReleaseDeviceAddress(vm, &watchdog->info, NULL);
> +    VIR_FREE(watchdogstr);
> +    return ret;
> +}
> +
> +
>   static int
>   qemuDomainChangeNetBridge(virDomainObjPtr vm,
>                             virDomainNetDefPtr olddev,
> diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
> index 985c6733f..a9dfd8f7a 100644
> --- a/src/qemu/qemu_hotplug.h
> +++ b/src/qemu/qemu_hotplug.h
> @@ -80,6 +80,9 @@ int qemuDomainAttachHostDevice(virConnectPtr conn,
>   int qemuDomainAttachShmemDevice(virQEMUDriverPtr driver,
>                                   virDomainObjPtr vm,
>                                   virDomainShmemDefPtr shmem);
> +int qemuDomainAttachWatchdog(virQEMUDriverPtr driver,
> +                             virDomainObjPtr vm,
> +                             virDomainWatchdogDefPtr watchdog);
>   int qemuDomainFindGraphicsIndex(virDomainDefPtr def,
>                                   virDomainGraphicsDefPtr dev);
>   int qemuDomainAttachMemory(virQEMUDriverPtr driver,
> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index 19082d8bf..5d3f9df47 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
> @@ -4343,3 +4343,15 @@ qemuMonitorEventPanicInfoFree(qemuMonitorEventPanicInfoPtr info)
>   
>       VIR_FREE(info);
>   }
> +
> +
> +int
> +qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
> +                             virDomainWatchdogAction watchdogAction)
> +{
> +    VIR_DEBUG("watchdogAction=%d", watchdogAction);
> +
> +    QEMU_CHECK_MONITOR_JSON(mon);
> +
> +    return qemuMonitorJSONSetWatchdogAction(mon, watchdogAction);
> +}
> diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
> index 9805a3390..b8c9409e5 100644
> --- a/src/qemu/qemu_monitor.h
> +++ b/src/qemu/qemu_monitor.h
> @@ -1132,4 +1132,6 @@ int qemuMonitorSetBlockThreshold(qemuMonitorPtr mon,
>   
>   virJSONValuePtr qemuMonitorQueryNamedBlockNodes(qemuMonitorPtr mon);
>   
> +int qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
> +                                 virDomainWatchdogAction watchdogAction);
>   #endif /* QEMU_MONITOR_H */
> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index df5fb7c8f..02ba701e6 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -7679,3 +7679,31 @@ qemuMonitorJSONQueryNamedBlockNodes(qemuMonitorPtr mon)
>   
>       return ret;
>   }
> +
> +
> +int
> +qemuMonitorJSONSetWatchdogAction(qemuMonitorPtr mon,
> +                                 virDomainWatchdogAction watchdogAction)
> +{
> +    virJSONValuePtr cmd;
> +    virJSONValuePtr reply = NULL;
> +    const char *action = virDomainWatchdogActionTypeToString(watchdogAction);
> +    int ret = -1;
> +
> +    if (!(cmd = qemuMonitorJSONMakeCommand("watchdog-set-action",
> +                                           "s:action", action,
> +                                           NULL)))
> +        return -1;
> +    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
> +        goto cleanup;
> +
> +    if (qemuMonitorJSONCheckError(cmd, reply) < 0)
> +        goto cleanup;
> +
> +    ret = 0;
> +
> + cleanup:
> +    virJSONValueFree(cmd);
> +    virJSONValueFree(reply);
> +    return ret;
> +}
> diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
> index 7462967b5..a7a43d7b8 100644
> --- a/src/qemu/qemu_monitor_json.h
> +++ b/src/qemu/qemu_monitor_json.h
> @@ -524,4 +524,7 @@ int qemuMonitorJSONSetBlockThreshold(qemuMonitorPtr mon,
>   virJSONValuePtr qemuMonitorJSONQueryNamedBlockNodes(qemuMonitorPtr mon)
>       ATTRIBUTE_NONNULL(1);
>   
> +int qemuMonitorJSONSetWatchdogAction(qemuMonitorPtr mon,
> +                                     virDomainWatchdogAction watchdogAction)
> +    ATTRIBUTE_NONNULL(1);
>   #endif /* QEMU_MONITOR_JSON_H */
> diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c
> index 23a498617..b02ae8034 100644
> --- a/tests/qemuhotplugtest.c
> +++ b/tests/qemuhotplugtest.c
> @@ -127,6 +127,9 @@ testQemuHotplugAttach(virDomainObjPtr vm,
>       case VIR_DOMAIN_DEVICE_SHMEM:
>           ret = qemuDomainAttachShmemDevice(&driver, vm, dev->data.shmem);
>           break;
> +    case VIR_DOMAIN_DEVICE_WATCHDOG:
> +        ret = qemuDomainAttachWatchdog(&driver, vm, dev->data.watchdog);
> +        break;
>       default:
>           VIR_TEST_VERBOSE("device type '%s' cannot be attached\n",
>                   virDomainDeviceTypeToString(dev->type));
> @@ -811,10 +814,14 @@ mymain(void)
>                      "device_del", QMP_OK,
>                      "object-del", QMP_OK);
>       DO_TEST_ATTACH("base-live+disk-scsi-wwn",
> -                   "disk-scsi-duplicate-wwn", false, true,
> +                   "disk-scsi-duplicate-wwn", false, false,
>                      "human-monitor-command", HMP("OK\\r\\n"),
>                      "device_add", QMP_OK);
>   
> +    DO_TEST_ATTACH("base-live", "watchdog", false, false,
> +                   "watchdog-set-action", QMP_OK,
> +                   "device_add", QMP_OK);
> +
>   #define DO_TEST_CPU_GROUP(prefix, vcpus, modernhp, expectfail)                 \
>       do {                                                                       \
>           cpudata.test = prefix;                                                 \
> diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-watchdog.xml b/tests/qemuhotplugtestdevices/qemuhotplug-watchdog.xml
> new file mode 100644
> index 000000000..7e0e0a863
> --- /dev/null
> +++ b/tests/qemuhotplugtestdevices/qemuhotplug-watchdog.xml
> @@ -0,0 +1 @@
> +<watchdog model='ib700' action='poweroff'/>
> diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+watchdog.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+watchdog.xml
> new file mode 100644
> index 000000000..f884eec50
> --- /dev/null
> +++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+watchdog.xml
> @@ -0,0 +1,55 @@
> +<domain type='kvm' id='7'>
> +  <name>hotplug</name>
> +  <uuid>d091ea82-29e6-2e34-3005-f02617b36e87</uuid>
> +  <memory unit='KiB'>4194304</memory>
> +  <currentMemory unit='KiB'>4194304</currentMemory>
> +  <vcpu placement='static'>4</vcpu>
> +  <os>
> +    <type arch='x86_64' machine='pc'>hvm</type>
> +    <boot dev='hd'/>
> +  </os>
> +  <features>
> +    <acpi/>
> +    <apic/>
> +    <pae/>
> +  </features>
> +  <clock offset='utc'/>
> +  <on_poweroff>destroy</on_poweroff>
> +  <on_reboot>restart</on_reboot>
> +  <on_crash>restart</on_crash>
> +  <devices>
> +    <emulator>/usr/bin/qemu-system-x86_64</emulator>
> +    <controller type='usb' index='0'>
> +      <alias name='usb'/>
> +      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
> +    </controller>
> +    <controller type='ide' index='0'>
> +      <alias name='ide'/>
> +      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
> +    </controller>
> +    <controller type='scsi' index='0' model='virtio-scsi'>
> +      <alias name='scsi0'/>
> +      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
> +    </controller>
> +    <controller type='pci' index='0' model='pci-root'>
> +      <alias name='pci'/>
> +    </controller>
> +    <controller type='virtio-serial' index='0'>
> +      <alias name='virtio-serial0'/>
> +      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
> +    </controller>
> +    <input type='mouse' bus='ps2'>
> +      <alias name='input0'/>
> +    </input>
> +    <input type='keyboard' bus='ps2'>
> +      <alias name='input1'/>
> +    </input>
> +    <watchdog model='ib700' action='poweroff'>
> +      <alias name='watchdog0'/>
> +    </watchdog>
> +    <memballoon model='none'>
> +      <alias name='balloon0'/>
> +    </memballoon>
> +  </devices>
> +  <seclabel type='none' model='none'/>
> +</domain>
> 


-- 
Mit freundlichen Grüßen/Kind regards
    Boris Fiuczynski

IBM Deutschland Research & Development GmbH
Vorsitzender des Aufsichtsrats: Martina Köderitz
Geschäftsführung: Dirk Wittkopp
Sitz der Gesellschaft: Böblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294




More information about the libvir-list mailing list