[libvirt] [PATCH 0/4] add virsh domxml-formats

I previously proposed this here: https://www.redhat.com/archives/libvir-list/2011-December/msg00899.html although it's been on my wish list a lot longer than that. Questions: I had the new API take nformats as an int, and return the number of populated slots; should I switch this to take *nformats as a pointer (being both input and output) with a return value of 0, so as to be more consistent with things like virDomainGetMemoryParameters? I'm not very familiar with writing python bindings, at least not without the benefit of copy-and-paste, and I didn't see a good example to copy from. Ultimately, I envision that the python API will be something like virConnect.domainNativeFormats(self, flags), with a return being a python list of strings (where the underlying code calls virConnectDomainNativeFormats twice, once to determine the list size, and once to determine the list contents), but I'm not sure how to go about doing that (I don't know if generator.py can do it, or if it needs an override, or what). So I left the python bindings undone, and would appreciate if someone else can step in and help. Eric Blake (4): native: add virConnectNativeFormats API native: add virsh command domxml-formats native: implement rpc handling of new API native: add driver support daemon/remote.c | 56 ++++++++++++++++++++++++++++++++++++ include/libvirt/libvirt.h.in | 4 ++ python/generator.py | 3 ++ src/driver.h | 6 ++++ src/esx/esx_driver.c | 20 ++++++++++++- src/libvirt.c | 59 ++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 +++ src/libxl/libxl_driver.c | 22 +++++++++++++- src/qemu/qemu_driver.c | 17 +++++++++++ src/remote/remote_driver.c | 64 +++++++++++++++++++++++++++++++++++++++++- src/remote/remote_protocol.x | 17 ++++++++++- src/remote_protocol-structs | 12 ++++++++ src/xen/xen_driver.c | 27 +++++++++++++++++- tools/virsh.c | 48 +++++++++++++++++++++++++++++++ tools/virsh.pod | 11 ++++++- 15 files changed, 362 insertions(+), 9 deletions(-) -- 1.7.7.5

Make it easier to query what nativeFormat strings are valid in the conversion between XML and native formats. * include/libvirt/libvirt.h.in (virConnectDomainNativeFormats): New declaration. * src/libvirt.c (virConnectDomainNativeFormats): Implement it. * src/driver.h (virDrvConnectDomainNativeFormats): New callback. * src/libvirt_public.syms (LIBVIRT_0.9.10): Export it. * python/generator.py (skip_function): Skip python binding for now. --- include/libvirt/libvirt.h.in | 4 +++ python/generator.py | 3 ++ src/driver.h | 6 ++++ src/libvirt.c | 59 ++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 +++ 5 files changed, 77 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index e436f3c..7d7f22a 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1432,6 +1432,10 @@ char * virConnectDomainXMLToNative(virConnectPtr conn, const char *nativeFormat, const char *domainXml, unsigned int flags); +int virConnectDomainNativeFormats(virConnectPtr conn, + char **formats, + int nformats, + unsigned int flags); int virDomainBlockStats (virDomainPtr dom, const char *disk, diff --git a/python/generator.py b/python/generator.py index 6fee3a4..57615b8 100755 --- a/python/generator.py +++ b/python/generator.py @@ -477,6 +477,9 @@ skip_function = ( "virNWFilterGetConnect", "virStoragePoolGetConnect", "virStorageVolGetConnect", + + # Not implemented yet + "virConnectDomainNativeFormats", ) qemu_skip_function = ( diff --git a/src/driver.h b/src/driver.h index 24636a4..15e4f2c 100644 --- a/src/driver.h +++ b/src/driver.h @@ -243,6 +243,11 @@ typedef char * const char *domainXml, unsigned int flags); typedef int + (*virDrvConnectDomainNativeFormats) (virConnectPtr conn, + char **formats, + int nformats, + unsigned int flags); +typedef int (*virDrvListDefinedDomains) (virConnectPtr conn, char **const names, int maxnames); @@ -868,6 +873,7 @@ struct _virDriver { virDrvDomainGetXMLDesc domainGetXMLDesc; virDrvConnectDomainXMLFromNative domainXMLFromNative; virDrvConnectDomainXMLToNative domainXMLToNative; + virDrvConnectDomainNativeFormats domainNativeFormats; virDrvListDefinedDomains listDefinedDomains; virDrvNumOfDefinedDomains numOfDefinedDomains; virDrvDomainCreate domainCreate; diff --git a/src/libvirt.c b/src/libvirt.c index a540424..2e9f773 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -4347,6 +4347,65 @@ error: return NULL; } +/** + * virConnectDomainNativeFormats: + * @conn: pointer to the hypervisor connection. + * @formats: array for storing result + * @nformats: maximum size of array + * @flags: extra flags; not used yet, so callers should always pass 0 + * + * This function provides a list of all supported formats used by + * virConnectDomainXMLToNative() and virConnectDomainXMLFromNative(). + * + * As a special case, if @formats is NULL and @nformats is 0, the output + * will be the number of supported formats; the caller can use this to + * properly allocate the @formats array. For example: + * + * nformats = virConnectNativeFormats(conn, NULL, 0, 0); + * if (nformats < 0 || + * (formats = calloc(nformats, sizeof(char *))) == NULL || + * (nformats = virConnectNativeFormats(conn, formats, nformats, 0)) < 0) + * goto error; + * + * This function doesn't require privileged access to the hypervisor. + * This function expects the caller to allocate the @formats array, + * and to call free() on each returned array element. + * + * Returns -1 in case of error, or the count of returned elements. + */ +int +virConnectDomainNativeFormats(virConnectPtr conn, char **formats, int nformats, + unsigned int flags) +{ + VIR_DEBUG("conn=%p, formats=%p, nformats=%d, flags=%x", + conn, formats, nformats, flags); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (formats == NULL ? nformats != 0 : nformats < 1) { + virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (conn->driver->domainNativeFormats) { + int ret; + ret = conn->driver->domainNativeFormats(conn, formats, nformats, flags); + if (ret < 0) + goto error; + return ret; + } + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return -1; +} /* * Sequence v1: diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 4ca7216..dde3c7a 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -516,4 +516,9 @@ LIBVIRT_0.9.9 { virDomainSetNumaParameters; } LIBVIRT_0.9.8; +LIBVIRT_0.9.10 { + global: + virConnectDomainNativeFormats; +} LIBVIRT_0.9.9; + # .... define new API here using predicted next version number .... -- 1.7.7.5

I've wanted this command for ages :) * tools/virsh.c (cmdDomXMLFormats): New function. * tools/virsh.pod (domxml-formats): Document it. --- tools/virsh.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 11 +++++++++-- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index c511e2a..b1a0fb7 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -6268,6 +6268,52 @@ cmdDomXMLToNative(vshControl *ctl, const vshCmd *cmd) } /* + * "domxml-formats" command + */ +static const vshCmdInfo info_domxmlformats[] = { + {"help", N_("List native formats compatible with domain XML")}, + {"desc", + N_("List the valid formats for domxml-to-native and domxml-from-native.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_domxmlformats[] = { + {NULL, 0, 0, NULL} +}; + +static bool +cmdDomXMLFormats(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) +{ + bool ret = false; + unsigned int flags = 0; + char **formats = NULL; + int nformats = 0; + int i; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return false; + + if ((nformats = virConnectDomainNativeFormats(ctl->conn, NULL, 0, + flags)) < 0) + goto cleanup; + + formats = vshCalloc(ctl, nformats, sizeof(*formats)); + if ((nformats = virConnectDomainNativeFormats(ctl->conn, formats, nformats, + flags)) < 0) + goto cleanup; + + for (i = 0; i < nformats; i++) + vshPrint(ctl, "%s\n", formats[i]); + ret = true; + +cleanup: + for (i = 0; i < nformats; i++) + VIR_FREE(formats[i]); + VIR_FREE(formats); + return ret; +} + +/* * "domname" command */ static const vshCmdInfo info_domname[] = { @@ -15930,6 +15976,8 @@ static const vshCmdDef domManagementCmds[] = { {"domjobinfo", cmdDomjobinfo, opts_domjobinfo, info_domjobinfo, 0}, {"domname", cmdDomname, opts_domname, info_domname, 0}, {"domuuid", cmdDomuuid, opts_domuuid, info_domuuid, 0}, + {"domxml-formats", cmdDomXMLFormats, opts_domxmlformats, + info_domxmlformats, 0}, {"domxml-from-native", cmdDomXMLFromNative, opts_domxmlfromnative, info_domxmlfromnative, 0}, {"domxml-to-native", cmdDomXMLToNative, opts_domxmltonative, diff --git a/tools/virsh.pod b/tools/virsh.pod index c88395b..19f93cf 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -624,19 +624,26 @@ Returns state of an interface to VMM used to control a domain. For states other than "ok" or "error" the command also prints number of seconds elapsed since the control interface entered its current state. +=item B<domxml-formats> + +List the valid formats for use by B<domxml-from-native> and +B<domxml-to-native>. + =item B<domxml-from-native> I<format> I<config> Convert the file I<config> in the native guest configuration format named by I<format> to a domain XML format. For QEMU/KVM hypervisor, the I<format> argument must be B<qemu-argv>. For Xen hypervisor, the -I<format> argument may be B<xen-xm> or B<xen-sxpr>. +I<format> argument may be B<xen-xm> or B<xen-sxpr>. See also +B<domxml-formats>. =item B<domxml-to-native> I<format> I<xml> Convert the file I<xml> in domain XML format to the native guest configuration format named by I<format>. For QEMU/KVM hypervisor, the I<format> argument must be B<qemu-argv>. For Xen hypervisor, the -I<format> argument may be B<xen-xm> or B<xen-sxpr>. +I<format> argument may be B<xen-xm> or B<xen-sxpr>. See also +B<domxml-formats>. =item B<dump> I<domain-id> I<corefilepath> [I<--bypass-cache>] { [I<--live>] | [I<--crash>] | [I<--reset>] } [I<--verbose>] -- 1.7.7.5

Alas, the special handling of nformats == 0 means we can't use autogen. * src/remote/remote_protocol.x (remote_domain_native_formats_args) (remote_domain_native_formats_ret): New types. * daemon/remote.c (remoteDispatchDomainNativeFormats): New function. * src/remote/remote_driver.c (remoteDomainNativeFormats): Likewise. (remote_driver): Register it. * src/remote_protocol-structs: Regenerate. --- daemon/remote.c | 56 ++++++++++++++++++++++++++++++++++++ src/remote/remote_driver.c | 64 +++++++++++++++++++++++++++++++++++++++++- src/remote/remote_protocol.x | 17 ++++++++++- src/remote_protocol-structs | 12 ++++++++ 4 files changed, 146 insertions(+), 3 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index a28a754..3511158 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -1298,6 +1298,62 @@ cleanup: } static int +remoteDispatchDomainNativeFormats(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_domain_native_formats_args *args, + remote_domain_native_formats_ret *ret) +{ + char **formats = NULL; + unsigned int flags; + int rv = -1; + struct daemonClientPrivate *priv = + virNetServerClientGetPrivateData(client); + + if (!priv->conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + flags = args->flags; + + if (args->nformats > REMOTE_DOMAIN_NATIVE_FORMATS_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("nformats too large")); + goto cleanup; + } + if (args->nformats) { + if (VIR_ALLOC_N(formats, args->nformats) < 0) { + virReportOOMError(); + goto cleanup; + } + ret->formats.formats_val = formats; + } + + ret->nformats = virConnectDomainNativeFormats(priv->conn, + ret->formats.formats_val, + args->nformats, flags); + if (ret->nformats < 0) + goto cleanup; + + /* In this case, we need to send back the number of formats supported + */ + if (args->nformats == 0) + goto success; + + ret->formats.formats_len = ret->nformats; +success: + rv = 0; + +cleanup: + if (rv < 0) { + virNetMessageSaveError(rerr); + VIR_FREE(ret->formats.formats_val); + } + return rv; +} + +static int remoteDispatchDomainGetVcpuPinInfo(virNetServerPtr server ATTRIBUTE_UNUSED, virNetServerClientPtr client ATTRIBUTE_UNUSED, virNetMessagePtr msg ATTRIBUTE_UNUSED, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index e28840b..8b35c5f 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2,7 +2,7 @@ * remote_driver.c: driver to provide access to libvirtd running * on a remote machine * - * Copyright (C) 2007-2011 Red Hat, Inc. + * Copyright (C) 2007-2012 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -1901,6 +1901,67 @@ done: } static int +remoteDomainNativeFormats (virConnectPtr conn, + char **formats, int nformats, + unsigned int flags) +{ + int rv = -1; + remote_domain_native_formats_args args; + remote_domain_native_formats_ret ret; + int i = -1; + struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); + + args.nformats = nformats; + args.flags = flags; + + memset (&ret, 0, sizeof ret); + if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_NATIVE_FORMATS, + (xdrproc_t) xdr_remote_domain_native_formats_args, (char *) &args, + (xdrproc_t) xdr_remote_domain_native_formats_ret, (char *) &ret) == -1) + goto done; + + /* Check the length of the returned list carefully. */ + if (ret.formats.formats_len > REMOTE_DOMAIN_NATIVE_FORMATS_MAX || + ret.formats.formats_len > nformats) { + remoteError(VIR_ERR_RPC, "%s", + _("remoteDomainNativeFormats: " + "returned number of formats exceeds limit")); + goto cleanup; + } + /* Handle the case when the caller does not know the number of formats + * and is asking for the number of formats supported + */ + if (nformats == 0) { + rv = ret.nformats; + goto cleanup; + } + + /* Deserialise the result. */ + for (i = 0; i < ret.formats.formats_len; ++i) { + if ((formats[i] = strdup(ret.formats.formats_val[i])) == NULL) { + virReportOOMError(); + goto cleanup; + } + } + + rv = ret.formats.formats_len; + +cleanup: + if (rv < 0) { + int j; + for (j = 0; j < i; j++) + VIR_FREE(formats[j]); + } + xdr_free ((xdrproc_t) xdr_remote_domain_native_formats_ret, + (char *) &ret); +done: + remoteDriverUnlock(priv); + return rv; +} + +static int remoteDomainMigratePrepare (virConnectPtr dconn, char **cookie, int *cookielen, const char *uri_in, char **uri_out, @@ -4654,6 +4715,7 @@ static virDriver remote_driver = { .domainGetXMLDesc = remoteDomainGetXMLDesc, /* 0.3.0 */ .domainXMLFromNative = remoteDomainXMLFromNative, /* 0.6.4 */ .domainXMLToNative = remoteDomainXMLToNative, /* 0.6.4 */ + .domainNativeFormats = remoteDomainNativeFormats, /* 0.9.10 */ .listDefinedDomains = remoteListDefinedDomains, /* 0.3.0 */ .numOfDefinedDomains = remoteNumOfDefinedDomains, /* 0.3.0 */ .domainCreate = remoteDomainCreate, /* 0.3.0 */ diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index ca739ff..cda7501 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3,7 +3,7 @@ * remote_internal driver and libvirtd. This protocol is * internal and may change at any time. * - * Copyright (C) 2006-2011 Red Hat, Inc. + * Copyright (C) 2006-2012 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -207,6 +207,9 @@ const REMOTE_DOMAIN_SEND_KEY_MAX = 16; */ const REMOTE_DOMAIN_INTERFACE_PARAMETERS_MAX = 16; +/* Upper limit on number of domain native formats */ +const REMOTE_DOMAIN_NATIVE_FORMATS_MAX = 16; + /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */ typedef opaque remote_uuid[VIR_UUID_BUFLEN]; @@ -1800,6 +1803,15 @@ struct remote_domain_xml_to_native_ret { remote_nonnull_string nativeConfig; }; +struct remote_domain_native_formats_args { + int nformats; + unsigned int flags; +}; + +struct remote_domain_native_formats_ret { + remote_nonnull_string formats<REMOTE_DOMAIN_NATIVE_FORMATS_MAX>; + int nformats; +}; struct remote_num_of_secrets_ret { int num; @@ -2653,7 +2665,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_SET_NUMA_PARAMETERS = 254, /* autogen autogen */ REMOTE_PROC_DOMAIN_GET_NUMA_PARAMETERS = 255, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_SET_INTERFACE_PARAMETERS = 256, /* autogen autogen */ - REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257 /* skipgen skipgen */ + REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257, /* skipgen skipgen */ + REMOTE_PROC_DOMAIN_NATIVE_FORMATS = 258 /* skipgen skipgen priority:high */ /* * Notice how the entries are grouped in sets of 10 ? diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 2758315..9dacbce 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1354,6 +1354,17 @@ struct remote_domain_xml_to_native_args { struct remote_domain_xml_to_native_ret { remote_nonnull_string nativeConfig; }; +struct remote_domain_native_formats_args { + int nformats; + u_int flags; +}; +struct remote_domain_native_formats_ret { + struct { + u_int formats_len; + remote_nonnull_string * formats_val; + } formats; + int nformats; +}; struct remote_num_of_secrets_ret { int num; }; @@ -2090,4 +2101,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_NUMA_PARAMETERS = 255, REMOTE_PROC_DOMAIN_SET_INTERFACE_PARAMETERS = 256, REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257, + REMOTE_PROC_DOMAIN_NATIVE_FORMATS = 258, }; -- 1.7.7.5

Xen was the trickiest, since it supports two formats. * src/esx/esx_driver.c (esxDomainNativeFormats): New function. * src/libxl/libxl_driver.c (libxlDomainNativeFormats): Likewise. * src/qemu/qemu_driver.c (qemuDomainNativeFormats): Likewise. * src/xen/xen_driver.c (xenUnifiedDomainNativeFormats): Likewise. --- src/esx/esx_driver.c | 20 +++++++++++++++++++- src/libxl/libxl_driver.c | 22 ++++++++++++++++++++-- src/qemu/qemu_driver.c | 17 +++++++++++++++++ src/xen/xen_driver.c | 27 ++++++++++++++++++++++++++- 4 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 1e424eb..b29c642 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -2,7 +2,7 @@ /* * esx_driver.c: core driver functions for managing VMware ESX hosts * - * Copyright (C) 2010-2011 Red Hat, Inc. + * Copyright (C) 2010-2012 Red Hat, Inc. * Copyright (C) 2009-2011 Matthias Bolte <matthias.bolte@googlemail.com> * Copyright (C) 2009 Maximilian Wilhelm <max@rfc2324.org> * @@ -2941,6 +2941,23 @@ esxDomainXMLToNative(virConnectPtr conn, const char *nativeFormat, } +static int +esxDomainNativeFormats(virConnectPtr conn ATTRIBUTE_UNUSED, + char **formats, int nformats, unsigned int flags) +{ + virCheckFlags(0, -1); + + if (!nformats) + return 1; + + if ((*formats = strdup("vmware-vmx")) == NULL) { + virReportOOMError(); + return -1; + } + + return 1; +} + static int esxListDefinedDomains(virConnectPtr conn, char **const names, int maxnames) @@ -4978,6 +4995,7 @@ static virDriver esxDriver = { .domainGetXMLDesc = esxDomainGetXMLDesc, /* 0.7.0 */ .domainXMLFromNative = esxDomainXMLFromNative, /* 0.7.0 */ .domainXMLToNative = esxDomainXMLToNative, /* 0.7.2 */ + .domainNativeFormats = esxDomainNativeFormats, /* 0.9.10 */ .listDefinedDomains = esxListDefinedDomains, /* 0.7.0 */ .numOfDefinedDomains = esxNumberOfDefinedDomains, /* 0.7.0 */ .domainCreate = esxDomainCreate, /* 0.7.0 */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 0500ed0..72b1d03 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -1,7 +1,7 @@ /*---------------------------------------------------------------------------*/ -/* Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. +/* Copyright (C) 2006-2012 Red Hat, Inc. + * Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. * Copyright (C) 2011 Univention GmbH. - * Copyright (C) 2006-2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -2633,6 +2633,23 @@ cleanup: } static int +libxlDomainNativeFormats(virConnectPtr conn ATTRIBUTE_UNUSED, + char **formats, int nformats, unsigned int flags) +{ + virCheckFlags(0, -1); + + if (!nformats) + return 1; + + if ((*formats = strdup(LIBXL_CONFIG_FORMAT_XM)) == NULL) { + virReportOOMError(); + return -1; + } + + return 1; +} + +static int libxlListDefinedDomains(virConnectPtr conn, char **const names, int nnames) { @@ -3900,6 +3917,7 @@ static virDriver libxlDriver = { .domainGetXMLDesc = libxlDomainGetXMLDesc, /* 0.9.0 */ .domainXMLFromNative = libxlDomainXMLFromNative, /* 0.9.0 */ .domainXMLToNative = libxlDomainXMLToNative, /* 0.9.0 */ + .domainNativeFormats = libxlDomainNativeFormats, /* 0.9.10 */ .listDefinedDomains = libxlListDefinedDomains, /* 0.9.0 */ .numOfDefinedDomains = libxlNumDefinedDomains, /* 0.9.0 */ .domainCreate = libxlDomainCreate, /* 0.9.0 */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 712f1fc..c3f4510 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4544,6 +4544,22 @@ cleanup: return ret; } +static int +qemuDomainNativeFormats(virConnectPtr conn ATTRIBUTE_UNUSED, + char **formats, int nformats, unsigned int flags) +{ + virCheckFlags(0, -1); + + if (!nformats) + return 1; + + if ((*formats = strdup(QEMU_CONFIG_FORMAT_ARGV)) == NULL) { + virReportOOMError(); + return -1; + } + + return 1; +} static int qemudListDefinedDomains(virConnectPtr conn, char **const names, int nnames) { @@ -11890,6 +11906,7 @@ static virDriver qemuDriver = { .domainGetXMLDesc = qemuDomainGetXMLDesc, /* 0.2.0 */ .domainXMLFromNative = qemuDomainXMLFromNative, /* 0.6.4 */ .domainXMLToNative = qemuDomainXMLToNative, /* 0.6.4 */ + .domainNativeFormats = qemuDomainNativeFormats, /* 0.9.10 */ .listDefinedDomains = qemudListDefinedDomains, /* 0.2.0 */ .numOfDefinedDomains = qemudNumDefinedDomains, /* 0.2.0 */ .domainCreate = qemuDomainStart, /* 0.2.0 */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 20671c0..1cec988 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -1,7 +1,7 @@ /* * xen_driver.c: Unified Xen driver. * - * Copyright (C) 2007-2011 Red Hat, Inc. + * Copyright (C) 2007-2012 Red Hat, Inc. * * See COPYING.LIB for the License of this software * @@ -1352,6 +1352,30 @@ cleanup: return ret; } +static int +xenUnifiedDomainNativeFormats(virConnectPtr conn ATTRIBUTE_UNUSED, + char **formats, int nformats, + unsigned int flags) +{ + virCheckFlags(0, -1); + + if (!nformats) + return 2; + + if ((formats[0] = strdup(XEN_CONFIG_FORMAT_XM)) == NULL) + goto memory; + if (nformats > 1 && + (formats[1] = strdup(XEN_CONFIG_FORMAT_SEXPR)) == NULL) + goto memory; + + return nformats < 2 ? nformats : 2; + +memory: + virReportOOMError(); + VIR_FREE(formats[0]); + return -1; +} + static int xenUnifiedDomainMigratePrepare (virConnectPtr dconn, @@ -2210,6 +2234,7 @@ static virDriver xenUnifiedDriver = { .domainGetXMLDesc = xenUnifiedDomainGetXMLDesc, /* 0.0.3 */ .domainXMLFromNative = xenUnifiedDomainXMLFromNative, /* 0.6.4 */ .domainXMLToNative = xenUnifiedDomainXMLToNative, /* 0.6.4 */ + .domainNativeFormats = xenUnifiedDomainNativeFormats, /* 0.9.10 */ .listDefinedDomains = xenUnifiedListDefinedDomains, /* 0.1.1 */ .numOfDefinedDomains = xenUnifiedNumOfDefinedDomains, /* 0.1.5 */ .domainCreate = xenUnifiedDomainCreate, /* 0.1.1 */ -- 1.7.7.5

On 01/13/2012 02:11 PM, Eric Blake wrote:
I previously proposed this here: https://www.redhat.com/archives/libvir-list/2011-December/msg00899.html although it's been on my wish list a lot longer than that.
Questions: I had the new API take nformats as an int, and return the number of populated slots; should I switch this to take *nformats as a pointer (being both input and output) with a return value of 0, so as to be more consistent with things like virDomainGetMemoryParameters?
I'm not very familiar with writing python bindings, at least not without the benefit of copy-and-paste, and I didn't see a good example to copy from. Ultimately, I envision that the python API will be something like virConnect.domainNativeFormats(self, flags), with a return being a python list of strings (where the underlying code calls virConnectDomainNativeFormats twice, once to determine the list size, and once to determine the list contents), but I'm not sure how to go about doing that (I don't know if generator.py can do it, or if it needs an override, or what). So I left the python bindings undone, and would appreciate if someone else can step in and help.
Hmm, why not just include this info in capabilities XML? Might not be as easy for some simple apps like virsh to consume, but it seems like more of the proper place to put this. (sorry if this has been discussed before, I haven't been following libvirt-list too closely as of late). Thanks, Cole

On 01/16/2012 06:01 AM, Cole Robinson wrote:
On 01/13/2012 02:11 PM, Eric Blake wrote:
I previously proposed this here: https://www.redhat.com/archives/libvir-list/2011-December/msg00899.html although it's been on my wish list a lot longer than that.
Questions: I had the new API take nformats as an int, and return the number of populated slots; should I switch this to take *nformats as a pointer (being both input and output) with a return value of 0, so as to be more consistent with things like virDomainGetMemoryParameters?
I'm not very familiar with writing python bindings, at least not without the benefit of copy-and-paste, and I didn't see a good example to copy from. Ultimately, I envision that the python API will be something like virConnect.domainNativeFormats(self, flags), with a return being a python list of strings (where the underlying code calls virConnectDomainNativeFormats twice, once to determine the list size, and once to determine the list contents), but I'm not sure how to go about doing that (I don't know if generator.py can do it, or if it needs an override, or what). So I left the python bindings undone, and would appreciate if someone else can step in and help.
Hmm, why not just include this info in capabilities XML? Might not be as easy for some simple apps like virsh to consume, but it seems like more of the proper place to put this.
(sorry if this has been discussed before, I haven't been following libvirt-list too closely as of late).
Hmm, good idea. We already use capabilities to expose the list of supported migration URIs, so I'll see about re-spinning this patch into one that adds the supported names as capabilities, then teaches virsh domxml-formats to do an XPath scrape of the capabilities XML rather than needing a new API. -- Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
participants (2)
-
Cole Robinson
-
Eric Blake