[libvirt] VMware Workstation/Player support
by Jean-Baptiste Rouault
Hi all,
I'm working on the hynesim project (http://www.hynesim.org
http://blog.hynesim.org).
We are going to add VMware Workstation support to hynesim,
so we would like to contribute to the development of a libvirt driver.
There probably are multiple ways of doing this, one of them could
be to use the VIX C API provided by VMware :
http://www.vmware.com/support/developer/vix-api/
However, the VIX license seems to be quite restrictive :
http://www.vmware.com/download/eula/vixapi_eula.html
I'm not a license expert so I don't know if this license forbids
using the API in software like libvirt.
Another possibility could be to run VMware command line tools
from libvirt to control guests.
As Daniel P. Berrange stated on IRC yesterday, the vmx <-> XML
conversion code can be reused from the ESX driver.
I'd like to have your opinion about the "best" to implement this
VMware Workstation driver.
Regards,
Jean-Baptiste Rouault
14 years, 1 month
[libvirt] process= support for 'qemu-kvm -name' [Bug 576950]
by John Morrissey
I wrote (attached here, and to the bug) a quick patch that sets the process
name to the same value as the window title.
I'm unsure where to go from here. Should I add support for converting
"native" QEMU command lines to libvirt XML? What would that look like, since
I'm not modifying the libvirt format? Should it just drop any ,process= from
the QEMU command line it's parsing? I also imagine the test cases will need
updating.
If someone could give me some high-level guidance, I'd be happy to keep
going on this.
john
--
John Morrissey _o /\ ---- __o
jwm(a)horde.net _-< \_ / \ ---- < \,
www.horde.net/ __(_)/_(_)________/ \_______(_) /_(_)__
14 years, 1 month
[libvirt] New save/restore api proposal
by Jean-Baptiste Rouault
Hello all,
I'd like to add support for save and restore to the OpenVZ and VirtualBox
drivers because I have to support these operations in the application I'm
working on.
However, the save/restore API in its current state doesn't fit well to our
needs. The main problem is that the domain definition is included inside the
save file. This is problematic because between the save and the restore
operations, the names of the network interfaces on the host side are likely to
have changed and we can't modify them before restoring the domain.
To summarize, what we would like to be able to do is:
- save a domain and undefine it
- update the domain definition to use the new names of host side interfaces
- restore the domain
This is why I would like to add two new functions with the following
signatures (better names are probably needed):
int virDomainSaveState(virDomainPtr domain, const char *to);
int virDomainRestoreState(virDomainPtr domain, const char *from);
The first one would do the same as virDomainSave but without prepending the
domain's definition to the save file.
The other function would be able to restore a domain saved by the first one.
What do you think ?
Regards,
Jean-Baptiste
14 years, 1 month
[libvirt] RFC [0/3]: A proposal for lock manager plugins
by Daniel P. Berrange
A few weeks back David introduce sync-manager as a means for protecting
against the same VM being started on multiple hosts:
https://www.redhat.com/archives/libvir-list/2010-August/msg00179.html
This is obviously a desirable feature for libvirt, but we don't want to
have a hardcoded dependancy on a particular implementation. We can
achieve isolation between libvirt & sync-manager, allowing for alternative
implementations by specifying a formal plugin for supervisor processes.
What follows is my mockup of what a plugin API would look like, its
internal libvirt API and an outline of the usage scenarios in psuedo
code.
At the minimum level of compliance, the plugin implementation provides
for per-VM level exclusion. Optionally a plugin can declare that it
- supports locks against individual resources (disks)
- supports hotplug of individual resources
- supports migration of the supervised process
Migration/hotplug will be forbid if those capabilities aren't declared
by the plugin.
In parallel with David's work on sync-manager, I intend to write a simple
plugin implementation based solely on fcntl() locking. It is important
that we have 2 independant implementations to prove the validity of the
plugin API. The fcntl() impl should provide a zero-config impl we can
deploy out of the box that will provide protection against 2 vms using
the same disk image on a host, and limited protection in multi-host
scenarios with shared filesystems (no protection for shared block devs).
Perhaps we should have a 3rd impl based on libdlm too, for Red Hat
ClusterSuite scenarios, though sync-manager may well be general &
simple enough to easily cope with this already.
Daniel
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
14 years, 1 month
[libvirt] [PATCH V2] virsh: rework command parsing
by Lai Jiangshan
Old virsh command parsing mashes all the args back into a string and
miss the quotes, this patch fixes it. It is also needed for introducing
qemu-monitor-command which is very useful.
This patch split the command-parsing into 2 phrases:
1) parse command string and make it into <args, argv> style arguments.
2) parse <args, argv> style arguments and make it into vshCmd structure.
The first step is needed when we use virsh as a shell.
And the usage was changed:
old:
virsh [options] [commands]
new:
virsh [options]... [<command_name> args...]
virsh [options]... <command_string>
So we still support commands like:
# virsh "define D.xml; dumpxml D"
"define D.xml; dumpxml D" was parsed as a commands-string.
and support commands like:
# virsh qemu-monitor-command f13guest "info cpus"
we will not mash them into a string, we just skip the step 1 parsing
and goto the step 2 parsing directly.
But we don't support the command like:
# virsh "define D.xml; dumpxml" D
"define D.xml; dumpxml" was parsed as a command-name, but we have no such command-name.
Misc changed behavior:
1) support escape '\'
2) a better quoting support, the following commands are now supported:
virsh # dumpxml --"update-cpu" vm1
virsh # dumpxml --update-cpu vm"1"
3) better handling the boolean options, in old code the following commands are equivalent:
virsh # dumpxml --update-cpu=vm1
virsh # dumpxml --update-cpu vm1
after this patch applied, the first one will become illegal.
The idea of this patch is from Daniel P. Berrange.
changed from V1:
changed the usage as Eric Blake suggested.
Signed-off-by: Lai Jiangshan <laijs(a)cn.fujitsu.com>
---
virsh.c | 351 ++++++++++++++++++++++++++++++----------------------------------
1 file changed, 170 insertions(+), 181 deletions(-)
--- libvirt-0.8.4.old/tools/virsh.c 2010-09-10 20:47:06.000000000 +0800
+++ libvirt-0.8.4/tools/virsh.c 2010-09-16 17:13:55.000000000 +0800
@@ -10162,90 +10162,166 @@ vshCommandRun(vshControl *ctl, const vsh
* Command string parsing
* ---------------
*/
-#define VSH_TK_ERROR -1
-#define VSH_TK_NONE 0
-#define VSH_TK_OPTION 1
-#define VSH_TK_DATA 2
-#define VSH_TK_END 3
-static int
-vshCommandGetToken(vshControl *ctl, char *str, char **end, char **res)
+static char *
+vshCmdStrGetArg(vshControl *ctl, char *str, char **end, int *last_arg)
{
- int tk = VSH_TK_NONE;
- int quote = FALSE;
- int sz = 0;
+ int quote = 0;
char *p = str;
- char *tkstr = NULL;
+ char *argstr = NULL;
+ char *res = NULL;
*end = NULL;
+ *last_arg = 0;
while (p && *p && (*p == ' ' || *p == '\t'))
p++;
if (p == NULL || *p == '\0')
- return VSH_TK_END;
+ return NULL;
+
if (*p == ';') {
- *end = ++p; /* = \0 or begin of next command */
- return VSH_TK_END;
+ *end = p + 1; /* = \0 or begin of next command */
+ return NULL;
}
+
+ res = argstr = p;
while (*p) {
- /* end of token is blank space or ';' */
- if ((quote == FALSE && (*p == ' ' || *p == '\t')) || *p == ';')
+ if (*p == '\\') { /* escape */
+ p++;
+ if (*p == '\0')
+ break;
+ } else if (*p == '"') { /* quote */
+ quote = !quote;
+ p++;
+ continue;
+ } else if ((!quote && (*p == ' ' || *p == '\t')) || *p == ';')
break;
- /* end of option name could be '=' */
- if (tk == VSH_TK_OPTION && *p == '=') {
- p++; /* skip '=' */
- break;
- }
+ *argstr++ = *p++;
+ }
+
+ if (*p != '\0') {
+ if (*p == ';')
+ *last_arg = 1;
+ *end = p + 1; /* skip the \0 braught by *argstr = '\0' */
+ } else
+ *end = p;
+ *argstr = '\0';
+
+ if (quote) {
+ vshError(ctl, "%s", _("missing \""));
+ return NULL;
+ }
+
+ return res;
+}
- if (tk == VSH_TK_NONE) {
- if (*p == '-' && *(p + 1) == '-' && *(p + 2)
+static vshCmd *
+vshCommandParseArgv(vshControl *ctl, int args, char *argv[])
+{
+ vshCmdOpt *first = NULL, *last = NULL;
+ const vshCmdDef *cmd;
+ vshCmd *c;
+ int i;
+ int data_ct = 0;
+
+ if (!(cmd = vshCmddefSearch(argv[0]))) {
+ vshError(ctl, _("unknown command: '%s'"), argv[0]);
+ goto syntaxError; /* ... or ignore this command only? */
+ }
+
+ for (i = 1; i < args; i++) {
+ vshCmdOpt *arg;
+ const vshCmdOptDef *opt;
+ char *p, *q;
+
+ p = vshStrdup(ctl, argv[i]);
+ if (*p == '-' && *(p + 1) == '-' && *(p + 2)
&& c_isalnum(*(p + 2))) {
- tk = VSH_TK_OPTION;
- p += 2;
- } else {
- tk = VSH_TK_DATA;
- if (*p == '"') {
- quote = TRUE;
- p++;
- } else {
- quote = FALSE;
+ q = strchr(p + 2, '=');
+ if (q) {
+ *q = '\0';
+ q = vshStrdup(ctl, q + 1);
+ }
+
+ if (!(opt = vshCmddefGetOption(cmd, p + 2))) {
+ vshError(ctl,
+ _("command '%s' doesn't support option --%s"),
+ cmd->name, p);
+ VIR_FREE(p);
+ VIR_FREE(q);
+ goto syntaxError;
+ }
+ VIR_FREE(p);
+
+ if (opt->type == VSH_OT_BOOL) {
+ if (q) {
+ vshError(ctl, _("invalid '=' after option --%s"),
+ opt->name);
+ VIR_FREE(q);
+ goto syntaxError;
}
+ } else if (!q) {
+ i++;
+ if (i == args) {
+ vshError(ctl,
+ _("expected syntax: --%s <%s>"),
+ opt->name,
+ opt->type ==
+ VSH_OT_INT ? _("number") : _("string"));
+ goto syntaxError;
+ }
+ q = vshStrdup(ctl, argv[i]);
+ }
+ } else {
+ q = p;
+ if (!(opt = vshCmddefGetData(cmd, data_ct++))) {
+ vshError(ctl, _("unexpected data '%s'"), q);
+ VIR_FREE(q);
+ goto syntaxError;
}
- tkstr = p; /* begin of token */
- } else if (quote && *p == '"') {
- quote = FALSE;
- p++;
- break; /* end of "..." token */
}
- p++;
- sz++;
+
+ arg = vshMalloc(ctl, sizeof(vshCmdOpt));
+ arg->def = opt;
+ arg->data = q;
+ arg->next = NULL;
+
+ if (!first)
+ first = arg;
+ if (last)
+ last->next = arg;
+ last = arg;
+
+ vshDebug(ctl, 4, "%s: %s(%s): %s\n", cmd->name, opt->name,
+ arg->data != p ? _("OPTION") : _("DATA"), arg->data);
}
- if (quote) {
- vshError(ctl, "%s", _("missing \""));
- return VSH_TK_ERROR;
+
+ c = vshMalloc(ctl, sizeof(vshCmd));
+
+ c->opts = first;
+ c->def = cmd;
+ c->next = NULL;
+
+ if (!vshCommandCheckOpts(ctl, c)) {
+ VIR_FREE(c);
+ goto syntaxError;
}
- if (tkstr == NULL || *tkstr == '\0' || p == NULL)
- return VSH_TK_END;
- if (sz == 0)
- return VSH_TK_END;
-
- *res = vshMalloc(ctl, sz + 1);
- memcpy(*res, tkstr, sz);
- *(*res + sz) = '\0';
+ return c;
- *end = p;
- return tk;
+syntaxError:
+ if (first)
+ vshCommandOptFree(first);
+ return NULL;
}
+
static int
vshCommandParse(vshControl *ctl, char *cmdstr)
{
char *str;
- char *tkdata = NULL;
vshCmd *clast = NULL;
- vshCmdOpt *first = NULL;
if (ctl->cmd) {
vshCommandFree(ctl->cmd);
@@ -10257,130 +10333,42 @@ vshCommandParse(vshControl *ctl, char *c
str = cmdstr;
while (str && *str) {
- vshCmdOpt *last = NULL;
- const vshCmdDef *cmd = NULL;
- int tk = VSH_TK_NONE;
- int data_ct = 0;
-
- first = NULL;
-
- while (tk != VSH_TK_END) {
- char *end = NULL;
- const vshCmdOptDef *opt = NULL;
-
- tkdata = NULL;
-
- /* get token */
- tk = vshCommandGetToken(ctl, str, &end, &tkdata);
-
- str = end;
-
- if (tk == VSH_TK_END) {
- VIR_FREE(tkdata);
- break;
- }
- if (tk == VSH_TK_ERROR)
+ vshCmd *c;
+ int args = 0;
+ char *argv[20];
+ char *arg;
+ int last_arg = 0;
+
+ while ((arg = vshCmdStrGetArg(ctl, str, &str, &last_arg)) != NULL) {
+ if (args == sizeof(argv) / sizeof(argv[0])) {
+ vshError(ctl, _("too many args"));
goto syntaxError;
-
- if (cmd == NULL) {
- /* first token must be command name */
- if (tk != VSH_TK_DATA) {
- vshError(ctl,
- _("unexpected token (command name): '%s'"),
- tkdata);
- goto syntaxError;
- }
- if (!(cmd = vshCmddefSearch(tkdata))) {
- vshError(ctl, _("unknown command: '%s'"), tkdata);
- goto syntaxError; /* ... or ignore this command only? */
- }
- VIR_FREE(tkdata);
- } else if (tk == VSH_TK_OPTION) {
- if (!(opt = vshCmddefGetOption(cmd, tkdata))) {
- vshError(ctl,
- _("command '%s' doesn't support option --%s"),
- cmd->name, tkdata);
- goto syntaxError;
- }
- VIR_FREE(tkdata); /* option name */
-
- if (opt->type != VSH_OT_BOOL) {
- /* option data */
- tk = vshCommandGetToken(ctl, str, &end, &tkdata);
- str = end;
- if (tk == VSH_TK_ERROR)
- goto syntaxError;
- if (tk != VSH_TK_DATA) {
- vshError(ctl,
- _("expected syntax: --%s <%s>"),
- opt->name,
- opt->type ==
- VSH_OT_INT ? _("number") : _("string"));
- goto syntaxError;
- }
- }
- } else if (tk == VSH_TK_DATA) {
- if (!(opt = vshCmddefGetData(cmd, data_ct++))) {
- vshError(ctl, _("unexpected data '%s'"), tkdata);
- goto syntaxError;
- }
- }
- if (opt) {
- /* save option */
- vshCmdOpt *arg = vshMalloc(ctl, sizeof(vshCmdOpt));
-
- arg->def = opt;
- arg->data = tkdata;
- arg->next = NULL;
- tkdata = NULL;
-
- if (!first)
- first = arg;
- if (last)
- last->next = arg;
- last = arg;
-
- vshDebug(ctl, 4, "%s: %s(%s): %s\n",
- cmd->name,
- opt->name,
- tk == VSH_TK_OPTION ? _("OPTION") : _("DATA"),
- arg->data);
}
- if (!str)
+ argv[args++] = arg;
+ if (last_arg)
break;
}
+ if (args == 0)
+ continue;
- /* command parsed -- allocate new struct for the command */
- if (cmd) {
- vshCmd *c = vshMalloc(ctl, sizeof(vshCmd));
-
- c->opts = first;
- c->def = cmd;
- c->next = NULL;
-
- if (!vshCommandCheckOpts(ctl, c)) {
- VIR_FREE(c);
- goto syntaxError;
- }
-
- if (!ctl->cmd)
- ctl->cmd = c;
- if (clast)
- clast->next = c;
- clast = c;
- }
+ c = vshCommandParseArgv(ctl, args, argv);
+ if (!c)
+ goto syntaxError;
+
+ if (!ctl->cmd)
+ ctl->cmd = c;
+ if (clast)
+ clast->next = c;
+ clast = c;
}
return TRUE;
- syntaxError:
+syntaxError:
if (ctl->cmd) {
vshCommandFree(ctl->cmd);
ctl->cmd = NULL;
}
- if (first)
- vshCommandOptFree(first);
- VIR_FREE(tkdata);
return FALSE;
}
@@ -10939,7 +10927,8 @@ static void
vshUsage(void)
{
const vshCmdDef *cmd;
- fprintf(stdout, _("\n%s [options] [commands]\n\n"
+ fprintf(stdout, _("\n%s [options]... [<command_name> args...]"
+ "\n%s [options]... <command_string>\n\n"
" options:\n"
" -c | --connect <uri> hypervisor connection URI\n"
" -r | --readonly connect readonly\n"
@@ -10949,7 +10938,7 @@ vshUsage(void)
" -t | --timing print timing information\n"
" -l | --log <file> output logging to file\n"
" -v | --version program version\n\n"
- " commands (non interactive mode):\n"), progname);
+ " commands (non interactive mode):\n"), progname, progname);
for (cmd = commands; cmd->name; cmd++)
fprintf(stdout,
@@ -11069,25 +11058,25 @@ vshParseArgv(vshControl *ctl, int argc,
if (argc > end) {
/* parse command */
- char *cmdstr;
- int sz = 0, ret;
+ int ret = TRUE;
ctl->imode = FALSE;
- for (i = end; i < argc; i++)
- sz += strlen(argv[i]) + 1; /* +1 is for blank space between items */
-
- cmdstr = vshCalloc(ctl, sz + 1, 1);
-
- for (i = end; i < argc; i++) {
- strncat(cmdstr, argv[i], sz);
- sz -= strlen(argv[i]);
- strncat(cmdstr, " ", sz--);
+ if (argc - end == 1) {
+ char *cmdstr = vshStrdup(ctl, argv[end]);
+ vshDebug(ctl, 2, "commands: \"%s\"\n", cmdstr);
+ ret = vshCommandParse(ctl, cmdstr);
+ VIR_FREE(cmdstr);
+ } else {
+ if (ctl->cmd) {
+ vshCommandFree(ctl->cmd);
+ ctl->cmd = NULL;
+ }
+ ctl->cmd = vshCommandParseArgv(ctl, argc - end, argv + end);
+ if (!ctl->cmd)
+ ret = FALSE;
}
- vshDebug(ctl, 2, "command: \"%s\"\n", cmdstr);
- ret = vshCommandParse(ctl, cmdstr);
- VIR_FREE(cmdstr);
return ret;
}
return TRUE;
14 years, 1 month
[libvirt] [PATCH 0/2] speed up qemu domain save by increasing dd blocksize
by Laine Stump
These two patches are posted together because applying the 2nd exposes
the bug fixed by the first.
Here are the results of tests I made with various block sizes before
deciding the 1MB really was the best balance (all tests were done on a
paused 512MB domain, saving to local disk on a Lenovo T61 laptop)
BS M:SS save image size
----- ---- ---------------
2048K - 0:56 476135451
1024K - 0:56 475090953
512k - 1:02 474564173
256k - 1:10 474303797
128k - 1:25 474176859
512 - 3:47 474085423 - the original
I didn't bother testing sizes between 512 and 128k, as there was still
significant improvement from 128k to 256k.
14 years, 1 month
[libvirt] Initial working Mac OS X libvirt client build
by Justin Clift
Hi all,
This is for anyone using the Homebrew package management system on Mac
OS X. :)
A first working (but still experimental) libvirt formula is online:
http://github.com/justinclift/libvirt
It includes the libvirt text mode client (virsh), and the libvirt
development libraries.
If you have time to test it and report success/failure/(etc), please do.
Be aware, for the moment, it pulls down a tarred up snapshot of libvirt
git, with a few trivial patches applied to make compiling work:
What works:
+ Remote connections using TLS (qemu+tls://) <-- encrypted
+ Remote connections using TCP (qemu+tls://) <-- not encrypted!
What doesn't work:
+ Remote connections using SSH (qemu+ssh://), if the server has
PolicyKit enabled. (possible bug, will look into it)
In theory, this means connecting to Ubuntu server should work,
as that uses groups to control access rather than PolicyKit.
Haven't tried it though, so if you do, please let me know how
it goes. ;)
Testing and feedback is encouraged. The aim here is to have the libvirt
client (virsh) plus development libraries work properly on OS X.
Please note, I'm new to OS X, github, and Homebrew, so if you notice
things that should be done better/differently/etc, please let me know. :)
Regards and best wishes,
Justin Clift
14 years, 2 months
[libvirt] Xen string2sexpr and sexpr2string lose quotes?
by Thomas Graves
Hello all,
I am running xen on rhel5 and using libvirt0.7.2 (I also tried 0.7.7) and it
looks like the routines string2sexpr and sexpr2string seem to lose the
quotes around the image args in the configuration.
Has anyone seen this and have a patch for this?
I have the following libvirt config:
<os>
<type>linux</type>
<kernel>/usr/lib/xen/boot/pv-grub-x86_64.gz</kernel>
<cmdline>(hd0,0)/grub/menu.lst</cmdline>
</os>
It generates the xm config info:
(image
(linux
(kernel /usr/lib/xen/boot/pv-grub-x86_64.gz)
(args '(hd0,0)/grub/menu.lst')
(device_model /usr/lib64/xen/bin/qemu-dm)
)
)
I call virDomainSetAutostart on the domain and traced it through and saw
that it gets the string quoted (args '(hd0,0)/grub/menu.lst') from xen then
ends up calling string2sexpr, changes the xend_on_start, and then
sexpr2string, and it ends up without quotes (args (hd0,0)/grub/menu.lst) and
that is what it sends back to xen. Xen then seems to chop it off to (args
('hd0,0'))
Thanks,
Tom
14 years, 2 months