[Libvir] PATCH: Separate QEMU impl of nodeinfo API
Daniel P. Berrange
berrange at redhat.com
Wed Jul 25 14:31:53 UTC 2007
On Wed, Jul 25, 2007 at 10:22:53AM +0100, Richard W.M. Jones wrote:
> + if (!strncmp(line, "processor", 9)) {
> //...
> + } else if (!strncmp(line, "cpu MHz", 7)) {
>
> Gaah. I know we don't have macros for these, but "== 0".
We do now.
STREQLEN(a,b,n)
STRNEQLEN(a,b,n)
> There might be a pathological cpuinfo file which has another entry
> beginning with ^processor. If only we were using a real language which
> allowed simple use of regexps.
It now checks that the data following is all whitespace upto the ':'
character.
> The error handling in this next section of the patch is wrong. It
> should call __virRaiseError when the files cannot be opened or if the
> functions fail for some reason. In the Solaris case it should also call
> __virRaiseError (that print to stderr could be lost), but perhaps it's
> better to #error out?
I made it use __virRaiseError everywhere. #error is unneccessarily
harsh - all our APIs return -1 & raise an error if they're not implemented
by a particular driver.
Dan.
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules: http://search.cpan.org/~danberr/ -=|
|=- Projects: http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
-------------- next part --------------
Index: src/Makefile.am
===================================================================
RCS file: /data/cvs/libvirt/src/Makefile.am,v
retrieving revision 1.46
diff -u -p -u -p -r1.46 Makefile.am
--- src/Makefile.am 19 Jul 2007 16:22:40 -0000 1.46
+++ src/Makefile.am 25 Jul 2007 14:28:12 -0000
@@ -50,6 +50,7 @@ CLIENT_SOURCES = \
qemu_conf.c qemu_conf.h \
openvz_conf.c openvz_conf.h \
openvz_driver.c openvz_driver.h \
+ nodeinfo.h nodeinfo.c \
util.c util.h
SERVER_SOURCES = \
Index: src/internal.h
===================================================================
RCS file: /data/cvs/libvirt/src/internal.h,v
retrieving revision 1.46
diff -u -p -u -p -r1.46 internal.h
--- src/internal.h 6 Jul 2007 15:02:09 -0000 1.46
+++ src/internal.h 25 Jul 2007 14:28:12 -0000
@@ -36,6 +36,8 @@ extern "C" {
#define STRCASEEQ(a,b) (strcasecmp((a),(b)) == 0)
#define STRNEQ(a,b) (strcmp((a),(b)) != 0)
#define STRCASENEQ(a,b) (strcasecmp((a),(b)) != 0)
+#define STREQLEN(a,b,n) (strncmp((a),(b),(n)) == 0)
+#define STRNEQLEN(a,b,n) (strncmp((a),(b),(n)) != 0)
/**
* ATTRIBUTE_UNUSED:
Index: src/nodeinfo.c
===================================================================
RCS file: src/nodeinfo.c
diff -N src/nodeinfo.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/nodeinfo.c 25 Jul 2007 14:28:12 -0000
@@ -0,0 +1,193 @@
+/*
+ * nodeinfo.c: Helper routines for OS specific node information
+ *
+ * Copyright (C) 2006, 2007 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * 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: Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/utsname.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "nodeinfo.h"
+
+#ifdef __linux__
+#define MEMINFO_PATH "/proc/meminfo"
+#define CPUINFO_PATH "/proc/cpuinfo"
+
+/* NB, these are not static as we need to call them from testsuite */
+int linuxNodeInfoCPUPopulate(virConnectPtr conn, FILE *cpuinfo, virNodeInfoPtr nodeinfo);
+int linuxNodeInfoMemPopulate(virConnectPtr conn, FILE *meminfo, virNodeInfoPtr nodeinfo);
+
+int linuxNodeInfoCPUPopulate(virConnectPtr conn, FILE *cpuinfo, virNodeInfoPtr nodeinfo) {
+ char line[1024];
+
+ nodeinfo->cpus = 0;
+ nodeinfo->mhz = 0;
+ nodeinfo->nodes = nodeinfo->sockets = nodeinfo->cores = nodeinfo->threads = 1;
+
+ /* NB: It is impossible to fill our nodes, since cpuinfo
+ * has not knowledge of NUMA nodes */
+
+ /* XXX hyperthreads */
+ while (fgets(line, sizeof(line), cpuinfo) != NULL) {
+ char *buf = line;
+ if (STREQLEN(buf, "processor", 9)) { /* aka a single logical CPU */
+ buf += 9;
+ while (*buf && isspace(*buf))
+ buf++;
+ if (*buf != ':') {
+ __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR,
+ VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
+ "parsing cpuinfo processor");
+ return -1;
+ }
+ nodeinfo->cpus++;
+ } else if (STREQLEN(buf, "cpu MHz", 7)) {
+ buf += 9;
+ while (*buf && isspace(*buf))
+ buf++;
+ if (*buf != ':' || !buf[1]) {
+ __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR,
+ VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
+ "parsing cpuinfo cpu MHz");
+ return -1;
+ }
+ nodeinfo->mhz = (unsigned int)strtol(buf+1, NULL, 10);
+ } else if (STREQLEN(buf, "cpu cores", 9)) { /* aka cores */
+ unsigned int id;
+ buf += 9;
+ while (*buf && isspace(*buf))
+ buf++;
+ if (*buf != ':' || !buf[1]) {
+ __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR,
+ VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
+ "parsing cpuinfo cpu cores %c", *buf);
+ return -1;
+ }
+ id = (unsigned int)strtol(buf+1, NULL, 10);
+ if (id > nodeinfo->cores)
+ nodeinfo->cores = id;
+ }
+ }
+
+ if (!nodeinfo->cpus) {
+ __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR,
+ VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
+ "no cpus found");
+ return -1;
+ }
+
+ /*
+ * Can't reliably count sockets from proc metadata, so
+ * infer it based on total CPUs vs cores.
+ * XXX hyperthreads
+ */
+ nodeinfo->sockets = nodeinfo->cpus / nodeinfo->cores;
+
+ return 0;
+}
+
+
+int linuxNodeInfoMemPopulate(virConnectPtr conn, FILE *meminfo, virNodeInfoPtr nodeinfo) {
+ char line[1024];
+
+ nodeinfo->memory = 0;
+
+ while (fgets(line, sizeof(line), meminfo) != NULL) {
+ if (STREQLEN(line, "MemTotal:", 9)) {
+ nodeinfo->memory = (unsigned int)strtol(line + 10, NULL, 10);
+ }
+ }
+ if (!nodeinfo->memory) {
+ __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR,
+ VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
+ "no memory found");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+#endif
+
+int virNodeInfoPopulate(virConnectPtr conn,
+ virNodeInfoPtr nodeinfo) {
+ struct utsname info;
+#ifdef __linux__
+ int ret;
+ FILE *cpuinfo, *meminfo;
+#endif
+
+ if (uname(&info) < 0) {
+ __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR,
+ VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
+ "cannot extract machine type %s", strerror(errno));
+ return -1;
+ }
+
+ strncpy(nodeinfo->model, info.machine, sizeof(nodeinfo->model)-1);
+ nodeinfo->model[sizeof(nodeinfo->model)-1] = '\0';
+
+#ifdef __linux__
+ cpuinfo = fopen(CPUINFO_PATH, "r");
+ if (!cpuinfo) {
+ __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR,
+ VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
+ "cannot open %s %s", CPUINFO_PATH, strerror(errno));
+ return -1;
+ }
+ ret = linuxNodeInfoCPUPopulate(conn, cpuinfo, nodeinfo);
+ fclose(cpuinfo);
+ if (ret < 0)
+ return -1;
+
+ meminfo = fopen(MEMINFO_PATH, "r");
+ if (!meminfo) {
+ __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR,
+ VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
+ "cannot open %s %s", MEMINFO_PATH, strerror(errno));
+ return -1;
+ }
+ ret = linuxNodeInfoMemPopulate(conn, meminfo, nodeinfo);
+ fclose(meminfo);
+
+ return ret;
+#else
+ /* XXX Solaris will need an impl later if they port QEMU driver */
+ __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR,
+ VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
+ "%s:%s not implemented on this platform\n", __FILE__, __FUNCTION__);
+ return -1;
+#endif
+}
+
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
Index: src/nodeinfo.h
===================================================================
RCS file: src/nodeinfo.h
diff -N src/nodeinfo.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/nodeinfo.h 25 Jul 2007 14:28:12 -0000
@@ -0,0 +1,39 @@
+/*
+ * nodeinfo.c: Helper routines for OS specific node information
+ *
+ * Copyright (C) 2006, 2007 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * 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: Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#ifndef __VIR_NODEINFO_H__
+#define __VIR_NODEINFO_H__
+
+#include "internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ int virNodeInfoPopulate(virConnectPtr conn, virNodeInfoPtr nodeinfo);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __VIR_NODEINFO_H__*/
Index: src/openvz_driver.c
===================================================================
RCS file: /data/cvs/libvirt/src/openvz_driver.c,v
retrieving revision 1.2
diff -u -p -u -p -r1.2 openvz_driver.c
--- src/openvz_driver.c 19 Jul 2007 16:22:40 -0000 1.2
+++ src/openvz_driver.c 25 Jul 2007 14:28:12 -0000
@@ -55,12 +55,14 @@
#include "util.h"
#include "openvz_driver.h"
#include "openvz_conf.h"
+#include "nodeinfo.h"
#define openvzLog(level, msg...) fprintf(stderr, msg)
static virDomainPtr openvzDomainLookupByID(virConnectPtr conn, int id);
static char *openvzGetOSType(virDomainPtr dom);
+static int openvzGetNodeInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo);
static virDomainPtr openvzDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid);
static virDomainPtr openvzDomainLookupByName(virConnectPtr conn, const char *name);
static int openvzDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info);
@@ -327,6 +329,12 @@ static const char *openvzGetType(virConn
}
+static int openvzGetNodeInfo(virConnectPtr conn,
+ virNodeInfoPtr nodeinfo) {
+ return virNodeInfoPopulate(conn, nodeinfo);
+}
+
+
static int openvzListDomains(virConnectPtr conn, int *ids, int nids) {
int got = 0;
int veid, pid, outfd, errfd;
@@ -431,7 +439,7 @@ static virDriver openvzDriver = {
NULL, /* hostname */
NULL, /* uri */
NULL, /* getMaxVcpus */
- NULL, /* nodeGetInfo */
+ openvzGetNodeInfo, /* nodeGetInfo */
NULL, /* getCapabilities */
openvzListDomains, /* listDomains */
openvzNumDomains, /* numOfDomains */
Index: src/qemu_driver.c
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_driver.c,v
retrieving revision 1.11
diff -u -p -u -p -r1.11 qemu_driver.c
--- src/qemu_driver.c 24 Jul 2007 14:24:52 -0000 1.11
+++ src/qemu_driver.c 25 Jul 2007 14:28:12 -0000
@@ -53,6 +53,7 @@
#include "util.h"
#include "qemu_driver.h"
#include "qemu_conf.h"
+#include "nodeinfo.h"
static int qemudShutdown(void);
@@ -1358,81 +1359,6 @@ static int qemudMonitorCommand(struct qe
}
-static int qemudGetMemInfo(unsigned long *memory) {
- FILE *meminfo = fopen("/proc/meminfo", "r");
- char line[1024];
-
- *memory = 0;
-
- if (!meminfo) {
- return -1;
- }
-
- /* XXX NUMA and hyperthreads ? */
- while (fgets(line, sizeof(line), meminfo) != NULL) {
- if (!strncmp(line, "MemTotal:", 9)) {
- *memory = (unsigned int)strtol(line + 10, NULL, 10);
- }
- }
- fclose(meminfo);
- return 0;
-}
-
-static int qemudGetCPUInfo(unsigned int *cpus, unsigned int *mhz,
- unsigned int *nodes, unsigned int *sockets,
- unsigned int *cores, unsigned int *threads) {
- FILE *cpuinfo = fopen("/proc/cpuinfo", "r");
- char line[1024];
-
- *cpus = 0;
- *mhz = 0;
- *nodes = *sockets = *cores = *threads = 1;
-
- if (!cpuinfo) {
- return -1;
- }
-
- /* XXX NUMA and hyperthreads ? */
- while (fgets(line, sizeof(line), cpuinfo) != NULL) {
- if (!strncmp(line, "processor\t", 10)) { /* aka a single logical CPU */
- (*cpus)++;
- } else if (!strncmp(line, "cpu MHz\t", 8)) {
- char *offset = strchr(line, ':');
- if (!offset)
- continue;
- offset++;
- if (!*offset)
- continue;
- *mhz = (unsigned int)strtol(offset, NULL, 10);
- } else if (!strncmp(line, "physical id\t", 12)) { /* aka socket */
- unsigned int id;
- char *offset = strchr(line, ':');
- if (!offset)
- continue;
- offset++;
- if (!*offset)
- continue;
- id = (unsigned int)strtol(offset, NULL, 10);
- if ((id+1) > *sockets)
- *sockets = (id + 1);
- } else if (!strncmp(line, "cpu cores\t", 9)) { /* aka cores */
- unsigned int id;
- char *offset = strchr(line, ':');
- if (!offset)
- continue;
- offset++;
- if (!*offset)
- continue;
- id = (unsigned int)strtol(offset, NULL, 10);
- if (id > *cores)
- *cores = id;
- }
- }
- fclose(cpuinfo);
-
- return 0;
-}
-
static virDrvOpenStatus qemudOpen(virConnectPtr conn,
const char *name,
int flags ATTRIBUTE_UNUSED) {
@@ -1485,23 +1411,9 @@ static int qemudGetMaxVCPUs(virConnectPt
return -1;
}
-static int qemudGetNodeInfo(virConnectPtr conn ATTRIBUTE_UNUSED,
- virNodeInfoPtr node) {
- struct utsname info;
-
- if (uname(&info) < 0)
- return -1;
-
- strncpy(node->model, info.machine, sizeof(node->model)-1);
- node->model[sizeof(node->model)-1] = '\0';
-
- if (qemudGetMemInfo(&(node->memory)) < 0)
- return -1;
-
- if (qemudGetCPUInfo(&(node->cpus), &(node->mhz), &(node->nodes),
- &(node->sockets), &(node->cores), &(node->threads)) < 0)
- return -1;
- return 0;
+static int qemudGetNodeInfo(virConnectPtr conn,
+ virNodeInfoPtr nodeinfo) {
+ return virNodeInfoPopulate(conn, nodeinfo);
}
static char *qemudGetCapabilities(virConnectPtr conn ATTRIBUTE_UNUSED) {
? tests/nodeinfodata
? tests/nodeinfotest
Index: tests/Makefile.am
===================================================================
RCS file: /data/cvs/libvirt/tests/Makefile.am,v
retrieving revision 1.21
diff -u -p -u -p -r1.21 Makefile.am
--- tests/Makefile.am 18 Jul 2007 21:34:22 -0000 1.21
+++ tests/Makefile.am 25 Jul 2007 14:28:21 -0000
@@ -32,10 +32,11 @@ LDADDS = \
EXTRA_DIST = xmlrpcserver.py test_conf.sh
noinst_PROGRAMS = xmlrpctest xml2sexprtest sexpr2xmltest virshtest conftest \
- reconnect xmconfigtest xencapstest qemuxml2argvtest qemuxml2xmltest
+ reconnect xmconfigtest xencapstest qemuxml2argvtest qemuxml2xmltest \
+ nodeinfotest
TESTS = xml2sexprtest sexpr2xmltest virshtest test_conf.sh xmconfigtest \
- xencapstest qemuxml2argvtest qemuxml2xmltest
+ xencapstest qemuxml2argvtest qemuxml2xmltest nodeinfotest
if ENABLE_XEN_TESTS
TESTS += reconnect
endif
@@ -99,6 +100,11 @@ xencapstest_SOURCES = \
xencapstest_LDFLAGS =
xencapstest_LDADD = $(LDADDS)
+nodeinfotest_SOURCES = \
+ nodeinfotest.c testutils.h testutils.c
+nodeinfotest_LDFLAGS =
+nodeinfotest_LDADD = $(LDADDS)
+
reconnect_SOURCES = \
reconnect.c
reconnect_LDFLAGS =
Index: tests/nodeinfotest.c
===================================================================
RCS file: tests/nodeinfotest.c
diff -N tests/nodeinfotest.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/nodeinfotest.c 25 Jul 2007 14:28:21 -0000
@@ -0,0 +1,117 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "config.h"
+
+#include <string.h>
+
+#include "testutils.h"
+#include "internal.h"
+#include "nodeinfo.h"
+
+static char *progname;
+
+#define MAX_FILE 4096
+
+#ifdef __linux__
+
+extern int linuxNodeInfoCPUPopulate(virConnectPtr conn, FILE *cpuinfo, virNodeInfoPtr nodeinfo);
+extern int linuxNodeInfoMemPopulate(virConnectPtr conn, FILE *meminfo, virNodeInfoPtr nodeinfo);
+
+static int linuxTestCompareFiles(const char *cpuinfofile, const char *meminfofile, const char *outputfile) {
+ char actualData[MAX_FILE];
+ char expectData[MAX_FILE];
+ char *expect = &expectData[0];
+ virNodeInfo nodeinfo;
+ FILE *cpuinfo, *meminfo;
+
+ if (virtTestLoadFile(outputfile, &expect, MAX_FILE) < 0)
+ return -1;
+
+ cpuinfo = fopen(cpuinfofile, "r");
+ if (!cpuinfo)
+ return -1;
+ if (linuxNodeInfoCPUPopulate(NULL, cpuinfo, &nodeinfo) < 0) {
+ fclose(cpuinfo);
+ return -1;
+ }
+ fclose(cpuinfo);
+
+ meminfo = fopen(meminfofile, "r");
+ if (!meminfo)
+ return -1;
+ if (linuxNodeInfoMemPopulate(NULL, meminfo, &nodeinfo) < 0) {
+ fclose(meminfo);
+ return -1;
+ }
+ fclose(meminfo);
+
+ snprintf(actualData, MAX_FILE,
+ "CPUs: %u, MHz: %u, Nodes: %u, Sockets: %u, Cores: %u, Threads: %u, Memory: %lu\n",
+ nodeinfo.cpus, nodeinfo.mhz, nodeinfo.nodes, nodeinfo.sockets,
+ nodeinfo.cores, nodeinfo.threads, nodeinfo.memory);
+
+ if (STRNEQ(actualData, expectData)) {
+ if (getenv("DEBUG_TESTS")) {
+ printf("Expect %d '%s'\n", (int)strlen(expectData), expectData);
+ printf("Actual %d '%s'\n", (int)strlen(actualData), actualData);
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int linuxTestNodeInfo(const void *data) {
+ char cpuinfo[PATH_MAX];
+ char meminfo[PATH_MAX];
+ char output[PATH_MAX];
+ snprintf(cpuinfo, PATH_MAX, "nodeinfodata/linux-%s.cpuinfo", (const char*)data);
+ snprintf(meminfo, PATH_MAX, "nodeinfodata/linux-%s.meminfo", (const char*)data);
+ snprintf(output, PATH_MAX, "nodeinfodata/linux-%s.txt", (const char*)data);
+ return linuxTestCompareFiles(cpuinfo, meminfo, output);
+}
+#endif
+
+
+int
+main(int argc, char **argv)
+{
+ int ret = 0;
+#ifdef __linux__
+ int i;
+ const char *nodeData[] = {
+ "nodeinfo-1",
+ "nodeinfo-2",
+ "nodeinfo-3",
+ "nodeinfo-4",
+ "nodeinfo-5",
+ "nodeinfo-6",
+ };
+
+ progname = argv[0];
+
+ if (argc > 1) {
+ fprintf(stderr, "Usage: %s\n", progname);
+ exit(EXIT_FAILURE);
+ }
+
+ virInitialize();
+
+ for (i = 0 ; i < (sizeof(nodeData)/sizeof(nodeData[0])) ; i++)
+ if (virtTestRun(nodeData[i], 1, linuxTestNodeInfo, nodeData[i]) != 0)
+ ret = -1;
+#endif
+
+ exit(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
More information about the libvir-list
mailing list