~ubuntu-branches/ubuntu/natty/libvirt/natty-proposed

« back to all changes in this revision

Viewing changes to .pc/9021-Allow-chardev-of-type-file-for-UML-domains.patch/src/uml/uml_driver.c

  • Committer: Bazaar Package Importer
  • Author(s): Soren Hansen
  • Date: 2010-08-23 14:24:06 UTC
  • Revision ID: james.westby@ubuntu.com-20100823142406-1jsss896fyjl13qp
Tags: 0.8.3-1ubuntu6
* FFe: LP: #622682.
* Replace 9019-Remove-wrong-check-for-uml-monitor-response-size.patch with
  9019-uml-fix-logic-bug-in-checking-reply-length.patch which is what ended
  up getting applied upstream.
* Add the following patches taken from upstream git:
  - 9021-Allow-chardev-of-type-file-for-UML-domains.patch
  - 9022-Rename-qemudShrinkDisks-to-virDomainDiskRemove-and-m.patch
  - 9023-Support-virDomainAttachDevice-and-virDomainDetachDev.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * uml_driver.c: core driver methods for managing UML guests
 
3
 *
 
4
 * Copyright (C) 2006-2010 Red Hat, Inc.
 
5
 * Copyright (C) 2006-2008 Daniel P. Berrange
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2.1 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this library; if not, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 
20
 *
 
21
 * Author: Daniel P. Berrange <berrange@redhat.com>
 
22
 */
 
23
 
 
24
#include <config.h>
 
25
 
 
26
#include <sys/types.h>
 
27
#include <sys/poll.h>
 
28
#include <dirent.h>
 
29
#include <limits.h>
 
30
#include <string.h>
 
31
#include <stdio.h>
 
32
#include <stdarg.h>
 
33
#include <stdlib.h>
 
34
#include <unistd.h>
 
35
#include <errno.h>
 
36
#include <sys/utsname.h>
 
37
#include <sys/stat.h>
 
38
#include <fcntl.h>
 
39
#include <signal.h>
 
40
#include <paths.h>
 
41
#include <pwd.h>
 
42
#include <stdio.h>
 
43
#include <sys/wait.h>
 
44
#include <sys/ioctl.h>
 
45
#include <sys/inotify.h>
 
46
#include <sys/un.h>
 
47
 
 
48
#include "uml_driver.h"
 
49
#include "uml_conf.h"
 
50
#include "event.h"
 
51
#include "buf.h"
 
52
#include "util.h"
 
53
#include "nodeinfo.h"
 
54
#include "stats_linux.h"
 
55
#include "capabilities.h"
 
56
#include "memory.h"
 
57
#include "uuid.h"
 
58
#include "domain_conf.h"
 
59
#include "datatypes.h"
 
60
#include "logging.h"
 
61
 
 
62
#define VIR_FROM_THIS VIR_FROM_UML
 
63
 
 
64
/* For storing short-lived temporary files. */
 
65
#define TEMPDIR LOCAL_STATE_DIR "/cache/libvirt"
 
66
 
 
67
typedef struct _umlDomainObjPrivate umlDomainObjPrivate;
 
68
typedef umlDomainObjPrivate *umlDomainObjPrivatePtr;
 
69
struct _umlDomainObjPrivate {
 
70
    int monitor;
 
71
    int monitorWatch;
 
72
};
 
73
 
 
74
 
 
75
static int umlShutdown(void);
 
76
 
 
77
static void *umlDomainObjPrivateAlloc(void)
 
78
{
 
79
    umlDomainObjPrivatePtr priv;
 
80
 
 
81
    if (VIR_ALLOC(priv) < 0)
 
82
        return NULL;
 
83
 
 
84
    priv->monitor = -1;
 
85
    priv->monitorWatch = -1;
 
86
 
 
87
    return priv;
 
88
}
 
89
 
 
90
static void umlDomainObjPrivateFree(void *data)
 
91
{
 
92
    umlDomainObjPrivatePtr priv = data;
 
93
 
 
94
    VIR_FREE(priv);
 
95
}
 
96
 
 
97
 
 
98
static void umlDriverLock(struct uml_driver *driver)
 
99
{
 
100
    virMutexLock(&driver->lock);
 
101
}
 
102
static void umlDriverUnlock(struct uml_driver *driver)
 
103
{
 
104
    virMutexUnlock(&driver->lock);
 
105
}
 
106
 
 
107
 
 
108
static int umlOpenMonitor(struct uml_driver *driver,
 
109
                          virDomainObjPtr vm);
 
110
static int umlReadPidFile(struct uml_driver *driver,
 
111
                          virDomainObjPtr vm);
 
112
 
 
113
static int umlSetCloseExec(int fd) {
 
114
    int flags;
 
115
    if ((flags = fcntl(fd, F_GETFD)) < 0)
 
116
        goto error;
 
117
    flags |= FD_CLOEXEC;
 
118
    if ((fcntl(fd, F_SETFD, flags)) < 0)
 
119
        goto error;
 
120
    return 0;
 
121
 error:
 
122
    VIR_ERROR0(_("Failed to set close-on-exec file descriptor flag"));
 
123
    return -1;
 
124
}
 
125
 
 
126
static int umlStartVMDaemon(virConnectPtr conn,
 
127
                            struct uml_driver *driver,
 
128
                            virDomainObjPtr vm);
 
129
 
 
130
static void umlShutdownVMDaemon(virConnectPtr conn,
 
131
                                struct uml_driver *driver,
 
132
                                virDomainObjPtr vm);
 
133
 
 
134
 
 
135
static int umlMonitorCommand(const struct uml_driver *driver,
 
136
                             const virDomainObjPtr vm,
 
137
                             const char *cmd,
 
138
                             char **reply);
 
139
 
 
140
static struct uml_driver *uml_driver = NULL;
 
141
 
 
142
struct umlAutostartData {
 
143
    struct uml_driver *driver;
 
144
    virConnectPtr conn;
 
145
};
 
146
 
 
147
static void
 
148
umlAutostartDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
 
149
{
 
150
    virDomainObjPtr vm = payload;
 
151
    const struct umlAutostartData *data = opaque;
 
152
 
 
153
    virDomainObjLock(vm);
 
154
    if (vm->autostart &&
 
155
        !virDomainObjIsActive(vm)) {
 
156
        virResetLastError();
 
157
        if (umlStartVMDaemon(data->conn, data->driver, vm) < 0) {
 
158
            virErrorPtr err = virGetLastError();
 
159
            VIR_ERROR(_("Failed to autostart VM '%s': %s"),
 
160
                      vm->def->name, err ? err->message : _("unknown error"));
 
161
        }
 
162
    }
 
163
    virDomainObjUnlock(vm);
 
164
}
 
165
 
 
166
static void
 
167
umlAutostartConfigs(struct uml_driver *driver) {
 
168
    /* XXX: Figure out a better way todo this. The domain
 
169
     * startup code needs a connection handle in order
 
170
     * to lookup the bridge associated with a virtual
 
171
     * network
 
172
     */
 
173
    virConnectPtr conn = virConnectOpen(driver->privileged ?
 
174
                                        "uml:///system" :
 
175
                                        "uml:///session");
 
176
    /* Ignoring NULL conn which is mostly harmless here */
 
177
 
 
178
    struct umlAutostartData data = { driver, conn };
 
179
 
 
180
    virHashForEach(driver->domains.objs, umlAutostartDomain, &data);
 
181
 
 
182
    if (conn)
 
183
        virConnectClose(conn);
 
184
}
 
185
 
 
186
 
 
187
static int
 
188
umlIdentifyOneChrPTY(struct uml_driver *driver,
 
189
                     virDomainObjPtr dom,
 
190
                     virDomainChrDefPtr def,
 
191
                     const char *dev)
 
192
{
 
193
    char *cmd;
 
194
    char *res = NULL;
 
195
    int retries = 0;
 
196
    if (virAsprintf(&cmd, "config %s%d", dev, def->target.port) < 0) {
 
197
        virReportOOMError();
 
198
        return -1;
 
199
    }
 
200
requery:
 
201
    if (umlMonitorCommand(driver, dom, cmd, &res) < 0)
 
202
        return -1;
 
203
 
 
204
    if (res && STRPREFIX(res, "pts:")) {
 
205
        VIR_FREE(def->data.file.path);
 
206
        if ((def->data.file.path = strdup(res + 4)) == NULL) {
 
207
            virReportOOMError();
 
208
            VIR_FREE(res);
 
209
            VIR_FREE(cmd);
 
210
            return -1;
 
211
        }
 
212
    } else if (!res || STRPREFIX(res, "pts")) {
 
213
        /* It can take a while to startup, so retry for
 
214
           upto 5 seconds */
 
215
        /* XXX should do this in a better non-blocking
 
216
           way somehow ...perhaps register a timer */
 
217
        if (retries++ < 50) {
 
218
            usleep(1000*10);
 
219
            goto requery;
 
220
        }
 
221
    }
 
222
 
 
223
    VIR_FREE(cmd);
 
224
    VIR_FREE(res);
 
225
    return 0;
 
226
}
 
227
 
 
228
static int
 
229
umlIdentifyChrPTY(struct uml_driver *driver,
 
230
                  virDomainObjPtr dom)
 
231
{
 
232
    int i;
 
233
 
 
234
    if (dom->def->console &&
 
235
        dom->def->console->type == VIR_DOMAIN_CHR_TYPE_PTY)
 
236
        if (umlIdentifyOneChrPTY(driver, dom,
 
237
                                 dom->def->console, "con") < 0)
 
238
            return -1;
 
239
 
 
240
    for (i = 0 ; i < dom->def->nserials; i++)
 
241
        if (dom->def->serials[i]->type == VIR_DOMAIN_CHR_TYPE_PTY &&
 
242
            umlIdentifyOneChrPTY(driver, dom,
 
243
                                 dom->def->serials[i], "ssl") < 0)
 
244
            return -1;
 
245
 
 
246
    return 0;
 
247
}
 
248
 
 
249
static void
 
250
umlInotifyEvent(int watch,
 
251
                int fd,
 
252
                int events ATTRIBUTE_UNUSED,
 
253
                void *data)
 
254
{
 
255
    char buf[1024];
 
256
    struct inotify_event *e;
 
257
    int got;
 
258
    char *tmp, *name;
 
259
    struct uml_driver *driver = data;
 
260
    virDomainObjPtr dom;
 
261
 
 
262
    umlDriverLock(driver);
 
263
    if (watch != driver->inotifyWatch)
 
264
        goto cleanup;
 
265
 
 
266
reread:
 
267
    got = read(fd, buf, sizeof(buf));
 
268
    if (got == -1) {
 
269
        if (errno == EINTR)
 
270
            goto reread;
 
271
        goto cleanup;
 
272
    }
 
273
 
 
274
    tmp = buf;
 
275
    while (got) {
 
276
        if (got < sizeof(struct inotify_event))
 
277
            goto cleanup; /* bad */
 
278
 
 
279
        e = (struct inotify_event *)tmp;
 
280
        tmp += sizeof(struct inotify_event);
 
281
        got -= sizeof(struct inotify_event);
 
282
 
 
283
        if (got < e->len)
 
284
            goto cleanup;
 
285
 
 
286
        tmp += e->len;
 
287
        got -= e->len;
 
288
 
 
289
        name = (char *)&(e->name);
 
290
 
 
291
        dom = virDomainFindByName(&driver->domains, name);
 
292
 
 
293
        if (!dom) {
 
294
            continue;
 
295
        }
 
296
 
 
297
        if (e->mask & IN_DELETE) {
 
298
            VIR_DEBUG("Got inotify domain shutdown '%s'", name);
 
299
            if (!virDomainObjIsActive(dom)) {
 
300
                virDomainObjUnlock(dom);
 
301
                continue;
 
302
            }
 
303
 
 
304
            umlShutdownVMDaemon(NULL, driver, dom);
 
305
        } else if (e->mask & (IN_CREATE | IN_MODIFY)) {
 
306
            VIR_DEBUG("Got inotify domain startup '%s'", name);
 
307
            if (virDomainObjIsActive(dom)) {
 
308
                virDomainObjUnlock(dom);
 
309
                continue;
 
310
            }
 
311
 
 
312
            if (umlReadPidFile(driver, dom) < 0) {
 
313
                virDomainObjUnlock(dom);
 
314
                continue;
 
315
            }
 
316
 
 
317
            dom->def->id = driver->nextvmid++;
 
318
            dom->state = VIR_DOMAIN_RUNNING;
 
319
 
 
320
            if (umlOpenMonitor(driver, dom) < 0) {
 
321
                VIR_WARN0("Could not open monitor for new domain");
 
322
                umlShutdownVMDaemon(NULL, driver, dom);
 
323
            } else if (umlIdentifyChrPTY(driver, dom) < 0) {
 
324
                VIR_WARN0("Could not identify charater devices for new domain");
 
325
                umlShutdownVMDaemon(NULL, driver, dom);
 
326
            }
 
327
        }
 
328
        virDomainObjUnlock(dom);
 
329
    }
 
330
 
 
331
cleanup:
 
332
    umlDriverUnlock(driver);
 
333
}
 
334
 
 
335
/**
 
336
 * umlStartup:
 
337
 *
 
338
 * Initialization function for the Uml daemon
 
339
 */
 
340
static int
 
341
umlStartup(int privileged) {
 
342
    uid_t uid = geteuid();
 
343
    char *base = NULL;
 
344
    char driverConf[PATH_MAX];
 
345
    char *userdir = NULL;
 
346
 
 
347
    if (VIR_ALLOC(uml_driver) < 0)
 
348
        return -1;
 
349
 
 
350
    uml_driver->privileged = privileged;
 
351
 
 
352
    if (virMutexInit(&uml_driver->lock) < 0) {
 
353
        VIR_FREE(uml_driver);
 
354
        return -1;
 
355
    }
 
356
    umlDriverLock(uml_driver);
 
357
 
 
358
    /* Don't have a dom0 so start from 1 */
 
359
    uml_driver->nextvmid = 1;
 
360
    uml_driver->inotifyWatch = -1;
 
361
 
 
362
    if (virDomainObjListInit(&uml_driver->domains) < 0)
 
363
        goto error;
 
364
 
 
365
    userdir = virGetUserDirectory(uid);
 
366
    if (!userdir)
 
367
        goto error;
 
368
 
 
369
    if (privileged) {
 
370
        if (virAsprintf(&uml_driver->logDir,
 
371
                        "%s/log/libvirt/uml", LOCAL_STATE_DIR) == -1)
 
372
            goto out_of_memory;
 
373
 
 
374
        if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
 
375
            goto out_of_memory;
 
376
    } else {
 
377
 
 
378
        if (virAsprintf(&uml_driver->logDir,
 
379
                        "%s/.libvirt/uml/log", userdir) == -1)
 
380
            goto out_of_memory;
 
381
 
 
382
        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1)
 
383
            goto out_of_memory;
 
384
    }
 
385
 
 
386
    if (virAsprintf(&uml_driver->monitorDir,
 
387
                    "%s/.uml", userdir) == -1)
 
388
        goto out_of_memory;
 
389
 
 
390
    /* Configuration paths are either ~/.libvirt/uml/... (session) or
 
391
     * /etc/libvirt/uml/... (system).
 
392
     */
 
393
    if (snprintf (driverConf, sizeof(driverConf), "%s/uml.conf", base) == -1)
 
394
        goto out_of_memory;
 
395
    driverConf[sizeof(driverConf)-1] = '\0';
 
396
 
 
397
    if (virAsprintf(&uml_driver->configDir, "%s/uml", base) == -1)
 
398
        goto out_of_memory;
 
399
 
 
400
    if (virAsprintf(&uml_driver->autostartDir, "%s/uml/autostart", base) == -1)
 
401
        goto out_of_memory;
 
402
 
 
403
    VIR_FREE(base);
 
404
 
 
405
    if ((uml_driver->caps = umlCapsInit()) == NULL)
 
406
        goto out_of_memory;
 
407
 
 
408
    uml_driver->caps->privateDataAllocFunc = umlDomainObjPrivateAlloc;
 
409
    uml_driver->caps->privateDataFreeFunc = umlDomainObjPrivateFree;
 
410
 
 
411
    if ((uml_driver->inotifyFD = inotify_init()) < 0) {
 
412
        VIR_ERROR0(_("cannot initialize inotify"));
 
413
        goto error;
 
414
    }
 
415
 
 
416
    if (virFileMakePath(uml_driver->monitorDir) != 0) {
 
417
        char ebuf[1024];
 
418
        VIR_ERROR(_("Failed to create monitor directory %s: %s"),
 
419
               uml_driver->monitorDir, virStrerror(errno, ebuf, sizeof ebuf));
 
420
        goto error;
 
421
    }
 
422
 
 
423
    VIR_INFO("Adding inotify watch on %s", uml_driver->monitorDir);
 
424
    if (inotify_add_watch(uml_driver->inotifyFD,
 
425
                          uml_driver->monitorDir,
 
426
                          IN_CREATE | IN_MODIFY | IN_DELETE) < 0) {
 
427
        goto error;
 
428
    }
 
429
 
 
430
    if ((uml_driver->inotifyWatch =
 
431
         virEventAddHandle(uml_driver->inotifyFD, POLLIN,
 
432
                           umlInotifyEvent, uml_driver, NULL)) < 0)
 
433
        goto error;
 
434
 
 
435
    if (virDomainLoadAllConfigs(uml_driver->caps,
 
436
                                &uml_driver->domains,
 
437
                                uml_driver->configDir,
 
438
                                uml_driver->autostartDir,
 
439
                                0, NULL, NULL) < 0)
 
440
        goto error;
 
441
 
 
442
    umlAutostartConfigs(uml_driver);
 
443
 
 
444
    umlDriverUnlock(uml_driver);
 
445
    VIR_FREE(userdir);
 
446
 
 
447
    return 0;
 
448
 
 
449
out_of_memory:
 
450
    VIR_ERROR0(_("umlStartup: out of memory"));
 
451
 
 
452
error:
 
453
    VIR_FREE(userdir);
 
454
    VIR_FREE(base);
 
455
    umlDriverUnlock(uml_driver);
 
456
    umlShutdown();
 
457
    return -1;
 
458
}
 
459
 
 
460
/**
 
461
 * umlReload:
 
462
 *
 
463
 * Function to restart the Uml daemon, it will recheck the configuration
 
464
 * files and update its state and the networking
 
465
 */
 
466
static int
 
467
umlReload(void) {
 
468
    if (!uml_driver)
 
469
        return 0;
 
470
 
 
471
    umlDriverLock(uml_driver);
 
472
    virDomainLoadAllConfigs(uml_driver->caps,
 
473
                            &uml_driver->domains,
 
474
                            uml_driver->configDir,
 
475
                            uml_driver->autostartDir,
 
476
                            0, NULL, NULL);
 
477
 
 
478
    umlAutostartConfigs(uml_driver);
 
479
    umlDriverUnlock(uml_driver);
 
480
 
 
481
    return 0;
 
482
}
 
483
 
 
484
/**
 
485
 * umlActive:
 
486
 *
 
487
 * Checks if the Uml daemon is active, i.e. has an active domain or
 
488
 * an active network
 
489
 *
 
490
 * Returns 1 if active, 0 otherwise
 
491
 */
 
492
static int
 
493
umlActive(void) {
 
494
    int active = 0;
 
495
 
 
496
    if (!uml_driver)
 
497
        return 0;
 
498
 
 
499
    umlDriverLock(uml_driver);
 
500
    active = virDomainObjListNumOfDomains(&uml_driver->domains, 1);
 
501
    umlDriverUnlock(uml_driver);
 
502
 
 
503
    return active;
 
504
}
 
505
 
 
506
static void
 
507
umlShutdownOneVM(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
 
508
{
 
509
    virDomainObjPtr dom = payload;
 
510
    struct uml_driver *driver = opaque;
 
511
 
 
512
    virDomainObjLock(dom);
 
513
    if (virDomainObjIsActive(dom))
 
514
        umlShutdownVMDaemon(NULL, driver, dom);
 
515
    virDomainObjUnlock(dom);
 
516
}
 
517
 
 
518
/**
 
519
 * umlShutdown:
 
520
 *
 
521
 * Shutdown the Uml daemon, it will stop all active domains and networks
 
522
 */
 
523
static int
 
524
umlShutdown(void) {
 
525
    if (!uml_driver)
 
526
        return -1;
 
527
 
 
528
    umlDriverLock(uml_driver);
 
529
    if (uml_driver->inotifyWatch != -1)
 
530
        virEventRemoveHandle(uml_driver->inotifyWatch);
 
531
    close(uml_driver->inotifyFD);
 
532
    virCapabilitiesFree(uml_driver->caps);
 
533
 
 
534
    /* shutdown active VMs
 
535
     * XXX allow them to stay around & reconnect */
 
536
    virHashForEach(uml_driver->domains.objs, umlShutdownOneVM, uml_driver);
 
537
 
 
538
    virDomainObjListDeinit(&uml_driver->domains);
 
539
 
 
540
    VIR_FREE(uml_driver->logDir);
 
541
    VIR_FREE(uml_driver->configDir);
 
542
    VIR_FREE(uml_driver->autostartDir);
 
543
    VIR_FREE(uml_driver->monitorDir);
 
544
 
 
545
    if (uml_driver->brctl)
 
546
        brShutdown(uml_driver->brctl);
 
547
 
 
548
    umlDriverUnlock(uml_driver);
 
549
    virMutexDestroy(&uml_driver->lock);
 
550
    VIR_FREE(uml_driver);
 
551
 
 
552
    return 0;
 
553
}
 
554
 
 
555
 
 
556
static int umlReadPidFile(struct uml_driver *driver,
 
557
                          virDomainObjPtr vm)
 
558
{
 
559
    int rc = -1;
 
560
    FILE *file;
 
561
    char *pidfile = NULL;
 
562
    int retries = 0;
 
563
 
 
564
    vm->pid = -1;
 
565
    if (virAsprintf(&pidfile, "%s/%s/pid",
 
566
                    driver->monitorDir, vm->def->name) < 0) {
 
567
        virReportOOMError();
 
568
        return -1;
 
569
    }
 
570
 
 
571
reopen:
 
572
    if (!(file = fopen(pidfile, "r"))) {
 
573
        if (errno == ENOENT &&
 
574
            retries++ < 50) {
 
575
            usleep(1000 * 100);
 
576
            goto reopen;
 
577
        }
 
578
        goto cleanup;
 
579
    }
 
580
 
 
581
    if (fscanf(file, "%d", &vm->pid) != 1) {
 
582
        errno = EINVAL;
 
583
        fclose(file);
 
584
        goto cleanup;
 
585
    }
 
586
 
 
587
    if (fclose(file) < 0)
 
588
        goto cleanup;
 
589
 
 
590
    rc = 0;
 
591
 
 
592
 cleanup:
 
593
    if (rc != 0)
 
594
        virReportSystemError(errno,
 
595
                             _("failed to read pid: %s"),
 
596
                             pidfile);
 
597
    VIR_FREE(pidfile);
 
598
    return rc;
 
599
}
 
600
 
 
601
static int umlMonitorAddress(const struct uml_driver *driver,
 
602
                             virDomainObjPtr vm,
 
603
                             struct sockaddr_un *addr) {
 
604
    char *sockname;
 
605
    int retval = 0;
 
606
 
 
607
    if (virAsprintf(&sockname, "%s/%s/mconsole",
 
608
                    driver->monitorDir, vm->def->name) < 0) {
 
609
        virReportOOMError();
 
610
        return -1;
 
611
    }
 
612
 
 
613
    memset(addr, 0, sizeof *addr);
 
614
    addr->sun_family = AF_UNIX;
 
615
    if (virStrcpyStatic(addr->sun_path, sockname) == NULL) {
 
616
        umlReportError(VIR_ERR_INTERNAL_ERROR,
 
617
                       _("Unix path %s too long for destination"), sockname);
 
618
        retval = -1;
 
619
    }
 
620
    VIR_FREE(sockname);
 
621
    return retval;
 
622
}
 
623
 
 
624
static int umlOpenMonitor(struct uml_driver *driver,
 
625
                          virDomainObjPtr vm) {
 
626
    struct sockaddr_un addr;
 
627
    struct stat sb;
 
628
    int retries = 0;
 
629
    umlDomainObjPrivatePtr priv = vm->privateData;
 
630
 
 
631
    if (umlMonitorAddress(driver, vm, &addr) < 0)
 
632
        return -1;
 
633
 
 
634
    VIR_DEBUG("Dest address for monitor is '%s'", addr.sun_path);
 
635
restat:
 
636
    if (stat(addr.sun_path, &sb) < 0) {
 
637
        if (errno == ENOENT &&
 
638
            retries++ < 50) {
 
639
            usleep(1000 * 100);
 
640
            goto restat;
 
641
        }
 
642
        return -1;
 
643
    }
 
644
 
 
645
    if ((priv->monitor = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
 
646
        virReportSystemError(errno,
 
647
                             "%s", _("cannot open socket"));
 
648
        return -1;
 
649
    }
 
650
 
 
651
    memset(addr.sun_path, 0, sizeof addr.sun_path);
 
652
    sprintf(addr.sun_path + 1, "libvirt-uml-%u", vm->pid);
 
653
    VIR_DEBUG("Reply address for monitor is '%s'", addr.sun_path+1);
 
654
    if (bind(priv->monitor, (struct sockaddr *)&addr, sizeof addr) < 0) {
 
655
        virReportSystemError(errno,
 
656
                             "%s", _("cannot bind socket"));
 
657
        close(priv->monitor);
 
658
        priv->monitor = -1;
 
659
        return -1;
 
660
    }
 
661
 
 
662
    return 0;
 
663
}
 
664
 
 
665
 
 
666
#define MONITOR_MAGIC 0xcafebabe
 
667
#define MONITOR_BUFLEN 512
 
668
#define MONITOR_VERSION 2
 
669
 
 
670
struct monitor_request {
 
671
    uint32_t magic;
 
672
    uint32_t version;
 
673
    uint32_t length;
 
674
    char data[MONITOR_BUFLEN];
 
675
};
 
676
 
 
677
struct monitor_response {
 
678
    uint32_t error;
 
679
    uint32_t extra;
 
680
    uint32_t length;
 
681
    char data[MONITOR_BUFLEN];
 
682
};
 
683
 
 
684
 
 
685
static int umlMonitorCommand(const struct uml_driver *driver,
 
686
                             const virDomainObjPtr vm,
 
687
                             const char *cmd,
 
688
                             char **reply)
 
689
{
 
690
    struct monitor_request req;
 
691
    struct monitor_response res;
 
692
    char *retdata = NULL;
 
693
    int retlen = 0, ret = 0;
 
694
    struct sockaddr_un addr;
 
695
    unsigned int addrlen;
 
696
    umlDomainObjPrivatePtr priv = vm->privateData;
 
697
 
 
698
    VIR_DEBUG("Run command '%s'", cmd);
 
699
 
 
700
    *reply = NULL;
 
701
 
 
702
    if (umlMonitorAddress(driver, vm, &addr) < 0)
 
703
        return -1;
 
704
 
 
705
    memset(&req, 0, sizeof(req));
 
706
    req.magic = MONITOR_MAGIC;
 
707
    req.version = MONITOR_VERSION;
 
708
    req.length = strlen(cmd);
 
709
    if (req.length > (MONITOR_BUFLEN-1)) {
 
710
        virReportSystemError(EINVAL,
 
711
                             _("cannot send too long command %s (%d bytes)"),
 
712
                             cmd, req.length);
 
713
        return -1;
 
714
    }
 
715
    if (virStrcpyStatic(req.data, cmd) == NULL) {
 
716
        umlReportError(VIR_ERR_INTERNAL_ERROR,
 
717
                       _("Command %s too long for destination"), cmd);
 
718
        return -1;
 
719
    }
 
720
 
 
721
    if (sendto(priv->monitor, &req, sizeof req, 0,
 
722
               (struct sockaddr *)&addr, sizeof addr) != (sizeof req)) {
 
723
        virReportSystemError(errno,
 
724
                             _("cannot send command %s"),
 
725
                             cmd);
 
726
        return -1;
 
727
    }
 
728
 
 
729
    do {
 
730
        ssize_t nbytes;
 
731
        addrlen = sizeof(addr);
 
732
        nbytes = recvfrom(priv->monitor, &res, sizeof res, 0,
 
733
                          (struct sockaddr *)&addr, &addrlen);
 
734
        if (nbytes < 0) {
 
735
            if (errno == EAGAIN || errno == EINTR)
 
736
                continue;
 
737
            virReportSystemError(errno, _("cannot read reply %s"), cmd);
 
738
            goto error;
 
739
        }
 
740
        /* Ensure res.length is safe to read before validating its value.  */
 
741
        if (nbytes < offsetof(struct monitor_request, data) ||
 
742
            nbytes < offsetof(struct monitor_request, data) + res.length) {
 
743
            virReportSystemError(0, _("incomplete reply %s"), cmd);
 
744
            goto error;
 
745
        }
 
746
 
 
747
        if (VIR_REALLOC_N(retdata, retlen + res.length) < 0) {
 
748
            virReportOOMError();
 
749
            goto error;
 
750
        }
 
751
        memcpy(retdata + retlen, res.data, res.length);
 
752
        retlen += res.length - 1;
 
753
        retdata[retlen] = '\0';
 
754
 
 
755
        if (res.error)
 
756
            ret = -1;
 
757
 
 
758
    } while (res.extra);
 
759
 
 
760
    VIR_DEBUG("Command reply is '%s'", NULLSTR(retdata));
 
761
 
 
762
    if (ret < 0)
 
763
        VIR_FREE(retdata);
 
764
    else
 
765
        *reply = retdata;
 
766
 
 
767
    return ret;
 
768
 
 
769
error:
 
770
    VIR_FREE(retdata);
 
771
    return -1;
 
772
}
 
773
 
 
774
 
 
775
static int umlCleanupTapDevices(virConnectPtr conn ATTRIBUTE_UNUSED,
 
776
                                virDomainObjPtr vm) {
 
777
    int i;
 
778
    int err;
 
779
    int ret = 0;
 
780
    brControl *brctl = NULL;
 
781
    VIR_ERROR0(_("Cleanup tap"));
 
782
    if (brInit(&brctl) < 0)
 
783
        return -1;
 
784
 
 
785
    for (i = 0 ; i < vm->def->nnets ; i++) {
 
786
        virDomainNetDefPtr def = vm->def->nets[i];
 
787
 
 
788
        if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
 
789
            def->type != VIR_DOMAIN_NET_TYPE_NETWORK)
 
790
            continue;
 
791
 
 
792
        VIR_ERROR(_("Cleanup '%s'"), def->ifname);
 
793
        err = brDeleteTap(brctl, def->ifname);
 
794
        if (err) {
 
795
            VIR_ERROR(_("Cleanup failed %d"), err);
 
796
            ret = -1;
 
797
        }
 
798
    }
 
799
    VIR_ERROR0(_("Cleanup tap done"));
 
800
    brShutdown(brctl);
 
801
    return ret;
 
802
}
 
803
 
 
804
static int umlStartVMDaemon(virConnectPtr conn,
 
805
                            struct uml_driver *driver,
 
806
                            virDomainObjPtr vm) {
 
807
    const char **argv = NULL, **tmp;
 
808
    const char **progenv = NULL;
 
809
    int i, ret;
 
810
    pid_t pid;
 
811
    char *logfile;
 
812
    int logfd = -1;
 
813
    struct stat sb;
 
814
    fd_set keepfd;
 
815
    char ebuf[1024];
 
816
    umlDomainObjPrivatePtr priv = vm->privateData;
 
817
 
 
818
    FD_ZERO(&keepfd);
 
819
 
 
820
    if (virDomainObjIsActive(vm)) {
 
821
        umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
 
822
                       _("VM is already active"));
 
823
        return -1;
 
824
    }
 
825
 
 
826
    if (!vm->def->os.kernel) {
 
827
        umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
 
828
                       _("no kernel specified"));
 
829
        return -1;
 
830
    }
 
831
    /* Make sure the binary we are about to try exec'ing exists.
 
832
     * Technically we could catch the exec() failure, but that's
 
833
     * in a sub-process so its hard to feed back a useful error
 
834
     */
 
835
    if (stat(vm->def->os.kernel, &sb) < 0) {
 
836
        virReportSystemError(errno,
 
837
                             _("Cannot find UML kernel %s"),
 
838
                             vm->def->os.kernel);
 
839
        return -1;
 
840
    }
 
841
 
 
842
    if (virFileMakePath(driver->logDir) != 0) {
 
843
        virReportSystemError(errno,
 
844
                             _("cannot create log directory %s"),
 
845
                             driver->logDir);
 
846
        return -1;
 
847
    }
 
848
 
 
849
    if (virAsprintf(&logfile, "%s/%s.log",
 
850
                    driver->logDir, vm->def->name) < 0) {
 
851
        virReportOOMError();
 
852
        return -1;
 
853
    }
 
854
 
 
855
    if ((logfd = open(logfile, O_CREAT | O_TRUNC | O_WRONLY,
 
856
                      S_IRUSR | S_IWUSR)) < 0) {
 
857
        virReportSystemError(errno,
 
858
                             _("failed to create logfile %s"),
 
859
                             logfile);
 
860
        VIR_FREE(logfile);
 
861
        return -1;
 
862
    }
 
863
    VIR_FREE(logfile);
 
864
 
 
865
    if (umlSetCloseExec(logfd) < 0) {
 
866
        virReportSystemError(errno,
 
867
                             "%s", _("Unable to set VM logfile close-on-exec flag"));
 
868
        close(logfd);
 
869
        return -1;
 
870
    }
 
871
 
 
872
    if (umlBuildCommandLine(conn, driver, vm,
 
873
                            &argv, &progenv) < 0) {
 
874
        close(logfd);
 
875
        umlCleanupTapDevices(conn, vm);
 
876
        return -1;
 
877
    }
 
878
 
 
879
    tmp = progenv;
 
880
    while (*tmp) {
 
881
        if (safewrite(logfd, *tmp, strlen(*tmp)) < 0)
 
882
            VIR_WARN("Unable to write envv to logfile: %s",
 
883
                   virStrerror(errno, ebuf, sizeof ebuf));
 
884
        if (safewrite(logfd, " ", 1) < 0)
 
885
            VIR_WARN("Unable to write envv to logfile: %s",
 
886
                   virStrerror(errno, ebuf, sizeof ebuf));
 
887
        tmp++;
 
888
    }
 
889
    tmp = argv;
 
890
    while (*tmp) {
 
891
        if (safewrite(logfd, *tmp, strlen(*tmp)) < 0)
 
892
            VIR_WARN("Unable to write argv to logfile: %s",
 
893
                   virStrerror(errno, ebuf, sizeof ebuf));
 
894
        if (safewrite(logfd, " ", 1) < 0)
 
895
            VIR_WARN("Unable to write argv to logfile: %s",
 
896
                   virStrerror(errno, ebuf, sizeof ebuf));
 
897
        tmp++;
 
898
    }
 
899
    if (safewrite(logfd, "\n", 1) < 0)
 
900
        VIR_WARN("Unable to write argv to logfile: %s",
 
901
                 virStrerror(errno, ebuf, sizeof ebuf));
 
902
 
 
903
    priv->monitor = -1;
 
904
 
 
905
    ret = virExecDaemonize(argv, progenv, &keepfd, &pid,
 
906
                           -1, &logfd, &logfd,
 
907
                           VIR_EXEC_CLEAR_CAPS,
 
908
                           NULL, NULL, NULL);
 
909
    close(logfd);
 
910
 
 
911
    for (i = 0 ; argv[i] ; i++)
 
912
        VIR_FREE(argv[i]);
 
913
    VIR_FREE(argv);
 
914
 
 
915
    for (i = 0 ; progenv[i] ; i++)
 
916
        VIR_FREE(progenv[i]);
 
917
    VIR_FREE(progenv);
 
918
 
 
919
    if (ret < 0)
 
920
        umlCleanupTapDevices(conn, vm);
 
921
 
 
922
    /* NB we don't mark it running here - we do that async
 
923
       with inotify */
 
924
    /* XXX what if someone else tries to start it again
 
925
       before we get the inotification ? Sounds like
 
926
       trouble.... */
 
927
 
 
928
    return ret;
 
929
}
 
930
 
 
931
static void umlShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
 
932
                                struct uml_driver *driver ATTRIBUTE_UNUSED,
 
933
                                virDomainObjPtr vm)
 
934
{
 
935
    int ret;
 
936
    umlDomainObjPrivatePtr priv = vm->privateData;
 
937
 
 
938
    if (!virDomainObjIsActive(vm))
 
939
        return;
 
940
 
 
941
    virKillProcess(vm->pid, SIGTERM);
 
942
 
 
943
    if (priv->monitor != -1)
 
944
        close(priv->monitor);
 
945
    priv->monitor = -1;
 
946
 
 
947
    if ((ret = waitpid(vm->pid, NULL, 0)) != vm->pid) {
 
948
        VIR_WARN("Got unexpected pid %d != %d",
 
949
               ret, vm->pid);
 
950
    }
 
951
 
 
952
    vm->pid = -1;
 
953
    vm->def->id = -1;
 
954
    vm->state = VIR_DOMAIN_SHUTOFF;
 
955
 
 
956
    umlCleanupTapDevices(conn, vm);
 
957
 
 
958
    if (vm->newDef) {
 
959
        virDomainDefFree(vm->def);
 
960
        vm->def = vm->newDef;
 
961
        vm->def->id = -1;
 
962
        vm->newDef = NULL;
 
963
    }
 
964
}
 
965
 
 
966
 
 
967
static virDrvOpenStatus umlOpen(virConnectPtr conn,
 
968
                                virConnectAuthPtr auth ATTRIBUTE_UNUSED,
 
969
                                int flags ATTRIBUTE_UNUSED) {
 
970
    if (conn->uri == NULL) {
 
971
        if (uml_driver == NULL)
 
972
            return VIR_DRV_OPEN_DECLINED;
 
973
 
 
974
        conn->uri = xmlParseURI(uml_driver->privileged ?
 
975
                                "uml:///system" :
 
976
                                "uml:///session");
 
977
        if (!conn->uri) {
 
978
            virReportOOMError();
 
979
            return VIR_DRV_OPEN_ERROR;
 
980
        }
 
981
    } else {
 
982
        if (conn->uri->scheme == NULL ||
 
983
            STRNEQ (conn->uri->scheme, "uml"))
 
984
            return VIR_DRV_OPEN_DECLINED;
 
985
 
 
986
        /* Allow remote driver to deal with URIs with hostname server */
 
987
        if (conn->uri->server != NULL)
 
988
            return VIR_DRV_OPEN_DECLINED;
 
989
 
 
990
 
 
991
        /* Check path and tell them correct path if they made a mistake */
 
992
        if (uml_driver->privileged) {
 
993
            if (STRNEQ (conn->uri->path, "/system") &&
 
994
                STRNEQ (conn->uri->path, "/session")) {
 
995
                umlReportError(VIR_ERR_INTERNAL_ERROR,
 
996
                               _("unexpected UML URI path '%s', try uml:///system"),
 
997
                               conn->uri->path);
 
998
                return VIR_DRV_OPEN_ERROR;
 
999
            }
 
1000
        } else {
 
1001
            if (STRNEQ (conn->uri->path, "/session")) {
 
1002
                umlReportError(VIR_ERR_INTERNAL_ERROR,
 
1003
                               _("unexpected UML URI path '%s', try uml:///session"),
 
1004
                               conn->uri->path);
 
1005
                return VIR_DRV_OPEN_ERROR;
 
1006
            }
 
1007
        }
 
1008
 
 
1009
        /* URI was good, but driver isn't active */
 
1010
        if (uml_driver == NULL) {
 
1011
            umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
 
1012
                           _("uml state driver is not active"));
 
1013
            return VIR_DRV_OPEN_ERROR;
 
1014
        }
 
1015
    }
 
1016
 
 
1017
    conn->privateData = uml_driver;
 
1018
 
 
1019
    return VIR_DRV_OPEN_SUCCESS;
 
1020
}
 
1021
 
 
1022
static int umlClose(virConnectPtr conn) {
 
1023
    /*struct uml_driver *driver = conn->privateData;*/
 
1024
 
 
1025
    conn->privateData = NULL;
 
1026
 
 
1027
    return 0;
 
1028
}
 
1029
 
 
1030
static const char *umlGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
 
1031
    return "UML";
 
1032
}
 
1033
 
 
1034
 
 
1035
static int umlIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
 
1036
{
 
1037
    /* Trivially secure, since always inside the daemon */
 
1038
    return 1;
 
1039
}
 
1040
 
 
1041
 
 
1042
static int umlIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
 
1043
{
 
1044
    /* Not encrypted, but remote driver takes care of that */
 
1045
    return 0;
 
1046
}
 
1047
 
 
1048
 
 
1049
static char *umlGetCapabilities(virConnectPtr conn) {
 
1050
    struct uml_driver *driver = (struct uml_driver *)conn->privateData;
 
1051
    char *xml;
 
1052
 
 
1053
    umlDriverLock(driver);
 
1054
    if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
 
1055
        virReportOOMError();
 
1056
    umlDriverUnlock(driver);
 
1057
 
 
1058
    return xml;
 
1059
}
 
1060
 
 
1061
 
 
1062
 
 
1063
static int umlGetProcessInfo(unsigned long long *cpuTime, int pid) {
 
1064
    char proc[PATH_MAX];
 
1065
    FILE *pidinfo;
 
1066
    unsigned long long usertime, systime;
 
1067
 
 
1068
    if (snprintf(proc, sizeof(proc), "/proc/%d/stat", pid) >= (int)sizeof(proc)) {
 
1069
        return -1;
 
1070
    }
 
1071
 
 
1072
    if (!(pidinfo = fopen(proc, "r"))) {
 
1073
        /*printf("cannot read pid info");*/
 
1074
        /* VM probably shut down, so fake 0 */
 
1075
        *cpuTime = 0;
 
1076
        return 0;
 
1077
    }
 
1078
 
 
1079
    if (fscanf(pidinfo, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu", &usertime, &systime) != 2) {
 
1080
        umlDebug("not enough arg");
 
1081
        fclose(pidinfo);
 
1082
        return -1;
 
1083
    }
 
1084
 
 
1085
    /* We got jiffies
 
1086
     * We want nanoseconds
 
1087
     * _SC_CLK_TCK is jiffies per second
 
1088
     * So calulate thus....
 
1089
     */
 
1090
    *cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime) / (unsigned long long)sysconf(_SC_CLK_TCK);
 
1091
 
 
1092
    umlDebug("Got %llu %llu %llu", usertime, systime, *cpuTime);
 
1093
 
 
1094
    fclose(pidinfo);
 
1095
 
 
1096
    return 0;
 
1097
}
 
1098
 
 
1099
 
 
1100
static virDomainPtr umlDomainLookupByID(virConnectPtr conn,
 
1101
                                          int id) {
 
1102
    struct uml_driver *driver = (struct uml_driver *)conn->privateData;
 
1103
    virDomainObjPtr vm;
 
1104
    virDomainPtr dom = NULL;
 
1105
 
 
1106
    umlDriverLock(driver);
 
1107
    vm = virDomainFindByID(&driver->domains, id);
 
1108
    umlDriverUnlock(driver);
 
1109
 
 
1110
    if (!vm) {
 
1111
        umlReportError(VIR_ERR_NO_DOMAIN, NULL);
 
1112
        goto cleanup;
 
1113
    }
 
1114
 
 
1115
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
 
1116
    if (dom) dom->id = vm->def->id;
 
1117
 
 
1118
cleanup:
 
1119
    if (vm)
 
1120
        virDomainObjUnlock(vm);
 
1121
    return dom;
 
1122
}
 
1123
 
 
1124
static virDomainPtr umlDomainLookupByUUID(virConnectPtr conn,
 
1125
                                            const unsigned char *uuid) {
 
1126
    struct uml_driver *driver = (struct uml_driver *)conn->privateData;
 
1127
    virDomainObjPtr vm;
 
1128
    virDomainPtr dom = NULL;
 
1129
 
 
1130
    umlDriverLock(driver);
 
1131
    vm = virDomainFindByUUID(&driver->domains, uuid);
 
1132
    umlDriverUnlock(driver);
 
1133
 
 
1134
    if (!vm) {
 
1135
        umlReportError(VIR_ERR_NO_DOMAIN, NULL);
 
1136
        goto cleanup;
 
1137
    }
 
1138
 
 
1139
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
 
1140
    if (dom) dom->id = vm->def->id;
 
1141
 
 
1142
cleanup:
 
1143
    if (vm)
 
1144
        virDomainObjUnlock(vm);
 
1145
    return dom;
 
1146
}
 
1147
 
 
1148
static virDomainPtr umlDomainLookupByName(virConnectPtr conn,
 
1149
                                            const char *name) {
 
1150
    struct uml_driver *driver = (struct uml_driver *)conn->privateData;
 
1151
    virDomainObjPtr vm;
 
1152
    virDomainPtr dom = NULL;
 
1153
 
 
1154
    umlDriverLock(driver);
 
1155
    vm = virDomainFindByName(&driver->domains, name);
 
1156
    umlDriverUnlock(driver);
 
1157
 
 
1158
    if (!vm) {
 
1159
        umlReportError(VIR_ERR_NO_DOMAIN, NULL);
 
1160
        goto cleanup;
 
1161
    }
 
1162
 
 
1163
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
 
1164
    if (dom) dom->id = vm->def->id;
 
1165
 
 
1166
cleanup:
 
1167
    if (vm)
 
1168
        virDomainObjUnlock(vm);
 
1169
    return dom;
 
1170
}
 
1171
 
 
1172
 
 
1173
static int umlDomainIsActive(virDomainPtr dom)
 
1174
{
 
1175
    struct uml_driver *driver = dom->conn->privateData;
 
1176
    virDomainObjPtr obj;
 
1177
    int ret = -1;
 
1178
 
 
1179
    umlDriverLock(driver);
 
1180
    obj = virDomainFindByUUID(&driver->domains, dom->uuid);
 
1181
    umlDriverUnlock(driver);
 
1182
    if (!obj) {
 
1183
        umlReportError(VIR_ERR_NO_DOMAIN, NULL);
 
1184
        goto cleanup;
 
1185
    }
 
1186
    ret = virDomainObjIsActive(obj);
 
1187
 
 
1188
cleanup:
 
1189
    if (obj)
 
1190
        virDomainObjUnlock(obj);
 
1191
    return ret;
 
1192
}
 
1193
 
 
1194
 
 
1195
static int umlDomainIsPersistent(virDomainPtr dom)
 
1196
{
 
1197
    struct uml_driver *driver = dom->conn->privateData;
 
1198
    virDomainObjPtr obj;
 
1199
    int ret = -1;
 
1200
 
 
1201
    umlDriverLock(driver);
 
1202
    obj = virDomainFindByUUID(&driver->domains, dom->uuid);
 
1203
    umlDriverUnlock(driver);
 
1204
    if (!obj) {
 
1205
        umlReportError(VIR_ERR_NO_DOMAIN, NULL);
 
1206
        goto cleanup;
 
1207
    }
 
1208
    ret = obj->persistent;
 
1209
 
 
1210
cleanup:
 
1211
    if (obj)
 
1212
        virDomainObjUnlock(obj);
 
1213
    return ret;
 
1214
}
 
1215
 
 
1216
 
 
1217
static int umlGetVersion(virConnectPtr conn, unsigned long *version) {
 
1218
    struct uml_driver *driver = conn->privateData;
 
1219
    struct utsname ut;
 
1220
    int ret = -1;
 
1221
 
 
1222
    umlDriverLock(driver);
 
1223
 
 
1224
    if (driver->umlVersion == 0) {
 
1225
        uname(&ut);
 
1226
 
 
1227
        if (virParseVersionString(ut.release, &driver->umlVersion) < 0) {
 
1228
            umlReportError(VIR_ERR_INTERNAL_ERROR,
 
1229
                           _("cannot parse version %s"), ut.release);
 
1230
            goto cleanup;
 
1231
        }
 
1232
    }
 
1233
 
 
1234
    *version = driver->umlVersion;
 
1235
    ret = 0;
 
1236
 
 
1237
cleanup:
 
1238
    umlDriverUnlock(driver);
 
1239
    return ret;
 
1240
}
 
1241
 
 
1242
static int umlListDomains(virConnectPtr conn, int *ids, int nids) {
 
1243
    struct uml_driver *driver = conn->privateData;
 
1244
    int n;
 
1245
 
 
1246
    umlDriverLock(driver);
 
1247
    n = virDomainObjListGetActiveIDs(&driver->domains, ids, nids);
 
1248
    umlDriverUnlock(driver);
 
1249
 
 
1250
    return n;
 
1251
}
 
1252
static int umlNumDomains(virConnectPtr conn) {
 
1253
    struct uml_driver *driver = conn->privateData;
 
1254
    int n;
 
1255
 
 
1256
    umlDriverLock(driver);
 
1257
    n = virDomainObjListNumOfDomains(&driver->domains, 1);
 
1258
    umlDriverUnlock(driver);
 
1259
 
 
1260
    return n;
 
1261
}
 
1262
static virDomainPtr umlDomainCreate(virConnectPtr conn, const char *xml,
 
1263
                                      unsigned int flags) {
 
1264
    struct uml_driver *driver = conn->privateData;
 
1265
    virDomainDefPtr def;
 
1266
    virDomainObjPtr vm = NULL;
 
1267
    virDomainPtr dom = NULL;
 
1268
 
 
1269
    virCheckFlags(0, NULL);
 
1270
 
 
1271
    umlDriverLock(driver);
 
1272
    if (!(def = virDomainDefParseString(driver->caps, xml,
 
1273
                                        VIR_DOMAIN_XML_INACTIVE)))
 
1274
        goto cleanup;
 
1275
 
 
1276
    if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
 
1277
        goto cleanup;
 
1278
 
 
1279
    if (!(vm = virDomainAssignDef(driver->caps,
 
1280
                                  &driver->domains,
 
1281
                                  def, false)))
 
1282
        goto cleanup;
 
1283
    def = NULL;
 
1284
 
 
1285
    if (umlStartVMDaemon(conn, driver, vm) < 0) {
 
1286
        virDomainRemoveInactive(&driver->domains,
 
1287
                                vm);
 
1288
        vm = NULL;
 
1289
        goto cleanup;
 
1290
    }
 
1291
 
 
1292
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
 
1293
    if (dom) dom->id = vm->def->id;
 
1294
 
 
1295
cleanup:
 
1296
    virDomainDefFree(def);
 
1297
    if (vm)
 
1298
        virDomainObjUnlock(vm);
 
1299
    umlDriverUnlock(driver);
 
1300
    return dom;
 
1301
}
 
1302
 
 
1303
 
 
1304
static int umlDomainShutdown(virDomainPtr dom) {
 
1305
    struct uml_driver *driver = dom->conn->privateData;
 
1306
    virDomainObjPtr vm;
 
1307
    char *info = NULL;
 
1308
    int ret = -1;
 
1309
 
 
1310
    umlDriverLock(driver);
 
1311
    vm = virDomainFindByID(&driver->domains, dom->id);
 
1312
    umlDriverUnlock(driver);
 
1313
    if (!vm) {
 
1314
        umlReportError(VIR_ERR_INVALID_DOMAIN,
 
1315
                       _("no domain with matching id %d"), dom->id);
 
1316
        goto cleanup;
 
1317
    }
 
1318
 
 
1319
#if 0
 
1320
    if (umlMonitorCommand(driver, vm, "system_powerdown", &info) < 0) {
 
1321
        umlReportError(VIR_ERR_OPERATION_FAILED, "%s",
 
1322
                       _("shutdown operation failed"));
 
1323
        goto cleanup;
 
1324
    }
 
1325
    ret = 0;
 
1326
#endif
 
1327
 
 
1328
cleanup:
 
1329
    VIR_FREE(info);
 
1330
    if (vm)
 
1331
        virDomainObjUnlock(vm);
 
1332
    return ret;
 
1333
}
 
1334
 
 
1335
 
 
1336
static int umlDomainDestroy(virDomainPtr dom) {
 
1337
    struct uml_driver *driver = dom->conn->privateData;
 
1338
    virDomainObjPtr vm;
 
1339
    int ret = -1;
 
1340
 
 
1341
    umlDriverLock(driver);
 
1342
    vm = virDomainFindByID(&driver->domains, dom->id);
 
1343
    if (!vm) {
 
1344
        umlReportError(VIR_ERR_INVALID_DOMAIN,
 
1345
                       _("no domain with matching id %d"), dom->id);
 
1346
        goto cleanup;
 
1347
    }
 
1348
 
 
1349
    umlShutdownVMDaemon(dom->conn, driver, vm);
 
1350
    if (!vm->persistent) {
 
1351
        virDomainRemoveInactive(&driver->domains,
 
1352
                                vm);
 
1353
        vm = NULL;
 
1354
    }
 
1355
    ret = 0;
 
1356
 
 
1357
cleanup:
 
1358
    if (vm)
 
1359
        virDomainObjUnlock(vm);
 
1360
    umlDriverUnlock(driver);
 
1361
    return ret;
 
1362
}
 
1363
 
 
1364
 
 
1365
static char *umlDomainGetOSType(virDomainPtr dom) {
 
1366
    struct uml_driver *driver = dom->conn->privateData;
 
1367
    virDomainObjPtr vm;
 
1368
    char *type = NULL;
 
1369
 
 
1370
    umlDriverLock(driver);
 
1371
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
 
1372
    umlDriverUnlock(driver);
 
1373
    if (!vm) {
 
1374
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
 
1375
                       _("no domain with matching uuid"));
 
1376
        goto cleanup;
 
1377
    }
 
1378
 
 
1379
    if (!(type = strdup(vm->def->os.type)))
 
1380
        virReportOOMError();
 
1381
 
 
1382
cleanup:
 
1383
    if (vm)
 
1384
        virDomainObjUnlock(vm);
 
1385
    return type;
 
1386
}
 
1387
 
 
1388
/* Returns max memory in kb, 0 if error */
 
1389
static unsigned long umlDomainGetMaxMemory(virDomainPtr dom) {
 
1390
    struct uml_driver *driver = dom->conn->privateData;
 
1391
    virDomainObjPtr vm;
 
1392
    unsigned long ret = 0;
 
1393
 
 
1394
    umlDriverLock(driver);
 
1395
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
 
1396
    umlDriverUnlock(driver);
 
1397
 
 
1398
    if (!vm) {
 
1399
        char uuidstr[VIR_UUID_STRING_BUFLEN];
 
1400
 
 
1401
        virUUIDFormat(dom->uuid, uuidstr);
 
1402
        umlReportError(VIR_ERR_INVALID_DOMAIN,
 
1403
                       _("no domain with matching uuid '%s'"), uuidstr);
 
1404
        goto cleanup;
 
1405
    }
 
1406
    ret = vm->def->maxmem;
 
1407
 
 
1408
cleanup:
 
1409
    if (vm)
 
1410
        virDomainObjUnlock(vm);
 
1411
    return ret;
 
1412
}
 
1413
 
 
1414
static int umlDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
 
1415
    struct uml_driver *driver = dom->conn->privateData;
 
1416
    virDomainObjPtr vm;
 
1417
    int ret = -1;
 
1418
 
 
1419
    umlDriverLock(driver);
 
1420
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
 
1421
    umlDriverUnlock(driver);
 
1422
 
 
1423
    if (!vm) {
 
1424
        char uuidstr[VIR_UUID_STRING_BUFLEN];
 
1425
 
 
1426
        virUUIDFormat(dom->uuid, uuidstr);
 
1427
        umlReportError(VIR_ERR_INVALID_DOMAIN,
 
1428
                       _("no domain with matching uuid '%s'"), uuidstr);
 
1429
        goto cleanup;
 
1430
    }
 
1431
 
 
1432
    if (newmax < vm->def->memory) {
 
1433
        umlReportError(VIR_ERR_INVALID_ARG, "%s",
 
1434
                       _("cannot set max memory lower than current memory"));
 
1435
        goto cleanup;
 
1436
    }
 
1437
 
 
1438
    vm->def->maxmem = newmax;
 
1439
    ret = 0;
 
1440
 
 
1441
cleanup:
 
1442
    if (vm)
 
1443
        virDomainObjUnlock(vm);
 
1444
    return ret;
 
1445
}
 
1446
 
 
1447
static int umlDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
 
1448
    struct uml_driver *driver = dom->conn->privateData;
 
1449
    virDomainObjPtr vm;
 
1450
    int ret = -1;
 
1451
 
 
1452
    umlDriverLock(driver);
 
1453
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
 
1454
    umlDriverUnlock(driver);
 
1455
 
 
1456
    if (!vm) {
 
1457
        char uuidstr[VIR_UUID_STRING_BUFLEN];
 
1458
 
 
1459
        virUUIDFormat(dom->uuid, uuidstr);
 
1460
        umlReportError(VIR_ERR_INVALID_DOMAIN,
 
1461
                       _("no domain with matching uuid '%s'"), uuidstr);
 
1462
        goto cleanup;
 
1463
    }
 
1464
 
 
1465
    if (virDomainObjIsActive(vm)) {
 
1466
        umlReportError(VIR_ERR_NO_SUPPORT, "%s",
 
1467
                       _("cannot set memory of an active domain"));
 
1468
        goto cleanup;
 
1469
    }
 
1470
 
 
1471
    if (newmem > vm->def->maxmem) {
 
1472
        umlReportError(VIR_ERR_INVALID_ARG, "%s",
 
1473
                       _("cannot set memory higher than max memory"));
 
1474
        goto cleanup;
 
1475
    }
 
1476
 
 
1477
    vm->def->memory = newmem;
 
1478
    ret = 0;
 
1479
 
 
1480
cleanup:
 
1481
    if (vm)
 
1482
        virDomainObjUnlock(vm);
 
1483
    return ret;
 
1484
}
 
1485
 
 
1486
static int umlDomainGetInfo(virDomainPtr dom,
 
1487
                              virDomainInfoPtr info) {
 
1488
    struct uml_driver *driver = dom->conn->privateData;
 
1489
    virDomainObjPtr vm;
 
1490
    int ret = -1;
 
1491
 
 
1492
    umlDriverLock(driver);
 
1493
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
 
1494
    umlDriverUnlock(driver);
 
1495
 
 
1496
    if (!vm) {
 
1497
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
 
1498
                       _("no domain with matching uuid"));
 
1499
        goto cleanup;
 
1500
    }
 
1501
 
 
1502
    info->state = vm->state;
 
1503
 
 
1504
    if (!virDomainObjIsActive(vm)) {
 
1505
        info->cpuTime = 0;
 
1506
    } else {
 
1507
        if (umlGetProcessInfo(&(info->cpuTime), vm->pid) < 0) {
 
1508
            umlReportError(VIR_ERR_OPERATION_FAILED, "%s",
 
1509
                           _("cannot read cputime for domain"));
 
1510
            goto cleanup;
 
1511
        }
 
1512
    }
 
1513
 
 
1514
    info->maxMem = vm->def->maxmem;
 
1515
    info->memory = vm->def->memory;
 
1516
    info->nrVirtCpu = vm->def->vcpus;
 
1517
    ret = 0;
 
1518
 
 
1519
cleanup:
 
1520
    if (vm)
 
1521
        virDomainObjUnlock(vm);
 
1522
    return ret;
 
1523
}
 
1524
 
 
1525
 
 
1526
static char *umlDomainDumpXML(virDomainPtr dom,
 
1527
                                int flags ATTRIBUTE_UNUSED) {
 
1528
    struct uml_driver *driver = dom->conn->privateData;
 
1529
    virDomainObjPtr vm;
 
1530
    char *ret = NULL;
 
1531
 
 
1532
    umlDriverLock(driver);
 
1533
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
 
1534
    umlDriverUnlock(driver);
 
1535
 
 
1536
    if (!vm) {
 
1537
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
 
1538
                       _("no domain with matching uuid"));
 
1539
        goto cleanup;
 
1540
    }
 
1541
 
 
1542
    ret = virDomainDefFormat((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ?
 
1543
                             vm->newDef : vm->def,
 
1544
                             flags);
 
1545
 
 
1546
cleanup:
 
1547
    if (vm)
 
1548
        virDomainObjUnlock(vm);
 
1549
    return ret;
 
1550
}
 
1551
 
 
1552
 
 
1553
static int umlListDefinedDomains(virConnectPtr conn,
 
1554
                            char **const names, int nnames) {
 
1555
    struct uml_driver *driver = conn->privateData;
 
1556
    int n;
 
1557
 
 
1558
    umlDriverLock(driver);
 
1559
    n = virDomainObjListGetInactiveNames(&driver->domains, names, nnames);
 
1560
    umlDriverUnlock(driver);
 
1561
 
 
1562
    return n;
 
1563
}
 
1564
 
 
1565
static int umlNumDefinedDomains(virConnectPtr conn) {
 
1566
    struct uml_driver *driver = conn->privateData;
 
1567
    int n;
 
1568
 
 
1569
    umlDriverLock(driver);
 
1570
    n = virDomainObjListNumOfDomains(&driver->domains, 0);
 
1571
    umlDriverUnlock(driver);
 
1572
 
 
1573
    return n;
 
1574
}
 
1575
 
 
1576
 
 
1577
static int umlDomainStartWithFlags(virDomainPtr dom, unsigned int flags) {
 
1578
    struct uml_driver *driver = dom->conn->privateData;
 
1579
    virDomainObjPtr vm;
 
1580
    int ret = -1;
 
1581
 
 
1582
    virCheckFlags(0, -1);
 
1583
 
 
1584
    umlDriverLock(driver);
 
1585
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
 
1586
 
 
1587
    if (!vm) {
 
1588
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
 
1589
                       _("no domain with matching uuid"));
 
1590
        goto cleanup;
 
1591
    }
 
1592
 
 
1593
    ret = umlStartVMDaemon(dom->conn, driver, vm);
 
1594
 
 
1595
cleanup:
 
1596
    if (vm)
 
1597
        virDomainObjUnlock(vm);
 
1598
    umlDriverUnlock(driver);
 
1599
    return ret;
 
1600
}
 
1601
 
 
1602
static int umlDomainStart(virDomainPtr dom) {
 
1603
    return umlDomainStartWithFlags(dom, 0);
 
1604
}
 
1605
 
 
1606
static virDomainPtr umlDomainDefine(virConnectPtr conn, const char *xml) {
 
1607
    struct uml_driver *driver = conn->privateData;
 
1608
    virDomainDefPtr def;
 
1609
    virDomainObjPtr vm = NULL;
 
1610
    virDomainPtr dom = NULL;
 
1611
 
 
1612
    umlDriverLock(driver);
 
1613
    if (!(def = virDomainDefParseString(driver->caps, xml,
 
1614
                                        VIR_DOMAIN_XML_INACTIVE)))
 
1615
        goto cleanup;
 
1616
 
 
1617
    if (virDomainObjIsDuplicate(&driver->domains, def, 0) < 0)
 
1618
        goto cleanup;
 
1619
 
 
1620
    if (!(vm = virDomainAssignDef(driver->caps,
 
1621
                                  &driver->domains,
 
1622
                                  def, false)))
 
1623
        goto cleanup;
 
1624
    def = NULL;
 
1625
    vm->persistent = 1;
 
1626
 
 
1627
    if (virDomainSaveConfig(driver->configDir,
 
1628
                            vm->newDef ? vm->newDef : vm->def) < 0) {
 
1629
        virDomainRemoveInactive(&driver->domains,
 
1630
                                vm);
 
1631
        vm = NULL;
 
1632
        goto cleanup;
 
1633
    }
 
1634
 
 
1635
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
 
1636
    if (dom) dom->id = vm->def->id;
 
1637
 
 
1638
cleanup:
 
1639
    virDomainDefFree(def);
 
1640
    if (vm)
 
1641
        virDomainObjUnlock(vm);
 
1642
    umlDriverUnlock(driver);
 
1643
    return dom;
 
1644
}
 
1645
 
 
1646
static int umlDomainUndefine(virDomainPtr dom) {
 
1647
    struct uml_driver *driver = dom->conn->privateData;
 
1648
    virDomainObjPtr vm;
 
1649
    int ret = -1;
 
1650
 
 
1651
    umlDriverLock(driver);
 
1652
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
 
1653
    if (!vm) {
 
1654
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
 
1655
                       _("no domain with matching uuid"));
 
1656
        goto cleanup;
 
1657
    }
 
1658
 
 
1659
    if (virDomainObjIsActive(vm)) {
 
1660
        umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
 
1661
                       _("cannot delete active domain"));
 
1662
        goto cleanup;
 
1663
    }
 
1664
 
 
1665
    if (!vm->persistent) {
 
1666
        umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
 
1667
                       _("cannot undefine transient domain"));
 
1668
        goto cleanup;
 
1669
    }
 
1670
 
 
1671
    if (virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm) < 0)
 
1672
        goto cleanup;
 
1673
 
 
1674
    virDomainRemoveInactive(&driver->domains,
 
1675
                            vm);
 
1676
    vm = NULL;
 
1677
    ret = 0;
 
1678
 
 
1679
cleanup:
 
1680
    if (vm)
 
1681
        virDomainObjUnlock(vm);
 
1682
    umlDriverUnlock(driver);
 
1683
    return ret;
 
1684
}
 
1685
 
 
1686
 
 
1687
 
 
1688
static int umlDomainGetAutostart(virDomainPtr dom,
 
1689
                            int *autostart) {
 
1690
    struct uml_driver *driver = dom->conn->privateData;
 
1691
    virDomainObjPtr vm;
 
1692
    int ret = -1;
 
1693
 
 
1694
    umlDriverLock(driver);
 
1695
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
 
1696
 
 
1697
    if (!vm) {
 
1698
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
 
1699
                       _("no domain with matching uuid"));
 
1700
        goto cleanup;
 
1701
    }
 
1702
 
 
1703
    *autostart = vm->autostart;
 
1704
    ret = 0;
 
1705
 
 
1706
cleanup:
 
1707
    if (vm)
 
1708
        virDomainObjUnlock(vm);
 
1709
    umlDriverUnlock(driver);
 
1710
    return ret;
 
1711
}
 
1712
 
 
1713
static int umlDomainSetAutostart(virDomainPtr dom,
 
1714
                                   int autostart) {
 
1715
    struct uml_driver *driver = dom->conn->privateData;
 
1716
    virDomainObjPtr vm;
 
1717
    char *configFile = NULL, *autostartLink = NULL;
 
1718
    int ret = -1;
 
1719
 
 
1720
    umlDriverLock(driver);
 
1721
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
 
1722
 
 
1723
    if (!vm) {
 
1724
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
 
1725
                       _("no domain with matching uuid"));
 
1726
        goto cleanup;
 
1727
    }
 
1728
 
 
1729
    if (!vm->persistent) {
 
1730
        umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
 
1731
                       _("cannot set autostart for transient domain"));
 
1732
        goto cleanup;
 
1733
    }
 
1734
 
 
1735
    autostart = (autostart != 0);
 
1736
 
 
1737
    if (vm->autostart != autostart) {
 
1738
        if ((configFile = virDomainConfigFile(driver->configDir, vm->def->name)) == NULL)
 
1739
            goto cleanup;
 
1740
        if ((autostartLink = virDomainConfigFile(driver->autostartDir, vm->def->name)) == NULL)
 
1741
            goto cleanup;
 
1742
 
 
1743
        if (autostart) {
 
1744
            int err;
 
1745
 
 
1746
            if ((err = virFileMakePath(driver->autostartDir))) {
 
1747
                virReportSystemError(err,
 
1748
                                     _("cannot create autostart directory %s"),
 
1749
                                     driver->autostartDir);
 
1750
                goto cleanup;
 
1751
            }
 
1752
 
 
1753
            if (symlink(configFile, autostartLink) < 0) {
 
1754
                virReportSystemError(errno,
 
1755
                                     _("Failed to create symlink '%s to '%s'"),
 
1756
                                     autostartLink, configFile);
 
1757
                goto cleanup;
 
1758
            }
 
1759
        } else {
 
1760
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
 
1761
                virReportSystemError(errno,
 
1762
                                     _("Failed to delete symlink '%s'"),
 
1763
                                     autostartLink);
 
1764
                goto cleanup;
 
1765
            }
 
1766
        }
 
1767
 
 
1768
        vm->autostart = autostart;
 
1769
    }
 
1770
    ret = 0;
 
1771
 
 
1772
cleanup:
 
1773
    VIR_FREE(configFile);
 
1774
    VIR_FREE(autostartLink);
 
1775
    if (vm)
 
1776
        virDomainObjUnlock(vm);
 
1777
    umlDriverUnlock(driver);
 
1778
    return ret;
 
1779
}
 
1780
 
 
1781
 
 
1782
static int
 
1783
umlDomainBlockPeek (virDomainPtr dom,
 
1784
                      const char *path,
 
1785
                      unsigned long long offset, size_t size,
 
1786
                      void *buffer,
 
1787
                      unsigned int flags ATTRIBUTE_UNUSED)
 
1788
{
 
1789
    struct uml_driver *driver = dom->conn->privateData;
 
1790
    virDomainObjPtr vm;
 
1791
    int fd = -1, ret = -1, i;
 
1792
 
 
1793
    umlDriverLock(driver);
 
1794
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
 
1795
    umlDriverUnlock(driver);
 
1796
 
 
1797
    if (!vm) {
 
1798
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
 
1799
                       _("no domain with matching uuid"));
 
1800
        goto cleanup;
 
1801
    }
 
1802
 
 
1803
    if (!path || path[0] == '\0') {
 
1804
        umlReportError(VIR_ERR_INVALID_ARG, "%s",
 
1805
                       _("NULL or empty path"));
 
1806
        goto cleanup;
 
1807
    }
 
1808
 
 
1809
    /* Check the path belongs to this domain. */
 
1810
    for (i = 0 ; i < vm->def->ndisks ; i++) {
 
1811
        if (vm->def->disks[i]->src != NULL &&
 
1812
            STREQ (vm->def->disks[i]->src, path)) {
 
1813
            ret = 0;
 
1814
            break;
 
1815
        }
 
1816
    }
 
1817
 
 
1818
    if (ret == 0) {
 
1819
        ret = -1;
 
1820
        /* The path is correct, now try to open it and get its size. */
 
1821
        fd = open (path, O_RDONLY);
 
1822
        if (fd == -1) {
 
1823
            virReportSystemError(errno,
 
1824
                                 _("cannot open %s"), path);
 
1825
            goto cleanup;
 
1826
        }
 
1827
 
 
1828
        /* Seek and read. */
 
1829
        /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
 
1830
         * be 64 bits on all platforms.
 
1831
         */
 
1832
        if (lseek (fd, offset, SEEK_SET) == (off_t) -1 ||
 
1833
            saferead (fd, buffer, size) == (ssize_t) -1) {
 
1834
            virReportSystemError(errno,
 
1835
                                 _("cannot read %s"), path);
 
1836
            goto cleanup;
 
1837
        }
 
1838
 
 
1839
        ret = 0;
 
1840
    } else {
 
1841
        umlReportError(VIR_ERR_INVALID_ARG, "%s",
 
1842
                       _("invalid path"));
 
1843
    }
 
1844
 
 
1845
cleanup:
 
1846
    if (fd >= 0) close (fd);
 
1847
    if (vm)
 
1848
        virDomainObjUnlock(vm);
 
1849
    return ret;
 
1850
}
 
1851
 
 
1852
 
 
1853
 
 
1854
static virDriver umlDriver = {
 
1855
    VIR_DRV_UML,
 
1856
    "UML",
 
1857
    umlOpen, /* open */
 
1858
    umlClose, /* close */
 
1859
    NULL, /* supports_feature */
 
1860
    umlGetType, /* type */
 
1861
    umlGetVersion, /* version */
 
1862
    NULL, /* libvirtVersion (impl. in libvirt.c) */
 
1863
    virGetHostname, /* getHostname */
 
1864
    NULL, /* getMaxVcpus */
 
1865
    nodeGetInfo, /* nodeGetInfo */
 
1866
    umlGetCapabilities, /* getCapabilities */
 
1867
    umlListDomains, /* listDomains */
 
1868
    umlNumDomains, /* numOfDomains */
 
1869
    umlDomainCreate, /* domainCreateXML */
 
1870
    umlDomainLookupByID, /* domainLookupByID */
 
1871
    umlDomainLookupByUUID, /* domainLookupByUUID */
 
1872
    umlDomainLookupByName, /* domainLookupByName */
 
1873
    NULL, /* domainSuspend */
 
1874
    NULL, /* domainResume */
 
1875
    umlDomainShutdown, /* domainShutdown */
 
1876
    NULL, /* domainReboot */
 
1877
    umlDomainDestroy, /* domainDestroy */
 
1878
    umlDomainGetOSType, /* domainGetOSType */
 
1879
    umlDomainGetMaxMemory, /* domainGetMaxMemory */
 
1880
    umlDomainSetMaxMemory, /* domainSetMaxMemory */
 
1881
    umlDomainSetMemory, /* domainSetMemory */
 
1882
    umlDomainGetInfo, /* domainGetInfo */
 
1883
    NULL, /* domainSave */
 
1884
    NULL, /* domainRestore */
 
1885
    NULL, /* domainCoreDump */
 
1886
    NULL, /* domainSetVcpus */
 
1887
    NULL, /* domainPinVcpu */
 
1888
    NULL, /* domainGetVcpus */
 
1889
    NULL, /* domainGetMaxVcpus */
 
1890
    NULL, /* domainGetSecurityLabel */
 
1891
    NULL, /* nodeGetSecurityModel */
 
1892
    umlDomainDumpXML, /* domainDumpXML */
 
1893
    NULL, /* domainXMLFromNative */
 
1894
    NULL, /* domainXMLToNative */
 
1895
    umlListDefinedDomains, /* listDefinedDomains */
 
1896
    umlNumDefinedDomains, /* numOfDefinedDomains */
 
1897
    umlDomainStart, /* domainCreate */
 
1898
    umlDomainStartWithFlags, /* domainCreateWithFlags */
 
1899
    umlDomainDefine, /* domainDefineXML */
 
1900
    umlDomainUndefine, /* domainUndefine */
 
1901
    NULL, /* domainAttachDevice */
 
1902
    NULL, /* domainAttachDeviceFlags */
 
1903
    NULL, /* domainDetachDevice */
 
1904
    NULL, /* domainDetachDeviceFlags */
 
1905
    NULL, /* domainUpdateDeviceFlags */
 
1906
    umlDomainGetAutostart, /* domainGetAutostart */
 
1907
    umlDomainSetAutostart, /* domainSetAutostart */
 
1908
    NULL, /* domainGetSchedulerType */
 
1909
    NULL, /* domainGetSchedulerParameters */
 
1910
    NULL, /* domainSetSchedulerParameters */
 
1911
    NULL, /* domainMigratePrepare */
 
1912
    NULL, /* domainMigratePerform */
 
1913
    NULL, /* domainMigrateFinish */
 
1914
    NULL, /* domainBlockStats */
 
1915
    NULL, /* domainInterfaceStats */
 
1916
    NULL, /* domainMemoryStats */
 
1917
    umlDomainBlockPeek, /* domainBlockPeek */
 
1918
    NULL, /* domainMemoryPeek */
 
1919
    NULL, /* domainGetBlockInfo */
 
1920
    nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
 
1921
    nodeGetFreeMemory,  /* getFreeMemory */
 
1922
    NULL, /* domainEventRegister */
 
1923
    NULL, /* domainEventDeregister */
 
1924
    NULL, /* domainMigratePrepare2 */
 
1925
    NULL, /* domainMigrateFinish2 */
 
1926
    NULL, /* nodeDeviceDettach */
 
1927
    NULL, /* nodeDeviceReAttach */
 
1928
    NULL, /* nodeDeviceReset */
 
1929
    NULL, /* domainMigratePrepareTunnel */
 
1930
    umlIsEncrypted, /* isEncrypted */
 
1931
    umlIsSecure, /* isSecure */
 
1932
    umlDomainIsActive, /* domainIsActive */
 
1933
    umlDomainIsPersistent, /* domainIsPersistent */
 
1934
    NULL, /* cpuCompare */
 
1935
    NULL, /* cpuBaseline */
 
1936
    NULL, /* domainGetJobInfo */
 
1937
    NULL, /* domainAbortJob */
 
1938
    NULL, /* domainMigrateSetMaxDowntime */
 
1939
    NULL, /* domainEventRegisterAny */
 
1940
    NULL, /* domainEventDeregisterAny */
 
1941
    NULL, /* domainManagedSave */
 
1942
    NULL, /* domainHasManagedSaveImage */
 
1943
    NULL, /* domainManagedSaveRemove */
 
1944
    NULL, /* domainSnapshotCreateXML */
 
1945
    NULL, /* domainSnapshotDumpXML */
 
1946
    NULL, /* domainSnapshotNum */
 
1947
    NULL, /* domainSnapshotListNames */
 
1948
    NULL, /* domainSnapshotLookupByName */
 
1949
    NULL, /* domainHasCurrentSnapshot */
 
1950
    NULL, /* domainSnapshotCurrent */
 
1951
    NULL, /* domainRevertToSnapshot */
 
1952
    NULL, /* domainSnapshotDelete */
 
1953
    NULL, /* qemuDomainMonitorCommand */
 
1954
};
 
1955
 
 
1956
 
 
1957
static virStateDriver umlStateDriver = {
 
1958
    .name = "UML",
 
1959
    .initialize = umlStartup,
 
1960
    .cleanup = umlShutdown,
 
1961
    .reload = umlReload,
 
1962
    .active = umlActive,
 
1963
};
 
1964
 
 
1965
int umlRegister(void) {
 
1966
    virRegisterDriver(&umlDriver);
 
1967
    virRegisterStateDriver(&umlStateDriver);
 
1968
    return 0;
 
1969
}