[libvirt] [PATCH v4 1/6] undefine: Define the new API

This introduces a new API virDomainUndefineFlags to control the domain undefine process, as the existing API virDomainUndefine doesn't support flags. Currently only flag VIR_DOMAIN_UNDEFINE_MANAGED_SAVE is supported. If the domain has a managed save image, including VIR_DOMAIN_UNDEFINE_MANAGED_SAVE in @flags will also remove that file, and omitting the flag will cause undefine process to fail. This patch also changes the behavior of virDomainUndefine, if the domain has a managed save image, the undefine will be refused. --- include/libvirt/libvirt.h.in | 10 +++++++ src/driver.h | 4 +++ src/libvirt.c | 60 +++++++++++++++++++++++++++++++++++++++++- src/libvirt_public.syms | 5 +++ 4 files changed, 78 insertions(+), 1 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 607b5bc..5f9f08a 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1200,6 +1200,16 @@ int virDomainMemoryPeek (virDomainPtr dom, virDomainPtr virDomainDefineXML (virConnectPtr conn, const char *xml); int virDomainUndefine (virDomainPtr domain); + +typedef enum { + VIR_DOMAIN_UNDEFINE_MANAGED_SAVE = 1, + + /* Future undefine control flags should come here. */ +} virDomainUndefineFlagsValues; + + +int virDomainUndefineFlags (virDomainPtr domain, + unsigned int flags); int virConnectNumOfDefinedDomains (virConnectPtr conn); int virConnectListDefinedDomains (virConnectPtr conn, char **const names, diff --git a/src/driver.h b/src/driver.h index 9d0d3de..4c4955f 100644 --- a/src/driver.h +++ b/src/driver.h @@ -219,6 +219,9 @@ typedef virDomainPtr typedef int (*virDrvDomainUndefine) (virDomainPtr dom); typedef int + (*virDrvDomainUndefineFlags) (virDomainPtr dom, + unsigned int flags); +typedef int (*virDrvDomainSetVcpus) (virDomainPtr domain, unsigned int nvcpus); typedef int @@ -733,6 +736,7 @@ struct _virDriver { virDrvDomainCreateWithFlags domainCreateWithFlags; virDrvDomainDefineXML domainDefineXML; virDrvDomainUndefine domainUndefine; + virDrvDomainUndefineFlags domainUndefineFlags; virDrvDomainAttachDevice domainAttachDevice; virDrvDomainAttachDeviceFlags domainAttachDeviceFlags; virDrvDomainDetachDevice domainDetachDevice; diff --git a/src/libvirt.c b/src/libvirt.c index 39e2041..2f5241a 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -6374,7 +6374,13 @@ error: * virDomainUndefine: * @domain: pointer to a defined domain * - * Undefine a domain but does not stop it if it is running + * Undefine a domain. If the domain is running, it's converted to + * transient domain, without stopping it. If the domain is inactive, + * the domain configuration is removed. + * + * If the domain has a managed save image (see + * virDomainHasManagedSaveImage()), then the undefine will fail. See + * virDomainUndefineFlags() for more control. * * Returns 0 in case of success, -1 in case of error */ @@ -6413,6 +6419,58 @@ error: } /** + * virDomainUndefineFlags: + * @domain: pointer to a defined domain + * @flags: bitwise-or of supported virDomainUndefineFlagsValues + * + * Undefine a domain. If the domain is running, it's converted to + * transient domain, without stopping it. If the domain is inactive, + * the domain configuration is removed. + * + * If the domain has a managed save image (see virDomainHasManagedSaveImage()), + * then including VIR_DOMAIN_UNDEFINE_MANAGED_SAVE in @flags will also remove + * that file, and omitting the flag will cause the undefine process to fail. + * + * Returns 0 in case of success, -1 in case of error + */ +int +virDomainUndefineFlags(virDomainPtr domain, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "flags=%x", flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + conn = domain->conn; + if (conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->driver->domainUndefineFlags) { + int ret; + ret = conn->driver->domainUndefineFlags (domain, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; +} + + +/** * virConnectNumOfDefinedDomains: * @conn: pointer to the hypervisor connection * diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 5f2541a..5cc480e 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -466,4 +466,9 @@ LIBVIRT_0.9.3 { virNodeGetMemoryStats; } LIBVIRT_0.9.2; +LIBVIRT_0.9.4 { + global: + virDomainUndefineFlags; +} LIBVIRT_0.9.3; + # .... define new API here using predicted next version number .... -- 1.7.6

On 07/19/2011 09:57 AM, Osier Yang wrote:
This introduces a new API virDomainUndefineFlags to control the domain undefine process, as the existing API virDomainUndefine doesn't support flags.
Currently only flag VIR_DOMAIN_UNDEFINE_MANAGED_SAVE is supported. If the domain has a managed save image, including VIR_DOMAIN_UNDEFINE_MANAGED_SAVE in @flags will also remove that file, and omitting the flag will cause undefine process to fail.
This patch also changes the behavior of virDomainUndefine, if the domain has a managed save image, the undefine will be refused. --- include/libvirt/libvirt.h.in | 10 +++++++ src/driver.h | 4 +++ src/libvirt.c | 60 +++++++++++++++++++++++++++++++++++++++++- src/libvirt_public.syms | 5 +++ 4 files changed, 78 insertions(+), 1 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 607b5bc..5f9f08a 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1200,6 +1200,16 @@ int virDomainMemoryPeek (virDomainPtr dom, virDomainPtr virDomainDefineXML (virConnectPtr conn, const char *xml); int virDomainUndefine (virDomainPtr domain); + +typedef enum { + VIR_DOMAIN_UNDEFINE_MANAGED_SAVE = 1,
Style nit - I'd write this "1<<0" rather than "1", to make it clear that future additions will be bits, as in "1<<1", "1<<2". ACK. We're finally there on a nice interface. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

--- src/remote/remote_driver.c | 3 ++- src/remote/remote_protocol.x | 9 ++++++++- src/remote_protocol-structs | 5 +++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index c2f8bbd..db60089 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1,5 +1,5 @@ /* - * remote_internal.c: driver to provide access to libvirtd running + * remote_driver.c: driver to provide access to libvirtd running * on a remote machine * * Copyright (C) 2007-2011 Red Hat, Inc. @@ -4185,6 +4185,7 @@ static virDriver remote_driver = { .domainCreateWithFlags = remoteDomainCreateWithFlags, /* 0.8.2 */ .domainDefineXML = remoteDomainDefineXML, /* 0.3.0 */ .domainUndefine = remoteDomainUndefine, /* 0.3.0 */ + .domainUndefineFlags = remoteDomainUndefineFlags, /* 0.9.4 */ .domainAttachDevice = remoteDomainAttachDevice, /* 0.3.0 */ .domainAttachDeviceFlags = remoteDomainAttachDeviceFlags, /* 0.7.7 */ .domainDetachDevice = remoteDomainDetachDevice, /* 0.3.0 */ diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index d72a60d..ef9dd10 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -848,6 +848,11 @@ struct remote_domain_undefine_args { remote_nonnull_domain dom; }; +struct remote_domain_undefine_flags_args { + remote_nonnull_domain dom; + unsigned int flags; +}; + struct remote_domain_inject_nmi_args { remote_nonnull_domain dom; unsigned int flags; @@ -2383,7 +2388,9 @@ enum remote_procedure { REMOTE_PROC_NODE_GET_CPU_STATS = 227, /* skipgen skipgen */ REMOTE_PROC_NODE_GET_MEMORY_STATS = 228, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_GET_CONTROL_INFO = 229, /* autogen autogen */ - REMOTE_PROC_DOMAIN_GET_VCPU_PIN_INFO = 230 /* skipgen skipgen */ + REMOTE_PROC_DOMAIN_GET_VCPU_PIN_INFO = 230, /* skipgen skipgen */ + + REMOTE_PROC_DOMAIN_UNDEFINE_FLAGS = 231 /* autogen autogen */ /* * Notice how the entries are grouped in sets of 10 ? diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 221562d..46f3a00 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -546,6 +546,10 @@ struct remote_domain_define_xml_ret { struct remote_domain_undefine_args { remote_nonnull_domain dom; }; +struct remote_domain_undefine_flags_args { + remote_nonnull_domain dom; + u_int flags; +}; struct remote_domain_inject_nmi_args { remote_nonnull_domain dom; u_int flags; @@ -1859,4 +1863,5 @@ enum remote_procedure { REMOTE_PROC_NODE_GET_MEMORY_STATS = 228, REMOTE_PROC_DOMAIN_GET_CONTROL_INFO = 229, REMOTE_PROC_DOMAIN_GET_VCPU_PIN_INFO = 230, + REMOTE_PROC_DOMAIN_GET_VCPU_PIN_INFO = 231, }; -- 1.7.6

On 07/19/2011 09:57 AM, Osier Yang wrote:
--- src/remote/remote_driver.c | 3 ++- src/remote/remote_protocol.x | 9 ++++++++- src/remote_protocol-structs | 5 +++++ 3 files changed, 15 insertions(+), 2 deletions(-)
ACK. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

* src/qemu/qemu_driver.c: New call back for qemu_driver, New function qemudDomainUndefineFlags, and changes on qemudDomainUndefine. --- src/qemu/qemu_driver.c | 36 +++++++++++++++++++++++++++++++++++- 1 files changed, 35 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 8870e33..1af5e1a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4311,12 +4311,18 @@ cleanup: return dom; } -static int qemudDomainUndefine(virDomainPtr dom) { +static int +qemudDomainUndefineFlags(virDomainPtr dom, + unsigned int flags) +{ struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; virDomainEventPtr event = NULL; + char *name = NULL; int ret = -1; + virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, -1); + qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -4340,6 +4346,26 @@ static int qemudDomainUndefine(virDomainPtr dom) { goto cleanup; } + name = qemuDomainManagedSavePath(driver, vm); + if (name == NULL) + goto cleanup; + + if (virFileExists(name)) { + if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE) { + if (unlink(name) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to remove domain managed " + "save image")); + goto cleanup; + } + } else { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("Refusing to undefine while domain managed " + "save image exists")); + goto cleanup; + } + } + if (virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm) < 0) goto cleanup; @@ -4354,6 +4380,7 @@ static int qemudDomainUndefine(virDomainPtr dom) { ret = 0; cleanup: + VIR_FREE(name); if (vm) virDomainObjUnlock(vm); if (event) @@ -4363,6 +4390,12 @@ cleanup: } static int +qemudDomainUndefine(virDomainPtr dom) +{ + return qemudDomainUndefineFlags(dom, 0); +} + +static int qemuDomainAttachDeviceDiskLive(struct qemud_driver *driver, virDomainObjPtr vm, virDomainDeviceDefPtr dev) @@ -8553,6 +8586,7 @@ static virDriver qemuDriver = { .domainCreateWithFlags = qemudDomainStartWithFlags, /* 0.8.2 */ .domainDefineXML = qemudDomainDefine, /* 0.2.0 */ .domainUndefine = qemudDomainUndefine, /* 0.2.0 */ + .domainUndefineFlags = qemudDomainUndefineFlags, /* 0.9.4 */ .domainAttachDevice = qemuDomainAttachDevice, /* 0.4.1 */ .domainAttachDeviceFlags = qemuDomainAttachDeviceFlags, /* 0.7.7 */ .domainDetachDevice = qemuDomainDetachDevice, /* 0.5.0 */ -- 1.7.6

On 07/19/2011 09:57 AM, Osier Yang wrote:
* src/qemu/qemu_driver.c: New call back for qemu_driver, New function qemudDomainUndefineFlags, and changes on qemudDomainUndefine. --- src/qemu/qemu_driver.c | 36 +++++++++++++++++++++++++++++++++++- 1 files changed, 35 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 8870e33..1af5e1a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4311,12 +4311,18 @@ cleanup: return dom; }
-static int qemudDomainUndefine(virDomainPtr dom) { +static int +qemudDomainUndefineFlags(virDomainPtr dom, + unsigned int flags)
s/qemudDomain/qemuDomain/
@@ -4363,6 +4390,12 @@ cleanup: }
static int +qemudDomainUndefine(virDomainPtr dom) +{ + return qemudDomainUndefineFlags(dom, 0);
Likewise.
+} + +static int qemuDomainAttachDeviceDiskLive(struct qemud_driver *driver, virDomainObjPtr vm, virDomainDeviceDefPtr dev) @@ -8553,6 +8586,7 @@ static virDriver qemuDriver = { .domainCreateWithFlags = qemudDomainStartWithFlags, /* 0.8.2 */ .domainDefineXML = qemudDomainDefine, /* 0.2.0 */ .domainUndefine = qemudDomainUndefine, /* 0.2.0 */ + .domainUndefineFlags = qemudDomainUndefineFlags, /* 0.9.4 */
Then update both of these lines to use the shorter spelling. ACK with that name change (we've been slowly migrating to the shorter name as we touch various APIs). -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

* src/libxl/libxl_driver.c: New callback for libxl_driver, new function libxlDomainUndefineFlags, and changes libxlDomainUndefine as a wrapper of libxlDomainUndefineFlags. --- src/libxl/libxl_driver.c | 33 ++++++++++++++++++++++++++++++++- 1 files changed, 32 insertions(+), 1 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index cc37d05..2e7197c 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2724,13 +2724,17 @@ cleanup: } static int -libxlDomainUndefine(virDomainPtr dom) +libxlDomainUndefineFlags(virDomainPtr dom, + unsigned int flags) { libxlDriverPrivatePtr driver = dom->conn->privateData; virDomainObjPtr vm; virDomainEventPtr event = NULL; + char *name = NULL; int ret = -1; + virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, -1); + libxlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -2755,6 +2759,25 @@ libxlDomainUndefine(virDomainPtr dom) goto cleanup; } + name = libxlDomainManagedSavePath(driver, vm); + if (name == NULL) + goto cleanup; + + if (virFileExists(name)) { + if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE) { + if (unlink(name) < 0) { + libxlError(VIR_ERR_INTERNAL_ERR, + _("Failed to remove domain managed save image")); + goto cleanup; + } + } else { + libxlError(VIR_ERR_OPERATION_INVALID, "%s", + _("Refusing to undefine while domain managed " + "save image exists")); + goto cleanup; + } + } + if (virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm) < 0) @@ -2768,6 +2791,7 @@ libxlDomainUndefine(virDomainPtr dom) ret = 0; cleanup: + VIR_FREE(name); if (vm) virDomainObjUnlock(vm); if (event) @@ -2777,6 +2801,12 @@ libxlDomainUndefine(virDomainPtr dom) } static int +libxlDomainUndefine(virDomainPtr dom) +{ + return libxlDomainUndefineFlags(dom, 0); +} + +static int libxlDomainChangeEjectableMedia(libxlDomainObjPrivatePtr priv, virDomainObjPtr vm, virDomainDiskDefPtr disk) { @@ -3836,6 +3866,7 @@ static virDriver libxlDriver = { .domainCreateWithFlags = libxlDomainCreateWithFlags, /* 0.9.0 */ .domainDefineXML = libxlDomainDefineXML, /* 0.9.0 */ .domainUndefine = libxlDomainUndefine, /* 0.9.0 */ + .domainUndefineFlags = libxlDomainUndefineFlags, /* 0.9.4 */ .domainAttachDevice = libxlDomainAttachDevice, /* 0.9.2 */ .domainAttachDeviceFlags = libxlDomainAttachDeviceFlags, /* 0.9.2 */ .domainDetachDevice = libxlDomainDetachDevice, /* 0.9.2 */ -- 1.7.6

On 07/19/2011 09:57 AM, Osier Yang wrote:
* src/libxl/libxl_driver.c: New callback for libxl_driver, new function libxlDomainUndefineFlags, and changes libxlDomainUndefine as a wrapper of libxlDomainUndefineFlags. --- src/libxl/libxl_driver.c | 33 ++++++++++++++++++++++++++++++++- 1 files changed, 32 insertions(+), 1 deletions(-)
ACK. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

--- src/esx/esx_driver.c | 11 ++++++++++- src/lxc/lxc_driver.c | 11 ++++++++++- src/openvz/openvz_driver.c | 11 ++++++++++- src/test/test_driver.c | 12 +++++++++++- src/uml/uml_driver.c | 12 +++++++++++- src/vmware/vmware_driver.c | 12 +++++++++++- src/xen/xen_driver.c | 9 ++++++++- 7 files changed, 71 insertions(+), 7 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 9b0a541..5ed6a38 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -3290,7 +3290,8 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml) static int -esxDomainUndefine(virDomainPtr domain) +esxDomainUndefineFlags(virDomainPtr domain, + unsigned int flags) { int result = -1; esxPrivate *priv = domain->conn->privateData; @@ -3299,6 +3300,8 @@ esxDomainUndefine(virDomainPtr domain) esxVI_String *propertyNameList = NULL; esxVI_VirtualMachinePowerState powerState; + virCheckFlags(0, -1); + if (priv->vCenter != NULL) { ctx = priv->vCenter; } else { @@ -3339,6 +3342,11 @@ esxDomainUndefine(virDomainPtr domain) } +static int +esxDomainUndefine(virDomainPtr domain) +{ + return esxDomainUndefineFlags(domain, 0); +} static int esxDomainGetAutostart(virDomainPtr domain, int *autostart) @@ -4747,6 +4755,7 @@ static virDriver esxDriver = { .domainCreateWithFlags = esxDomainCreateWithFlags, /* 0.8.2 */ .domainDefineXML = esxDomainDefineXML, /* 0.7.2 */ .domainUndefine = esxDomainUndefine, /* 0.7.1 */ + .domainUndefineFlags = esxDomainUndefineFlags, /* 0.9.4 */ .domainGetAutostart = esxDomainGetAutostart, /* 0.9.0 */ .domainSetAutostart = esxDomainSetAutostart, /* 0.9.0 */ .domainGetSchedulerType = esxDomainGetSchedulerType, /* 0.7.0 */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index fd1aea0..afac879 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -458,13 +458,16 @@ cleanup: return dom; } -static int lxcDomainUndefine(virDomainPtr dom) +static int lxcDomainUndefineFlags(virDomainPtr dom, + unsigned int flags) { lxc_driver_t *driver = dom->conn->privateData; virDomainObjPtr vm; virDomainEventPtr event = NULL; int ret = -1; + virCheckFlags(0, -1); + lxcDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { @@ -509,6 +512,11 @@ cleanup: return ret; } +static int lxcDomainUndefine(virDomainPtr dom) +{ + return lxcDomainUndefineFlags(dom, 0); +} + static int lxcDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { @@ -2935,6 +2943,7 @@ static virDriver lxcDriver = { .domainCreateWithFlags = lxcDomainStartWithFlags, /* 0.8.2 */ .domainDefineXML = lxcDomainDefine, /* 0.4.2 */ .domainUndefine = lxcDomainUndefine, /* 0.4.2 */ + .domainUndefineFlags = lxcDomainUndefineFlags, /* 0.9.4 */ .domainGetAutostart = lxcDomainGetAutostart, /* 0.7.0 */ .domainSetAutostart = lxcDomainSetAutostart, /* 0.7.0 */ .domainGetSchedulerType = lxcGetSchedulerType, /* 0.5.0 */ diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index cc0c590..d24a5e3 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1085,13 +1085,16 @@ openvzDomainCreate(virDomainPtr dom) } static int -openvzDomainUndefine(virDomainPtr dom) +openvzDomainUndefineFlags(virDomainPtr dom, + unsigned int flags) { struct openvz_driver *driver = dom->conn->privateData; virDomainObjPtr vm; const char *prog[] = { VZCTL, "--quiet", "destroy", PROGRAM_SENTINAL, NULL }; int ret = -1; + virCheckFlags(0, -1); + openvzDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { @@ -1123,6 +1126,11 @@ cleanup: } static int +openvzDomainUndefine(virDomainPtr dom) +{ + return openvzDomainUndefineFlags(dom, 0); +} +static int openvzDomainSetAutostart(virDomainPtr dom, int autostart) { struct openvz_driver *driver = dom->conn->privateData; @@ -1627,6 +1635,7 @@ static virDriver openvzDriver = { .domainCreateWithFlags = openvzDomainCreateWithFlags, /* 0.8.2 */ .domainDefineXML = openvzDomainDefineXML, /* 0.3.3 */ .domainUndefine = openvzDomainUndefine, /* 0.3.3 */ + .domainUndefineFlags = openvzDomainUndefineFlags, /* 0.9.4 */ .domainGetAutostart = openvzDomainGetAutostart, /* 0.4.6 */ .domainSetAutostart = openvzDomainSetAutostart, /* 0.4.6 */ .isEncrypted = openvzIsEncrypted, /* 0.7.3 */ diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 064a1cd..a68cc0d 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -2535,12 +2535,16 @@ static int testDomainCreate(virDomainPtr domain) { return testDomainCreateWithFlags(domain, 0); } -static int testDomainUndefine(virDomainPtr domain) { +static int testDomainUndefineFlags(virDomainPtr domain, + unsigned int flags) +{ testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; virDomainEventPtr event = NULL; int ret = -1; + virCheckFlags(0, -1); + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); @@ -2573,6 +2577,11 @@ cleanup: return ret; } +static int testDomainUndefine(virDomainPtr domain) +{ + return testDomainUndefineFlags(domain, 0); +} + static int testDomainGetAutostart(virDomainPtr domain, int *autostart) { @@ -5556,6 +5565,7 @@ static virDriver testDriver = { .domainCreateWithFlags = testDomainCreateWithFlags, /* 0.8.2 */ .domainDefineXML = testDomainDefineXML, /* 0.1.11 */ .domainUndefine = testDomainUndefine, /* 0.1.11 */ + .domainUndefineFlags = testDomainUndefineFlags, /* 0.9.4 */ .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */ .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */ .domainGetSchedulerType = testDomainGetSchedulerType, /* 0.3.2 */ diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 557c948..0d6f71a 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -1778,11 +1778,15 @@ cleanup: return dom; } -static int umlDomainUndefine(virDomainPtr dom) { +static int umlDomainUndefineFlags(virDomainPtr dom, + unsigned int flags) +{ struct uml_driver *driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; + virCheckFlags(0, -1); + umlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { @@ -1819,6 +1823,11 @@ cleanup: } +static int umlDomainUndefine(virDomainPtr dom) +{ + return umlDomainUndefineFlags(dom, 0); +} + static int umlDomainAttachUmlDisk(struct uml_driver *driver, virDomainObjPtr vm, virDomainDiskDefPtr disk) @@ -2427,6 +2436,7 @@ static virDriver umlDriver = { .domainCreateWithFlags = umlDomainStartWithFlags, /* 0.8.2 */ .domainDefineXML = umlDomainDefine, /* 0.5.0 */ .domainUndefine = umlDomainUndefine, /* 0.5.0 */ + .domainUndefineFlags = umlDomainUndefineFlags, /* 0.9.4 */ .domainAttachDevice = umlDomainAttachDevice, /* 0.8.4 */ .domainAttachDeviceFlags = umlDomainAttachDeviceFlags, /* 0.8.4 */ .domainDetachDevice = umlDomainDetachDevice, /* 0.8.4 */ diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index 36b48e0..7cec310 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -609,12 +609,15 @@ vmwareDomainCreate(virDomainPtr dom) } static int -vmwareDomainUndefine(virDomainPtr dom) +vmwareDomainUndefineFlags(virDomainPtr dom, + unsigned int flags) { struct vmware_driver *driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; + virCheckFlags(0, -1); + vmwareDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -650,6 +653,12 @@ vmwareDomainUndefine(virDomainPtr dom) return ret; } +static int +vmwareDomainUndefine(virDomainPtr dom) +{ + return vmwareDomainUndefineFlags(dom, 0); +} + static virDomainPtr vmwareDomainLookupByID(virConnectPtr conn, int id) { @@ -969,6 +978,7 @@ static virDriver vmwareDriver = { .domainCreateWithFlags = vmwareDomainCreateWithFlags, /* 0.8.7 */ .domainDefineXML = vmwareDomainDefineXML, /* 0.8.7 */ .domainUndefine = vmwareDomainUndefine, /* 0.8.7 */ + .domainUndefineFlags = vmwareDomainUndefineFlags, /* 0.9.4 */ .domainIsActive = vmwareDomainIsActive, /* 0.8.7 */ .domainIsPersistent = vmwareDomainIsPersistent, /* 0.8.7 */ }; diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index dd1ba6c..3b5df46 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -1527,11 +1527,12 @@ xenUnifiedDomainDefineXML (virConnectPtr conn, const char *xml) } static int -xenUnifiedDomainUndefine (virDomainPtr dom) +xenUnifiedDomainUndefineFlags (virDomainPtr dom, unsigned int flags) { GET_PRIVATE(dom->conn); int i; + virCheckFlags(0, -1); for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) if (priv->opened[i] && drivers[i]->domainUndefine && drivers[i]->domainUndefine (dom) == 0) @@ -1541,6 +1542,11 @@ xenUnifiedDomainUndefine (virDomainPtr dom) } static int +xenUnifiedDomainUndefine (virDomainPtr dom) { + return xenUnifiedDomainUndefineFlags(dom, 0); +} + +static int xenUnifiedDomainAttachDevice (virDomainPtr dom, const char *xml) { GET_PRIVATE(dom->conn); @@ -2223,6 +2229,7 @@ static virDriver xenUnifiedDriver = { .domainCreateWithFlags = xenUnifiedDomainCreateWithFlags, /* 0.8.2 */ .domainDefineXML = xenUnifiedDomainDefineXML, /* 0.1.1 */ .domainUndefine = xenUnifiedDomainUndefine, /* 0.1.1 */ + .domainUndefineFlags = xenUnifiedDomainUndefineFlags, /* 0.9.4 */ .domainAttachDevice = xenUnifiedDomainAttachDevice, /* 0.1.9 */ .domainAttachDeviceFlags = xenUnifiedDomainAttachDeviceFlags, /* 0.7.7 */ .domainDetachDevice = xenUnifiedDomainDetachDevice, /* 0.1.9 */ -- 1.7.6

On 07/19/2011 09:57 AM, Osier Yang wrote:
--- src/esx/esx_driver.c | 11 ++++++++++- src/lxc/lxc_driver.c | 11 ++++++++++- src/openvz/openvz_driver.c | 11 ++++++++++- src/test/test_driver.c | 12 +++++++++++- src/uml/uml_driver.c | 12 +++++++++++- src/vmware/vmware_driver.c | 12 +++++++++++- src/xen/xen_driver.c | 9 ++++++++- 7 files changed, 71 insertions(+), 7 deletions(-)
+++ b/src/test/test_driver.c @@ -2535,12 +2535,16 @@ static int testDomainCreate(virDomainPtr domain) { return testDomainCreateWithFlags(domain, 0); }
-static int testDomainUndefine(virDomainPtr domain) { +static int testDomainUndefineFlags(virDomainPtr domain, + unsigned int flags) +{ testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; virDomainEventPtr event = NULL; int ret = -1;
+ virCheckFlags(0, -1);
Huh, I just realized: Since these hypervisors do not support managed save in the first place, we could argue that they trivially support VIR_DOMAIN_UNDEFINE_MANAGED_SAVE (that is, they properly guarantee that all managed save files are safely deleted, since none exist in the first place). We could change all of these virCheckFlags(0, -1) into virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, -1), so that 'virsh undefine dom --managed-save' would also work on these hypervisors. I'm not sure whether to make that change though, so let's push this patch as-is, and debate about that change as a separate item. ACK. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

If the domain has managed save image, and --managed-save is not specified, then it fails with an error telling the user that a managed save image still exists. If the domain has managed save image, and --managed-save is specified, it invokes virDomainUndefineFlags. If virDomainUndefineFlags fails, then it tries to remove the managed save image using virDomainManagedSaveRemove first, with invoking virDomainUndefine following. (For compatibility between new virsh with this patch and older libvirt without this patch). Similarly if the domain has no managed save image. See the codes for detail. NOTE: Have not removing the codes checking if the domain is running in function "cmdUndefine", it will go along with qemu driver's fix (allow to undefine a running domain). --- tools/virsh.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- tools/virsh.pod | 14 ++++++++++-- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index a6803d8..e50fd8a 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1420,6 +1420,7 @@ static const vshCmdInfo info_undefine[] = { static const vshCmdOptDef opts_undefine[] = { {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name or uuid")}, + {"managed-save", VSH_OT_BOOL, 0, N_("remove domain managed state file")}, {NULL, 0, 0, NULL} }; @@ -1430,6 +1431,16 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name = NULL; int id; + int flags = 0; + int managed_save = vshCommandOptBool(cmd, "managed-save"); + int has_managed_save = 0; + int rc = -1; + + if (managed_save) + flags |= VIR_DOMAIN_UNDEFINE_MANAGED_SAVE; + + if (!managed_save) + flags = -1; if (!vshConnectionUsability(ctl, ctl->conn)) return false; @@ -1451,7 +1462,55 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) VSH_BYNAME|VSH_BYUUID))) return false; - if (virDomainUndefine(dom) == 0) { + has_managed_save = virDomainHasManagedSaveImage(dom, 0); + if (has_managed_save < 0) { + if (last_error->code != VIR_ERR_NO_SUPPORT) { + virshReportError(ctl); + virDomainFree(dom); + return false; + } else { + virFreeError(last_error); + last_error = NULL; + } + } + + if (flags == -1) { + if (has_managed_save == 1) { + vshError(ctl, + _("Refusing to undefine while domain managed save " + "image exists")); + virDomainFree(dom); + return false; + } + + rc = virDomainUndefine(dom); + } else { + rc = virDomainUndefineFlags(dom, flags); + + /* It might fail for virDomainUndefineFlags is not + * supported on older libvirt, try to undefine the + * domain with combo virDomainManagedSaveRemove and + * virDomainUndefine. + */ + if (rc < 0) { + if (last_error->code != VIR_ERR_NO_SUPPORT) { + virshReportError(ctl); + goto end; + } else { + virFreeError(last_error); + last_error = NULL; + } + + if (has_managed_save && + virDomainManagedSaveRemove(dom, 0) < 0) + goto end; + + rc = virDomainUndefine(dom); + } + } + +end: + if (rc == 0) { vshPrint(ctl, _("Domain %s has been undefined\n"), name); } else { vshError(ctl, _("Failed to undefine domain %s"), name); diff --git a/tools/virsh.pod b/tools/virsh.pod index af762ca..9cd2853 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -813,10 +813,18 @@ hypervisor. Output the device used for the TTY console of the domain. If the information is not available the processes will provide an exit code of 1. -=item B<undefine> I<domain-id> +=item B<undefine> I<domain-id> [I<--managed-save>] -Undefine the configuration for an inactive domain. Since it's not running -the domain name or UUID must be used as the I<domain-id>. +Undefine a domain. If the domain is running, this converts it to a +transient domain, without stopping it. If the domain is inactive, +the domain configuration is removed. + +The I<--managed-save> flag guarantees that any managed save image(see +the B<managedsave> command) is also cleaned up. Without the flag, attempts +to undefine a domain with a managed save image will fail. + +NOTE: For an inactive domain, the domain name or UUID must be used as the +I<domain-id>. =item B<vcpucount> I<domain-id> [{I<--maximum> | I<--current>} {I<--config> | I<--live>}] -- 1.7.6

On 07/19/2011 09:57 AM, Osier Yang wrote:
If the domain has managed save image, and --managed-save is not specified, then it fails with an error telling the user that a managed save image still exists.
If the domain has managed save image, and --managed-save is specified, it invokes virDomainUndefineFlags. If virDomainUndefineFlags fails, then it tries to remove the managed save image using virDomainManagedSaveRemove first, with invoking virDomainUndefine following. (For compatibility between new virsh with this patch and older libvirt without this patch).
Similarly if the domain has no managed save image. See the codes for detail.
NOTE: Have not removing the codes checking if the domain is running in function "cmdUndefine", it will go along with qemu driver's fix (allow to undefine a running domain). --- tools/virsh.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- tools/virsh.pod | 14 ++++++++++-- 2 files changed, 71 insertions(+), 4 deletions(-)
+ } else { + rc = virDomainUndefineFlags(dom, flags); + + /* It might fail for virDomainUndefineFlags is not
s/for/when/
+ * supported on older libvirt, try to undefine the + * domain with combo virDomainManagedSaveRemove and + * virDomainUndefine. + */ + if (rc< 0) { + if (last_error->code != VIR_ERR_NO_SUPPORT) { + virshReportError(ctl); + goto end; + } else { + virFreeError(last_error); + last_error = NULL; + } + + if (has_managed_save&&
s/has_managed_save/has_managed_save == 1/ Your earlier changes mean that you can now get here even while has_managed_save == -1 because the hypervisors lacks managed save support altogether, in which case, the virDomainManagedSaveRemove will also fail for unsupported, but the plain undefine is safe in that case. ACK with those changes. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

于 2011年07月19日 23:54, Eric Blake 写道:
On 07/19/2011 09:57 AM, Osier Yang wrote:
If the domain has managed save image, and --managed-save is not specified, then it fails with an error telling the user that a managed save image still exists.
If the domain has managed save image, and --managed-save is specified, it invokes virDomainUndefineFlags. If virDomainUndefineFlags fails, then it tries to remove the managed save image using virDomainManagedSaveRemove first, with invoking virDomainUndefine following. (For compatibility between new virsh with this patch and older libvirt without this patch).
Similarly if the domain has no managed save image. See the codes for detail.
NOTE: Have not removing the codes checking if the domain is running in function "cmdUndefine", it will go along with qemu driver's fix (allow to undefine a running domain). --- tools/virsh.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- tools/virsh.pod | 14 ++++++++++-- 2 files changed, 71 insertions(+), 4 deletions(-)
+ } else { + rc = virDomainUndefineFlags(dom, flags); + + /* It might fail for virDomainUndefineFlags is not
s/for/when/
+ * supported on older libvirt, try to undefine the + * domain with combo virDomainManagedSaveRemove and + * virDomainUndefine. + */ + if (rc< 0) { + if (last_error->code != VIR_ERR_NO_SUPPORT) { + virshReportError(ctl); + goto end; + } else { + virFreeError(last_error); + last_error = NULL; + } + + if (has_managed_save&&
s/has_managed_save/has_managed_save == 1/
Your earlier changes mean that you can now get here even while has_managed_save == -1 because the hypervisors lacks managed save support altogether, in which case, the virDomainManagedSaveRemove will also fail for unsupported, but the plain undefine is safe in that case.
ACK with those changes.
Thanks for the reviewing, pushed the whole series with the small nits fixed, ([PATCH v4 5/6] is pushed as is). Regards Osier
participants (2)
-
Eric Blake
-
Osier Yang