virtio functions are available in libmetrics and in libserialclient (with minimal dependencies). --- We would like to have the serialclient code available in a library without additional dependencies, because linking against libmetrics requires libxml2. virtio adds the 3rd transport method to vhostmd and the available '#ifdef WITH_XENSTORE' sections in vm-dump-metrics/main.c should be reviewed. libmetrics/Makefile.am | 17 +++- libmetrics/libmetrics.h | 6 ++ libmetrics/libserialclient.c | 172 +++++++++++++++++++++++++++++++++++ libmetrics/libserialclient.h | 30 ++++++ vm-dump-metrics/main.c | 29 ++++-- 5 files changed, 246 insertions(+), 8 deletions(-) create mode 100644 libmetrics/libserialclient.c create mode 100644 libmetrics/libserialclient.h diff --git a/libmetrics/Makefile.am b/libmetrics/Makefile.am index 28490ee..468f08f 100644 --- a/libmetrics/Makefile.am +++ b/libmetrics/Makefile.am @@ -6,7 +6,7 @@ if WITH_XENSTORE AM_CFLAGS += -DWITH_XENSTORE endif -lib_LTLIBRARIES=libmetrics.la +lib_LTLIBRARIES=libmetrics.la libserialclient.la libmetricsincdir=$(includedir)/vhostmd libmetricsinc_HEADERS = libmetrics.h @@ -15,8 +15,21 @@ libmetrics_la_SOURCES = \ libmetrics.c \ vm_metrics.c \ host_metrics.c \ + libserialclient.c \ libmetrics.h libmetrics_la_DEPENDENCIES = \ - libmetrics.h + libmetrics.h \ + libserialclient.h + + +libserialclientincdir= +libserialclientinc_HEADERS = libserialclient.h + +libserialclient_la_SOURCES = \ + libserialclient.c \ + libserialclient.h + +libserialclient_la_DEPENDENCIES = \ + libserialclient.h diff --git a/libmetrics/libmetrics.h b/libmetrics/libmetrics.h index 717bc73..1908de8 100644 --- a/libmetrics/libmetrics.h +++ b/libmetrics/libmetrics.h @@ -100,4 +100,10 @@ int dump_metrics(const char *dest_file); /* dump metrics from xenstore to xml formatted file */ int dump_xenstore_metrics(const char *dest_file); +/* dump metrics from virtio serial port to xml formatted file */ +int dump_virtio_metrics(const char *dest_file); + +/* dump metrics from virtio serial port to buffer */ +const char *get_virtio_metrics(const char *dev_name); + #endif diff --git a/libmetrics/libserialclient.c b/libmetrics/libserialclient.c new file mode 100644 index 0000000..61adc2b --- /dev/null +++ b/libmetrics/libserialclient.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2018 SAP SE + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Michael Trapp <michael.trapp@xxxxxxx> + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +#include "libserialclient.h" + + +/* + * dump metrics from virtio serial port to xml formatted file + */ +int dump_virtio_metrics(const char *dest_file) +{ + FILE *fp = stdout; + char *response; + size_t len; + + response = get_virtio_metrics(NULL); + if (response == NULL) + goto error; + + len = strlen(response); + + if (dest_file) { + fp = fopen(dest_file, "w"); + if (fp == NULL) { + fprintf(stderr, + "LIB_SERIALCLIENT: Error, unable to dump metrics: fopen(%s) %s\n", + dest_file, strerror(errno)); + goto error; + } + } + + if (fwrite(response, 1UL, len, fp) != len) { + fprintf(stderr, + "LIB_SERIALCLIENT: Error, unable to export metrics to file:%s - error:%s\n", + dest_file ? dest_file : "STDOUT", strerror(errno)); + goto error; + } + + if (response) + free(response); + + return 0; + + error: + if (dest_file && fp) + fclose(fp); + + if (response) + free(response); + + return -1; +} + +/* + * dump metrics from virtio serial port to buffer + */ +char *get_virtio_metrics(const char *dev_name) +{ + const char request[] = "GET /metrics/XML\n\n", end_token[] = "\n\n"; + const char *dev; + char *response = NULL; + int fd = -1; + size_t pos; + size_t buf_size = (1 << 16); + const size_t req_len = (size_t) strlen(request); + const time_t start_time = time(NULL); + + if (dev_name) + dev = dev_name; + else + dev = "/dev/virtio-ports/vhostmd"; + + response = calloc(1UL, buf_size); + if (response == NULL) + goto error; + + fd = open(dev, O_RDWR | O_NONBLOCK); + + if (fd < 0) { + fprintf(stderr, + "LIB_SERIALCLIENT: Error, unable to dump metrics: open(%s) %s\n", + dev, strerror(errno)); + goto error; + } + + pos = 0; + while (pos < req_len) { + ssize_t len = write(fd, &request[pos], req_len - pos); + if (len > 0) + pos += (size_t) len; + else { + if (errno == EAGAIN) + usleep(10000); + else + goto error; + } + } + + pos = 0; + do { + ssize_t len = read(fd, &response[pos], buf_size - pos - 1); + if (len > 0) { + pos += (size_t) len; + response[pos] = 0; + + if ((pos + 1) >= buf_size) { + buf_size = buf_size << 1; // increase response buffer + if (buf_size > (1 << 24)) // max 16MB + goto error; + + response = realloc(response, buf_size); + if (response == NULL) + goto error; + + memset(&response[pos], 0, buf_size - pos); + } + } else { + if (errno == EAGAIN) { + usleep(10000); + if (time(NULL) > (start_time + 30)) { + fprintf(stderr, + "LIB_SERIALCLIENT: Error, unable to read metrics" + " - timeout after 30s\n"); + goto error; + } + } else + goto error; + } + } while ((pos < (size_t) strlen(end_token) || + strcmp(end_token, &response[pos - (size_t) strlen(end_token)]) != 0) && + pos < buf_size); + + if (fd >= 0) + close(fd); + + return response; + + error: + if (fd >= 0) + close(fd); + if (response) + free(response); + + return NULL; +} diff --git a/libmetrics/libserialclient.h b/libmetrics/libserialclient.h new file mode 100644 index 0000000..887c6a5 --- /dev/null +++ b/libmetrics/libserialclient.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 SAP SE + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Michael Trapp <michael.trapp@xxxxxxx> + */ + +#ifndef __LIBSERIALCLIENT_H__ +#define __LIBSERIALCLIENT_H__ + +/* dump metrics from virtio serial port to xml formatted file */ +int dump_virtio_metrics(const char *dest_file); + +/* dump metrics from virtio serial port to buffer */ +char *get_virtio_metrics(const char *dev_name); + +#endif diff --git a/vm-dump-metrics/main.c b/vm-dump-metrics/main.c index 53874e8..aff92ad 100644 --- a/vm-dump-metrics/main.c +++ b/vm-dump-metrics/main.c @@ -34,6 +34,7 @@ static void usage(const char *argv0) #ifdef WITH_XENSTORE "\t-x | --xenstore Get metrics from xenstore.\n" #endif + "\t-i | --virtio Get metrics from virtio channel.\n" "\t-b | --vbd Get metrics from vbd.\n"; fprintf (stderr, "\nUsage: %s [options]\n\n%s\n", argv0, options_str); @@ -46,6 +47,7 @@ int main(int argc, char *argv[]) #ifdef WITH_XENSTORE int xenstore = 0; #endif + int virtio = 0; const char *dfile = NULL; struct option opts[] = { @@ -54,6 +56,7 @@ int main(int argc, char *argv[]) #ifdef WITH_XENSTORE { "xenstore", no_argument, &xenstore, 1}, #endif + { "virtio", no_argument, &virtio, 1}, { "help", no_argument, NULL, '?' }, { "dest", optional_argument, NULL, 'd'}, {0, 0, 0, 0} @@ -64,9 +67,9 @@ int main(int argc, char *argv[]) int c; #ifdef WITH_XENSTORE - c = getopt_long(argc, argv, "d:vbx", opts, &optidx); + c = getopt_long(argc, argv, "d:vbix", opts, &optidx); #else - c = getopt_long(argc, argv, "d:vb", opts, &optidx); + c = getopt_long(argc, argv, "d:vbi", opts, &optidx); #endif if (c == -1) @@ -82,6 +85,9 @@ int main(int argc, char *argv[]) case 'b': vbd = 1; break; + case 'i': + virtio = 1; + break; #ifdef WITH_XENSTORE case 'x': xenstore = 1; @@ -107,20 +113,31 @@ int main(int argc, char *argv[]) } #endif + if (virtio) { + if (dump_virtio_metrics(dfile) == -1) + exit(1); + exit(0); + } + if (vbd) { if (dump_metrics(dfile) == -1) exit(1); exit(0); } - /* If no metrics source is specfied, try disk first and then xenstore */ + /* + * If no metrics source is specfied, try default order + * disk, virtio, xenstore + */ if (dump_metrics(dfile) == -1) { + if (dump_virtio_metrics(dfile) == -1) { #ifdef WITH_XENSTORE - if (dump_xenstore_metrics(dfile) == -1) - exit(1); + if (dump_xenstore_metrics(dfile) == -1) + exit(1); #else - exit(1); + exit(1); #endif + } } exit(0); -- 2.17.2 (Apple Git-113) _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list