Re: [libvirt] [PATCHv4 1/4] vcpupin: inroduce a new libvir API (virDomainPinVcpuFlags)
Thank you for commenting. Also, shouldn't these flags be named VIR_DOMAIN_PIN_VCPU_FLAGS_{LIVE|CONFIG} since they are meant only for the virDomainPinVcpuFlags() API? If VIR_DOMAIN_PIN_VCPU_XXX is preferred instead of VIR_DOMAIN_VCPU_XXX , I'll do so. -- Best regards, Taku Izumi -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 0/6] Add virNodeGetCPUStats() API
Hi, This is v6 of virNodeGetCPUTimeParameters() API. (This time, I rename it to virNodeGetCPUStats()) It returns cpu utilization or cumulative cpu time of the node from /proc/stat since node boots up. This patch only supports linux host. Changes v5-v6 - Rename API name to virNodeGetCPUStats() - virsh nodecpustats subcommand returns raw/absolute cputime value by default, and add --percent option for printing utilization. v4-v5 - Rebase latest libvirt GIT tree. v3-v4 - Rebase this patch like virDomainGetMemoryParameters() from v2 patches. (drop v3 patches except virsh subcommand) - Rename API name to virNodeGetCPUTimeParameters() v2-v3 - Change user I/F. It is able to request what the user want by the @flags. - Minor change of virsh nodecputime I/F. v1-v2 - Change user I/F like virDomainGetMemoryStats() - It can return either cpu utilization or cumulative cpu time of the node depends on each driver. Minoru Usui (6): [v6] virNodeGetCPUStats: Expose new API [v6] virNodeGetCPUStats: Define internal driver API [v6] virNodeGetCPUStats: Implement public API [v6] virNodeGetCPUStats: Implement remote protocol [v6] virNodeGetCPUStats: Implement virsh support [v6] virNodeGetCPUStats: Implement linux support daemon/remote.c | 76 + include/libvirt/libvirt.h.in | 65 + src/driver.h |8 +++ src/libvirt.c| 85 src/libvirt_private.syms |1 + src/libvirt_public.syms |1 + src/lxc/lxc_driver.c |1 + src/nodeinfo.c | 127 ++ src/nodeinfo.h |5 +- src/qemu/qemu_driver.c |1 + src/remote/remote_driver.c | 65 + src/remote/remote_protocol.x | 21 +++- src/uml/uml_driver.c |1 + tools/virsh.c| 127 ++ tools/virsh.pod |6 ++ 15 files changed, 588 insertions(+), 2 deletions(-) -- Minoru Usui u...@mxm.nes.nec.co.jp -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 1/6] virNodeGetCPUStats: Expose new API
virNodeGetCPUStats: Expose new API Signed-off-by: Minoru Usui u...@mxm.nes.nec.co.jp --- include/libvirt/libvirt.h.in | 65 ++ src/libvirt_public.syms |1 + 2 files changed, 66 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 7cd6e13..431071b 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -194,6 +194,58 @@ typedef struct _virStream virStream; */ typedef virStream *virStreamPtr; +/** + * VIR_CPU_STATS_FIELD_LENGTH: + * + * Macro providing the field length of virNodeCPUStats + */ +#define VIR_CPU_STATS_FIELD_LENGTH 80 + +/** + * VIR_CPU_STATS_KERNEL: + * + * Macro for the cumulative CPU time which spends by kernel, + * when the node booting up.(in nanoseconds). + */ +#define VIR_CPU_STATS_KERNEL kernel + +/** + * The cumulative CPU time which spends by user processes, + * when the node booting up.(in nanoseconds). + */ +#define VIR_CPU_STATS_USER user + +/** + * The cumulative idle CPU time, + * when the node booting up.(in nanoseconds). + */ +#define VIR_CPU_STATS_IDLE idle + +/** + * The cumulative I/O wait CPU time, + * when the node booting up.(in nanoseconds). + */ +#define VIR_CPU_STATS_IOWAIT iowait + +/** + * The CPU utilization. + * The usage value is in percent and 100% represents all CPUs on + * the server. + */ +#define VIR_CPU_STATS_UTILIZATION utilization + +/** + * virCPUStats: + * + * a virNodeCPUStats is a structure filled by virNodeGetCPUStats() + * and providing the information for the cpu stats of the node. + */ +typedef struct _virCPUStats virCPUStats; + +struct _virCPUStats { +char field[VIR_CPU_STATS_FIELD_LENGTH]; +unsigned long long value; +}; /** * VIR_SECURITY_LABEL_BUFLEN: @@ -565,6 +617,14 @@ int virDomainMigrateSetMaxSpeed(virDomainPtr domain, typedef virNodeInfo *virNodeInfoPtr; /** + * virCPUStatsPtr: + * + * a virCPUStatsPtr is a pointer to a virCPUStats structure. + */ + +typedef virCPUStats *virCPUStatsPtr; + +/** * virConnectFlags * * Flags when opening a connection to a hypervisor @@ -698,6 +758,11 @@ int virNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info); char * virConnectGetCapabilities (virConnectPtr conn); +int virNodeGetCPUStats (virConnectPtr conn, +virCPUStatsPtr params, +int *nparams, +unsigned int flags); + unsigned long long virNodeGetFreeMemory(virConnectPtr conn); int virNodeGetSecurityModel (virConnectPtr conn, diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 0590535..2e34b89 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -442,6 +442,7 @@ LIBVIRT_0.9.2 { virDomainInjectNMI; virDomainScreenshot; virDomainSetSchedulerParametersFlags; +virNodeGetCPUStats; } LIBVIRT_0.9.0; # define new API here using predicted next version number -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 2/6] virNodeGetCPUStats: Define internal driver API
virNodeGetCPUStats: Define internal driver API Signed-off-by: Minoru Usui u...@mxm.nes.nec.co.jp --- src/driver.h |8 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index 450dd53..e981a9f 100644 --- a/src/driver.h +++ b/src/driver.h @@ -364,6 +364,13 @@ typedef struct _virDriver virDriver; typedef virDriver *virDriverPtr; typedef int +(*virDrvNodeGetCPUStats) +(virConnectPtr conn, + virCPUStatsPtr params, + int *nparams, + unsigned int flags); + +typedef int (*virDrvNodeGetCellsFreeMemory) (virConnectPtr conn, unsigned long long *freeMems, @@ -694,6 +701,7 @@ struct _virDriver { virDrvDomainBlockPeek domainBlockPeek; virDrvDomainMemoryPeek domainMemoryPeek; virDrvDomainGetBlockInfodomainGetBlockInfo; +virDrvNodeGetCPUStats nodeGetCPUStats; virDrvNodeGetCellsFreeMemory nodeGetCellsFreeMemory; virDrvNodeGetFreeMemorynodeGetFreeMemory; virDrvDomainEventRegister domainEventRegister; -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 4/6] virNodeGetCPUStats: Implement remote protocol
virNodeGetCPUStats: Implement remote protocol Signed-off-by: Minoru Usui u...@mxm.nes.nec.co.jp --- daemon/remote.c | 76 ++ src/remote/remote_driver.c | 65 +++ src/remote/remote_protocol.x | 21 +++- 3 files changed, 161 insertions(+), 1 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 80783b3..fb603f4 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -1788,6 +1788,82 @@ cleanup: return rv; } +static int +remoteDispatchNodeGetCPUStats (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_node_get_cpu_stats_args *args, + remote_node_get_cpu_stats_ret *ret) +{ +virCPUStatsPtr params = NULL; +int i; +int nparams = args-nparams; +unsigned int flags; +int rv = -1; + +if (!conn) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open)); +goto cleanup; +} + +flags = args-flags; + +if (nparams REMOTE_NODE_CPU_STATS_MAX) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(nparams too large)); +goto cleanup; +} +if (VIR_ALLOC_N(params, nparams) 0) { +virReportOOMError(); +goto cleanup; +} + +if (virNodeGetCPUStats(conn, params, nparams, flags) 0) +goto cleanup; + +/* In this case, we need to send back the number of stats + * supported + */ +if (args-nparams == 0) { +ret-nparams = nparams; +goto success; +} + +/* Serialise the memory parameters. */ +ret-params.params_len = nparams; +if (VIR_ALLOC_N(ret-params.params_val, nparams) 0) +goto no_memory; + +for (i = 0; i nparams; ++i) { +/* remoteDispatchClientRequest will free this: */ +ret-params.params_val[i].field = strdup(params[i].field); +if (ret-params.params_val[i].field == NULL) +goto no_memory; + +ret-params.params_val[i].value = params[i].value; +} + +success: +rv = 0; + +cleanup: +if (rv 0) { +remoteDispatchError(rerr); +if (ret-params.params_val) { +for (i = 0; i nparams; i++) +VIR_FREE(ret-params.params_val[i].field); +VIR_FREE(ret-params.params_val); +} +} +VIR_FREE(params); +return rv; + +no_memory: +virReportOOMError(); +goto cleanup; +} + /*-*/ static int diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 1691dab..924ea97 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1694,6 +1694,70 @@ done: } static int +remoteNodeGetCPUStats (virConnectPtr conn, + virCPUStatsPtr params, int *nparams, + unsigned int flags) +{ +int rv = -1; +remote_node_get_cpu_stats_args args; +remote_node_get_cpu_stats_ret ret; +int i = -1; +struct private_data *priv = conn-privateData; + +remoteDriverLock(priv); + +args.nparams = *nparams; +args.flags = flags; + +memset (ret, 0, sizeof ret); +if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_CPU_STATS, + (xdrproc_t) xdr_remote_node_get_cpu_stats_args, + (char *) args, + (xdrproc_t) xdr_remote_node_get_cpu_stats_ret, + (char *) ret) == -1) +goto done; + +/* Check the length of the returned list carefully. */ +if (ret.params.params_len REMOTE_NODE_CPU_STATS_MAX || +ret.params.params_len *nparams) { +remoteError(VIR_ERR_RPC, %s, +_(remoteNodeGetCPUStats: + returned number of stats exceeds limit)); +goto cleanup; +} +/* Handle the case when the caller does not know the number of stats + * and is asking for the number of stats supported + */ +if (*nparams == 0) { +*nparams = ret.nparams; +rv = 0; +goto cleanup; +} + +*nparams = ret.params.params_len; + +/* Deserialise the result. */ +for (i = 0; i *nparams; ++i) { +if (virStrcpyStatic(params[i].field, ret.params.params_val[i].field) == NULL) { +remoteError(VIR_ERR_INTERNAL_ERROR, +_(Stats %s too big for destination), +ret.params.params_val[i].field); +goto cleanup; +} +params[i].value = ret.params.params_val[i].value; +} + +rv = 0; + +cleanup: +xdr_free ((xdrproc_t) xdr_remote_node_get_cpu_stats_ret, + (char *) ret); +done: +remoteDriverUnlock(priv); +return rv; +} + +static int
[libvirt] [PATCHv6 5/6] virNodeGetCPUStats: Implement virsh support
virNodeGetCPUStats: Implement virsh support Add nodecpustats subcommand to virsh. This subcommand prints below output. [Linux] # virsh nodecpustats user :382024000 system:302956000 idle : 18638087000 iowait: 5183 # virsh nodecpustats --percent usage : 0.5% user : 0.0% system: 0.5% idle : 99.5% iowait: 0.0% [can get cpu utilization directly(ESX?)] # virsh nodecpustats # virsh nodecpustats --percent usage : 0.5% idle : 99.5% Signed-off-by: Minoru Usui u...@mxm.nes.nec.co.jp --- tools/virsh.c | 127 +++ tools/virsh.pod |6 +++ 2 files changed, 133 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index de49489..6d6a5dd 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -3490,6 +3490,132 @@ cmdNodeinfo(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } /* + * nodecpustats command + */ +static const vshCmdInfo info_nodecpustats[] = { +{help, N_(Prints cpu stats of the node.)}, +{desc, N_(Returns cpu stats of the node.(nsec))}, +{NULL, NULL} +}; + +static const vshCmdOptDef opts_node_cpustats[] = { +{percent, VSH_OT_BOOL, 0, N_(prints by percentage during 1 second.)}, +{NULL, 0, 0, NULL} +}; + +static bool +cmdNodeCPUStats(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) +{ +int i, j; +bool flag_utilization = false; +bool flag_percent = vshCommandOptBool(cmd, percent); +virCPUStatsPtr params; +int nparams = 0; +bool ret = false; +struct cpu_stats { +unsigned long long user; +unsigned long long sys; +unsigned long long idle; +unsigned long long iowait; +unsigned long long util; +} cpu_stats[2]; +double user_time, sys_time, idle_time, iowait_time, total_time; +double usage; + +if (!vshConnectionUsability(ctl, ctl-conn)) +return false; + +if (virNodeGetCPUStats(ctl-conn, NULL, nparams, 0) != 0) { +vshError(ctl, %s, + _(Unable to get number of cpu stats)); +return false; +} +if (nparams == 0) { +/* nothing to output */ +return true; +} + +memset(cpu_stats, 0, sizeof(struct cpu_stats) * 2); +params = vshCalloc(ctl, nparams, sizeof(*params)); + +i = 0; +do { +if (virNodeGetCPUStats(ctl-conn, params, nparams, 0) != 0) { +vshError(ctl, %s, _(Unable to get node cpu stats)); +goto cleanup; +} + +for (j = 0; j nparams; j++) { +unsigned long long value = params[j].value; + +if (strcmp(params[j].field, VIR_CPU_STATS_KERNEL) == 0) +cpu_stats[i].sys = value; + +if (strcmp(params[j].field, VIR_CPU_STATS_USER) == 0) +cpu_stats[i].user = value; + +if (strcmp(params[j].field, VIR_CPU_STATS_IDLE) == 0) +cpu_stats[i].idle = value; + +if (strcmp(params[j].field, VIR_CPU_STATS_IOWAIT) == 0) +cpu_stats[i].iowait = value; + +if (strcmp(params[j].field, VIR_CPU_STATS_UTILIZATION) == 0) { +cpu_stats[i].util = value; +flag_utilization = true; +} +} + +if (flag_utilization || (flag_percent == false)) +break; + +i++; +sleep(1); +} while(i 2); + +if (flag_percent == false) { +if (flag_utilization == false) { +vshPrint(ctl, %-15s %20llu\n, _(user :), cpu_stats[0].user); +vshPrint(ctl, %-15s %20llu\n, _(system:), cpu_stats[0].sys); +vshPrint(ctl, %-15s %20llu\n, _(idle :), cpu_stats[0].idle); +vshPrint(ctl, %-15s %20llu\n, _(iowait:), cpu_stats[0].iowait); +} +} else { +if (flag_utilization) { +usage = cpu_stats[0].util; + +vshPrint(ctl, %-15s %5.1lf%%\n, _(usage:), usage); +vshPrint(ctl, %-15s %5.1lf%%\n, _(idle :), 100 - usage); +} else { +user_time = cpu_stats[1].user - cpu_stats[0].user; +sys_time= cpu_stats[1].sys- cpu_stats[0].sys; +idle_time = cpu_stats[1].idle - cpu_stats[0].idle; +iowait_time = cpu_stats[1].iowait - cpu_stats[0].iowait; +total_time = user_time + sys_time + idle_time + iowait_time; + +usage = (user_time + sys_time) / total_time * 100; + +vshPrint(ctl, %-15s %5.1lf%%\n, + _(usage:), usage); +vshPrint(ctl, %-15s %5.1lf%%\n, + _(user :), user_time / total_time * 100); +vshPrint(ctl, %-15s %5.1lf%%\n, + _(system:), sys_time / total_time * 100); +vshPrint(ctl, %-15s %5.1lf%%\n, + _(idle :), idle_time / total_time * 100); +
[libvirt] [PATCHv6 3/6] virNodeGetCPUStats: Implement public API
virNodeGetCPUStats: Implement public API Signed-off-by: Minoru Usui u...@mxm.nes.nec.co.jp --- src/libvirt.c | 85 + 1 files changed, 85 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index ff16c48..937d8ab 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -4967,6 +4967,91 @@ error: } /** + * virNodeGetCPUStats: + * @conn: pointer to the hypervisor connection. + * @params: pointer to node cpu time parameter objects + * @nparams: number of node cpu time parameter (this value should be same or + * less than the number of parameters supported) + * @flags: currently unused, for future extension. always pass 0. + * + * This function provides cpu time statistics of the node. + * The @params array will be filled with the values equal to the number of + * parameters suggested by @nparams + * + * As the value of @nparams is dynamic, call the API setting @nparams to 0 and + * @params as NULL, the API returns the number of parameters supported by the + * HV by updating @nparams on SUCCESS. The caller should then allocate @params + * array, i.e. (sizeof(@virCPUStats) * @nparams) bytes and call + * the API again. + * + * Here is the sample code snippet: + * + * if ((virNodeGetCPUStats(conn, NULL, nparams, 0) == 0) + * (nparams != 0)) { + * params = vshMalloc(ctl, sizeof(virCPUStats) * nparams); + * memset(params, 0, sizeof(virCPUStats) * nparams); + * if (virNodeGetCPUStats(conn, params, nparams, 0)) { + * vshError(ctl, %s, _(Unable to get node cpu stats)); + * goto error; + * } + * } + * + * This function doesn't requires privileged access to the hypervisor. + * This function expects the caller to allocate the @params. + * + * CPU time Statistics: + * + * VIR_NODE_CPU_STATS_KERNEL: + * The cumulative CPU time which spends by kernel, + * when the node booting up.(nanoseconds) + * VIR_NODE_CPU_STATS_USER: + * The cumulative CPU time which spends by user processes, + * when the node booting up.(nanoseconds) + * VIR_NODE_CPU_STATS_IDLE: + * The cumulative idle CPU time, when the node booting up.(nanoseconds) + * VIR_NODE_CPU_STATS_IOWAIT: + * The cumulative I/O wait CPU time, when the node booting up.(nanoseconds) + * VIR_NODE_CPU_STATS_UTILIZATION: + * The CPU utilization. The usage value is in percent and 100% + * represents all CPUs on the server. + * + * Returns -1 in case of error, 0 in case of success. + */ +int virNodeGetCPUStats (virConnectPtr conn, +virCPUStatsPtr params, +int *nparams, unsigned int flags) +{ +VIR_DEBUG(conn=%p, params=%p, nparams=%d, flags=%u, + conn, params, nparams ? *nparams : -1, flags); + +virResetLastError(); + +if (!VIR_IS_CONNECT(conn)) { +virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); +virDispatchError(NULL); +return -1; +} + +if ((nparams == NULL) || (*nparams 0)) { +virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__); +goto error; +} + +if (conn-driver-nodeGetCPUStats) { +int ret; +ret = conn-driver-nodeGetCPUStats (conn, params, nparams, flags); +if (ret 0) +goto error; +return ret; +} +virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: +virDispatchError(conn); +return -1; +} + +/** * virNodeGetFreeMemory: * @conn: pointer to the hypervisor connection * -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 6/6] virNodeGetCPUStats: Implement linux support
virNodeGetCPUStats: Implement linux support Signed-off-by: Minoru Usui u...@mxm.nes.nec.co.jp --- src/libvirt_private.syms |1 + src/lxc/lxc_driver.c |1 + src/nodeinfo.c | 127 ++ src/nodeinfo.h |5 ++- src/qemu/qemu_driver.c |1 + src/uml/uml_driver.c |1 + 6 files changed, 135 insertions(+), 1 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 7b6151c..d8f26c4 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -687,6 +687,7 @@ virNodeDeviceObjUnlock; # nodeinfo.h nodeCapsInitNUMA; +nodeGetCPUStats; nodeGetCellsFreeMemory; nodeGetFreeMemory; nodeGetInfo; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 9e09c95..743219c 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2754,6 +2754,7 @@ static virDriver lxcDriver = { .domainGetSchedulerParameters = lxcGetSchedulerParameters, /* 0.5.0 */ .domainSetSchedulerParameters = lxcSetSchedulerParameters, /* 0.5.0 */ .domainInterfaceStats = lxcDomainInterfaceStats, /* 0.7.3 */ +.nodeGetCPUStats = nodeGetCPUStats, /* 0.9.2 */ .nodeGetCellsFreeMemory = nodeGetCellsFreeMemory, /* 0.6.5 */ .nodeGetFreeMemory = nodeGetFreeMemory, /* 0.6.5 */ .domainEventRegister = lxcDomainEventRegister, /* 0.7.0 */ diff --git a/src/nodeinfo.c b/src/nodeinfo.c index f55c83e..a1e37eb 100644 --- a/src/nodeinfo.c +++ b/src/nodeinfo.c @@ -57,12 +57,19 @@ #ifdef __linux__ # define CPUINFO_PATH /proc/cpuinfo # define CPU_SYS_PATH /sys/devices/system/cpu +# define PROCSTAT_PATH /proc/stat + +#define LINUX_NB_CPU_STATS 4 /* NB, this is not static as we need to call it from the testsuite */ int linuxNodeInfoCPUPopulate(FILE *cpuinfo, virNodeInfoPtr nodeinfo, bool need_hyperthreads); +int linuxNodeGetCPUStats(FILE *procstat, + virCPUStatsPtr params, + int *nparams); + /* Return the positive decimal contents of the given * CPU_SYS_PATH/cpu%u/FILE, or -1 on error. If MISSING_OK and the * file could not be found, return 1 instead of an error; this is @@ -378,6 +385,99 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo, return 0; } +#define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / sysconf(_SC_CLK_TCK)) + +int linuxNodeGetCPUStats(FILE *procstat, + virCPUStatsPtr params, + int *nparams) +{ +int ret = -1; +char line[1024]; +unsigned long long usr, ni, sys, idle, iowait; +unsigned long long irq, softirq, steal, guest, guest_nice; + +if ((*nparams) == 0) { +/* Current number of cpu stats supported by linux */ +*nparams = LINUX_NB_CPU_STATS; +ret = 0; +goto cleanup; +} + +if ((*nparams) != LINUX_NB_CPU_STATS) { +nodeReportError(VIR_ERR_INVALID_ARG, +%s, _(Invalid parameter count)); +goto cleanup; +} + +while (fgets(line, sizeof(line), procstat) != NULL) { +char *buf = line; + +if (STRPREFIX(buf, cpu )) { /* aka total logical CPU time */ +int i; + +if (sscanf(buf, + %*s %llu %llu %llu %llu %llu // user ~ iowait + %llu %llu %llu %llu %llu,// irq ~ guest_nice + usr, ni, sys, idle, iowait, + irq, softirq, steal, guest, guest_nice) 4) { +continue; +} + +for (i = 0; i *nparams; i++) { +virCPUStatsPtr param = params[i]; + +switch (i) { +case 0: /* fill kernel cpu time here */ +if (virStrcpyStatic(param-field, VIR_CPU_STATS_KERNEL)== NULL) { +nodeReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field kernel cpu time too long for destination)); +goto cleanup; +} +param-value = (sys + irq + softirq) * TICK_TO_NSEC; +break; + +case 1: /* fill user cpu time here */ +if (virStrcpyStatic(param-field, VIR_CPU_STATS_USER) == NULL) { +nodeReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field kernel cpu time too long for destination)); +goto cleanup; +} +param-value = (usr + ni) * TICK_TO_NSEC; +break; + +case 2: /* fill idle cpu time here */ +if (virStrcpyStatic(param-field, VIR_CPU_STATS_IDLE) == NULL) { +nodeReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field kernel cpu time too long for destination)); +goto cleanup; +} +
Re: [libvirt] [PATCH RFC] Add domainSave/Restore to libxl driver
Am Dienstag 24 Mai 2011 06:06:08 schrieb Jim Fehlig: + +event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SAVED); + +if (libxlVmReap(driver, vm, 1, VIR_DOMAIN_SHUTOFF_SAVED) != 0) { +libxlError(VIR_ERR_INTERNAL_ERROR, + _(Failed to destroy domain '%d'), dom-id); +goto cleanup; +} And here call libxl_domain_destroy() directly instead of libxlVmReap(), allowing the event handler to cleanup the vm. Can you make these changes and ensure all the save/restore issues are resolved in your environment? I made these changes but this leads to another issue. When using the event handler to cleanup the domain there seems to be a race condition. The call to libxl_event_get_domain_death_info returns a value != 1 sometimes and the domain gets not cleaned up. The latest version of the patch I posted in this thread earlier does not have this issue as it cleans up the domain directly. Maybe the every now and then fail of libxl_event_get_domain_death_info is a result of a bug or unhandled race condition in Xen. Cheers, Markus -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Add domainCoreDump to libxl driver
For core dumping to work correctly the following patch for xen is needed: http://lists.xensource.com/archives/html/xen-devel/2011-05/msg01469.html This patch is in xen-unstable and is considered for backport to the xen stable branches. Without this patch the mapped memory pages of the pv guest are not unmapped after core-dump. --- src/libxl/libxl_driver.c | 87 ++ 1 files changed, 87 insertions(+), 0 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index b2cc0e8..75008db 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -1627,6 +1627,92 @@ libxlDomainGetState(virDomainPtr dom, } static int +libxlDomainCoreDump(virDomainPtr dom, const char *to, int flags) +{ +libxlDriverPrivatePtr driver = dom-conn-privateData; +libxlDomainObjPrivatePtr priv; +virDomainObjPtr vm; +virDomainEventPtr event = NULL; +int paused = 0; +int ret = -1; + +virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH, -1); + +libxlDriverLock(driver); +vm = virDomainFindByUUID(driver-domains, dom-uuid); + +if (!vm) { +char uuidstr[VIR_UUID_STRING_BUFLEN]; +virUUIDFormat(dom-uuid, uuidstr); +libxlError(VIR_ERR_NO_DOMAIN, + _(No domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +if (!virDomainObjIsActive(vm)) { +libxlError(VIR_ERR_OPERATION_INVALID, %s, _(Domain is not running)); +goto cleanup; +} + +priv = vm-privateData; + +if (!(flags VIR_DUMP_LIVE) +virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { +if (libxl_domain_pause(priv-ctx, dom-id) != 0) { +libxlError(VIR_ERR_INTERNAL_ERROR, + _(Failed to suspend domain '%d' with libxenlight), + dom-id); +goto cleanup; +} +virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_DUMP); +paused = 1; +} + +if (libxl_domain_core_dump(priv-ctx, dom-id, to) != 0) { +libxlError(VIR_ERR_INTERNAL_ERROR, + _(Failed to dump core of domain '%d' with libxenlight), + dom-id); +goto cleanup; +} + +if (flags VIR_DUMP_CRASH) { +if (libxlVmReap(driver, vm, 1, VIR_DOMAIN_SHUTOFF_CRASHED) != 0) { +libxlError(VIR_ERR_INTERNAL_ERROR, + _(Failed to destroy domain '%d'), dom-id); +goto cleanup; +} + +event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_CRASHED); + +} else if (paused) { +if (libxl_domain_unpause(priv-ctx, dom-id) != 0) { +libxlError(VIR_ERR_INTERNAL_ERROR, + _(Failed to resume domain '%d' with libxenlight), + dom-id); +goto cleanup; +} +virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, + VIR_DOMAIN_RUNNING_UNPAUSED); +} + +if ((flags VIR_DUMP_CRASH) !vm-persistent) { +virDomainRemoveInactive(driver-domains, vm); +vm = NULL; +} + +ret = 0; + +cleanup: +if (vm) +virDomainObjUnlock(vm); +if (event) +libxlDomainEventQueue(driver, event); +libxlDriverUnlock(driver); +return ret; +} + +static int libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, unsigned int flags) { @@ -2722,6 +2808,7 @@ static virDriver libxlDriver = { .domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */ .domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */ .domainGetState = libxlDomainGetState, /* 0.9.2 */ +.domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */ .domainSetVcpus = libxlDomainSetVcpus, /* 0.9.0 */ .domainSetVcpusFlags = libxlDomainSetVcpusFlags, /* 0.9.0 */ .domainGetVcpusFlags = libxlDomainGetVcpusFlags, /* 0.9.0 */ -- 1.7.5.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/9] Add a second URI parameter to virDomainMigratePerform3 method
2011/5/24 Daniel P. Berrange berra...@redhat.com: The virDomainMigratePerform3 currently has a single URI parameter whose meaning varies. It is either - A QEMU migration URI (normal migration) - A libvirtd connection URI (peer2peer migration) Unfortunately when using peer2peer migration, without also using tunnelled migration, it is possible that both URIs are required. This adds a second URI parameter to the virDomainMigratePerform3 method, to cope with this scenario. Each parameter how has a fixed meaning. NB, there is no way to actually take advantage of this yet, since virDomainMigrate/virDomainMigrateToURI do not have any way to provide the 2 separate URIs * daemon/remote.c, src/remote/remote_driver.c, src/remote/remote_protocol.x, src/remote_protocol-structs: Add the second URI parameter to perform3 message * src/driver.h, src/libvirt.c, src/libvirt_internal.h: Add the second URI parameter to Perform3 method * src/libvirt_internal.h, src/qemu/qemu_migration.c, src/qemu/qemu_migration.h: Update to handle URIs correctly --- daemon/remote.c | 13 +++-- src/driver.h | 2 ++ src/libvirt.c | 37 + src/libvirt_internal.h | 6 -- src/qemu/qemu_driver.c | 12 ++-- src/qemu/qemu_migration.c | 26 +- src/qemu/qemu_migration.h | 1 + src/remote/remote_driver.c | 8 ++-- src/remote/remote_protocol.x | 6 -- src/remote_protocol-structs | 1 + 10 files changed, 81 insertions(+), 31 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 7b7323e..2b2c1fd 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -4766,10 +4778,10 @@ virDomainMigratePerform3(virDomainPtr domain, virConnectPtr conn; VIR_DOMAIN_DEBUG(domain, xmlin=%s cookiein=%p, cookieinlen=%d, - cookieout=%p, cookieoutlen=%p, + cookieout=%p, cookieoutlen=%p, dconnuri=%s, uri=%s, flags=%lu, dname=%s, bandwidth=%lu, NULLSTR(xmlin), cookiein, cookieinlen, - cookieout, cookieoutlen, + cookieout, cookieoutlen, NULLSTR(dconnuri), uri, flags, NULLSTR(dname), bandwidth); uri can be NULL here, can't it? So this should use NULLSTR(uri) instead of plain uri. @@ -4817,15 +4829,16 @@ virDomainMigrateFinish3(virConnectPtr dconn, int cookieinlen, char **cookieout, int *cookieoutlen, + const char *dconnuri, const char *uri, unsigned long flags, int cancelled, virDomainPtr *newdom) { VIR_DEBUG(dconn=%p, dname=%s, cookiein=%p, cookieinlen=%d, cookieout=%p, - cookieoutlen=%p, uri=%s, flags=%lu, retcode=%d newdom=%p, + cookieoutlen=%p, dconnuri=%s, uri=%s, flags=%lu, retcode=%d newdom=%p, dconn, NULLSTR(dname), cookiein, cookieinlen, cookieout, - cookieoutlen, uri, flags, cancelled, newdom); + cookieoutlen, NULLSTR(dconnuri), NULLSTR(uri), flags, cancelled, newdom); virResetLastError(); Here it's correct. diff --git a/src/libvirt_internal.h b/src/libvirt_internal.h index c7c1932..3144271 100644 --- a/src/libvirt_internal.h +++ b/src/libvirt_internal.h @@ -161,7 +161,8 @@ int virDomainMigratePerform3(virDomainPtr dom, int cookieinlen, char **cookieout, int *cookieoutlen, - const char *uri, + const char *dconnuri, /* libvirtd URI if Peer2Peer, NULL otherwise */ + const char *uri, /* VM Migration URI */ unsigned long flags, const char *dname, unsigned long resource); @@ -172,7 +173,8 @@ int virDomainMigrateFinish3(virConnectPtr dconn, int cookieinlen, char **cookieout, int *cookieoutlen, - const char *uri, + const char *dconnuri, /* libvirtd URI if Peer2Peer, NULL otherwise */ + const char *uri, /* VM Migration URI */ unsigned long flags, int cancelled, /* Kill the dst VM */ virDomainPtr *newdom); Maybe state in this comments that uri is NULL in the Peer2Peer case, just for clarity. diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 971f53a..014e5ac 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1510,6 +1510,7 @@
Re: [libvirt] [PATCH 1/9] Extend v3 migration protocol to allow app supplied XML for target
2011/5/24 Daniel P. Berrange berra...@redhat.com: This extends the v3 migration protocol such that the virDomainMigrateBegin3 and virDomainMigratePerform3 methods accept an application supplied XML config for the target VM. If the 'xmlin' parameter is NULL, then Begin3 uses the current guest XML as normal. A driver implementing the Begin3 method should either reject all non-NULL 'xmlin' parameters, or strictly validate that the app supplied XML does not change guest ABI. The Perform3 method also needed the xmlin parameter to cope with the Peer2Peer migration sequence. NB it is not yet possible to use this capability since neither of the public virDomainMigrate/virDomainMigrateToURI methods have a way to pass in XML. * daemon/remote.c, src/remote/remote_driver.c, src/remote/remote_protocol.x, src/remote_protocol-structs: Add 'remote_string xmlin' parameter to begin3/perform3 RPC messages * src/libvirt.c, src/driver.h, src/libvirt_internal.h: Add 'const char *xmlin' parameter to Begin3/Perform3 methods * src/qemu/qemu_driver.c, src/qemu/qemu_migration.c, src/qemu/qemu_migration.h: Pass xmlin parameter around migration methods --- daemon/remote.c | 8 +- src/driver.h | 2 + src/libvirt.c | 49 ++--- src/libvirt_internal.h | 2 + src/qemu/qemu_driver.c | 8 -- src/qemu/qemu_migration.c | 17 -- src/qemu/qemu_migration.h | 2 + src/remote/remote_driver.c | 4 +++ src/remote/remote_protocol.x | 2 + src/remote_protocol-structs | 2 + 10 files changed, 75 insertions(+), 21 deletions(-) ACK. Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 3/9] Introduce two method migration APIs
2011/5/24 Daniel P. Berrange berra...@redhat.com: There are two pieces of information which are desirable for migration, which cannot be supplied by applications - The explicit QEMU migration URI, while using Peer2Peer migration - An override for the target VM XML This introduces two new public APIs to support these extra parameters. There is no need for extra wire protocool changes, since this is supported by the v3 migration enhancements * include/libvirt/libvirt.h.in, src/libvirt.c, src/libvirt_public.syms: Add virDomainMigrate2 and virDomainMigrateToURI2 --- include/libvirt/libvirt.h.in | 12 ++ src/libvirt.c | 321 +- src/libvirt_public.syms | 2 + 3 files changed, 332 insertions(+), 3 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 2b2c1fd..4bdcd43 100644 --- a/src/libvirt.c +++ b/src/libvirt.c + +/** + * virDomainMigrate2: + * @domain: a domain object + * @dconn: destination host (a connection object) + * @flags: flags + * @dxml: optional XML config for launching guest on target The other optional parameters have their optional in (). So this optional should be in () too, or the others should have their () removed. + * @dname: (optional) rename domain to this at destination + * @uri: (optional) dest hostname/URI as seen from the source host + * @bandwidth: (optional) specify migration bandwidth limit in Mbps + * + * Migrate the domain object from its current host to the destination + * host given by dconn (a connection to the destination host). + * +/** + * virDomainMigrateToURI2: + * @domain: a domain object + * @dconnuri: optional URI for target libvirtd if @flags includes VIR_MIGRATE_PEER2PEER + * @miguri: optional URI for invoking the migration, not if @flags includs VIR_MIGRATE_TUNNELLED + * @dxml: optional XML config for launching guest on target The same comment from above about the word optional applies here too. + * @flags: flags + * @dname: (optional) rename domain to this at destination + * @bandwidth: (optional) specify migration bandwidth limit in Mbps ACK to be patch as it, but do we really want to add a new public API to 0.9.2 for a feature that no driver implements yet and might not implement it before 0.9.2? As I understand it the URI separation already works but the XML override isn't implemented yet. Or do you already have the XML override implemented but did post the patch yet? Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 4/9] Fix resume on destination when doing non-live tunnelled migration
2011/5/24 Daniel P. Berrange berra...@redhat.com: Before running perform in peer-2-peer migration, the current guest state must be recorded, so that non-live migration can currently unpause a running guest on completion. * src/qemu/qemu_migration.c: Move check for offline guest to fix non-live migration --- src/qemu/qemu_migration.c | 19 ++- 1 files changed, 14 insertions(+), 5 deletions(-) ACK. Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 5/9] Fix SPICE seemless migration hostname
2011/5/24 Daniel P. Berrange berra...@redhat.com: --- src/qemu/qemu_migration.c | 34 -- 1 files changed, 20 insertions(+), 14 deletions(-) @@ -434,26 +437,29 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, VIR_FREE(tmp); /* Check forbid localhost migration */ - if (!(tmp = virXPathString(string(./hostname[1]), ctxt))) { + if (!(mig-remoteHostname = virXPathString(string(./hostname[1]), ctxt))) { qemuReportError(VIR_ERR_INTERNAL_ERROR, %s, _(missing hostname element in migration data)); goto error; } - if (STREQ(tmp, mig-hostname)) { + if (STREQ(mig-remoteHostname, mig-localHostname)) { qemuReportError(VIR_ERR_INTERNAL_ERROR, _(Attempt to migrate guest to the same host %s), - tmp); + mig-remoteHostname); goto error; } - VIR_FREE(tmp); if (!(tmp = virXPathString(string(./hostuuid[1]), ctxt))) { qemuReportError(VIR_ERR_INTERNAL_ERROR, %s, _(missing hostuuid element in migration data)); goto error; } - virUUIDFormat(mig-hostuuid, uuidstr); - if (STREQ(tmp, uuidstr)) { + if (virUUIDParse(tmp, mig-remoteHostuuid) 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + %s, _(malformed hostuuid element in migration data)); + goto error; + } + if (memcmp(mig-remoteHostuuid, mig-localHostuuid, VIR_UUID_BUFLEN) == 0) { qemuReportError(VIR_ERR_INTERNAL_ERROR, _(Attempt to migrate guest to the same host %s), tmp); It took me a moment to figure out what the problem here is and how this patch fixes it. So I suggest you add some explanation to the commit message. The problem is that qemuMigrationCookieXMLParse doesn't really parse the XML formatted cookie into the qemuMigrationCookiePtr pointer but just compares and validates the XML against the local cookie. But in qemuDomainMigrateGraphicsRelocate this local cookie is expected to contain the remote hostname that was never inserted in this cookie. @@ -851,7 +857,7 @@ qemuDomainMigrateGraphicsRelocate(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorGraphicsRelocate(priv-mon, cookie-graphics-type, - cookie-hostname, + cookie-remoteHostname, cookie-graphics-port, cookie-graphics-tlsPort, cookie-graphics-tlsSubject); This patch fixes that problem by making qemuMigrationCookieXMLParse storing the remote hostname in the local cookie. ACK, with an extended commit message. Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 6/9] Fix error propagation in finish method for v3 migration
2011/5/24 Daniel P. Berrange berra...@redhat.com: Even when failing to start CPUs, the finish method was returning a success result. Fix this so that the QEMU process is killed off when finish fails under v3 protocol. Also rename the killOnFinish boolean to 'v3proto' to make it clearer that this is a tunable based on the migration protocol version * src/qemu/qemu_driver.c: Update for API change * src/qemu/qemu_migration.c, src/qemu/qemu_migration.h: Kill VM in qemuMigrationFinish if failing to start CPUs --- src/qemu/qemu_driver.c | 8 src/qemu/qemu_migration.c | 37 - src/qemu/qemu_migration.h | 5 +++-- 3 files changed, 39 insertions(+), 11 deletions(-) ACK. Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] libvirt.so.0: cannot open shared object file: No such file or directory
2011/5/24 YAO yffbr...@gmail.com: 2011/5/24 Matthias Bolte matthias.bo...@googlemail.com 2011/5/24 YAO yffbr...@gmail.com: Hi, I cloned the latest libvirt from git and compiled as follows: cd libvirt ./autogen.sh make sudo make install when installing, it reported /usr/bin/install: cannot stat `./xxx.html': No such file or directory, is that normal? You are probably missing some of the required tools for docs generator like xstlproc or xmllint or the xhtml1 dtd files. Thank you for your suggestions, I installed xsltproc and w3c-dtd-xhtml package on ubuntu 10.04 which fixed this problem. after install completed, I typed virsh, it showed: virsh: error while loading shared libraries: libvirt.so.0: cannot open shared object file: No such file or directory, how to fix it? I found libvirt.so.0 in /usr/local/lib, but why virsh can't find it? the same problem happens on /usr/local/sbin/libvirtd, it can't find libvirt-qemu.so.0 which is also located in /usr/local/lib. So, what's the general procedure to make git version work? Is this the first thing that got installed under /usr/local? You might need to update the ld cache by running ldconfig. It seems the system didn't search the /usr/local/lib, so I appended --prefix=/usr on ./autogen.sh to relocate the installation. Here's another question: I know the sVirt was merged into libvirt, did all the codes reside in src/security? I think so. How should I start to contribute? You already have a working git clone, that was the first step. The next step probably depends on what you want to do. Do you want to improve the security drivers or do you want to support an additional framework aside from SELinux and AppArmor, or do you want to restructure the security drivers, etc? If you want to do major or braking changes you should start by describing and discussing on this list what you want to do and get feedback on it. If you want to fix bugs or improve the security drivers you should probably just get familiar with the code and start to program. To get changes included into the official codebase send patches to this list to get a review. The preferred tool for sending patches is git send-email. You should also have a look at http://libvirt.org/hacking.html Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RESEND PATCH 1/3] Add new flags for setting memory parameters
This enables users to modify memory parameters for inactive domains --- include/libvirt/libvirt.h.in |7 +++ tools/virsh.c| 26 +++--- tools/virsh.pod |7 +++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 7cd6e13..0058d17 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -871,6 +871,13 @@ typedef enum { VIR_DOMAIN_MEMORY_PARAM_BOOLEAN = VIR_TYPED_PARAM_BOOLEAN, } virMemoryParameterType; +/* flags for setting memory parameters */ +typedef enum { +VIR_DOMAIN_MEMORY_PARAM_CURRENT = 0,/* affect current domain state */ +VIR_DOMAIN_MEMORY_PARAM_LIVE= (1 0), /* affect active domain */ +VIR_DOMAIN_MEMORY_PARAM_CONFIG = (1 1) /* affect next boot */ +} virMemoryParamFlags; + /** * VIR_DOMAIN_MEMORY_FIELD_LENGTH: * diff --git a/tools/virsh.c b/tools/virsh.c index de49489..ea8fd13 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -3307,6 +3307,9 @@ static const vshCmdOptDef opts_memtune[] = { N_(Max memory plus swap in kilobytes)}, {min-guarantee, VSH_OT_INT, VSH_OFLAG_NONE, N_(Min guaranteed memory in kilobytes)}, +{config, VSH_OT_BOOL, 0, N_(affect next boot)}, +{live, VSH_OT_BOOL, 0, N_(affect running domain)}, +{current, VSH_OT_BOOL, 0, N_(affect current domain)}, {NULL, 0, 0, NULL} }; @@ -3320,6 +3323,23 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) unsigned int i = 0; virMemoryParameterPtr params = NULL, temp = NULL; bool ret = false; +unsigned int flags = 0; +int current = vshCommandOptBool(cmd, current); +int config = vshCommandOptBool(cmd, config); +int live = vshCommandOptBool(cmd, live); + +if (current) { +if (live || config) { +vshError(ctl, %s, _(--current must be specified exclusively)); +return false; +} +flags = VIR_DOMAIN_MEMORY_PARAM_CURRENT; +} else { +if (config) +flags |= VIR_DOMAIN_MEMORY_PARAM_CONFIG; +if (live) +flags |= VIR_DOMAIN_MEMORY_PARAM_LIVE; +} if (!vshConnectionUsability(ctl, ctl-conn)) return false; @@ -3350,7 +3370,7 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) if (nparams == 0) { /* get the number of memory parameters */ -if (virDomainGetMemoryParameters(dom, NULL, nparams, 0) != 0) { +if (virDomainGetMemoryParameters(dom, NULL, nparams, flags) != 0) { vshError(ctl, %s, _(Unable to get number of memory parameters)); goto cleanup; @@ -3364,7 +3384,7 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) /* now go get all the memory parameters */ params = vshCalloc(ctl, nparams, sizeof(*params)); -if (virDomainGetMemoryParameters(dom, params, nparams, 0) != 0) { +if (virDomainGetMemoryParameters(dom, params, nparams, flags) != 0) { vshError(ctl, %s, _(Unable to get memory parameters)); goto cleanup; } @@ -3444,7 +3464,7 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) if (temp-value.ul == -1) temp-value.ul = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED; } -if (virDomainSetMemoryParameters(dom, params, nparams, 0) != 0) +if (virDomainSetMemoryParameters(dom, params, nparams, flags) != 0) vshError(ctl, %s, _(Unable to change memory parameters)); else ret = true; diff --git a/tools/virsh.pod b/tools/virsh.pod index ef01f41..9251db6 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -644,6 +644,13 @@ flags, the current settings are displayed; with a flag, the appropriate limit is adjusted if supported by the hypervisor. LXC and QEMU/KVM support I--hard-limit, I--soft-limit, and I--swap-hard-limit. +If I--live is specified, affect a running guest. +If I--config is specified, affect the next boot of a persistent guest. +If I--current is specified, affect the current guest state. +Both I--live and I--current flags may be given, but I--current is +exclusive. If no flag is specified, behavior is different depending +on hypervisor. + For QEMU/KVM, the parameters are applied to the QEMU process as a whole. Thus, when counting them, one needs to add up guest RAM, guest video RAM, and some memory overhead of QEMU itself. The last piece is hard to determine so -- 1.7.3.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RESEND PATCH 0/3] support for changing memory parameters for inactive domains
This series enables user to change memory parameters for inactive domains from virsh command line. This series is rebased on the latest git tree since patch 2 of the previous sent series is applied wrongly by git on the latest git tree. Hu Tao (3): Add new flags for setting memory parameters update qemuDomainGetMemoryParameters to use flags update qemuDomainSetMemoryParameters to use flags include/libvirt/libvirt.h.in |7 ++ src/qemu/qemu_driver.c | 206 +- tools/virsh.c| 26 +- tools/virsh.pod |7 ++ 4 files changed, 199 insertions(+), 47 deletions(-) -- 1.7.3.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RESEND PATCH 3/3] update qemuDomainSetMemoryParameters to use flags
--- src/qemu/qemu_driver.c | 106 +++- 1 files changed, 77 insertions(+), 29 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f04e443..9057a83 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4812,20 +4812,20 @@ cleanup: static int qemuDomainSetMemoryParameters(virDomainPtr dom, virMemoryParameterPtr params, int nparams, - unsigned int flags ATTRIBUTE_UNUSED) + unsigned int flags) { struct qemud_driver *driver = dom-conn-privateData; int i; +virDomainDefPtr persistentDef = NULL; virCgroupPtr group = NULL; virDomainObjPtr vm = NULL; int ret = -1; +bool isActive; + +virCheckFlags(VIR_DOMAIN_MEMORY_PARAM_LIVE | + VIR_DOMAIN_MEMORY_PARAM_CONFIG, -1); qemuDriverLock(driver); -if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY)) { -qemuReportError(VIR_ERR_OPERATION_INVALID, -%s, _(cgroup memory controller is not mounted)); -goto cleanup; -} vm = virDomainFindByUUID(driver-domains, dom-uuid); @@ -4835,16 +4835,43 @@ static int qemuDomainSetMemoryParameters(virDomainPtr dom, goto cleanup; } -if (!virDomainObjIsActive(vm)) { -qemuReportError(VIR_ERR_OPERATION_INVALID, -%s, _(domain is not running)); -goto cleanup; +isActive = virDomainObjIsActive(vm); + +if (flags == VIR_DOMAIN_MEMORY_PARAM_CURRENT) { +if (isActive) +flags = VIR_DOMAIN_MEMORY_PARAM_LIVE; +else +flags = VIR_DOMAIN_MEMORY_PARAM_CONFIG; } -if (virCgroupForDomain(driver-cgroup, vm-def-name, group, 0) != 0) { -qemuReportError(VIR_ERR_INTERNAL_ERROR, -_(cannot find cgroup for domain %s), vm-def-name); -goto cleanup; +if (flags VIR_DOMAIN_MEMORY_PARAM_LIVE) { +if (!isActive) { +qemuReportError(VIR_ERR_OPERATION_INVALID, +%s, _(domain is not running)); +goto cleanup; +} + +if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY)) { +qemuReportError(VIR_ERR_OPERATION_INVALID, +%s, _(cgroup memory controller is not mounted)); +goto cleanup; +} + +if (virCgroupForDomain(driver-cgroup, vm-def-name, group, 0) != 0) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +_(cannot find cgroup for domain %s), vm-def-name); +goto cleanup; +} +} + +if (flags VIR_DOMAIN_MEMORY_PARAM_CONFIG) { +if (!vm-persistent) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(cannot change persistent config of a transient domain)); +goto cleanup; +} +if (!(persistentDef = virDomainObjGetPersistentDef(driver-caps, vm))) +goto cleanup; } ret = 0; @@ -4860,11 +4887,17 @@ static int qemuDomainSetMemoryParameters(virDomainPtr dom, continue; } -rc = virCgroupSetMemoryHardLimit(group, params[i].value.ul); -if (rc != 0) { -virReportSystemError(-rc, %s, - _(unable to set memory hard_limit tunable)); -ret = -1; +if (flags VIR_DOMAIN_MEMORY_PARAM_LIVE) { +rc = virCgroupSetMemoryHardLimit(group, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory hard_limit tunable)); +ret = -1; +} +} + +if (flags VIR_DOMAIN_MEMORY_PARAM_CONFIG) { +persistentDef-mem.hard_limit = params[i].value.ul; } } else if (STREQ(param-field, VIR_DOMAIN_MEMORY_SOFT_LIMIT)) { int rc; @@ -4875,11 +4908,17 @@ static int qemuDomainSetMemoryParameters(virDomainPtr dom, continue; } -rc = virCgroupSetMemorySoftLimit(group, params[i].value.ul); -if (rc != 0) { -virReportSystemError(-rc, %s, - _(unable to set memory soft_limit tunable)); -ret = -1; +if (flags VIR_DOMAIN_MEMORY_PARAM_LIVE) { +rc = virCgroupSetMemorySoftLimit(group, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory soft_limit tunable)); +ret = -1; +} +} + +if (flags
[libvirt] [RESEND PATCH 2/3] update qemuDomainGetMemoryParameters to use flags
--- src/qemu/qemu_driver.c | 100 --- 1 files changed, 85 insertions(+), 15 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 691965d..f04e443 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4918,23 +4918,22 @@ cleanup: static int qemuDomainGetMemoryParameters(virDomainPtr dom, virMemoryParameterPtr params, int *nparams, - unsigned int flags ATTRIBUTE_UNUSED) + unsigned int flags) { struct qemud_driver *driver = dom-conn-privateData; int i; virCgroupPtr group = NULL; virDomainObjPtr vm = NULL; +virDomainDefPtr persistentDef = NULL; unsigned long long val; int ret = -1; int rc; +bool isActive; -qemuDriverLock(driver); +virCheckFlags(VIR_DOMAIN_MEMORY_PARAM_LIVE | + VIR_DOMAIN_MEMORY_PARAM_CONFIG, -1); -if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY)) { -qemuReportError(VIR_ERR_OPERATION_INVALID, -%s, _(cgroup memory controller is not mounted)); -goto cleanup; -} +qemuDriverLock(driver); vm = virDomainFindByUUID(driver-domains, dom-uuid); @@ -4944,10 +4943,43 @@ static int qemuDomainGetMemoryParameters(virDomainPtr dom, goto cleanup; } -if (!virDomainObjIsActive(vm)) { -qemuReportError(VIR_ERR_OPERATION_INVALID, -%s, _(domain is not running)); -goto cleanup; +isActive = virDomainObjIsActive(vm); + +if (flags == VIR_DOMAIN_MEMORY_PARAM_CURRENT) { +if (isActive) +flags = VIR_DOMAIN_MEMORY_PARAM_LIVE; +else +flags = VIR_DOMAIN_MEMORY_PARAM_CONFIG; +} + +if (flags VIR_DOMAIN_MEMORY_PARAM_LIVE) { +if (!isActive) { +qemuReportError(VIR_ERR_OPERATION_INVALID, +%s, _(domain is not running)); +goto cleanup; +} + +if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY)) { +qemuReportError(VIR_ERR_OPERATION_INVALID, +%s, _(cgroup memory controller is not mounted)); +goto cleanup; +} + +if (virCgroupForDomain(driver-cgroup, vm-def-name, group, 0) != 0) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +_(cannot find cgroup for domain %s), vm-def-name); +goto cleanup; +} +} + +if (flags VIR_DOMAIN_MEMORY_PARAM_CONFIG) { +if (!vm-persistent) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(cannot change persistent config of a transient domain)); +goto cleanup; +} +if (!(persistentDef = virDomainObjGetPersistentDef(driver-caps, vm))) +goto cleanup; } if ((*nparams) == 0) { @@ -4963,10 +4995,47 @@ static int qemuDomainGetMemoryParameters(virDomainPtr dom, goto cleanup; } -if (virCgroupForDomain(driver-cgroup, vm-def-name, group, 0) != 0) { -qemuReportError(VIR_ERR_INTERNAL_ERROR, -_(cannot find cgroup for domain %s), vm-def-name); -goto cleanup; +if (flags VIR_DOMAIN_MEMORY_PARAM_CONFIG) { +for (i = 0; i *nparams; i++) { +virMemoryParameterPtr param = params[i]; +val = 0; +param-value.ul = 0; +param-type = VIR_DOMAIN_MEMORY_PARAM_ULLONG; + +switch (i) { +case 0: /* fill memory hard limit here */ +if (virStrcpyStatic(param-field, VIR_DOMAIN_MEMORY_HARD_LIMIT) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field memory hard limit too long for destination)); +goto cleanup; +} +param-value.ul = persistentDef-mem.hard_limit; +break; + +case 1: /* fill memory soft limit here */ +if (virStrcpyStatic(param-field, VIR_DOMAIN_MEMORY_SOFT_LIMIT) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field memory soft limit too long for destination)); +goto cleanup; +} +param-value.ul = persistentDef-mem.soft_limit; +break; + +case 2: /* fill swap hard limit here */ +if (virStrcpyStatic(param-field, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field swap hard limit too long for destination)); +goto cleanup; +} +param-value.ul =
Re: [libvirt] [PATCH 8/9] Fix preservation of errors across migration steps
2011/5/24 Daniel P. Berrange berra...@redhat.com: When doing migration, if an error occurs in Perform, it must not be overwritten during Finish/Confirm steps. If an error occurs in Finish, it must not be overwritten in Confirm. Previous commit a9d12c2444e43a0d3e5135eb15b4b62a7c011427 added code to qemudDomainMigrateFinish2 to preserve the error. This is not the right place, because it is not applicable in non-p2p migration. The src/libvirt.c virDomainMigrateV2/3 methods need code to preserve errors for non-p2p migration, while the doPeer2PeerMigrate2 and doPeer2PeerMigrate3 methods contain code to preverse errors for p2p migration. Remove the bogus error preservation from qemudDomainMigrateFinish2 and qemudDomainMigrateFinish3. Fix virDomainMigrateV3 and doPeer2PeerMigrate3 so that they preserve any error hit during the Finish3 step, before invoking Confirm3. Finally if qemuMigrationFinish fails to resume the CPUs, it must preserve the error before tearing down the VM, so that VM cleanup doesn't overwrite it. * src/libvirt.c: Preserve error before invoking Confirm3 * src/qemu/qemu_driver.c: Remove bogus error preservation code in qemudDomainMigrateFinish2/qemudDomainMigrateFinish3 * src/qemu/qemu_migration.c: Preserve error before invoking Confirm3 and after resume fails in qemuMigrationFinish. --- src/libvirt.c | 6 ++ src/qemu/qemu_driver.c | 24 src/qemu/qemu_migration.c | 23 --- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 280b8cb..a0365ac 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2382,6 +2394,11 @@ cleanup: if (event) qemuDomainEventQueue(driver, event); qemuMigrationCookieFree(mig); + if (orig_err) { + virSetError(orig_err); + virFreeError(orig_err); + orig_err = virGetLastError(); + } return dom; } The last virGetLastError isn't necessary and can be removed, can't it? ACK. Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 0/6] Add virNodeGetMemoryStats() API
Hi, everyone. I wrote new API called virNodeGetMemoryStats(). It returns total/free/buffer/cached memory of the node from /proc/meminfo. The user I/F is like virNodeGetCPUStats(). Previous discussion is here. (See about virNodeGetFreeMemory() part.) http://www.mail-archive.com/libvir-list@redhat.com/msg32553.html This patch series based on latest git tree. If my virNodeGetCPUStats() patch series applied, I'll rebase on it. Minoru Usui (6): virNodeGetMemoryStats: Expose new API virNodeGetMemoryStats: Define internal driver API virNodeGetMemoryStats: Implement public API virNodeGetMemoryStats: Implement remote protocol virNodeGetMemoryStats: Implement virsh support virNodeGetMemoryStats: Implement linux support daemon/remote.c | 76 + include/libvirt/libvirt.h.in | 65 +++- src/driver.h |8 +++ src/libvirt.c| 81 +++ src/libvirt_private.syms |1 + src/libvirt_public.syms |1 + src/lxc/lxc_driver.c |1 + src/nodeinfo.c | 97 ++ src/nodeinfo.h |4 ++ src/qemu/qemu_driver.c |1 + src/remote/remote_driver.c | 63 +++ src/remote/remote_protocol.x | 21 +- src/uml/uml_driver.c |1 + tools/virsh.c| 51 ++ tools/virsh.pod |4 ++ 15 files changed, 473 insertions(+), 2 deletions(-) -- Minoru Usui u...@mxm.nes.nec.co.jp -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 1/6] virNodeGetMemoryStats: Expose new API
virNodeGetMemoryStats: Expose new API Signed-off-by: Minoru Usui u...@mxm.nes.nec.co.jp --- include/libvirt/libvirt.h.in | 65 +- src/libvirt_public.syms |1 + 2 files changed, 65 insertions(+), 1 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 7cd6e13..69e2255 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -280,6 +280,58 @@ struct _virNodeInfo { unsigned int threads;/* number of threads per core */ }; +/** + * VIR_MEMORY_STATS_FIELD_LENGTH: + * + * Macro providing the field length of virMemoryStats + */ +#define VIR_MEMORY_STATS_FIELD_LENGTH 80 + +/** + * VIR_MEMORY_STATS_TOTAL: + * + * Macro for the total memory: it represents the maximum memory. + */ + +#define VIR_MEMORY_STATS_TOTAL total + +/** + * VIR_MEMORY_STATS_FREE: + * + * Macro for the free memory: On linux, it includes buffer and cached memory. + */ + +#define VIR_MEMORY_STATS_FREE free + +/** + * VIR_MEMORY_STATS_BUFFERS: + * + * Macro for the buffer memory: + */ + +#define VIR_MEMORY_STATS_BUFFERS buffers + +/** + * VIR_MEMORY_STATS_CACHED: + * + * Macro for the cached memory: + */ + +#define VIR_MEMORY_STATS_CACHED cached + +/** + * virMemoryStats: + * + * a virMemoryStats is a structure filled by virNodeGetMemoryStats() + * and providing the information of the memory of the Node. + */ + +typedef struct _virMemoryStats virMemoryStats; + +struct _virMemoryStats { +char field[VIR_MEMORY_STATS_FIELD_LENGTH]; +unsigned long long value; +}; /* Common data types shared among interfaces with name/type/value lists. */ @@ -565,6 +617,14 @@ int virDomainMigrateSetMaxSpeed(virDomainPtr domain, typedef virNodeInfo *virNodeInfoPtr; /** + * virMemoryStatsPtr: + * + * a virMemoryStatsPtr is a pointer to a virMemoryStats structure. + */ + +typedef virMemoryStats *virMemoryStatsPtr; + +/** * virConnectFlags * * Flags when opening a connection to a hypervisor @@ -697,7 +757,10 @@ int virConnectGetMaxVcpus (virConnectPtr conn, int virNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info); char * virConnectGetCapabilities (virConnectPtr conn); - +int virNodeGetMemoryStats(virConnectPtr conn, + virMemoryStatsPtr params, + int *nparams, + unsigned int flags); unsigned long long virNodeGetFreeMemory(virConnectPtr conn); int virNodeGetSecurityModel (virConnectPtr conn, diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 0590535..277978e 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -442,6 +442,7 @@ LIBVIRT_0.9.2 { virDomainInjectNMI; virDomainScreenshot; virDomainSetSchedulerParametersFlags; + virNodeGetMemoryStats; } LIBVIRT_0.9.0; # define new API here using predicted next version number -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 2/6] virNodeGetMemoryStats: Define internal driver API
virNodeGetMemoryStats: Define internal driver API Signed-off-by: Minoru Usui u...@mxm.nes.nec.co.jp --- src/driver.h |8 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index 450dd53..daced6b 100644 --- a/src/driver.h +++ b/src/driver.h @@ -364,6 +364,13 @@ typedef struct _virDriver virDriver; typedef virDriver *virDriverPtr; typedef int +(*virDrvNodeGetMemoryStats) +(virConnectPtr conn, + virMemoryStatsPtr params, + int *nparams, + unsigned int flags); + +typedef int (*virDrvNodeGetCellsFreeMemory) (virConnectPtr conn, unsigned long long *freeMems, @@ -694,6 +701,7 @@ struct _virDriver { virDrvDomainBlockPeek domainBlockPeek; virDrvDomainMemoryPeek domainMemoryPeek; virDrvDomainGetBlockInfodomainGetBlockInfo; +virDrvNodeGetMemoryStats nodeGetMemoryStats; virDrvNodeGetCellsFreeMemory nodeGetCellsFreeMemory; virDrvNodeGetFreeMemorynodeGetFreeMemory; virDrvDomainEventRegister domainEventRegister; -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 4/6] virNodeGetMemoryStats: Implement remote protocol
virNodeGetMemoryStats: Implement remote protocol Signed-off-by: Minoru Usui u...@mxm.nes.nec.co.jp --- daemon/remote.c | 76 ++ src/remote/remote_driver.c | 63 ++ src/remote/remote_protocol.x | 21 +++- 3 files changed, 159 insertions(+), 1 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 80783b3..190e213 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -1788,6 +1788,82 @@ cleanup: return rv; } +static int +remoteDispatchNodeGetMemoryStats (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_node_get_memory_stats_args *args, + remote_node_get_memory_stats_ret *ret) +{ +virMemoryStatsPtr params = NULL; +int i; +int nparams = args-nparams; +unsigned int flags; +int rv = -1; + +if (!conn) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open)); +goto cleanup; +} + +flags = args-flags; + +if (nparams REMOTE_NODE_MEMORY_STATS_MAX) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(nparams too large)); +goto cleanup; +} +if (VIR_ALLOC_N(params, nparams) 0) { +virReportOOMError(); +goto cleanup; +} + +if (virNodeGetMemoryStats(conn, params, nparams, flags) 0) +goto cleanup; + +/* In this case, we need to send back the number of parameters + * supported + */ +if (args-nparams == 0) { +ret-nparams = nparams; +goto success; +} + +/* Serialise the memory parameters. */ +ret-params.params_len = nparams; +if (VIR_ALLOC_N(ret-params.params_val, nparams) 0) +goto no_memory; + +for (i = 0; i nparams; ++i) { +/* remoteDispatchClientRequest will free this: */ +ret-params.params_val[i].field = strdup(params[i].field); +if (ret-params.params_val[i].field == NULL) +goto no_memory; + +ret-params.params_val[i].value = params[i].value; +} + +success: +rv = 0; + +cleanup: +if (rv 0) { +remoteDispatchError(rerr); +if (ret-params.params_val) { +for (i = 0; i nparams; i++) +VIR_FREE(ret-params.params_val[i].field); +VIR_FREE(ret-params.params_val); +} +} +VIR_FREE(params); +return rv; + +no_memory: +virReportOOMError(); +goto cleanup; +} + /*-*/ static int diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 1691dab..475fd74 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1694,6 +1694,68 @@ done: } static int +remoteNodeGetMemoryStats (virConnectPtr conn, + virMemoryStatsPtr params, int *nparams, + unsigned int flags) +{ +int rv = -1; +remote_node_get_memory_stats_args args; +remote_node_get_memory_stats_ret ret; +int i = -1; +struct private_data *priv = conn-privateData; + +remoteDriverLock(priv); + +args.nparams = *nparams; +args.flags = flags; + +memset (ret, 0, sizeof ret); +if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_MEMORY_STATS, + (xdrproc_t) xdr_remote_node_get_memory_stats_args, (char *) args, + (xdrproc_t) xdr_remote_node_get_memory_stats_ret, (char *) ret) == -1) +goto done; + +/* Check the length of the returned list carefully. */ +if (ret.params.params_len REMOTE_NODE_MEMORY_STATS_MAX || +ret.params.params_len *nparams) { +remoteError(VIR_ERR_RPC, %s, +_(remoteNodeGetMemoryStats: + returned number of stats exceeds limit)); +goto cleanup; +} +/* Handle the case when the caller does not know the number of stats + * and is asking for the number of stats supported + */ +if (*nparams == 0) { +*nparams = ret.nparams; +rv = 0; +goto cleanup; +} + +*nparams = ret.params.params_len; + +/* Deserialise the result. */ +for (i = 0; i *nparams; ++i) { +if (virStrcpyStatic(params[i].field, ret.params.params_val[i].field) == NULL) { +remoteError(VIR_ERR_INTERNAL_ERROR, +_(Stats %s too big for destination), +ret.params.params_val[i].field); +goto cleanup; +} +params[i].value = ret.params.params_val[i].value; +} + +rv = 0; + +cleanup: +xdr_free ((xdrproc_t) xdr_remote_node_get_memory_stats_ret, + (char *) ret); +done: +remoteDriverUnlock(priv); +return
[libvirt] [PATCH 6/6] virNodeGetMemoryStats: Implement linux support
virNodeGetMemoryStats: Implement linux support Signed-off-by: Minoru Usui u...@mxm.nes.nec.co.jp --- src/libvirt_private.syms |1 + src/lxc/lxc_driver.c |1 + src/nodeinfo.c | 97 ++ src/nodeinfo.h |4 ++ src/qemu/qemu_driver.c |1 + src/uml/uml_driver.c |1 + 6 files changed, 105 insertions(+), 0 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 4cb8dda..5e55cf1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -689,6 +689,7 @@ virNodeDeviceObjUnlock; # nodeinfo.h nodeCapsInitNUMA; +nodeGetMemoryStats; nodeGetCellsFreeMemory; nodeGetFreeMemory; nodeGetInfo; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 9e09c95..41b6260 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2754,6 +2754,7 @@ static virDriver lxcDriver = { .domainGetSchedulerParameters = lxcGetSchedulerParameters, /* 0.5.0 */ .domainSetSchedulerParameters = lxcSetSchedulerParameters, /* 0.5.0 */ .domainInterfaceStats = lxcDomainInterfaceStats, /* 0.7.3 */ +.nodeGetMemoryStats = nodeGetMemoryStats, /* 0.9.2 */ .nodeGetCellsFreeMemory = nodeGetCellsFreeMemory, /* 0.6.5 */ .nodeGetFreeMemory = nodeGetFreeMemory, /* 0.6.5 */ .domainEventRegister = lxcDomainEventRegister, /* 0.7.0 */ diff --git a/src/nodeinfo.c b/src/nodeinfo.c index f55c83e..63d7822 100644 --- a/src/nodeinfo.c +++ b/src/nodeinfo.c @@ -57,11 +57,17 @@ #ifdef __linux__ # define CPUINFO_PATH /proc/cpuinfo # define CPU_SYS_PATH /sys/devices/system/cpu +# define MEMINFO_PATH /proc/meminfo + +# define LINUX_NB_MEMORY_STATS 4 /* NB, this is not static as we need to call it from the testsuite */ int linuxNodeInfoCPUPopulate(FILE *cpuinfo, virNodeInfoPtr nodeinfo, bool need_hyperthreads); +int linuxNodeGetMemoryStats(FILE *meminfo, +virMemoryStatsPtr params, +int *nparams); /* Return the positive decimal contents of the given * CPU_SYS_PATH/cpu%u/FILE, or -1 on error. If MISSING_OK and the @@ -378,6 +384,71 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo, return 0; } +int linuxNodeGetMemoryStats(FILE *meminfo, +virMemoryStatsPtr params, +int *nparams) +{ +int ret = -1; +int i = 0, j = 0; +char line[1024]; +char meminfo_hdr[VIR_MEMORY_STATS_FIELD_LENGTH]; +unsigned long val; +struct field_conv { +const char *meminfo_hdr; // meminfo header +const char *field;// MemoryStats field name +} field_conv[] = { +{MemTotal:, VIR_MEMORY_STATS_TOTAL}, +{MemFree:, VIR_MEMORY_STATS_FREE}, +{Buffers:, VIR_MEMORY_STATS_BUFFERS}, +{Cached:, VIR_MEMORY_STATS_CACHED}, +{NULL,NULL} +}; + +if ((*nparams) == 0) { +/* Current number of memory stats supported by linux */ +*nparams = LINUX_NB_MEMORY_STATS; +ret = 0; +goto cleanup; +} + +if ((*nparams) != LINUX_NB_MEMORY_STATS) { +nodeReportError(VIR_ERR_INVALID_ARG, +%s, _(Invalid stats count)); +goto cleanup; +} + +while (fgets(line, sizeof(line), meminfo) != NULL) { +char *buf = line; + +if (sscanf(buf, %s %lu kB, meminfo_hdr, val) 2) { +continue; +} + +for (j = 0; field_conv[j].meminfo_hdr != NULL; j++) { +struct field_conv *convp = field_conv[j]; + +if (STREQ(meminfo_hdr, convp-meminfo_hdr)) { +virMemoryStatsPtr param = params[i++]; + +if (virStrcpyStatic(param-field, convp-field) == NULL) { +nodeReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field kernel memory too long for destination)); +goto cleanup; +} +param-value = val; +break; +} +} +} + +ret = 0; +goto cleanup; + +nodeReportError(VIR_ERR_INTERNAL_ERROR, %s, _(no \'cpu \' line found)); + +cleanup: +return ret; +} #endif int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) { @@ -416,6 +487,32 @@ int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) { #endif } +int nodeGetMemoryStats(virConnectPtr conn ATTRIBUTE_UNUSED, + virMemoryStatsPtr params, + int *nparams, + unsigned int flags ATTRIBUTE_UNUSED) +{ +#ifdef __linux__ +{ +int ret; +FILE *meminfo = fopen(MEMINFO_PATH, r); +if (!meminfo) { +virReportSystemError(errno, + _(cannot open %s), MEMINFO_PATH); +return -1; +} +ret = linuxNodeGetMemoryStats(meminfo, params, nparams); +
[libvirt] [PATCH 3/6] virNodeGetMemoryStats: Implement public API
virNodeGetMemoryStats: Implement public API Signed-off-by: Minoru Usui u...@mxm.nes.nec.co.jp --- src/libvirt.c | 81 + 1 files changed, 81 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index ff16c48..2205ebb 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -4967,6 +4967,87 @@ error: } /** + * virNodeGetMemoryStats: + * @conn: pointer to the hypervisor connection. + * @params: pointer to node memory stats objects + * @nparams: number of node memory stats (this value should be same or + * less than the number of stats supported) + * @flags: currently unused, for future extension. always pass 0. + * + * This function provides memory stats of the node. + * The @params array will be filled with the values equal to the number of + * stats suggested by @nparams + * + * As the value of @nparams is dynamic, call the API setting @nparams to 0 and + * @params as NULL, the API returns the number of parameters supported by the + * HV by updating @nparams on SUCCESS. The caller should then allocate @params + * array, i.e. (sizeof(@virMemoryStats) * @nparams) bytes and call + * the API again. + * + * Here is the sample code snippet: + * + * if ((virNodeGetMemoryStats(conn, NULL, nparams, 0) == 0) + * (nparams != 0)) { + * params = vshMalloc(ctl, sizeof(virMemoryStats) * nparams); + * memset(params, 0, sizeof(virMemoryStats) * nparams); + * if (virNodeGetMemoryStats(conn, params, nparams, 0)) { + * vshError(ctl, %s, _(Unable to get node memory stats)); + * goto error; + * } + * } + * + * This function doesn't requires privileged access to the hypervisor. + * This function expects the caller to allocate the @params. + * + * Memory Stats: + * + * VIR_MEMORY_STATS_TOTAL: + * The total memory usage.(KB) + * VIR_MEMORY_STATS_FREE: + * The free memory usage.(KB) + * On linux, this usage includes buffers and cached. + * VIR_MEMORY_STATS_BUFFERS: + * The buffers memory usage.(KB) + * VIR_MEMORY_STATS_CACHED: + * The cached memory usage.(KB) + * + * Returns -1 in case of error, 0 in case of success. + */ +int virNodeGetMemoryStats (virConnectPtr conn, + virMemoryStatsPtr params, + int *nparams, unsigned int flags) +{ +VIR_DEBUG(conn=%p, params=%p, nparams=%d, flags=%u, + conn, params, nparams ? *nparams : -1, flags); + +virResetLastError(); + +if (!VIR_IS_CONNECT(conn)) { +virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); +virDispatchError(NULL); +return -1; +} + +if ((nparams == NULL) || (*nparams 0)) { +virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__); +goto error; +} + +if (conn-driver-nodeGetMemoryStats) { +int ret; +ret = conn-driver-nodeGetMemoryStats (conn, params, nparams, flags); +if (ret 0) +goto error; +return ret; +} +virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: +virDispatchError(conn); +return -1; +} + +/** * virNodeGetFreeMemory: * @conn: pointer to the hypervisor connection * -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 5/6] virNodeGetMemoryStats: Implement virsh support
virNodeGetMemoryStats: Implement virsh support Add nodecpustats subcommand to virsh. This subcommand prints below output. [Linux] # build/tools/virsh nodememstats total : 8058876 kB free : 5042384 kB buffers: 832728 kB cached : 776736 kB Signed-off-by: Minoru Usui u...@mxm.nes.nec.co.jp --- tools/virsh.c | 51 +++ tools/virsh.pod |4 2 files changed, 55 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index de49489..9e57b27 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -3490,6 +3490,56 @@ cmdNodeinfo(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } /* + * nodememstats command + */ +static const vshCmdInfo info_nodememstats[] = { +{help, N_(Prints memory stats of the node.)}, +{desc, N_(Returns memory stats of the node.(KB))}, +{NULL, NULL} +}; + +static bool +cmdNodememstats(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED) +{ +int nparams = 0; +unsigned int i = 0; +virMemoryStatsPtr params = NULL; +bool ret = false; + +if (!vshConnectionUsability(ctl, ctl-conn)) +return false; + +/* get the number of memory parameters */ +if (virNodeGetMemoryStats(ctl-conn, NULL, nparams, 0) != 0) { +vshError(ctl, %s, + _(Unable to get number of memory stats)); +goto cleanup; +} + +if (nparams == 0) { +/* nothing to output */ +ret = true; +goto cleanup; +} + +/* now go get all the memory parameters */ +params = vshCalloc(ctl, nparams, sizeof(*params)); +if (virNodeGetMemoryStats(ctl-conn, params, nparams, 0) != 0) { +vshError(ctl, %s, _(Unable to get memory stats)); +goto cleanup; +} + +for (i = 0; i nparams; i++) +vshPrint(ctl, %-15s: %20llu kB\n, params[i].field, params[i].value); + +ret = true; + + cleanup: +VIR_FREE(params); +return ret; +} + +/* * capabilities command */ static const vshCmdInfo info_capabilities[] = { @@ -10998,6 +11048,7 @@ static const vshCmdDef hostAndHypervisorCmds[] = { {freecell, cmdFreecell, opts_freecell, info_freecell, 0}, {hostname, cmdHostname, NULL, info_hostname, 0}, {nodeinfo, cmdNodeinfo, NULL, info_nodeinfo, 0}, +{nodememstats, cmdNodememstats, NULL, info_nodememstats, 0}, {qemu-monitor-command, cmdQemuMonitorCommand, opts_qemu_monitor_command, info_qemu_monitor_command, 0}, {sysinfo, cmdSysinfo, NULL, info_sysinfo, 0}, diff --git a/tools/virsh.pod b/tools/virsh.pod index ef01f41..bafc6f2 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -237,6 +237,10 @@ Print the XML representation of the hypervisor sysinfo, if available. Returns basic information about the node, like number and type of CPU, and size of the physical memory. +=item Bnodememstats + +Returns memory stats of the node. + =item Bcapabilities Print an XML document describing the capabilities of the hypervisor -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 9/9] Fix the signature of virDomainMigrateFinish3 for error reporting
2011/5/24 Daniel P. Berrange berra...@redhat.com: The current virDomainMigrateFinish3 method signature attempts to distinguish two types of errors, by allowing return with ret== 0, but ddomain == NULL, to indicate a failure to start the guest. This is flawed, because when ret == 0, there is no way for the virErrorPtr details to be sent back to the client. Change the signature of virDomainMigrateFinish3 so it simply returns a virDomainPtr, in the same way as virDomainMigrateFinish2 The disk locking code will protect against the only possible failure mode this doesn't account for (loosing conenctivity to libvirtd after Finish3 starts the CPUs, but before the client sees the reply for Finish3). * src/driver.h, src/libvirt.c, src/libvirt_internal.h: Change virDomainMigrateFinish3 to return a virDomainPtr instead of int * src/remote/remote_driver.c, src/remote/remote_protocol.x, daemon/remote.c, src/qemu/qemu_driver.c, src/qemu/qemu_migration.c: Update for API change --- daemon/remote.c | 35 --- src/driver.h | 5 ++--- src/libvirt.c | 41 - src/libvirt_internal.h | 21 ++--- src/qemu/qemu_driver.c | 21 + src/qemu/qemu_migration.c | 19 ++- src/remote/remote_driver.c | 29 - src/remote/remote_protocol.x | 2 +- 8 files changed, 64 insertions(+), 109 deletions(-) ACK. Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 7/9] Improve debug logging of migration APIs
2011/5/24 Daniel P. Berrange berra...@redhat.com: * src/libvirt.c: Add further debug lines in helper APIs for migration * src/qemu/qemu_migration.c: Add debug lines for all internal migration API parameters --- src/libvirt.c | 19 - src/qemu/qemu_migration.c | 47 - 2 files changed, 63 insertions(+), 3 deletions(-) @@ -1292,6 +1304,10 @@ static int doNativeMigrate(struct qemud_driver *driver, qemuDomainObjPrivatePtr priv = vm-privateData; unsigned int background_flags = QEMU_MONITOR_MIGRATE_BACKGROUND; qemuMigrationCookiePtr mig = NULL; + VIR_DEBUG(driver=%p, vm=%p, uri=%s, cookiein=%s, cookieinlen=%d, + cookieout=%p, cookieoutlen=%p, flags=%u, dname=%s, resource=%lu, + driver, vm, uri, NULLSTR(cookiein), cookieinlen, + cookieout, cookieoutlen, flags, dname, resource); dname can be NULL, needs to be NULLSTR(dname). @@ -1685,6 +1705,10 @@ static int doPeer2PeerMigrate2(struct qemud_driver *driver, virErrorPtr orig_err = NULL; int cancelled; virStreamPtr st = NULL; + VIR_DEBUG(driver=%p, sconn=%p, dconn=%p, vm=%p, dconnuri=%s, + flags=%lu, dname=%s, resource=%lu, + driver, sconn, dconn, vm, NULLSTR(dconnuri), + flags, dname, resource); dname can be NULL, needs to be NULLSTR(dname). @@ -1824,8 +1848,11 @@ static int doPeer2PeerMigrate3(struct qemud_driver *driver, virErrorPtr orig_err = NULL; int cancelled; virStreamPtr st = NULL; + VIR_DEBUG(driver=%p, sconn=%p, dconn=%p, vm=%p, xmlin=%s, + dconnuri=%s, uri=%s, flags=%lu, dname=%s, resource=%lu, + driver, sconn, dconn, vm, NULLSTR(xmlin), + NULLSTR(dconnuri), NULLSTR(uri), flags, dname, resource); dname can be NULL, needs to be NULLSTR(dname). @@ -1983,6 +2010,10 @@ static int doPeer2PeerMigrate(struct qemud_driver *driver, virConnectPtr dconn = NULL; bool p2p; bool v3; + VIR_DEBUG(driver=%p, sconn=%p, vm=%p, xmlin=%s, dconnuri=%s, + uri=%s, flags=%lu, dname=%s, resource=%lu, + driver, sconn, vm, NULLSTR(xmlin), NULLSTR(dconnuri), + NULLSTR(uri), flags, dname, resource); And again dname. @@ -2053,6 +2084,12 @@ int qemuMigrationPerform(struct qemud_driver *driver, int ret = -1; int resume = 0; qemuDomainObjPrivatePtr priv = vm-privateData; + VIR_DEBUG(driver=%p, conn=%p, vm=%p, xmlin=%s, dconnuri=%s, + uri=%s, cookiein=%s, cookieinlen=%d, cookieout=%p, + cookieoutlen=%p, flags=%lu, dname=%s, resource=%lu, v3proto=%d, + driver, conn, vm, NULLSTR(xmlin), NULLSTR(dconnuri), + NULLSTR(uri), NULLSTR(cookiein), cookieinlen, + cookieout, cookieoutlen, flags, dname, resource, v3proto); And another dname. ACK, with this dnames wrapped in NULLSTR. Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 08/13] send-key: Implementing the remote protocol
Signed-off-by: Lai Jiangshan la...@fujitsu.com --- src/remote/remote_driver.c |1 + src/remote/remote_protocol.x | 19 ++- src/remote_protocol-structs | 11 +++ 3 files changed, 30 insertions(+), 1 deletions(-) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 1691dab..6614250 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -6868,6 +6868,7 @@ static virDriver remote_driver = { .domainMigrateFinish3 = remoteDomainMigrateFinish3, /* 0.9.2 */ .domainMigrateConfirm3 = remoteDomainMigrateConfirm3, /* 0.9.2 */ .domainSetSchedulerParametersFlags = remoteDomainSetSchedulerParametersFlags, /* 0.9.2 */ +.domainSendKey = remoteDomainSendKey, /* 0.9.2 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index f0da95d..61504c4 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -191,6 +191,14 @@ const REMOTE_SECRET_UUID_LIST_MAX = 16384; */ const REMOTE_CPU_BASELINE_MAX = 256; +/* + * Max number of sending keycodes. + */ +const REMOTE_SEND_KEY_MAX = 16; + +/* define dynamic array's base type for unsigned int */ +typedef unsigned int u_int_DABT; + /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */ typedef opaque remote_uuid[VIR_UUID_BUFLEN]; @@ -838,6 +846,14 @@ struct remote_domain_inject_nmi_args { unsigned int flags; }; +struct remote_domain_send_key_args { +remote_nonnull_domain dom; +unsigned int codeset; +unsigned int holdtime; +u_int_DABT keycodesREMOTE_SEND_KEY_MAX; +unsigned int flags; +}; + struct remote_domain_set_vcpus_args { remote_nonnull_domain dom; int nvcpus; @@ -2291,7 +2307,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_PERFORM3 = 216, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_MIGRATE_FINISH3 = 217, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3 = 218, /* skipgen skipgen */ -REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS_FLAGS = 219 /* skipgen skipgen */ +REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS_FLAGS = 219, /* skipgen skipgen */ +REMOTE_PROC_DOMAIN_SEND_KEY = 220 /* 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 414b4d5..814821a 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1553,3 +1553,14 @@ struct remote_message_header { u_int serial; remote_message_status status; }; + +struct remote_domain_send_key_args { +remote_nonnull_domain dom; +unsigned int codeset; +unsigned int holdtime; +struct { +unsigned int keycodes_len; +unsigned int * keycodes_val; +} keycodes; +unsigned int flags; +}; -- 1.7.4.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 09/13] send-key: Expose the new API in virsh
Signed-off-by: Lai Jiangshan la...@fujitsu.com --- tools/virsh.c | 103 +++ tools/virsh.pod |4 ++ 2 files changed, 107 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 80cffac..505a821 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -33,6 +33,8 @@ #include signal.h #include poll.h +#include libvirt/virtkeys.h + #include libxml/parser.h #include libxml/tree.h #include libxml/xpath.h @@ -3010,6 +3012,106 @@ cmdInjectNMI(vshControl *ctl, const vshCmd *cmd) } /* + * send-key command + */ +static const vshCmdInfo info_send_key[] = { +{help, N_(Send keycodes to the guest)}, +{desc, N_(Send keycodes to the guest, the keycodes must be integers\n +Examples:\n\n +virsh # send-key domain 37 18 21\n +virsh # send-key domain --holdtime 1000 0x15 18 0xf\n +{NULL, NULL} +}; + +static const vshCmdOptDef opts_send_key[] = { +{domain, VSH_OT_DATA, VSH_OFLAG_REQ, N_(domain name, id or uuid)}, +{codeset, VSH_OT_STRING, VSH_OFLAG_REQ_OPT, N_(the codeset of keycodes, default:linux)}, +{holdtime, VSH_OT_INT, VSH_OFLAG_REQ_OPT, + N_(the time (in millsecond) how long the keys will be held)}, +{keycode, VSH_OT_ARGV, VSH_OFLAG_REQ, N_(the key code)}, +{NULL, 0, 0, NULL} +}; + +static int get_integer_keycode(const char *key_name) +{ +long val; +char *endptr; + +val = strtol(key_name, endptr, 0); +if (*endptr != '\0' || val 255 || val = 0) + return -1; + +return val; +} + +static bool +cmdSendKey(vshControl *ctl, const vshCmd *cmd) +{ +virDomainPtr dom; +int ret = false; +const char *codeset_option; +int codeset; +int holdtime; +int count = 0; +const vshCmdOpt *opt; +int keycode; +unsigned int keycodes[MAX_SEND_KEY]; + +if (!vshConnectionUsability(ctl, ctl-conn)) +return false; + +if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) +return false; + +if (vshCommandOptString(cmd, codeset, codeset_option) = 0) +codeset_option = default; + +if (vshCommandOptInt(cmd, holdtime, holdtime) = 0) +holdtime = 0; + +if (STREQ(codeset_option, default) || STREQ(codeset_option, linux)) { +codeset = LIBVIRT_KEYCODE_LINUX; +} else if (STREQ(codeset_option, diriver_default)) { +codeset = LIBVIRT_KEYCODE_DRIVER_DEFAULT; +} else if (STREQ(codeset_option, xt)) { +codeset = LIBVIRT_KEYCODE_XT; +} else if (STREQ(codeset_option, atset1)) { +codeset = LIBVIRT_KEYCODE_ATSET1; +} else if (STREQ(codeset_option, atset2)) { +codeset = LIBVIRT_KEYCODE_ATSET2; +} else if (STREQ(codeset_option, atset3)) { +codeset = LIBVIRT_KEYCODE_ATSET3; +} else { +vshError(ctl, _(unknown codeset: '%s'), codeset_option); +goto free_domain; +} + +for_each_variable_arg(cmd, opt) { +if (count == MAX_SEND_KEY) { +vshError(ctl, _(too many keycode)); +goto free_domain; +} + +if ((keycode = get_integer_keycode(opt-data)) 0) +goto get_keycode; + +vshError(ctl, _(invalid keycode: '%s'), opt-data); +goto free_domain; + +get_keycode: +keycodes[count] = keycode; +count++; +} + +if (!(virDomainSendKey(dom, codeset, holdtime, count, keycodes, 0) 0)) +ret = true; + +free_domain: +virDomainFree(dom); +return ret; +} + +/* * setmemory command */ static const vshCmdInfo info_setmem[] = { @@ -10807,6 +10909,7 @@ static const vshCmdDef domManagementCmds[] = { {dumpxml, cmdDumpXML, opts_dumpxml, info_dumpxml, 0}, {edit, cmdEdit, opts_edit, info_edit, 0}, {inject-nmi, cmdInjectNMI, opts_inject_nmi, info_inject_nmi, 0}, +{send-key, cmdSendKey, opts_send_key, info_send_key}, {managedsave, cmdManagedSave, opts_managedsave, info_managedsave, 0}, {managedsave-remove, cmdManagedSaveRemove, opts_managedsaveremove, info_managedsaveremove, 0}, diff --git a/tools/virsh.pod b/tools/virsh.pod index ef01f41..beef608 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -294,6 +294,10 @@ scheduling by the hypervisor. Inject NMI to the guest +=item Bsend-key Idomain-id I--codeset Bcodeset I--holdtime Bholdtime Bkeycode... + +Send keys to the guest + =item Bshutdown The domain is in the process of shutting down, i.e. the guest operating system -- 1.7.4.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 04/13] remote_generator: support general dynamic array
It will allow us use dynamic_array_basic_type member_nameMAX for remote protocol and avoid so many manual coding. For avoiding ambiguity, dynamic_array_basic_type must have a _DABT suffix. Signed-off-by: Lai Jiangshan la...@fujitsu.com --- daemon/remote_generator.pl | 18 ++ 1 files changed, 18 insertions(+), 0 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index d21f959..6905ff3 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -343,6 +343,12 @@ elsif ($opt_b) { } push(@args_list, args-$2.$2_len); +} elsif ($args_member =~ m/^(\S+_DABT) (\S+)\S+;/) { # normal dynamic array +if (! @args_list) { +push(@args_list, conn); +} +push(@args_list, args-$2.$2_len); +push(@args_list, ($1 *)args-$2.$2_val); } elsif ($args_member =~ m/\S+;/ or $args_member =~ m/\[\S+\];/) { # just make all other array types fail die unhandled type for argument value: $args_member; @@ -838,6 +844,18 @@ elsif ($opt_k) { push(@setters_list, args.$arg_name.${arg_name}_val = (char *)$arg_name;); push(@setters_list, args.$arg_name.${arg_name}_len = ${arg_name}len;); push(@args_check_list, { name = \$arg_name\, arg = ${arg_name}len, limit = $limit }); +} elsif ($args_member =~ m/^(\S+_DABT) (\S+)(\S+);/) { # normal dynamic array +my $type_name = $1; +my $arg_name = $2; +my $limit = $3; + +push(@args_list, unsigned int n${arg_name}); +push(@args_list, ${type_name} *$arg_name); + +push(@setters_list, args.$arg_name.${arg_name}_len = n${arg_name};); +push(@setters_list, args.$arg_name.${arg_name}_val = (${type_name} *)$arg_name;); + +push(@args_check_list, { name = \$arg_name\, arg = n${arg_name}, limit = $limit }); } elsif ($args_member =~ m/^(unsigned )?(int|hyper) (\S+);/) { my $type_name; my $arg_name = $3; -- 1.7.4.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 11/13] send-key: support KEY_XXX names for the linux keycode
It make send-key command more friendly for user. Signed-off-by: Lai Jiangshan la...@fujitsu.com --- include/libvirt/virtkeys.h | 253 tools/virsh.c | 21 2 files changed, 274 insertions(+), 0 deletions(-) diff --git a/include/libvirt/virtkeys.h b/include/libvirt/virtkeys.h index eb07129..7893450 100644 --- a/include/libvirt/virtkeys.h +++ b/include/libvirt/virtkeys.h @@ -20,4 +20,257 @@ enum libvirt_keycode_set { #define MAX_SEND_KEY 16 +#define ITEM_KEYCODE(KEY_XXX) VIRT##KEY_XXX +#define KEYCODES() \ +keycode(KEY_ESC, 1)\ +keycode(KEY_1, 2)\ +keycode(KEY_2, 3)\ +keycode(KEY_3, 4)\ +keycode(KEY_4, 5)\ +keycode(KEY_5, 6)\ +keycode(KEY_6, 7)\ +keycode(KEY_7, 8)\ +keycode(KEY_8, 9)\ +keycode(KEY_9, 10)\ +keycode(KEY_0, 11)\ +keycode(KEY_MINUS, 12)\ +keycode(KEY_EQUAL, 13)\ +keycode(KEY_BACKSPACE, 14)\ +keycode(KEY_TAB, 15)\ +keycode(KEY_Q, 16)\ +keycode(KEY_W, 17)\ +keycode(KEY_E, 18)\ +keycode(KEY_R, 19)\ +keycode(KEY_T, 20)\ +keycode(KEY_Y, 21)\ +keycode(KEY_U, 22)\ +keycode(KEY_I, 23)\ +keycode(KEY_O, 24)\ +keycode(KEY_P, 25)\ +keycode(KEY_LEFTBRACE, 26)\ +keycode(KEY_RIGHTBRACE, 27)\ +keycode(KEY_ENTER, 28)\ +keycode(KEY_LEFTCTRL,29)\ +keycode(KEY_A, 30)\ +keycode(KEY_S, 31)\ +keycode(KEY_D, 32)\ +keycode(KEY_F, 33)\ +keycode(KEY_G, 34)\ +keycode(KEY_H, 35)\ +keycode(KEY_J, 36)\ +keycode(KEY_K, 37)\ +keycode(KEY_L, 38)\ +keycode(KEY_SEMICOLON, 39)\ +keycode(KEY_APOSTROPHE, 40)\ +keycode(KEY_GRAVE, 41)\ +keycode(KEY_LEFTSHIFT, 42)\ +keycode(KEY_BACKSLASH, 43)\ +keycode(KEY_Z, 44)\ +keycode(KEY_X, 45)\ +keycode(KEY_C, 46)\ +keycode(KEY_V, 47)\ +keycode(KEY_B, 48)\ +keycode(KEY_N, 49)\ +keycode(KEY_M, 50)\ +keycode(KEY_COMMA, 51)\ +keycode(KEY_DOT, 52)\ +keycode(KEY_SLASH, 53)\ +keycode(KEY_RIGHTSHIFT, 54)\ +keycode(KEY_KPASTERISK, 55)\ +keycode(KEY_LEFTALT, 56)\ +keycode(KEY_SPACE, 57)\ +keycode(KEY_CAPSLOCK,58)\ +keycode(KEY_F1, 59)\ +keycode(KEY_F2, 60)\ +keycode(KEY_F3, 61)\ +keycode(KEY_F4, 62)\ +keycode(KEY_F5, 63)\ +keycode(KEY_F6, 64)\ +keycode(KEY_F7, 65)\ +keycode(KEY_F8, 66)\ +keycode(KEY_F9, 67)\ +keycode(KEY_F10, 68)\ +keycode(KEY_NUMLOCK, 69)\ +keycode(KEY_SCROLLLOCK, 70)\ +keycode(KEY_KP7, 71)\ +keycode(KEY_KP8, 72)\ +keycode(KEY_KP9, 73)\ +keycode(KEY_KPMINUS, 74)\ +keycode(KEY_KP4, 75)\ +keycode(KEY_KP5, 76)\ +keycode(KEY_KP6, 77)\ +keycode(KEY_KPPLUS, 78)\ +keycode(KEY_KP1, 79)\ +keycode(KEY_KP2, 80)\ +keycode(KEY_KP3, 81)\ +keycode(KEY_KP0, 82)\ +keycode(KEY_KPDOT, 83)\ +keycode(KEY_ZENKAKUHANKAKU, 85)\ +keycode(KEY_102ND, 86)\ +keycode(KEY_F11, 87)\ +keycode(KEY_F12, 88)\ +keycode(KEY_RO, 89)\ +keycode(KEY_KATAKANA,90)\ +keycode(KEY_HIRAGANA,91)\ +keycode(KEY_HENKAN, 92)\ +keycode(KEY_KATAKANAHIRAGANA,93)\ +keycode(KEY_MUHENKAN,94)\ +keycode(KEY_KPJPCOMMA, 95)\ +keycode(KEY_KPENTER, 96)\ +keycode(KEY_RIGHTCTRL, 97)\ +keycode(KEY_KPSLASH, 98)\ +keycode(KEY_SYSRQ, 99)\ +keycode(KEY_RIGHTALT,100)\ +keycode(KEY_LINEFEED,101)\ +keycode(KEY_HOME,102)\ +keycode(KEY_UP, 103)\ +
[libvirt] [PATCH 03/13] add VSH_OFLAG_REQ_OPT options
A VSH_OFLAG_REQ_OPT option means --optionname is required when used. It will kill any ambiguity even !VSH_OFLAG_REQ option listed before VSH_OFLAG_REQ option if the !VSH_OFLAG_REQ option is a VSH_OFLAG_REQ_OPT option. It will help us use optional arguement with VSH_OT_ARGV argument. Signed-off-by: Lai Jiangshan la...@fujitsu.com --- tools/virsh.c |7 +++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 2e27535..80cffac 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -152,6 +152,7 @@ enum { VSH_OFLAG_NONE = 0,/* without flags */ VSH_OFLAG_REQ = (1 0), /* option required */ VSH_OFLAG_EMPTY_OK = (1 1), /* empty string option allowed */ +VSH_OFLAG_REQ_OPT = (1 2), /* --optionname required */ }; /* dummy */ @@ -11080,6 +11081,12 @@ vshCmddefOptParse(const vshCmdDef *cmd, uint32_t* opts_need_arg, return -1; /* bool options can't be mandatory */ continue; } +if (opt-flag VSH_OFLAG_REQ_OPT) { +if (opt-flag VSH_OFLAG_REQ) +*opts_required |= 1 i; +continue; +} + *opts_need_arg |= 1 i; if (opt-flag VSH_OFLAG_REQ) { if (optional) -- 1.7.4.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 01/13] allow name for VSH_OT_ARGV options
A name will improve the usege, example # virsh help echo NAME echo - echo arguments SYNOPSIS echo [--shell] [--xml] [string]... DESCRIPTION Echo back arguments, possibly with quoting. OPTIONS --shell escape for shell use --xmlescape for XML use string arguments to echo [string]... is added to SYNOPSIS. string arguments to echo is added to OPTIONS. Signed-off-by: Lai Jiangshan la...@fujitsu.com --- tools/virsh.c | 19 +-- 1 files changed, 13 insertions(+), 6 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index de49489..c358580 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -126,7 +126,7 @@ typedef enum { VSH_OT_STRING, /* optional string option */ VSH_OT_INT, /* optional or mandatory int option */ VSH_OT_DATA, /* string data (as non-option) */ -VSH_OT_ARGV /* remaining arguments, opt-name should be */ +VSH_OT_ARGV /* remaining arguments */ } vshCmdOptType; /* @@ -10046,7 +10046,7 @@ static const vshCmdInfo info_echo[] = { static const vshCmdOptDef opts_echo[] = { {shell, VSH_OT_BOOL, 0, N_(escape for shell use)}, {xml, VSH_OT_BOOL, 0, N_(escape for XML use)}, -{, VSH_OT_ARGV, 0, N_(arguments to echo)}, +{string, VSH_OT_ARGV, 0, N_(arguments to echo)}, {NULL, 0, 0, NULL} }; @@ -11084,6 +11084,11 @@ vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name, vshError(ctl, _(option --%s already seen), name); return NULL; } +if (opt-type == VSH_OT_ARGV) { +vshError(ctl, _(variable argument %s + should not be used with --%s), name, name); +return NULL; +} *opts_seen |= 1 i; return opt; } @@ -11132,7 +11137,7 @@ vshCommandCheckOpts(vshControl *ctl, const vshCmd *cmd, uint32_t opts_required, const vshCmdOptDef *opt = def-opts[i]; vshError(ctl, - opt-type == VSH_OT_DATA ? + opt-type == VSH_OT_DATA || opt-type == VSH_OT_ARGV ? _(command '%s' requires %s option) : _(command '%s' requires --%s option), def-name, opt-name); @@ -11240,7 +11245,8 @@ vshCmddefHelp(vshControl *ctl, const char *cmdname) break; case VSH_OT_ARGV: /* xgettext:c-format */ -fmt = _([string]...); +fmt = (opt-flag VSH_OFLAG_REQ) ? _(%s...) + : _([%s]...); break; default: assert(0); @@ -11280,7 +11286,8 @@ vshCmddefHelp(vshControl *ctl, const char *cmdname) break; case VSH_OT_ARGV: /* Not really an option. */ -continue; +snprintf(buf, sizeof(buf), _(%s), opt-name); +break; default: assert(0); } @@ -12693,7 +12700,7 @@ vshReadlineOptionsGenerator(const char *text, int state) list_index++; -if (opt-type == VSH_OT_DATA) +if (opt-type == VSH_OT_DATA || opt-type == VSH_OT_ARGV) /* ignore non --option */ continue; -- 1.7.4.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 06/13] send-key: Defining the internal API
Signed-off-by: Lai Jiangshan la...@fujitsu.com --- src/driver.h |8 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index 450dd53..70a30d9 100644 --- a/src/driver.h +++ b/src/driver.h @@ -535,6 +535,13 @@ typedef int typedef int (*virDrvDomainInjectNMI)(virDomainPtr dom, unsigned int flags); +typedef int +(*virDrvDomainSendKey)(virDomainPtr dom, unsigned int codeset, + unsigned int holdtime, + unsigned int nkeycodes, + unsigned int *keycodes, + unsigned int flags); + typedef char * (*virDrvDomainMigrateBegin3) (virDomainPtr domain, @@ -738,6 +745,7 @@ struct _virDriver { virDrvDomainMigratePerform3domainMigratePerform3; virDrvDomainMigrateFinish3 domainMigrateFinish3; virDrvDomainMigrateConfirm3domainMigrateConfirm3; +virDrvDomainSendKey domainSendKey; }; typedef int -- 1.7.4.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 10/13] qemu:send-key: Implement the driver methods
Signed-off-by: Lai Jiangshan la...@fujitsu.com --- src/qemu/qemu_driver.c | 50 ++ src/qemu/qemu_monitor.c | 28 +++ src/qemu/qemu_monitor.h |6 + src/qemu/qemu_monitor_json.c | 15 src/qemu/qemu_monitor_json.h |5 src/qemu/qemu_monitor_text.c | 48 src/qemu/qemu_monitor_text.h |5 7 files changed, 157 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 691965d..f7e21bf 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1753,6 +1753,55 @@ cleanup: return ret; } +static int qemuDomainSendKey(virDomainPtr domain, + unsigned int codeset, + unsigned int holdtime, + unsigned int nkeycodes, + unsigned int *keycodes, + unsigned int flags) +{ +struct qemud_driver *driver = domain-conn-privateData; +virDomainObjPtr vm = NULL; +int ret = -1; +qemuDomainObjPrivatePtr priv; + +virCheckFlags(0, -1); + +qemuDriverLock(driver); +vm = virDomainFindByUUID(driver-domains, domain-uuid); +if (!vm) { +char uuidstr[VIR_UUID_STRING_BUFLEN]; +virUUIDFormat(domain-uuid, uuidstr); +qemuReportError(VIR_ERR_NO_DOMAIN, +_(no domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +if (!virDomainObjIsActive(vm)) { +qemuReportError(VIR_ERR_OPERATION_INVALID, +%s, _(domain is not running)); +goto cleanup; +} + +priv = vm-privateData; + +if (qemuDomainObjBeginJobWithDriver(driver, vm) 0) +goto cleanup; +qemuDomainObjEnterMonitorWithDriver(driver, vm); +ret = qemuMonitorSendKey(priv-mon, codeset, holdtime, nkeycodes, keycodes); +qemuDomainObjExitMonitorWithDriver(driver, vm); +if (qemuDomainObjEndJob(vm) == 0) { +vm = NULL; +goto cleanup; +} + +cleanup: +if (vm) +virDomainObjUnlock(vm); +qemuDriverUnlock(driver); +return ret; +} + static int qemudDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { @@ -7746,6 +7795,7 @@ static virDriver qemuDriver = { .domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */ .domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */ .domainSetSchedulerParametersFlags = qemuSetSchedulerParametersFlags, /* 0.9.2 */ +.domainSendKey = qemuDomainSendKey, /* 0.9.2 */ }; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 5186f99..c0688fd 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -38,6 +38,8 @@ #include logging.h #include files.h +#include libvirt/virtkeys.h + #define VIR_FROM_THIS VIR_FROM_QEMU #define DEBUG_IO 0 @@ -2294,6 +2296,32 @@ int qemuMonitorInjectNMI(qemuMonitorPtr mon) return ret; } +int qemuMonitorSendKey(qemuMonitorPtr mon, + unsigned int codeset, + unsigned int holdtime, + unsigned int nkeycodes, + unsigned int *keycodes) +{ +int ret; + +VIR_DEBUG(mon=%p, codeset=%u, holdtime=%u, nkeycodes=%u, + mon, codeset, holdtime, nkeycodes); + +if (!(codeset == LIBVIRT_KEYCODE_DRIVER_DEFAULT +|| codeset == LIBVIRT_KEYCODE_XT)) { +qemuReportError(VIR_ERR_NO_SUPPORT, +qemu monitor can not support the codeset: %d, +codeset); +return -1; +} + +if (mon-json) +ret = qemuMonitorJSONSendKey(mon, holdtime, nkeycodes, keycodes); +else +ret = qemuMonitorTextSendKey(mon, holdtime, nkeycodes, keycodes); +return ret; +} + int qemuMonitorScreendump(qemuMonitorPtr mon, const char *file) { diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 05c3359..76a849a 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -435,6 +435,12 @@ int qemuMonitorInjectNMI(qemuMonitorPtr mon); int qemuMonitorScreendump(qemuMonitorPtr mon, const char *file); +int qemuMonitorSendKey(qemuMonitorPtr mon, + unsigned int codeset, + unsigned int holdtime, + unsigned int nkeycodes, + unsigned int *keycodes); + /** * When running two dd process and using redirection, we need a * shell that will not truncate files. These two strings serve that diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 2d8a390..a547f1d 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2615,6 +2615,21 @@ cleanup: return ret; } +int qemuMonitorJSONSendKey(qemuMonitorPtr mon, +
[libvirt] [PATCH 00/13] Add support for send keys to guest
Add API virDomainSendKey() and virsh send-key command. # virsh help send-key NAME send-key - Send keycodes to the guest SYNOPSIS send-key domain [--codeset string] [--holdtime number] keycode... DESCRIPTION Send keycodes to the guest, the keycodes must be integers or the qemu-style key strings for the xt:keystring codeset or the KEY_* strings listed below for the linux codeset. Available codeset: linux the keycodes specified in /usr/include/linux/input.h(default) defaultlinux codeset will be used driver_default the hypervisor default codeset will be used xt XT(set1) scancode of standard AT keyboards and PS/2 keyboards atset1 set1 scancode of standard AT keyboards and PS/2 keyboards atset2 set2 scancode of standard AT keyboards and PS/2 keyboards atset3 set3 scancode of standard AT keyboards and PS/2 keyboards xt:keystring XT scancode, but keycode... must be the qemu-style key strings Examples: virsh # send-key domain 37 18 21 virsh # send-key domain --holdtime 1000 0x15 18 0xf virsh # send-key domain KEY_LEFTCTRL KEY_LEFTALT KEY_F1 virsh # send-key domain --codeset xt:keystring alt-sysrq h KEY_XXX strings for the linux codeset: . . . OPTIONS [--domain] string domain name, id or uuid --codeset string the codeset of keycodes, default:linux --holdtime number the time (in millsecond) how long the keys will be held keycodethe key code PATCH 01~04 prepare PATCH 05~10 Add support for send keys to guest PATCH 11~13 improve usage of send keys. Python version of virDomainSendKey() has not been implemented yet, it will be done soon. Lai Jiangshan (13): allow name for VSH_OT_ARGV options improve the iteration of VSH_OT_ARGV options add VSH_OFLAG_REQ_OPT options remote_generator: support general dynamic array send-key: Defining the public API send-key: Defining the internal API send-key: Implementing the public API send-key: Implementing the remote protocol send-key: Expose the new API in virsh qemu:send-key: Implement the driver methods send-key: support KEY_XXX names for the linux keycode qemu,send-key: map linux keycode to xt keycode virsh,send-key: add --codeset xt:keystring support daemon/remote_generator.pl | 18 ++ include/libvirt/libvirt.h.in |7 + include/libvirt/virtkeys.h | 276 python/generator.py |1 + src/driver.h |8 + src/libvirt.c| 54 ++ src/libvirt_public.syms |1 + src/qemu/qemu_driver.c | 50 + src/qemu/qemu_monitor.c | 75 src/qemu/qemu_monitor.h |6 + src/qemu/qemu_monitor_json.c | 15 ++ src/qemu/qemu_monitor_json.h |5 + src/qemu/qemu_monitor_text.c | 48 + src/qemu/qemu_monitor_text.h |5 + src/remote/remote_driver.c |1 + src/remote/remote_protocol.x | 19 ++- src/remote_protocol-structs | 11 + tools/virsh.c| 415 +++--- tools/virsh.pod |4 + 19 files changed, 989 insertions(+), 30 deletions(-) create mode 100644 include/libvirt/virtkeys.h -- 1.7.4.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 13/13] virsh, send-key: add --codeset xt:keystring support
It make send-key command more friendly for user. Signed-off-by: Lai Jiangshan la...@fujitsu.com --- tools/virsh.c | 224 - 1 files changed, 221 insertions(+), 3 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 3bccc08..18ef4bb 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -3017,11 +3017,24 @@ cmdInjectNMI(vshControl *ctl, const vshCmd *cmd) static const vshCmdInfo info_send_key[] = { {help, N_(Send keycodes to the guest)}, {desc, N_(Send keycodes to the guest, the keycodes must be integers\n +or the qemu-style key strings for the \xt:keystring\ codeset\n or the KEY_* strings listed below for the \linux\ codeset.\n\n +Available codeset:\n +linux the keycodes specified in \n +/usr/include/linux/input.h(default)\n +defaultlinux codeset will be used\n +driver_default the hypervisor default codeset will be used\n +xt XT(set1) scancode of standard AT keyboards and PS/2 keyboards\n +atset1 set1 scancode of standard AT keyboards and PS/2 keyboards\n +atset2 set2 scancode of standard AT keyboards and PS/2 keyboards\n +atset3 set3 scancode of standard AT keyboards and PS/2 keyboards\n +xt:keystring XT scancode, but keycode... must be the qemu-style key strings\n +\n Examples:\n\n virsh # send-key domain 37 18 21\n virsh # send-key domain --holdtime 1000 0x15 18 0xf\n -virsh # send-eky domain KEY_LEFTCTRL KEY_LEFTALT KEY_F1\n +virsh # send-key domain KEY_LEFTCTRL KEY_LEFTALT KEY_F1\n +virsh # send-key domain --codeset xt:keystring alt-sysrq h\n \n KEY_XXX strings for the \linux\ codeset:\n #define keycode(var, value) #var = #value \n @@ -3062,6 +3075,178 @@ static int get_integer_keycode(const char *key_name) return val; } + +typedef struct { +int keycode; +const char *name; +} KeyDef; + +static const KeyDef key_defs[] = { +{ 0x2a, shift }, +{ 0x36, shift_r }, + +{ 0x38, alt }, +{ 0xb8, alt_r }, +{ 0x64, altgr }, +{ 0xe4, altgr_r }, +{ 0x1d, ctrl }, +{ 0x9d, ctrl_r }, + +{ 0xdd, menu }, + +{ 0x01, esc }, + +{ 0x02, 1 }, +{ 0x03, 2 }, +{ 0x04, 3 }, +{ 0x05, 4 }, +{ 0x06, 5 }, +{ 0x07, 6 }, +{ 0x08, 7 }, +{ 0x09, 8 }, +{ 0x0a, 9 }, +{ 0x0b, 0 }, +{ 0x0c, minus }, +{ 0x0d, equal }, +{ 0x0e, backspace }, + +{ 0x0f, tab }, +{ 0x10, q }, +{ 0x11, w }, +{ 0x12, e }, +{ 0x13, r }, +{ 0x14, t }, +{ 0x15, y }, +{ 0x16, u }, +{ 0x17, i }, +{ 0x18, o }, +{ 0x19, p }, +{ 0x1a, bracket_left }, +{ 0x1b, bracket_right }, +{ 0x1c, ret }, + +{ 0x1e, a }, +{ 0x1f, s }, +{ 0x20, d }, +{ 0x21, f }, +{ 0x22, g }, +{ 0x23, h }, +{ 0x24, j }, +{ 0x25, k }, +{ 0x26, l }, +{ 0x27, semicolon }, +{ 0x28, apostrophe }, +{ 0x29, grave_accent }, + +{ 0x2b, backslash }, +{ 0x2c, z }, +{ 0x2d, x }, +{ 0x2e, c }, +{ 0x2f, v }, +{ 0x30, b }, +{ 0x31, n }, +{ 0x32, m }, +{ 0x33, comma }, +{ 0x34, dot }, +{ 0x35, slash }, + +{ 0x37, asterisk }, + +{ 0x39, spc }, +{ 0x3a, caps_lock }, +{ 0x3b, f1 }, +{ 0x3c, f2 }, +{ 0x3d, f3 }, +{ 0x3e, f4 }, +{ 0x3f, f5 }, +{ 0x40, f6 }, +{ 0x41, f7 }, +{ 0x42, f8 }, +{ 0x43, f9 }, +{ 0x44, f10 }, +{ 0x45, num_lock }, +{ 0x46, scroll_lock }, + +{ 0xb5, kp_divide }, +{ 0x37, kp_multiply }, +{ 0x4a, kp_subtract }, +{ 0x4e, kp_add }, +{ 0x9c, kp_enter }, +{ 0x53, kp_decimal }, +{ 0x54, sysrq }, + +{ 0x52, kp_0 }, +{ 0x4f, kp_1 }, +{ 0x50, kp_2 }, +{ 0x51, kp_3 }, +{ 0x4b, kp_4 }, +{ 0x4c, kp_5 }, +{ 0x4d, kp_6 }, +{ 0x47, kp_7 }, +{ 0x48, kp_8 }, +{ 0x49, kp_9 }, + +{ 0x56, }, + +{ 0x57, f11 }, +{ 0x58, f12 }, + +{ 0xb7, print }, + +{ 0xc7, home }, +{ 0xc9, pgup }, +{ 0xd1, pgdn }, +{ 0xcf, end }, + +{ 0xcb, left }, +{ 0xc8, up }, +{ 0xd0, down }, +{ 0xcd, right }, + +{ 0xd2, insert }, +{ 0xd3, delete }, + +{ 0xf0, stop }, +{ 0xf1, again }, +{ 0xf2, props }, +{ 0xf3, undo }, +{ 0xf4, front }, +{ 0xf5, copy }, +{ 0xf6, open }, +{ 0xf7, paste }, +{ 0xf8, find }, +{ 0xf9, cut }, +{ 0xfa, lf }, +{ 0xfb, help }, +{ 0xfc, meta_l }, +{ 0xfd, meta_r }, +{ 0xfe, compose }, + +{ 0, NULL }, +};
[libvirt] [PATCH 05/13] send-key: Defining the public API
Add public virDomainSendKey() and enum libvirt_keycode_set for the @codeset. Python version of virDomainSendKey() has not been implemented yet, it will be done soon. Signed-off-by: Lai Jiangshan la...@fujitsu.com --- include/libvirt/libvirt.h.in |7 +++ include/libvirt/virtkeys.h | 23 +++ python/generator.py |1 + src/libvirt_public.syms |1 + 4 files changed, 32 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 7cd6e13..9167dbc 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -2617,6 +2617,13 @@ int virDomainOpenConsole(virDomainPtr dom, int virDomainInjectNMI(virDomainPtr domain, unsigned int flags); +int virDomainSendKey(virDomainPtr domain, + unsigned int codeset, + unsigned int holdtime, + unsigned int nkeycodes, + unsigned int *keycodes, + unsigned int flags); + #ifdef __cplusplus } #endif diff --git a/include/libvirt/virtkeys.h b/include/libvirt/virtkeys.h new file mode 100644 index 000..eb07129 --- /dev/null +++ b/include/libvirt/virtkeys.h @@ -0,0 +1,23 @@ +#ifndef _LIBVIRT_VIRTKEYS_H +#define _LIBVIRT_VIRTKEYS_H + +/* + * Copyright (c) 2011 Lai Jiangshan + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +enum libvirt_keycode_set { +LIBVIRT_KEYCODE_LINUX = 0, +LIBVIRT_KEYCODE_DRIVER_DEFAULT = 1, +LIBVIRT_KEYCODE_XT = 2, +LIBVIRT_KEYCODE_ATSET1 = LIBVIRT_KEYCODE_XT, +LIBVIRT_KEYCODE_ATSET2 = 3, +LIBVIRT_KEYCODE_ATSET3 = 4, +}; + +#define MAX_SEND_KEY 16 + +#endif diff --git a/python/generator.py b/python/generator.py index 1741bba..3d57bf9 100755 --- a/python/generator.py +++ b/python/generator.py @@ -355,6 +355,7 @@ skip_impl = ( 'virNodeDeviceListCaps', 'virConnectBaselineCPU', 'virDomainRevertToSnapshot', +'virDomainSendKey', ) diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 0590535..9e8a37c 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -442,6 +442,7 @@ LIBVIRT_0.9.2 { virDomainInjectNMI; virDomainScreenshot; virDomainSetSchedulerParametersFlags; +virDomainSendKey; } LIBVIRT_0.9.0; # define new API here using predicted next version number -- 1.7.4.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 02/13] improve the iteration of VSH_OT_ARGV options
Signed-off-by: Lai Jiangshan la...@fujitsu.com --- tools/virsh.c | 47 --- 1 files changed, 24 insertions(+), 23 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index c358580..2e27535 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -277,7 +277,27 @@ static int vshCommandOptULongLong(const vshCmd *cmd, const char *name, unsigned long long *value) ATTRIBUTE_NONNULL(3) ATTRIBUTE_RETURN_CHECK; static bool vshCommandOptBool(const vshCmd *cmd, const char *name); -static char *vshCommandOptArgv(const vshCmd *cmd, int count); + +/* + * Iterate all the argv arguments. + * + * Requires that a VSH_OT_ARGV option be last in the + * list of supported options in CMD-def-opts. + */ +static inline const vshCmdOpt *__variable_arg(const vshCmdOpt *opt) +{ +while (opt) { + if (opt-def opt-def-type == VSH_OT_ARGV) + break; + opt = opt-next; +} + +return opt; +} + +#define for_each_variable_arg(cmd, opt) \ +for (opt = __variable_arg(cmd-opts); opt; opt = __variable_arg(opt-next)) + #define VSH_BYID (1 1) #define VSH_BYUUID (1 2) @@ -10059,6 +10079,7 @@ cmdEcho (vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd) bool shell = false; bool xml = false; int count = 0; +const vshCmdOpt *opt; char *arg; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -10067,10 +10088,11 @@ cmdEcho (vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd) if (vshCommandOptBool(cmd, xml)) xml = true; -while ((arg = vshCommandOptArgv(cmd, count)) != NULL) { +for_each_variable_arg(cmd, opt) { bool close_quote = false; char *q; +arg = opt-data; if (count) virBufferAddChar(buf, ' '); /* Add outer '' only if arg included shell metacharacters. */ @@ -11484,27 +11506,6 @@ vshCommandOptBool(const vshCmd *cmd, const char *name) return vshCommandOpt(cmd, name) != NULL; } -/* - * Returns the COUNT argv argument, or NULL after last argument. - * - * Requires that a VSH_OT_ARGV option with the name be last in the - * list of supported options in CMD-def-opts. - */ -static char * -vshCommandOptArgv(const vshCmd *cmd, int count) -{ -vshCmdOpt *opt = cmd-opts; - -while (opt) { -if (opt-def opt-def-type == VSH_OT_ARGV) { -if (count-- == 0) -return opt-data; -} -opt = opt-next; -} -return NULL; -} - /* Determine whether CMD-opts includes an option with name OPTNAME. If not, give a diagnostic and return false. If so, return true. */ -- 1.7.4.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 07/13] send-key: Implementing the public API
Signed-off-by: Lai Jiangshan la...@fujitsu.com --- src/libvirt.c | 54 ++ 1 files changed, 54 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index ff16c48..8246975 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -6080,6 +6080,60 @@ error: } /** + * virDomainSendKey: + * @domain:pointer to domain object, or NULL for Domain0 + * @codeset: the code set of keycodes + * @holdtime: the time (in millsecond) how long the keys will be held + * @nkeycodes: number of keycodes + * @keycodes: array of keycodes + * @flags: the flags for controlling behavior, pass 0 for now + * + * Send key to the guest + * + * Returns 0 in case of success, -1 in case of failure. + */ + +int virDomainSendKey(virDomainPtr domain, + unsigned int codeset, + unsigned int holdtime, + unsigned int nkeycodes, + unsigned int *keycodes, + unsigned int flags) +{ +virConnectPtr conn; +VIR_DOMAIN_DEBUG(domain, flags=%u, flags); + +virResetLastError(); + +if (!VIR_IS_CONNECTED_DOMAIN(domain)) { +virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); +virDispatchError(NULL); +return -1; +} +if (domain-conn-flags VIR_CONNECT_RO) { +virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); +goto error; +} + +conn = domain-conn; + +if (conn-driver-domainSendKey) { +int ret; +ret = conn-driver-domainSendKey(domain, codeset, holdtime, + nkeycodes, keycodes, flags); +if (ret 0) +goto error; +return ret; +} + +virLibConnError (VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: +virDispatchError(domain-conn); +return -1; +} + +/** * virDomainSetVcpus: * @domain: pointer to domain object, or NULL for Domain0 * @nvcpus: the new number of virtual CPUs for this domain -- 1.7.4.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 12/13] qemu, send-key: map linux keycode to xt keycode
It allows us use linux keycode for qemu driver. Signed-off-by: Lai Jiangshan la...@fujitsu.com --- src/qemu/qemu_monitor.c | 49 ++- 1 files changed, 48 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index c0688fd..f6cdff1 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2296,6 +2296,41 @@ int qemuMonitorInjectNMI(qemuMonitorPtr mon) return ret; } +unsigned int linux2xt_keycode[256] = { +/* 00: */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +/* 08: */ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, +/* 10: */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, +/* 18: */ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, +/* 20: */ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, +/* 28: */ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, +/* 30: */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, +/* 38: */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, +/* 40: */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, +/* 48: */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x00, 0x4f, +/* 50: */ 0x50, 0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x57, +/* 58: */ 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 60: */ 0x00, 0x9d, 0xb5, 0x54, 0xb8, 0x00, 0xc7, 0xc8, +/* 68: */ 0xc9, 0xcb, 0xcd, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, +/* 70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 80: */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, +/* 88: */ 0xf8, 0xf9, 0xfb, 0xdd, 0x00, 0x00, 0x00, 0x00, +/* 90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* d0: */ 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, +/* d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + int qemuMonitorSendKey(qemuMonitorPtr mon, unsigned int codeset, unsigned int holdtime, @@ -2307,7 +2342,19 @@ int qemuMonitorSendKey(qemuMonitorPtr mon, VIR_DEBUG(mon=%p, codeset=%u, holdtime=%u, nkeycodes=%u, mon, codeset, holdtime, nkeycodes); -if (!(codeset == LIBVIRT_KEYCODE_DRIVER_DEFAULT +if (codeset == LIBVIRT_KEYCODE_LINUX) { +int i; + +for (i = 0; i nkeycodes; i++) { +if (keycodes[i] = 256 || !linux2xt_keycode[keycodes[i]]) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +can not map the linux keycode:%d to XT keycode, +keycodes[i]); +return -1; +} +keycodes[i] = linux2xt_keycode[keycodes[i]]; +} +} else if (!(codeset == LIBVIRT_KEYCODE_DRIVER_DEFAULT || codeset == LIBVIRT_KEYCODE_XT)) { qemuReportError(VIR_ERR_NO_SUPPORT, qemu monitor can not support the codeset: %d, -- 1.7.4.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] storage: fix volDelete return when volume still being allocated
volDelete used to return VIR_ERR_INTERNAL_ERROR when attempting to delete a volume which was still being allocated. It should return VIR_ERR_OPERATION_INVALID. * src/storage/storage_driver.c: Fix return of volDelete. --- src/storage/storage_driver.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index 2da2feb..d9c2137 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -1914,7 +1914,7 @@ storageVolumeDelete(virStorageVolPtr obj, } if (vol-building) { -virStorageReportError(VIR_ERR_INTERNAL_ERROR, +virStorageReportError(VIR_ERR_OPERATION_INVALID, _(volume '%s' is still being allocated.), vol-name); goto cleanup; -- 1.7.4.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] storage: fix volDelete return when volume still being allocated
On Wed, May 25, 2011 at 11:55:08AM +0100, Matthew Booth wrote: volDelete used to return VIR_ERR_INTERNAL_ERROR when attempting to delete a volume which was still being allocated. It should return VIR_ERR_OPERATION_INVALID. * src/storage/storage_driver.c: Fix return of volDelete. --- src/storage/storage_driver.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index 2da2feb..d9c2137 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -1914,7 +1914,7 @@ storageVolumeDelete(virStorageVolPtr obj, } if (vol-building) { -virStorageReportError(VIR_ERR_INTERNAL_ERROR, +virStorageReportError(VIR_ERR_OPERATION_INVALID, _(volume '%s' is still being allocated.), vol-name); goto cleanup; ACK If someone is motivated, it would be desirable to actually make delete work, even while the volume is building. Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 3/9] Introduce two method migration APIs
On Wed, May 25, 2011 at 09:45:50AM +0200, Matthias Bolte wrote: 2011/5/24 Daniel P. Berrange berra...@redhat.com: There are two pieces of information which are desirable for migration, which cannot be supplied by applications - The explicit QEMU migration URI, while using Peer2Peer migration - An override for the target VM XML This introduces two new public APIs to support these extra parameters. There is no need for extra wire protocool changes, since this is supported by the v3 migration enhancements * include/libvirt/libvirt.h.in, src/libvirt.c, src/libvirt_public.syms: Add virDomainMigrate2 and virDomainMigrateToURI2 --- include/libvirt/libvirt.h.in | 12 ++ src/libvirt.c | 321 +- src/libvirt_public.syms | 2 + 3 files changed, 332 insertions(+), 3 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 2b2c1fd..4bdcd43 100644 --- a/src/libvirt.c +++ b/src/libvirt.c + +/** + * virDomainMigrate2: + * @domain: a domain object + * @dconn: destination host (a connection object) + * @flags: flags + * @dxml: optional XML config for launching guest on target The other optional parameters have their optional in (). So this optional should be in () too, or the others should have their () removed. + * @dname: (optional) rename domain to this at destination + * @uri: (optional) dest hostname/URI as seen from the source host + * @bandwidth: (optional) specify migration bandwidth limit in Mbps + * + * Migrate the domain object from its current host to the destination + * host given by dconn (a connection to the destination host). + * +/** + * virDomainMigrateToURI2: + * @domain: a domain object + * @dconnuri: optional URI for target libvirtd if @flags includes VIR_MIGRATE_PEER2PEER + * @miguri: optional URI for invoking the migration, not if @flags includs VIR_MIGRATE_TUNNELLED + * @dxml: optional XML config for launching guest on target The same comment from above about the word optional applies here too. + * @flags: flags + * @dname: (optional) rename domain to this at destination + * @bandwidth: (optional) specify migration bandwidth limit in Mbps ACK to be patch as it, but do we really want to add a new public API to 0.9.2 for a feature that no driver implements yet and might not implement it before 0.9.2? As I understand it the URI separation already works but the XML override isn't implemented yet. Or do you already have the XML override implemented but did post the patch yet? I don't have XML override implemented yet. QEMU returns an error if you attempt to use it. I figured that since I had made the migration wire protocol support it, we might as well have the public API too. I can work up some QEMU code without much trouble too. The only missing bit is the ability to compare two virDomainDefPtr instances and validate that they have the same guest ABI (ie same list of device models + device addresses). Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 3/9] Introduce two method migration APIs
2011/5/25 Daniel P. Berrange berra...@redhat.com: On Wed, May 25, 2011 at 09:45:50AM +0200, Matthias Bolte wrote: 2011/5/24 Daniel P. Berrange berra...@redhat.com: There are two pieces of information which are desirable for migration, which cannot be supplied by applications - The explicit QEMU migration URI, while using Peer2Peer migration - An override for the target VM XML This introduces two new public APIs to support these extra parameters. There is no need for extra wire protocool changes, since this is supported by the v3 migration enhancements * include/libvirt/libvirt.h.in, src/libvirt.c, src/libvirt_public.syms: Add virDomainMigrate2 and virDomainMigrateToURI2 --- include/libvirt/libvirt.h.in | 12 ++ src/libvirt.c | 321 +- src/libvirt_public.syms | 2 + 3 files changed, 332 insertions(+), 3 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 2b2c1fd..4bdcd43 100644 --- a/src/libvirt.c +++ b/src/libvirt.c + +/** + * virDomainMigrate2: + * @domain: a domain object + * @dconn: destination host (a connection object) + * @flags: flags + * @dxml: optional XML config for launching guest on target The other optional parameters have their optional in (). So this optional should be in () too, or the others should have their () removed. + * @dname: (optional) rename domain to this at destination + * @uri: (optional) dest hostname/URI as seen from the source host + * @bandwidth: (optional) specify migration bandwidth limit in Mbps + * + * Migrate the domain object from its current host to the destination + * host given by dconn (a connection to the destination host). + * +/** + * virDomainMigrateToURI2: + * @domain: a domain object + * @dconnuri: optional URI for target libvirtd if @flags includes VIR_MIGRATE_PEER2PEER + * @miguri: optional URI for invoking the migration, not if @flags includs VIR_MIGRATE_TUNNELLED + * @dxml: optional XML config for launching guest on target The same comment from above about the word optional applies here too. + * @flags: flags + * @dname: (optional) rename domain to this at destination + * @bandwidth: (optional) specify migration bandwidth limit in Mbps ACK to be patch as it, but do we really want to add a new public API to 0.9.2 for a feature that no driver implements yet and might not implement it before 0.9.2? As I understand it the URI separation already works but the XML override isn't implemented yet. Or do you already have the XML override implemented but did post the patch yet? I don't have XML override implemented yet. QEMU returns an error if you attempt to use it. I figured that since I had made the migration wire protocol support it, we might as well have the public API too. I can work up some QEMU code without much trouble too. The only missing bit is the ability to compare two virDomainDefPtr instances and validate that they have the same guest ABI (ie same list of device models + device addresses). Daniel My concern here is that we add a public API and don't implemented it in a driver for 0.9.2 and later on when we implement it we might figure out that we should have made the public API for it different, but we already released it and can't change it anymore. To be fair this concern is quite weak and I don't see how this could actually happen in this particular case, but I'd like to be on the safe side with something that we can't change easily later on anymore. So, I would appreciate it if we get this actually implemented for 0.9.2, but if not I don't consider this as a showstopper for this patch. Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] esx: Report an error when auth pointer is missing instead of declining
Otherwise an attempt to use virConnectOpen or virConnectOpenAuth without auth pointer results in the driver declining the URI and libvirt falling back to the remote driver for an esx:// URI. --- src/esx/esx_driver.c | 15 --- 1 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 7fe5446..845dd4a 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -922,9 +922,18 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) return VIR_DRV_OPEN_DECLINED; } -/* Decline URIs without server part, or missing auth */ -if (conn-uri-server == NULL || auth == NULL || auth-cb == NULL) { -return VIR_DRV_OPEN_DECLINED; +/* Require server part */ +if (conn-uri-server == NULL) { +ESX_ERROR(VIR_ERR_INVALID_ARG, %s, + _(URI is missing the server part)); +return VIR_DRV_OPEN_ERROR; +} + +/* Require auth */ +if (auth == NULL || auth-cb == NULL) { +ESX_ERROR(VIR_ERR_INVALID_ARG, %s, + _(Missing or invalid auth pointer)); +return VIR_DRV_OPEN_ERROR; } /* Allocate per-connection private data */ -- 1.7.0.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] esx: Report an error when auth pointer is missing instead of declining
On 05/25/2011 07:53 AM, Matthias Bolte wrote: Otherwise an attempt to use virConnectOpen or virConnectOpenAuth without auth pointer results in the driver declining the URI and libvirt falling back to the remote driver for an esx:// URI. --- src/esx/esx_driver.c | 15 --- 1 files changed, 12 insertions(+), 3 deletions(-) ACK. -- Eric Blake ebl...@redhat.com+1-801-349-2682 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] esx: Report an error when auth pointer is missing instead of declining
2011/5/25 Eric Blake ebl...@redhat.com: On 05/25/2011 07:53 AM, Matthias Bolte wrote: Otherwise an attempt to use virConnectOpen or virConnectOpenAuth without auth pointer results in the driver declining the URI and libvirt falling back to the remote driver for an esx:// URI. --- src/esx/esx_driver.c | 15 --- 1 files changed, 12 insertions(+), 3 deletions(-) ACK. Thanks, pushed. Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2] time_t is not a long on FreeBSD, switch internal type to long long
--- v2: switch internal type to long long instead of adding casts for time_t src/conf/domain_conf.c |8 src/conf/domain_conf.h |2 +- src/esx/esx_vi_types.c |2 +- src/esx/esx_vi_types.h |2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 3f2fb11..8ff155b 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9183,7 +9183,7 @@ virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, def-name = virXPathString(string(./name), ctxt); if (def-name == NULL) -ignore_value(virAsprintf(def-name, %ld, tv.tv_sec)); +ignore_value(virAsprintf(def-name, %lld, (long long)tv.tv_sec)); if (def-name == NULL) { virReportOOMError(); @@ -9193,8 +9193,8 @@ virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, def-description = virXPathString(string(./description), ctxt); if (!newSnapshot) { -if (virXPathLong(string(./creationTime), ctxt, - def-creationTime) 0) { +if (virXPathLongLong(string(./creationTime), ctxt, + def-creationTime) 0) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, %s, _(missing creationTime from existing snapshot)); goto cleanup; @@ -9259,7 +9259,7 @@ char *virDomainSnapshotDefFormat(char *domain_uuid, virBufferAsprintf(buf, name%s/name\n, def-parent); virBufferAddLit(buf, /parent\n); } -virBufferAsprintf(buf, creationTime%ld/creationTime\n, +virBufferAsprintf(buf, creationTime%lld/creationTime\n, def-creationTime); virBufferAddLit(buf, domain\n); virBufferAsprintf(buf, uuid%s/uuid\n, domain_uuid); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 9d4349e..d4245d8 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1042,7 +1042,7 @@ struct _virDomainSnapshotDef { char *name; char *description; char *parent; -time_t creationTime; +long long creationTime; /* in seconds */ int state; long active; diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c index c689ab0..2332fde 100644 --- a/src/esx/esx_vi_types.c +++ b/src/esx/esx_vi_types.c @@ -1402,7 +1402,7 @@ esxVI_DateTime_Deserialize(xmlNodePtr node, esxVI_DateTime **dateTime) int esxVI_DateTime_ConvertToCalendarTime(esxVI_DateTime *dateTime, - time_t *secondsSinceEpoch) + long long *secondsSinceEpoch) { char value[64] = ; char *tmp; diff --git a/src/esx/esx_vi_types.h b/src/esx/esx_vi_types.h index d141a38..3d843bf 100644 --- a/src/esx/esx_vi_types.h +++ b/src/esx/esx_vi_types.h @@ -264,7 +264,7 @@ int esxVI_DateTime_Serialize(esxVI_DateTime *dateTime, const char *element, virBufferPtr output); int esxVI_DateTime_Deserialize(xmlNodePtr node, esxVI_DateTime **dateTime); int esxVI_DateTime_ConvertToCalendarTime(esxVI_DateTime *dateTime, - time_t *secondsSinceEpoch); + long long *secondsSinceEpoch); -- 1.7.0.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2] virsh: time_t is not a long on FreeBSD
localtime_r expects time_t. --- v2: add overflow check tools/virsh.c | 14 ++ 1 files changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index de49489..b43c167 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -10442,7 +10442,8 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) char *doc = NULL; virDomainSnapshotPtr snapshot = NULL; char *state = NULL; -long creation; +long long creation_longlong; +time_t creation_time_t; char timestr[100]; struct tm time_info; @@ -10501,10 +10502,15 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) state = virXPathString(string(/domainsnapshot/state), ctxt); if (state == NULL) continue; -if (virXPathLong(string(/domainsnapshot/creationTime), ctxt, - creation) 0) +if (virXPathLongLong(string(/domainsnapshot/creationTime), ctxt, + creation_longlong) 0) continue; -localtime_r(creation, time_info); +creation_time_t = creation_longlong; +if (creation_time_t != creation_longlong) { +vshError(ctl, %s, _(time_t overflow)); +continue; +} +localtime_r(creation_time_t, time_info); strftime(timestr, sizeof(timestr), %Y-%m-%d %H:%M:%S %z, time_info); vshPrint(ctl, %-20s %-25s %s\n, names[i], timestr, state); -- 1.7.0.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 0/9] Many migration enhancements bug fixes
On Tue, May 24, 2011 at 10:47:40AM -0400, Daniel P. Berrange wrote: This is a series containing all my pending migration related enhancements and bugfixes. It includes these previous patches to change the migration v3 protocol API + ABI http://www.redhat.com/archives/libvir-list/2011-May/msg01243.html Patch 9 also changes the v3 protocol API/ABI to deal with an error reporting problem I discovered in testing. I've pushed this series, with all the review comments addressed Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 3/9] Introduce two method migration APIs
On Wed, May 25, 2011 at 03:09:53PM +0200, Matthias Bolte wrote: 2011/5/25 Daniel P. Berrange berra...@redhat.com: On Wed, May 25, 2011 at 09:45:50AM +0200, Matthias Bolte wrote: 2011/5/24 Daniel P. Berrange berra...@redhat.com: There are two pieces of information which are desirable for migration, which cannot be supplied by applications - The explicit QEMU migration URI, while using Peer2Peer migration - An override for the target VM XML This introduces two new public APIs to support these extra parameters. There is no need for extra wire protocool changes, since this is supported by the v3 migration enhancements * include/libvirt/libvirt.h.in, src/libvirt.c, src/libvirt_public.syms: Add virDomainMigrate2 and virDomainMigrateToURI2 --- include/libvirt/libvirt.h.in | 12 ++ src/libvirt.c | 321 +- src/libvirt_public.syms | 2 + 3 files changed, 332 insertions(+), 3 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 2b2c1fd..4bdcd43 100644 --- a/src/libvirt.c +++ b/src/libvirt.c + +/** + * virDomainMigrate2: + * @domain: a domain object + * @dconn: destination host (a connection object) + * @flags: flags + * @dxml: optional XML config for launching guest on target The other optional parameters have their optional in (). So this optional should be in () too, or the others should have their () removed. + * @dname: (optional) rename domain to this at destination + * @uri: (optional) dest hostname/URI as seen from the source host + * @bandwidth: (optional) specify migration bandwidth limit in Mbps + * + * Migrate the domain object from its current host to the destination + * host given by dconn (a connection to the destination host). + * +/** + * virDomainMigrateToURI2: + * @domain: a domain object + * @dconnuri: optional URI for target libvirtd if @flags includes VIR_MIGRATE_PEER2PEER + * @miguri: optional URI for invoking the migration, not if @flags includs VIR_MIGRATE_TUNNELLED + * @dxml: optional XML config for launching guest on target The same comment from above about the word optional applies here too. + * @flags: flags + * @dname: (optional) rename domain to this at destination + * @bandwidth: (optional) specify migration bandwidth limit in Mbps ACK to be patch as it, but do we really want to add a new public API to 0.9.2 for a feature that no driver implements yet and might not implement it before 0.9.2? As I understand it the URI separation already works but the XML override isn't implemented yet. Or do you already have the XML override implemented but did post the patch yet? I don't have XML override implemented yet. QEMU returns an error if you attempt to use it. I figured that since I had made the migration wire protocol support it, we might as well have the public API too. I can work up some QEMU code without much trouble too. The only missing bit is the ability to compare two virDomainDefPtr instances and validate that they have the same guest ABI (ie same list of device models + device addresses). Daniel My concern here is that we add a public API and don't implemented it in a driver for 0.9.2 and later on when we implement it we might figure out that we should have made the public API for it different, but we already released it and can't change it anymore. To be fair this concern is quite weak and I don't see how this could actually happen in this particular case, but I'd like to be on the safe side with something that we can't change easily later on anymore. Even without the public API addition, the previous patches add the functionality at the wire protocol, so we're tied down in that respect already. So, I would appreciate it if we get this actually implemented for 0.9.2, but if not I don't consider this as a showstopper for this patch. I'll work on a QEMU impl for it asap. Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2] time_t is not a long on FreeBSD, switch internal type to long long
On 05/25/2011 09:05 AM, Matthias Bolte wrote: --- v2: switch internal type to long long instead of adding casts for time_t src/conf/domain_conf.c |8 src/conf/domain_conf.h |2 +- src/esx/esx_vi_types.c |2 +- src/esx/esx_vi_types.h |2 +- 4 files changed, 7 insertions(+), 7 deletions(-) ACK. -- Eric Blake ebl...@redhat.com+1-801-349-2682 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2] virsh: time_t is not a long on FreeBSD
On 05/25/2011 09:06 AM, Matthias Bolte wrote: localtime_r expects time_t. --- v2: add overflow check ACK. -localtime_r(creation, time_info); +creation_time_t = creation_longlong; +if (creation_time_t != creation_longlong) { +vshError(ctl, %s, _(time_t overflow)); We shouldn't hit this error until 2038, and by then, hopefully more 32-bit platforms (if any are still running) will have switched to 64-bit time_t. :) But I agree with keeping this error in the code, since silent wraparound is always worse than explicit mention of overflow. -- Eric Blake ebl...@redhat.com+1-801-349-2682 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 1/7] remote generator: Handle virDomainCreateWithFlags
On Mon, May 23, 2011 at 07:36:04PM +0200, Matthias Bolte wrote: Add special case code for updating a given domain object instead of returning a new one. --- daemon/remote.c | 30 --- daemon/remote_generator.pl | 55 + src/remote/remote_driver.c | 32 src/remote/remote_protocol.x |2 +- 4 files changed, 40 insertions(+), 79 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 80783b3..fcda2c5 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -895,36 +895,6 @@ cleanup: } static int -remoteDispatchDomainCreateWithFlags(struct qemud_server *server ATTRIBUTE_UNUSED, -struct qemud_client *client ATTRIBUTE_UNUSED, -virConnectPtr conn, -remote_message_header *hdr ATTRIBUTE_UNUSED, -remote_error *rerr, -remote_domain_create_with_flags_args *args, -remote_domain_create_with_flags_ret *ret) -{ -int rv = -1; -virDomainPtr dom = NULL; - -if (!(dom = get_nonnull_domain(conn, args-dom))) -goto cleanup; - -if (virDomainCreateWithFlags(dom, args-flags) 0) -goto cleanup; - -make_nonnull_domain(ret-dom, dom); - -rv = 0; - -cleanup: -if (rv 0) -remoteDispatchError(rerr); -if (dom) -virDomainFree(dom); -return rv; -} - -static int remoteDispatchDomainGetSecurityLabel(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index d21f959..b23e3b1 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -450,14 +450,22 @@ elsif ($opt_b) { } elsif ($ret_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|interface|node_device|secret|nwfilter|domain_snapshot) (\S+);/) { my $type_name = name_to_ProcName($1); -push(@vars_list, vir${type_name}Ptr $2 = NULL); -push(@ret_list, make_nonnull_$1(ret-$2, $2);); -push(@free_list, - if ($2)\n . - vir${type_name}Free($2);); -$single_ret_var = $2; -$single_ret_by_ref = 0; -$single_ret_check = == NULL; +if ($call-{ProcName} eq DomainCreateWithFlags) { +# SPECIAL: virDomainCreateWithFlags updates the given +# domain object instead of returning a new one +push(@ret_list, make_nonnull_$1(ret-$2, $2);); +$single_ret_var = undef; +$single_ret_by_ref = 1; +} else { +push(@vars_list, vir${type_name}Ptr $2 = NULL); +push(@ret_list, make_nonnull_$1(ret-$2, $2);); +push(@free_list, + if ($2)\n . + vir${type_name}Free($2);); +$single_ret_var = $2; +$single_ret_by_ref = 0; +$single_ret_check = == NULL; +} } elsif ($ret_member =~ m/^int (\S+)(\S+);/) { push(@vars_list, int len); push(@ret_list, ret-$1.$1_len = len;); @@ -679,7 +687,12 @@ elsif ($opt_b) { if ($single_ret_by_ref) { print if (vir$prefix$proc_name(; print join(', ', @args_list); -print , $single_ret_var) 0)\n; + +if (defined $single_ret_var) { +print , $single_ret_var; +} + +print ) 0)\n; } else { print if (($single_ret_var = vir$prefix$proc_name(; print join(', ', @args_list); @@ -979,15 +992,25 @@ elsif ($opt_k) { $priv_name = ${name}PrivateData; } -if ($name eq domain_snapshot) { -push(@ret_list, rv = get_nonnull_$name(dom, ret.$arg_name);); +if ($call-{ProcName} eq DomainCreateWithFlags) { +# SPECIAL: virDomainCreateWithFlags updates the given +# domain object instead of returning a new one +push(@ret_list, dom-id = ret.dom.id;); +push(@ret_list, xdr_free((xdrproc_t)xdr_$call-{ret}, (char
Re: [libvirt] [PATCH 2/7] remote generator: Rename virNodeGetCellsFreeMemory parameters to common pattern
On Mon, May 23, 2011 at 07:36:05PM +0200, Matthias Bolte wrote: This allows to remove some special case code from the generator. --- daemon/remote_generator.pl |3 +-- src/remote/remote_driver.c |8 src/remote/remote_protocol.x |4 ++-- src/remote_protocol-structs |8 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index b23e3b1..2da0f2e 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -505,17 +505,16 @@ elsif ($opt_b) { $single_ret_by_ref = 0; $single_ret_as_list = 1; $single_ret_list_name = $1; +$single_ret_list_max_var = max$1; $single_ret_list_max_define = $2; my $conn = shift(@args_list); if ($call-{ProcName} eq NodeGetCellsFreeMemory) { $single_ret_check = = 0; -$single_ret_list_max_var = maxCells; unshift(@args_list, (unsigned long long *)ret-$1.$1_val); } else { $single_ret_check = 0; -$single_ret_list_max_var = max$1; unshift(@args_list, ret-$1.$1_val); } diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 69b888d..fb542c5 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1715,7 +1715,7 @@ remoteNodeGetCellsFreeMemory(virConnectPtr conn, } args.startCell = startCell; -args.maxCells = maxCells; +args.maxcells = maxCells; memset (ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_CELLS_FREE_MEMORY, @@ -1723,12 +1723,12 @@ remoteNodeGetCellsFreeMemory(virConnectPtr conn, (xdrproc_t) xdr_remote_node_get_cells_free_memory_ret, (char *)ret) == -1) goto done; -for (i = 0 ; i ret.freeMems.freeMems_len ; i++) -freeMems[i] = ret.freeMems.freeMems_val[i]; +for (i = 0 ; i ret.cells.cells_len ; i++) +freeMems[i] = ret.cells.cells_val[i]; xdr_free((xdrproc_t) xdr_remote_node_get_cells_free_memory_ret, (char *) ret); -rv = ret.freeMems.freeMems_len; +rv = ret.cells.cells_len; done: remoteDriverUnlock(priv); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 9df86da..3e9bd5c 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -442,11 +442,11 @@ struct remote_get_capabilities_ret { struct remote_node_get_cells_free_memory_args { int startCell; -int maxCells; +int maxcells; }; struct remote_node_get_cells_free_memory_ret { -hyper freeMemsREMOTE_NODE_MAX_CELLS; +hyper cellsREMOTE_NODE_MAX_CELLS; }; struct remote_node_get_free_memory_ret { diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 414b4d5..5491f73 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -153,13 +153,13 @@ struct remote_get_capabilities_ret { }; struct remote_node_get_cells_free_memory_args { intstartCell; -intmaxCells; +intmaxcells; }; struct remote_node_get_cells_free_memory_ret { struct { -u_int freeMems_len; -int64_t * freeMems_val; -} freeMems; +u_int cells_len; +int64_t * cells_val; +} cells; }; struct remote_node_get_free_memory_ret { int64_tfreeMem; ACK Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 3/7] remote generator: Make call-by-reference handling stricter
On Mon, May 23, 2011 at 07:36:06PM +0200, Matthias Bolte wrote: Several functions return values by reference parameters. This is realized by passing the members of remote_CALL_ret by reference to the called function. The position of this parameters in the function signature follows some patterns with some exceptions. This patterns and exceptions are hardcoded in the generator. Add an insert@offset annotation to the remote_CALL_ret struct members for functions that return lists to remove some of the hardcoded patterns and exceptions. --- daemon/remote_generator.pl | 69 ++--- src/remote/remote_protocol.x | 37 -- 2 files changed, 44 insertions(+), 62 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 2da0f2e..8b3794f 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -405,8 +405,9 @@ elsif ($opt_b) { } else { die unhandled type for multi-return-value: $ret_member; } -} elsif ($ret_member =~ m/^remote_nonnull_string (\S+)(\S+);/) { +} elsif ($ret_member =~ m/^remote_nonnull_string (\S+)(\S+);\s*\/\*\s*insert@(\d+)\s*\*\//) { push(@vars_list, int len); +splice(@args_list, int($3), 0, (ret-$1.$1_val)); push(@ret_list, ret-$1.$1_len = len;); push(@free_list_on_error, VIR_FREE(ret-$1.$1_val);); $single_ret_var = len; @@ -416,18 +417,9 @@ elsif ($opt_b) { $single_ret_list_name = $1; $single_ret_list_max_var = max$1; $single_ret_list_max_define = $2; - -if ($call-{ProcName} eq NodeListDevices) { -my $conn = shift(@args_list); -my $cap = shift(@args_list); -unshift(@args_list, ret-$1.$1_val); -unshift(@args_list, $cap); -unshift(@args_list, $conn); -} else { -my $conn = shift(@args_list); -unshift(@args_list, ret-$1.$1_val); -unshift(@args_list, $conn); -} +} elsif ($ret_member =~ m/^remote_nonnull_string (\S+)\S+;/) { +# error out on unannotated arrays +die remote_nonnull_string array without insert@offset annotation: $ret_member; } elsif ($ret_member =~ m/^remote_nonnull_string (\S+);/) { if ($call-{ProcName} eq GetType) { # SPECIAL: virConnectGetType returns a constant string that must @@ -466,8 +458,9 @@ elsif ($opt_b) { $single_ret_by_ref = 0; $single_ret_check = == NULL; } -} elsif ($ret_member =~ m/^int (\S+)(\S+);/) { +} elsif ($ret_member =~ m/^int (\S+)(\S+);\s*\/\*\s*insert@(\d+)\s*\*\//) { push(@vars_list, int len); +splice(@args_list, int($3), 0, (ret-$1.$1_val)); push(@ret_list, ret-$1.$1_len = len;); push(@free_list_on_error, VIR_FREE(ret-$1.$1_val);); $single_ret_var = len; @@ -477,10 +470,9 @@ elsif ($opt_b) { $single_ret_list_name = $1; $single_ret_list_max_var = max$1; $single_ret_list_max_define = $2; - -my $conn = shift(@args_list); -unshift(@args_list, ret-$1.$1_val); -unshift(@args_list, $conn); +} elsif ($ret_member =~ m/^int (\S+)\S+;/) { +# error out on unannotated arrays +die int array without insert@offset annotation: $ret_member; } elsif ($ret_member =~ m/^int (\S+);/) { push(@vars_list, int $1); push(@ret_list, ret-$1 = $1;); @@ -497,7 +489,7 @@ elsif ($opt_b) { $single_ret_check = 0; } } -} elsif ($ret_member =~ m/^hyper (\S+)(\S+);/) { +} elsif ($ret_member =~ m/^hyper (\S+)(\S+);\s*\/\*\s*insert@(\d+)\s*\*\//) { push(@vars_list, int len); push(@ret_list, ret-$1.$1_len = len;); push(@free_list_on_error, VIR_FREE(ret-$1.$1_val);); @@ -508,17 +500,16 @@ elsif ($opt_b) { $single_ret_list_max_var = max$1; $single_ret_list_max_define = $2; -my $conn = shift(@args_list); - if ($call-{ProcName} eq NodeGetCellsFreeMemory) {
Re: [libvirt] [PATCH] build: avoid strerror_r pitfalls
On 05/24/2011 11:23 PM, Matthias Bolte wrote: 2011/5/25 Eric Blake ebl...@redhat.com: In particular, this guarantees that virStrerror always gives a useful result. * .gnulib: Update to latest, for (lots of) strerror_r fixes. --- This patch removes the need for Daniel's proposal: https://www.redhat.com/archives/libvir-list/2011-May/msg01236.html Now gnulib guarantees that strerror_r will never leave garbage in the buffer. I'm impressed - I'm now up to 3 out of 3 glibc bugs reported and fixed in the last month (more often than not, I've had the misfortune of my glibc bugs report attempts being rejected with rather scathing comments that the bug is not in glibc but in my understanding, or left without a response for months on end). Leaving garbage in buf upon strerror_r failure was one of those fixes. This also pulls in the fix for the fnmatch compile warning. ACK. Thanks; pushed. -- Eric Blake ebl...@redhat.com+1-801-349-2682 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 4/7] remote generator: Handle stream-using functions
On Mon, May 23, 2011 at 07:36:07PM +0200, Matthias Bolte wrote: Extend procedure annotation in the .x file for stream handling. Adds a missing remoteStreamRelease call to remoteDomainScreenshot error path. --- daemon/remote.c | 238 -- daemon/remote_generator.pl | 114 + src/remote/remote_driver.c | 207 src/remote/remote_protocol.x | 38 +--- 4 files changed, 120 insertions(+), 477 deletions(-) diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 63f7ebb..5b9300a 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -2054,7 +2054,14 @@ 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 - * it handles src/remote. */ + * it handles src/remote. Additional flags can be specified after a + * pipe. + * + * The (readstream|writestream)@offset flag lets daemon and src/remote + * create a stream. The direction is defined from the src/remote point + * of view. A readstream transfers data from daemon to src/remote. The + * offset specifies at which offset the stream parameter is inserted + * in the function parameter list. */ REMOTE_PROC_OPEN = 1, /* skipgen skipgen */ REMOTE_PROC_CLOSE = 2, /* skipgen skipgen */ REMOTE_PROC_GET_TYPE = 3, /* autogen skipgen */ @@ -2216,7 +2223,7 @@ enum remote_procedure { REMOTE_PROC_SECRET_GET_VALUE = 145, /* skipgen skipgen */ REMOTE_PROC_SECRET_UNDEFINE = 146, /* autogen autogen */ REMOTE_PROC_SECRET_LOOKUP_BY_USAGE = 147, /* autogen autogen */ -REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL = 148, /* skipgen skipgen */ +REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL = 148, /* autogen autogen | writestream@1 */ REMOTE_PROC_IS_SECURE = 149, /* autogen skipgen */ REMOTE_PROC_DOMAIN_IS_ACTIVE = 150, /* autogen autogen */ @@ -2275,35 +2282,40 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS = 199, /* autogen autogen */ REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS = 200, /* autogen autogen */ -REMOTE_PROC_DOMAIN_OPEN_CONSOLE = 201, /* skipgen skipgen */ +REMOTE_PROC_DOMAIN_OPEN_CONSOLE = 201, /* autogen autogen | readstream@2 */ Technically this is a bi-directional stream, but that doesn't matter from a code-gen POV, so fine. REMOTE_PROC_DOMAIN_IS_UPDATED = 202, /* autogen autogen */ REMOTE_PROC_GET_SYSINFO = 203, /* autogen autogen */ REMOTE_PROC_DOMAIN_SET_MEMORY_FLAGS = 204, /* autogen autogen */ REMOTE_PROC_DOMAIN_SET_BLKIO_PARAMETERS = 205, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, /* autogen autogen */ -REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, /* skipgen skipgen */ -REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, /* skipgen skipgen */ +REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, /* autogen autogen | writestream@1 */ +REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, /* autogen autogen | readstream@1 */ REMOTE_PROC_DOMAIN_INJECT_NMI = 210, /* autogen autogen */ -REMOTE_PROC_DOMAIN_SCREENSHOT = 211, /* skipgen skipgen */ +REMOTE_PROC_DOMAIN_SCREENSHOT = 211, /* skipgen autogen | readstream@1 */ REMOTE_PROC_DOMAIN_GET_STATE = 212, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_MIGRATE_BEGIN3 = 213, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_MIGRATE_PREPARE3 = 214, /* skipgen skipgen */ -REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3 = 215, /* skipgen skipgen */ +REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3 = 215, /* autogen skipgen | writestream@1 */ REMOTE_PROC_DOMAIN_MIGRATE_PERFORM3 = 216, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_MIGRATE_FINISH3 = 217, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3 = 218, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS_FLAGS = 219 /* skipgen skipgen */ -/* - * Notice how the entries are grouped in sets of 10 ? +/* Notice how the entries are grouped in sets of 10 ? * Nice isn't it. Please keep it this way when adding more. - */ - -/* Each function must have a two-word comment. The first word is + * + * Each function must have a two-word comment. The first word is * whether remote_generator.pl handles daemon, the second whether - * it handles src/remote. */ + * it handles src/remote. Additional flags can be specified after a + * pipe. + * + * The (readstream|writestream)@offset flag lets daemon and src/remote + * create a stream. The direction is defined from the src/remote point + * of view. A readstream transfers data from daemon to src/remote. The + *
Re: [libvirt] [PATCH 5/7] remote generator: Fix XDR sign mismatch for virNodeGet(Cells)FreeMemory
On Mon, May 23, 2011 at 07:36:08PM +0200, Matthias Bolte wrote: virNodeGetFreeMemory used unsigned long long in the public API but signed hyper in the XDR protocol. Convert the XDR protocol to use unsigned hyper. As explained by Eric before, this doesn't affect the on-the-wire protocol. --- daemon/remote_generator.pl | 18 ++ src/remote/remote_protocol.x |4 ++-- src/remote_protocol-structs |4 ++-- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index c405dc8..9143b3a 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -501,7 +501,7 @@ elsif ($opt_b) { $single_ret_check = 0; } } -} elsif ($ret_member =~ m/^hyper (\S+)(\S+);\s*\/\*\s*insert@(\d+)\s*\*\//) { +} elsif ($ret_member =~ m/^(?:unsigned )?hyper (\S+)(\S+);\s*\/\*\s*insert@(\d+)\s*\*\//) { push(@vars_list, int len); push(@ret_list, ret-$1.$1_len = len;); push(@free_list_on_error, VIR_FREE(ret-$1.$1_val);); @@ -519,7 +519,7 @@ elsif ($opt_b) { $single_ret_check = 0; splice(@args_list, int($3), 0, (ret-$1.$1_val)); } -} elsif ($ret_member =~ m/^hyper (\S+)\S+;/) { +} elsif ($ret_member =~ m/^(?:unsigned )?hyper (\S+)\S+;/) { # error out on unannotated arrays die hyper array without insert@offset annotation: $ret_member; } elsif ($ret_member =~ m/^(unsigned )?hyper (\S+);/) { @@ -1063,20 +1063,14 @@ elsif ($opt_k) { push(@ret_list, rv = 0;); $single_ret_var = int rv = -1; $single_ret_type = int; -} else { -push(@ret_list, rv = ret.$arg_name;); -$single_ret_var = unsigned long rv = 0; -$single_ret_type = unsigned long; -} -} elsif ($ret_member =~ m/^hyper (\S+);/) { -my $arg_name = $1; - -if ($call-{ProcName} eq NodeGetFreeMemory) { +} elsif ($call-{ProcName} eq NodeGetFreeMemory) { push(@ret_list, rv = ret.$arg_name;); $single_ret_var = unsigned long long rv = 0; $single_ret_type = unsigned long long; } else { -die unhandled type for return value: $ret_member; +push(@ret_list, rv = ret.$arg_name;); +$single_ret_var = unsigned long rv = 0; +$single_ret_type = unsigned long; } } elsif ($ret_member =~ m/^(\/)?\*/) { # ignore comments diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 5b9300a..f5218cd 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -449,11 +449,11 @@ struct remote_node_get_cells_free_memory_args { }; struct remote_node_get_cells_free_memory_ret { -hyper cellsREMOTE_NODE_MAX_CELLS; /* insert@1 */ +unsigned hyper cellsREMOTE_NODE_MAX_CELLS; /* insert@1 */ }; struct remote_node_get_free_memory_ret { -hyper freeMem; +unsigned hyper freeMem; }; struct remote_domain_get_scheduler_type_args { diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 5491f73..fd23fa0 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -158,11 +158,11 @@ struct remote_node_get_cells_free_memory_args { struct remote_node_get_cells_free_memory_ret { struct { u_int cells_len; -int64_t * cells_val; +uint64_t * cells_val; } cells; }; struct remote_node_get_free_memory_ret { -int64_tfreeMem; +uint64_t freeMem; }; struct remote_domain_get_scheduler_type_args { remote_nonnull_domain dom; ACK Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 6/7] Fix sign mismatches between public API, driver API and XDR protocol
On Mon, May 23, 2011 at 07:36:09PM +0200, Matthias Bolte wrote: In most cases this affects flags parameters that are unsigned in the public and driver API but signed in the XDR protocol. Switch the XDR protocol to unsigned for those. A counterexample is virNWFilterGetXMLDesc. Its flags parameter is signed in the public API and XDR protocol, but unsigned in the driver API. --- daemon/remote_generator.pl | 16 src/driver.h |2 +- src/nwfilter/nwfilter_driver.c |2 +- src/remote/remote_protocol.x | 30 +++--- src/remote_protocol-structs| 30 +++--- 5 files changed, 32 insertions(+), 48 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 9143b3a..ac808fb 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -896,22 +896,6 @@ elsif ($opt_k) { $type_name .= $2; $type_name =~ s/hyper/long/; -if ($type_name eq int) { -# fix bad decisions in the xdr protocol -if ($arg_name eq flags and -$call-{ProcName} ne DomainCoreDump and -$call-{ProcName} ne DomainGetXMLDesc and -$call-{ProcName} ne NetworkGetXMLDesc) { -$type_name = unsigned int; -} elsif ($arg_name eq nvcpus and - $call-{ProcName} eq DomainSetVcpus) { -$type_name = unsigned int; -} elsif ($arg_name eq vcpu and - $call-{ProcName} eq DomainPinVcpu) { -$type_name = unsigned int; -} -} - # SPECIAL: some hyper parameters map to long longs if (($call-{ProcName} eq DomainMigrateSetMaxDowntime and $arg_name eq downtime) or diff --git a/src/driver.h b/src/driver.h index 450dd53..58e8f02 100644 --- a/src/driver.h +++ b/src/driver.h @@ -1282,7 +1282,7 @@ typedef int typedef char * (*virDrvNWFilterGetXMLDesc) (virNWFilterPtr nwfilter, - unsigned int flags); + int flags); typedef struct _virNWFilterDriver virNWFilterDriver; diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index db3d789..d9ac17e 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -407,7 +407,7 @@ cleanup: static char * nwfilterGetXMLDesc(virNWFilterPtr obj, - unsigned int flags) { + int flags) { virNWFilterDriverStatePtr driver = obj-conn-nwfilterPrivateData; virNWFilterObjPtr nwfilter; char *ret = NULL; diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index f5218cd..2b9f9de 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -430,7 +430,7 @@ struct remote_get_max_vcpus_ret { struct remote_node_get_info_ret { char model[32]; -hyper memory; +unsigned hyper memory; int cpus; int mhz; int nodes; @@ -612,7 +612,7 @@ struct remote_num_of_domains_ret { struct remote_domain_create_xml_args { remote_nonnull_string xml_desc; -int flags; +unsigned int flags; }; struct remote_domain_create_xml_ret { @@ -657,7 +657,7 @@ struct remote_domain_shutdown_args { struct remote_domain_reboot_args { remote_nonnull_domain dom; -int flags; +unsigned int flags; }; struct remote_domain_destroy_args { @@ -843,7 +843,7 @@ struct remote_domain_inject_nmi_args { struct remote_domain_set_vcpus_args { remote_nonnull_domain dom; -int nvcpus; +unsigned int nvcpus; }; struct remote_domain_set_vcpus_flags_args { @@ -863,7 +863,7 @@ struct remote_domain_get_vcpus_flags_ret { struct remote_domain_pin_vcpu_args { remote_nonnull_domain dom; -int vcpu; +unsigned int vcpu; opaque cpumapREMOTE_CPUMAP_MAX; }; @@ -1527,7 +1527,7 @@ struct remote_node_device_reset_args { struct remote_node_device_create_xml_args { remote_nonnull_string xml_desc; -int flags; +unsigned int flags; }; struct remote_node_device_create_xml_ret { @@ -1871,7 +1871,7 @@ struct remote_domain_managed_save_remove_args { struct remote_domain_snapshot_create_xml_args { remote_nonnull_domain dom; remote_nonnull_string xml_desc; -int flags; +unsigned int flags; }; struct remote_domain_snapshot_create_xml_ret { @@ -1880,7 +1880,7 @@ struct remote_domain_snapshot_create_xml_ret { struct remote_domain_snapshot_get_xml_desc_args {
Re: [libvirt] [PATCH 6/7] Fix sign mismatches between public API, driver API and XDR protocol
On Mon, May 23, 2011 at 07:36:09PM +0200, Matthias Bolte wrote: In most cases this affects flags parameters that are unsigned in the public and driver API but signed in the XDR protocol. Switch the XDR protocol to unsigned for those. A counterexample is virNWFilterGetXMLDesc. Its flags parameter is signed in the public API and XDR protocol, but unsigned in the driver API. For the record, the XDR code confirms this is ok. Compare the xdr_int32 with xdr_uint32 functions: bool_t xdr_int32_t (XDR *xdrs, int32_t *lp) { switch (xdrs-x_op) { case XDR_ENCODE: return XDR_PUTINT32 (xdrs, lp); case XDR_DECODE: return XDR_GETINT32 (xdrs, lp); case XDR_FREE: return TRUE; default: return FALSE; } } /* XDR 32bit unsigned integers */ bool_t xdr_uint32_t (XDR *xdrs, uint32_t *ulp) { switch (xdrs-x_op) { case XDR_ENCODE: return XDR_PUTINT32 (xdrs, (int32_t *) ulp); case XDR_DECODE: return XDR_GETINT32 (xdrs, (int32_t *) ulp); case XDR_FREE: return TRUE; default: return FALSE; } } So the uint32 function just casts to an int32 and put that on the wire. So there's no difference at all. Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 7/7] remote generator: Annotate hyper with the actual C type
On Mon, May 23, 2011 at 07:36:10PM +0200, Matthias Bolte wrote: Remove some special case code that took care of mapping hyper to the correct C types. Use macros for hyper to long assignments that perform overflow checks when long is smaller than hyper. Also use such macros for the safe hyper to longlong assignemts as this allows to keep the generator a bit simpler. +} elsif ($ret_member =~ m/^(unsigned )?hyper (\S+)\[\S+\];/) { +# error out on unannotated hypers +die (unsigned)? hyper without (u)?(long|longlong) annotation: $ret_member; 'hyper' in XDR world is a fixed 64 bit type, so IMHO, this should automatically map to 'long long' in the API, without requiring an annotation. eg, we should only annotate if the public API uses the variable sized 'long' / 'unsigned long' types in C. +} elsif ($ret_member =~ m/\S+;/ or $ret_member =~ m/\[\S+\];/) { +# just make all other array types fail +die unhandled type for multi-return-value: $ret_member; +} elsif ($ret_member =~ m/^(unsigned )?(char|short|int) (\S+);/) { +return $dst-$3 = $src.$3;; diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 2b9f9de..9928b77 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -371,7 +371,11 @@ struct remote_memory_param { * * '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 - * parameter list of the function to be called. */ + * parameter list of the function to be called. + * + * 'remote_CALL_args' and 'remote_CALL_ret' members of type hyper must be + * annotated with the C type they should be mapped to: long, ulong, longlong + * or ulonglong */ struct remote_open_args { /* NB. name might be NULL although in practice you can't @@ -394,11 +398,11 @@ struct remote_get_type_ret { }; struct remote_get_version_ret { -unsigned hyper hv_ver; +unsigned hyper hv_ver; /* ulong */ }; struct remote_get_lib_version_ret { -unsigned hyper lib_ver; +unsigned hyper lib_ver; /* ulong */ }; struct remote_get_hostname_ret { @@ -430,7 +434,7 @@ struct remote_get_max_vcpus_ret { struct remote_node_get_info_ret { char model[32]; -unsigned hyper memory; +unsigned hyper memory; /* ulong */ int cpus; int mhz; int nodes; @@ -449,11 +453,11 @@ struct remote_node_get_cells_free_memory_args { }; struct remote_node_get_cells_free_memory_ret { -unsigned hyper cellsREMOTE_NODE_MAX_CELLS; /* insert@1 */ +unsigned hyper cellsREMOTE_NODE_MAX_CELLS; /* insert@1 ulonglong */ }; struct remote_node_get_free_memory_ret { -unsigned hyper freeMem; +unsigned hyper freeMem; /* ulonglong */ }; struct remote_domain_get_scheduler_type_args { @@ -525,11 +529,11 @@ struct remote_domain_block_stats_args { }; struct remote_domain_block_stats_ret { -hyper rd_req; -hyper rd_bytes; -hyper wr_req; -hyper wr_bytes; -hyper errs; +hyper rd_req; /* longlong */ +hyper rd_bytes; /* longlong */ +hyper wr_req; /* longlong */ +hyper wr_bytes; /* longlong */ +hyper errs; /* longlong */ }; struct remote_domain_interface_stats_args { @@ -538,14 +542,14 @@ struct remote_domain_interface_stats_args { }; struct remote_domain_interface_stats_ret { -hyper rx_bytes; -hyper rx_packets; -hyper rx_errs; -hyper rx_drop; -hyper tx_bytes; -hyper tx_packets; -hyper tx_errs; -hyper tx_drop; +hyper rx_bytes; /* longlong */ +hyper rx_packets; /* longlong */ +hyper rx_errs; /* longlong */ +hyper rx_drop; /* longlong */ +hyper tx_bytes; /* longlong */ +hyper tx_packets; /* longlong */ +hyper tx_errs; /* longlong */ +hyper tx_drop; /* longlong */ }; struct remote_domain_memory_stats_args { @@ -556,7 +560,7 @@ struct remote_domain_memory_stats_args { struct remote_domain_memory_stat { int tag; -unsigned hyper val; +unsigned hyper val; /* longlong */ }; struct remote_domain_memory_stats_ret { @@ -593,9 +597,9 @@ struct remote_domain_get_block_info_args { }; struct remote_domain_get_block_info_ret { -unsigned hyper allocation; -unsigned hyper capacity; -unsigned hyper physical; +unsigned hyper allocation; /* ulonglong */ +unsigned hyper capacity; /* ulonglong */ +unsigned hyper physical; /* ulonglong */ }; struct remote_list_domains_args { @@ -677,22 +681,22 @@ struct remote_domain_get_max_memory_args { }; struct remote_domain_get_max_memory_ret { -unsigned hyper memory; +unsigned hyper memory; /* ulong */ }; struct remote_domain_set_max_memory_args { remote_nonnull_domain dom; -unsigned hyper memory; +unsigned hyper memory; /* ulong */ }; struct
Re: [libvirt] Live Migration UDP implementation
On Mon, May 23, 2011 at 11:23:55PM +0530, prakash hr wrote: Hi all, For my academic project to analyse the Performance of transport protocols in Live Migration of Virtual Machines.I have configured the live migration using tcp and I succeed the live migration. Now for my further remaining project work I need to do the same thing for the UDP implemataiton.When I changed the command in virsh, (My fianl command in TCP isvirsh migrate --live ubuntu21 qemu+ssh://172.16.17.23/system tcp:// 172.16.17.23:444) to udp it is not workng. It is given that qemu embeds user mode network stack which includes tcp,dhcp,udp.etc within the wemu process. Its giving the error no API found for UDP. ---Now i want to implement the patch file for migration using UDP if possible. IMHO doing migration over UDP is crazy, because migration needs to be reliable, so you'll end up having to reimplemnt most of TCP features in your UDP migration code. In any case, this is something that would have to be done in QEMU code, rather than libvirt. ---Where I should change the API in order to perform the live migration using UDP. ---Is any patch file available so that modifying that patch file will perform the Live Migration using UDP. This would be the QEMU migration code, rather than libvirt. --Is there any other transport layer protocols can be used instead of TCP during Live migration.? Not currently. --How about using RUDP instead of TCP. Best to take all these questions to the QEMU mailing list Regards,x Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 7/7] remote generator: Annotate hyper with the actual C type
On 05/25/2011 10:23 AM, Daniel P. Berrange wrote: On Mon, May 23, 2011 at 07:36:10PM +0200, Matthias Bolte wrote: Remove some special case code that took care of mapping hyper to the correct C types. Use macros for hyper to long assignments that perform overflow checks when long is smaller than hyper. Also use such macros for the safe hyper to longlong assignemts as this allows to keep the generator a bit simpler. +} elsif ($ret_member =~ m/^(unsigned )?hyper (\S+)\[\S+\];/) { +# error out on unannotated hypers +die (unsigned)? hyper without (u)?(long|longlong) annotation: $ret_member; 'hyper' in XDR world is a fixed 64 bit type, so IMHO, this should automatically map to 'long long' in the API, without requiring an annotation. eg, we should only annotate if the public API uses the variable sized 'long' / 'unsigned long' types in C. All the 'longlong' and 'ulonglong' annotations should be removed here IMHO, since they should be the default for hyper/unsigned hyper. If we add a new API that uses 'long' but forget the annotation, then we have silent type mismatch in the generated code. Since we are using hyper for both types in C, I find it better to require an annotation on all uses to be explicit on which type we meant, rather than defaulting the lack of annotation as 'long long' and only requiring annotation for 'long' - that is, I find that from the maintenance aspect, having the code generator explicitly fail because you forget an annotation (even if the annotation is the default of llong) is safer than risking silent code misgeneration. But anything is better than nothing, so I won't give any further complaints if we go with your idea of only annotating the exceptions to the 'long long' default, rather than all uses of hyper. -- Eric Blake ebl...@redhat.com+1-801-349-2682 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Allow to explicitly disable the secrets a directory storage driver
2011/5/24 Daniel Veillard veill...@redhat.com: On Tue, May 24, 2011 at 01:21:51PM +0200, Matthias Bolte wrote: --- configure.ac | 7 +-- 1 files changed, 5 insertions(+), 2 deletions(-) Okay, ACK, Daniel Thanks, pushed. Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 00/13] Add support for send keys to guest
On Wed, May 25, 2011 at 05:37:42PM +0800, Lai Jiangshan wrote: Add API virDomainSendKey() and virsh send-key command. # virsh help send-key NAME send-key - Send keycodes to the guest SYNOPSIS send-key domain [--codeset string] [--holdtime number] keycode... DESCRIPTION Send keycodes to the guest, the keycodes must be integers or the qemu-style key strings for the xt:keystring codeset or the KEY_* strings listed below for the linux codeset. Available codeset: linux the keycodes specified in /usr/include/linux/input.h(default) defaultlinux codeset will be used driver_default the hypervisor default codeset will be used xt XT(set1) scancode of standard AT keyboards and PS/2 keyboards atset1 set1 scancode of standard AT keyboards and PS/2 keyboards atset2 set2 scancode of standard AT keyboards and PS/2 keyboards atset3 set3 scancode of standard AT keyboards and PS/2 keyboards xt:keystring XT scancode, but keycode... must be the qemu-style key strings I was thinking we'd just use the Linux keycode set in the API, but I guess if the client app already has things in XT codeset, it isn't too nice to force them to convert to Linux keycodes, only for libvirt to convert them straight back for QEMU. So I think it was a good idea to add different codesets. I don't think that 'driver_default' makes sense though. For that to be usable, the person invoking the API must somehow know what the driver default codeset is. If they know that, then they can trivially just specify that already, so 'driver_default' doesn't seem to add any benefit. As for 'xt:keystring', if you think it is worth being able to use key strings, then perhaps we should have 2 apis. One API that takes a list of keycodes as ints, and one API that takes a list of keycodes as strings. This would avoid the need for every client application to maintain a mapping table of strings - ints. eg, all the mapping tables would be contained within libvirt. Examples: virsh # send-key domain 37 18 21 virsh # send-key domain --holdtime 1000 0x15 18 0xf virsh # send-key domain KEY_LEFTCTRL KEY_LEFTALT KEY_F1 virsh # send-key domain --codeset xt:keystring alt-sysrq h KEY_XXX strings for the linux codeset: For virsh, perhaps it should default to always using the strings for the keys, and only use integers if given a special flag. I think most admins using virsh would just be using strings. The integer keycodes are mostly useful for apps using the API directly. eg, perhaps virsh # send-key domain KEY_LEFTCTRL KEY_LEFTALT KEY_F1 virsh # send-key domain --codeset linux KEY_LEFTCTRL KEY_LEFTALT KEY_F1 virsh # send-key domain --codeset xt alt-sysrq h virsh # send-key domain --num 37 18 21 virsh # send-key domain --num --holdtime 1000 0x15 18 0xf virsh # send-key domain --num --codeset linux --holdtime 1000 0x15 18 0xf . . . OPTIONS [--domain] string domain name, id or uuid --codeset string the codeset of keycodes, default:linux --numthe keys are specified as integer values, --holdtime number the time (in millsecond) how long the keys will be held keycodethe key string (or value if --num is set) Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 01/13] allow name for VSH_OT_ARGV options
On Wed, May 25, 2011 at 05:37:43PM +0800, Lai Jiangshan wrote: A name will improve the usege, example # virsh help echo NAME echo - echo arguments SYNOPSIS echo [--shell] [--xml] [string]... DESCRIPTION Echo back arguments, possibly with quoting. OPTIONS --shell escape for shell use --xmlescape for XML use string arguments to echo [string]... is added to SYNOPSIS. string arguments to echo is added to OPTIONS. Signed-off-by: Lai Jiangshan la...@fujitsu.com --- tools/virsh.c | 19 +-- 1 files changed, 13 insertions(+), 6 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index de49489..c358580 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -126,7 +126,7 @@ typedef enum { VSH_OT_STRING, /* optional string option */ VSH_OT_INT, /* optional or mandatory int option */ VSH_OT_DATA, /* string data (as non-option) */ -VSH_OT_ARGV /* remaining arguments, opt-name should be */ +VSH_OT_ARGV /* remaining arguments */ } vshCmdOptType; /* @@ -10046,7 +10046,7 @@ static const vshCmdInfo info_echo[] = { static const vshCmdOptDef opts_echo[] = { {shell, VSH_OT_BOOL, 0, N_(escape for shell use)}, {xml, VSH_OT_BOOL, 0, N_(escape for XML use)}, -{, VSH_OT_ARGV, 0, N_(arguments to echo)}, +{string, VSH_OT_ARGV, 0, N_(arguments to echo)}, {NULL, 0, 0, NULL} }; @@ -11084,6 +11084,11 @@ vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name, vshError(ctl, _(option --%s already seen), name); return NULL; } +if (opt-type == VSH_OT_ARGV) { +vshError(ctl, _(variable argument %s + should not be used with --%s), name, name); +return NULL; +} *opts_seen |= 1 i; return opt; } @@ -11132,7 +11137,7 @@ vshCommandCheckOpts(vshControl *ctl, const vshCmd *cmd, uint32_t opts_required, const vshCmdOptDef *opt = def-opts[i]; vshError(ctl, - opt-type == VSH_OT_DATA ? + opt-type == VSH_OT_DATA || opt-type == VSH_OT_ARGV ? _(command '%s' requires %s option) : _(command '%s' requires --%s option), def-name, opt-name); @@ -11240,7 +11245,8 @@ vshCmddefHelp(vshControl *ctl, const char *cmdname) break; case VSH_OT_ARGV: /* xgettext:c-format */ -fmt = _([string]...); +fmt = (opt-flag VSH_OFLAG_REQ) ? _(%s...) + : _([%s]...); break; default: assert(0); @@ -11280,7 +11286,8 @@ vshCmddefHelp(vshControl *ctl, const char *cmdname) break; case VSH_OT_ARGV: /* Not really an option. */ -continue; +snprintf(buf, sizeof(buf), _(%s), opt-name); +break; default: assert(0); } @@ -12693,7 +12700,7 @@ vshReadlineOptionsGenerator(const char *text, int state) list_index++; -if (opt-type == VSH_OT_DATA) +if (opt-type == VSH_OT_DATA || opt-type == VSH_OT_ARGV) /* ignore non --option */ continue; ACK Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 02/13] improve the iteration of VSH_OT_ARGV options
On Wed, May 25, 2011 at 05:37:44PM +0800, Lai Jiangshan wrote: Signed-off-by: Lai Jiangshan la...@fujitsu.com --- tools/virsh.c | 47 --- 1 files changed, 24 insertions(+), 23 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index c358580..2e27535 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -277,7 +277,27 @@ static int vshCommandOptULongLong(const vshCmd *cmd, const char *name, unsigned long long *value) ATTRIBUTE_NONNULL(3) ATTRIBUTE_RETURN_CHECK; static bool vshCommandOptBool(const vshCmd *cmd, const char *name); -static char *vshCommandOptArgv(const vshCmd *cmd, int count); + +/* + * Iterate all the argv arguments. + * + * Requires that a VSH_OT_ARGV option be last in the + * list of supported options in CMD-def-opts. + */ +static inline const vshCmdOpt *__variable_arg(const vshCmdOpt *opt) +{ +while (opt) { + if (opt-def opt-def-type == VSH_OT_ARGV) + break; + opt = opt-next; +} + +return opt; +} + +#define for_each_variable_arg(cmd, opt) \ +for (opt = __variable_arg(cmd-opts); opt; opt = __variable_arg(opt-next)) + #define VSH_BYID (1 1) #define VSH_BYUUID (1 2) @@ -10059,6 +10079,7 @@ cmdEcho (vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd) bool shell = false; bool xml = false; int count = 0; +const vshCmdOpt *opt; char *arg; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -10067,10 +10088,11 @@ cmdEcho (vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd) if (vshCommandOptBool(cmd, xml)) xml = true; -while ((arg = vshCommandOptArgv(cmd, count)) != NULL) { +for_each_variable_arg(cmd, opt) { bool close_quote = false; char *q; +arg = opt-data; if (count) virBufferAddChar(buf, ' '); /* Add outer '' only if arg included shell metacharacters. */ @@ -11484,27 +11506,6 @@ vshCommandOptBool(const vshCmd *cmd, const char *name) return vshCommandOpt(cmd, name) != NULL; } -/* - * Returns the COUNT argv argument, or NULL after last argument. - * - * Requires that a VSH_OT_ARGV option with the name be last in the - * list of supported options in CMD-def-opts. - */ -static char * -vshCommandOptArgv(const vshCmd *cmd, int count) -{ -vshCmdOpt *opt = cmd-opts; - -while (opt) { -if (opt-def opt-def-type == VSH_OT_ARGV) { -if (count-- == 0) -return opt-data; -} -opt = opt-next; -} -return NULL; -} - /* Determine whether CMD-opts includes an option with name OPTNAME. If not, give a diagnostic and return false. If so, return true. */ I'm not entirely sure I understand what the effect of this patch is. Can you explain what the change in semantics for the parser is with this patch applied Regards, Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 04/13] remote_generator: support general dynamic array
On Wed, May 25, 2011 at 05:37:46PM +0800, Lai Jiangshan wrote: It will allow us use dynamic_array_basic_type member_nameMAX for remote protocol and avoid so many manual coding. For avoiding ambiguity, dynamic_array_basic_type must have a _DABT suffix. Signed-off-by: Lai Jiangshan la...@fujitsu.com A good idea to make the generator support more, but rather than requiring a magic name for the data type, add an annotation to the data type eg, kind of like Matthias has done to annotate 'hyper' http://www.redhat.com/archives/libvir-list/2011-May/msg01434.html Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 05/13] send-key: Defining the public API
On Wed, May 25, 2011 at 05:37:47PM +0800, Lai Jiangshan wrote: Add public virDomainSendKey() and enum libvirt_keycode_set for the @codeset. Python version of virDomainSendKey() has not been implemented yet, it will be done soon. Signed-off-by: Lai Jiangshan la...@fujitsu.com --- include/libvirt/libvirt.h.in |7 +++ include/libvirt/virtkeys.h | 23 +++ python/generator.py |1 + src/libvirt_public.syms |1 + 4 files changed, 32 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 7cd6e13..9167dbc 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -2617,6 +2617,13 @@ int virDomainOpenConsole(virDomainPtr dom, int virDomainInjectNMI(virDomainPtr domain, unsigned int flags); +int virDomainSendKey(virDomainPtr domain, + unsigned int codeset, + unsigned int holdtime, + unsigned int nkeycodes, + unsigned int *keycodes, + unsigned int flags); + This looks fine. As mentioned earlier we might like to *also* have a variant which takes strings, to make life easier for virsh, or similar use cases +int virDomainSendKeyStr(virDomainPtr domain, + unsigned int codeset, + unsigned int holdtime, + unsigned int nkeycodes, + unsigned char **keycodestrs, + unsigned int flags); + #ifdef __cplusplus } #endif diff --git a/include/libvirt/virtkeys.h b/include/libvirt/virtkeys.h new file mode 100644 index 000..eb07129 --- /dev/null +++ b/include/libvirt/virtkeys.h @@ -0,0 +1,23 @@ +#ifndef _LIBVIRT_VIRTKEYS_H +#define _LIBVIRT_VIRTKEYS_H + +/* + * Copyright (c) 2011 Lai Jiangshan + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +enum libvirt_keycode_set { +LIBVIRT_KEYCODE_LINUX = 0, +LIBVIRT_KEYCODE_DRIVER_DEFAULT = 1, +LIBVIRT_KEYCODE_XT = 2, +LIBVIRT_KEYCODE_ATSET1 = LIBVIRT_KEYCODE_XT, +LIBVIRT_KEYCODE_ATSET2 = 3, +LIBVIRT_KEYCODE_ATSET3 = 4, +}; If we're going to have constants for XT and ATSET1 then we probably want to have them separate values. If not then we should just kill one of them. As mentioned in the initial message, I think 'driver default' isn't useful, so I'd go with: +enum libvirt_keycode_set { +LIBVIRT_KEYCODE_LINUX = 0, +LIBVIRT_KEYCODE_XT = 1, +LIBVIRT_KEYCODE_ATSET1 = 2 +LIBVIRT_KEYCODE_ATSET2 = 3, +LIBVIRT_KEYCODE_ATSET3 = 4, +}; + +#define MAX_SEND_KEY 16 + +#endif diff --git a/python/generator.py b/python/generator.py index 1741bba..3d57bf9 100755 --- a/python/generator.py +++ b/python/generator.py @@ -355,6 +355,7 @@ skip_impl = ( 'virNodeDeviceListCaps', 'virConnectBaselineCPU', 'virDomainRevertToSnapshot', +'virDomainSendKey', ) diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 0590535..9e8a37c 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -442,6 +442,7 @@ LIBVIRT_0.9.2 { virDomainInjectNMI; virDomainScreenshot; virDomainSetSchedulerParametersFlags; +virDomainSendKey; } LIBVIRT_0.9.0; # define new API here using predicted next version number Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2] time_t is not a long on FreeBSD, switch internal type to long long
2011/5/25 Eric Blake ebl...@redhat.com: On 05/25/2011 09:05 AM, Matthias Bolte wrote: --- v2: switch internal type to long long instead of adding casts for time_t src/conf/domain_conf.c | 8 src/conf/domain_conf.h | 2 +- src/esx/esx_vi_types.c | 2 +- src/esx/esx_vi_types.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) ACK. I missed to fix the test case to the esxVI_DateTime_ConvertToCalendarTime function, so fold this in before pushing. diff --git a/tests/esxutilstest.c b/tests/esxutilstest.c index 2b36535..51c1e34 100644 --- a/tests/esxutilstest.c +++ b/tests/esxutilstest.c @@ -169,7 +169,7 @@ testParseDatastorePath(const void *data ATTRIBUTE_UNUSED) struct testDateTime { const char *dateTime; -time_t calendarTime; +long long calendarTime; }; static struct testDateTime times[] = { @@ -205,7 +205,7 @@ testConvertDateTimeToCalendarTime(const void *data ATTRIBUTE_UNUSED) { int i; esxVI_DateTime dateTime; -time_t calendarTime; +long long calendarTime; for (i = 0; i ARRAY_CARDINALITY(times); ++i) { dateTime.value = (char *)times[i].dateTime; Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2] virsh: time_t is not a long on FreeBSD
2011/5/25 Eric Blake ebl...@redhat.com: On 05/25/2011 09:06 AM, Matthias Bolte wrote: localtime_r expects time_t. --- v2: add overflow check ACK. - localtime_r(creation, time_info); + creation_time_t = creation_longlong; + if (creation_time_t != creation_longlong) { + vshError(ctl, %s, _(time_t overflow)); We shouldn't hit this error until 2038, and by then, hopefully more 32-bit platforms (if any are still running) will have switched to 64-bit time_t. :) But I agree with keeping this error in the code, since silent wraparound is always worse than explicit mention of overflow. I like to be on the safe side :) Thanks, pushed. Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] json: Avoid passing large positive 64 bit integers to QMP.
We don't seem to be reaching any sort of sensible conclusion with qemu about this bug, so it seems easier (albeit uglier) to fix it on the libvirt side. I have verified that with this patch virDomainMemoryPeek works on 64 bit guests. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/ From 9def1fb4a1b59b086493cf5eb78228515933e0b7 Mon Sep 17 00:00:00 2001 From: Richard W.M. Jones rjo...@redhat.com Date: Wed, 25 May 2011 17:52:26 +0100 Subject: [PATCH] json: Avoid passing large positive 64 bit integers to QMP. http://lists.gnu.org/archive/html/qemu-devel/2011-05/threads.html#02162 Currently, qemu silently clips any JSON integer in the range 0x8000 - 0x (all numbers in this range will be clipped to 0x7fff == LLONG_MAX). To avoid this, pass these as signed 64 bit integers in the QMP request. --- src/qemu/qemu_monitor_json.c |9 +++-- 1 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 2d8a390..bdd0dcb 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -413,8 +413,13 @@ qemuMonitorJSONMakeCommand(const char *cmdname, ret = virJSONValueObjectAppendNumberLong(jargs, key, val); } break; case 'U': { -unsigned long long val = va_arg(args, unsigned long long); -ret = virJSONValueObjectAppendNumberUlong(jargs, key, val); +/* qemu silently truncates numbers larger than LLONG_MAX, + * so passing the full range of unsigned 64 bit integers + * is not safe here. Pass them as signed 64 bit integers + * instead. + */ +long long val = va_arg(args, long long); +ret = virJSONValueObjectAppendNumberLong(jargs, key, val); } break; case 'd': { double val = va_arg(args, double); -- 1.7.5.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] json: Avoid passing large positive 64 bit integers to QMP.
On 05/25/2011 10:55 AM, Richard W.M. Jones wrote: We don't seem to be reaching any sort of sensible conclusion with qemu about this bug, so it seems easier (albeit uglier) to fix it on the libvirt side. I have verified that with this patch virDomainMemoryPeek works on 64 bit guests. ACK. -- Eric Blake ebl...@redhat.com+1-801-349-2682 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 0/7] More remote generator work
2011/5/23 Matthias Bolte matthias.bo...@googlemail.com: This series removes special case code from the generator and moves it to annotations in the .x files. There are also cleanups of sign mismatches between the different API layers and additional moves of functions to generated code. This series superseds patch 4/5 of the last series [1] and implements Eric's suggestions. [1] https://www.redhat.com/archives/libvir-list/2011-May/msg00991.html configure.ac | 1 + daemon/remote.c | 289 ++--- daemon/remote_generator.pl | 473 src/driver.h | 2 +- src/nwfilter/nwfilter_driver.c | 2 +- src/remote/remote_driver.c | 268 ++ src/remote/remote_protocol.x | 247 +++-- src/remote_protocol-structs | 40 ++-- 8 files changed, 532 insertions(+), 790 deletions(-) Matthias I pushed the ACKed patch 1-6 now. Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 05/13] send-key: Defining the public API
2011/5/25 Lai Jiangshan la...@cn.fujitsu.com: Add public virDomainSendKey() and enum libvirt_keycode_set for the @codeset. Python version of virDomainSendKey() has not been implemented yet, it will be done soon. Signed-off-by: Lai Jiangshan la...@fujitsu.com --- include/libvirt/libvirt.h.in | 7 +++ include/libvirt/virtkeys.h | 23 +++ python/generator.py | 1 + src/libvirt_public.syms | 1 + 4 files changed, 32 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 7cd6e13..9167dbc 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -2617,6 +2617,13 @@ int virDomainOpenConsole(virDomainPtr dom, int virDomainInjectNMI(virDomainPtr domain, unsigned int flags); +int virDomainSendKey(virDomainPtr domain, + unsigned int codeset, + unsigned int holdtime, + unsigned int nkeycodes, + unsigned int *keycodes, + unsigned int flags); + This should have nkeycodes and keycodes renamed and reordered to match the common pattern: keycodes, keycodeslen Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 08/13] send-key: Implementing the remote protocol
2011/5/25 Lai Jiangshan la...@cn.fujitsu.com: Signed-off-by: Lai Jiangshan la...@fujitsu.com --- src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 19 ++- src/remote_protocol-structs | 11 +++ 3 files changed, 30 insertions(+), 1 deletions(-) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 1691dab..6614250 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -6868,6 +6868,7 @@ static virDriver remote_driver = { .domainMigrateFinish3 = remoteDomainMigrateFinish3, /* 0.9.2 */ .domainMigrateConfirm3 = remoteDomainMigrateConfirm3, /* 0.9.2 */ .domainSetSchedulerParametersFlags = remoteDomainSetSchedulerParametersFlags, /* 0.9.2 */ + .domainSendKey = remoteDomainSendKey, /* 0.9.2 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index f0da95d..61504c4 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -191,6 +191,14 @@ const REMOTE_SECRET_UUID_LIST_MAX = 16384; */ const REMOTE_CPU_BASELINE_MAX = 256; +/* + * Max number of sending keycodes. + */ +const REMOTE_SEND_KEY_MAX = 16; + Why such a low limit? +/* define dynamic array's base type for unsigned int */ +typedef unsigned int u_int_DABT; + No need for this typedef /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */ typedef opaque remote_uuid[VIR_UUID_BUFLEN]; @@ -838,6 +846,14 @@ struct remote_domain_inject_nmi_args { unsigned int flags; }; +struct remote_domain_send_key_args { + remote_nonnull_domain dom; + unsigned int codeset; + unsigned int holdtime; + u_int_DABT keycodesREMOTE_SEND_KEY_MAX; + unsigned int flags; +}; + As said in 4/13 there is no need for such an annotation. Here's a v2 that works in combination with my v2 for 4/13. Matthias From a9f64a5e3fbff8e78cb70acab32ae5af40b8b50f Mon Sep 17 00:00:00 2001 From: Lai Jiangshan la...@cn.fujitsu.com Date: Wed, 25 May 2011 17:37:50 +0800 Subject: [PATCH] send-key: Implementing the remote protocol Signed-off-by: Lai Jiangshan la...@fujitsu.com --- src/remote/remote_driver.c |1 + src/remote/remote_protocol.x | 16 +++- src/remote_protocol-structs | 11 +++ 3 files changed, 27 insertions(+), 1 deletions(-) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index c9af14a..4a47ef6 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -6637,6 +6637,7 @@ static virDriver remote_driver = { .domainMigrateFinish3 = remoteDomainMigrateFinish3, /* 0.9.2 */ .domainMigrateConfirm3 = remoteDomainMigrateConfirm3, /* 0.9.2 */ .domainSetSchedulerParametersFlags = remoteDomainSetSchedulerParametersFlags, /* 0.9.2 */ +.domainSendKey = remoteDomainSendKey, /* 0.9.2 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index f0b9cd5..9afa909 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -191,6 +191,11 @@ const REMOTE_SECRET_UUID_LIST_MAX = 16384; */ const REMOTE_CPU_BASELINE_MAX = 256; +/* + * Max number of sending keycodes. + */ +const REMOTE_SEND_KEY_MAX = 16; + /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */ typedef opaque remote_uuid[VIR_UUID_BUFLEN]; @@ -845,6 +850,14 @@ struct remote_domain_inject_nmi_args { unsigned int flags; }; +struct remote_domain_send_key_args { +remote_nonnull_domain dom; +unsigned int codeset; +unsigned int holdtime; +unsigned int keycodesREMOTE_SEND_KEY_MAX; +unsigned int flags; +}; + struct remote_domain_set_vcpus_args { remote_nonnull_domain dom; unsigned int nvcpus; @@ -2309,7 +2322,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_PERFORM3 = 216, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_MIGRATE_FINISH3 = 217, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3 = 218, /* skipgen skipgen */ -REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS_FLAGS = 219 /* skipgen skipgen */ +REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS_FLAGS = 219, /* skipgen skipgen */ +REMOTE_PROC_DOMAIN_SEND_KEY = 220 /* autogen autogen */ /* Notice how the entries are grouped in sets of 10 ? * Nice isn't it. Please keep it this way when adding more. diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index c0152cb..477b569 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1557,3 +1557,14 @@ struct remote_message_header { u_int serial; remote_message_status status; }; + +struct remote_domain_send_key_args { +remote_nonnull_domain dom; +unsigned int codeset; +unsigned int holdtime; +struct { +unsigned int keycodes_len; +unsigned int * keycodes_val; +} keycodes; +unsigned int flags; +}; --
Re: [libvirt] [PATCH 04/13] remote_generator: support general dynamic array
2011/5/25 Daniel P. Berrange berra...@redhat.com: On Wed, May 25, 2011 at 05:37:46PM +0800, Lai Jiangshan wrote: It will allow us use dynamic_array_basic_type member_nameMAX for remote protocol and avoid so many manual coding. For avoiding ambiguity, dynamic_array_basic_type must have a _DABT suffix. Signed-off-by: Lai Jiangshan la...@fujitsu.com A good idea to make the generator support more, but rather than requiring a magic name for the data type, add an annotation to the data type eg, kind of like Matthias has done to annotate 'hyper' http://www.redhat.com/archives/libvir-list/2011-May/msg01434.html Actually there is not need for this _DABT suffix nor for any other annotation. unsigned int keycodesREMOTE_SEND_KEY_MAX is just a common pattern and the generator already deals with such arrays. I propose the attached patch as a v2 of this patch. It doesn't try to cover the generic array case at that isn't useful, it just deals with [unsigned] int arrays. This patch assumes that keycodes and keycodeslen are reordered to the common pattern. Matthias From b48bfdf41e8b164877869e8590b60e8549bb53fd Mon Sep 17 00:00:00 2001 From: Matthias Bolte matthias.bo...@googlemail.com Date: Wed, 25 May 2011 17:37:46 +0800 Subject: [PATCH] remote generator: Handle (unsigned) int arrays --- daemon/remote_generator.pl | 20 1 files changed, 20 insertions(+), 0 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index f34f420..cd51c9a 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -411,6 +411,13 @@ elsif ($opt_b) { } push(@args_list, args-$2.$2_len); +} elsif ($args_member =~ m/^(?:unsigned )?int (\S+)\S+;/) { +if (! @args_list) { +push(@args_list, conn); +} + +push(@args_list, args-$1.$1_val); +push(@args_list, args-$1.$1_len); } elsif ($args_member =~ m/\S+;/ or $args_member =~ m/\[\S+\];/) { # just make all other array types fail die unhandled type for argument value: $args_member; @@ -1000,6 +1007,19 @@ elsif ($opt_k) { push(@setters_list, args.$arg_name.${arg_name}_val = (char *)$arg_name;); push(@setters_list, args.$arg_name.${arg_name}_len = ${arg_name}len;); push(@args_check_list, { name = \$arg_name\, arg = ${arg_name}len, limit = $limit }); +} elsif ($args_member =~ m/^(unsigned )?int (\S+)(\S+);/) { +my $type_name; +my $arg_name = $2; +my $limit = $3; + +$type_name = $1 if ($1); +$type_name .= int; + +push(@args_list, ${type_name} *$arg_name); +push(@args_list, unsigned int ${arg_name}len); +push(@setters_list, args.$arg_name.${arg_name}_val = $arg_name;); +push(@setters_list, args.$arg_name.${arg_name}_len = ${arg_name}len;); +push(@args_check_list, { name = \$arg_name\, arg = ${arg_name}len, limit = $limit }); } elsif ($args_member =~ m/^(unsigned )?int (\S+);/) { my $type_name; my $arg_name = $2; -- 1.7.0.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 07/13] send-key: Implementing the public API
On Wed, May 25, 2011 at 05:37:49PM +0800, Lai Jiangshan wrote: Signed-off-by: Lai Jiangshan la...@fujitsu.com --- src/libvirt.c | 54 ++ 1 files changed, 54 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index ff16c48..8246975 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -6080,6 +6080,60 @@ error: } /** + * virDomainSendKey: + * @domain:pointer to domain object, or NULL for Domain0 + * @codeset: the code set of keycodes + * @holdtime: the time (in millsecond) how long the keys will be held + * @nkeycodes: number of keycodes + * @keycodes: array of keycodes + * @flags: the flags for controlling behavior, pass 0 for now + * + * Send key to the guest + * + * Returns 0 in case of success, -1 in case of failure. + */ + +int virDomainSendKey(virDomainPtr domain, + unsigned int codeset, + unsigned int holdtime, + unsigned int nkeycodes, + unsigned int *keycodes, + unsigned int flags) +{ +virConnectPtr conn; +VIR_DOMAIN_DEBUG(domain, flags=%u, flags); Should include the other parameters in this debug message too + +virResetLastError(); + +if (!VIR_IS_CONNECTED_DOMAIN(domain)) { +virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); +virDispatchError(NULL); +return -1; +} +if (domain-conn-flags VIR_CONNECT_RO) { +virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); +goto error; +} + +conn = domain-conn; + +if (conn-driver-domainSendKey) { +int ret; +ret = conn-driver-domainSendKey(domain, codeset, holdtime, + nkeycodes, keycodes, flags); +if (ret 0) +goto error; +return ret; +} + +virLibConnError (VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: +virDispatchError(domain-conn); +return -1; +} + +/** * virDomainSetVcpus: * @domain: pointer to domain object, or NULL for Domain0 * @nvcpus: the new number of virtual CPUs for this domain ACK, pending the changes suggest to the public API signature Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 06/13] send-key: Defining the internal API
On Wed, May 25, 2011 at 05:37:48PM +0800, Lai Jiangshan wrote: Signed-off-by: Lai Jiangshan la...@fujitsu.com --- src/driver.h |8 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index 450dd53..70a30d9 100644 --- a/src/driver.h +++ b/src/driver.h @@ -535,6 +535,13 @@ typedef int typedef int (*virDrvDomainInjectNMI)(virDomainPtr dom, unsigned int flags); +typedef int +(*virDrvDomainSendKey)(virDomainPtr dom, unsigned int codeset, + unsigned int holdtime, + unsigned int nkeycodes, + unsigned int *keycodes, + unsigned int flags); + typedef char * (*virDrvDomainMigrateBegin3) (virDomainPtr domain, @@ -738,6 +745,7 @@ struct _virDriver { virDrvDomainMigratePerform3 domainMigratePerform3; virDrvDomainMigrateFinish3 domainMigrateFinish3; virDrvDomainMigrateConfirm3 domainMigrateConfirm3; +virDrvDomainSendKey domainSendKey; }; ACK looks fine wrt to whatever the public API ends up being Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 09/13] send-key: Expose the new API in virsh
On Wed, May 25, 2011 at 05:37:51PM +0800, Lai Jiangshan wrote: Signed-off-by: Lai Jiangshan la...@fujitsu.com --- tools/virsh.c | 103 +++ tools/virsh.pod |4 ++ 2 files changed, 107 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 80cffac..505a821 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -33,6 +33,8 @@ #include signal.h #include poll.h +#include libvirt/virtkeys.h + #include libxml/parser.h #include libxml/tree.h #include libxml/xpath.h @@ -3010,6 +3012,106 @@ cmdInjectNMI(vshControl *ctl, const vshCmd *cmd) } /* + * send-key command + */ +static const vshCmdInfo info_send_key[] = { +{help, N_(Send keycodes to the guest)}, +{desc, N_(Send keycodes to the guest, the keycodes must be integers\n +Examples:\n\n +virsh # send-key domain 37 18 21\n +virsh # send-key domain --holdtime 1000 0x15 18 0xf\n +{NULL, NULL} +}; As mentioned in my earlier message, it is probably desirable for this to use key strings by default, since that is more friendly for the admin. Either have an explicit flag to enable use of key values, or perhaps can auto-detect them. +static const vshCmdOptDef opts_send_key[] = { +{domain, VSH_OT_DATA, VSH_OFLAG_REQ, N_(domain name, id or uuid)}, +{codeset, VSH_OT_STRING, VSH_OFLAG_REQ_OPT, N_(the codeset of keycodes, default:linux)}, +{holdtime, VSH_OT_INT, VSH_OFLAG_REQ_OPT, + N_(the time (in millsecond) how long the keys will be held)}, +{keycode, VSH_OT_ARGV, VSH_OFLAG_REQ, N_(the key code)}, +{NULL, 0, 0, NULL} +}; + +static int get_integer_keycode(const char *key_name) +{ +long val; +char *endptr; + +val = strtol(key_name, endptr, 0); +if (*endptr != '\0' || val 255 || val = 0) + return -1; + +return val; +} + +static bool +cmdSendKey(vshControl *ctl, const vshCmd *cmd) +{ +virDomainPtr dom; +int ret = false; +const char *codeset_option; +int codeset; +int holdtime; +int count = 0; +const vshCmdOpt *opt; +int keycode; +unsigned int keycodes[MAX_SEND_KEY]; + +if (!vshConnectionUsability(ctl, ctl-conn)) +return false; + +if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) +return false; + +if (vshCommandOptString(cmd, codeset, codeset_option) = 0) +codeset_option = default; + +if (vshCommandOptInt(cmd, holdtime, holdtime) = 0) +holdtime = 0; + +if (STREQ(codeset_option, default) || STREQ(codeset_option, linux)) { +codeset = LIBVIRT_KEYCODE_LINUX; +} else if (STREQ(codeset_option, diriver_default)) { +codeset = LIBVIRT_KEYCODE_DRIVER_DEFAULT; As mentioned, I don't think we want 'driver_default' as a use case. +} else if (STREQ(codeset_option, xt)) { +codeset = LIBVIRT_KEYCODE_XT; +} else if (STREQ(codeset_option, atset1)) { +codeset = LIBVIRT_KEYCODE_ATSET1; +} else if (STREQ(codeset_option, atset2)) { +codeset = LIBVIRT_KEYCODE_ATSET2; +} else if (STREQ(codeset_option, atset3)) { +codeset = LIBVIRT_KEYCODE_ATSET3; +} else { +vshError(ctl, _(unknown codeset: '%s'), codeset_option); +goto free_domain; +} + +for_each_variable_arg(cmd, opt) { +if (count == MAX_SEND_KEY) { +vshError(ctl, _(too many keycode)); +goto free_domain; +} + +if ((keycode = get_integer_keycode(opt-data)) 0) +goto get_keycode; + +vshError(ctl, _(invalid keycode: '%s'), opt-data); +goto free_domain; + +get_keycode: +keycodes[count] = keycode; +count++; +} + +if (!(virDomainSendKey(dom, codeset, holdtime, count, keycodes, 0) 0)) +ret = true; + +free_domain: +virDomainFree(dom); +return ret; +} + +/* * setmemory command */ static const vshCmdInfo info_setmem[] = { @@ -10807,6 +10909,7 @@ static const vshCmdDef domManagementCmds[] = { {dumpxml, cmdDumpXML, opts_dumpxml, info_dumpxml, 0}, {edit, cmdEdit, opts_edit, info_edit, 0}, {inject-nmi, cmdInjectNMI, opts_inject_nmi, info_inject_nmi, 0}, +{send-key, cmdSendKey, opts_send_key, info_send_key}, {managedsave, cmdManagedSave, opts_managedsave, info_managedsave, 0}, {managedsave-remove, cmdManagedSaveRemove, opts_managedsaveremove, info_managedsaveremove, 0}, diff --git a/tools/virsh.pod b/tools/virsh.pod index ef01f41..beef608 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -294,6 +294,10 @@ scheduling by the hypervisor. Inject NMI to the guest +=item Bsend-key Idomain-id I--codeset Bcodeset I--holdtime Bholdtime Bkeycode... + +Send keys to the guest + =item Bshutdown The domain is in the process of shutting
Re: [libvirt] [PATCHv2 3/7] interface: implement public APIs for libvirt transactional network changes
On 05/24/2011 04:44 AM, Daniel P. Berrange wrote: On Tue, May 24, 2011 at 02:13:12PM +0800, Daniel Veillard wrote: On Thu, May 19, 2011 at 04:51:25PM -0400, Laine Stump wrote: From: Michal Privoznikmpriv...@redhat.com --- src/libvirt.c | 141 - 1 files changed, 139 insertions(+), 2 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index ff16c48..786ce15 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -8143,7 +8143,9 @@ error: * @xml: the XML description for the interface, preferably in UTF-8 * @flags: and OR'ed set of extraction flags, not used yet * - * Define an interface (or modify existing interface configuration) + * Define an interface (or modify existing interface configuration). + * This can, however be affected by virInterfaceChangeBegin + * and/or friends. Small nit, I would suggest making the 4 extra comments a bit more explicit that it's about transaction support, something along the lines of: * This can however be affected by the transaction support for * interface configuration change, see virInterfaceChangeBegin(), * virInterfaceChangeCommit() and related functions. I made the comments more verbose (possibly *too* verbose) in the upcoming V3 of this patch. If the explanation is too much, you can let me know and I'll dial it back before pushing. [...] @@ -8374,6 +8382,135 @@ virInterfaceFree(virInterfacePtr iface) return 0; } +/** + * virInterfaceChangeBegin: + * @conn: pointer to hypervisor connection + * @flags: flags, not used yet + * + * This functions creates a restore point to which one can return + * later by calling virInterfaceChangeRollback. This function should + * be called before any transaction with interface configuration. + * Once knowing, new configuration works, it can be commited via + * virInterfaceChangeCommit, which frees restore point. which frees the restore point. I would like the description of what happens ona sequence of virInterfaceChangeBegin() virInterfaceChangeBegin() calls for the same connection, is that an error ? Will netcf implement this, this behaviour should probably be documented. It should return the VIR_ERR_INVALID_OPERATION code with a message that a transaction is already active. Yes, netcf checks for this and returns an error (likewise if commit or rollback is called when there is no open transaction). I will make sure this is translated to VIR_ERR_INVALID_OPERATION so that it is logged properly. (it's good that you pointed this out now, because netcf had been just returning a generic error for this, so I modified the netcf patches to return a new unique code, and have updated patch 6/7 (the netcf driver additions) to recognize this new code when it's available). +/** + * virInterfaceChangeCommit: + * @conn: pointer to hypervisor connection + * @flags: flags, not used yet + * + * This commits the changes made to interfaces and frees restore point frees the restore point + * created by virInterfaceChangeBegin. Same thing behaviour of virInterfaceChangeCommit() in case there was no Begin() associated should be documented. Likewise VIR_ERR_INVALID_OPERATION Yup. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 10/13] qemu:send-key: Implement the driver methods
On Wed, May 25, 2011 at 05:37:52PM +0800, Lai Jiangshan wrote: Signed-off-by: Lai Jiangshan la...@fujitsu.com --- src/qemu/qemu_driver.c | 50 ++ src/qemu/qemu_monitor.c | 28 +++ src/qemu/qemu_monitor.h |6 + src/qemu/qemu_monitor_json.c | 15 src/qemu/qemu_monitor_json.h |5 src/qemu/qemu_monitor_text.c | 48 src/qemu/qemu_monitor_text.h |5 7 files changed, 157 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 691965d..f7e21bf 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1753,6 +1753,55 @@ cleanup: return ret; } +static int qemuDomainSendKey(virDomainPtr domain, + unsigned int codeset, + unsigned int holdtime, + unsigned int nkeycodes, + unsigned int *keycodes, + unsigned int flags) +{ +struct qemud_driver *driver = domain-conn-privateData; +virDomainObjPtr vm = NULL; +int ret = -1; +qemuDomainObjPrivatePtr priv; + +virCheckFlags(0, -1); + +qemuDriverLock(driver); +vm = virDomainFindByUUID(driver-domains, domain-uuid); +if (!vm) { +char uuidstr[VIR_UUID_STRING_BUFLEN]; +virUUIDFormat(domain-uuid, uuidstr); +qemuReportError(VIR_ERR_NO_DOMAIN, +_(no domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +if (!virDomainObjIsActive(vm)) { +qemuReportError(VIR_ERR_OPERATION_INVALID, +%s, _(domain is not running)); +goto cleanup; +} + +priv = vm-privateData; + +if (qemuDomainObjBeginJobWithDriver(driver, vm) 0) +goto cleanup; +qemuDomainObjEnterMonitorWithDriver(driver, vm); +ret = qemuMonitorSendKey(priv-mon, codeset, holdtime, nkeycodes, keycodes); +qemuDomainObjExitMonitorWithDriver(driver, vm); +if (qemuDomainObjEndJob(vm) == 0) { +vm = NULL; +goto cleanup; +} + +cleanup: +if (vm) +virDomainObjUnlock(vm); +qemuDriverUnlock(driver); +return ret; +} + static int qemudDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { @@ -7746,6 +7795,7 @@ static virDriver qemuDriver = { .domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */ .domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */ .domainSetSchedulerParametersFlags = qemuSetSchedulerParametersFlags, /* 0.9.2 */ +.domainSendKey = qemuDomainSendKey, /* 0.9.2 */ }; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 5186f99..c0688fd 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -38,6 +38,8 @@ #include logging.h #include files.h +#include libvirt/virtkeys.h + #define VIR_FROM_THIS VIR_FROM_QEMU #define DEBUG_IO 0 @@ -2294,6 +2296,32 @@ int qemuMonitorInjectNMI(qemuMonitorPtr mon) return ret; } +int qemuMonitorSendKey(qemuMonitorPtr mon, + unsigned int codeset, + unsigned int holdtime, + unsigned int nkeycodes, + unsigned int *keycodes) +{ +int ret; + +VIR_DEBUG(mon=%p, codeset=%u, holdtime=%u, nkeycodes=%u, + mon, codeset, holdtime, nkeycodes); + +if (!(codeset == LIBVIRT_KEYCODE_DRIVER_DEFAULT +|| codeset == LIBVIRT_KEYCODE_XT)) { +qemuReportError(VIR_ERR_NO_SUPPORT, +qemu monitor can not support the codeset: %d, +codeset); +return -1; +} + +if (mon-json) +ret = qemuMonitorJSONSendKey(mon, holdtime, nkeycodes, keycodes); +else +ret = qemuMonitorTextSendKey(mon, holdtime, nkeycodes, keycodes); +return ret; +} + int qemuMonitorScreendump(qemuMonitorPtr mon, const char *file) { diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 05c3359..76a849a 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -435,6 +435,12 @@ int qemuMonitorInjectNMI(qemuMonitorPtr mon); int qemuMonitorScreendump(qemuMonitorPtr mon, const char *file); +int qemuMonitorSendKey(qemuMonitorPtr mon, + unsigned int codeset, + unsigned int holdtime, + unsigned int nkeycodes, + unsigned int *keycodes); + /** * When running two dd process and using redirection, we need a * shell that will not truncate files. These two strings serve that diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index
Re: [libvirt] [PATCH 11/13] send-key: support KEY_XXX names for the linux keycode
On Wed, May 25, 2011 at 05:37:53PM +0800, Lai Jiangshan wrote: It make send-key command more friendly for user. Signed-off-by: Lai Jiangshan la...@fujitsu.com --- include/libvirt/virtkeys.h | 253 tools/virsh.c | 21 2 files changed, 274 insertions(+), 0 deletions(-) diff --git a/include/libvirt/virtkeys.h b/include/libvirt/virtkeys.h index eb07129..7893450 100644 --- a/include/libvirt/virtkeys.h +++ b/include/libvirt/virtkeys.h @@ -20,4 +20,257 @@ enum libvirt_keycode_set { #define MAX_SEND_KEY 16 +#define ITEM_KEYCODE(KEY_XXX) VIRT##KEY_XXX +#define KEYCODES() \ +keycode(KEY_ESC, 1)\ +keycode(KEY_1, 2)\ +keycode(KEY_2, 3)\ +keycode(KEY_3, 4)\ +keycode(KEY_4, 5)\ +keycode(KEY_5, 6)\ +keycode(KEY_6, 7)\ +keycode(KEY_7, 8)\ +keycode(KEY_8, 9)\ +keycode(KEY_9, 10)\ +keycode(KEY_0, 11)\ +keycode(KEY_MINUS, 12)\ +keycode(KEY_EQUAL, 13)\ +keycode(KEY_BACKSPACE, 14)\ +keycode(KEY_TAB, 15)\ +keycode(KEY_Q, 16)\ +keycode(KEY_W, 17)\ +keycode(KEY_E, 18)\ +keycode(KEY_R, 19)\ +keycode(KEY_T, 20)\ +keycode(KEY_Y, 21)\ +keycode(KEY_U, 22)\ +keycode(KEY_I, 23)\ +keycode(KEY_O, 24)\ +keycode(KEY_P, 25)\ +keycode(KEY_LEFTBRACE, 26)\ +keycode(KEY_RIGHTBRACE, 27)\ +keycode(KEY_ENTER, 28)\ +keycode(KEY_LEFTCTRL,29)\ +keycode(KEY_A, 30)\ +keycode(KEY_S, 31)\ +keycode(KEY_D, 32)\ +keycode(KEY_F, 33)\ +keycode(KEY_G, 34)\ +keycode(KEY_H, 35)\ +keycode(KEY_J, 36)\ +keycode(KEY_K, 37)\ +keycode(KEY_L, 38)\ +keycode(KEY_SEMICOLON, 39)\ +keycode(KEY_APOSTROPHE, 40)\ +keycode(KEY_GRAVE, 41)\ +keycode(KEY_LEFTSHIFT, 42)\ +keycode(KEY_BACKSLASH, 43)\ +keycode(KEY_Z, 44)\ +keycode(KEY_X, 45)\ +keycode(KEY_C, 46)\ +keycode(KEY_V, 47)\ +keycode(KEY_B, 48)\ +keycode(KEY_N, 49)\ +keycode(KEY_M, 50)\ +keycode(KEY_COMMA, 51)\ +keycode(KEY_DOT, 52)\ +keycode(KEY_SLASH, 53)\ +keycode(KEY_RIGHTSHIFT, 54)\ +keycode(KEY_KPASTERISK, 55)\ +keycode(KEY_LEFTALT, 56)\ +keycode(KEY_SPACE, 57)\ +keycode(KEY_CAPSLOCK,58)\ +keycode(KEY_F1, 59)\ +keycode(KEY_F2, 60)\ +keycode(KEY_F3, 61)\ +keycode(KEY_F4, 62)\ +keycode(KEY_F5, 63)\ +keycode(KEY_F6, 64)\ +keycode(KEY_F7, 65)\ +keycode(KEY_F8, 66)\ +keycode(KEY_F9, 67)\ +keycode(KEY_F10, 68)\ +keycode(KEY_NUMLOCK, 69)\ +keycode(KEY_SCROLLLOCK, 70)\ +keycode(KEY_KP7, 71)\ +keycode(KEY_KP8, 72)\ +keycode(KEY_KP9, 73)\ +keycode(KEY_KPMINUS, 74)\ +keycode(KEY_KP4, 75)\ +keycode(KEY_KP5, 76)\ +keycode(KEY_KP6, 77)\ +keycode(KEY_KPPLUS, 78)\ +keycode(KEY_KP1, 79)\ +keycode(KEY_KP2, 80)\ +keycode(KEY_KP3, 81)\ +keycode(KEY_KP0, 82)\ +keycode(KEY_KPDOT, 83)\ +keycode(KEY_ZENKAKUHANKAKU, 85)\ +keycode(KEY_102ND, 86)\ +keycode(KEY_F11, 87)\ +keycode(KEY_F12, 88)\ +keycode(KEY_RO, 89)\ +keycode(KEY_KATAKANA,90)\ +keycode(KEY_HIRAGANA,91)\ +keycode(KEY_HENKAN, 92)\ +keycode(KEY_KATAKANAHIRAGANA,93)\ +keycode(KEY_MUHENKAN,94)\ +keycode(KEY_KPJPCOMMA, 95)\ +keycode(KEY_KPENTER, 96)\ +keycode(KEY_RIGHTCTRL, 97)\ +keycode(KEY_KPSLASH, 98)\ +keycode(KEY_SYSRQ, 99)\ +
Re: [libvirt] [PATCH 07/13] send-key: Implementing the public API
2011/5/25 Lai Jiangshan la...@cn.fujitsu.com: Signed-off-by: Lai Jiangshan la...@fujitsu.com --- src/libvirt.c | 54 ++ 1 files changed, 54 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index ff16c48..8246975 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -6080,6 +6080,60 @@ error: } /** + * virDomainSendKey: + * @domain: pointer to domain object, or NULL for Domain0 + * @codeset: the code set of keycodes + * @holdtime: the time (in millsecond) how long the keys will be held + * @nkeycodes: number of keycodes + * @keycodes: array of keycodes + * @flags: the flags for controlling behavior, pass 0 for now + * + * Send key to the guest + * + * Returns 0 in case of success, -1 in case of failure. + */ + +int virDomainSendKey(virDomainPtr domain, + unsigned int codeset, + unsigned int holdtime, + unsigned int nkeycodes, + unsigned int *keycodes, + unsigned int flags) +{ + virConnectPtr conn; + VIR_DOMAIN_DEBUG(domain, flags=%u, flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + if (domain-conn-flags VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + Invalid argument checks are missing, For example keycodes should not be NULL and nkeycodes should probably be larger than 0. Also the comment about renaming an reordering of nkeycodes and keycodes applies here too. Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 12/13] qemu, send-key: map linux keycode to xt keycode
On Wed, May 25, 2011 at 05:37:54PM +0800, Lai Jiangshan wrote: It allows us use linux keycode for qemu driver. Signed-off-by: Lai Jiangshan la...@fujitsu.com --- src/qemu/qemu_monitor.c | 49 ++- 1 files changed, 48 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index c0688fd..f6cdff1 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2296,6 +2296,41 @@ int qemuMonitorInjectNMI(qemuMonitorPtr mon) return ret; } +unsigned int linux2xt_keycode[256] = { +/* 00: */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +/* 08: */ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, +/* 10: */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, +/* 18: */ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, +/* 20: */ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, +/* 28: */ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, +/* 30: */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, +/* 38: */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, +/* 40: */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, +/* 48: */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x00, 0x4f, +/* 50: */ 0x50, 0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x57, +/* 58: */ 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 60: */ 0x00, 0x9d, 0xb5, 0x54, 0xb8, 0x00, 0xc7, 0xc8, +/* 68: */ 0xc9, 0xcb, 0xcd, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, +/* 70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 80: */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, +/* 88: */ 0xf8, 0xf9, 0xfb, 0xdd, 0x00, 0x00, 0x00, 0x00, +/* 90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* d0: */ 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, +/* d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; See my comment in the previous patch. This table can be automatically generated by my keymap-gen.pl script during build, so we don't need to manually have this table of wierd magic numbers. Regards, Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 13/13] virsh, send-key: add --codeset xt:keystring support
On Wed, May 25, 2011 at 05:37:55PM +0800, Lai Jiangshan wrote: It make send-key command more friendly for user. Signed-off-by: Lai Jiangshan la...@fujitsu.com --- tools/virsh.c | 224 - 1 files changed, 221 insertions(+), 3 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 3bccc08..18ef4bb 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -3017,11 +3017,24 @@ cmdInjectNMI(vshControl *ctl, const vshCmd *cmd) static const vshCmdInfo info_send_key[] = { {help, N_(Send keycodes to the guest)}, {desc, N_(Send keycodes to the guest, the keycodes must be integers\n +or the qemu-style key strings for the \xt:keystring\ codeset\n or the KEY_* strings listed below for the \linux\ codeset.\n\n +Available codeset:\n +linux the keycodes specified in \n + /usr/include/linux/input.h(default)\n +defaultlinux codeset will be used\n +driver_default the hypervisor default codeset will be used\n +xt XT(set1) scancode of standard AT keyboards and PS/2 keyboards\n +atset1 set1 scancode of standard AT keyboards and PS/2 keyboards\n +atset2 set2 scancode of standard AT keyboards and PS/2 keyboards\n +atset3 set3 scancode of standard AT keyboards and PS/2 keyboards\n +xt:keystring XT scancode, but keycode... must be the qemu-style key strings\n +\n Examples:\n\n virsh # send-key domain 37 18 21\n virsh # send-key domain --holdtime 1000 0x15 18 0xf\n -virsh # send-eky domain KEY_LEFTCTRL KEY_LEFTALT KEY_F1\n +virsh # send-key domain KEY_LEFTCTRL KEY_LEFTALT KEY_F1\n +virsh # send-key domain --codeset xt:keystring alt-sysrq h\n \n KEY_XXX strings for the \linux\ codeset:\n #define keycode(var, value) #var = #value \n @@ -3062,6 +3075,178 @@ static int get_integer_keycode(const char *key_name) return val; } + +typedef struct { +int keycode; +const char *name; +} KeyDef; + +static const KeyDef key_defs[] = { +{ 0x2a, shift }, +{ 0x36, shift_r }, + +{ 0x38, alt }, +{ 0xb8, alt_r }, +{ 0x64, altgr }, +{ 0xe4, altgr_r }, +{ 0x1d, ctrl }, +{ 0x9d, ctrl_r }, + +{ 0xdd, menu }, + +{ 0x01, esc }, + +{ 0x02, 1 }, +{ 0x03, 2 }, +{ 0x04, 3 }, +{ 0x05, 4 }, +{ 0x06, 5 }, +{ 0x07, 6 }, +{ 0x08, 7 }, +{ 0x09, 8 }, +{ 0x0a, 9 }, +{ 0x0b, 0 }, +{ 0x0c, minus }, +{ 0x0d, equal }, +{ 0x0e, backspace }, + +{ 0x0f, tab }, +{ 0x10, q }, +{ 0x11, w }, +{ 0x12, e }, +{ 0x13, r }, +{ 0x14, t }, +{ 0x15, y }, +{ 0x16, u }, +{ 0x17, i }, +{ 0x18, o }, +{ 0x19, p }, +{ 0x1a, bracket_left }, +{ 0x1b, bracket_right }, +{ 0x1c, ret }, + +{ 0x1e, a }, +{ 0x1f, s }, +{ 0x20, d }, +{ 0x21, f }, +{ 0x22, g }, +{ 0x23, h }, +{ 0x24, j }, +{ 0x25, k }, +{ 0x26, l }, +{ 0x27, semicolon }, +{ 0x28, apostrophe }, +{ 0x29, grave_accent }, + +{ 0x2b, backslash }, +{ 0x2c, z }, +{ 0x2d, x }, +{ 0x2e, c }, +{ 0x2f, v }, +{ 0x30, b }, +{ 0x31, n }, +{ 0x32, m }, +{ 0x33, comma }, +{ 0x34, dot }, +{ 0x35, slash }, + +{ 0x37, asterisk }, + +{ 0x39, spc }, +{ 0x3a, caps_lock }, +{ 0x3b, f1 }, +{ 0x3c, f2 }, +{ 0x3d, f3 }, +{ 0x3e, f4 }, +{ 0x3f, f5 }, +{ 0x40, f6 }, +{ 0x41, f7 }, +{ 0x42, f8 }, +{ 0x43, f9 }, +{ 0x44, f10 }, +{ 0x45, num_lock }, +{ 0x46, scroll_lock }, + +{ 0xb5, kp_divide }, +{ 0x37, kp_multiply }, +{ 0x4a, kp_subtract }, +{ 0x4e, kp_add }, +{ 0x9c, kp_enter }, +{ 0x53, kp_decimal }, +{ 0x54, sysrq }, + +{ 0x52, kp_0 }, +{ 0x4f, kp_1 }, +{ 0x50, kp_2 }, +{ 0x51, kp_3 }, +{ 0x4b, kp_4 }, +{ 0x4c, kp_5 }, +{ 0x4d, kp_6 }, +{ 0x47, kp_7 }, +{ 0x48, kp_8 }, +{ 0x49, kp_9 }, + +{ 0x56, }, + +{ 0x57, f11 }, +{ 0x58, f12 }, + +{ 0xb7, print }, + +{ 0xc7, home }, +{ 0xc9, pgup }, +{ 0xd1, pgdn }, +{ 0xcf, end }, + +{ 0xcb, left }, +{ 0xc8, up }, +{ 0xd0, down }, +{ 0xcd, right }, + +{ 0xd2, insert }, +{ 0xd3, delete }, + +{ 0xf0, stop }, +{ 0xf1, again }, +{ 0xf2, props }, +{ 0xf3, undo }, +
Re: [libvirt] [PATCH] json: Avoid passing large positive 64 bit integers to QMP.
On Wed, May 25, 2011 at 11:06:10AM -0600, Eric Blake wrote: On 05/25/2011 10:55 AM, Richard W.M. Jones wrote: We don't seem to be reaching any sort of sensible conclusion with qemu about this bug, so it seems easier (albeit uglier) to fix it on the libvirt side. I have verified that with this patch virDomainMemoryPeek works on 64 bit guests. ACK. Thanks, I've pushed it. I'm also going to add this patch to libvirt in Fedora Rawhide. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/ -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 7/7] remote generator: Annotate hyper with the actual C type
2011/5/25 Eric Blake ebl...@redhat.com: On 05/25/2011 10:23 AM, Daniel P. Berrange wrote: On Mon, May 23, 2011 at 07:36:10PM +0200, Matthias Bolte wrote: Remove some special case code that took care of mapping hyper to the correct C types. Use macros for hyper to long assignments that perform overflow checks when long is smaller than hyper. Also use such macros for the safe hyper to longlong assignemts as this allows to keep the generator a bit simpler. + } elsif ($ret_member =~ m/^(unsigned )?hyper (\S+)\[\S+\];/) { + # error out on unannotated hypers + die (unsigned)? hyper without (u)?(long|longlong) annotation: $ret_member; 'hyper' in XDR world is a fixed 64 bit type, so IMHO, this should automatically map to 'long long' in the API, without requiring an annotation. eg, we should only annotate if the public API uses the variable sized 'long' / 'unsigned long' types in C. All the 'longlong' and 'ulonglong' annotations should be removed here IMHO, since they should be the default for hyper/unsigned hyper. If we add a new API that uses 'long' but forget the annotation, then we have silent type mismatch in the generated code. Since we are using hyper for both types in C, I find it better to require an annotation on all uses to be explicit on which type we meant, rather than defaulting the lack of annotation as 'long long' and only requiring annotation for 'long' - that is, I find that from the maintenance aspect, having the code generator explicitly fail because you forget an annotation (even if the annotation is the default of llong) is safer than risking silent code misgeneration. But anything is better than nothing, so I won't give any further complaints if we go with your idea of only annotating the exceptions to the 'long long' default, rather than all uses of hyper. I think that being more explicit here is better and would like to stick with annotating all hyper members. This way we cannot overlook a missing (u)long annotation in a review because the generator will complain for us. Matthias -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] build: fix 'make dist' for ./configure --without-remote
On 05/15/2011 08:51 PM, Wen Congyang wrote: At 05/12/2011 04:30 AM, Eric Blake Write: Anything generated that must end up in the tarball must either have unconditional rules for generation (remote_protocol.c) or must live in libvirt.git for the case where the person running 'make dist' has disabled the configure options that control the rebuild of the generated file (remote_protocol-structs). * src/Makefile.am (remote_protocol-structs): Add a dependency and document why it must live in git. ($(srcdir)/remote/%_protocol.c, $(srcdir)/remote/%_protocol.c): Unconditionally generate. --- This should be the last piece of the puzzle for fixing an issue that I first pointed out here: https://www.redhat.com/archives/libvir-list/2011-May/msg00343.html This patch still isn't in. Should it be? .PHONY: remote_protocol-structs -remote_protocol-structs: +if WITH_REMOTE +remote_protocol-structs: libvirt_driver_remote_la-remote_protocol.$(OBJEXT) This line will introduce another problem for ./configure --with-remote: make[1]: *** No rule to make target `libvirt_driver_remote_la-remote_protocol.o', needed by `remote_protocol-structs'. Stop. make[1]: Leaving directory `/home/wency/source/libvirt-nodaemon/src' make: *** [distdir] Error 1 I can't reproduce that failure on Fedora 14. What system were you on? Perhaps it is dependent on libtool version or automake version used to generate the Makefile? Should I isolate this change from the rest of the patch, so that 'make dist' works better from a --without-remote setup? -- Eric Blake ebl...@redhat.com+1-801-349-2682 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] build: fix 'make dist' for ./configure --without-remote
On 05/25/2011 04:10 PM, Eric Blake wrote: On 05/15/2011 08:51 PM, Wen Congyang wrote: At 05/12/2011 04:30 AM, Eric Blake Write: Anything generated that must end up in the tarball must either have unconditional rules for generation (remote_protocol.c) or must live in libvirt.git for the case where the person running 'make dist' has disabled the configure options that control the rebuild of the generated file (remote_protocol-structs). * src/Makefile.am (remote_protocol-structs): Add a dependency and document why it must live in git. ($(srcdir)/remote/%_protocol.c, $(srcdir)/remote/%_protocol.c): Unconditionally generate. --- This should be the last piece of the puzzle for fixing an issue that I first pointed out here: https://www.redhat.com/archives/libvir-list/2011-May/msg00343.html This patch still isn't in. Should it be? Actually, I've going ahead and pushing it under the build-breaker rule (after fixing a nit below), since I was able to confirm that: mkdir build cd build ../configure --without-remote make distcheck failed without this patch, because remote_protocol.h was not in the tarball and that resulted in make trying to (re)generate the file into a read-only directory (make distcheck is time-consuming, but it's nice for proving issues like this). Furthermore, there was talk on IRC about the daily snapshots not being generated lately, precisely because they are being generated from a build configured --without-remote, so this should help snapshot builds be more useful. .PHONY: remote_protocol-structs -remote_protocol-structs: +if WITH_REMOTE +remote_protocol-structs: libvirt_driver_remote_la-remote_protocol.$(OBJEXT) This line will introduce another problem for ./configure --with-remote: make[1]: *** No rule to make target `libvirt_driver_remote_la-remote_protocol.o', needed by `remote_protocol-structs'. Stop. make[1]: Leaving directory `/home/wency/source/libvirt-nodaemon/src' make: *** [distdir] Error 1 I can't reproduce that failure on Fedora 14. What system were you on? Perhaps it is dependent on libtool version or automake version used to generate the Makefile? Should I isolate this change from the rest of the patch, so that 'make dist' works better from a --without-remote setup? Oh, I think I see it now. libvirt_driver_remote_la-remote_protocol.o is a side-effect of the libtool rule for creating libvirt_driver_remote_la-remote_protocol.lo; so while the subsequent pdwtags call operates directly on the .o file, the Makefile dependency has to be on the witness .lo file that signifies whether the build has been done. I squashed this in: diff --git i/src/Makefile.am w/src/Makefile.am index 82cf6c4..c3d3102 100644 --- i/src/Makefile.am +++ w/src/Makefile.am @@ -207,7 +207,9 @@ r2 = /\* [[:xdigit:]]+ \S+:\d+ \*/ .PHONY: remote_protocol-structs if WITH_REMOTE -remote_protocol-structs: libvirt_driver_remote_la-remote_protocol.$(OBJEXT) +# The .o file that pdwtags parses is created as a side effect of running +# libtool; but from make's perspective we depend on the .lo file. +remote_protocol-structs: libvirt_driver_remote_la-remote_protocol.lo $(AM_V_GEN)if (pdwtags --help) /dev/null 21; then \ pdwtags --verbose libvirt_driver_remote_la-remote_protocol.$(OBJEXT) \ | perl -0777 -n \ -- Eric Blake ebl...@redhat.com+1-801-349-2682 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [Libvirt-test-API][PATCH] Modify try/except/finally format in all testcases for python backward compatibility
于 2011年05月23日 22:23, Guannan Ren 写道: From: Wayne Sung...@redhat.com * modify all cases under repos/ of try/except/finally format * delete utils/Python/virt.cfg which in wrong place Signed-off-by: Guannan Reng...@redhat.com --- repos/domain/attach_disk.py| 29 repos/domain/attach_interface.py | 29 repos/domain/autostart.py | 29 repos/domain/blkstats.py |9 +- repos/domain/create.py | 13 ++-- repos/domain/define.py | 19 +++-- repos/domain/destroy.py| 13 ++-- repos/domain/detach_disk.py| 29 repos/domain/detach_interface.py | 31 repos/domain/domain_uuid.py| 25 +++--- repos/domain/reboot.py | 13 ++-- repos/domain/save.py | 25 +++--- repos/domain/undefine.py | 19 +++-- repos/interface/create.py | 29 repos/interface/define.py | 25 +++--- repos/interface/destroy.py | 29 repos/interface/undefine.py| 25 +++--- repos/network/autostart.py | 39 +- repos/network/create.py| 31 repos/network/define.py| 29 repos/network/destroy.py | 31 repos/network/network_name.py | 25 +++--- repos/network/network_uuid.py | 25 +++--- repos/network/undefine.py | 29 repos/nodedevice/detach.py | 33 repos/nodedevice/reattach.py | 33 repos/nodedevice/reset.py | 21 +++--- repos/npiv/create_virtual_hba.py | 35 + repos/snapshot/delete.py | 23 +++--- repos/snapshot/internal_create.py | 15 ++-- repos/snapshot/revert.py | 15 ++-- repos/storage/activate_pool.py | 23 +++--- repos/storage/build_dir_pool.py| 27 --- repos/storage/build_disk_pool.py | 27 --- repos/storage/build_logical_pool.py| 29 repos/storage/build_netfs_pool.py | 27 --- repos/storage/create_dir_pool.py | 25 +++--- repos/storage/create_dir_volume.py | 13 ++-- repos/storage/create_fs_pool.py| 35 + repos/storage/create_iscsi_pool.py | 25 +++--- repos/storage/create_logical_volume.py | 31 repos/storage/create_netfs_pool.py | 35 + repos/storage/create_netfs_volume.py | 13 ++-- repos/storage/define_dir_pool.py | 37 +- repos/storage/define_disk_pool.py | 31 repos/storage/define_iscsi_pool.py | 29 repos/storage/define_logical_pool.py | 29 repos/storage/define_mpath_pool.py | 31 repos/storage/define_netfs_pool.py | 29 repos/storage/define_scsi_pool.py | 31 repos/storage/delete_dir_volume.py | 27 --- repos/storage/delete_logical_pool.py | 29 repos/storage/delete_logical_volume.py | 31 repos/storage/delete_netfs_volume.py | 27 --- repos/storage/pool_name.py | 23 +++--- repos/storage/pool_uuid.py | 23 +++--- repos/storage/undefine_pool.py | 29 utils/Python/virt.cfg | 129 58 files changed, 774 insertions(+), 846 deletions(-) delete mode 100644 utils/Python/virt.cfg Quite big patch, but the pricinple is very simple, doing the same fixing on all the related scripts. Looks good to me, ACK. Regards Osier -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCHv2 7/7] interface: implement a test driver for network config transaction API.
On 05/24/2011 02:24 AM, Daniel Veillard wrote: On Thu, May 19, 2011 at 04:51:29PM -0400, Laine Stump wrote: From: Michal Privoznikmpriv...@redhat.com --- src/conf/interface_conf.c | 45 src/conf/interface_conf.h |4 ++ src/test/test_driver.c| 83 + 3 files changed, 132 insertions(+), 0 deletions(-) diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index f3848bd..4ff68aa 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -1227,6 +1227,51 @@ void virInterfaceObjListFree(virInterfaceObjListPtr interfaces) interfaces-count = 0; } +int virInterfaceObjListClone(virConnectPtr conn, + virInterfaceObjListPtr src, + virInterfaceObjListPtr dest) +{ +int ret = -1; +unsigned int i, cnt; + +if (!src || !dest) +goto end; + +cnt = src-count; +for (i = 0; i cnt; i++) { +virInterfaceDefPtr def = src-objs[i]-def; +virInterfaceDefPtr backup; +virInterfaceObjPtr iface; +char *xml = virInterfaceDefFormat(def); + +if (!xml) { +virReportOOMError(); +goto no_memory; +} + +if ((backup = virInterfaceDefParseString(xml)) == NULL) { +VIR_FREE(xml); +goto no_memory; +} + +VIR_FREE(xml); +if ((iface = virInterfaceAssignDef(dest, backup)) == NULL) +goto no_memory; + +virInterfaceObjUnlock(iface); + +conn-refs++; +} + +ret = cnt; +end: +return ret; + +no_memory: +virInterfaceObjListFree(dest); I'ts always a problem when the callee frees up memory allocated by the caller in case of error, as it's so easy to mess things up. I would rather not do that here, and have the caller do the free if we fail. example: src == NULL, dest != NULL, and we leak dest. But virInterfaceObjListFree(dest) doesn't free dest itself, it only frees the items that are contained by dest (not dest itself), and those items were not allocated by the caller, but were allocated within virInterfaceObjListClone(), so I don't see the problem you see. There *is* a problem in general with this function, though - dest is not cleaned out before copying over the contents of src, so if it starts out non-empty, there may be extra stuff in there at the end. Michal - since you wrote it, maybe you should answer this question - shouldn't virInterfaceObjListClone() call virInterfaceObjListFree(dest) as soon as it determines dest != NULL? +goto end; +} + virInterfaceObjPtr virInterfaceAssignDef(virInterfaceObjListPtr interfaces, const virInterfaceDefPtr def) { diff --git a/src/conf/interface_conf.h b/src/conf/interface_conf.h index 6073b49..870a8ee 100644 --- a/src/conf/interface_conf.h +++ b/src/conf/interface_conf.h @@ -192,6 +192,10 @@ virInterfaceObjPtr virInterfaceFindByName(const virInterfaceObjListPtr void virInterfaceDefFree(virInterfaceDefPtr def); void virInterfaceObjFree(virInterfaceObjPtr iface); void virInterfaceObjListFree(virInterfaceObjListPtr vms); +int virInterfaceObjListClone(virConnectPtr conn, + virInterfaceObjListPtr src, + virInterfaceObjListPtr dest); + virInterfaceObjPtr virInterfaceAssignDef(virInterfaceObjListPtr interfaces, const virInterfaceDefPtr def); diff --git a/src/test/test_driver.c b/src/test/test_driver.c index e86bc4e..b58c5d2 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -85,6 +85,8 @@ struct _testConn { virDomainObjList domains; virNetworkObjList networks; virInterfaceObjList ifaces; +bool transaction_running; +virInterfaceObjList backupIfaces; virStoragePoolObjList pools; virNodeDeviceObjList devs; int numCells; @@ -3455,6 +3457,84 @@ cleanup: return ret; } +static int testInterfaceChangeBegin(virConnectPtr conn, +unsigned int flags ATTRIBUTE_UNUSED) +{ +testConnPtr privconn = conn-privateData; +int ret = -1; + +testDriverLock(privconn); +if (privconn-transaction_running) { +testError(VIR_ERR_OPERATION_INVALID, _(there is another transaction + running.)); +goto cleanup; +} + +privconn-transaction_running = true; + +if (virInterfaceObjListClone(conn,privconn-ifaces, +privconn-backupIfaces) 0) +goto cleanup; + +ret = 0; +cleanup: +testDriverUnlock(privconn); +return ret; +} + +static int testInterfaceChangeCommit(virConnectPtr conn, + unsigned int flags ATTRIBUTE_UNUSED) +{ +testConnPtr privconn = conn-privateData; +int ret = -1; + +testDriverLock(privconn); + +if (!privconn-transaction_running) { +
[libvirt] [PATCHv3 3/7] interface: implement public APIs for libvirt transactional network changes
From: Michal Privoznik mpriv...@redhat.com --- src/libvirt.c | 178 - 1 files changed, 176 insertions(+), 2 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index ff16c48..12b849a 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -8143,7 +8143,18 @@ error: * @xml: the XML description for the interface, preferably in UTF-8 * @flags: and OR'ed set of extraction flags, not used yet * - * Define an interface (or modify existing interface configuration) + + * Define an interface (or modify existing interface configuration). + * + * Normally this change in the interface configuration is immediately + * permanent/persistent, but if virInterfaceChangeBegin() has been + * previously called (i.e. if an interface config transaction is + * open), the new interface definition will only become permanent if + * virInterfaceChangeCommit() is called prior to the next reboot of + * the system running libvirtd. Prior to that time, it can be + * explicitly removed using virInterfaceChangeRollback(), or will be + * automatically removed during the next reboot of the system running + * libvirtd. * * Returns NULL in case of error, a pointer to the interface otherwise */ @@ -8190,6 +8201,16 @@ error: * Undefine an interface, ie remove it from the config. * This does not free the associated virInterfacePtr object. * + * Normally this change in the interface configuration is + * permanent/persistent, but if virInterfaceChangeBegin() has been + * previously called (i.e. if an interface config transaction is + * open), the removal of the interface definition will only become + * permanent if virInterfaceChangeCommit() is called prior to the next + * reboot of the system running libvirtd. Prior to that time, the + * definition can be explicitly restored using + * virInterfaceChangeRollback(), or will be automatically restored + * during the next reboot of the system running libvirtd. + * * Returns 0 in case of success, -1 in case of error */ int @@ -8230,7 +8251,12 @@ error: * @iface: pointer to a defined interface * @flags: and OR'ed set of extraction flags, not used yet * - * Activate an interface (ie call ifup) + * Activate an interface (i.e. call ifup). + * + * If there was an open network config transaction at the time this + * interface was defined (that is, if virInterfaceChangeBegin() had + * been called), the interface will be brought back down (and then + * undefined) if virInterfaceChangeRollback() is called. * * Returns 0 in case of success, -1 in case of error */ @@ -8277,6 +8303,13 @@ error: * This does not remove the interface from the config, and * does not free the associated virInterfacePtr object. * + + * If there is an open network config transaction at the time this + * interface is destroyed (that is, if virInterfaceChangeBegin() had + * been called), and if the interface is later undefined and then + * virInterfaceChangeRollback() is called, the restoral of the + * interface definition will also bring the interface back up. + * * Returns 0 in case of success and -1 in case of failure. */ int @@ -8374,6 +8407,147 @@ virInterfaceFree(virInterfacePtr iface) return 0; } +/** + * virInterfaceChangeBegin: + * @conn: pointer to hypervisor connection + * @flags: flags, not used yet + * + * This functions creates a restore point to which one can return + * later by calling virInterfaceChangeRollback(). This function should + * be called before any transaction with interface configuration. + * Once knowing, new configuration works, it can be commited via + * virInterfaceChangeCommit(), which frees the restore point. + * + * If virInterfaceChangeBegin() is called when a transaction is + * already opened, this function will fail, and a + * VIR_ERR_INVALID_OPERATION will be logged. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virInterfaceChangeBegin(virConnectPtr conn, unsigned int flags) +{ +int ret = -1; + +VIR_DEBUG(conn=%p, flags=%d, conn, flags); + +virResetLastError(); + +if (!VIR_IS_CONNECT(conn)) { +virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); +virDispatchError(NULL); +goto end; +} + +if (conn-flags VIR_CONNECT_RO) { +virLibInterfaceError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); +virDispatchError(conn); +goto end; +} + +if (conn-interfaceDriver conn-interfaceDriver-interfaceChangeBegin) { +ret = conn-interfaceDriver-interfaceChangeBegin(conn, flags); +} else { +virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); +} + +end: +VIR_DEBUG(returning: %d, ret); +return ret; +} + +/** + * virInterfaceChangeCommit: + * @conn: pointer to hypervisor connection + * @flags: flags, not used yet + * + * This commits the changes made to interfaces and frees the restore point + * created by virInterfaceChangeBegin(). + * + * If virInterfaceChangeCommit() is called