[libvirt] [PATCH v2 0/8] Introduce New API virDomainUndefineFlags

Per discussion on https://www.redhat.com/archives/libvir-list/2011-July/msg00556.html, This patch series introduce new API virDomainUndefineFlags, which only support flag VIR_DOMAIN_UNDEFINE_MANAGED_STATE now, might introduce more flags in future though. If the domain has a managed state file, then including VIR_DOMAIN_UNDEFINE_MANAGED_STATE in @flags will also remove that file, and omitting the flag will cause the undefine process to fail. This also changes the behavior of virDomainUndefine, but considering undefine a domain with managed state file left is unsafe, we need to do so. [PATCH v2 1/8] is small fix on rpc generator scripts, not related with the new API. [PATCH v2 1/8] rpc: Fix typos in rpc generator scripts [PATCH v2 2/8] undefine: Define the new API [PATCH v2 3/8] undefine: Wire up the remote protocol [PATCH v2 4/8] undefine: Implement internal API for qemu driver [PATCH v2 5/8] undefine: Implement internal API for libxl driver [PATCH v2 6/8] undefine: Implement undefineFlags in all other [PATCH v2 7/8] undefine: Extend virsh undefine to support the new [PATCH v2 8/8] virsh: Extend virsh dominfo to display if managed v1 - v2: * s/virDomainUndefineWithFlags/virDomainUndefineFlags/ * Update with other bunch of feedbacks from Eric * Changes on virsh dominfo to display if domain managed state exists Regards Osier

These typos are introduced by file renaming in commit b17b4afaf. src/remote/qemu_protocol.x \ src/remote/remote_protocol.x \ src/rpc/gendispatch.pl: s/remote_generator/gendispatch/ src/rpc/genprotocol.pl: s/remote\/remote_protocol/remote_protocol/ --- src/remote/qemu_protocol.x | 2 +- src/remote/remote_protocol.x | 6 +++--- src/rpc/gendispatch.pl | 6 +++--- src/rpc/genprotocol.pl | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/remote/qemu_protocol.x b/src/remote/qemu_protocol.x index 0bafbaf..3279405 100644 --- a/src/remote/qemu_protocol.x +++ b/src/remote/qemu_protocol.x @@ -53,7 +53,7 @@ const QEMU_PROTOCOL_VERSION = 1; enum qemu_procedure { /* Each function must have a two-word comment. The first word is - * whether remote_generator.pl handles daemon, the second whether + * whether gendispatch.pl handles daemon, the second whether * it handles src/remote. */ QEMU_PROC_MONITOR_COMMAND = 1, /* skipgen skipgen */ QEMU_PROC_DOMAIN_ATTACH = 2 /* autogen autogen */ diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index ee169fd..d72a60d 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -339,7 +339,7 @@ struct remote_node_get_memory_stats { * connection). Errors are returned implicitly in the RPC protocol. * * Please follow the naming convention carefully - this file is - * parsed by 'remote_generator.pl'. + * parsed by 'gendispatch.pl'. * * 'remote_CALL_ret' members that are filled via call-by-reference must be * annotated with a insert@<offset> comment to indicate the offset in the @@ -2123,7 +2123,7 @@ const REMOTE_PROTOCOL_VERSION = 1; enum remote_procedure { /* Each function must have a two-word comment. The first word is - * whether remote_generator.pl handles daemon, the second whether + * whether gendispatch.pl handles daemon, the second whether * it handles src/remote. Additional flags can be specified after a * pipe. * @@ -2390,7 +2390,7 @@ enum remote_procedure { * Nice isn't it. Please keep it this way when adding more. * * Each function must have a two-word comment. The first word is - * whether remote_generator.pl handles daemon, the second whether + * whether gendispatch.pl handles daemon, the second whether * it handles src/remote. Additional flags can be specified after a * pipe. * diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl index 85a0c0e..e068b53 100755 --- a/src/rpc/gendispatch.pl +++ b/src/rpc/gendispatch.pl @@ -9,8 +9,8 @@ # for both remote_protocol.x and qemu_protocol.x, you would run the # following: # -# remote_generator.pl -c -t remote ../src/remote/remote_protocol.x -# remote_generator.pl -t qemu ../src/remote/qemu_protocol.x +# gendispatch.pl -c -t remote ../src/remote/remote_protocol.x +# gendispatch.pl -t qemu ../src/remote/qemu_protocol.x # # By Richard Jones <rjones@redhat.com> # Extended by Matthias Bolte <matthias.bolte@googlemail.com> @@ -239,7 +239,7 @@ sub hyper_to_long # Output print <<__EOF__; -/* Automatically generated by remote_generator.pl. +/* Automatically generated by gendispatch.pl. * Do not edit this file. Any changes you make will be lost. */ __EOF__ diff --git a/src/rpc/genprotocol.pl b/src/rpc/genprotocol.pl index 4edba98..7124e5c 100755 --- a/src/rpc/genprotocol.pl +++ b/src/rpc/genprotocol.pl @@ -59,7 +59,7 @@ while (<RPCGEN>) { s/xdr_u_quad_t/xdr_uint64_t/g; s/xdr_quad_t/xdr_int64_t/g; s/(?<!IXDR_GET_INT32 )IXDR_GET_LONG/IXDR_GET_INT32/g; - s,#include "\./remote/remote_protocol\.h",#include "remote_protocol.h",; + s,#include "remote/remote_protocol\.h",#include "remote_protocol.h",; if (m/^}/) { $in_function = 0; -- 1.7.6

On 07/15/2011 03:06 AM, Osier Yang wrote:
These typos are introduced by file renaming in commit b17b4afaf.
src/remote/qemu_protocol.x \ src/remote/remote_protocol.x \ src/rpc/gendispatch.pl: s/remote_generator/gendispatch/
src/rpc/genprotocol.pl: s/remote\/remote_protocol/remote_protocol/ --- src/remote/qemu_protocol.x | 2 +- src/remote/remote_protocol.x | 6 +++--- src/rpc/gendispatch.pl | 6 +++--- src/rpc/genprotocol.pl | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-)
No change from v1 ACK, you can go ahead and push this now, regardless of how the rest of the review goes. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

? 2011?07?16? 03:53, Eric Blake ??:
n 07/15/2011 03:06 AM, Osier Yang wrote:
These typos are introduced by file renaming in commit b17b4afaf.
src/remote/qemu_protocol.x \ src/remote/remote_protocol.x \ src/rpc/gendispatch.pl: s/remote_generator/gendispatch/
src/rpc/genprotocol.pl: s/remote\/remote_protocol/remote_protocol/ Thanks, pushed
Osier

This introduce a new API virDomainUndefineFlags to control the domain undefine process, as the existed API virDomainUndefine doesn't support flags. Currently only flag VIR_DOMAIN_UNDEFINE_MANAGED_STATE is supported. If the domain has a managed state file, including VIR_DOMAIN_UNDEFINE_MANAGED_STATE 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 state file, the undefine will be refused. --- include/libvirt/libvirt.h.in | 10 +++++++ src/driver.h | 4 +++ src/libvirt.c | 56 +++++++++++++++++++++++++++++++++++++++++- src/libvirt_public.syms | 5 +++ 4 files changed, 74 insertions(+), 1 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index d5a7105..c69a48e 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_STATE = 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 70ea4c2..0c3bcfc 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 @@ -732,6 +735,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 7e70caa..3e1a0ff 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -6376,7 +6376,11 @@ error: * virDomainUndefine: * @domain: pointer to a defined domain * - * Undefine a domain but does not stop it if it is running + * Undefine the configuration for an inactive domain. + * + * If the domain has a managed state file (see + * virDomainHasManagedSaveImage()), then the undefine will fail. See + * virDomainUndefineFlags() for more control. * * Returns 0 in case of success, -1 in case of error */ @@ -6415,6 +6419,56 @@ error: } /** + * virDomainUndefineFlags: + * @domain: pointer to a defined domain + * @flags: bitwise-or of supported virDomainUndefineFlagsValues + * + * Undefine the configuration for an inactive domain. + * + * If the domain has a managed state file (see virDomainHasManagedSaveImage()), + * then including VIR_DOMAIN_UNDEFINE_MANAGED_STATE 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/15/2011 03:06 AM, Osier Yang wrote:
This introduce a new API virDomainUndefineFlags to control the
s/introduce/introduces/
domain undefine process, as the existed API virDomainUndefine
s/existed/existing/
doesn't support flags.
Currently only flag VIR_DOMAIN_UNDEFINE_MANAGED_STATE is supported. If the domain has a managed state file, including VIR_DOMAIN_UNDEFINE_MANAGED_STATE 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 state file, the undefine will be refused.
I also just realized that this is the right change, because by default, libvirt should never allow data loss without explicit action. If a domain has managed state and libvirt were to silently delete the file, then you have lost the data that was in memory at the time the managed state file was created. And undefining a domain while leaving the state file behind opens the door for some other domain to be created and clobber the state file, which is also data loss. So even though it is a semantic change to refuse to delete a domain with managed save data, it fixes a data loss bug so it is the right thing to do.
+++ b/src/libvirt.c @@ -6376,7 +6376,11 @@ error: * virDomainUndefine: * @domain: pointer to a defined domain * - * Undefine a domain but does not stop it if it is running + * Undefine the configuration for an inactive domain.
Per the discussion in related threads, we want this to read more like: Undefine a domain. If the domain is running, this converts it to a transient domain, without halting the guest. If the domain is inactive, this removes all traces of the domain.
+ * + * If the domain has a managed state file (see + * virDomainHasManagedSaveImage()), then the undefine will fail. See + * virDomainUndefineFlags() for more control. * * Returns 0 in case of success, -1 in case of error */ @@ -6415,6 +6419,56 @@ error: }
/** + * virDomainUndefineFlags: + * @domain: pointer to a defined domain + * @flags: bitwise-or of supported virDomainUndefineFlagsValues + * + * Undefine the configuration for an inactive domain.
Same paragraph change as for virDomainUndefine. ACK with those paragraphs changed (and we'll have to fix qemu behavior in a later patch). -- 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 | 4 ++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index a2c62ba..1acef17 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. @@ -4178,6 +4178,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 b2de8e9..a40bc78 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -533,6 +533,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; -- 1.7.6

On 07/15/2011 03:06 AM, Osier Yang wrote:
--- src/remote/remote_driver.c | 3 ++- src/remote/remote_protocol.x | 9 ++++++++- src/remote_protocol-structs | 4 ++++ 3 files changed, 14 insertions(+), 2 deletions(-)
+++ b/src/remote_protocol-structs @@ -533,6 +533,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;
ACK, but be sure to run 'make check' before committing, because you'll have to add a line to remote_protocol-structs if I get my enum-checking patch pushed first. -- 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 | 35 ++++++++++++++++++++++++++++++++++- 1 files changed, 34 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 3d4207e..0bf135d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4303,12 +4303,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_STATE, -1); + qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -4332,6 +4338,25 @@ 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_STATE) + && (unlink(name) < 0)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed on removing domain managed " + "state file '%s'"), name); + goto cleanup; + } else { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Refusing to undefine with managed state " + "file '%s' exists"), name); + goto cleanup; + } + } + if (virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm) < 0) goto cleanup; @@ -4346,6 +4371,7 @@ static int qemudDomainUndefine(virDomainPtr dom) { ret = 0; cleanup: + VIR_FREE(name); if (vm) virDomainObjUnlock(vm); if (event) @@ -4355,6 +4381,12 @@ cleanup: } static int +qemudDomainUndefine(virDomainPtr dom) +{ + return qemudDomainUndefineFlags(dom, 0); +} + +static int qemuDomainAttachDeviceDiskLive(struct qemud_driver *driver, virDomainObjPtr vm, virDomainDeviceDefPtr dev) @@ -8599,6 +8631,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/15/2011 03:06 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 | 35 ++++++++++++++++++++++++++++++++++- 1 files changed, 34 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 3d4207e..0bf135d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4303,12 +4303,18 @@ cleanup: return dom; }
-static int qemudDomainUndefine(virDomainPtr dom) { +static int +qemudDomainUndefineFlags(virDomainPtr dom, + unsigned int flags)
As long as we're touching this, s/qemudDomain/qemuDomain/
+ name = qemuDomainManagedSavePath(driver, vm); + if (name == NULL) + goto cleanup; + + if (virFileExists(name)) { + if ((flags & VIR_DOMAIN_UNDEFINE_MANAGED_STATE) + && (unlink(name) < 0)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed on removing domain managed "
Grammar.
+ "state file '%s'"), name);
No need to expose our internal file name details to the user.
+ goto cleanup; + } else { + qemuReportError(VIR_ERR_INTERNAL_ERROR,
Not an internal error.
+ _("Refusing to undefine with managed state " + "file '%s' exists"), name);
Grammar.
+ goto cleanup; + }
Logic bug. This fails with "Refusing to undefine" if the unlink() succeeds. Rather, you want: if (virFileExists(name)) { if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_STATE) { if (unlink(name) < 0) { virReportSystemError(errno, "%s", _("Failed to remove managed state for domain")); goto cleanup; } } else { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Refusing to undefine domain with managed state")); goto cleanup; } } Needs a v3. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

于 2011年07月16日 05:24, Eric Blake 写道:
On 07/15/2011 03:06 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 | 35 ++++++++++++++++++++++++++++++++++- 1 files changed, 34 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 3d4207e..0bf135d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4303,12 +4303,18 @@ cleanup: return dom; }
-static int qemudDomainUndefine(virDomainPtr dom) { +static int +qemudDomainUndefineFlags(virDomainPtr dom, + unsigned int flags) As long as we're touching this, s/qemudDomain/qemuDomain/
+ name = qemuDomainManagedSavePath(driver, vm); + if (name == NULL) + goto cleanup; + + if (virFileExists(name)) { + if ((flags& VIR_DOMAIN_UNDEFINE_MANAGED_STATE) +&& (unlink(name)< 0)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed on removing domain managed " Grammar.
+ "state file '%s'"), name); No need to expose our internal file name details to the user.
+ goto cleanup; + } else { + qemuReportError(VIR_ERR_INTERNAL_ERROR, Not an internal error.
+ _("Refusing to undefine with managed state " + "file '%s' exists"), name); Grammar.
+ goto cleanup; + } Logic bug. This fails with "Refusing to undefine" if the unlink() succeeds. Rather, you want:
I changed this before posting, but sent the old patch without the change mistakenly. :(
if (virFileExists(name)) { if (flags& VIR_DOMAIN_UNDEFINE_MANAGED_STATE) { if (unlink(name)< 0) { virReportSystemError(errno, "%s", _("Failed to remove managed state for domain")); goto cleanup; } } else { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Refusing to undefine domain with managed state")); goto cleanup; } }
Needs a v3.

* 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 8d54e58..0310b45 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 +qemuDomainUndefineFlags(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_STATE, -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_STATE) { + 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 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 qemuDomainUndefineFlags(dom, 0); +} + +static int qemuDomainAttachDeviceDiskLive(struct qemud_driver *driver, virDomainObjPtr vm, virDomainDeviceDefPtr dev) @@ -8550,6 +8583,7 @@ static virDriver qemuDriver = { .domainCreateWithFlags = qemudDomainStartWithFlags, /* 0.8.2 */ .domainDefineXML = qemudDomainDefine, /* 0.2.0 */ .domainUndefine = qemudDomainUndefine, /* 0.2.0 */ + .domainUndefineFlags = qemuDomainUndefineFlags, /* 0.9.4 */ .domainAttachDevice = qemuDomainAttachDevice, /* 0.4.1 */ .domainAttachDeviceFlags = qemuDomainAttachDeviceFlags, /* 0.7.7 */ .domainDetachDevice = qemuDomainDetachDevice, /* 0.5.0 */ -- 1.7.6

On 07/18/2011 01:52 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(-)
+qemuDomainUndefineFlags(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_STATE, -1);
Still not sure if we should have named the flag VIR_DOMAIN_UNDEFINE_MANAGED_SAVE in patch 2. But that's a naming nit, with obvious fallout for the entire series if we adjust that name. ACK to this patch. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

This is just similiar as changes on qemu driver. * 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 | 31 ++++++++++++++++++++++++++++++- 1 files changed, 30 insertions(+), 1 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index f938e24..b474eb9 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2722,11 +2722,13 @@ 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; libxlDriverLock(driver); @@ -2753,6 +2755,25 @@ libxlDomainUndefine(virDomainPtr dom) goto cleanup; } + name = libxlDomainManagedSavePath(driver, vm); + if (name == NULL) + goto cleanup; + + if (virFileExists(name)) { + if ((flags & VIR_DOMAIN_UNDEFINE_MANAGED_STATE) && + (unlink(name) < 0)) { + libxlError(VIR_ERR_INTERNAL_ERR, + _("Failed on removing domain managed state " + "file '%s'"), name); + goto cleanup; + } else { + libxlError(VIR_ERR_INTERNAL_ERR, + _("Refusing to undefine with managed state " + "file '%s' exists"), name); + goto cleanup; + } + } + if (virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm) < 0) @@ -2766,6 +2787,7 @@ libxlDomainUndefine(virDomainPtr dom) ret = 0; cleanup: + VIR_FREE(name); if (vm) virDomainObjUnlock(vm); if (event) @@ -2775,6 +2797,12 @@ libxlDomainUndefine(virDomainPtr dom) } static int +libxlDomainUndefine(virDomainPtr dom) +{ + return libxlDomainUndefineFlags(dom, 0); +} + +static int libxlDomainChangeEjectableMedia(libxlDomainObjPrivatePtr priv, virDomainObjPtr vm, virDomainDiskDefPtr disk) { @@ -3834,6 +3862,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/15/2011 03:06 AM, Osier Yang wrote:
This is just similiar as changes on qemu driver.
* 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 | 31 ++++++++++++++++++++++++++++++- 1 files changed, 30 insertions(+), 1 deletions(-)
And with the same logic bug. :(
+ if (virFileExists(name)) { + if ((flags & VIR_DOMAIN_UNDEFINE_MANAGED_STATE) && + (unlink(name) < 0)) { + libxlError(VIR_ERR_INTERNAL_ERR, + _("Failed on removing domain managed state " + "file '%s'"), name); + goto cleanup; + } else { + libxlError(VIR_ERR_INTERNAL_ERR, + _("Refusing to undefine with managed state " + "file '%s' exists"), name); + goto cleanup; + } + }
-- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

This is just similiar as changes on qemu driver. * 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 | 34 +++++++++++++++++++++++++++++++++- 1 files changed, 33 insertions(+), 1 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index cc37d05..0bbf113 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,26 @@ 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, "%s", + _("Failed to remove domain managed save " + "image")); + goto cleanup; + } + } else { + libxlError(VIR_ERR_OPERATION_INVALID, "%s", + _("Refuse to undefine while managed save " + "image exists")); + goto cleanup; + } + } + if (virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm) < 0) @@ -2768,6 +2792,7 @@ libxlDomainUndefine(virDomainPtr dom) ret = 0; cleanup: + VIR_FREE(name); if (vm) virDomainObjUnlock(vm); if (event) @@ -2777,6 +2802,12 @@ libxlDomainUndefine(virDomainPtr dom) } static int +libxlDomainUndefine(virDomainPtr dom) +{ + return libxlDomainUndefineFlags(dom, 0); +} + +static int libxlDomainChangeEjectableMedia(libxlDomainObjPrivatePtr priv, virDomainObjPtr vm, virDomainDiskDefPtr disk) { @@ -3836,6 +3867,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/18/2011 01:53 AM, Osier Yang wrote:
This is just similiar as changes on qemu driver.
* 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 | 34 +++++++++++++++++++++++++++++++++- 1 files changed, 33 insertions(+), 1 deletions(-)
ACK.
+ char *name = NULL; int ret = -1;
+ virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, -1);
Oh, here you went with MANAGED_SAVE, instead of MANAGED_STATE in patch 4/8 v3. Double check that each patch in your series compiles cleanly before pushing. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

于 2011年07月19日 02:43, Eric Blake 写道:
On 07/18/2011 01:53 AM, Osier Yang wrote:
This is just similiar as changes on qemu driver.
* 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 | 34 +++++++++++++++++++++++++++++++++- 1 files changed, 33 insertions(+), 1 deletions(-)
ACK.
+ char *name = NULL; int ret = -1;
+ virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, -1);
Oh, here you went with MANAGED_SAVE, instead of MANAGED_STATE in patch 4/8 v3. Double check that each patch in your series compiles cleanly before pushing.
I'm creating a whole v4 series (without the patch for virsh dominfo), in case of I miss something again, I'm always careless. :( Osier

Add domainUndefineFlags support for these drivers (except qemu and libxl driver), and changes domainUndefine as a wrapper of domainUndefineFlags, but they actually perform same. --- 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 4643a32..b3bdf1d 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -3280,7 +3280,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; @@ -3289,6 +3290,8 @@ esxDomainUndefine(virDomainPtr domain) esxVI_String *propertyNameList = NULL; esxVI_VirtualMachinePowerState powerState; + virCheckFlags(0, -1); + if (priv->vCenter != NULL) { ctx = priv->vCenter; } else { @@ -3329,6 +3332,11 @@ esxDomainUndefine(virDomainPtr domain) } +static int +esxDomainUndefine(virDomainPtr domain) +{ + esxDomainUndefineFlags(domain, 0); +} static int esxDomainGetAutostart(virDomainPtr domain, int *autostart) @@ -4725,6 +4733,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 b6da757..3dddf2a 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) { @@ -2931,6 +2939,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 d50ecf1..c1147c3 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1083,13 +1083,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) { @@ -1121,6 +1124,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; @@ -1625,6 +1633,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 f3fb320..bcb409d 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -2533,12 +2533,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); @@ -2571,6 +2575,11 @@ cleanup: return ret; } +static int testDomainUndefine(virDomainPtr domain) +{ + return testDomainUndefineFlags(domain, 0); +} + static int testDomainGetAutostart(virDomainPtr domain, int *autostart) { @@ -5554,6 +5563,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 6eede55..2f7ff63 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -1706,11 +1706,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) { @@ -1747,6 +1751,11 @@ cleanup: } +static int umlDomainUndefine(virDomainPtr dom) +{ + return umlDomainUndefineFlags(dom, 0); +} + static int umlDomainAttachUmlDisk(struct uml_driver *driver, virDomainObjPtr vm, virDomainDiskDefPtr disk) @@ -2238,6 +2247,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 c0430fe..14e49d3 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -609,11 +609,14 @@ 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) { @@ -967,6 +976,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 1d75da3..571922e 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -1517,11 +1517,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) @@ -1531,6 +1532,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); @@ -2211,6 +2217,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/15/2011 03:06 AM, Osier Yang wrote:
Add domainUndefineFlags support for these drivers (except qemu and libxl driver), and changes domainUndefine as a wrapper of domainUndefineFlags, but they actually perform same. --- 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(-)
@@ -3329,6 +3332,11 @@ esxDomainUndefine(virDomainPtr domain) }
+static int +esxDomainUndefine(virDomainPtr domain) +{ + esxDomainUndefineFlags(domain, 0);
Missing a return keyword. I'm guessing you aren't set up to compile-test ESX. ACK with that fixed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

If the domain has managed state file, and --managed-state is not specified, then it fails with error prompt to tell user there is managed state file exists. And the domain has managed state file, and --managed-state is specified, it invokes virDomainUndefineFlags, if virDomainUndefineFlag fails, then it trys to remove the managed state file using virDomainManagedSaveRemove first, with invoking virDomainUndefine following. (For compatibility between new virsh with this patch and older libvirt without this fix) Simliar if the domain has no managed state. See the codes for detail. --- tools/virsh.c | 44 +++++++++++++++++++++++++++++++++++++++++++- tools/virsh.pod | 6 +++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 4af8fea..8a62612 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1409,6 +1409,7 @@ static const vshCmdInfo info_undefine[] = { static const vshCmdOptDef opts_undefine[] = { {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name or uuid")}, + {"managed-state", VSH_OT_BOOL, 0, N_("remove domain managed state file")}, {NULL, 0, 0, NULL} }; @@ -1419,6 +1420,16 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name = NULL; int id; + int flags = 0; + int managed_state = vshCommandOptBool(cmd, "managed-state"); + int has_managed_state = 0; + int rc = -1; + + if (managed_state) + flags |= VIR_DOMAIN_UNDEFINE_MANAGED_STATE; + + if (!managed_state) + flags = -1; if (!vshConnectionUsability(ctl, ctl->conn)) return false; @@ -1440,7 +1451,37 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) VSH_BYNAME|VSH_BYUUID))) return false; - if (virDomainUndefine(dom) == 0) { + has_managed_state = virDomainHasManagedSaveImage(dom, 0); + if (has_managed_state < 0) + return false; + + if (flags == -1) { + if (has_managed_state == 1) { + vshError(ctl, + _("Refusing to undefine with managed state " + "file exists")); + 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 (has_managed_state && + virDomainManagedSaveRemove(dom, 0) < 0) + return false; + + rc = virDomainUndefine(dom); + } + } + + if (rc == 0) { vshPrint(ctl, _("Domain %s has been undefined\n"), name); } else { vshError(ctl, _("Failed to undefine domain %s"), name); @@ -2424,6 +2465,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) VIR_FREE(seclabel); } } + virDomainFree(dom); return ret; } diff --git a/tools/virsh.pod b/tools/virsh.pod index 52f1549..68cc484 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -805,11 +805,15 @@ 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-state> 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>. +The I<--managed-save> flag guarantees that any managed state (see the +B<managesave> command) is also cleaned up. Without the flag, attempts +to undefine a domain with managed state will fail. + =item B<vcpucount> I<domain-id> optional I<--maximum> I<--current> I<--config> I<--live> -- 1.7.6

On 07/15/2011 03:06 AM, Osier Yang wrote:
If the domain has managed state file, and --managed-state is not specified, then it fails with error prompt to tell user there is managed state file exists.
Grammar suggestion: then it fails with an error telling the user that a managed save still exists. Hmm, I'm now having second thoughts about the names "VIR_DOMAIN_UNDEFINE_MANAGED_STATE" and "--managed-state", since the name of the API is virDomainManagedSave and the virsh command is managedsave. Would it be better to go with: VIR_DOMAIN_UNDEFINE_MANAGED_SAVE and --managed-save? This would mean tweaking the earlier patches in this series.
And the domain has managed state file, and --managed-state is
s/And/If/
specified, it invokes virDomainUndefineFlags, if virDomainUndefineFlag fails, then it trys to remove the managed
s/trys/tries/
state file using virDomainManagedSaveRemove first, with invoking virDomainUndefine following. (For compatibility between new virsh with this patch and older libvirt without this fix)
Simliar if the domain has no managed state. See the codes for
s/Simliar/Similarly/
detail. --- tools/virsh.c | 44 +++++++++++++++++++++++++++++++++++++++++++- tools/virsh.pod | 6 +++++- 2 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c index 4af8fea..8a62612 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1409,6 +1409,7 @@ static const vshCmdInfo info_undefine[] = {
static const vshCmdOptDef opts_undefine[] = { {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name or uuid")}, + {"managed-state", VSH_OT_BOOL, 0, N_("remove domain managed state file")},
s/state/save/g, given my above thoughts.
{NULL, 0, 0, NULL} };
@@ -1419,6 +1420,16 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name = NULL; int id; + int flags = 0; + int managed_state = vshCommandOptBool(cmd, "managed-state"); + int has_managed_state = 0; + int rc = -1; + + if (managed_state) + flags |= VIR_DOMAIN_UNDEFINE_MANAGED_STATE; + + if (!managed_state) + flags = -1;
I'm not sure if you need this line. Instead...
if (!vshConnectionUsability(ctl, ctl->conn)) return false; @@ -1440,7 +1451,37 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) VSH_BYNAME|VSH_BYUUID))) return false;
- if (virDomainUndefine(dom) == 0) { + has_managed_state = virDomainHasManagedSaveImage(dom, 0); + if (has_managed_state < 0) + return false; + + if (flags == -1) {
...this conditional can just be if (!managed_state)
+ if (has_managed_state == 1) { + vshError(ctl, + _("Refusing to undefine with managed state " + "file exists"));
Grammar: Refusing to undefine while managed save image exists
+ 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) {
Here, we should optimize by checking the error. If the error is VIR_ERR_NO_SUPPORT, then we go with the fallback; but if it is anything else, then virDomainUndefineFlags exists but failed, and the fallback would also fail, so give up now.
+ if (has_managed_state && + virDomainManagedSaveRemove(dom, 0) < 0) + return false;
This early return...
+ + rc = virDomainUndefine(dom); + } + } + + if (rc == 0) { vshPrint(ctl, _("Domain %s has been undefined\n"), name); } else { vshError(ctl, _("Failed to undefine domain %s"), name);
...will lose out on this error message.
-=item B<undefine> I<domain-id> +=item B<undefine> I<domain-id> I<--managed-state>
managed-state (or managed-save, whatever we name it) is optional, so this should be: =item B<undefine> I<domain-id> [I<--managed-state>]
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>.
+The I<--managed-save> flag guarantees that any managed state (see the +B<managesave> command) is also cleaned up. Without the flag, attempts
s/managesave/managedsave/
+to undefine a domain with managed state will fail. + =item B<vcpucount> I<domain-id> optional I<--maximum> I<--current> I<--config> I<--live>
Probably needs a v3. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

于 2011年07月16日 05:40, Eric Blake 写道:
On 07/15/2011 03:06 AM, Osier Yang wrote:
If the domain has managed state file, and --managed-state is not specified, then it fails with error prompt to tell user there is managed state file exists. Grammar suggestion:
then it fails with an error telling the user that a managed save still exists.
Hmm, I'm now having second thoughts about the names "VIR_DOMAIN_UNDEFINE_MANAGED_STATE" and "--managed-state", since the name of the API is virDomainManagedSave and the virsh command is managedsave. Would it be better to go with:
VIR_DOMAIN_UNDEFINE_MANAGED_SAVE and --managed-save? This would mean tweaking the earlier patches in this series.
And the domain has managed state file, and --managed-state is s/And/If/
specified, it invokes virDomainUndefineFlags, if virDomainUndefineFlag fails, then it trys to remove the managed s/trys/tries/
state file using virDomainManagedSaveRemove first, with invoking virDomainUndefine following. (For compatibility between new virsh with this patch and older libvirt without this fix)
Simliar if the domain has no managed state. See the codes for s/Simliar/Similarly/
detail. --- tools/virsh.c | 44 +++++++++++++++++++++++++++++++++++++++++++- tools/virsh.pod | 6 +++++- 2 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c index 4af8fea..8a62612 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1409,6 +1409,7 @@ static const vshCmdInfo info_undefine[] = {
static const vshCmdOptDef opts_undefine[] = { {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name or uuid")}, + {"managed-state", VSH_OT_BOOL, 0, N_("remove domain managed state file")}, s/state/save/g, given my above thoughts.
{NULL, 0, 0, NULL} };
@@ -1419,6 +1420,16 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name = NULL; int id; + int flags = 0; + int managed_state = vshCommandOptBool(cmd, "managed-state"); + int has_managed_state = 0; + int rc = -1; + + if (managed_state) + flags |= VIR_DOMAIN_UNDEFINE_MANAGED_STATE; + + if (!managed_state) + flags = -1;
I'm not sure if you need this line. Instead...
This is for future use, we might introduce more flags. Such as VIR_DOMAIN_UNDEFINE_SNAPSHOTS, VIR_DOMAIN_UNDEFINE_IMAGES.
if (!vshConnectionUsability(ctl, ctl->conn)) return false; @@ -1440,7 +1451,37 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) VSH_BYNAME|VSH_BYUUID))) return false;
- if (virDomainUndefine(dom) == 0) { + has_managed_state = virDomainHasManagedSaveImage(dom, 0); + if (has_managed_state< 0) + return false; + + if (flags == -1) {
...this conditional can just be if (!managed_state)
And this.
+ if (has_managed_state == 1) { + vshError(ctl, + _("Refusing to undefine with managed state " + "file exists")); Grammar:
Refusing to undefine while managed save image exists
+ 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) { Here, we should optimize by checking the error. If the error is VIR_ERR_NO_SUPPORT, then we go with the fallback; but if it is anything else, then virDomainUndefineFlags exists but failed, and the fallback would also fail, so give up now.
+ if (has_managed_state&& + virDomainManagedSaveRemove(dom, 0)< 0) + return false; This early return...
+ + rc = virDomainUndefine(dom); + } + } + + if (rc == 0) { vshPrint(ctl, _("Domain %s has been undefined\n"), name); } else { vshError(ctl, _("Failed to undefine domain %s"), name); ...will lose out on this error message.
-=item B<undefine> I<domain-id> +=item B<undefine> I<domain-id> I<--managed-state>
managed-state (or managed-save, whatever we name it) is optional, so this should be:
=item B<undefine> I<domain-id> [I<--managed-state>]
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>.
+The I<--managed-save> flag guarantees that any managed state (see the +B<managesave> command) is also cleaned up. Without the flag, attempts
s/managesave/managedsave/
+to undefine a domain with managed state will fail. + =item B<vcpucount> I<domain-id> optional I<--maximum> I<--current> I<--config> I<--live>
Probably needs a v3.
Agree with the other comments.

If the domain has managed state file, and --managed-state is not specified, then it fails with an error telling the user that a managed save image still exists. If the domain has managed state file, and --managed-state 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 state. 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 | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- tools/virsh.pod | 14 +++++++++++--- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index e75a249..06eff0e 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; @@ -1447,11 +1458,50 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) virDomainFree(dom); return false; } + if (!(dom = vshCommandOptDomainBy(ctl, cmd, &name, VSH_BYNAME|VSH_BYUUID))) return false; - if (virDomainUndefine(dom) == 0) { + has_managed_save = virDomainHasManagedSaveImage(dom, 0); + if (has_managed_save < 0) { + virDomainFree(dom); + return false; + } + + 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) { + virErrorPtr err = virGetLastError(); + if (err && err->code != VIR_ERR_NO_SUPPORT) + goto end; + + 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); @@ -2436,6 +2486,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) VIR_FREE(seclabel); } } + virDomainFree(dom); return ret; } diff --git a/tools/virsh.pod b/tools/virsh.pod index 2d65cf9..377fac0 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -807,10 +807,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> optional 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 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> optional I<--maximum> I<--current> I<--config> I<--live> -- 1.7.6

On 07/18/2011 01:54 AM, Osier Yang wrote:
If the domain has managed state file, and --managed-state is not specified, then it fails with an error telling the user that a managed save image still exists.
Commit message is now out of date with the code, where you renamed things --managed-save.
If the domain has managed state file, and --managed-state 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 state. 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).
Makes sense; after all, that's a separate fix.
@@ -1447,11 +1458,50 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) virDomainFree(dom); return false; } + if (!(dom = vshCommandOptDomainBy(ctl, cmd,&name, VSH_BYNAME|VSH_BYUUID))) return false;
- if (virDomainUndefine(dom) == 0) { + has_managed_save = virDomainHasManagedSaveImage(dom, 0); + if (has_managed_save< 0) { + virDomainFree(dom); + return false; + }
Not quite right. If last_error->code == VIR_ERR_NO_SUPPORT, then the reason that virDomainHasManagedSaveImage returned -1 is because the hypervisor _can't_ create managed save, and therefore, we should not fail the undefine (because the undefine by definition won't have any managed state to worry about). This logic needs to be updated to return false only if last_error->code is something besides VIR_ERR_NO_SUPPORT (meaning we hit a real error on a hypervisor that supports managed save, but can't answer us, rather than a hypervisor that doesn't have managed save in the first place).
+ + 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) { + virErrorPtr err = virGetLastError();
Overkill; look at how cmdVcpucount uses the virsh.c global last_error, rather than having to call virGetLastError(). That is, virsh already hooked up a custom handler that captures all errors at the point they are created, so you can then query last_error, rather than having to make more virGetLastError API calls yourself.
+++ b/tools/virsh.pod @@ -807,10 +807,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> optional I<--managed-save>
Now that my virsh.pod cleanup is in (commit 08d3b0a2), this needs to be: =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 managed save image will fail.
s/with managed/with a managed/ -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

--- tools/virsh.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 8a62612..120f3c8 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2366,6 +2366,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) int autostart; unsigned int id; char *str, uuid[VIR_UUID_STRING_BUFLEN]; + int has_managed_state = 0; if (!vshConnectionUsability(ctl, ctl->conn)) return false; @@ -2430,6 +2431,13 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) autostart ? _("enable") : _("disable") ); } + has_managed_state = virDomainHasManagedSaveImage(dom, 0); + if (has_managed_state < 0) + vshPrint(ctl, "%-15s %s\n", _("Has managed state:"), _("unknown")); + else + vshPrint(ctl, "%-15s %s\n", _("Has managed state:"), + has_managed_state ? _("yes") : _("no")); + /* Security model and label information */ memset(&secmodel, 0, sizeof secmodel); if (virNodeGetSecurityModel(ctl->conn, &secmodel) == -1) { -- 1.7.6

On 07/15/2011 03:06 AM, Osier Yang wrote:
--- tools/virsh.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c index 8a62612..120f3c8 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2366,6 +2366,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) int autostart; unsigned int id; char *str, uuid[VIR_UUID_STRING_BUFLEN]; + int has_managed_state = 0;
if (!vshConnectionUsability(ctl, ctl->conn)) return false; @@ -2430,6 +2431,13 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) autostart ? _("enable") : _("disable") ); }
+ has_managed_state = virDomainHasManagedSaveImage(dom, 0); + if (has_managed_state < 0) + vshPrint(ctl, "%-15s %s\n", _("Has managed state:"), _("unknown")); + else + vshPrint(ctl, "%-15s %s\n", _("Has managed state:"), + has_managed_state ? _("yes") : _("no"));
This changes default output of an existing command, but it's not the first time we've done that (for example, commit aa2c9726 added the "Security model" string). For this particular command, that's fine, since it remains machine parsable (each line is a name-value pair, and you search for the line with the name you care about); still, I'd feel better if your new string came last rather than in the middle in case existing parsers count a certain number of lines and expect a particular name on that line. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

于 2011年07月16日 05:45, Eric Blake 写道:
On 07/15/2011 03:06 AM, Osier Yang wrote:
--- tools/virsh.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c index 8a62612..120f3c8 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2366,6 +2366,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) int autostart; unsigned int id; char *str, uuid[VIR_UUID_STRING_BUFLEN]; + int has_managed_state = 0;
if (!vshConnectionUsability(ctl, ctl->conn)) return false; @@ -2430,6 +2431,13 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) autostart ? _("enable") : _("disable") ); }
+ has_managed_state = virDomainHasManagedSaveImage(dom, 0); + if (has_managed_state< 0) + vshPrint(ctl, "%-15s %s\n", _("Has managed state:"), _("unknown")); + else + vshPrint(ctl, "%-15s %s\n", _("Has managed state:"), + has_managed_state ? _("yes") : _("no")); This changes default output of an existing command, but it's not the first time we've done that (for example, commit aa2c9726 added the "Security model" string). For this particular command, that's fine, since it remains machine parsable (each line is a name-value pair, and you search for the line with the name you care about); still, I'd feel better if your new string came last rather than in the middle in case existing parsers count a certain number of lines and expect a particular name on that line.
Agree it's better as a last string, but it's need changes on codes to print "Security *" strings, to prevent the early return.

于 2011年07月16日 11:11, Osier Yang 写道:
于 2011年07月16日 05:45, Eric Blake 写道:
On 07/15/2011 03:06 AM, Osier Yang wrote:
--- tools/virsh.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c index 8a62612..120f3c8 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2366,6 +2366,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) int autostart; unsigned int id; char *str, uuid[VIR_UUID_STRING_BUFLEN]; + int has_managed_state = 0;
if (!vshConnectionUsability(ctl, ctl->conn)) return false; @@ -2430,6 +2431,13 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) autostart ? _("enable") : _("disable") ); }
+ has_managed_state = virDomainHasManagedSaveImage(dom, 0); + if (has_managed_state< 0) + vshPrint(ctl, "%-15s %s\n", _("Has managed state:"), _("unknown")); + else + vshPrint(ctl, "%-15s %s\n", _("Has managed state:"), + has_managed_state ? _("yes") : _("no")); This changes default output of an existing command, but it's not the first time we've done that (for example, commit aa2c9726 added the "Security model" string). For this particular command, that's fine, since it remains machine parsable (each line is a name-value pair, and you search for the line with the name you care about); still, I'd feel better if your new string came last rather than in the middle in case existing parsers count a certain number of lines and expect a particular name on that line.
Agree it's better as a last string, but it's need changes on codes to print "Security *" strings, to prevent the early return.
I'm inclined to keep this patch unchanged, as for the "security" strings, there will be no strings printed out if virNodeGetSecurityModel is not supported. So it still may break the script which parse a certain number of lines. And if we print "security" strings regardless of whether is supported or not, success or failure, (just like "persistent", "autostart" do), it might break the scripts too. Regards Osier
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On 07/15/2011 03:06 AM, Osier Yang wrote:
--- tools/virsh.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
Your rebuttals to my arguments about positioning are sound, so I'm okay with leaving the positioning of this output prior to "Security" strings. However, on re-reading it, I see one more issue:
diff --git a/tools/virsh.c b/tools/virsh.c index 8a62612..120f3c8 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2366,6 +2366,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) int autostart; unsigned int id; char *str, uuid[VIR_UUID_STRING_BUFLEN]; + int has_managed_state = 0;
if (!vshConnectionUsability(ctl, ctl->conn)) return false; @@ -2430,6 +2431,13 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) autostart ? _("enable") : _("disable") ); }
+ has_managed_state = virDomainHasManagedSaveImage(dom, 0); + if (has_managed_state< 0) + vshPrint(ctl, "%-15s %s\n", _("Has managed state:"), _("unknown"));
Here, we print "managed state", but the command that creates that state is called "managedsave", and the API we call is virDomainHasManagedSaveImage. Not to mention that it surpasses 15 columns, which makes the output not lined up with all the other rows. Also, the "Has" is a bit redundant. I'd prefer to see this output as: Managed save: yes|no|unknown ACK with that nit fixed, and this can be pushed independently of the rest of the series. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 07/18/2011 11:34 AM, Eric Blake wrote:
Here, we print "managed state", but the command that creates that state is called "managedsave", and the API we call is virDomainHasManagedSaveImage. Not to mention that it surpasses 15 columns, which makes the output not lined up with all the other rows. Also, the "Has" is a bit redundant. I'd prefer to see this output as:
Managed save: yes|no|unknown
ACK with that nit fixed, and this can be pushed independently of the rest of the series.
Also, squash in some documentation: diff --git i/tools/virsh.pod w/tools/virsh.pod index 5afa1f2..312ddf0 100644 --- i/tools/virsh.pod +++ w/tools/virsh.pod @@ -514,6 +514,9 @@ Save and destroy (stop) a running domain, so it can be restarted from the same state at a later time. When the virsh B<start> command is next run for the domain, it will automatically be started from this saved state. +The B<dominfo> command can be used to query whether a domain currently +has any managed save state. + =item B<managedsave-remove> I<domain-id> Remove the B<managedsave> state file for a domain, if it exists. This -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

于 2011年07月19日 01:37, Eric Blake 写道:
On 07/18/2011 11:34 AM, Eric Blake wrote:
Here, we print "managed state", but the command that creates that state is called "managedsave", and the API we call is virDomainHasManagedSaveImage. Not to mention that it surpasses 15 columns, which makes the output not lined up with all the other rows. Also, the "Has" is a bit redundant. I'd prefer to see this output as:
Managed save: yes|no|unknown
ACK with that nit fixed, and this can be pushed independently of the rest of the series.
Also, squash in some documentation:
diff --git i/tools/virsh.pod w/tools/virsh.pod index 5afa1f2..312ddf0 100644 --- i/tools/virsh.pod +++ w/tools/virsh.pod @@ -514,6 +514,9 @@ Save and destroy (stop) a running domain, so it can be restarted from the same state at a later time. When the virsh B<start> command is next run for the domain, it will automatically be started from this saved state.
+The B<dominfo> command can be used to query whether a domain currently +has any managed save state. + =item B<managedsave-remove> I<domain-id>
Remove the B<managedsave> state file for a domain, if it exists. This
Pushed with the document, and the nits you mentioned in previous mail fixed. Thanks Osier
participants (2)
-
Eric Blake
-
Osier Yang