qemu_conf.c 36.1 KB
Newer Older
D
Daniel P. Berrange 已提交
1
/*
2
 * qemu_conf.c: QEMU configuration management
D
Daniel P. Berrange 已提交
3
 *
4
 * Copyright (C) 2006-2013 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>
D
Daniel P. Berrange 已提交
36

37
#include "virerror.h"
38
#include "qemu_conf.h"
39
#include "qemu_command.h"
40
#include "qemu_capabilities.h"
41
#include "qemu_bridge_filter.h"
42
#include "viruuid.h"
43
#include "virbuffer.h"
44
#include "virconf.h"
45
#include "viralloc.h"
46
#include "datatypes.h"
47
#include "virxml.h"
48
#include "nodeinfo.h"
49
#include "virlog.h"
50
#include "cpu/cpu.h"
51
#include "domain_nwfilter.h"
E
Eric Blake 已提交
52
#include "virfile.h"
53
#include "virstring.h"
54
#include "viratomic.h"
55
#include "configmake.h"
56

57 58
#define VIR_FROM_THIS VIR_FROM_QEMU

59 60 61 62 63
static virClassPtr virQEMUDriverConfigClass;
static void virQEMUDriverConfigDispose(void *obj);

static int virQEMUConfigOnceInit(void)
{
64 65 66 67
    virQEMUDriverConfigClass = virClassNew(virClassForObject(),
                                           "virQEMUDriverConfig",
                                           sizeof(virQEMUDriverConfig),
                                           virQEMUDriverConfigDispose);
68

69
    if (!virQEMUDriverConfigClass)
70 71 72
        return -1;
    else
        return 0;
73 74 75 76 77
}

VIR_ONCE_GLOBAL_INIT(virQEMUConfig)


78 79
static void
qemuDriverLock(virQEMUDriverPtr driver)
80 81 82
{
    virMutexLock(&driver->lock);
}
83 84
static void
qemuDriverUnlock(virQEMUDriverPtr driver)
85 86 87 88 89
{
    virMutexUnlock(&driver->lock);
}


90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged)
{
    virQEMUDriverConfigPtr cfg;

    if (virQEMUConfigInitialize() < 0)
        return NULL;

    if (!(cfg = virObjectNew(virQEMUDriverConfigClass)))
        return NULL;

    cfg->privileged = privileged;
    cfg->uri = privileged ? "qemu:///system" : "qemu:///session";

    if (privileged) {
        if (virGetUserID(QEMU_USER, &cfg->user) < 0)
            goto error;
        if (virGetGroupID(QEMU_GROUP, &cfg->group) < 0)
            goto error;
    } else {
109 110
        cfg->user = (uid_t)-1;
        cfg->group = (gid_t)-1;
111 112 113
    }
    cfg->dynamicOwnership = privileged;

114
    cfg->cgroupControllers = -1; /* -1 == auto-detect */
115 116 117 118

    if (privileged) {
        if (virAsprintf(&cfg->logDir,
                        "%s/log/libvirt/qemu", LOCALSTATEDIR) < 0)
119
            goto error;
120

121 122
        if (VIR_STRDUP(cfg->configBaseDir, SYSCONFDIR "/libvirt") < 0)
            goto error;
D
Daniel P. Berrange 已提交
123

124 125
        if (virAsprintf(&cfg->stateDir,
                      "%s/run/libvirt/qemu", LOCALSTATEDIR) < 0)
126
            goto error;
127 128 129

        if (virAsprintf(&cfg->libDir,
                      "%s/lib/libvirt/qemu", LOCALSTATEDIR) < 0)
130
            goto error;
131 132 133

        if (virAsprintf(&cfg->cacheDir,
                      "%s/cache/libvirt/qemu", LOCALSTATEDIR) < 0)
134
            goto error;
135 136
        if (virAsprintf(&cfg->saveDir,
                      "%s/lib/libvirt/qemu/save", LOCALSTATEDIR) < 0)
137
            goto error;
138 139
        if (virAsprintf(&cfg->snapshotDir,
                        "%s/lib/libvirt/qemu/snapshot", LOCALSTATEDIR) < 0)
140
            goto error;
141 142
        if (virAsprintf(&cfg->autoDumpPath,
                        "%s/lib/libvirt/qemu/dump", LOCALSTATEDIR) < 0)
143
            goto error;
144 145 146 147 148 149 150 151 152 153 154
    } else {
        char *rundir;
        char *cachedir;

        cachedir = virGetUserCacheDirectory();
        if (!cachedir)
            goto error;

        if (virAsprintf(&cfg->logDir,
                        "%s/qemu/log", cachedir) < 0) {
            VIR_FREE(cachedir);
155
            goto error;
156 157 158
        }
        if (virAsprintf(&cfg->cacheDir, "%s/qemu/cache", cachedir) < 0) {
            VIR_FREE(cachedir);
159
            goto error;
160 161
        }
        VIR_FREE(cachedir);
162

163 164 165 166 167
        rundir = virGetUserRuntimeDirectory();
        if (!rundir)
            goto error;
        if (virAsprintf(&cfg->stateDir, "%s/qemu/run", rundir) < 0) {
            VIR_FREE(rundir);
168
            goto error;
169 170 171 172 173 174 175
        }
        VIR_FREE(rundir);

        if (!(cfg->configBaseDir = virGetUserConfigDirectory()))
            goto error;

        if (virAsprintf(&cfg->libDir, "%s/qemu/lib", cfg->configBaseDir) < 0)
176
            goto error;
177
        if (virAsprintf(&cfg->saveDir, "%s/qemu/save", cfg->configBaseDir) < 0)
178
            goto error;
179
        if (virAsprintf(&cfg->snapshotDir, "%s/qemu/snapshot", cfg->configBaseDir) < 0)
180
            goto error;
181
        if (virAsprintf(&cfg->autoDumpPath, "%s/qemu/dump", cfg->configBaseDir) < 0)
182
            goto error;
183 184 185
    }

    if (virAsprintf(&cfg->configDir, "%s/qemu", cfg->configBaseDir) < 0)
186
        goto error;
187
    if (virAsprintf(&cfg->autostartDir, "%s/qemu/autostart", cfg->configBaseDir) < 0)
188
        goto error;
189 190


191 192
    if (VIR_STRDUP(cfg->vncListen, "127.0.0.1") < 0)
        goto error;
193

194 195
    if (VIR_STRDUP(cfg->vncTLSx509certdir, SYSCONFDIR "/pki/libvirt-vnc") < 0)
        goto error;
D
Daniel P. Berrange 已提交
196

197 198
    if (VIR_STRDUP(cfg->spiceListen, "127.0.0.1") < 0)
        goto error;
199

200 201
    if (VIR_STRDUP(cfg->spiceTLSx509certdir , SYSCONFDIR "/pki/libvirt-spice") < 0)
        goto error;
202

203 204 205
    cfg->remotePortMin = QEMU_REMOTE_PORT_MIN;
    cfg->remotePortMax = QEMU_REMOTE_PORT_MAX;

206 207 208
    cfg->webSocketPortMin = QEMU_WEBSOCKET_PORT_MIN;
    cfg->webSocketPortMax = QEMU_WEBSOCKET_PORT_MAX;

209
#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
210 211 212
    /* 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 */
213 214
    if (privileged &&
        !(cfg->hugetlbfsMount = virFileFindMountPoint("hugetlbfs"))) {
215
        if (errno != ENOENT) {
216
            virReportSystemError(errno, "%s",
217
                                 _("unable to find hugetlbfs mountpoint"));
218
            goto error;
219 220 221
        }
    }
#endif
222 223
    if (VIR_STRDUP(cfg->bridgeHelperName, "/usr/libexec/qemu-bridge-helper") < 0)
        goto error;
224

225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
    cfg->clearEmulatorCapabilities = true;

    cfg->securityDefaultConfined = true;
    cfg->securityRequireConfined = false;

    cfg->keepAliveInterval = 5;
    cfg->keepAliveCount = 5;
    cfg->seccompSandbox = -1;

    return cfg;

error:
    virObjectUnref(cfg);
    return NULL;
}


static void virQEMUDriverConfigDispose(void *obj)
{
    virQEMUDriverConfigPtr cfg = obj;


    virStringFreeList(cfg->cgroupDeviceACL);

    VIR_FREE(cfg->configBaseDir);
    VIR_FREE(cfg->configDir);
    VIR_FREE(cfg->autostartDir);
    VIR_FREE(cfg->logDir);
    VIR_FREE(cfg->stateDir);

    VIR_FREE(cfg->libDir);
    VIR_FREE(cfg->cacheDir);
    VIR_FREE(cfg->saveDir);
    VIR_FREE(cfg->snapshotDir);

    VIR_FREE(cfg->vncTLSx509certdir);
    VIR_FREE(cfg->vncListen);
    VIR_FREE(cfg->vncPassword);
    VIR_FREE(cfg->vncSASLdir);

    VIR_FREE(cfg->spiceTLSx509certdir);
    VIR_FREE(cfg->spiceListen);
    VIR_FREE(cfg->spicePassword);

    VIR_FREE(cfg->hugetlbfsMount);
    VIR_FREE(cfg->hugepagePath);
271
    VIR_FREE(cfg->bridgeHelperName);
272 273 274 275 276 277 278 279 280 281

    VIR_FREE(cfg->saveImageFormat);
    VIR_FREE(cfg->dumpImageFormat);
    VIR_FREE(cfg->autoDumpPath);

    virStringFreeList(cfg->securityDriverNames);

    VIR_FREE(cfg->lockManagerName);
}

282

283 284 285 286 287 288
int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
                                const char *filename)
{
    virConfPtr conf = NULL;
    virConfValuePtr p;
    int ret = -1;
289
    size_t i;
290

D
Daniel P. Berrange 已提交
291 292 293
    /* Just check the file is readable before opening it, otherwise
     * libvirt emits an error.
     */
294
    if (access(filename, R_OK) == -1) {
295
        VIR_INFO("Could not read qemu config file %s", filename);
296
        return 0;
297
    }
D
Daniel P. Berrange 已提交
298

299 300
    if (!(conf = virConfReadFile(filename, 0)))
        goto cleanup;
D
Daniel P. Berrange 已提交
301

302 303 304 305 306
#define CHECK_TYPE(name,typ)                          \
    if (p && p->type != (typ)) {                      \
        virReportError(VIR_ERR_INTERNAL_ERROR,        \
                       "%s: %s: expected type " #typ, \
                       filename, (name));             \
307
        goto cleanup;                                 \
308 309 310 311 312 313 314 315
    }

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

316 317 318 319 320 321
#define GET_VALUE_BOOL(NAME, VAR)     \
    p = virConfGetValue(conf, NAME);  \
    CHECK_TYPE(NAME, VIR_CONF_LONG);  \
    if (p)                            \
        VAR = p->l != 0;

322 323 324 325 326
#define GET_VALUE_STR(NAME, VAR)           \
    p = virConfGetValue(conf, NAME);       \
    CHECK_TYPE(NAME, VIR_CONF_STRING);     \
    if (p && p->str) {                     \
        VIR_FREE(VAR);                     \
327 328
        if (VIR_STRDUP(VAR, p->str) < 0)   \
            goto cleanup;                  \
329 330
    }

331 332 333 334 335 336 337 338 339
    GET_VALUE_BOOL("vnc_auto_unix_socket", cfg->vncAutoUnixSocket);
    GET_VALUE_BOOL("vnc_tls", cfg->vncTLS);
    GET_VALUE_BOOL("vnc_tls_x509_verify", cfg->vncTLSx509verify);
    GET_VALUE_STR("vnc_tls_x509_cert_dir", cfg->vncTLSx509certdir);
    GET_VALUE_STR("vnc_listen", cfg->vncListen);
    GET_VALUE_STR("vnc_password", cfg->vncPassword);
    GET_VALUE_BOOL("vnc_sasl", cfg->vncSASL);
    GET_VALUE_STR("vnc_sasl_dir", cfg->vncSASLdir);
    GET_VALUE_BOOL("vnc_allow_host_audio", cfg->vncAllowHostAudio);
340

341
    p = virConfGetValue(conf, "security_driver");
342 343 344 345
    if (p && p->type == VIR_CONF_LIST) {
        size_t len;
        virConfValuePtr pp;

J
Ján Tomko 已提交
346
        /* Calc length and check items */
347 348
        for (len = 0, pp = p->list; pp; len++, pp = pp->next) {
            if (pp->type != VIR_CONF_STRING) {
349 350 351
                virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                               _("security_driver must be a list of strings"));
                goto cleanup;
352 353 354
            }
        }

355
        if (VIR_ALLOC_N(cfg->securityDriverNames, len + 1) < 0)
356
            goto cleanup;
357 358

        for (i = 0, pp = p->list; pp; i++, pp = pp->next) {
359 360
            if (VIR_STRDUP(cfg->securityDriverNames[i], pp->str) < 0)
                goto cleanup;
361
        }
362
        cfg->securityDriverNames[len] = NULL;
363
    } else {
364
        CHECK_TYPE("security_driver", VIR_CONF_STRING);
365
        if (p && p->str) {
366
            if (VIR_ALLOC_N(cfg->securityDriverNames, 2) < 0)
367
                goto cleanup;
368 369
            if (VIR_STRDUP(cfg->securityDriverNames[0], p->str) < 0)
                goto cleanup;
370

371
            cfg->securityDriverNames[1] = NULL;
372
        }
373 374
    }

375 376
    GET_VALUE_BOOL("security_default_confined", cfg->securityDefaultConfined);
    GET_VALUE_BOOL("security_require_confined", cfg->securityRequireConfined);
377

378 379 380 381
    GET_VALUE_BOOL("spice_tls", cfg->spiceTLS);
    GET_VALUE_STR("spice_tls_x509_cert_dir", cfg->spiceTLSx509certdir);
    GET_VALUE_STR("spice_listen", cfg->spiceListen);
    GET_VALUE_STR("spice_password", cfg->spicePassword);
382 383


384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
    GET_VALUE_LONG("remote_websocket_port_min", cfg->webSocketPortMin);
    if (cfg->webSocketPortMin < QEMU_WEBSOCKET_PORT_MIN) {
        /* if the port is too low, we can't get the display name
         * to tell to vnc (usually subtract 5700, e.g. localhost:1
         * for port 5701) */
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("%s: remote_websocket_port_min: port must be greater "
                         "than or equal to %d"),
                        filename, QEMU_WEBSOCKET_PORT_MIN);
        goto cleanup;
    }

    GET_VALUE_LONG("remote_websocket_port_max", cfg->webSocketPortMax);
    if (cfg->webSocketPortMax > QEMU_WEBSOCKET_PORT_MAX ||
        cfg->webSocketPortMax < cfg->webSocketPortMin) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("%s: remote_websocket_port_max: port must be between "
                          "the minimal port and %d"),
                       filename, QEMU_WEBSOCKET_PORT_MAX);
        goto cleanup;
    }

    if (cfg->webSocketPortMin > cfg->webSocketPortMax) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("%s: remote_websocket_port_min: min port must not be "
                          "greater than max port"), filename);
        goto cleanup;
    }

413 414
    GET_VALUE_LONG("remote_display_port_min", cfg->remotePortMin);
    if (cfg->remotePortMin < QEMU_REMOTE_PORT_MIN) {
415 416 417 418 419 420 421
        /* 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);
422
        goto cleanup;
423 424
    }

425 426 427
    GET_VALUE_LONG("remote_display_port_max", cfg->remotePortMax);
    if (cfg->remotePortMax > QEMU_REMOTE_PORT_MAX ||
        cfg->remotePortMax < cfg->remotePortMin) {
428 429 430 431
        virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("%s: remote_display_port_max: port must be between "
                          "the minimal port and %d"),
                       filename, QEMU_REMOTE_PORT_MAX);
432
        goto cleanup;
433 434
    }

435
    if (cfg->remotePortMin > cfg->remotePortMax) {
436
        virReportError(VIR_ERR_INTERNAL_ERROR,
437 438
                        _("%s: remote_display_port_min: min port must not be "
                          "greater than max port"), filename);
439
        goto cleanup;
440 441
    }

442 443
    p = virConfGetValue(conf, "user");
    CHECK_TYPE("user", VIR_CONF_STRING);
444 445
    if (p && p->str &&
        virGetUserID(p->str, &cfg->user) < 0)
446
        goto cleanup;
447

448 449
    p = virConfGetValue(conf, "group");
    CHECK_TYPE("group", VIR_CONF_STRING);
450 451
    if (p && p->str &&
        virGetGroupID(p->str, &cfg->group) < 0)
452
        goto cleanup;
453

454
    GET_VALUE_BOOL("dynamic_ownership", cfg->dynamicOwnership);
455

456 457
    p = virConfGetValue(conf, "cgroup_controllers");
    CHECK_TYPE("cgroup_controllers", VIR_CONF_LIST);
458
    if (p) {
459
        cfg->cgroupControllers = 0;
460 461 462 463
        virConfValuePtr pp;
        for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
            int ctl;
            if (pp->type != VIR_CONF_STRING) {
464 465 466 467
                virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                               _("cgroup_controllers must be a "
                                 "list of strings"));
                goto cleanup;
468
            }
469 470 471 472 473

            if ((ctl = virCgroupControllerTypeFromString(pp->str)) < 0) {
                virReportError(VIR_ERR_CONF_SYNTAX,
                               _("Unknown cgroup controller '%s'"), pp->str);
                goto cleanup;
474
            }
475
            cfg->cgroupControllers |= (1 << ctl);
476 477 478
        }
    }

479 480
    p = virConfGetValue(conf, "cgroup_device_acl");
    CHECK_TYPE("cgroup_device_acl", VIR_CONF_LIST);
481 482 483 484 485
    if (p) {
        int len = 0;
        virConfValuePtr pp;
        for (pp = p->list; pp; pp = pp->next)
            len++;
486
        if (VIR_ALLOC_N(cfg->cgroupDeviceACL, 1+len) < 0)
487
            goto cleanup;
488

489 490
        for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
            if (pp->type != VIR_CONF_STRING) {
491 492 493 494
                virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                               _("cgroup_device_acl must be a "
                                 "list of strings"));
                goto cleanup;
495
            }
496 497
            if (VIR_STRDUP(cfg->cgroupDeviceACL[i], pp->str) < 0)
                goto cleanup;
498
        }
499
        cfg->cgroupDeviceACL[i] = NULL;
500 501
    }

502 503 504 505 506
    GET_VALUE_STR("save_image_format", cfg->saveImageFormat);
    GET_VALUE_STR("dump_image_format", cfg->dumpImageFormat);
    GET_VALUE_STR("auto_dump_path", cfg->autoDumpPath);
    GET_VALUE_BOOL("auto_dump_bypass_cache", cfg->autoDumpBypassCache);
    GET_VALUE_BOOL("auto_start_bypass_cache", cfg->autoStartBypassCache);
507

508
    GET_VALUE_STR("hugetlbfs_mount", cfg->hugetlbfsMount);
509
    GET_VALUE_STR("bridge_helper", cfg->bridgeHelperName);
510

511 512 513 514 515 516 517 518
    GET_VALUE_BOOL("mac_filter", cfg->macFilter);

    GET_VALUE_BOOL("relaxed_acs_check", cfg->relaxedACS);
    GET_VALUE_BOOL("clear_emulator_capabilities", cfg->clearEmulatorCapabilities);
    GET_VALUE_BOOL("allow_disk_format_probing", cfg->allowDiskFormatProbing);
    GET_VALUE_BOOL("set_process_name", cfg->setProcessName);
    GET_VALUE_LONG("max_processes", cfg->maxProcesses);
    GET_VALUE_LONG("max_files", cfg->maxFiles);
519

520 521 522 523 524 525 526 527
    GET_VALUE_STR("lock_manager", cfg->lockManagerName);

    GET_VALUE_LONG("max_queued", cfg->maxQueuedJobs);

    GET_VALUE_LONG("keepalive_interval", cfg->keepAliveInterval);
    GET_VALUE_LONG("keepalive_count", cfg->keepAliveCount);

    GET_VALUE_LONG("seccomp_sandbox", cfg->seccompSandbox);
528

529 530 531
    ret = 0;

cleanup:
532
    virConfFree(conf);
533
    return ret;
D
Daniel P. Berrange 已提交
534
}
535
#undef GET_VALUE_BOOL
536 537
#undef GET_VALUE_LONG
#undef GET_VALUE_STRING
538

539 540
virQEMUDriverConfigPtr virQEMUDriverGetConfig(virQEMUDriverPtr driver)
{
541 542 543 544 545
    virQEMUDriverConfigPtr conf;
    qemuDriverLock(driver);
    conf = virObjectRef(driver->config);
    qemuDriverUnlock(driver);
    return conf;
546 547
}

548
virDomainXMLOptionPtr
549
virQEMUDriverCreateXMLConf(virQEMUDriverPtr driver)
550
{
551
    virQEMUDriverDomainDefParserConfig.priv = driver;
552
    return virDomainXMLOptionNew(&virQEMUDriverDomainDefParserConfig,
553 554
                                 &virQEMUDriverPrivateDataCallbacks,
                                 &virQEMUDriverDomainXMLNamespace);
555 556
}

557 558 559 560 561 562 563 564 565 566 567

virCapsPtr virQEMUDriverCreateCapabilities(virQEMUDriverPtr driver)
{
    size_t i;
    virCapsPtr caps;
    virSecurityManagerPtr *sec_managers = NULL;
    /* Security driver data */
    const char *doi, *model;
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);

    /* Basic host arch / guest machine capabilities */
568
    if (!(caps = virQEMUCapsInit(driver->qemuCapsCache)))
569
        goto error;
570 571 572 573

    if (virGetHostUUID(caps->host.host_uuid)) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot get the host uuid"));
574
        goto error;
575 576 577
    }

    /* access sec drivers and create a sec model for each one */
578 579
    if (!(sec_managers = virSecurityManagerGetNested(driver->securityManager)))
        goto error;
580 581 582 583 584 585 586

    /* calculate length */
    for (i = 0; sec_managers[i]; i++)
        ;
    caps->host.nsecModels = i;

    if (VIR_ALLOC_N(caps->host.secModels, caps->host.nsecModels) < 0)
587
        goto error;
588 589 590 591

    for (i = 0; sec_managers[i]; i++) {
        doi = virSecurityManagerGetDOI(sec_managers[i]);
        model = virSecurityManagerGetModel(sec_managers[i]);
592 593 594
        if (VIR_STRDUP(caps->host.secModels[i].model, model) < 0 ||
            VIR_STRDUP(caps->host.secModels[i].doi, doi) < 0)
            goto error;
595 596 597 598 599 600 601 602
        VIR_DEBUG("Initialized caps for security driver \"%s\" with "
                  "DOI \"%s\"", model, doi);
    }
    VIR_FREE(sec_managers);

    virObjectUnref(cfg);
    return caps;

603
error:
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
    VIR_FREE(sec_managers);
    virObjectUnref(caps);
    virObjectUnref(cfg);
    return NULL;
}


/**
 * virQEMUDriverGetCapabilities:
 *
 * Get a reference to the virCapsPtr instance for the
 * driver. If @refresh is true, the capabilities will be
 * rebuilt first
 *
 * The caller must release the reference with virObjetUnref
 *
 * Returns: a reference to a virCapsPtr instance or NULL
 */
virCapsPtr virQEMUDriverGetCapabilities(virQEMUDriverPtr driver,
                                        bool refresh)
{
625
    virCapsPtr ret = NULL;
626 627 628 629 630
    if (refresh) {
        virCapsPtr caps = NULL;
        if ((caps = virQEMUDriverCreateCapabilities(driver)) == NULL)
            return NULL;

631
        qemuDriverLock(driver);
632 633
        virObjectUnref(driver->caps);
        driver->caps = caps;
634 635
    } else {
        qemuDriverLock(driver);
636 637
    }

638 639 640
    ret = virObjectRef(driver->caps);
    qemuDriverUnlock(driver);
    return ret;
641 642
}

643
struct _qemuSharedDeviceEntry {
644 645 646 647
    size_t ref;
    char **domains; /* array of domain names */
};

648
/* Construct the hash key for sharedDevices as "major:minor" */
649
char *
650
qemuGetSharedDeviceKey(const char *device_path)
651 652 653 654 655
{
    int maj, min;
    char *key = NULL;
    int rc;

656
    if ((rc = virGetDeviceID(device_path, &maj, &min)) < 0) {
657 658
        virReportSystemError(-rc,
                             _("Unable to get minor number of device '%s'"),
659
                             device_path);
660 661 662
        return NULL;
    }

663
    if (virAsprintf(&key, "%d:%d", maj, min) < 0)
664 665 666 667 668
        return NULL;

    return key;
}

669
/* Check if a shared device's setting conflicts with the conf
670 671
 * used by other domain(s). Currently only checks the sgio
 * setting. Note that this should only be called for disk with
672
 * block source if the device type is disk.
673 674 675 676
 *
 * Returns 0 if no conflicts, otherwise returns -1.
 */
static int
677 678
qemuCheckSharedDevice(virHashTablePtr sharedDevices,
                      virDomainDeviceDefPtr dev)
679
{
680 681
    virDomainDiskDefPtr disk = NULL;
    virDomainHostdevDefPtr hostdev = NULL;
682 683
    char *sysfs_path = NULL;
    char *key = NULL;
684 685 686
    char *hostdev_name = NULL;
    char *hostdev_path = NULL;
    char *device_path = NULL;
687
    int val;
688 689
    int ret = 0;

690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
        disk = dev->data.disk;

        /* The only conflicts between shared disk we care about now
         * is sgio setting, which is only valid for device='lun'.
         */
        if (disk->device != VIR_DOMAIN_DISK_DEVICE_LUN)
            return 0;

        device_path = disk->src;
    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
        hostdev = dev->data.hostdev;

        if (!(hostdev_name = virSCSIDeviceGetDevName(hostdev->source.subsys.u.scsi.adapter,
                                                     hostdev->source.subsys.u.scsi.bus,
                                                     hostdev->source.subsys.u.scsi.target,
                                                     hostdev->source.subsys.u.scsi.unit)))
            goto cleanup;

709
        if (virAsprintf(&hostdev_path, "/dev/%s", hostdev_name) < 0)
710 711 712 713
            goto cleanup;

        device_path = hostdev_path;
    } else {
714
        return 0;
715
    }
716

717
    if (!(sysfs_path = virGetUnprivSGIOSysfsPath(device_path, NULL))) {
718 719 720 721 722 723 724 725 726 727
        ret = -1;
        goto cleanup;
    }

    /* It can't be conflict if unpriv_sgio is not supported
     * by kernel.
     */
    if (!virFileExists(sysfs_path))
        goto cleanup;

728
    if (!(key = qemuGetSharedDeviceKey(device_path))) {
729 730 731 732 733 734 735
        ret = -1;
        goto cleanup;
    }

    /* It can't be conflict if no other domain is
     * is sharing it.
     */
736
    if (!(virHashLookup(sharedDevices, key)))
737 738
        goto cleanup;

739
    if (virGetDeviceUnprivSGIO(device_path, NULL, &val) < 0) {
740 741 742 743 744
        ret = -1;
        goto cleanup;
    }

    if ((val == 0 &&
745 746
         (disk->sgio == VIR_DOMAIN_DEVICE_SGIO_FILTERED ||
          disk->sgio == VIR_DOMAIN_DEVICE_SGIO_DEFAULT)) ||
747
        (val == 1 &&
748
         disk->sgio == VIR_DOMAIN_DEVICE_SGIO_UNFILTERED))
749 750
        goto cleanup;

751 752 753 754 755 756 757 758 759 760 761 762
    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
        if (disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME) {
            virReportError(VIR_ERR_OPERATION_INVALID,
                           _("sgio of shared disk 'pool=%s' 'volume=%s' conflicts "
                             "with other active domains"),
                           disk->srcpool->pool,
                           disk->srcpool->volume);
        } else {
            virReportError(VIR_ERR_OPERATION_INVALID,
                           _("sgio of shared disk '%s' conflicts with other "
                             "active domains"), disk->src);
        }
763 764
    } else {
        virReportError(VIR_ERR_OPERATION_INVALID,
765 766 767 768 769 770
                       _("sgio of shared scsi host device '%s-%d-%d-%d' conflicts "
                          "with other active domains"),
                       hostdev->source.subsys.u.scsi.adapter,
                       hostdev->source.subsys.u.scsi.bus,
                       hostdev->source.subsys.u.scsi.target,
                       hostdev->source.subsys.u.scsi.unit);
771 772
    }

773 774
    ret = -1;
cleanup:
775 776
    VIR_FREE(hostdev_name);
    VIR_FREE(hostdev_path);
777 778 779 780
    VIR_FREE(sysfs_path);
    VIR_FREE(key);
    return ret;
}
781
bool
782 783 784
qemuSharedDeviceEntryDomainExists(qemuSharedDeviceEntryPtr entry,
                                  const char *name,
                                  int *idx)
785 786 787 788 789 790 791 792 793 794 795 796 797 798 799
{
    size_t i;

    for (i = 0; i < entry->ref; i++) {
        if (STREQ(entry->domains[i], name)) {
            if (idx)
                *idx = i;
            return true;
        }
    }

    return false;
}

void
800
qemuSharedDeviceEntryFree(void *payload, const void *name ATTRIBUTE_UNUSED)
801
{
802
    qemuSharedDeviceEntryPtr entry = payload;
803 804
    size_t i;

805 806 807
    if (!entry)
        return;

808 809 810 811 812 813 814
    for (i = 0; i < entry->ref; i++) {
        VIR_FREE(entry->domains[i]);
    }
    VIR_FREE(entry->domains);
    VIR_FREE(entry);
}

815 816
static qemuSharedDeviceEntryPtr
qemuSharedDeviceEntryCopy(const qemuSharedDeviceEntryPtr entry)
817
{
818
    qemuSharedDeviceEntryPtr ret = NULL;
819 820
    size_t i;

821
    if (VIR_ALLOC(ret) < 0)
822 823
        return NULL;

824
    if (VIR_ALLOC_N(ret->domains, entry->ref) < 0)
825 826 827
        goto cleanup;

    for (i = 0; i < entry->ref; i++) {
828
        if (VIR_STRDUP(ret->domains[i], entry->domains[i]) < 0)
829 830 831 832 833 834 835
            goto cleanup;
        ret->ref++;
    }

    return ret;

cleanup:
836
    qemuSharedDeviceEntryFree(ret, NULL);
837 838 839
    return NULL;
}

840
/* qemuAddSharedDevice:
841
 * @driver: Pointer to qemu driver struct
842
 * @dev: The device def
843 844 845
 * @name: The domain name
 *
 * Increase ref count and add the domain name into the list which
846
 * records all the domains that use the shared device if the entry
847
 * already exists, otherwise add a new entry.
848 849
 */
int
850 851 852
qemuAddSharedDevice(virQEMUDriverPtr driver,
                    virDomainDeviceDefPtr dev,
                    const char *name)
853
{
854 855
    qemuSharedDeviceEntry *entry = NULL;
    qemuSharedDeviceEntry *new_entry = NULL;
856 857 858 859
    virDomainDiskDefPtr disk = NULL;
    virDomainHostdevDefPtr hostdev = NULL;
    char *dev_name = NULL;
    char *dev_path = NULL;
860
    char *key = NULL;
861
    int ret = -1;
862

863 864 865
    /* Currently the only conflicts we have to care about for
     * the shared disk and shared host device is "sgio" setting,
     * which is only valid for block disk and scsi host device.
866
     */
867 868 869
    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
        disk = dev->data.disk;

870
        if (!disk->shared ||
871 872 873 874 875 876 877 878 879 880 881 882 883 884
            !disk->src ||
            (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK &&
             !(disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME &&
               disk->srcpool &&
               disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK)))
            return 0;
    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
        hostdev = dev->data.hostdev;

        if (!hostdev->shareable ||
            !(hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
              hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI))
            return 0;
    } else {
885
        return 0;
886
    }
887

888
    qemuDriverLock(driver);
889 890
    if (qemuCheckSharedDevice(driver->sharedDevices, dev) < 0)
        goto cleanup;
891

892
    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
893 894 895 896 897 898 899 900 901
        if (!(key = qemuGetSharedDeviceKey(disk->src)))
            goto cleanup;
    } else {
        if (!(dev_name = virSCSIDeviceGetDevName(hostdev->source.subsys.u.scsi.adapter,
                                                 hostdev->source.subsys.u.scsi.bus,
                                                 hostdev->source.subsys.u.scsi.target,
                                                 hostdev->source.subsys.u.scsi.unit)))
            goto cleanup;

902
        if (virAsprintf(&dev_path, "/dev/%s", dev_name) < 0)
903 904 905 906 907
            goto cleanup;

        if (!(key = qemuGetSharedDeviceKey(dev_path)))
            goto cleanup;
    }
908

909
    if ((entry = virHashLookup(driver->sharedDevices, key))) {
910 911
        /* Nothing to do if the shared scsi host device is already
         * recorded in the table.
912
         */
913
        if (qemuSharedDeviceEntryDomainExists(entry, name, NULL)) {
914 915 916 917
            ret = 0;
            goto cleanup;
        }

918
        if (!(new_entry = qemuSharedDeviceEntryCopy(entry)))
919 920
            goto cleanup;

921 922
        if (VIR_EXPAND_N(new_entry->domains, new_entry->ref, 1) < 0 ||
            VIR_STRDUP(new_entry->domains[new_entry->ref - 1], name) < 0) {
923
            qemuSharedDeviceEntryFree(new_entry, NULL);
924 925 926
            goto cleanup;
        }

927 928
        if (virHashUpdateEntry(driver->sharedDevices, key, new_entry) < 0) {
            qemuSharedDeviceEntryFree(new_entry, NULL);
929 930
            goto cleanup;
        }
931
    } else {
932 933 934
        if (VIR_ALLOC(entry) < 0 ||
            VIR_ALLOC_N(entry->domains, 1) < 0 ||
            VIR_STRDUP(entry->domains[0], name) < 0) {
935
            qemuSharedDeviceEntryFree(entry, NULL);
936 937 938 939 940
            goto cleanup;
        }

        entry->ref = 1;

941
        if (virHashAddEntry(driver->sharedDevices, key, entry))
942
            goto cleanup;
943 944
    }

945 946
    ret = 0;
cleanup:
947
    qemuDriverUnlock(driver);
948 949
    VIR_FREE(dev_name);
    VIR_FREE(dev_path);
950
    VIR_FREE(key);
951
    return ret;
952 953
}

954
/* qemuRemoveSharedDevice:
955
 * @driver: Pointer to qemu driver struct
956
 * @device: The device def
957 958 959
 * @name: The domain name
 *
 * Decrease ref count and remove the domain name from the list which
960 961
 * records all the domains that use the shared device if ref is not
 * 1, otherwise remove the entry.
962 963
 */
int
964 965 966
qemuRemoveSharedDevice(virQEMUDriverPtr driver,
                       virDomainDeviceDefPtr dev,
                       const char *name)
967
{
968 969
    qemuSharedDeviceEntryPtr entry = NULL;
    qemuSharedDeviceEntryPtr new_entry = NULL;
970 971
    virDomainDiskDefPtr disk = NULL;
    virDomainHostdevDefPtr hostdev = NULL;
972
    char *key = NULL;
973 974
    char *dev_name = NULL;
    char *dev_path = NULL;
975
    int ret = -1;
976
    int idx;
977

978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995
    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
        disk = dev->data.disk;

        if (!disk->shared ||
            !disk->src ||
            (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK &&
             !(disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME &&
               disk->srcpool &&
               disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK)))
            return 0;
    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
        hostdev = dev->data.hostdev;

        if (!hostdev->shareable ||
            !(hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
              hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI))
            return 0;
    } else {
996
        return 0;
997
    }
998

999
    qemuDriverLock(driver);
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010

    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
        if (!(key = qemuGetSharedDeviceKey(disk->src)))
            goto cleanup;
    } else {
        if (!(dev_name = virSCSIDeviceGetDevName(hostdev->source.subsys.u.scsi.adapter,
                                                 hostdev->source.subsys.u.scsi.bus,
                                                 hostdev->source.subsys.u.scsi.target,
                                                 hostdev->source.subsys.u.scsi.unit)))
            goto cleanup;

1011
        if (virAsprintf(&dev_path, "/dev/%s", dev_name) < 0)
1012 1013 1014 1015 1016
            goto cleanup;

        if (!(key = qemuGetSharedDeviceKey(dev_path)))
            goto cleanup;
    }
1017

1018
    if (!(entry = virHashLookup(driver->sharedDevices, key)))
1019
        goto cleanup;
1020

1021 1022 1023
    /* Nothing to do if the shared disk is not recored in
     * the table.
     */
1024
    if (!qemuSharedDeviceEntryDomainExists(entry, name, &idx)) {
1025 1026 1027 1028 1029
        ret = 0;
        goto cleanup;
    }

    if (entry->ref != 1) {
1030
        if (!(new_entry = qemuSharedDeviceEntryCopy(entry)))
1031 1032 1033 1034 1035 1036 1037 1038 1039
            goto cleanup;

        if (idx != new_entry->ref - 1)
            memmove(&new_entry->domains[idx],
                    &new_entry->domains[idx + 1],
                    sizeof(*new_entry->domains) * (new_entry->ref - idx - 1));

        VIR_SHRINK_N(new_entry->domains, new_entry->ref, 1);

1040 1041
        if (virHashUpdateEntry(driver->sharedDevices, key, new_entry) < 0){
            qemuSharedDeviceEntryFree(new_entry, NULL);
1042
            goto cleanup;
1043
        }
1044
    } else {
1045
        if (virHashRemoveEntry(driver->sharedDevices, key) < 0)
1046
            goto cleanup;
1047 1048
    }

1049 1050
    ret = 0;
cleanup:
1051
    qemuDriverUnlock(driver);
1052 1053
    VIR_FREE(dev_name);
    VIR_FREE(dev_path);
1054
    VIR_FREE(key);
1055
    return ret;
1056
}
1057

1058
int
1059
qemuSetUnprivSGIO(virDomainDeviceDefPtr dev)
1060
{
1061 1062
    virDomainDiskDefPtr disk = NULL;
    virDomainHostdevDefPtr hostdev = NULL;
1063
    char *sysfs_path = NULL;
1064 1065 1066
    char *path = NULL;
    char *hostdev_name = NULL;
    char *hostdev_path = NULL;
1067 1068 1069 1070 1071 1072
    int val = -1;
    int ret = 0;

    /* "sgio" is only valid for block disk; cdrom
     * and floopy disk can have empty source.
     */
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
        disk = dev->data.disk;

        if (!disk->src ||
            disk->device != VIR_DOMAIN_DISK_DEVICE_LUN ||
            (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK &&
             !(disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME &&
               disk->srcpool &&
               disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK)))
            return 0;

        path = disk->src;
    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
        hostdev = dev->data.hostdev;

        if (!hostdev->shareable ||
            !(hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
              hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI))
            return 0;

        if (!(hostdev_name = virSCSIDeviceGetDevName(hostdev->source.subsys.u.scsi.adapter,
                                                     hostdev->source.subsys.u.scsi.bus,
                                                     hostdev->source.subsys.u.scsi.target,
                                                     hostdev->source.subsys.u.scsi.unit)))
            goto cleanup;

1099
        if (virAsprintf(&hostdev_path, "/dev/%s", hostdev_name) < 0)
1100 1101 1102 1103
            goto cleanup;

        path = hostdev_path;
    } else {
1104
        return 0;
1105
    }
1106

1107 1108 1109 1110 1111
    sysfs_path = virGetUnprivSGIOSysfsPath(path, NULL);
    if (sysfs_path == NULL) {
        ret = -1;
        goto cleanup;
    }
1112 1113

    /* By default, filter the SG_IO commands, i.e. set unpriv_sgio to 0.  */
1114 1115 1116 1117 1118 1119

    if (dev->type == VIR_DOMAIN_DEVICE_DISK)
        val = (disk->sgio == VIR_DOMAIN_DEVICE_SGIO_UNFILTERED);
    else
        val = (hostdev->source.subsys.u.scsi.sgio ==
               VIR_DOMAIN_DEVICE_SGIO_UNFILTERED);
1120 1121 1122 1123 1124 1125

    /* Do not do anything if unpriv_sgio is not supported by the kernel and the
     * whitelist is enabled.  But if requesting unfiltered access, always call
     * virSetDeviceUnprivSGIO, to report an error for unsupported unpriv_sgio.
     */
    if ((virFileExists(sysfs_path) || val == 1) &&
1126
        virSetDeviceUnprivSGIO(path, NULL, val) < 0)
1127 1128
        ret = -1;

1129
cleanup:
1130
    VIR_FREE(sysfs_path);
1131 1132
    VIR_FREE(hostdev_name);
    VIR_FREE(hostdev_path);
1133 1134
    return ret;
}
1135

1136 1137 1138 1139
int qemuDriverAllocateID(virQEMUDriverPtr driver)
{
    return virAtomicIntInc(&driver->nextvmid);
}
1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191

int
qemuTranslateDiskSourcePool(virConnectPtr conn,
                            virDomainDiskDefPtr def)
{
    virStoragePoolPtr pool = NULL;
    virStorageVolPtr vol = NULL;
    virStorageVolInfo info;
    int ret = -1;

    if (def->type != VIR_DOMAIN_DISK_TYPE_VOLUME)
        return 0;

    if (!def->srcpool)
        return 0;

    if (!(pool = virStoragePoolLookupByName(conn, def->srcpool->pool)))
        return -1;

    if (!(vol = virStorageVolLookupByName(pool, def->srcpool->volume)))
        goto cleanup;

    if (virStorageVolGetInfo(vol, &info) < 0)
        goto cleanup;

    if (def->startupPolicy &&
        info.type != VIR_STORAGE_VOL_FILE) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("'startupPolicy' is only valid for 'file' type volume"));
        goto cleanup;
    }

    switch (info.type) {
    case VIR_STORAGE_VOL_FILE:
    case VIR_STORAGE_VOL_BLOCK:
    case VIR_STORAGE_VOL_DIR:
        if (!(def->src = virStorageVolGetPath(vol)))
            goto cleanup;
        break;
    case VIR_STORAGE_VOL_NETWORK:
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Using network volume as disk source is not supported"));
        goto cleanup;
    }

    def->srcpool->voltype = info.type;
    ret = 0;
cleanup:
    virStoragePoolFree(pool);
    virStorageVolFree(vol);
    return ret;
}