
On Mon, Aug 28, 2006 at 04:55:09AM -0400, Daniel Veillard wrote:
On Mon, Aug 28, 2006 at 12:18:52AM +0100, Daniel P. Berrange wrote:
There is intended to be one qemud instance per UNIX user - the so called 'session' instance, and optionally one system global instance runing as root (or a system daemon account?) - the so called 'system' instance. When using libvirt, the URIs for each are 'qemu:///session' and 'qemu:///system' respectively.
I'm wondering what would be the role of the system instance. Aggregate the informations from the set of users running qemu when running as root ?
Well, the session instance is intended to fill the desktop user use-case, while the system instance is more aimed at a data-center use case where an admin might set up a bunch of persistently running QEMU instances on a server.
The UNIX socket for session instances is $HOME/.qemud and is chmod 0700 - no support is provided for users connecting to each other's instances. Although we could trivially extend to create a read-only socket $HOME/.qemud-ro if desired. The system instance is currently not finished but intended to run in /var/run/qemud or some such.
hum .... I'm not too fond of putting the socket directly in the user home directory, I would feel better with a .qemud directory, protected 700 by default and then have the socket mapped in that directory, I think it is more secure, a bit cleaner to not have socket in home dir, and gives a place to store informations if needed. Actually you already create .qemud.d for storage, can we just make it .qemud and store the socket there ?
Or we can use a socket not mapped in the filesystem at all, based on the user name, which usually avoid the race when checking and then opening.
Actually, the socket is already in the abstract namespace - i use the abstract path '\0$HOME/.qemud' - could easily put it in a dir below though
+static int qemudParseUUID(const char *uuid, + unsigned char *rawuuid) {
Should we make a lib subdir to avoid duplicating code like this ? Alone that doesn't sound worth it, but if there is more routines duplicated could be useful.
Ues, as karel pointed out, there are a number of utility functions from libvirt that I duplicated in the qemud/ directory primarily because I wanted to avoid the circular depedancy back onto libvirt from the daemon. I think it would be worthwhile having the various helper routines in some lib that we can then pull into both libvirt & the daemon as needed.
+ //virXMLError(VIR_ERR_NO_SOURCE, (const char *) target, 0); + //virXMLError(VIR_ERR_NO_TARGET, (const char *) source, 0); + printf("Bogus floppy\n"); + printf("Bogus cdomr\n"); + printf("alse %s %s\n", device, target);
Need to unify and make the usual wrappers for error code. Even if not linked in the libvirt lib, so that error messages could be carried back at the protocol level, if we put much logic in the qemud we will need some logging facilities, or transport errors, right ?
Yes, I need to rip out the debug code & formalize the set of error codes which can be returned to libvirt. Currently I catch every error and just return a generic -1, internal error. Obviously this needs to be better before the patch is merged.
+ obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics", ctxt); + if ((obj == NULL) || (obj->type != XPATH_NODESET) || + (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0)) { + vm->def.graphicsType = QEMUD_GRAPHICS_NONE; + } else { + prop = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "type"); + if (!strcmp((char *)prop, "vnc")) { + vm->def.graphicsType = QEMUD_GRAPHICS_VNC; + prop = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "port"); + if (prop) { + conv = NULL; + vm->def.vncPort = strtoll((const char*)prop, &conv, 10); + } else { + vm->def.vncPort = 0; + } + } + }
Hum ... if we have no graphic device what's going on ? the QEmu process is forked by a daemon, so there is no way to get back to the console... The console access is something we didn't tried to address so far in libvirt. At least some console logs would be useful, otherwise we have the problem of hitting asynchronous interface is we really want to give interactive access... Well we can probably live without :-)
There's a couple of different ways this can work - the VNC console, or we can hook up a serial device to the guest (and assume user puts appropriate kernl boot command line args in 'console=ttyS0'. I also expect to save the stderr and stdout from QEMU to a log file so user can see if stuff goes wrong. I expect VNC is the primary console though.
+ if (stat(server->configDir, &sb) < 0) { + if (errno == ENOENT) { + if (mkdir(server->configDir, 0700) < 0) + return -1; + } else { + return -1; + } + } else if (!S_ISDIR(sb.st_mode)) { + return -1; + }
Shouldn't we check the mode and owner if the directory already exists ? that should be in the stat informations.
Yes, worthwhile doing.
+ if (qemudFindVMByUUID(server, vm->def.uuid)) { + qemudFreeVM(vm); + printf("Duplicate domains, discarding %s\n", file); + return NULL; + }
UUID clashes due to users manually copying files may be more frequent than expected. Cloning is gonna be fun in general ...
Yes, I'm not entirely sure what we can do there - either document - "do not do that", or automatically re-generate the UUID if they have a duplicate (re-saving the cofig file to disk with the new UUID). I believe VMWare automatically re-generates the UUID if you manually copy a file, so its a reasonable approach to take. Could do the same with the Name if neccessary - just append '-1', '-2', or something on to the end of it.
+ if (qemudFindVMByName(server, vm->def.name)) { + qemudFreeVM(vm); + printf("Duplicate domains, discarding %s\n", file); + return NULL; + } [...] +int qemudScanConfigs(struct qemud_server *server) {
2 things here: 1/ caching if the modification timestamps of the directory and file didn't changed. I don't know how often the scanning will be done but it's not lightweight since it reparses everything 2/ name and uuid clashes could be detected here or when adding some.
If we wanted to be really clever we could use INotify to automatically re-scan. A simple approach though would just re-scan the directory comparing timestamps every minute or so & re-loading configs which have changed.
I scanned quickly the protocol part but I need to get my head around it :-)
There's a couple of important assumptions I apply in the network code which I should document further to help explain the way it works.
That's a lot of code ! One think I would like is to try to get all commenting at the same level, i.e. having every function carrying a comment header, That's something I will help with, maybe as a side effect of reviewing the code. Tell me how we could do that ? Maybe I could start with the simplest code from qemud.
-#define MAX_DRIVERS 5 +#define MAX_DRIVERS 10
I didn't expect that initially :-)
Hehe - took me a little while to track down that issue too - I just could not work out why nothing was working at first :-) 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 -=|