From 6609ed5a377c3beaf8389e870b6851856cee42c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= Date: Thu, 4 Jan 2018 12:04:07 +0100 Subject: [PATCH 1/3] Extract stats functions from the qemu driver Some of the qemu functions getting statistics can easily be reused in other drivers. Create a conf/domain_stats.[ch] pair to host some of them. --- src/Makefile.am | 1 + src/conf/domain_stats.c | 139 +++++++++++++++++++++++++++++++++++++++++ src/conf/domain_stats.h | 64 +++++++++++++++++++ src/libvirt_private.syms | 4 ++ src/qemu/qemu_driver.c | 158 +++-------------------------------------------- src/util/vircgroup.c | 46 ++++++++++++++ src/util/vircgroup.h | 4 ++ 7 files changed, 265 insertions(+), 151 deletions(-) create mode 100644 src/conf/domain_stats.c create mode 100644 src/conf/domain_stats.h Index: libvirt-4.5.0/src/conf/domain_stats.c =================================================================== --- /dev/null +++ libvirt-4.5.0/src/conf/domain_stats.c @@ -0,0 +1,139 @@ +/* + * domain_stats.c: domain stats extraction helpers + * + * Copyright (C) 2006-2016 Red Hat, Inc. + * Copyright (C) 2006-2008 Daniel P. Berrange + * Copyright (c) 2018 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Author: Daniel P. Berrange + */ + +#include + +#include + +#include "virlog.h" +#include "domain_stats.h" +#include "virtypedparam.h" +#include "virnetdevtap.h" +#include "virnetdevopenvswitch.h" + +#define VIR_FROM_THIS VIR_FROM_DOMAIN + +VIR_LOG_INIT("conf.domain_stats"); + +int +virDomainStatsGetState(virDomainObjPtr dom, + virDomainStatsRecordPtr record, + int *maxparams) +{ + if (virTypedParamsAddInt(&record->params, + &record->nparams, + maxparams, + "state.state", + dom->state.state) < 0) + return -1; + + if (virTypedParamsAddInt(&record->params, + &record->nparams, + maxparams, + "state.reason", + dom->state.reason) < 0) + return -1; + + return 0; +} + +#define STATS_ADD_NET_PARAM(record, maxparams, num, name, value) \ +do { \ + char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \ + snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \ + "net.%zu.%s", num, name); \ + if (value >= 0 && virTypedParamsAddULLong(&(record)->params, \ + &(record)->nparams, \ + maxparams, \ + param_name, \ + value) < 0) \ + return -1; \ +} while (0) + +int +virDomainStatsGetInterface(virDomainObjPtr dom, + virDomainStatsRecordPtr record, + int *maxparams) +{ + size_t i; + struct _virDomainInterfaceStats tmp; + int ret = -1; + + if (!virDomainObjIsActive(dom)) + return 0; + + VIR_DOMAIN_STATS_ADD_COUNT_PARAM(record, maxparams, "net", dom->def->nnets); + + /* Check the path is one of the domain's network interfaces. */ + for (i = 0; i < dom->def->nnets; i++) { + virDomainNetDefPtr net = dom->def->nets[i]; + virDomainNetType actualType; + + if (!net->ifname) + continue; + + memset(&tmp, 0, sizeof(tmp)); + + actualType = virDomainNetGetActualType(net); + + VIR_DOMAIN_STATS_ADD_NAME_PARAM(record, maxparams, + "net", "name", i, net->ifname); + + if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) { + if (virNetDevOpenvswitchInterfaceStats(net->ifname, &tmp) < 0) { + virResetLastError(); + continue; + } + } else { + if (virNetDevTapInterfaceStats(net->ifname, &tmp, + !virDomainNetTypeSharesHostView(net)) < 0) { + virResetLastError(); + continue; + } + } + + STATS_ADD_NET_PARAM(record, maxparams, i, + "rx.bytes", tmp.rx_bytes); + STATS_ADD_NET_PARAM(record, maxparams, i, + "rx.pkts", tmp.rx_packets); + STATS_ADD_NET_PARAM(record, maxparams, i, + "rx.errs", tmp.rx_errs); + STATS_ADD_NET_PARAM(record, maxparams, i, + "rx.drop", tmp.rx_drop); + STATS_ADD_NET_PARAM(record, maxparams, i, + "tx.bytes", tmp.tx_bytes); + STATS_ADD_NET_PARAM(record, maxparams, i, + "tx.pkts", tmp.tx_packets); + STATS_ADD_NET_PARAM(record, maxparams, i, + "tx.errs", tmp.tx_errs); + STATS_ADD_NET_PARAM(record, maxparams, i, + "tx.drop", tmp.tx_drop); + } + + ret = 0; + cleanup: + return ret; +} + +#undef STATS_ADD_NET_PARAM Index: libvirt-4.5.0/src/conf/domain_stats.h =================================================================== --- /dev/null +++ libvirt-4.5.0/src/conf/domain_stats.h @@ -0,0 +1,64 @@ +/* + * domain_stats.h: domain stats extraction helpers + * + * Copyright (C) 2006-2016 Red Hat, Inc. + * Copyright (C) 2006-2008 Daniel P. Berrange + * Copyright (c) 2018 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Author: Daniel P. Berrange + */ +#ifndef __DOMAIN_STATS_H +# define __DOMAIN_STATS_H + +# include "internal.h" +# include "domain_conf.h" + + +# define VIR_DOMAIN_STATS_ADD_COUNT_PARAM(record, maxparams, type, count) \ +do { \ + char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \ + snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, "%s.count", type); \ + if (virTypedParamsAddUInt(&(record)->params, \ + &(record)->nparams, \ + maxparams, \ + param_name, \ + count) < 0) \ + goto cleanup; \ +} while (0) + +# define VIR_DOMAIN_STATS_ADD_NAME_PARAM(record, maxparams, type, subtype, num, name) \ +do { \ + char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \ + snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \ + "%s.%zu.%s", type, num, subtype); \ + if (virTypedParamsAddString(&(record)->params, \ + &(record)->nparams, \ + maxparams, \ + param_name, \ + name) < 0) \ + goto cleanup; \ +} while (0) + +int virDomainStatsGetState(virDomainObjPtr dom, + virDomainStatsRecordPtr record, + int *maxparams); + +int virDomainStatsGetInterface(virDomainObjPtr dom, + virDomainStatsRecordPtr record, + int *maxparams); + +#endif /* __DOMAIN_STATS_H */ Index: libvirt-4.5.0/src/libvirt_private.syms =================================================================== --- libvirt-4.5.0.orig/src/libvirt_private.syms +++ libvirt-4.5.0/src/libvirt_private.syms @@ -654,6 +654,9 @@ virDomainConfNWFilterInstantiate; virDomainConfNWFilterTeardown; virDomainConfVMNWFilterTeardown; +# conf/domain_stats.h +virDomainStatsGetInterface; +virDomainStatsGetState; # conf/interface_conf.h virInterfaceDefFormat; @@ -1543,6 +1546,7 @@ virCgroupGetMemoryUsage; virCgroupGetMemSwapHardLimit; virCgroupGetMemSwapUsage; virCgroupGetPercpuStats; +virCgroupGetStatsCpu; virCgroupHasController; virCgroupHasEmptyTasks; virCgroupKill; Index: libvirt-4.5.0/src/qemu/qemu_driver.c =================================================================== --- libvirt-4.5.0.orig/src/qemu/qemu_driver.c +++ libvirt-4.5.0/src/qemu/qemu_driver.c @@ -74,6 +74,7 @@ #include "virarptable.h" #include "viruuid.h" #include "domain_conf.h" +#include "domain_stats.h" #include "domain_audit.h" #include "node_device_conf.h" #include "virpci.h" @@ -19670,21 +19671,7 @@ qemuDomainGetStatsState(virQEMUDriverPtr int *maxparams, unsigned int privflags ATTRIBUTE_UNUSED) { - if (virTypedParamsAddInt(&record->params, - &record->nparams, - maxparams, - "state.state", - dom->state.state) < 0) - return -1; - - if (virTypedParamsAddInt(&record->params, - &record->nparams, - maxparams, - "state.reason", - dom->state.reason) < 0) - return -1; - - return 0; + return virDomainStatsGetState(dom, record, maxparams); } @@ -19707,37 +19694,7 @@ qemuDomainGetStatsCpu(virQEMUDriverPtr d unsigned int privflags ATTRIBUTE_UNUSED) { qemuDomainObjPrivatePtr priv = dom->privateData; - unsigned long long cpu_time = 0; - unsigned long long user_time = 0; - unsigned long long sys_time = 0; - int err = 0; - - if (!priv->cgroup) - return 0; - - err = virCgroupGetCpuacctUsage(priv->cgroup, &cpu_time); - if (!err && virTypedParamsAddULLong(&record->params, - &record->nparams, - maxparams, - "cpu.time", - cpu_time) < 0) - return -1; - - err = virCgroupGetCpuacctStat(priv->cgroup, &user_time, &sys_time); - if (!err && virTypedParamsAddULLong(&record->params, - &record->nparams, - maxparams, - "cpu.user", - user_time) < 0) - return -1; - if (!err && virTypedParamsAddULLong(&record->params, - &record->nparams, - maxparams, - "cpu.system", - sys_time) < 0) - return -1; - - return 0; + return virCgroupGetStatsCpu(priv->cgroup, record, maxparams); } static int @@ -19916,44 +19873,6 @@ qemuDomainGetStatsVcpu(virQEMUDriverPtr return ret; } -#define QEMU_ADD_COUNT_PARAM(record, maxparams, type, count) \ -do { \ - char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \ - snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, "%s.count", type); \ - if (virTypedParamsAddUInt(&(record)->params, \ - &(record)->nparams, \ - maxparams, \ - param_name, \ - count) < 0) \ - goto cleanup; \ -} while (0) - -#define QEMU_ADD_NAME_PARAM(record, maxparams, type, subtype, num, name) \ -do { \ - char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \ - snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \ - "%s.%zu.%s", type, num, subtype); \ - if (virTypedParamsAddString(&(record)->params, \ - &(record)->nparams, \ - maxparams, \ - param_name, \ - name) < 0) \ - goto cleanup; \ -} while (0) - -#define QEMU_ADD_NET_PARAM(record, maxparams, num, name, value) \ -do { \ - char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \ - snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \ - "net.%zu.%s", num, name); \ - if (value >= 0 && virTypedParamsAddULLong(&(record)->params, \ - &(record)->nparams, \ - maxparams, \ - param_name, \ - value) < 0) \ - return -1; \ -} while (0) - static int qemuDomainGetStatsInterface(virQEMUDriverPtr driver ATTRIBUTE_UNUSED, virDomainObjPtr dom, @@ -19961,68 +19880,9 @@ qemuDomainGetStatsInterface(virQEMUDrive int *maxparams, unsigned int privflags ATTRIBUTE_UNUSED) { - size_t i; - struct _virDomainInterfaceStats tmp; - int ret = -1; - - if (!virDomainObjIsActive(dom)) - return 0; - - QEMU_ADD_COUNT_PARAM(record, maxparams, "net", dom->def->nnets); - - /* Check the path is one of the domain's network interfaces. */ - for (i = 0; i < dom->def->nnets; i++) { - virDomainNetDefPtr net = dom->def->nets[i]; - virDomainNetType actualType; - - if (!net->ifname) - continue; - - memset(&tmp, 0, sizeof(tmp)); - - actualType = virDomainNetGetActualType(net); - - QEMU_ADD_NAME_PARAM(record, maxparams, - "net", "name", i, net->ifname); - - if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) { - if (virNetDevOpenvswitchInterfaceStats(net->ifname, &tmp) < 0) { - virResetLastError(); - continue; - } - } else { - if (virNetDevTapInterfaceStats(net->ifname, &tmp, - !virDomainNetTypeSharesHostView(net)) < 0) { - virResetLastError(); - continue; - } - } - - QEMU_ADD_NET_PARAM(record, maxparams, i, - "rx.bytes", tmp.rx_bytes); - QEMU_ADD_NET_PARAM(record, maxparams, i, - "rx.pkts", tmp.rx_packets); - QEMU_ADD_NET_PARAM(record, maxparams, i, - "rx.errs", tmp.rx_errs); - QEMU_ADD_NET_PARAM(record, maxparams, i, - "rx.drop", tmp.rx_drop); - QEMU_ADD_NET_PARAM(record, maxparams, i, - "tx.bytes", tmp.tx_bytes); - QEMU_ADD_NET_PARAM(record, maxparams, i, - "tx.pkts", tmp.tx_packets); - QEMU_ADD_NET_PARAM(record, maxparams, i, - "tx.errs", tmp.tx_errs); - QEMU_ADD_NET_PARAM(record, maxparams, i, - "tx.drop", tmp.tx_drop); - } - - ret = 0; - cleanup: - return ret; + return virDomainStatsGetInterface(dom, record, maxparams); } -#undef QEMU_ADD_NET_PARAM - #define QEMU_ADD_BLOCK_PARAM_UI(record, maxparams, num, name, value) \ do { \ char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \ @@ -20144,10 +20004,10 @@ qemuDomainGetStatsOneBlock(virQEMUDriver if (disk->info.alias) alias = qemuDomainStorageAlias(disk->info.alias, backing_idx); - QEMU_ADD_NAME_PARAM(record, maxparams, "block", "name", block_idx, + VIR_DOMAIN_STATS_ADD_NAME_PARAM(record, maxparams, "block", "name", block_idx, disk->dst); if (virStorageSourceIsLocalStorage(src) && src->path) - QEMU_ADD_NAME_PARAM(record, maxparams, "block", "path", + VIR_DOMAIN_STATS_ADD_NAME_PARAM(record, maxparams, "block", "path", block_idx, src->path); if (backing_idx) QEMU_ADD_BLOCK_PARAM_UI(record, maxparams, block_idx, "backingIndex", @@ -20263,7 +20123,7 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr * after the iteration than it is to iterate twice; but we still * want count listed first. */ count_index = record->nparams; - QEMU_ADD_COUNT_PARAM(record, maxparams, "block", 0); + VIR_DOMAIN_STATS_ADD_COUNT_PARAM(record, maxparams, "block", 0); for (i = 0; i < dom->def->ndisks; i++) { virDomainDiskDefPtr disk = dom->def->disks[i]; @@ -20297,10 +20157,6 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr #undef QEMU_ADD_BLOCK_PARAM_ULL -#undef QEMU_ADD_NAME_PARAM - -#undef QEMU_ADD_COUNT_PARAM - static int qemuDomainGetStatsPerfOneEvent(virPerfPtr perf, virPerfEventType type, Index: libvirt-4.5.0/src/util/vircgroup.c =================================================================== --- libvirt-4.5.0.orig/src/util/vircgroup.c +++ libvirt-4.5.0/src/util/vircgroup.c @@ -4122,6 +4122,44 @@ virCgroupControllerAvailable(int control return ret; } +int +virCgroupGetStatsCpu(virCgroupPtr cgroup, + virDomainStatsRecordPtr record, + int *maxparams) +{ + unsigned long long cpu_time = 0; + unsigned long long user_time = 0; + unsigned long long sys_time = 0; + int err = 0; + + if (!cgroup) + return 0; + + err = virCgroupGetCpuacctUsage(cgroup, &cpu_time); + if (!err && virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + "cpu.time", + cpu_time) < 0) + return -1; + + err = virCgroupGetCpuacctStat(cgroup, &user_time, &sys_time); + if (!err && virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + "cpu.user", + user_time) < 0) + return -1; + if (!err && virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + "cpu.system", + sys_time) < 0) + return -1; + + return 0; +} + #else /* !VIR_CGROUP_SUPPORTED */ bool @@ -4899,6 +4937,14 @@ virCgroupControllerAvailable(int control { return false; } + +int +virCgroupGetStatsCpu(virCgroupPtr cgroup, + virDomainStatsRecordPtr record, + int *maxparams) +{ + return 0; +} #endif /* !VIR_CGROUP_SUPPORTED */ Index: libvirt-4.5.0/src/util/vircgroup.h =================================================================== --- libvirt-4.5.0.orig/src/util/vircgroup.h +++ libvirt-4.5.0/src/util/vircgroup.h @@ -297,4 +297,8 @@ int virCgroupSetOwner(virCgroupPtr cgrou int virCgroupHasEmptyTasks(virCgroupPtr cgroup, int controller); bool virCgroupControllerAvailable(int controller); + +int virCgroupGetStatsCpu(virCgroupPtr cgroup, + virDomainStatsRecordPtr record, + int *maxparams); #endif /* __VIR_CGROUP_H__ */ Index: libvirt-4.5.0/src/conf/Makefile.inc.am =================================================================== --- libvirt-4.5.0.orig/src/conf/Makefile.inc.am +++ libvirt-4.5.0/src/conf/Makefile.inc.am @@ -20,6 +20,8 @@ DOMAIN_CONF_SOURCES = \ conf/domain_audit.h \ conf/domain_nwfilter.c \ conf/domain_nwfilter.h \ + conf/domain_stats.c \ + conf/domain_stats.h \ conf/virsavecookie.c \ conf/virsavecookie.h \ conf/snapshot_conf.c \