lxc_process.c 44.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * Copyright (C) 2010-2012 Red Hat, Inc.
 * Copyright IBM Corp. 2008
 *
 * lxc_process.c: LXC process lifecycle management
 *
 * 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/>.
20 21 22 23
 */

#include <config.h>

G
Guido Günther 已提交
24
#include <sys/stat.h>
25 26 27 28 29 30 31
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>

#include "lxc_process.h"
#include "lxc_domain.h"
#include "lxc_container.h"
32
#include "lxc_cgroup.h"
G
Gao feng 已提交
33
#include "lxc_fuse.h"
34 35 36 37 38 39 40 41 42
#include "datatypes.h"
#include "virfile.h"
#include "virpidfile.h"
#include "virnetdev.h"
#include "virnetdevveth.h"
#include "virnetdevbridge.h"
#include "virtime.h"
#include "domain_nwfilter.h"
#include "network/bridge_driver.h"
43
#include "viralloc.h"
44
#include "domain_audit.h"
45
#include "virerror.h"
46
#include "virlog.h"
47
#include "vircommand.h"
48
#include "lxc_hostdev.h"
49
#include "virhook.h"
50
#include "virstring.h"
51
#include "viratomic.h"
52 53 54 55 56

#define VIR_FROM_THIS VIR_FROM_LXC

#define START_POSTFIX ": starting up\n"

57 58 59 60
static virDomainObjPtr
lxcProcessAutoDestroy(virDomainObjPtr dom,
                      virConnectPtr conn,
                      void *opaque)
61
{
62
    virLXCDriverPtr driver = opaque;
63
    virDomainEventPtr event = NULL;
64
    virLXCDomainObjPrivatePtr priv;
65

66
    VIR_DEBUG("driver=%p dom=%s conn=%p", driver, dom->def->name, conn);
67

68
    priv = dom->privateData;
69
    VIR_DEBUG("Killing domain");
70
    virLXCProcessStop(driver, dom, VIR_DOMAIN_SHUTOFF_DESTROYED);
71 72 73 74
    virDomainAuditStop(dom, "destroyed");
    event = virDomainEventNewFromObj(dom,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
75
    priv->doneStopEvent = true;
76

77 78 79 80
    if (dom && !dom->persistent) {
        virDomainObjListRemove(driver->domains, dom);
        dom = NULL;
    }
81 82

    if (event)
83 84 85
        virDomainEventStateQueue(driver->domainEventState, event);

    return dom;
86 87 88 89 90
}

/*
 * Precondition: driver is locked
 */
91 92 93 94
static int
virLXCProcessReboot(virLXCDriverPtr driver,
                    virDomainObjPtr vm)
{
95
    virConnectPtr conn = virCloseCallbacksGetConn(driver->closeCallbacks, vm);
96 97 98 99 100
    int reason = vm->state.reason;
    bool autodestroy = false;
    int ret = -1;
    virDomainDefPtr savedDef;

101 102
    VIR_DEBUG("Faking reboot");

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
    if (conn) {
        virConnectRef(conn);
        autodestroy = true;
    } else {
        conn = virConnectOpen("lxc:///");
        /* Ignoring NULL conn which is mostly harmless here */
    }

    /* In a reboot scenario, we need to make sure we continue
     * to use the current 'def', and not switch to 'newDef'.
     * So temporarily hide the newDef and then reinstate it
     */
    savedDef = vm->newDef;
    vm->newDef = NULL;
    virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
    vm->newDef = savedDef;
119 120
    if (virLXCProcessStart(conn, driver, vm,
                           0, NULL, autodestroy, reason) < 0) {
121 122 123 124 125 126 127 128 129 130 131 132 133 134
        VIR_WARN("Unable to handle reboot of vm %s",
                 vm->def->name);
        goto cleanup;
    }

    if (conn)
        virConnectClose(conn);

    ret = 0;

cleanup:
    return ret;
}

135 136

/**
137
 * virLXCProcessCleanup:
138 139 140 141 142 143 144
 * @driver: pointer to driver structure
 * @vm: pointer to VM to clean up
 * @reason: reason for switching the VM to shutoff state
 *
 * Cleanout resources associated with the now dead VM
 *
 */
145
static void virLXCProcessCleanup(virLXCDriverPtr driver,
146 147
                                 virDomainObjPtr vm,
                                 virDomainShutoffReason reason)
148
{
149
    size_t i;
150
    virLXCDomainObjPrivatePtr priv = vm->privateData;
151
    virNetDevVPortProfilePtr vport = NULL;
152
    virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
153

154 155 156
    VIR_DEBUG("Stopping VM name=%s pid=%d reason=%d",
              vm->def->name, (int)vm->pid, (int)reason);

157 158 159 160 161 162 163 164 165 166 167 168
    /* now that we know it's stopped call the hook if present */
    if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
        char *xml = virDomainDefFormat(vm->def, 0);

        /* we can't stop the operation even if the script raised an error */
        virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
                    VIR_HOOK_LXC_OP_STOPPED, VIR_HOOK_SUBOP_END,
                    NULL, xml, NULL);
        VIR_FREE(xml);
    }

    /* Stop autodestroy in case guest is restarted */
169 170
    virCloseCallbacksUnset(driver->closeCallbacks, vm,
                           lxcProcessAutoDestroy);
171

172 173
    if (priv->monitor) {
        virLXCMonitorClose(priv->monitor);
174
        virObjectUnref(priv->monitor);
175 176
        priv->monitor = NULL;
    }
177

178 179
    virPidFileDelete(cfg->stateDir, vm->def->name);
    virDomainDeleteConfig(cfg->stateDir, NULL, vm);
180 181 182 183 184

    virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
    vm->pid = -1;
    vm->def->id = -1;

185
    if (virAtomicIntDecAndTest(&driver->nactive) && driver->inhibitCallback)
186 187
        driver->inhibitCallback(false, driver->inhibitOpaque);

188 189
    virLXCDomainReAttachHostDevices(driver, vm->def);

190
    for (i = 0; i < vm->def->nnets; i++) {
191 192
        virDomainNetDefPtr iface = vm->def->nets[i];
        vport = virDomainNetGetActualVirtPortProfile(iface);
193
        if (iface->ifname) {
194
            ignore_value(virNetDevSetOnline(iface->ifname, false));
195 196 197 198 199 200 201
            if (vport &&
                vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
                ignore_value(virNetDevOpenvswitchRemovePort(
                                virDomainNetGetActualBridgeName(iface),
                                iface->ifname));
            ignore_value(virNetDevVethDelete(iface->ifname));
        }
202 203 204 205 206
        networkReleaseActualDevice(iface);
    }

    virDomainConfVMNWFilterTeardown(vm);

207 208 209
    if (priv->cgroup) {
        virCgroupRemove(priv->cgroup);
        virCgroupFree(&priv->cgroup);
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
    }

    /* now that we know it's stopped call the hook if present */
    if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
        char *xml = virDomainDefFormat(vm->def, 0);

        /* we can't stop the operation even if the script raised an error */
        virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
                    VIR_HOOK_LXC_OP_RELEASE, VIR_HOOK_SUBOP_END,
                    NULL, xml, NULL);
        VIR_FREE(xml);
    }

    if (vm->newDef) {
        virDomainDefFree(vm->def);
        vm->def = vm->newDef;
        vm->def->id = -1;
        vm->newDef = NULL;
    }
229
    virObjectUnref(cfg);
230 231 232
}


233 234 235 236
char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn,
                                         virDomainDefPtr vm,
                                         virDomainNetDefPtr net,
                                         const char *brname)
237
{
238
    char *ret = NULL;
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
    char *parentVeth;
    char *containerVeth = NULL;
    const virNetDevVPortProfilePtr vport = virDomainNetGetActualVirtPortProfile(net);

    VIR_DEBUG("calling vethCreate()");
    parentVeth = net->ifname;
    if (virNetDevVethCreate(&parentVeth, &containerVeth) < 0)
        goto cleanup;
    VIR_DEBUG("parentVeth: %s, containerVeth: %s", parentVeth, containerVeth);

    if (net->ifname == NULL)
        net->ifname = parentVeth;

    if (virNetDevSetMAC(containerVeth, &net->mac) < 0)
        goto cleanup;

255 256 257 258 259 260 261 262
    if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) {
        if (virNetDevOpenvswitchAddPort(brname, parentVeth, &net->mac,
                                        vm->uuid, vport, virDomainNetGetActualVlan(net)) < 0)
            goto cleanup;
    } else {
        if (virNetDevBridgeAddPort(brname, parentVeth) < 0)
            goto cleanup;
    }
263 264 265 266 267

    if (virNetDevSetOnline(parentVeth, true) < 0)
        goto cleanup;

    if (virNetDevBandwidthSet(net->ifname,
268 269
                              virDomainNetGetActualBandwidth(net),
                              false) < 0) {
270 271 272
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("cannot set bandwidth limits on %s"),
                       net->ifname);
273 274 275 276 277 278 279
        goto cleanup;
    }

    if (net->filter &&
        virDomainConfNWFilterInstantiate(conn, vm->uuid, net) < 0)
        goto cleanup;

280
    ret = containerVeth;
281 282 283 284 285 286

cleanup:
    return ret;
}


287 288 289
char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn,
                                        virDomainDefPtr def,
                                        virDomainNetDefPtr net)
290
{
291
    char *ret = NULL;
292
    char *res_ifname = NULL;
293
    virLXCDriverPtr driver = conn->privateData;
294 295
    virNetDevBandwidthPtr bw;
    virNetDevVPortProfilePtr prof;
296
    virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
297 298 299 300 301 302 303 304

    /* XXX how todo bandwidth controls ?
     * Since the 'net-ifname' is about to be moved to a different
     * namespace & renamed, there will be no host side visible
     * interface for the container to attach rules to
     */
    bw = virDomainNetGetActualBandwidth(net);
    if (bw) {
305 306
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Unable to set network bandwidth on direct interfaces"));
307
        return NULL;
308 309 310 311 312 313 314 315 316 317 318
    }

    /* XXX how todo port profiles ?
     * Although we can do the association during container
     * startup, at shutdown we are unable to disassociate
     * because the macvlan device was moved to the container
     * and automagically dies when the container dies. So
     * we have no dev to perform disassociation with.
     */
    prof = virDomainNetGetActualVirtPortProfile(net);
    if (prof) {
319 320
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Unable to set port profile on direct interfaces"));
321
        return NULL;
322 323 324 325 326 327 328 329 330 331
    }

    if (virNetDevMacVLanCreateWithVPortProfile(
            net->ifname, &net->mac,
            virDomainNetGetActualDirectDev(net),
            virDomainNetGetActualDirectMode(net),
            false, false, def->uuid,
            virDomainNetGetActualVirtPortProfile(net),
            &res_ifname,
            VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
332
            cfg->stateDir,
333 334 335
            virDomainNetGetActualBandwidth(net)) < 0)
        goto cleanup;

336
    ret = res_ifname;
337 338

cleanup:
339
    virObjectUnref(cfg);
340 341 342 343 344
    return ret;
}


/**
345
 * virLXCProcessSetupInterfaces:
346 347 348 349 350 351 352 353 354 355 356
 * @conn: pointer to connection
 * @def: pointer to virtual machine structure
 * @nveths: number of interfaces
 * @veths: interface names
 *
 * Sets up the container interfaces by creating the veth device pairs and
 * attaching the parent end to the appropriate bridge.  The container end
 * will moved into the container namespace later after clone has been called.
 *
 * Returns 0 on success or -1 in case of error
 */
357 358
static int virLXCProcessSetupInterfaces(virConnectPtr conn,
                                        virDomainDefPtr def,
359
                                        size_t *nveths,
360
                                        char ***veths)
361 362 363 364
{
    int ret = -1;
    size_t i;

365
    for (i = 0; i < def->nnets; i++) {
366
        char *veth = NULL;
367 368 369 370 371 372 373
        /* If appropriate, grab a physical device from the configured
         * network's pool of devices, or resolve bridge device name
         * to the one defined in the network definition.
         */
        if (networkAllocateActualDevice(def->nets[i]) < 0)
            goto cleanup;

374
        if (VIR_EXPAND_N(*veths, *nveths, 1) < 0)
375 376
            goto cleanup;

377 378 379 380
        switch (virDomainNetGetActualType(def->nets[i])) {
        case VIR_DOMAIN_NET_TYPE_NETWORK: {
            virNetworkPtr network;
            char *brname = NULL;
381 382 383
            bool fail = false;
            int active;
            virErrorPtr errobj;
384 385 386 387 388

            if (!(network = virNetworkLookupByName(conn,
                                                   def->nets[i]->data.network.name)))
                goto cleanup;

389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
            active = virNetworkIsActive(network);
            if (active != 1) {
                fail = true;
                if (active == 0)
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("Network '%s' is not active."),
                                   def->nets[i]->data.network.name);
            }

            if (!fail) {
                brname = virNetworkGetBridgeName(network);
                if (brname == NULL)
                    fail = true;
            }

            /* Make sure any above failure is preserved */
            errobj = virSaveLastError();
406
            virNetworkFree(network);
407 408 409 410
            virSetError(errobj);
            virFreeError(errobj);

            if (fail)
411 412
                goto cleanup;

413 414 415 416
            if (!(veth = virLXCProcessSetupInterfaceBridged(conn,
                                                            def,
                                                            def->nets[i],
                                                            brname))) {
417 418 419 420 421 422 423 424 425
                VIR_FREE(brname);
                goto cleanup;
            }
            VIR_FREE(brname);
            break;
        }
        case VIR_DOMAIN_NET_TYPE_BRIDGE: {
            const char *brname = virDomainNetGetActualBridgeName(def->nets[i]);
            if (!brname) {
426 427
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("No bridge name specified"));
428 429
                goto cleanup;
            }
430 431 432 433
            if (!(veth = virLXCProcessSetupInterfaceBridged(conn,
                                                            def,
                                                            def->nets[i],
                                                            brname)))
434 435 436 437
                goto cleanup;
        }   break;

        case VIR_DOMAIN_NET_TYPE_DIRECT:
438 439 440
            if (!(veth = virLXCProcessSetupInterfaceDirect(conn,
                                                           def,
                                                           def->nets[i])))
441 442 443 444 445 446 447 448 449 450
                goto cleanup;
            break;

        case VIR_DOMAIN_NET_TYPE_USER:
        case VIR_DOMAIN_NET_TYPE_ETHERNET:
        case VIR_DOMAIN_NET_TYPE_SERVER:
        case VIR_DOMAIN_NET_TYPE_CLIENT:
        case VIR_DOMAIN_NET_TYPE_MCAST:
        case VIR_DOMAIN_NET_TYPE_INTERNAL:
        case VIR_DOMAIN_NET_TYPE_LAST:
451 452 453 454 455
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unsupported network type %s"),
                           virDomainNetTypeToString(
                               virDomainNetGetActualType(def->nets[i])
                               ));
456 457
            goto cleanup;
        }
458 459

        (*veths)[(*nveths)-1] = veth;
460 461
    }

462
    ret = 0;
463 464

cleanup:
465
    if (ret < 0) {
466
        for (i = 0; i < def->nnets; i++) {
467 468 469 470 471 472 473 474 475 476 477 478 479
            virDomainNetDefPtr iface = def->nets[i];
            virNetDevVPortProfilePtr vport = virDomainNetGetActualVirtPortProfile(iface);
            if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
                ignore_value(virNetDevOpenvswitchRemovePort(
                                virDomainNetGetActualBridgeName(iface),
                                iface->ifname));
            networkReleaseActualDevice(iface);
        }
    }
    return ret;
}


480
extern virLXCDriverPtr lxc_driver;
481
static void virLXCProcessMonitorEOFNotify(virLXCMonitorPtr mon,
482
                                          virDomainObjPtr vm)
483 484 485 486 487
{
    virLXCDriverPtr driver = lxc_driver;
    virDomainEventPtr event = NULL;
    virLXCDomainObjPrivatePtr priv;

488 489
    VIR_DEBUG("mon=%p vm=%p", mon, vm);

490
    lxcDriverLock(driver);
491
    virObjectLock(vm);
492 493 494 495
    lxcDriverUnlock(driver);

    priv = vm->privateData;
    virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
496 497 498 499 500 501 502 503 504 505 506
    if (!priv->wantReboot) {
        virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
        if (!priv->doneStopEvent) {
            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_STOPPED,
                                             priv->stopReason);
            virDomainAuditStop(vm, "shutdown");
        } else {
            VIR_DEBUG("Stop event has already been sent");
        }
        if (!vm->persistent) {
507
            virDomainObjListRemove(driver->domains, vm);
508 509
            vm = NULL;
        }
510
    } else {
511 512 513 514 515 516 517 518 519 520
        int ret = virLXCProcessReboot(driver, vm);
        virDomainAuditStop(vm, "reboot");
        virDomainAuditStart(vm, "reboot", ret == 0);
        if (ret == 0) {
            event = virDomainEventRebootNewFromObj(vm);
        } else {
            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_STOPPED,
                                             priv->stopReason);
            if (!vm->persistent) {
521
                virDomainObjListRemove(driver->domains, vm);
522 523 524
                vm = NULL;
            }
        }
525 526 527
    }

    if (vm)
528
        virObjectUnlock(vm);
529 530 531 532 533 534 535
    if (event) {
        lxcDriverLock(driver);
        virDomainEventStateQueue(driver->domainEventState, event);
        lxcDriverUnlock(driver);
    }
}

536
static void virLXCProcessMonitorExitNotify(virLXCMonitorPtr mon ATTRIBUTE_UNUSED,
537
                                           virLXCMonitorExitStatus status,
538 539
                                           virDomainObjPtr vm)
{
540
    virLXCDriverPtr driver = lxc_driver;
541 542
    virLXCDomainObjPrivatePtr priv = vm->privateData;

543 544 545 546
    lxcDriverLock(driver);
    virObjectLock(vm);
    lxcDriverUnlock(driver);

547
    switch (status) {
548
    case VIR_LXC_MONITOR_EXIT_STATUS_SHUTDOWN:
549 550
        priv->stopReason = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN;
        break;
551
    case VIR_LXC_MONITOR_EXIT_STATUS_ERROR:
552 553
        priv->stopReason = VIR_DOMAIN_EVENT_STOPPED_FAILED;
        break;
554
    case VIR_LXC_MONITOR_EXIT_STATUS_REBOOT:
555 556 557
        priv->stopReason = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN;
        priv->wantReboot = true;
        break;
558 559 560 561 562 563
    default:
        priv->stopReason = VIR_DOMAIN_EVENT_STOPPED_FAILED;
        break;
    }
    VIR_DEBUG("Domain shutoff reason %d (from status %d)",
              priv->stopReason, status);
564 565

    virObjectUnlock(vm);
566
}
567

568 569 570 571 572 573 574 575 576 577
static int
virLXCProcessGetNsInode(pid_t pid,
                        const char *nsname,
                        ino_t *inode)
{
    char *path = NULL;
    struct stat sb;
    int ret = -1;

    if (virAsprintf(&path, "/proc/%llu/ns/%s",
578
                    (unsigned long long)pid, nsname) < 0)
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
        goto cleanup;

    if (stat(path, &sb) < 0) {
        virReportSystemError(errno,
                             _("Unable to stat %s"), path);
        goto cleanup;
    }

    *inode = sb.st_ino;
    ret = 0;

cleanup:
    VIR_FREE(path);
    return ret;
}


596 597
/* XXX a little evil */
extern virLXCDriverPtr lxc_driver;
598 599 600 601
static void virLXCProcessMonitorInitNotify(virLXCMonitorPtr mon ATTRIBUTE_UNUSED,
                                           pid_t initpid,
                                           virDomainObjPtr vm)
{
602 603
    virLXCDriverPtr driver = lxc_driver;
    virLXCDomainObjPrivatePtr priv;
604
    virLXCDriverConfigPtr cfg;
605 606
    ino_t inode;

607 608
    lxcDriverLock(driver);
    virObjectLock(vm);
609
    cfg = virLXCDriverGetConfig(driver);
610 611 612
    lxcDriverUnlock(driver);

    priv = vm->privateData;
613
    priv->initpid = initpid;
614 615 616 617 618 619 620 621 622 623

    if (virLXCProcessGetNsInode(initpid, "pid", &inode) < 0) {
        virErrorPtr err = virGetLastError();
        VIR_WARN("Cannot obtain pid NS inode for %llu: %s",
                 (unsigned long long)initpid,
                 err && err->message ? err->message : "<unknown>");
        virResetLastError();
        inode = 0;
    }
    virDomainAuditInit(vm, initpid, inode);
624

625
    if (virDomainSaveStatus(lxc_driver->xmlopt, cfg->stateDir, vm) < 0)
626
        VIR_WARN("Cannot update XML with PID for LXC %s", vm->def->name);
627 628

    virObjectUnlock(vm);
629
    virObjectUnref(cfg);
630 631
}

632 633
static virLXCMonitorCallbacks monitorCallbacks = {
    .eofNotify = virLXCProcessMonitorEOFNotify,
634
    .exitNotify = virLXCProcessMonitorExitNotify,
635
    .initNotify = virLXCProcessMonitorInitNotify,
636
};
637

638 639 640 641 642

static virLXCMonitorPtr virLXCProcessConnectMonitor(virLXCDriverPtr driver,
                                                    virDomainObjPtr vm)
{
    virLXCMonitorPtr monitor = NULL;
643
    virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
644

645 646
    if (virSecurityManagerSetSocketLabel(driver->securityManager, vm->def) < 0)
        goto cleanup;
647

648 649
    /* Hold an extra reference because we can't allow 'vm' to be
     * deleted while the monitor is active */
650
    virObjectRef(vm);
651

652
    monitor = virLXCMonitorNew(vm, cfg->stateDir, &monitorCallbacks);
653 654

    if (monitor == NULL)
655
        virObjectUnref(vm);
656 657

    if (virSecurityManagerClearSocketLabel(driver->securityManager, vm->def) < 0) {
658
        if (monitor) {
659
            virObjectUnref(monitor);
660 661
            monitor = NULL;
        }
662
        goto cleanup;
663 664
    }

665
cleanup:
666
    virObjectUnref(cfg);
667
    return monitor;
668 669 670
}


671
int virLXCProcessStop(virLXCDriverPtr driver,
672 673
                      virDomainObjPtr vm,
                      virDomainShutoffReason reason)
674 675
{
    int rc;
676
    virLXCDomainObjPrivatePtr priv;
677

678 679
    VIR_DEBUG("Stopping VM name=%s pid=%d reason=%d",
              vm->def->name, (int)vm->pid, (int)reason);
680 681 682 683 684
    if (!virDomainObjIsActive(vm)) {
        VIR_DEBUG("VM '%s' not active", vm->def->name);
        return 0;
    }

685 686
    priv = vm->privateData;

687
    if (vm->pid <= 0) {
688 689
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Invalid PID %d for container"), vm->pid);
690 691 692 693 694 695 696
        return -1;
    }

    virSecurityManagerRestoreAllLabel(driver->securityManager,
                                      vm->def, false);
    virSecurityManagerReleaseLabel(driver->securityManager, vm->def);
    /* Clear out dynamically assigned labels */
697 698 699 700 701
    if (vm->def->nseclabels &&
        vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
        VIR_FREE(vm->def->seclabels[0]->model);
        VIR_FREE(vm->def->seclabels[0]->label);
        VIR_FREE(vm->def->seclabels[0]->imagelabel);
702 703
    }

704 705
    if (priv->cgroup) {
        rc = virCgroupKillPainfully(priv->cgroup);
706 707 708 709 710 711 712
        if (rc < 0) {
            virReportSystemError(-rc, "%s",
                                 _("Failed to kill container PIDs"));
            rc = -1;
            goto cleanup;
        }
        if (rc == 1) {
713 714
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Some container PIDs refused to die"));
715 716 717 718 719 720 721 722 723
            rc = -1;
            goto cleanup;
        }
    } else {
        /* If cgroup doesn't exist, the VM pids must have already
         * died and so we're just cleaning up stale state
         */
    }

724
    virLXCProcessCleanup(driver, vm, reason);
725 726 727 728 729 730 731 732 733

    rc = 0;

cleanup:
    return rc;
}


static virCommandPtr
734
virLXCProcessBuildControllerCmd(virLXCDriverPtr driver,
735 736 737 738 739
                                virDomainObjPtr vm,
                                int nveths,
                                char **veths,
                                int *ttyFDs,
                                size_t nttyFDs,
740 741
                                int *files,
                                size_t nfiles,
742
                                int handshakefd)
743 744 745 746 747
{
    size_t i;
    char *filterstr;
    char *outputstr;
    virCommandPtr cmd;
748
    virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768

    cmd = virCommandNew(vm->def->emulator);

    /* The controller may call ip command, so we have to retain PATH. */
    virCommandAddEnvPass(cmd, "PATH");

    virCommandAddEnvFormat(cmd, "LIBVIRT_DEBUG=%d",
                           virLogGetDefaultPriority());

    if (virLogGetNbFilters() > 0) {
        filterstr = virLogGetFilters();
        if (!filterstr) {
            virReportOOMError();
            goto cleanup;
        }

        virCommandAddEnvPair(cmd, "LIBVIRT_LOG_FILTERS", filterstr);
        VIR_FREE(filterstr);
    }

769
    if (cfg->log_libvirtd) {
770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
        if (virLogGetNbOutputs() > 0) {
            outputstr = virLogGetOutputs();
            if (!outputstr) {
                virReportOOMError();
                goto cleanup;
            }

            virCommandAddEnvPair(cmd, "LIBVIRT_LOG_OUTPUTS", outputstr);
            VIR_FREE(outputstr);
        }
    } else {
        virCommandAddEnvFormat(cmd,
                               "LIBVIRT_LOG_OUTPUTS=%d:stderr",
                               virLogGetDefaultPriority());
    }

    virCommandAddArgList(cmd, "--name", vm->def->name, NULL);
787
    for (i = 0; i < nttyFDs; i++) {
788 789
        virCommandAddArg(cmd, "--console");
        virCommandAddArgFormat(cmd, "%d", ttyFDs[i]);
790
        virCommandPassFD(cmd, ttyFDs[i], 0);
791 792
    }

793 794 795
    for (i = 0; i < nfiles; i++) {
        virCommandAddArg(cmd, "--passfd");
        virCommandAddArgFormat(cmd, "%d", files[i]);
796
        virCommandPassFD(cmd, files[i], 0);
797 798
    }

799 800 801 802 803 804 805
    virCommandAddArgPair(cmd, "--security",
                         virSecurityManagerGetModel(driver->securityManager));

    virCommandAddArg(cmd, "--handshake");
    virCommandAddArgFormat(cmd, "%d", handshakefd);
    virCommandAddArg(cmd, "--background");

806
    for (i = 0; i < nveths; i++) {
807 808 809
        virCommandAddArgList(cmd, "--veth", veths[i], NULL);
    }

810
    virCommandPassFD(cmd, handshakefd, 0);
811 812 813 814

    return cmd;
cleanup:
    virCommandFree(cmd);
815
    virObjectUnref(cfg);
816 817 818
    return NULL;
}

819

820
static int
821 822 823 824
virLXCProcessReadLogOutputData(virDomainObjPtr vm,
                               int fd,
                               char *buf,
                               size_t buflen)
825 826
{
    int retries = 10;
827 828 829
    int got = 0;
    int ret = -1;
    char *filter_next = buf;
830

831
    buf[0] = '\0';
832 833 834

    while (retries) {
        ssize_t bytes;
835
        bool isdead = false;
836
        char *eol;
837

838 839
        if (vm->pid <= 0 ||
            (kill(vm->pid, 0) == -1 && errno == ESRCH))
840
            isdead = true;
841 842 843 844 845 846

        /* Any failures should be detected before we read the log, so we
         * always have something useful to report on failure. */
        bytes = saferead(fd, buf+got, buflen-got-1);
        if (bytes < 0) {
            virReportSystemError(errno, "%s",
847
                                 _("Failure while reading log output"));
848 849 850 851 852 853
            goto cleanup;
        }

        got += bytes;
        buf[got] = '\0';

854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875
        /* Filter out debug messages from intermediate libvirt process */
        while ((eol = strchr(filter_next, '\n'))) {
            *eol = '\0';
            if (virLogProbablyLogMessage(filter_next)) {
                memmove(filter_next, eol + 1, got - (eol - buf));
                got -= eol + 1 - filter_next;
            } else {
                filter_next = eol + 1;
                *eol = '\n';
            }
        }

        if (got == buflen-1) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Out of space while reading log output: %s"),
                           buf);
            goto cleanup;
        }

        if (isdead) {
            ret = got;
            goto cleanup;
876 877 878 879 880 881
        }

        usleep(100*1000);
        retries--;
    }

882 883 884
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Timed out while reading log output: %s"),
                   buf);
885 886

cleanup:
887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920
    return ret;
}


static int
virLXCProcessReadLogOutput(virDomainObjPtr vm,
                           char *logfile,
                           off_t pos,
                           char *buf,
                           size_t buflen)
{
    int fd = -1;
    int ret;

    if ((fd = open(logfile, O_RDONLY)) < 0) {
        virReportSystemError(errno,
                             _("Unable to open log file %s"),
                             logfile);
        return -1;
    }

    if (lseek(fd, pos, SEEK_SET) < 0) {
        virReportSystemError(errno,
                             _("Unable to seek log file %s to %llu"),
                             logfile, (unsigned long long)pos);
        VIR_FORCE_CLOSE(fd);
        return -1;
    }

    ret = virLXCProcessReadLogOutputData(vm,
                                         fd,
                                         buf,
                                         buflen);

921 922 923 924
    VIR_FORCE_CLOSE(fd);
    return ret;
}

925 926 927 928 929 930 931 932 933 934

static int
virLXCProcessEnsureRootFS(virDomainObjPtr vm)
{
    virDomainFSDefPtr root = virDomainGetRootFilesystem(vm->def);

    if (root)
        return 0;

    if (VIR_ALLOC(root) < 0)
935
        goto error;
936 937 938

    root->type = VIR_DOMAIN_FS_TYPE_MOUNT;

939 940 941
    if (VIR_STRDUP(root->src, "/") < 0 ||
        VIR_STRDUP(root->dst, "/") < 0)
        goto error;
942

943 944 945 946 947
    if (VIR_INSERT_ELEMENT(vm->def->fss,
                           0,
                           vm->def->nfss,
                           root) < 0)
        goto error;
948 949 950

    return 0;

951
error:
952 953 954 955
    virDomainFSDefFree(root);
    return -1;
}

956
/**
957
 * virLXCProcessStart:
958 959 960 961 962 963 964 965 966 967
 * @conn: pointer to connection
 * @driver: pointer to driver structure
 * @vm: pointer to virtual machine structure
 * @autoDestroy: mark the domain for auto destruction
 * @reason: reason for switching vm to running state
 *
 * Starts a vm
 *
 * Returns 0 on success or -1 in case of error
 */
968
int virLXCProcessStart(virConnectPtr conn,
969
                       virLXCDriverPtr  driver,
970
                       virDomainObjPtr vm,
971
                       unsigned int nfiles, int *files,
972 973
                       bool autoDestroy,
                       virDomainRunningReason reason)
974 975 976 977 978 979 980
{
    int rc = -1, r;
    size_t nttyFDs = 0;
    int *ttyFDs = NULL;
    size_t i;
    char *logfile = NULL;
    int logfd = -1;
981
    size_t nveths = 0;
982 983 984 985 986 987
    char **veths = NULL;
    int handshakefds[2] = { -1, -1 };
    off_t pos = -1;
    char ebuf[1024];
    char *timestamp;
    virCommandPtr cmd = NULL;
988
    virLXCDomainObjPrivatePtr priv = vm->privateData;
989
    virCapsPtr caps = NULL;
990
    virErrorPtr err = NULL;
991
    virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
992

993 994
    virCgroupFree(&priv->cgroup);

995
    if (!(priv->cgroup = virLXCCgroupCreate(vm->def, true)))
996 997
        return -1;

998 999 1000
    if (!virCgroupHasController(priv->cgroup,
                                VIR_CGROUP_CONTROLLER_CPUACCT)) {
        virCgroupFree(&priv->cgroup);
1001 1002
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to find 'cpuacct' cgroups controller mount"));
1003 1004
        return -1;
    }
1005
    if (!virCgroupHasController(priv->cgroup,
1006
                                VIR_CGROUP_CONTROLLER_DEVICES)) {
1007
        virCgroupFree(&priv->cgroup);
1008 1009
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to find 'devices' cgroups controller mount"));
1010 1011
        return -1;
    }
1012
    if (!virCgroupHasController(priv->cgroup,
1013
                                VIR_CGROUP_CONTROLLER_MEMORY)) {
1014
        virCgroupFree(&priv->cgroup);
1015 1016
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to find 'memory' cgroups controller mount"));
1017 1018 1019
        return -1;
    }

1020
    if (virFileMakePath(cfg->logDir) < 0) {
1021 1022
        virReportSystemError(errno,
                             _("Cannot create log directory '%s'"),
1023
                             cfg->logDir);
1024 1025 1026 1027
        return -1;
    }

    if (virAsprintf(&logfile, "%s/%s.log",
1028
                    cfg->logDir, vm->def->name) < 0)
1029 1030
        return -1;

1031 1032 1033
    if (!(caps = virLXCDriverGetCapabilities(driver, false)))
        goto cleanup;

1034 1035 1036 1037 1038
    /* Do this up front, so any part of the startup process can add
     * runtime state to vm->def that won't be persisted. This let's us
     * report implicit runtime defaults in the XML, like vnc listen/socket
     */
    VIR_DEBUG("Setting current domain def as transient");
1039
    if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, true) < 0)
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058
        goto cleanup;

    /* Run an early hook to set-up missing devices */
    if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
        char *xml = virDomainDefFormat(vm->def, 0);
        int hookret;

        hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
                              VIR_HOOK_LXC_OP_PREPARE, VIR_HOOK_SUBOP_BEGIN,
                              NULL, xml, NULL);
        VIR_FREE(xml);

        /*
         * If the script raised an error abort the launch
         */
        if (hookret < 0)
            goto cleanup;
    }

1059 1060 1061
    if (virLXCProcessEnsureRootFS(vm) < 0)
        goto cleanup;

1062 1063 1064 1065 1066
    /* Must be run before security labelling */
    VIR_DEBUG("Preparing host devices");
    if (virLXCPrepareHostDevices(driver, vm->def) < 0)
        goto cleanup;

1067 1068 1069 1070 1071
    /* Here we open all the PTYs we need on the host OS side.
     * The LXC controller will open the guest OS side PTYs
     * and forward I/O between them.
     */
    nttyFDs = vm->def->nconsoles;
1072
    if (VIR_ALLOC_N(ttyFDs, nttyFDs) < 0)
1073
        goto cleanup;
1074
    for (i = 0; i < vm->def->nconsoles; i++)
1075
        ttyFDs[i] = -1;
1076 1077 1078 1079

    /* If you are using a SecurityDriver with dynamic labelling,
       then generate a security label for isolation */
    VIR_DEBUG("Generating domain security label (if required)");
1080 1081 1082
    if (vm->def->nseclabels &&
        vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DEFAULT)
        vm->def->seclabels[0]->type = VIR_DOMAIN_SECLABEL_NONE;
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094

    if (virSecurityManagerGenLabel(driver->securityManager, vm->def) < 0) {
        virDomainAuditSecurityLabel(vm, false);
        goto cleanup;
    }
    virDomainAuditSecurityLabel(vm, true);

    VIR_DEBUG("Setting domain security labels");
    if (virSecurityManagerSetAllLabel(driver->securityManager,
                                      vm->def, NULL) < 0)
        goto cleanup;

1095
    for (i = 0; i < vm->def->nconsoles; i++) {
1096 1097
        char *ttyPath;
        if (vm->def->consoles[i]->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
1098 1099
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Only PTY console types are supported"));
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
            goto cleanup;
        }

        if (virFileOpenTty(&ttyFDs[i], &ttyPath, 1) < 0) {
            virReportSystemError(errno, "%s",
                                 _("Failed to allocate tty"));
            goto cleanup;
        }

        VIR_FREE(vm->def->consoles[i]->source.data.file.path);
        vm->def->consoles[i]->source.data.file.path = ttyPath;

        VIR_FREE(vm->def->consoles[i]->info.alias);
1113
        if (virAsprintf(&vm->def->consoles[i]->info.alias, "console%zu", i) < 0)
1114 1115 1116
            goto cleanup;
    }

1117
    if (virLXCProcessSetupInterfaces(conn, vm->def, &nveths, &veths) < 0)
1118 1119 1120
        goto cleanup;

    /* Save the configuration for the controller */
1121
    if (virDomainSaveConfig(cfg->stateDir, vm->def) < 0)
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
        goto cleanup;

    if ((logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT,
             S_IRUSR|S_IWUSR)) < 0) {
        virReportSystemError(errno,
                             _("Failed to open '%s'"),
                             logfile);
        goto cleanup;
    }

    if (pipe(handshakefds) < 0) {
        virReportSystemError(errno, "%s",
                             _("Unable to create pipe"));
        goto cleanup;
    }

1138 1139 1140 1141
    if (!(cmd = virLXCProcessBuildControllerCmd(driver,
                                                vm,
                                                nveths, veths,
                                                ttyFDs, nttyFDs,
1142
                                                files, nfiles,
1143
                                                handshakefds[1])))
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
        goto cleanup;
    virCommandSetOutputFD(cmd, &logfd);
    virCommandSetErrorFD(cmd, &logfd);

    /* now that we know it is about to start call the hook if present */
    if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
        char *xml = virDomainDefFormat(vm->def, 0);
        int hookret;

        hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
                              VIR_HOOK_LXC_OP_START, VIR_HOOK_SUBOP_BEGIN,
                              NULL, xml, NULL);
        VIR_FREE(xml);

        /*
         * If the script raised an error abort the launch
         */
        if (hookret < 0)
            goto cleanup;
    }

    /* Log timestamp */
1166
    if ((timestamp = virTimeStringNow()) == NULL)
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
        goto cleanup;
    if (safewrite(logfd, timestamp, strlen(timestamp)) < 0 ||
        safewrite(logfd, START_POSTFIX, strlen(START_POSTFIX)) < 0) {
        VIR_WARN("Unable to write timestamp to logfile: %s",
                 virStrerror(errno, ebuf, sizeof(ebuf)));
    }
    VIR_FREE(timestamp);

    /* Log generated command line */
    virCommandWriteArgLog(cmd, logfd);
    if ((pos = lseek(logfd, 0, SEEK_END)) < 0)
        VIR_WARN("Unable to seek to end of logfile: %s",
                 virStrerror(errno, ebuf, sizeof(ebuf)));

    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    if (VIR_CLOSE(handshakefds[1]) < 0) {
        virReportSystemError(errno, "%s", _("could not close handshake fd"));
        goto cleanup;
    }

    /* Connect to the controller as a client *first* because
     * this will block until the child has written their
     * pid file out to disk */
1192
    if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm)))
1193 1194 1195
        goto cleanup;

    /* And get its pid */
1196
    if ((r = virPidFileRead(cfg->stateDir, vm->def->name, &vm->pid)) < 0) {
1197 1198 1199 1200 1201 1202 1203 1204
        char out[1024];

        if (virLXCProcessReadLogOutput(vm, logfile, pos, out, 1024) > 0)
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("guest failed to start: %s"), out);
        else
            virReportSystemError(-r,
                                 _("Failed to read pid file %s/%s.pid"),
1205
                                 cfg->stateDir, vm->def->name);
1206 1207 1208
        goto cleanup;
    }

1209
    priv->stopReason = VIR_DOMAIN_EVENT_STOPPED_FAILED;
1210
    priv->wantReboot = false;
1211 1212
    vm->def->id = vm->pid;
    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
1213
    priv->doneStopEvent = false;
1214

1215
    if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
1216 1217
        driver->inhibitCallback(true, driver->inhibitOpaque);

1218 1219 1220
    if (lxcContainerWaitForContinue(handshakefds[0]) < 0) {
        char out[1024];

1221
        if (!(virLXCProcessReadLogOutput(vm, logfile, pos, out, 1024) < 0)) {
1222 1223
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("guest failed to start: %s"), out);
1224 1225 1226 1227 1228 1229
        }

        goto error;
    }

    if (autoDestroy &&
1230 1231
        virCloseCallbacksSet(driver->closeCallbacks, vm,
                             conn, lxcProcessAutoDestroy) < 0)
1232 1233
        goto error;

1234
    if (virDomainObjSetDefTransient(caps, driver->xmlopt,
1235
                                    vm, false) < 0)
1236 1237 1238 1239 1240 1241 1242 1243
        goto error;

    /* Write domain status to disk.
     *
     * XXX: Earlier we wrote the plain "live" domain XML to this
     * location for the benefit of libvirt_lxc. We're now overwriting
     * it with the live status XML instead. This is a (currently
     * harmless) inconsistency we should fix one day */
1244
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
        goto error;

    /* finally we can call the 'started' hook script if any */
    if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
        char *xml = virDomainDefFormat(vm->def, 0);
        int hookret;

        hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
                              VIR_HOOK_LXC_OP_STARTED, VIR_HOOK_SUBOP_BEGIN,
                              NULL, xml, NULL);
        VIR_FREE(xml);

        /*
         * If the script raised an error abort the launch
         */
        if (hookret < 0)
            goto error;
    }

    rc = 0;

cleanup:
    if (rc != 0 && !err)
        err = virSaveLastError();
    virCommandFree(cmd);
    if (VIR_CLOSE(logfd) < 0) {
        virReportSystemError(errno, "%s", _("could not close logfile"));
        rc = -1;
    }
1274
    for (i = 0; i < nveths; i++) {
1275 1276 1277 1278 1279
        if (rc != 0)
            ignore_value(virNetDevVethDelete(veths[i]));
        VIR_FREE(veths[i]);
    }
    if (rc != 0) {
1280 1281 1282 1283
        if (vm->newDef) {
            virDomainDefFree(vm->newDef);
            vm->newDef = NULL;
        }
1284
        if (priv->monitor) {
1285
            virObjectUnref(priv->monitor);
1286 1287
            priv->monitor = NULL;
        }
1288 1289 1290 1291 1292 1293
        virDomainConfVMNWFilterTeardown(vm);

        virSecurityManagerRestoreAllLabel(driver->securityManager,
                                          vm->def, false);
        virSecurityManagerReleaseLabel(driver->securityManager, vm->def);
        /* Clear out dynamically assigned labels */
1294 1295 1296 1297 1298
        if (vm->def->nseclabels &&
            vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
            VIR_FREE(vm->def->seclabels[0]->model);
            VIR_FREE(vm->def->seclabels[0]->label);
            VIR_FREE(vm->def->seclabels[0]->imagelabel);
1299 1300
        }
    }
1301
    for (i = 0; i < nttyFDs; i++)
1302 1303 1304 1305 1306
        VIR_FORCE_CLOSE(ttyFDs[i]);
    VIR_FREE(ttyFDs);
    VIR_FORCE_CLOSE(handshakefds[0]);
    VIR_FORCE_CLOSE(handshakefds[1]);
    VIR_FREE(logfile);
1307
    virObjectUnref(cfg);
1308
    virObjectUnref(caps);
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318

    if (err) {
        virSetError(err);
        virFreeError(err);
    }

    return rc;

error:
    err = virSaveLastError();
1319
    virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED);
1320 1321 1322
    goto cleanup;
}

1323
struct virLXCProcessAutostartData {
1324
    virLXCDriverPtr driver;
1325 1326 1327
    virConnectPtr conn;
};

1328 1329 1330
static int
virLXCProcessAutostartDomain(virDomainObjPtr vm,
                             void *opaque)
1331
{
1332
    const struct virLXCProcessAutostartData *data = opaque;
1333
    int ret = 0;
1334

1335
    virObjectLock(vm);
1336 1337
    if (vm->autostart &&
        !virDomainObjIsActive(vm)) {
1338 1339
        ret = virLXCProcessStart(data->conn, data->driver, vm,
                                 0, NULL, false,
1340
                                 VIR_DOMAIN_RUNNING_BOOTED);
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355
        virDomainAuditStart(vm, "booted", ret >= 0);
        if (ret < 0) {
            virErrorPtr err = virGetLastError();
            VIR_ERROR(_("Failed to autostart VM '%s': %s"),
                      vm->def->name,
                      err ? err->message : "");
        } else {
            virDomainEventPtr event =
                virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STARTED,
                                         VIR_DOMAIN_EVENT_STARTED_BOOTED);
            if (event)
                virDomainEventStateQueue(data->driver->domainEventState, event);
        }
    }
1356
    virObjectUnlock(vm);
1357
    return ret;
1358 1359 1360 1361
}


void
1362 1363
virLXCProcessAutostartAll(virLXCDriverPtr driver)
{
1364 1365 1366 1367 1368 1369 1370 1371
    /* XXX: Figure out a better way todo this. The domain
     * startup code needs a connection handle in order
     * to lookup the bridge associated with a virtual
     * network
     */
    virConnectPtr conn = virConnectOpen("lxc:///");
    /* Ignoring NULL conn which is mostly harmless here */

1372
    struct virLXCProcessAutostartData data = { driver, conn };
1373 1374

    lxcDriverLock(driver);
1375 1376 1377
    virDomainObjListForEach(driver->domains,
                            virLXCProcessAutostartDomain,
                            &data);
1378 1379 1380 1381 1382 1383
    lxcDriverUnlock(driver);

    if (conn)
        virConnectClose(conn);
}

1384 1385 1386
static int
virLXCProcessReconnectDomain(virDomainObjPtr vm,
                             void *opaque)
1387
{
1388
    virLXCDriverPtr driver = opaque;
1389
    virLXCDomainObjPrivatePtr priv;
1390
    int ret = -1;
1391

1392
    virObjectLock(vm);
1393
    VIR_DEBUG("Reconnect id=%d pid=%d state=%d", vm->def->id, vm->pid, vm->state.state);
1394 1395 1396 1397 1398 1399 1400 1401

    priv = vm->privateData;

    if (vm->pid != 0) {
        vm->def->id = vm->pid;
        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_UNKNOWN);

1402
        if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
1403 1404
            driver->inhibitCallback(true, driver->inhibitOpaque);

1405
        if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm)))
1406 1407
            goto error;

1408
        if (!(priv->cgroup = virLXCCgroupCreate(vm->def, false)))
1409 1410
            goto error;

1411 1412 1413
        if (virLXCUpdateActiveUsbHostdevs(driver, vm->def) < 0)
            goto error;

1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435
        if (virSecurityManagerReserveLabel(driver->securityManager,
                                           vm->def, vm->pid) < 0)
            goto error;

        /* now that we know it's reconnected call the hook if present */
        if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
            char *xml = virDomainDefFormat(vm->def, 0);
            int hookret;

            /* we can't stop the operation even if the script raised an error */
            hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
                                  VIR_HOOK_LXC_OP_RECONNECT, VIR_HOOK_SUBOP_BEGIN,
                                  NULL, xml, NULL);
            VIR_FREE(xml);
            if (hookret < 0)
                goto error;
        }

    } else {
        vm->def->id = -1;
    }

1436
    ret = 0;
1437
cleanup:
1438
    virObjectUnlock(vm);
1439
    return ret;
1440 1441

error:
1442
    virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED);
1443 1444 1445 1446 1447
    virDomainAuditStop(vm, "failed");
    goto cleanup;
}


1448
int virLXCProcessReconnectAll(virLXCDriverPtr driver,
1449
                              virDomainObjListPtr doms)
1450
{
1451
    virDomainObjListForEach(doms, virLXCProcessReconnectDomain, driver);
1452 1453
    return 0;
}