[libvirt] [PATCH v3 0/5] Support of auto-dump on watchdog event in libvirtd
by Hu Tao
This patch series adds a new watchdog action `dump' which lets libvirtd
can do auto-dump when receiving a watchdog event from qemu guest.
In order to make the function work, there must be a watchdog device
added to guest, and guest must have a watchdog daemon running, for
example, /etc/init.d/watchdog start or auto-started on boot.
Changes from v2:
- let default auto-dump dir be /var/lib/libvirt/qemu/dump
Hu Tao (5):
Add a threadpool implementation
Fall back to QEMUD_SAVE_FORMAT_RAW if compression method fails.
Add a new function doCoreDump
Add a watchdog action `dump'
Add me to AUTHORS to make `make syntax-check' happy
AUTHORS | 1 +
src/Makefile.am | 3 +-
src/conf/domain_conf.c | 1 +
src/conf/domain_conf.h | 1 +
src/qemu/qemu.conf | 5 +
src/qemu/qemu_conf.c | 13 +++-
src/qemu/qemu_conf.h | 4 +
src/qemu/qemu_driver.c | 235 ++++++++++++++++++++++++++++++++++--------------
src/util/threadpool.c | 140 ++++++++++++++++++++++++++++
src/util/threadpool.h | 35 +++++++
10 files changed, 367 insertions(+), 71 deletions(-)
create mode 100644 src/util/threadpool.c
create mode 100644 src/util/threadpool.h
--
1.7.3
--
Thanks,
Hu Tao
13 years, 11 months
[libvirt] CGROUPS network classID setting in domain
by D. Herrendoerfer
Hello,
I'm looking into the possibility of putting a network(tc) classID into
to the domain description and adding it into a (possibly) mounted
cgroup directory upon launch of a VM.
Has anyone before looked into this ?
I've seen this mentioned in an abstract by Daniel B.
I imagine a classid entry to look somewhat like:
<domain type='qemu'>
<name > foo</name>
<uuid>3e3fce45-4f53-4fa7-bb32-11f34168b82b </uuid>
...
<classid>0x1234</classid>
...
Thoughts ?
Best regards,
D. Herrendoerfer
13 years, 11 months
[libvirt] [PATCH 0/2] Add unit tests for internal CPU APIs
by Jiri Denemark
*** BLURB HERE ***
Jiri Denemark (2):
cpu: Add support for overriding path to CPU map XML file
tests: Add unit tests for internal CPU APIs
src/cpu/cpu_map.c | 21 +-
src/cpu/cpu_map.h | 3 +
src/libvirt_private.syms | 1 +
tests/Makefile.am | 12 +-
tests/cputest.c | 610 ++++++++++++++++++++
tests/cputestdata/x86-baseline-1-result.xml | 5 +
tests/cputestdata/x86-baseline-1.xml | 20 +
tests/cputestdata/x86-baseline-2-result.xml | 4 +
tests/cputestdata/x86-baseline-2.xml | 22 +
.../x86-baseline-incompatible-vendors.xml | 14 +
.../cputestdata/x86-baseline-no-vendor-result.xml | 5 +
tests/cputestdata/x86-baseline-no-vendor.xml | 12 +
.../x86-baseline-some-vendors-result.xml | 3 +
tests/cputestdata/x86-baseline-some-vendors.xml | 13 +
tests/cputestdata/x86-bogus-feature.xml | 4 +
tests/cputestdata/x86-bogus-model.xml | 3 +
tests/cputestdata/x86-bogus-vendor.xml | 4 +
tests/cputestdata/x86-exact-disable-extra.xml | 4 +
tests/cputestdata/x86-exact-disable.xml | 4 +
tests/cputestdata/x86-exact-disable2.xml | 5 +
tests/cputestdata/x86-exact-forbid-extra.xml | 4 +
tests/cputestdata/x86-exact-forbid.xml | 4 +
tests/cputestdata/x86-exact-force.xml | 4 +
tests/cputestdata/x86-exact-require-extra.xml | 4 +
tests/cputestdata/x86-exact-require.xml | 4 +
tests/cputestdata/x86-exact.xml | 3 +
tests/cputestdata/x86-guest.xml | 18 +
.../cputestdata/x86-host+guest,model486-result.xml | 37 ++
.../x86-host+guest,models,Penryn-result.xml | 13 +
.../x86-host+guest,models,qemu64-result.xml | 14 +
tests/cputestdata/x86-host+guest,models-result.xml | 13 +
tests/cputestdata/x86-host+guest-result.xml | 11 +
tests/cputestdata/x86-host+guest.xml | 17 +
tests/cputestdata/x86-host+min.xml | 17 +
.../cputestdata/x86-host+nehalem-force-result.xml | 4 +
tests/cputestdata/x86-host+pentium3.xml | 27 +
.../x86-host+strict-force-extra-result.xml | 19 +
tests/cputestdata/x86-host-amd-fake.xml | 20 +
tests/cputestdata/x86-host-amd.xml | 18 +
.../x86-host-better+pentium3,core2duo-result.xml | 21 +
.../x86-host-better+pentium3,pentium3-result.xml | 30 +
.../x86-host-better+pentium3-result.xml | 18 +
tests/cputestdata/x86-host-better.xml | 20 +
tests/cputestdata/x86-host-incomp-arch.xml | 6 +
tests/cputestdata/x86-host-no-vendor.xml | 19 +
tests/cputestdata/x86-host-worse+guest-result.xml | 9 +
tests/cputestdata/x86-host-worse.xml | 6 +
tests/cputestdata/x86-host.xml | 20 +
tests/cputestdata/x86-min.xml | 3 +
tests/cputestdata/x86-nehalem-force.xml | 6 +
tests/cputestdata/x86-pentium3-amd.xml | 4 +
tests/cputestdata/x86-pentium3.xml | 3 +
tests/cputestdata/x86-strict-disable.xml | 18 +
tests/cputestdata/x86-strict-force-extra.xml | 18 +
tests/cputestdata/x86-strict-full.xml | 17 +
tests/cputestdata/x86-strict.xml | 3 +
56 files changed, 1238 insertions(+), 3 deletions(-)
create mode 100644 tests/cputest.c
create mode 100644 tests/cputestdata/x86-baseline-1-result.xml
create mode 100644 tests/cputestdata/x86-baseline-1.xml
create mode 100644 tests/cputestdata/x86-baseline-2-result.xml
create mode 100644 tests/cputestdata/x86-baseline-2.xml
create mode 100644 tests/cputestdata/x86-baseline-incompatible-vendors.xml
create mode 100644 tests/cputestdata/x86-baseline-no-vendor-result.xml
create mode 100644 tests/cputestdata/x86-baseline-no-vendor.xml
create mode 100644 tests/cputestdata/x86-baseline-some-vendors-result.xml
create mode 100644 tests/cputestdata/x86-baseline-some-vendors.xml
create mode 100644 tests/cputestdata/x86-bogus-feature.xml
create mode 100644 tests/cputestdata/x86-bogus-model.xml
create mode 100644 tests/cputestdata/x86-bogus-vendor.xml
create mode 100644 tests/cputestdata/x86-exact-disable-extra.xml
create mode 100644 tests/cputestdata/x86-exact-disable.xml
create mode 100644 tests/cputestdata/x86-exact-disable2.xml
create mode 100644 tests/cputestdata/x86-exact-forbid-extra.xml
create mode 100644 tests/cputestdata/x86-exact-forbid.xml
create mode 100644 tests/cputestdata/x86-exact-force.xml
create mode 100644 tests/cputestdata/x86-exact-require-extra.xml
create mode 100644 tests/cputestdata/x86-exact-require.xml
create mode 100644 tests/cputestdata/x86-exact.xml
create mode 100644 tests/cputestdata/x86-guest.xml
create mode 100644 tests/cputestdata/x86-host+guest,model486-result.xml
create mode 100644 tests/cputestdata/x86-host+guest,models,Penryn-result.xml
create mode 100644 tests/cputestdata/x86-host+guest,models,qemu64-result.xml
create mode 100644 tests/cputestdata/x86-host+guest,models-result.xml
create mode 100644 tests/cputestdata/x86-host+guest-result.xml
create mode 100644 tests/cputestdata/x86-host+guest.xml
create mode 100644 tests/cputestdata/x86-host+min.xml
create mode 100644 tests/cputestdata/x86-host+nehalem-force-result.xml
create mode 100644 tests/cputestdata/x86-host+pentium3.xml
create mode 100644 tests/cputestdata/x86-host+strict-force-extra-result.xml
create mode 100644 tests/cputestdata/x86-host-amd-fake.xml
create mode 100644 tests/cputestdata/x86-host-amd.xml
create mode 100644 tests/cputestdata/x86-host-better+pentium3,core2duo-result.xml
create mode 100644 tests/cputestdata/x86-host-better+pentium3,pentium3-result.xml
create mode 100644 tests/cputestdata/x86-host-better+pentium3-result.xml
create mode 100644 tests/cputestdata/x86-host-better.xml
create mode 100644 tests/cputestdata/x86-host-incomp-arch.xml
create mode 100644 tests/cputestdata/x86-host-no-vendor.xml
create mode 100644 tests/cputestdata/x86-host-worse+guest-result.xml
create mode 100644 tests/cputestdata/x86-host-worse.xml
create mode 100644 tests/cputestdata/x86-host.xml
create mode 100644 tests/cputestdata/x86-min.xml
create mode 100644 tests/cputestdata/x86-nehalem-force.xml
create mode 100644 tests/cputestdata/x86-pentium3-amd.xml
create mode 100644 tests/cputestdata/x86-pentium3.xml
create mode 100644 tests/cputestdata/x86-strict-disable.xml
create mode 100644 tests/cputestdata/x86-strict-force-extra.xml
create mode 100644 tests/cputestdata/x86-strict-full.xml
create mode 100644 tests/cputestdata/x86-strict.xml
--
1.7.3.2
13 years, 11 months
[libvirt] [v3] virsh: Categorize commands into groups for virsh help
by Osier Yang
Change the virsh help out. The new output of "virsh help" and
"virsh --help" will be like:
Secret (help keyword 'secret'):
secret-define define or modify a secret from an XML file
secret-dumpxml secret attributes in XML
secret-set-value set a secret value
secret-get-value Output a secret value
secret-undefine undefine a secret
secret-list list secrets
Snapshot (help keyword 'snapshot'):
snapshot-create Create a snapshot
snapshot-current Get the current snapshot
snapshot-delete Delete a domain snapshot
snapshot-dumpxml Dump XML for a domain snapshot
snapshot-list List snapshots for a domain
snapshot-revert Revert a domain to a snapshot
Also support output help information of specified command group, e.g.
% ./tools/virsh help "Network Filter"
Network Filter (help keyword 'filter'):
nwfilter-define define or update a network filter from an XML file
nwfilter-undefine undefine a network filter
nwfilter-dumpxml network filter information in XML
nwfilter-list list network filters
nwfilter-edit edit XML configuration for a network filter
Each group has a help keyword, e.g.
% ./tools/virsh help filter
Network Filter (help keyword 'filter'):
nwfilter-define define or update a network filter from an XML file
nwfilter-undefine undefine a network filter
nwfilter-dumpxml network filter information in XML
nwfilter-list list network filters
nwfilter-edit edit XML configuration for a network filter
* tools/virsh.c:
- introduce new struct "vshCmdGrp" and macros to define the groups.
- split previous array "commands" into small arrays which are orgnized
by group
- changed some functions, e.g. "vshCmdDefSearch"
- Added new functions, e.g. "vshCmdGrpSearch"
- commands of each group are in "alphabetical order" now.
- command groups are in "alphabetical order" now.
- the commands are categorized with reference of
http://wiki.libvirt.org/page/VirshHelpV2 (by Justin)
- the modifications doesn't affect tests
* TODO:
- doc
---
tools/virsh.c | 414 ++++++++++++++++++++++++++++++++++++++------------------
1 files changed, 281 insertions(+), 133 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index aec7749..17dd524 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -131,6 +131,22 @@ typedef enum {
} vshCmdOptType;
/*
+ * Command group types
+ */
+#define VSH_CMD_GRP_DOM_MANAGEMENT "Domain Management"
+#define VSH_CMD_GRP_DOM_MONITORING "Domain Monitoring"
+#define VSH_CMD_GRP_STORAGE_POOL "Storage Pool"
+#define VSH_CMD_GRP_STORAGE_VOL "Storage Volume"
+#define VSH_CMD_GRP_NETWORK "Networking"
+#define VSH_CMD_GRP_NODEDEV "Node Device"
+#define VSH_CMD_GRP_IFACE "Interface"
+#define VSH_CMD_GRP_NWFILTER "Network Filter"
+#define VSH_CMD_GRP_SECRET "Secret"
+#define VSH_CMD_GRP_SNAPSHOT "Snapshot"
+#define VSH_CMD_GRP_HOST_AND_HV "Host and Hypervisor"
+#define VSH_CMD_GRP_VIRSH "Virsh itself"
+
+/*
* Command Option Flags
*/
#define VSH_OFLAG_NONE 0 /* without flags */
@@ -207,8 +223,13 @@ typedef struct __vshControl {
char *historyfile; /* readline history file name */
} __vshControl;
+typedef struct vshCmdGrp {
+ const char *name;
+ const char *keyword; /* help keyword */
+ const vshCmdDef *commands;
+} vshCmdGrp;
-static const vshCmdDef commands[];
+static const vshCmdGrp cmdGroups[];
static void vshError(vshControl *ctl, const char *format, ...)
ATTRIBUTE_FMT_PRINTF(2, 3);
@@ -224,6 +245,8 @@ static int vshParseArgv(vshControl *ctl, int argc, char **argv);
static const char *vshCmddefGetInfo(const vshCmdDef *cmd, const char *info);
static const vshCmdDef *vshCmddefSearch(const char *cmdname);
static int vshCmddefHelp(vshControl *ctl, const char *name);
+static const vshCmdGrp *vshCmdGrpSearch(const char *grpname);
+static int vshCmdGrpHelp(vshControl *ctl, const char *name);
static vshCmdOpt *vshCommandOpt(const vshCmd *cmd, const char *name);
static int vshCommandOptInt(const vshCmd *cmd, const char *name, int *found);
@@ -551,19 +574,39 @@ static const vshCmdOptDef opts_help[] = {
static int
cmdHelp(vshControl *ctl, const vshCmd *cmd)
-{
- const char *cmdname = vshCommandOptString(cmd, "command", NULL);
+ {
+ const vshCmdDef *c;
+ const vshCmdGrp *g;
+ const char *name = vshCommandOptString(cmd, "command", NULL);
- if (!cmdname) {
+ if (!name) {
+ const vshCmdGrp *grp;
const vshCmdDef *def;
- vshPrint(ctl, "%s", _("Commands:\n\n"));
- for (def = commands; def->name; def++)
- vshPrint(ctl, " %-15s %s\n", def->name,
- _(vshCmddefGetInfo(def, "help")));
- return TRUE;
+ vshPrint(ctl, "%s", _("Grouped commands:\n\n"));
+
+ for (grp = cmdGroups; grp->name; grp++) {
+ vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name,
+ grp->keyword);
+
+ for (def = grp->commands; def->name; def++)
+ vshPrint(ctl, " %-30s %s\n", def->name,
+ _(vshCmddefGetInfo(def, "help")));
+
+ vshPrint(ctl, "\n");
+ }
+
+ return TRUE;
+ }
+
+ if ((c = vshCmddefSearch(name))) {
+ return vshCmddefHelp(ctl, name);
+ } else if ((g = vshCmdGrpSearch(name))) {
+ return vshCmdGrpHelp(ctl, name);
+ } else {
+ vshError(ctl, _("command or command group '%s' doesn't exist"), name);
+ return FALSE;
}
- return vshCmddefHelp(ctl, cmdname);
}
/*
@@ -9880,60 +9923,117 @@ cleanup:
return ret;
}
-
-/*
- * Commands
- */
-static const vshCmdDef commands[] = {
- {"help", cmdHelp, opts_help, info_help},
+static const vshCmdDef domManagementCmds[] = {
{"attach-device", cmdAttachDevice, opts_attach_device, info_attach_device},
{"attach-disk", cmdAttachDisk, opts_attach_disk, info_attach_disk},
{"attach-interface", cmdAttachInterface, opts_attach_interface, info_attach_interface},
{"autostart", cmdAutostart, opts_autostart, info_autostart},
- {"capabilities", cmdCapabilities, NULL, info_capabilities},
-#ifndef WIN32
- {"cd", cmdCd, opts_cd, info_cd},
-#endif
- {"connect", cmdConnect, opts_connect, info_connect},
#ifndef WIN32
{"console", cmdConsole, opts_console, info_console},
#endif
{"cpu-baseline", cmdCPUBaseline, opts_cpu_baseline, info_cpu_baseline},
{"cpu-compare", cmdCPUCompare, opts_cpu_compare, info_cpu_compare},
{"create", cmdCreate, opts_create, info_create},
- {"start", cmdStart, opts_start, info_start},
+ {"define", cmdDefine, opts_define, info_define},
{"destroy", cmdDestroy, opts_destroy, info_destroy},
{"detach-device", cmdDetachDevice, opts_detach_device, info_detach_device},
{"detach-disk", cmdDetachDisk, opts_detach_disk, info_detach_disk},
{"detach-interface", cmdDetachInterface, opts_detach_interface, info_detach_interface},
- {"define", cmdDefine, opts_define, info_define},
{"domid", cmdDomid, opts_domid, info_domid},
- {"domuuid", cmdDomuuid, opts_domuuid, info_domuuid},
- {"dominfo", cmdDominfo, opts_dominfo, info_dominfo},
- {"domjobinfo", cmdDomjobinfo, opts_domjobinfo, info_domjobinfo},
{"domjobabort", cmdDomjobabort, opts_domjobabort, info_domjobabort},
+ {"domjobinfo", cmdDomjobinfo, opts_domjobinfo, info_domjobinfo},
{"domname", cmdDomname, opts_domname, info_domname},
- {"domstate", cmdDomstate, opts_domstate, info_domstate},
- {"domblkstat", cmdDomblkstat, opts_domblkstat, info_domblkstat},
- {"domifstat", cmdDomIfstat, opts_domifstat, info_domifstat},
- {"dommemstat", cmdDomMemStat, opts_dommemstat, info_dommemstat},
- {"domblkinfo", cmdDomblkinfo, opts_domblkinfo, info_domblkinfo},
+ {"domuuid", cmdDomuuid, opts_domuuid, info_domuuid},
{"domxml-from-native", cmdDomXMLFromNative, opts_domxmlfromnative, info_domxmlfromnative},
{"domxml-to-native", cmdDomXMLToNative, opts_domxmltonative, info_domxmltonative},
+ {"dump", cmdDump, opts_dump, info_dump},
{"dumpxml", cmdDumpXML, opts_dumpxml, info_dumpxml},
{"echo", cmdEcho, opts_echo, info_echo},
{"edit", cmdEdit, opts_edit, info_edit},
- {"find-storage-pool-sources", cmdPoolDiscoverSources,
- opts_find_storage_pool_sources, info_find_storage_pool_sources},
{"find-storage-pool-sources-as", cmdPoolDiscoverSourcesAs,
opts_find_storage_pool_sources_as, info_find_storage_pool_sources_as},
+ {"find-storage-pool-sources", cmdPoolDiscoverSources,
+ opts_find_storage_pool_sources, info_find_storage_pool_sources},
{"freecell", cmdFreecell, opts_freecell, info_freecell},
{"hostname", cmdHostname, NULL, info_hostname},
- {"list", cmdList, opts_list, info_list},
+ {"managedsave", cmdManagedSave, opts_managedsave, info_managedsave},
+ {"managedsave-remove", cmdManagedSaveRemove, opts_managedsaveremove, info_managedsaveremove},
{"maxvcpus", cmdMaxvcpus, opts_maxvcpus, info_maxvcpus},
+ {"memtune", cmdMemtune, opts_memtune, info_memtune},
{"migrate", cmdMigrate, opts_migrate, info_migrate},
{"migrate-setmaxdowntime", cmdMigrateSetMaxDowntime, opts_migrate_setmaxdowntime, info_migrate_setmaxdowntime},
+ {"reboot", cmdReboot, opts_reboot, info_reboot},
+ {"restore", cmdRestore, opts_restore, info_restore},
+ {"resume", cmdResume, opts_resume, info_resume},
+ {"save", cmdSave, opts_save, info_save},
+ {"schedinfo", cmdSchedinfo, opts_schedinfo, info_schedinfo},
+ {"setmaxmem", cmdSetmaxmem, opts_setmaxmem, info_setmaxmem},
+ {"setmem", cmdSetmem, opts_setmem, info_setmem},
+ {"setvcpus", cmdSetvcpus, opts_setvcpus, info_setvcpus},
+ {"shutdown", cmdShutdown, opts_shutdown, info_shutdown},
+ {"start", cmdStart, opts_start, info_start},
+ {"suspend", cmdSuspend, opts_suspend, info_suspend},
+ {"ttyconsole", cmdTTYConsole, opts_ttyconsole, info_ttyconsole},
+ {"undefine", cmdUndefine, opts_undefine, info_undefine},
+ {"update-device", cmdUpdateDevice, opts_update_device, info_update_device},
+ {"vcpucount", cmdVcpucount, opts_vcpucount, info_vcpucount},
+ {"vcpuinfo", cmdVcpuinfo, opts_vcpuinfo, info_vcpuinfo},
+ {"vcpupin", cmdVcpupin, opts_vcpupin, info_vcpupin},
+ {"version", cmdVersion, NULL, info_version},
+ {"vncdisplay", cmdVNCDisplay, opts_vncdisplay, info_vncdisplay},
+ {NULL, NULL, NULL, NULL}
+};
+
+static const vshCmdDef domMonitoringCmds[] = {
+ {"domblkinfo", cmdDomblkinfo, opts_domblkinfo, info_domblkinfo},
+ {"domblkstat", cmdDomblkstat, opts_domblkstat, info_domblkstat},
+ {"domifstat", cmdDomIfstat, opts_domifstat, info_domifstat},
+ {"dominfo", cmdDominfo, opts_dominfo, info_dominfo},
+ {"dommemstat", cmdDomMemStat, opts_dommemstat, info_dommemstat},
+ {"domstate", cmdDomstate, opts_domstate, info_domstate},
+ {"list", cmdList, opts_list, info_list},
+ {NULL, NULL, NULL, NULL}
+};
+
+static const vshCmdDef storagePoolCmds[] = {
+ {"pool-autostart", cmdPoolAutostart, opts_pool_autostart, info_pool_autostart},
+ {"pool-build", cmdPoolBuild, opts_pool_build, info_pool_build},
+ {"pool-create-as", cmdPoolCreateAs, opts_pool_X_as, info_pool_create_as},
+ {"pool-create", cmdPoolCreate, opts_pool_create, info_pool_create},
+ {"pool-define-as", cmdPoolDefineAs, opts_pool_X_as, info_pool_define_as},
+ {"pool-define", cmdPoolDefine, opts_pool_define, info_pool_define},
+ {"pool-delete", cmdPoolDelete, opts_pool_delete, info_pool_delete},
+ {"pool-destroy", cmdPoolDestroy, opts_pool_destroy, info_pool_destroy},
+ {"pool-dumpxml", cmdPoolDumpXML, opts_pool_dumpxml, info_pool_dumpxml},
+ {"pool-edit", cmdPoolEdit, opts_pool_edit, info_pool_edit},
+ {"pool-info", cmdPoolInfo, opts_pool_info, info_pool_info},
+ {"pool-list", cmdPoolList, opts_pool_list, info_pool_list},
+ {"pool-name", cmdPoolName, opts_pool_name, info_pool_name},
+ {"pool-refresh", cmdPoolRefresh, opts_pool_refresh, info_pool_refresh},
+ {"pool-start", cmdPoolStart, opts_pool_start, info_pool_start},
+ {"pool-undefine", cmdPoolUndefine, opts_pool_undefine, info_pool_undefine},
+ {"pool-uuid", cmdPoolUuid, opts_pool_uuid, info_pool_uuid},
+ {NULL, NULL, NULL, NULL}
+};
+
+static const vshCmdDef storageVolCmds[] = {
+ {"vol-clone", cmdVolClone, opts_vol_clone, info_vol_clone},
+ {"vol-create-as", cmdVolCreateAs, opts_vol_create_as, info_vol_create_as},
+ {"vol-create", cmdVolCreate, opts_vol_create, info_vol_create},
+ {"vol-create-from", cmdVolCreateFrom, opts_vol_create_from, info_vol_create_from},
+ {"vol-delete", cmdVolDelete, opts_vol_delete, info_vol_delete},
+ {"vol-dumpxml", cmdVolDumpXML, opts_vol_dumpxml, info_vol_dumpxml},
+ {"vol-info", cmdVolInfo, opts_vol_info, info_vol_info},
+ {"vol-key", cmdVolKey, opts_vol_key, info_vol_key},
+ {"vol-list", cmdVolList, opts_vol_list, info_vol_list},
+ {"vol-name", cmdVolName, opts_vol_name, info_vol_name},
+ {"vol-path", cmdVolPath, opts_vol_path, info_vol_path},
+ {"vol-pool", cmdVolPool, opts_vol_pool, info_vol_pool},
+ {"vol-wipe", cmdVolWipe, opts_vol_wipe, info_vol_wipe},
+ {NULL, NULL, NULL, NULL}
+};
+static const vshCmdDef networkCmds[] = {
{"net-autostart", cmdNetworkAutostart, opts_network_autostart, info_network_autostart},
{"net-create", cmdNetworkCreate, opts_network_create, info_network_create},
{"net-define", cmdNetworkDefine, opts_network_define, info_network_define},
@@ -9946,116 +10046,104 @@ static const vshCmdDef commands[] = {
{"net-start", cmdNetworkStart, opts_network_start, info_network_start},
{"net-undefine", cmdNetworkUndefine, opts_network_undefine, info_network_undefine},
{"net-uuid", cmdNetworkUuid, opts_network_uuid, info_network_uuid},
+ {NULL, NULL, NULL, NULL}
+};
- {"iface-list", cmdInterfaceList, opts_interface_list, info_interface_list},
- {"iface-name", cmdInterfaceName, opts_interface_name, info_interface_name},
- {"iface-mac", cmdInterfaceMAC, opts_interface_mac, info_interface_mac},
- {"iface-dumpxml", cmdInterfaceDumpXML, opts_interface_dumpxml, info_interface_dumpxml},
- {"iface-define", cmdInterfaceDefine, opts_interface_define, info_interface_define},
- {"iface-undefine", cmdInterfaceUndefine, opts_interface_undefine, info_interface_undefine},
- {"iface-edit", cmdInterfaceEdit, opts_interface_edit, info_interface_edit},
- {"iface-start", cmdInterfaceStart, opts_interface_start, info_interface_start},
- {"iface-destroy", cmdInterfaceDestroy, opts_interface_destroy, info_interface_destroy},
-
- {"managedsave", cmdManagedSave, opts_managedsave, info_managedsave},
- {"managedsave-remove", cmdManagedSaveRemove, opts_managedsaveremove, info_managedsaveremove},
-
- {"nodeinfo", cmdNodeinfo, NULL, info_nodeinfo},
-
- {"nodedev-list", cmdNodeListDevices, opts_node_list_devices, info_node_list_devices},
- {"nodedev-dumpxml", cmdNodeDeviceDumpXML, opts_node_device_dumpxml, info_node_device_dumpxml},
+static const vshCmdDef nodedevCmds[] = {
+ {"nodedev-create", cmdNodeDeviceCreate, opts_node_device_create, info_node_device_create},
+ {"nodedev-destroy", cmdNodeDeviceDestroy, opts_node_device_destroy, info_node_device_destroy},
{"nodedev-dettach", cmdNodeDeviceDettach, opts_node_device_dettach, info_node_device_dettach},
+ {"nodedev-dumpxml", cmdNodeDeviceDumpXML, opts_node_device_dumpxml, info_node_device_dumpxml},
+ {"nodedev-list", cmdNodeListDevices, opts_node_list_devices, info_node_list_devices},
{"nodedev-reattach", cmdNodeDeviceReAttach, opts_node_device_reattach, info_node_device_reattach},
{"nodedev-reset", cmdNodeDeviceReset, opts_node_device_reset, info_node_device_reset},
- {"nodedev-create", cmdNodeDeviceCreate, opts_node_device_create, info_node_device_create},
- {"nodedev-destroy", cmdNodeDeviceDestroy, opts_node_device_destroy, info_node_device_destroy},
+ {"nodeinfo", cmdNodeinfo, NULL, info_nodeinfo},
+ {NULL, NULL, NULL, NULL}
+};
+
+static const vshCmdDef ifaceCmds[] = {
+ {"iface-define", cmdInterfaceDefine, opts_interface_define, info_interface_define},
+ {"iface-destroy", cmdInterfaceDestroy, opts_interface_destroy, info_interface_destroy},
+ {"iface-dumpxml", cmdInterfaceDumpXML, opts_interface_dumpxml, info_interface_dumpxml},
+ {"iface-edit", cmdInterfaceEdit, opts_interface_edit, info_interface_edit},
+ {"iface-list", cmdInterfaceList, opts_interface_list, info_interface_list},
+ {"iface-mac", cmdInterfaceMAC, opts_interface_mac, info_interface_mac},
+ {"iface-name", cmdInterfaceName, opts_interface_name, info_interface_name},
+ {"iface-start", cmdInterfaceStart, opts_interface_start, info_interface_start},
+ {"iface-undefine", cmdInterfaceUndefine, opts_interface_undefine, info_interface_undefine},
+ {NULL, NULL, NULL, NULL}
+};
+static const vshCmdDef nwfilterCmds[] = {
{"nwfilter-define", cmdNWFilterDefine, opts_nwfilter_define, info_nwfilter_define},
- {"nwfilter-undefine", cmdNWFilterUndefine, opts_nwfilter_undefine, info_nwfilter_undefine},
{"nwfilter-dumpxml", cmdNWFilterDumpXML, opts_nwfilter_dumpxml, info_nwfilter_dumpxml},
- {"nwfilter-list", cmdNWFilterList, opts_nwfilter_list, info_nwfilter_list},
{"nwfilter-edit", cmdNWFilterEdit, opts_nwfilter_edit, info_nwfilter_edit},
+ {"nwfilter-list", cmdNWFilterList, opts_nwfilter_list, info_nwfilter_list},
+ {"nwfilter-undefine", cmdNWFilterUndefine, opts_nwfilter_undefine, info_nwfilter_undefine},
+ {NULL, NULL, NULL, NULL}
+};
- {"pool-autostart", cmdPoolAutostart, opts_pool_autostart, info_pool_autostart},
- {"pool-build", cmdPoolBuild, opts_pool_build, info_pool_build},
- {"pool-create", cmdPoolCreate, opts_pool_create, info_pool_create},
- {"pool-create-as", cmdPoolCreateAs, opts_pool_X_as, info_pool_create_as},
- {"pool-define", cmdPoolDefine, opts_pool_define, info_pool_define},
- {"pool-define-as", cmdPoolDefineAs, opts_pool_X_as, info_pool_define_as},
- {"pool-destroy", cmdPoolDestroy, opts_pool_destroy, info_pool_destroy},
- {"pool-delete", cmdPoolDelete, opts_pool_delete, info_pool_delete},
- {"pool-dumpxml", cmdPoolDumpXML, opts_pool_dumpxml, info_pool_dumpxml},
- {"pool-edit", cmdPoolEdit, opts_pool_edit, info_pool_edit},
- {"pool-info", cmdPoolInfo, opts_pool_info, info_pool_info},
- {"pool-list", cmdPoolList, opts_pool_list, info_pool_list},
- {"pool-name", cmdPoolName, opts_pool_name, info_pool_name},
- {"pool-refresh", cmdPoolRefresh, opts_pool_refresh, info_pool_refresh},
- {"pool-start", cmdPoolStart, opts_pool_start, info_pool_start},
- {"pool-undefine", cmdPoolUndefine, opts_pool_undefine, info_pool_undefine},
- {"pool-uuid", cmdPoolUuid, opts_pool_uuid, info_pool_uuid},
-
+static const vshCmdDef secretCmds[] = {
{"secret-define", cmdSecretDefine, opts_secret_define, info_secret_define},
{"secret-dumpxml", cmdSecretDumpXML, opts_secret_dumpxml, info_secret_dumpxml},
- {"secret-set-value", cmdSecretSetValue, opts_secret_set_value, info_secret_set_value},
{"secret-get-value", cmdSecretGetValue, opts_secret_get_value, info_secret_get_value},
- {"secret-undefine", cmdSecretUndefine, opts_secret_undefine, info_secret_undefine},
{"secret-list", cmdSecretList, NULL, info_secret_list},
+ {"secret-set-value", cmdSecretSetValue, opts_secret_set_value, info_secret_set_value},
+ {"secret-undefine", cmdSecretUndefine, opts_secret_undefine, info_secret_undefine},
+ {NULL, NULL, NULL, NULL}
+};
-
+static const vshCmdDef virshCmds[] = {
+#ifndef WIN32
+ {"cd", cmdCd, opts_cd, info_cd},
+#endif
+ {"echo", cmdEcho, opts_echo, info_echo},
+ {"exit", cmdQuit, NULL, info_quit},
+ {"help", cmdHelp, opts_help, info_help},
#ifndef WIN32
{"pwd", cmdPwd, NULL, info_pwd},
#endif
{"quit", cmdQuit, NULL, info_quit},
- {"exit", cmdQuit, NULL, info_quit},
- {"reboot", cmdReboot, opts_reboot, info_reboot},
- {"restore", cmdRestore, opts_restore, info_restore},
- {"resume", cmdResume, opts_resume, info_resume},
- {"save", cmdSave, opts_save, info_save},
- {"schedinfo", cmdSchedinfo, opts_schedinfo, info_schedinfo},
- {"dump", cmdDump, opts_dump, info_dump},
- {"shutdown", cmdShutdown, opts_shutdown, info_shutdown},
- {"setmem", cmdSetmem, opts_setmem, info_setmem},
- {"setmaxmem", cmdSetmaxmem, opts_setmaxmem, info_setmaxmem},
- {"memtune", cmdMemtune, opts_memtune, info_memtune},
- {"setvcpus", cmdSetvcpus, opts_setvcpus, info_setvcpus},
- {"suspend", cmdSuspend, opts_suspend, info_suspend},
- {"ttyconsole", cmdTTYConsole, opts_ttyconsole, info_ttyconsole},
- {"undefine", cmdUndefine, opts_undefine, info_undefine},
- {"update-device", cmdUpdateDevice, opts_update_device, info_update_device},
- {"uri", cmdURI, NULL, info_uri},
-
- {"vol-create", cmdVolCreate, opts_vol_create, info_vol_create},
- {"vol-create-from", cmdVolCreateFrom, opts_vol_create_from, info_vol_create_from},
- {"vol-create-as", cmdVolCreateAs, opts_vol_create_as, info_vol_create_as},
- {"vol-clone", cmdVolClone, opts_vol_clone, info_vol_clone},
- {"vol-delete", cmdVolDelete, opts_vol_delete, info_vol_delete},
- {"vol-wipe", cmdVolWipe, opts_vol_wipe, info_vol_wipe},
- {"vol-dumpxml", cmdVolDumpXML, opts_vol_dumpxml, info_vol_dumpxml},
- {"vol-info", cmdVolInfo, opts_vol_info, info_vol_info},
- {"vol-list", cmdVolList, opts_vol_list, info_vol_list},
- {"vol-pool", cmdVolPool, opts_vol_pool, info_vol_pool},
- {"vol-path", cmdVolPath, opts_vol_path, info_vol_path},
- {"vol-name", cmdVolName, opts_vol_name, info_vol_name},
- {"vol-key", cmdVolKey, opts_vol_key, info_vol_key},
-
- {"vcpucount", cmdVcpucount, opts_vcpucount, info_vcpucount},
- {"vcpuinfo", cmdVcpuinfo, opts_vcpuinfo, info_vcpuinfo},
- {"vcpupin", cmdVcpupin, opts_vcpupin, info_vcpupin},
- {"version", cmdVersion, NULL, info_version},
- {"vncdisplay", cmdVNCDisplay, opts_vncdisplay, info_vncdisplay},
+ {NULL, NULL, NULL, NULL}
+};
+static const vshCmdDef snapshotCmds[] = {
{"snapshot-create", cmdSnapshotCreate, opts_snapshot_create, info_snapshot_create},
{"snapshot-current", cmdSnapshotCurrent, opts_snapshot_current, info_snapshot_current},
{"snapshot-delete", cmdSnapshotDelete, opts_snapshot_delete, info_snapshot_delete},
{"snapshot-dumpxml", cmdSnapshotDumpXML, opts_snapshot_dumpxml, info_snapshot_dumpxml},
{"snapshot-list", cmdSnapshotList, opts_snapshot_list, info_snapshot_list},
{"snapshot-revert", cmdDomainSnapshotRevert, opts_snapshot_revert, info_snapshot_revert},
+ {NULL, NULL, NULL, NULL}
+};
+static const vshCmdDef hostAndHypervisorCmds[] = {
+ {"capabilities", cmdCapabilities, NULL, info_capabilities},
+ {"connect", cmdConnect, opts_connect, info_connect},
+ {"freecell", cmdFreecell, opts_freecell, info_freecell},
+ {"hostname", cmdHostname, NULL, info_hostname},
{"qemu-monitor-command", cmdQemuMonitorCommand, opts_qemu_monitor_command, info_qemu_monitor_command},
-
+ {"uri", cmdURI, NULL, info_uri},
{NULL, NULL, NULL, NULL}
};
+static const vshCmdGrp cmdGroups[] = {
+ {VSH_CMD_GRP_DOM_MANAGEMENT, "domain", domManagementCmds},
+ {VSH_CMD_GRP_DOM_MONITORING, "monitor", domMonitoringCmds},
+ {VSH_CMD_GRP_HOST_AND_HV, "host", hostAndHypervisorCmds},
+ {VSH_CMD_GRP_IFACE, "interface", ifaceCmds},
+ {VSH_CMD_GRP_NWFILTER, "filter", nwfilterCmds},
+ {VSH_CMD_GRP_NETWORK, "network", networkCmds},
+ {VSH_CMD_GRP_NODEDEV, "nodedev", nodedevCmds},
+ {VSH_CMD_GRP_SECRET, "secret", secretCmds},
+ {VSH_CMD_GRP_SNAPSHOT, "snapshot", snapshotCmds},
+ {VSH_CMD_GRP_STORAGE_POOL, "pool", storagePoolCmds},
+ {VSH_CMD_GRP_STORAGE_VOL, "volume", storageVolCmds},
+ {VSH_CMD_GRP_VIRSH, "virsh", virshCmds},
+ {NULL, NULL, NULL}
+};
+
+
/* ---------------
* Utils for work with command definition
* ---------------
@@ -10137,14 +10225,54 @@ vshCommandCheckOpts(vshControl *ctl, const vshCmd *cmd)
static const vshCmdDef *
vshCmddefSearch(const char *cmdname)
{
+ const vshCmdGrp *g;
const vshCmdDef *c;
- for (c = commands; c->name; c++)
- if (STREQ(c->name, cmdname))
- return c;
+ for (g = cmdGroups; g->name; g++) {
+ for (c = g->commands; c->name; c++) {
+ if(STREQ(c->name, cmdname))
+ return c;
+ }
+ }
+
return NULL;
}
+static const vshCmdGrp *
+vshCmdGrpSearch(const char *grpname)
+{
+ const vshCmdGrp *g;
+
+ for (g = cmdGroups; g->name; g++) {
+ if(STREQ(g->name, grpname) || STREQ(g->keyword, grpname))
+ return g;
+ }
+
+ return NULL;
+}
+
+static int
+vshCmdGrpHelp(vshControl *ctl, const char *grpname)
+{
+ const vshCmdGrp *grp = vshCmdGrpSearch(grpname);
+ const vshCmdDef *cmd = NULL;
+
+ if (!grp) {
+ vshError(ctl, _("command group '%s' doesn't exist"), grpname);
+ return FALSE;
+ } else {
+ vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name,
+ grp->keyword);
+
+ for (cmd = grp->commands; cmd->name; cmd++) {
+ vshPrint(ctl, " %-30s %s\n", cmd->name,
+ _(vshCmddefGetInfo(cmd, "help")));
+ }
+ }
+
+ return TRUE;
+}
+
static int
vshCmddefHelp(vshControl *ctl, const char *cmdname)
{
@@ -11325,25 +11453,36 @@ vshCloseLogFile(vshControl *ctl)
static char *
vshReadlineCommandGenerator(const char *text, int state)
{
- static int list_index, len;
+ static int grp_list_index, cmd_list_index, len;
const char *name;
+ const vshCmdGrp *grp;
+ const vshCmdDef *cmds;
- /* If this is a new word to complete, initialize now. This
- * includes saving the length of TEXT for efficiency, and
- * initializing the index variable to 0.
- */
if (!state) {
- list_index = 0;
+ grp_list_index = 0;
+ cmd_list_index = 0;
len = strlen(text);
}
+ grp = cmdGroups;
+
/* Return the next name which partially matches from the
* command list.
*/
- while ((name = commands[list_index].name)) {
- list_index++;
- if (STREQLEN(name, text, len))
- return vshStrdup(NULL, name);
+ while (grp[grp_list_index].name) {
+ cmds = grp[grp_list_index].commands;
+
+ if (cmds[cmd_list_index].name) {
+ while ((name = cmds[cmd_list_index].name)) {
+ cmd_list_index++;
+
+ if (STREQLEN(name, text, len))
+ return vshStrdup(NULL, name);
+ }
+ } else {
+ cmd_list_index = 0;
+ grp_list_index++;
+ }
}
/* If no names matched, then return NULL. */
@@ -11542,7 +11681,9 @@ vshDeinit(vshControl *ctl)
static void
vshUsage(void)
{
+ const vshCmdGrp *grp;
const vshCmdDef *cmd;
+
fprintf(stdout, _("\n%s [options]... [<command_string>]"
"\n%s [options]... <command> [args...]\n\n"
" options:\n"
@@ -11553,14 +11694,21 @@ vshUsage(void)
" -q | --quiet quiet mode\n"
" -t | --timing print timing information\n"
" -l | --log <file> output logging to file\n"
- " -v | --version[=short] program version\n\n"
- " -V | --version=long version and full options\n\n"
- " commands (non interactive mode):\n"), progname, progname);
+ " -v | --version program version\n\n"
+ " commands (non interactive mode):\n\n"), progname, progname);
- for (cmd = commands; cmd->name; cmd++)
- fprintf(stdout,
- " %-15s %s\n", cmd->name, _(vshCmddefGetInfo(cmd, "help")));
+ for (grp = cmdGroups; grp->name; grp++) {
+ fprintf(stdout, _(" %s (help keyword '%s')\n"), grp->name, grp->keyword);
+ for (cmd = grp->commands; cmd->name; cmd++)
+ fprintf(stdout,
+ " %-30s %s\n", cmd->name, _(vshCmddefGetInfo(cmd, "help")));
+
+ fprintf(stdout, "\n");
+ }
+
+ fprintf(stdout, "%s",
+ _("\n (specify help <group> for details about the commands in the group)\n"));
fprintf(stdout, "%s",
_("\n (specify help <command> for details about the command)\n\n"));
return;
--
1.7.3.2
13 years, 11 months
[libvirt] [PATCH] maint: allow 'make syntax-check' to run again
by Eric Blake
* .x-sc_prohibit_xmlGetProp: Add exception.
---
docs/news.html.in broke 'make syntax-check' again (how many releases
have we done with that issue?)
This is alternative 1. However, I won't push this, if alternative 2
pans out.
.x-sc_prohibit_xmlGetProp | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/.x-sc_prohibit_xmlGetProp b/.x-sc_prohibit_xmlGetProp
index f6d7ee2..68a1da5 100644
--- a/.x-sc_prohibit_xmlGetProp
+++ b/.x-sc_prohibit_xmlGetProp
@@ -1 +1,2 @@
^src/util/xml.c$
+^docs/.*
--
1.7.3.2
13 years, 11 months
[libvirt] libvirt-0.8.5 sometimes crahing
by Nikola Ciprich
Hello,
I noticed that libvirtd sometimes crashes immediately after start..
here's the backtrace:
Core was generated by `libvirtd --daemon --listen'.
Program terminated with signal 11, Segmentation fault.
#0 0x00007fee038c0ca0 in pthread_mutex_lock () from /lib64/libpthread.so.0
(gdb) bt
#0 0x00007fee038c0ca0 in pthread_mutex_lock () from /lib64/libpthread.so.0
#1 0x000000000042eb21 in qemuDomainObjEnterMonitor (obj=0xe417d0) at qemu/qemu_driver.c:478
#2 0x0000000000448e7e in qemudDomainGetInfo (dom=<value optimized out>, info=0x43392e10) at qemu/qemu_driver.c:5165
#3 0x00007fee054f29f2 in virDomainGetInfo (domain=0xe3f610, info=0x43392e10) at libvirt.c:3177
#4 0x000000000042554e in remoteDispatchDomainGetInfo (server=<value optimized out>, client=<value optimized out>, conn=0xdd8a20, hdr=<value optimized out>, rerr=0x43392eb0,
args=<value optimized out>, ret=0x43392f90) at remote.c:1503
#5 0x0000000000427444 in remoteDispatchClientCall (server=0xdb84d0, client=0x7fedfc040bc0, msg=0x7fedfc0410a0) at dispatch.c:529
#6 remoteDispatchClientRequest (server=0xdb84d0, client=0x7fedfc040bc0, msg=0x7fedfc0410a0) at dispatch.c:407
#7 0x00000000004194c7 in qemudWorker (data=<value optimized out>) at libvirtd.c:1587
#8 0x00007fee038be73d in start_thread () from /lib64/libpthread.so.0
#9 0x00007fee03430f6d in clone () from /lib64/libc.so.6
Could somebody please look at it?
If I could provide any additional information, please let me know.
Thanks in advance
BR
nik
--
-------------------------------------
Ing. Nikola CIPRICH
LinuxBox.cz, s.r.o.
28. rijna 168, 709 01 Ostrava
tel.: +420 596 603 142
fax: +420 596 621 273
mobil: +420 777 093 799
www.linuxbox.cz
mobil servis: +420 737 238 656
email servis: servis(a)linuxbox.cz
-------------------------------------
13 years, 11 months
[libvirt] [PATCH v2] 802.1Qbg: use pre-associate state at beginning of incoming migration
by Stefan Berger
-v2:
- changing the vmOpStr array and vmOperation enum to use
VIR_ENUM_IMPL and VIR_ENUM_DECL. Renaming the enum to virVMOperationType
and adapting the name of the enum constants.
This patch introduces the usage of the pre-associate state of the IEEE
802.1Qbg standard on incoming VM migration on the target host. It is in
response to bugzilla entry 632750.
https://bugzilla.redhat.com/show_bug.cgi?id=632750
For being able to differentiate the exact reason as to why a macvtap
device is being created, either due to a VM creation or an incoming VM
migration, I needed to pass that reason as a parameter from wherever
qemudStartVMDaemon is being called in order to determine whether to send
an ASSOCIATE (VM creation) or a PRE-ASSOCIATE (incoming VM migration)
towards lldpad.
I am also fixing a problem with the virsh domainxml-to-native call on
the way.
Gerhard successfully tested the patch with a recent blade network
802.1Qbg-compliant switch.
The patch should not have any side-effects on the 802.1Qbh support in
libvirt, but Roopa (cc'ed) may want to verify this.
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
Signed-off-by: Gerhard Stenzel <gerhard.stenzel(a)de.ibm.com>
---
src/libvirt_macvtap.syms | 2 +
src/qemu/qemu_conf.c | 12 +++++--
src/qemu/qemu_conf.h | 7 +++-
src/qemu/qemu_driver.c | 72
+++++++++++++++++++++++++++++++++++++----------
src/util/macvtap.c | 54 ++++++++++++++++++++++++++++++-----
src/util/macvtap.h | 20 +++++++++++--
6 files changed, 137 insertions(+), 30 deletions(-)
Index: libvirt-acl/src/qemu/qemu_conf.c
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_conf.c
+++ libvirt-acl/src/qemu/qemu_conf.c
@@ -1642,7 +1642,8 @@ qemudPhysIfaceConnect(virConnectPtr conn
struct qemud_driver *driver,
virDomainNetDefPtr net,
unsigned long long qemuCmdFlags,
- const unsigned char *vmuuid)
+ const unsigned char *vmuuid,
+ enum virVMOperationType vmop)
{
int rc;
#if WITH_MACVTAP
@@ -1656,7 +1657,8 @@ qemudPhysIfaceConnect(virConnectPtr conn
rc = openMacvtapTap(net->ifname, net->mac, net->data.direct.linkdev,
net->data.direct.mode, vnet_hdr, vmuuid,
- &net->data.direct.virtPortProfile, &res_ifname);
+ &net->data.direct.virtPortProfile, &res_ifname,
+ vmop);
if (rc >= 0) {
VIR_FREE(net->ifname);
net->ifname = res_ifname;
@@ -3953,7 +3955,8 @@ int qemudBuildCommandLine(virConnectPtr
int **vmfds,
int *nvmfds,
const char *migrateFrom,
- virDomainSnapshotObjPtr current_snapshot)
+ virDomainSnapshotObjPtr current_snapshot,
+ enum virVMOperationType vmop)
{
int i;
char memory[50];
@@ -4796,7 +4799,8 @@ int qemudBuildCommandLine(virConnectPtr
} else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
int tapfd = qemudPhysIfaceConnect(conn, driver, net,
qemuCmdFlags,
- def->uuid);
+ def->uuid,
+ vmop);
if (tapfd < 0)
goto error;
Index: libvirt-acl/src/qemu/qemu_conf.h
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_conf.h
+++ libvirt-acl/src/qemu/qemu_conf.h
@@ -40,6 +40,7 @@
# include "cpu_conf.h"
# include "driver.h"
# include "bitmap.h"
+# include "macvtap.h"
# define qemudDebug(fmt, ...) do {} while(0)
@@ -238,7 +239,8 @@ int qemudBuildCommandLine
int **vmfds,
int *nvmfds,
const char *migrateFrom,
- virDomainSnapshotObjPtr
current_snapshot)
+ virDomainSnapshotObjPtr
current_snapshot,
+ enum virVMOperationType vmop)
ATTRIBUTE_NONNULL(1);
/* With vlan == -1, use netdev syntax, else old hostnet */
@@ -317,7 +319,8 @@ int qemudPhysIfaceConnect(virConnectPtr
struct qemud_driver *driver,
virDomainNetDefPtr net,
unsigned long long qemuCmdFlags,
- const unsigned char *vmuuid);
+ const unsigned char *vmuuid,
+ enum virVMOperationType vmop);
int qemudProbeMachineTypes (const char *binary,
virCapsGuestMachinePtr
**machines,
Index: libvirt-acl/src/qemu/qemu_driver.c
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_driver.c
+++ libvirt-acl/src/qemu/qemu_driver.c
@@ -163,7 +163,8 @@ static int qemudStartVMDaemon(virConnect
const char *migrateFrom,
bool start_paused,
int stdin_fd,
- const char *stdin_path);
+ const char *stdin_path,
+ enum virVMOperationType vmop);
static void qemudShutdownVMDaemon(struct qemud_driver *driver,
virDomainObjPtr vm,
@@ -3864,7 +3865,8 @@ static int qemudStartVMDaemon(virConnect
const char *migrateFrom,
bool start_paused,
int stdin_fd,
- const char *stdin_path) {
+ const char *stdin_path,
+ enum virVMOperationType vmop) {
const char **argv = NULL, **tmp;
const char **progenv = NULL;
int i, ret, runflags;
@@ -4065,7 +4067,7 @@ static int qemudStartVMDaemon(virConnect
if (qemudBuildCommandLine(conn, driver, vm->def, priv->monConfig,
priv->monJSON, qemuCmdFlags, &argv,
&progenv,
&vmfds, &nvmfds, migrateFrom,
- vm->current_snapshot) < 0)
+ vm->current_snapshot, vmop) < 0)
goto cleanup;
if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir) < 0)
@@ -4879,7 +4881,7 @@ static virDomainPtr qemudDomainCreate(vi
if (qemudStartVMDaemon(conn, driver, vm, NULL,
(flags & VIR_DOMAIN_START_PAUSED) != 0,
- -1, NULL) < 0) {
+ -1, NULL, VIR_VM_OP_CREATE) < 0) {
qemuDomainStartAudit(vm, "booted", false);
if (qemuDomainObjEndJob(vm) > 0)
virDomainRemoveInactive(&driver->domains,
@@ -7015,7 +7017,8 @@ qemudDomainSaveImageStartVM(virConnectPt
}
/* Set the migration source and start it up. */
- ret = qemudStartVMDaemon(conn, driver, vm, "stdio", true, fd, path);
+ ret = qemudStartVMDaemon(conn, driver, vm, "stdio", true, fd, path,
+ VIR_VM_OP_RESTORE);
if (intermediate_pid != -1) {
/* Wait for intermediate process to exit */
@@ -7334,14 +7337,15 @@ static char *qemuDomainXMLToNative(virCo
if (!def)
goto cleanup;
- /* Since we're just exporting args, we can't do bridge/network
- * setups, since libvirt will normally create TAP devices
+ /* Since we're just exporting args, we can't do bridge/network/direct
+ * setups, since libvirt will normally create TAP/macvtap devices
* directly. We convert those configs into generic 'ethernet'
* config and assume the user has suitable 'ifup-qemu' scripts
*/
for (i = 0 ; i < def->nnets ; i++) {
virDomainNetDefPtr net = def->nets[i];
- if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
+ if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
+ net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
VIR_FREE(net->data.network.name);
memset(net, 0, sizeof *net);
@@ -7397,7 +7401,8 @@ static char *qemuDomainXMLToNative(virCo
&monConfig, 0, qemuCmdFlags,
&retargv, &retenv,
NULL, NULL, /* Don't want it to create
TAP devices */
- NULL, NULL) < 0) {
+ NULL, NULL,
+ VIR_VM_OP_NO_OP) < 0) {
goto cleanup;
}
@@ -7484,7 +7489,8 @@ static int qemudDomainObjStart(virConnec
goto cleanup;
}
- ret = qemudStartVMDaemon(conn, driver, vm, NULL, start_paused, -1,
NULL);
+ ret = qemudStartVMDaemon(conn, driver, vm, NULL, start_paused, -1,
NULL,
+ VIR_VM_OP_CREATE);
qemuDomainStartAudit(vm, "booted", ret >= 0);
if (ret >= 0) {
virDomainEventPtr event =
@@ -8327,7 +8333,8 @@ static int qemudDomainAttachNetDevice(vi
if ((tapfd = qemudPhysIfaceConnect(conn, driver, net,
qemuCmdFlags,
- vm->def->uuid)) < 0)
+ vm->def->uuid,
+ VIR_VM_OP_CREATE)) < 0)
return -1;
}
@@ -11001,7 +11008,7 @@ qemudDomainMigratePrepareTunnel(virConne
* -incoming unix:/path/to/file or exec:nc -U /path/to/file
*/
internalret = qemudStartVMDaemon(dconn, driver, vm, migrateFrom, true,
- -1, NULL);
+ -1, NULL, VIR_VM_OP_MIGRATE_IN_START);
VIR_FREE(migrateFrom);
if (internalret < 0) {
qemuDomainStartAudit(vm, "migrated", false);
@@ -11247,7 +11254,7 @@ qemudDomainMigratePrepare2 (virConnectPt
*/
snprintf (migrateFrom, sizeof (migrateFrom), "tcp:0.0.0.0:%d",
this_port);
if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom, true,
- -1, NULL) < 0) {
+ -1, NULL, VIR_VM_OP_MIGRATE_IN_START) < 0) {
qemuDomainStartAudit(vm, "migrated", false);
/* Note that we don't set an error here because qemudStartVMDaemon
* should have already done that.
@@ -11862,6 +11869,41 @@ cleanup:
return ret;
}
+static void
+qemudVPAssociatePortProfiles(virDomainDefPtr def) {
+ int i;
+ int last_good_net = -1;
+ virDomainNetDefPtr net;
+
+ for (i = 0; i < def->nnets; i++) {
+ net = def->nets[i];
+ if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+ if (vpAssociatePortProfileId(net->ifname,
+ net->mac,
+ net->data.direct.linkdev,
+ &net->data.direct.virtPortProfile,
+ def->uuid,
+ VIR_VM_OP_MIGRATE_IN_FINISH) != 0)
+ goto err_exit;
+ }
+ last_good_net = i;
+ }
+
+ return;
+
+err_exit:
+ for (i = 0; i < last_good_net; i++) {
+ net = def->nets[i];
+ if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+ vpDisassociatePortProfileId(net->ifname,
+ net->mac,
+ net->data.direct.linkdev,
+ &net->data.direct.virtPortProfile,
+ VIR_VM_OP_MIGRATE_IN_FINISH);
+ }
+ }
+}
+
/* Finish is the third and final step, and it runs on the destination
host. */
static virDomainPtr
qemudDomainMigrateFinish2 (virConnectPtr dconn,
@@ -11922,6 +11964,8 @@ qemudDomainMigrateFinish2 (virConnectPtr
goto cleanup;
}
+ qemudVPAssociatePortProfiles(vm->def);
+
if (flags & VIR_MIGRATE_PERSIST_DEST) {
if (vm->persistent)
newVM = 0;
@@ -12814,7 +12858,7 @@ static int qemuDomainRevertToSnapshot(vi
goto endjob;
rc = qemudStartVMDaemon(snapshot->domain->conn, driver,
vm, NULL,
- false, -1, NULL);
+ false, -1, NULL, VIR_VM_OP_CREATE);
qemuDomainStartAudit(vm, "from-snapshot", rc >= 0);
if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir)
< 0)
goto endjob;
Index: libvirt-acl/src/util/macvtap.c
===================================================================
--- libvirt-acl.orig/src/util/macvtap.c
+++ libvirt-acl/src/util/macvtap.c
@@ -77,9 +77,21 @@
# define LLDPAD_PID_FILE "/var/run/lldpad.pid"
+VIR_ENUM_IMPL(virVMOperation, VIR_VM_OP_LAST,
+ "create",
+ "save",
+ "restore",
+ "destroy",
+ "migrate out",
+ "migrate in start",
+ "migrate in finish",
+ "no-op")
+
+
enum virVirtualPortOp {
ASSOCIATE = 0x1,
DISASSOCIATE = 0x2,
+ PREASSOCIATE = 0x3,
};
@@ -551,7 +563,8 @@ openMacvtapTap(const char *tgifname,
int vnet_hdr,
const unsigned char *vmuuid,
virVirtualPortProfileParamsPtr virtPortProfile,
- char **res_ifname)
+ char **res_ifname,
+ enum virVMOperationType vmOp)
{
const char *type = "macvtap";
int c, rc;
@@ -563,6 +576,8 @@ openMacvtapTap(const char *tgifname,
*res_ifname = NULL;
+ VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__,
virVMOperationTypeToString(vmOp));
+
if (tgifname) {
if(ifaceGetIndex(false, tgifname, &ifindex) == 0) {
if (STRPREFIX(tgifname,
@@ -601,7 +616,7 @@ create_name:
macaddress,
linkdev,
virtPortProfile,
- vmuuid) != 0) {
+ vmuuid, vmOp) != 0) {
rc = -1;
goto link_del_exit;
}
@@ -634,7 +649,8 @@ disassociate_exit:
vpDisassociatePortProfileId(cr_ifname,
macaddress,
linkdev,
- virtPortProfile);
+ virtPortProfile,
+ vmOp);
link_del_exit:
link_del(cr_ifname);
@@ -662,7 +678,8 @@ delMacvtap(const char *ifname,
if (ifname) {
vpDisassociatePortProfileId(ifname, macaddr,
linkdev,
- virtPortProfile);
+ virtPortProfile,
+ VIR_VM_OP_DESTROY);
link_del(ifname);
}
}
@@ -1320,6 +1337,9 @@ doPortProfileOp8021Qbg(const char *ifnam
portVsi.vsi_type_id[0] = virtPort->u.virtPort8021Qbg.typeID;
switch (virtPortOp) {
+ case PREASSOCIATE:
+ op = PORT_REQUEST_PREASSOCIATE;
+ break;
case ASSOCIATE:
op = PORT_REQUEST_ASSOCIATE;
break;
@@ -1484,6 +1504,7 @@ err_exit:
* @macvtap_ifname: The name of the macvtap device
* @virtPort: pointer to the object holding port profile parameters
* @vmuuid : the UUID of the virtual machine
+ * @vmOp : The VM operation (i.e., create, no-op)
*
* Associate a port on a swtich with a profile. This function
* may notify a kernel driver or an external daemon to run
@@ -1499,13 +1520,19 @@ vpAssociatePortProfileId(const char *mac
const unsigned char *macvtap_macaddr,
const char *linkdev,
const virVirtualPortProfileParamsPtr virtPort,
- const unsigned char *vmuuid)
+ const unsigned char *vmuuid,
+ enum virVMOperationType vmOp)
{
int rc = 0;
VIR_DEBUG("Associating port profile '%p' on link device '%s'",
virtPort, macvtap_ifname);
+ VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__,
virVMOperationTypeToString(vmOp));
+
+ if (vmOp == VIR_VM_OP_NO_OP)
+ return 0;
+
switch (virtPort->virtPortType) {
case VIR_VIRTUALPORT_NONE:
case VIR_VIRTUALPORT_TYPE_LAST:
@@ -1513,10 +1540,16 @@ vpAssociatePortProfileId(const char *mac
case VIR_VIRTUALPORT_8021QBG:
rc = doPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr,
- virtPort, ASSOCIATE);
+ virtPort,
+ (vmOp == VIR_VM_OP_MIGRATE_IN_START)
+ ? PREASSOCIATE
+ : ASSOCIATE);
break;
case VIR_VIRTUALPORT_8021QBH:
+ /* avoid associating twice */
+ if (vmOp == VIR_VM_OP_MIGRATE_IN_FINISH)
+ break;
rc = doPortProfileOp8021Qbh(linkdev, virtPort,
vmuuid,
ASSOCIATE);
@@ -1542,13 +1575,16 @@ int
vpDisassociatePortProfileId(const char *macvtap_ifname,
const unsigned char *macvtap_macaddr,
const char *linkdev,
- const virVirtualPortProfileParamsPtr virtPort)
+ const virVirtualPortProfileParamsPtr virtPort,
+ enum virVMOperationType vmOp)
{
int rc = 0;
VIR_DEBUG("Disassociating port profile id '%p' on link device '%s' ",
virtPort, macvtap_ifname);
+ VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__,
virVMOperationTypeToString(vmOp));
+
switch (virtPort->virtPortType) {
case VIR_VIRTUALPORT_NONE:
case VIR_VIRTUALPORT_TYPE_LAST:
@@ -1560,6 +1596,9 @@ vpDisassociatePortProfileId(const char *
break;
case VIR_VIRTUALPORT_8021QBH:
+ /* avoid disassociating twice */
+ if (vmOp == VIR_VM_OP_MIGRATE_IN_FINISH)
+ break;
rc = doPortProfileOp8021Qbh(linkdev, virtPort,
NULL,
DISASSOCIATE);
Index: libvirt-acl/src/util/macvtap.h
===================================================================
--- libvirt-acl.orig/src/util/macvtap.h
+++ libvirt-acl/src/util/macvtap.h
@@ -62,6 +62,19 @@ struct _virVirtualPortProfileParams {
# include "internal.h"
+enum virVMOperationType {
+ VIR_VM_OP_CREATE,
+ VIR_VM_OP_SAVE,
+ VIR_VM_OP_RESTORE,
+ VIR_VM_OP_DESTROY,
+ VIR_VM_OP_MIGRATE_OUT,
+ VIR_VM_OP_MIGRATE_IN_START,
+ VIR_VM_OP_MIGRATE_IN_FINISH,
+ VIR_VM_OP_NO_OP,
+
+ VIR_VM_OP_LAST
+};
+
int openMacvtapTap(const char *ifname,
const unsigned char *macaddress,
const char *linkdev,
@@ -69,7 +82,8 @@ int openMacvtapTap(const char *ifname,
int vnet_hdr,
const unsigned char *vmuuid,
virVirtualPortProfileParamsPtr virtPortProfile,
- char **res_ifname);
+ char **res_ifname,
+ enum virVMOperationType vmop);
void delMacvtap(const char *ifname,
const unsigned char *macaddress,
@@ -86,13 +100,16 @@ int vpAssociatePortProfileId(const char
const unsigned char *macvtap_macaddr,
const char *linkdev,
const virVirtualPortProfileParamsPtr
virtPort,
- const unsigned char *vmuuid);
+ const unsigned char *vmuuid,
+ enum virVMOperationType vmOp);
int vpDisassociatePortProfileId(const char *macvtap_ifname,
const unsigned char *macvtap_macaddr,
const char *linkdev,
- const virVirtualPortProfileParamsPtr
virtPort);
+ const virVirtualPortProfileParamsPtr
virtPort,
+ enum virVMOperationType vmOp);
VIR_ENUM_DECL(virVirtualPort)
+VIR_ENUM_DECL(virVMOperation)
#endif /* __UTIL_MACVTAP_H__ */
Index: libvirt-acl/src/libvirt_macvtap.syms
===================================================================
--- libvirt-acl.orig/src/libvirt_macvtap.syms
+++ libvirt-acl/src/libvirt_macvtap.syms
@@ -3,3 +3,7 @@
# macvtap.h
openMacvtapTap;
delMacvtap;
+vpAssociatePortProfileId;
+vpDisassociatePortProfileId;
+virVMOperationTypeToString;
+virVMOperationTypeFromString;
13 years, 11 months
[libvirt] [PATCH] OpenVZ: take veid from vmdef->name when defining new domains
by Guido Günther
Hi,
We currently use the next free veid although there's one given in the
domain xml. This currently breaks defining new domains since vmdef->name
and veid don't match leading to the following error later on:
error: Failed to define domain from 110.xml
error: internal error Could not set UUID
Since silently ignoring vmdef->name is not nice respect it instead. We
avoid veid collisions in the upper levels already.
O.k. to apply?
-- Guido
13 years, 12 months
[libvirt] [PATCH] Log client errors in libvirtd at debug priority
by Matthias Bolte
This reverts commit
Log all errors at level INFO to stop polluting syslog
04bd0360f32ec628ecf7943b3fd1468d6eb2dde5.
and makes virRaiseErrorFull() log errors at debug priority
when called from inside libvirtd. This stops libvirtd from
polluting it's own log with client errors at error priority
that'll be reported and logged on the client side anyway.
---
This is basically a v2 for
https://www.redhat.com/archives/libvir-list/2010-November/msg01060.html
v2 logs client error at debug priority in libvirtd instead of
not logging them at all. Also the way it's implemented is
changed the way that Daniel suggested.
daemon/libvirtd.c | 4 ++++
src/libvirt_private.syms | 1 +
src/util/virterror.c | 28 +++++++++++++++++++++++++++-
src/util/virterror_internal.h | 1 +
4 files changed, 33 insertions(+), 1 deletions(-)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 66f1388..caf51bf 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -3083,6 +3083,10 @@ int main(int argc, char **argv) {
exit(EXIT_FAILURE);
}
+ /* Set error logging priority to debug, so client errors don't
+ * show up as errors in the daemon log */
+ virErrorSetLogPriority(VIR_LOG_DEBUG);
+
while (1) {
int optidx = 0;
int c;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 33e52e2..ef33f86 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -831,6 +831,7 @@ virAuditSend;
# virterror_internal.h
virDispatchError;
virErrorMsg;
+virErrorSetLogPriority;
virRaiseErrorFull;
virReportErrorHelper;
virReportOOMErrorFull;
diff --git a/src/util/virterror.c b/src/util/virterror.c
index 83c4c9d..491da23 100644
--- a/src/util/virterror.c
+++ b/src/util/virterror.c
@@ -26,6 +26,7 @@ virThreadLocal virLastErr;
virErrorFunc virErrorHandler = NULL; /* global error handler */
void *virUserData = NULL; /* associated data */
+static int virErrorLogPriority = -1;
/*
* Macro used to format the message as a string in virRaiseError
@@ -64,6 +65,18 @@ void *virUserData = NULL; /* associated data */
}} \
}
+static virLogPriority virErrorLevelPriority(virErrorLevel level) {
+ switch (level) {
+ case VIR_ERR_NONE:
+ return(VIR_LOG_INFO);
+ case VIR_ERR_WARNING:
+ return(VIR_LOG_WARN);
+ case VIR_ERR_ERROR:
+ return(VIR_LOG_ERROR);
+ }
+ return(VIR_LOG_ERROR);
+}
+
static const char *virErrorDomainName(virErrorDomain domain) {
const char *dom = "unknown";
switch (domain) {
@@ -676,6 +689,7 @@ virRaiseErrorFull(virConnectPtr conn ATTRIBUTE_UNUSED,
{
virErrorPtr to;
char *str;
+ int priority;
/*
* All errors are recorded in thread local storage
@@ -700,11 +714,18 @@ virRaiseErrorFull(virConnectPtr conn ATTRIBUTE_UNUSED,
VIR_GET_VAR_STR(fmt, str);
}
+
/*
* Hook up the error or warning to the logging facility
* XXXX should we include filename as 'category' instead of domain name ?
+ *
+ * When an explicit error log priority is set then use it, otherwise
+ * translate the error level to the log priority. This is used by libvirtd
+ * to log client errors at debug priority.
*/
- virLogMessage(virErrorDomainName(domain), VIR_LOG_INFO,
+ priority = virErrorLogPriority == -1 ? virErrorLevelPriority(level)
+ : virErrorLogPriority;
+ virLogMessage(virErrorDomainName(domain), priority,
funcname, linenr, 1, "%s", str);
/*
@@ -1319,3 +1340,8 @@ void virReportOOMErrorFull(int domcode,
domcode, VIR_ERR_NO_MEMORY, VIR_ERR_ERROR,
virerr, NULL, NULL, -1, -1, virerr, NULL);
}
+
+void virErrorSetLogPriority(int priority)
+{
+ virErrorLogPriority = priority;
+}
diff --git a/src/util/virterror_internal.h b/src/util/virterror_internal.h
index 601a884..2dd2b4a 100644
--- a/src/util/virterror_internal.h
+++ b/src/util/virterror_internal.h
@@ -89,5 +89,6 @@ void virReportOOMErrorFull(int domcode,
int virSetError(virErrorPtr newerr);
void virDispatchError(virConnectPtr conn);
const char *virStrerror(int theerrno, char *errBuf, size_t errBufLen);
+void virErrorSetLogPriority(int priority);
#endif
--
1.7.0.4
13 years, 12 months
[libvirt] Bootstrap fail, but non-useful message :/
by Justin Clift
Hi Eric,
Just ran ./autogen.sh on an OSX box with only the system provided
autotools installed, and got this:
************************************************************************************
Copying file po/remove-potcdate.sin
./bootstrap: patching m4/gettext.m4 to remove need for intl/* ...
./bootstrap: glibtoolize -c -f ...
glibtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, `build-aux'.
glibtoolize: copying file `build-aux/ltmain.sh'
glibtoolize: putting macros in AC_CONFIG_MACRO_DIR, `m4'.
glibtoolize: copying file `m4/libtool.m4'
glibtoolize: copying file `m4/ltoptions.m4'
glibtoolize: copying file `m4/ltsugar.m4'
glibtoolize: copying file `m4/ltversion.m4'
glibtoolize: copying file `m4/lt~obsolete.m4'
./bootstrap: aclocal -I gnulib/m4 --force -I m4 ...
configure.ac:13: warning: macro `AM_SILENT_RULES' not found in library
./bootstrap: autoconf --force ...
configure.ac:60: error: possibly undefined macro: AC_MSG_ERROR
If this token and others are legitimate, please use m4_pattern_allow.
See the Autoconf documentation.
configure.ac:512: error: possibly undefined macro: AC_MSG_NOTICE
configure.ac:627: error: possibly undefined macro: PKG_CHECK_MODULES
Failed to bootstrap, please investigate.
$
************************************************************************************
This system is using the "MacPorts" packaging system instead of Homebrew.
The problem was easy enough to resolve by installing the newer autoconf
and automake MacPorts provides.
But, I'm concerned about the less-than-helpful error message given here.
Isn't the bootstrap supposed to detect the required versions of things (as specified
in the .conf file), and inform us clearly if they're not found?
Regards and best wishes,
Justin Clift
13 years, 12 months