qemu_conf.c 17.7 KB
Newer Older
D
Daniel P. Berrange 已提交
1
/*
2
 * qemu_conf.c: QEMU configuration management
D
Daniel P. Berrange 已提交
3
 *
4
 * Copyright (C) 2006-2012 Red Hat, Inc.
D
Daniel P. Berrange 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17
 * Copyright (C) 2006 Daniel P. Berrange
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library.  If not, see
O
Osier Yang 已提交
19
 * <http://www.gnu.org/licenses/>.
D
Daniel P. Berrange 已提交
20 21 22 23
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

24
#include <config.h>
25

D
Daniel P. Berrange 已提交
26 27 28 29
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
30
#include <stdlib.h>
D
Daniel P. Berrange 已提交
31 32 33
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
34
#include <sys/wait.h>
35
#include <arpa/inet.h>
36
#include <sys/utsname.h>
37
#include <mntent.h>
D
Daniel P. Berrange 已提交
38

39
#include "virterror_internal.h"
40
#include "qemu_conf.h"
41
#include "qemu_command.h"
42
#include "qemu_capabilities.h"
43
#include "qemu_bridge_filter.h"
44
#include "uuid.h"
45
#include "buf.h"
D
Daniel P. Berrange 已提交
46
#include "conf.h"
47
#include "util.h"
48
#include "memory.h"
49 50
#include "datatypes.h"
#include "xml.h"
51
#include "nodeinfo.h"
52
#include "logging.h"
53
#include "cpu/cpu.h"
54
#include "domain_nwfilter.h"
E
Eric Blake 已提交
55
#include "virfile.h"
56
#include "configmake.h"
57

58 59
#define VIR_FROM_THIS VIR_FROM_QEMU

60 61 62 63 64
struct _qemuDriverCloseDef {
    virConnectPtr conn;
    qemuDriverCloseCallback cb;
};

65
void qemuDriverLock(virQEMUDriverPtr driver)
66 67 68
{
    virMutexLock(&driver->lock);
}
69
void qemuDriverUnlock(virQEMUDriverPtr driver)
70 71 72 73 74
{
    virMutexUnlock(&driver->lock);
}


75
int qemuLoadDriverConfig(virQEMUDriverPtr driver,
76
                         const char *filename) {
77
    virConfPtr conf = NULL;
D
Daniel P. Berrange 已提交
78
    virConfValuePtr p;
79 80 81
    char *user = NULL;
    char *group = NULL;
    int ret = -1;
82
    int i;
D
Daniel P. Berrange 已提交
83

84
    /* Setup critical defaults */
85 86
    driver->securityDefaultConfined = true;
    driver->securityRequireConfined = false;
87
    driver->dynamicOwnership = 1;
88
    driver->clearEmulatorCapabilities = 1;
89

90 91
    if (!(driver->vncListen = strdup("127.0.0.1")))
        goto no_memory;
92 93 94 95

    driver->remotePortMin = QEMU_REMOTE_PORT_MIN;
    driver->remotePortMax = QEMU_REMOTE_PORT_MAX;

96 97 98 99 100
    if (!(driver->vncTLSx509certdir = strdup(SYSCONFDIR "/pki/libvirt-vnc")))
        goto no_memory;

    if (!(driver->spiceListen = strdup("127.0.0.1")))
        goto no_memory;
D
Daniel P. Berrange 已提交
101

102
    if (!(driver->spiceTLSx509certdir
103 104
          = strdup(SYSCONFDIR "/pki/libvirt-spice")))
        goto no_memory;
105

106
#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
107 108 109 110 111 112
    /* For privileged driver, try and find hugepage mount automatically.
     * Non-privileged driver requires admin to create a dir for the
     * user, chown it, and then let user configure it manually */
    if (driver->privileged &&
        !(driver->hugetlbfs_mount = virFileFindMountPoint("hugetlbfs"))) {
        if (errno != ENOENT) {
113
            virReportSystemError(errno, "%s",
114
                                 _("unable to find hugetlbfs mountpoint"));
115
            goto cleanup;
116 117 118 119
        }
    }
#endif

120 121
    if (!(driver->lockManager = virLockManagerPluginNew("nop", NULL, 0)))
        goto cleanup;
122

123 124
    driver->keepAliveInterval = 5;
    driver->keepAliveCount = 5;
125
    driver->seccompSandbox = -1;
126

D
Daniel P. Berrange 已提交
127 128 129
    /* Just check the file is readable before opening it, otherwise
     * libvirt emits an error.
     */
130
    if (access(filename, R_OK) == -1) {
131
        VIR_INFO("Could not read qemu config file %s", filename);
132 133
        ret = 0;
        goto cleanup;
134
    }
D
Daniel P. Berrange 已提交
135

136 137
    if (!(conf = virConfReadFile(filename, 0)))
        goto cleanup;
D
Daniel P. Berrange 已提交
138

139 140 141 142 143
#define CHECK_TYPE(name,typ)                          \
    if (p && p->type != (typ)) {                      \
        virReportError(VIR_ERR_INTERNAL_ERROR,        \
                       "%s: %s: expected type " #typ, \
                       filename, (name));             \
144
        goto cleanup;                                 \
145 146 147 148 149 150 151 152 153 154 155 156 157
    }

#define GET_VALUE_LONG(NAME, VAR)     \
    p = virConfGetValue(conf, NAME);  \
    CHECK_TYPE(NAME, VIR_CONF_LONG);  \
    if (p)                            \
        VAR = p->l;

#define GET_VALUE_STR(NAME, VAR)           \
    p = virConfGetValue(conf, NAME);       \
    CHECK_TYPE(NAME, VIR_CONF_STRING);     \
    if (p && p->str) {                     \
        VIR_FREE(VAR);                     \
158 159
        if (!(VAR = strdup(p->str)))       \
            goto no_memory;                \
160 161 162 163 164 165 166 167 168 169 170
    }

    GET_VALUE_LONG("vnc_auto_unix_socket", driver->vncAutoUnixSocket);
    GET_VALUE_LONG("vnc_tls", driver->vncTLS);
    GET_VALUE_LONG("vnc_tls_x509_verify", driver->vncTLSx509verify);
    GET_VALUE_STR("vnc_tls_x509_cert_dir", driver->vncTLSx509certdir);
    GET_VALUE_STR("vnc_listen", driver->vncListen);
    GET_VALUE_STR("vnc_password", driver->vncPassword);
    GET_VALUE_LONG("vnc_sasl", driver->vncSASL);
    GET_VALUE_STR("vnc_sasl_dir", driver->vncSASLdir);
    GET_VALUE_LONG("vnc_allow_host_audio", driver->vncAllowHostAudio);
171

172
    p = virConfGetValue(conf, "security_driver");
173 174 175 176
    if (p && p->type == VIR_CONF_LIST) {
        size_t len;
        virConfValuePtr pp;

J
Ján Tomko 已提交
177
        /* Calc length and check items */
178 179
        for (len = 0, pp = p->list; pp; len++, pp = pp->next) {
            if (pp->type != VIR_CONF_STRING) {
180 181 182
                virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                               _("security_driver must be a list of strings"));
                goto cleanup;
183 184 185
            }
        }

186 187
        if (VIR_ALLOC_N(driver->securityDriverNames, len + 1) < 0)
            goto no_memory;
188 189

        for (i = 0, pp = p->list; pp; i++, pp = pp->next) {
190 191
            if (!(driver->securityDriverNames[i] = strdup(pp->str)))
                goto no_memory;
192 193 194
        }
        driver->securityDriverNames[len] = NULL;
    } else {
195
        CHECK_TYPE("security_driver", VIR_CONF_STRING);
196 197
        if (p && p->str) {
            if (VIR_ALLOC_N(driver->securityDriverNames, 2) < 0 ||
198 199 200
                !(driver->securityDriverNames[0] = strdup(p->str)))
                goto no_memory;

201 202
            driver->securityDriverNames[1] = NULL;
        }
203 204
    }

205 206
    GET_VALUE_LONG("security_default_confined", driver->securityDefaultConfined);
    GET_VALUE_LONG("security_require_confined", driver->securityRequireConfined);
207

208 209 210 211
    GET_VALUE_LONG("spice_tls", driver->spiceTLS);
    GET_VALUE_STR("spice_tls_x509_cert_dir", driver->spiceTLSx509certdir);
    GET_VALUE_STR("spice_listen", driver->spiceListen);
    GET_VALUE_STR("spice_password", driver->spicePassword);
212 213


214 215 216 217 218 219 220 221 222
    GET_VALUE_LONG("remote_display_port_min", driver->remotePortMin);
    if (driver->remotePortMin < QEMU_REMOTE_PORT_MIN) {
        /* if the port is too low, we can't get the display name
         * to tell to vnc (usually subtract 5900, e.g. localhost:1
         * for port 5901) */
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("%s: remote_display_port_min: port must be greater "
                         "than or equal to %d"),
                        filename, QEMU_REMOTE_PORT_MIN);
223
        goto cleanup;
224 225
    }

226 227 228 229 230 231 232
    GET_VALUE_LONG("remote_display_port_max", driver->remotePortMax);
    if (driver->remotePortMax > QEMU_REMOTE_PORT_MAX ||
        driver->remotePortMax < driver->remotePortMin) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("%s: remote_display_port_max: port must be between "
                          "the minimal port and %d"),
                       filename, QEMU_REMOTE_PORT_MAX);
233
        goto cleanup;
234
    }
235 236 237 238
    /* increasing the value by 1 makes all the loops going through
    the bitmap (i = remotePortMin; i < remotePortMax; i++), work as
    expected. */
    driver->remotePortMax++;
239 240 241

    if (driver->remotePortMin > driver->remotePortMax) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
242 243
                        _("%s: remote_display_port_min: min port must not be "
                          "greater than max port"), filename);
244
        goto cleanup;
245 246
    }

247 248
    p = virConfGetValue(conf, "user");
    CHECK_TYPE("user", VIR_CONF_STRING);
249 250
    if (!(user = strdup(p && p->str ? p->str : QEMU_USER)))
        goto no_memory;
251

252 253
    if (virGetUserID(user, &driver->user) < 0)
        goto cleanup;
254

255 256
    p = virConfGetValue(conf, "group");
    CHECK_TYPE("group", VIR_CONF_STRING);
257 258 259 260 261
    if (!(group = strdup(p && p->str ? p->str : QEMU_GROUP)))
        goto no_memory;

    if (virGetGroupID(group, &driver->group) < 0)
        goto cleanup;
262

263
    GET_VALUE_LONG("dynamic_ownership", driver->dynamicOwnership);
264

265 266
    p = virConfGetValue(conf, "cgroup_controllers");
    CHECK_TYPE("cgroup_controllers", VIR_CONF_LIST);
267 268 269 270 271
    if (p) {
        virConfValuePtr pp;
        for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
            int ctl;
            if (pp->type != VIR_CONF_STRING) {
272 273 274 275
                virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                               _("cgroup_controllers must be a "
                                 "list of strings"));
                goto cleanup;
276
            }
277 278 279 280 281

            if ((ctl = virCgroupControllerTypeFromString(pp->str)) < 0) {
                virReportError(VIR_ERR_CONF_SYNTAX,
                               _("Unknown cgroup controller '%s'"), pp->str);
                goto cleanup;
282 283 284 285 286 287
            }
            driver->cgroupControllers |= (1 << ctl);
        }
    } else {
        driver->cgroupControllers =
            (1 << VIR_CGROUP_CONTROLLER_CPU) |
288
            (1 << VIR_CGROUP_CONTROLLER_DEVICES) |
289
            (1 << VIR_CGROUP_CONTROLLER_MEMORY) |
H
Hu Tao 已提交
290
            (1 << VIR_CGROUP_CONTROLLER_BLKIO) |
291 292
            (1 << VIR_CGROUP_CONTROLLER_CPUSET) |
            (1 << VIR_CGROUP_CONTROLLER_CPUACCT);
293 294 295 296 297 298 299 300
    }
    for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
        if (driver->cgroupControllers & (1 << i)) {
            VIR_INFO("Configured cgroup controller '%s'",
                     virCgroupControllerTypeToString(i));
        }
    }

301 302
    p = virConfGetValue(conf, "cgroup_device_acl");
    CHECK_TYPE("cgroup_device_acl", VIR_CONF_LIST);
303 304 305 306 307
    if (p) {
        int len = 0;
        virConfValuePtr pp;
        for (pp = p->list; pp; pp = pp->next)
            len++;
308 309 310
        if (VIR_ALLOC_N(driver->cgroupDeviceACL, 1+len) < 0)
            goto no_memory;

311 312
        for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
            if (pp->type != VIR_CONF_STRING) {
313 314 315 316
                virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                               _("cgroup_device_acl must be a "
                                 "list of strings"));
                goto cleanup;
317
            }
318 319
            if (!(driver->cgroupDeviceACL[i] = strdup(pp->str)))
                goto no_memory;
320 321 322 323
        }
        driver->cgroupDeviceACL[i] = NULL;
    }

324 325 326 327 328
    GET_VALUE_STR("save_image_format", driver->saveImageFormat);
    GET_VALUE_STR("dump_image_format", driver->dumpImageFormat);
    GET_VALUE_STR("auto_dump_path", driver->autoDumpPath);
    GET_VALUE_LONG("auto_dump_bypass_cache", driver->autoDumpBypassCache);
    GET_VALUE_LONG("auto_start_bypass_cache", driver->autoStartBypassCache);
329

330
    GET_VALUE_STR("hugetlbfs_mount", driver->hugetlbfs_mount);
331

332 333
    p = virConfGetValue(conf, "mac_filter");
    CHECK_TYPE("mac_filter", VIR_CONF_LONG);
334
    if (p && p->l) {
335 336 337
        driver->macFilter = p->l;
        if (!(driver->ebtables = ebtablesContextNew("qemu"))) {
            driver->macFilter = 0;
338
            virReportSystemError(errno,
S
Stefan Berger 已提交
339
                                 _("failed to enable mac filter in '%s'"),
340
                                 __FILE__);
341
            goto cleanup;
342 343 344
        }

        if ((errno = networkDisableAllFrames(driver))) {
345
            virReportSystemError(errno,
346 347
                         _("failed to add rule to drop all frames in '%s'"),
                                 __FILE__);
348
            goto cleanup;
349 350 351
        }
    }

352 353 354 355 356 357
    GET_VALUE_LONG("relaxed_acs_check", driver->relaxedACS);
    GET_VALUE_LONG("clear_emulator_capabilities", driver->clearEmulatorCapabilities);
    GET_VALUE_LONG("allow_disk_format_probing", driver->allowDiskFormatProbing);
    GET_VALUE_LONG("set_process_name", driver->setProcessName);
    GET_VALUE_LONG("max_processes", driver->maxProcesses);
    GET_VALUE_LONG("max_files", driver->maxFiles);
358

359 360
    p = virConfGetValue(conf, "lock_manager");
    CHECK_TYPE("lock_manager", VIR_CONF_STRING);
361
    if (p && p->str) {
362
        char *lockConf;
363
        virLockManagerPluginUnref(driver->lockManager);
364 365 366
        if (virAsprintf(&lockConf, "%s/libvirt/qemu-%s.conf", SYSCONFDIR, p->str) < 0)
            goto no_memory;

367
        if (!(driver->lockManager =
368
              virLockManagerPluginNew(p->str, lockConf, 0)))
369
            VIR_ERROR(_("Failed to load lock manager %s"), p->str);
370
        VIR_FREE(lockConf);
371 372
    }

373 374 375 376
    GET_VALUE_LONG("max_queued", driver->max_queued);
    GET_VALUE_LONG("keepalive_interval", driver->keepAliveInterval);
    GET_VALUE_LONG("keepalive_count", driver->keepAliveCount);
    GET_VALUE_LONG("seccomp_sandbox", driver->seccompSandbox);
377

378 379 380 381 382
    ret = 0;

cleanup:
    VIR_FREE(user);
    VIR_FREE(group);
383
    virConfFree(conf);
384 385 386 387 388
    return ret;

no_memory:
    virReportOOMError();
    goto cleanup;
D
Daniel P. Berrange 已提交
389
}
390 391
#undef GET_VALUE_LONG
#undef GET_VALUE_STRING
392 393 394 395 396 397 398 399 400

static void
qemuDriverCloseCallbackFree(void *payload,
                            const void *name ATTRIBUTE_UNUSED)
{
    VIR_FREE(payload);
}

int
401
qemuDriverCloseCallbackInit(virQEMUDriverPtr driver)
402 403 404 405 406 407 408 409 410
{
    driver->closeCallbacks = virHashCreate(5, qemuDriverCloseCallbackFree);
    if (!driver->closeCallbacks)
        return -1;

    return 0;
}

void
411
qemuDriverCloseCallbackShutdown(virQEMUDriverPtr driver)
412 413 414 415 416
{
    virHashFree(driver->closeCallbacks);
}

int
417
qemuDriverCloseCallbackSet(virQEMUDriverPtr driver,
418 419 420 421 422 423 424 425 426 427 428 429 430 431
                           virDomainObjPtr vm,
                           virConnectPtr conn,
                           qemuDriverCloseCallback cb)
{
    char uuidstr[VIR_UUID_STRING_BUFLEN];
    qemuDriverCloseDefPtr closeDef;

    virUUIDFormat(vm->def->uuid, uuidstr);
    VIR_DEBUG("vm=%s, uuid=%s, conn=%p, cb=%p",
              vm->def->name, uuidstr, conn, cb);

    closeDef = virHashLookup(driver->closeCallbacks, uuidstr);
    if (closeDef) {
        if (closeDef->conn != conn) {
432 433 434 435
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Close callback for domain %s already registered"
                             " with another connection %p"),
                           vm->def->name, closeDef->conn);
436 437 438
            return -1;
        }
        if (closeDef->cb && closeDef->cb != cb) {
439 440 441
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Another close callback is already defined for"
                             " domain %s"), vm->def->name);
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
            return -1;
        }

        closeDef->cb = cb;
    } else {
        if (VIR_ALLOC(closeDef) < 0) {
            virReportOOMError();
            return -1;
        }

        closeDef->conn = conn;
        closeDef->cb = cb;
        if (virHashAddEntry(driver->closeCallbacks, uuidstr, closeDef) < 0) {
            VIR_FREE(closeDef);
            return -1;
        }
    }
    return 0;
}

int
463
qemuDriverCloseCallbackUnset(virQEMUDriverPtr driver,
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
                             virDomainObjPtr vm,
                             qemuDriverCloseCallback cb)
{
    char uuidstr[VIR_UUID_STRING_BUFLEN];
    qemuDriverCloseDefPtr closeDef;

    virUUIDFormat(vm->def->uuid, uuidstr);
    VIR_DEBUG("vm=%s, uuid=%s, cb=%p",
              vm->def->name, uuidstr, cb);

    closeDef = virHashLookup(driver->closeCallbacks, uuidstr);
    if (!closeDef)
        return -1;

    if (closeDef->cb && closeDef->cb != cb) {
479 480 481
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Trying to remove mismatching close callback for"
                         " domain %s"), vm->def->name);
482 483 484 485 486 487 488
        return -1;
    }

    return virHashRemoveEntry(driver->closeCallbacks, uuidstr);
}

qemuDriverCloseCallback
489
qemuDriverCloseCallbackGet(virQEMUDriverPtr driver,
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
                           virDomainObjPtr vm,
                           virConnectPtr conn)
{
    char uuidstr[VIR_UUID_STRING_BUFLEN];
    qemuDriverCloseDefPtr closeDef;
    qemuDriverCloseCallback cb = NULL;

    virUUIDFormat(vm->def->uuid, uuidstr);
    VIR_DEBUG("vm=%s, uuid=%s, conn=%p",
              vm->def->name, uuidstr, conn);

    closeDef = virHashLookup(driver->closeCallbacks, uuidstr);
    if (closeDef && (!conn || closeDef->conn == conn))
        cb = closeDef->cb;

    VIR_DEBUG("cb=%p", cb);
    return cb;
}

struct qemuDriverCloseCallbackData {
510
    virQEMUDriverPtr driver;
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
    virConnectPtr conn;
};

static void
qemuDriverCloseCallbackRun(void *payload,
                           const void *name,
                           void *opaque)
{
    struct qemuDriverCloseCallbackData *data = opaque;
    qemuDriverCloseDefPtr closeDef = payload;
    const char *uuidstr = name;
    unsigned char uuid[VIR_UUID_BUFLEN];
    virDomainObjPtr dom;

    VIR_DEBUG("conn=%p, thisconn=%p, uuid=%s, cb=%p",
              closeDef->conn, data->conn, uuidstr, closeDef->cb);

    if (data->conn != closeDef->conn || !closeDef->cb)
        return;

    if (virUUIDParse(uuidstr, uuid) < 0) {
        VIR_WARN("Failed to parse %s", uuidstr);
        return;
    }

    if (!(dom = virDomainFindByUUID(&data->driver->domains, uuid))) {
        VIR_DEBUG("No domain object with UUID %s", uuidstr);
        return;
    }

    dom = closeDef->cb(data->driver, dom, data->conn);
    if (dom)
        virDomainObjUnlock(dom);

    virHashRemoveEntry(data->driver->closeCallbacks, uuidstr);
}

void
549
qemuDriverCloseCallbackRunAll(virQEMUDriverPtr driver,
550 551 552 553 554 555 556 557 558
                              virConnectPtr conn)
{
    struct qemuDriverCloseCallbackData data = {
        driver, conn
    };
    VIR_DEBUG("conn=%p", conn);

    virHashForEach(driver->closeCallbacks, qemuDriverCloseCallbackRun, &data);
}