[Libvir] [QEMU 3/3] the qemu driver & daemon

Daniel P. Berrange berrange at redhat.com
Mon Aug 28 11:33:27 UTC 2006


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  -=| 




More information about the libvir-list mailing list