static int
mymain(void)
{
    int ret = 0;
    virCapsPtr caps;

    if (virThreadInitialize() < 0)
        exit(EXIT_FAILURE);

    if (!(caps = testQemuCapsInit()))
        exit(EXIT_FAILURE);

    virEventRegisterDefaultImpl();

#define DO_TEST(name) \
    if (virtTestRun(# name, 1, testQemuMonitorJSON ## name, caps) < 0) \
        ret = -1

    DO_TEST(GetStatus);
    DO_TEST(GetVersion);
    DO_TEST(GetMachines);
    DO_TEST(GetCPUDefinitions);
    DO_TEST(GetCommands);

    virObjectUnref(caps);

    return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
Beispiel #2
0
static int
mymain(void)
{
    int ret = 0;
    virDomainXMLOptionPtr xmlopt;
    testQemuData data;

#if !WITH_YAJL
    fputs("libvirt not compiled with yajl, skipping this test\n", stderr);
    return EXIT_AM_SKIP;
#endif

    if (virThreadInitialize() < 0 ||
        !(xmlopt = virQEMUDriverCreateXMLConf(NULL)))
        return EXIT_FAILURE;

    virEventRegisterDefaultImpl();

    data.xmlopt = xmlopt;

#define DO_TEST(name) \
    data.base = name; \
    if (virtTestRun(name, testQemuCaps, &data) < 0) \
        ret = -1

    DO_TEST("caps_1.2.2-1");
    DO_TEST("caps_1.3.1-1");
    DO_TEST("caps_1.4.2-1");
    DO_TEST("caps_1.5.3-1");
    DO_TEST("caps_1.6.0-1");
    DO_TEST("caps_1.6.50-1");

    virObjectUnref(xmlopt);
    return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
Beispiel #3
0
virNetDaemonPtr
virNetDaemonNew(void)
{
    virNetDaemonPtr dmn;
    struct sigaction sig_action;

    if (virNetDaemonInitialize() < 0)
        return NULL;

    if (!(dmn = virObjectLockableNew(virNetDaemonClass)))
        return NULL;

    dmn->sigwrite = dmn->sigread = -1;
    dmn->privileged = geteuid() == 0;
    dmn->autoShutdownInhibitFd = -1;

    if (virEventRegisterDefaultImpl() < 0)
        goto error;

    memset(&sig_action, 0, sizeof(sig_action));
    sig_action.sa_handler = SIG_IGN;
    sigaction(SIGPIPE, &sig_action, NULL);

    return dmn;

 error:
    virObjectUnref(dmn);
    return NULL;
}
Beispiel #4
0
static int
mymain(void)
{
    int ret = 0;
    virDomainXMLOptionPtr xmlopt;

#if !WITH_YAJL
    fputs("libvirt not compiled with yajl, skipping this test\n", stderr);
    return EXIT_AM_SKIP;
#endif

    if (virThreadInitialize() < 0 ||
        !(xmlopt = virQEMUDriverCreateXMLConf(NULL)))
        return EXIT_FAILURE;

    virEventRegisterDefaultImpl();

#define DO_TEST(name) \
    if (virtTestRun(# name, 1, testQemuMonitorJSON ## name, xmlopt) < 0) \
        ret = -1

    DO_TEST(GetStatus);
    DO_TEST(GetVersion);
    DO_TEST(GetMachines);
    DO_TEST(GetCPUDefinitions);
    DO_TEST(GetCommands);
    DO_TEST(GetTPMModels);
    DO_TEST(GetCommandLineOptionParameters);

    virObjectUnref(xmlopt);

    return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
Beispiel #5
0
static int
mymain(void)
{
    int ret = 0;

    testQemuData data;

#if !WITH_YAJL
    fputs("libvirt not compiled with yajl, skipping this test\n", stderr);
    return EXIT_AM_SKIP;
#endif

    if (virThreadInitialize() < 0)
        return EXIT_FAILURE;

    virEventRegisterDefaultImpl();

#define DO_TEST_FULL(name, guest)                       \
    data.base = name;                                   \
    data.guestarch = guest;                             \
    if (virtTestRun(name, testQemuCapsXML, &data) < 0)  \
        ret = -1

#define DO_TEST(name) DO_TEST_FULL(name, VIR_ARCH_I686)

    DO_TEST("all_1.6.0-1");
    DO_TEST("nodisksnapshot_1.6.0-1");

    return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
Beispiel #6
0
static int
mymain(void)
{
    int ret = 0;
    virQEMUDriver driver;
    testQemuData data;

#if !WITH_YAJL
    fputs("libvirt not compiled with yajl, skipping this test\n", stderr);
    return EXIT_AM_SKIP;
#endif

    if (virThreadInitialize() < 0 ||
        qemuTestDriverInit(&driver) < 0)
        return EXIT_FAILURE;

    virEventRegisterDefaultImpl();

    data.xmlopt = driver.xmlopt;

#define DO_TEST(arch, name)                                             \
    do {                                                                \
        data.archName = arch;                                           \
        data.base = name;                                               \
        if (virTestRun(name "(" arch ")", testQemuCaps, &data) < 0)     \
            ret = -1;                                                   \
    } while (0)

    DO_TEST("x86_64", "caps_1.2.2");
    DO_TEST("x86_64", "caps_1.3.1");
    DO_TEST("x86_64", "caps_1.4.2");
    DO_TEST("x86_64", "caps_1.5.3");
    DO_TEST("x86_64", "caps_1.6.0");
    DO_TEST("x86_64", "caps_1.7.0");
    DO_TEST("x86_64", "caps_2.1.1");
    DO_TEST("x86_64", "caps_2.4.0");
    DO_TEST("x86_64", "caps_2.5.0");
    DO_TEST("x86_64", "caps_2.6.0");
    DO_TEST("aarch64", "caps_2.6.0-gicv2");
    DO_TEST("aarch64", "caps_2.6.0-gicv3");
    DO_TEST("ppc64le", "caps_2.6.0");

    /*
     * Run "tests/qemucapsprobe /path/to/qemu/binary >foo.replies"
     * to generate updated or new *.replies data files.
     */

    qemuTestDriverFree(&driver);

    return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
Beispiel #7
0
/*
 * Initialize connection.
 */
static bool
virshInit(vshControl *ctl)
{
    virshControlPtr priv = ctl->privData;

    /* Since we have the commandline arguments parsed, we need to
     * reload our initial settings to make debugging and readline
     * work properly */
    vshInitReload(ctl);

    if (priv->conn)
        return false;

    /* set up the library error handler */
    virSetErrorFunc(NULL, vshErrorHandler);

    if (virEventRegisterDefaultImpl() < 0) {
        vshReportError(ctl);
        return false;
    }

    if (virThreadCreate(&ctl->eventLoop, true, vshEventLoop, ctl) < 0) {
        vshReportError(ctl);
        return false;
    }
    ctl->eventLoopStarted = true;

    if ((ctl->eventTimerId = virEventAddTimeout(-1, vshEventTimeout, ctl,
                                                NULL)) < 0) {
        vshReportError(ctl);
        return false;
    }

    if (ctl->connname) {
        /* Connecting to a named connection must succeed, but we delay
         * connecting to the default connection until we need it
         * (since the first command might be 'connect' which allows a
         * non-default connection, or might be 'help' which needs no
         * connection).
         */
        if (virshReconnect(ctl, NULL, false, false) < 0) {
            vshReportError(ctl);
            return false;
        }
    }

    return true;
}
static int
mymain(void)
{
    int ret = 0;
    virQEMUDriver driver;
    testQemuData data;

#if !WITH_YAJL
    fputs("libvirt not compiled with yajl, skipping this test\n", stderr);
    return EXIT_AM_SKIP;
#endif

    if (virThreadInitialize() < 0 ||
        qemuTestDriverInit(&driver) < 0)
        return EXIT_FAILURE;

    virEventRegisterDefaultImpl();

    data.xmlopt = driver.xmlopt;

#define DO_TEST(name)                                   \
    do {                                                \
        data.base = name;                               \
        if (virtTestRun(name, testQemuCaps, &data) < 0) \
            ret = -1;                                   \
    } while (0)

    DO_TEST("caps_1.2.2-1");
    DO_TEST("caps_1.3.1-1");
    DO_TEST("caps_1.4.2-1");
    DO_TEST("caps_1.5.3-1");
    DO_TEST("caps_1.6.0-1");
    DO_TEST("caps_1.6.50-1");
    DO_TEST("caps_2.1.1-1");
    DO_TEST("caps_2.4.0-1");
    DO_TEST("caps_2.5.0-1");

    qemuTestDriverFree(&driver);

    return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
Beispiel #9
0
static int
mymain(void)
{
    int ret = 0;
    struct qemuHotplugTestData data = {0};
    virSecurityManagerPtr mgr;

#if !WITH_YAJL
    fputs("libvirt not compiled with yajl, skipping this test\n", stderr);
    return EXIT_AM_SKIP;
#endif

    if (virThreadInitialize() < 0 ||
        qemuTestDriverInit(&driver) < 0)
        return EXIT_FAILURE;

    virEventRegisterDefaultImpl();

    VIR_FREE(driver.config->spiceListen);
    VIR_FREE(driver.config->vncListen);
    /* some dummy values from 'config file' */
    if (VIR_STRDUP_QUIET(driver.config->spicePassword, "123456") < 0)
        return EXIT_FAILURE;

    if (!(driver.domainEventState = virObjectEventStateNew()))
        return EXIT_FAILURE;

    driver.lockManager = virLockManagerPluginNew("nop", "qemu",
                                                 driver.config->configBaseDir,
                                                 0);
    if (!driver.lockManager)
        return EXIT_FAILURE;

    if (!(mgr = virSecurityManagerNew("none", "qemu",
                                      VIR_SECURITY_MANAGER_PRIVILEGED)))
        return EXIT_FAILURE;
    if (!(driver.securityManager = virSecurityManagerNewStack(mgr)))
        return EXIT_FAILURE;

    /* wait only 100ms for DEVICE_DELETED event */
    qemuDomainRemoveDeviceWaitTime = 100;

#define DO_TEST(file, ACTION, dev, event, fial, kep, ...)                   \
    do {                                                                    \
        const char *my_mon[] = { __VA_ARGS__, NULL};                        \
        const char *name = file " " #ACTION " " dev;                        \
        data.action = ACTION;                                               \
        data.domain_filename = file;                                        \
        data.device_filename = dev;                                         \
        data.fail = fial;                                                   \
        data.mon = my_mon;                                                  \
        data.keep = kep;                                                    \
        data.deviceDeletedEvent = event;                                    \
        if (virtTestRun(name, testQemuHotplug, &data) < 0)                  \
            ret = -1;                                                       \
    } while (0)

#define DO_TEST_ATTACH(file, dev, fial, kep, ...)                           \
    DO_TEST(file, ATTACH, dev, false, fial, kep, __VA_ARGS__)

#define DO_TEST_DETACH(file, dev, fial, kep, ...)                           \
    DO_TEST(file, DETACH, dev, false, fial, kep, __VA_ARGS__)

#define DO_TEST_ATTACH_EVENT(file, dev, fial, kep, ...)                     \
    DO_TEST(file, ATTACH, dev, true, fial, kep, __VA_ARGS__)

#define DO_TEST_DETACH_EVENT(file, dev, fial, kep, ...)                     \
    DO_TEST(file, DETACH, dev, true, fial, kep, __VA_ARGS__)

#define DO_TEST_UPDATE(file, dev, fial, kep, ...)                           \
    DO_TEST(file, UPDATE, dev, false, fial, kep, __VA_ARGS__)


#define QMP_OK      "{\"return\": {}}"
#define HMP(msg)    "{\"return\": \"" msg "\"}"

#define QMP_DEVICE_DELETED(dev) \
    "{"                                                     \
    "    \"timestamp\": {"                                  \
    "        \"seconds\": 1374137171,"                      \
    "        \"microseconds\": 2659"                        \
    "    },"                                                \
    "    \"event\": \"DEVICE_DELETED\","                    \
    "    \"data\": {"                                       \
    "        \"device\": \"" dev "\","                      \
    "        \"path\": \"/machine/peripheral/" dev "\""     \
    "    }"                                                 \
    "}\r\n"

    DO_TEST_UPDATE("graphics-spice", "graphics-spice-nochange", false, false, NULL);
    DO_TEST_UPDATE("graphics-spice-timeout", "graphics-spice-timeout-nochange", false, false,
                   "set_password", QMP_OK, "expire_password", QMP_OK);
    DO_TEST_UPDATE("graphics-spice-timeout", "graphics-spice-timeout-password", false, false,
                   "set_password", QMP_OK, "expire_password", QMP_OK);
    DO_TEST_UPDATE("graphics-spice", "graphics-spice-listen", true, false, NULL);
    DO_TEST_UPDATE("graphics-spice-listen-network", "graphics-spice-listen-network", false, false,
                   "set_password", QMP_OK, "expire_password", QMP_OK);
    /* Strange huh? Currently, only graphics can be updated :-P */
    DO_TEST_UPDATE("disk-cdrom", "disk-cdrom-nochange", true, false, NULL);

    DO_TEST_ATTACH("console-compat-2", "console-virtio", false, true,
                   "chardev-add", "{\"return\": {\"pty\": \"/dev/pts/26\"}}",
                   "device_add", QMP_OK);

    DO_TEST_DETACH("console-compat-2", "console-virtio", false, false,
                   "device_del", QMP_OK,
                   "chardev-remove", QMP_OK);

    DO_TEST_ATTACH("hotplug-base", "disk-virtio", false, true,
                   "human-monitor-command", HMP("OK\\r\\n"),
                   "device_add", QMP_OK);
    DO_TEST_DETACH("hotplug-base", "disk-virtio", false, false,
                   "device_del", QMP_OK,
                   "human-monitor-command", HMP(""));

    DO_TEST_ATTACH_EVENT("hotplug-base", "disk-virtio", false, true,
                         "human-monitor-command", HMP("OK\\r\\n"),
                         "device_add", QMP_OK);
    DO_TEST_DETACH("hotplug-base", "disk-virtio", true, true,
                   "device_del", QMP_OK,
                   "human-monitor-command", HMP(""));
    DO_TEST_DETACH("hotplug-base", "disk-virtio", false, false,
                   "device_del", QMP_DEVICE_DELETED("virtio-disk4") QMP_OK,
                   "human-monitor-command", HMP(""));

    DO_TEST_ATTACH("hotplug-base", "disk-usb", false, true,
                   "human-monitor-command", HMP("OK\\r\\n"),
                   "device_add", QMP_OK);
    DO_TEST_DETACH("hotplug-base", "disk-usb", false, false,
                   "device_del", QMP_OK,
                   "human-monitor-command", HMP(""));

    DO_TEST_ATTACH_EVENT("hotplug-base", "disk-usb", false, true,
                         "human-monitor-command", HMP("OK\\r\\n"),
                         "device_add", QMP_OK);
    DO_TEST_DETACH("hotplug-base", "disk-usb", true, true,
                   "device_del", QMP_OK,
                   "human-monitor-command", HMP(""));
    DO_TEST_DETACH("hotplug-base", "disk-usb", false, false,
                   "device_del", QMP_DEVICE_DELETED("usb-disk16") QMP_OK,
                   "human-monitor-command", HMP(""));

    DO_TEST_ATTACH("hotplug-base", "disk-scsi", false, true,
                   "human-monitor-command", HMP("OK\\r\\n"),
                   "device_add", QMP_OK);
    DO_TEST_DETACH("hotplug-base", "disk-scsi", false, false,
                   "device_del", QMP_OK,
                   "human-monitor-command", HMP(""));

    DO_TEST_ATTACH_EVENT("hotplug-base", "disk-scsi", false, true,
                         "human-monitor-command", HMP("OK\\r\\n"),
                         "device_add", QMP_OK);
    DO_TEST_DETACH("hotplug-base", "disk-scsi", true, true,
                   "device_del", QMP_OK,
                   "human-monitor-command", HMP(""));
    DO_TEST_DETACH("hotplug-base", "disk-scsi", false, false,
                   "device_del", QMP_DEVICE_DELETED("scsi0-0-0-5") QMP_OK,
                   "human-monitor-command", HMP(""));

    qemuTestDriverFree(&driver);
    return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
Beispiel #10
0
virNetServerPtr virNetServerNew(size_t min_workers,
                                size_t max_workers,
                                size_t priority_workers,
                                size_t max_clients,
                                size_t max_anonymous_clients,
                                int keepaliveInterval,
                                unsigned int keepaliveCount,
                                bool keepaliveRequired,
                                const char *mdnsGroupName,
                                virNetServerClientPrivNew clientPrivNew,
                                virNetServerClientPrivPreExecRestart clientPrivPreExecRestart,
                                virFreeCallback clientPrivFree,
                                void *clientPrivOpaque)
{
    virNetServerPtr srv;
    struct sigaction sig_action;

    if (virNetServerInitialize() < 0)
        return NULL;

    if (!(srv = virObjectLockableNew(virNetServerClass)))
        return NULL;

    if (max_workers &&
        !(srv->workers = virThreadPoolNew(min_workers, max_workers,
                                          priority_workers,
                                          virNetServerHandleJob,
                                          srv)))
        goto error;

    srv->nclients_max = max_clients;
    srv->nclients_unauth_max = max_anonymous_clients;
    srv->keepaliveInterval = keepaliveInterval;
    srv->keepaliveCount = keepaliveCount;
    srv->keepaliveRequired = keepaliveRequired;
    srv->sigwrite = srv->sigread = -1;
    srv->clientPrivNew = clientPrivNew;
    srv->clientPrivPreExecRestart = clientPrivPreExecRestart;
    srv->clientPrivFree = clientPrivFree;
    srv->clientPrivOpaque = clientPrivOpaque;
    srv->privileged = geteuid() == 0;
    srv->autoShutdownInhibitFd = -1;

    if (VIR_STRDUP(srv->mdnsGroupName, mdnsGroupName) < 0)
        goto error;
    if (srv->mdnsGroupName) {
        if (!(srv->mdns = virNetServerMDNSNew()))
            goto error;
        if (!(srv->mdnsGroup = virNetServerMDNSAddGroup(srv->mdns,
                                                        srv->mdnsGroupName)))
            goto error;
    }

    if (virEventRegisterDefaultImpl() < 0)
        goto error;

    memset(&sig_action, 0, sizeof(sig_action));
    sig_action.sa_handler = SIG_IGN;
    sigaction(SIGPIPE, &sig_action, NULL);

    return srv;

error:
    virObjectUnref(srv);
    return NULL;
}
Beispiel #11
0
static int
mymain(void)
{
    int ret = 0;
    struct qemuHotplugTestData data = {0};

#if !WITH_YAJL
    fputs("libvirt not compiled with yajl, skipping this test\n", stderr);
    return EXIT_AM_SKIP;
#endif

    if (virThreadInitialize() < 0 ||
        !(driver.caps = testQemuCapsInit()) ||
        !(driver.xmlopt = virQEMUDriverCreateXMLConf(&driver)))
        return EXIT_FAILURE;

    virEventRegisterDefaultImpl();

    driver.config = virQEMUDriverConfigNew(false);
    VIR_FREE(driver.config->spiceListen);
    VIR_FREE(driver.config->vncListen);

    if (!(driver.domainEventState = virDomainEventStateNew()))
        return EXIT_FAILURE;

    /* some dummy values from 'config file' */
    if (VIR_STRDUP_QUIET(driver.config->spicePassword, "123456") < 0)
        return EXIT_FAILURE;

#define DO_TEST(file, dev, fial, kep, ...)                                  \
        const char *my_mon[] = { __VA_ARGS__, NULL};                        \
        data.domain_filename = file;                                        \
        data.device_filename = dev;                                         \
        data.fail = fial;                                                   \
        data.mon = my_mon;                                                  \
        data.keep = kep;                                                    \
        if (virtTestRun(#file, 1, testQemuHotplug, &data) < 0)              \
            ret = -1;                                                       \

#define DO_TEST_ATTACH(file, dev, fial, kep, ...)                           \
    do {                                                                    \
        data.action = ATTACH;                                               \
        DO_TEST(file, dev, fial, kep, __VA_ARGS__)                          \
    } while (0)

#define DO_TEST_DETACH(file, dev, fial, kep, ...)                           \
    do {                                                                    \
        data.action = DETACH;                                               \
        DO_TEST(file, dev, fial, kep, __VA_ARGS__)                          \
    } while (0)

#define DO_TEST_UPDATE(file, dev, fial, kep, ...)                           \
    do {                                                                    \
        data.action = UPDATE;                                               \
        DO_TEST(file, dev, fial, kep, __VA_ARGS__)                          \
    } while (0)

    DO_TEST_UPDATE("graphics-spice", "graphics-spice-nochange", false, false, NULL);
    DO_TEST_UPDATE("graphics-spice-timeout", "graphics-spice-timeout-nochange", false, false,
                   "set_password", "{\"return\":{}}", "expire_password", "{\"return\":{}}");
    DO_TEST_UPDATE("graphics-spice-timeout", "graphics-spice-timeout-password", false, false,
                   "set_password", "{\"return\":{}}", "expire_password", "{\"return\":{}}");
    DO_TEST_UPDATE("graphics-spice", "graphics-spice-listen", true, false, NULL);
    DO_TEST_UPDATE("graphics-spice-listen-network", "graphics-spice-listen-network", false, false,
                   "set_password", "{\"return\":{}}", "expire_password", "{\"return\":{}}");
    /* Strange huh? Currently, only graphics can be updated :-P */
    DO_TEST_UPDATE("disk-cdrom", "disk-cdrom-nochange", true, false, NULL);

    DO_TEST_ATTACH("console-compat-2", "console-virtio", false, true,
                   "chardev-add", "{\"return\": {\"pty\": \"/dev/pts/26\"}}",
                   "device_add", "{\"return\": {}}");

    DO_TEST_DETACH("console-compat-2", "console-virtio", false, false,
                   "device_del", "{\"return\": {}}",
                   "chardev-remove", "{\"return\": {}}");

    virObjectUnref(driver.caps);
    virObjectUnref(driver.xmlopt);
    virObjectUnref(driver.config);
    return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
Beispiel #12
0
int main(int argc, char *argv[])
{
    pid_t pid;
    int rc = 1;
    int client;
    char *name = NULL;
    int nveths = 0;
    char **veths = NULL;
    int monitor = -1;
    int handshakefd = -1;
    int bg = 0;
    virCapsPtr caps = NULL;
    virDomainDefPtr def = NULL;
    char *configFile = NULL;
    char *sockpath = NULL;
    const struct option options[] = {
        { "background", 0, NULL, 'b' },
        { "name",   1, NULL, 'n' },
        { "veth",   1, NULL, 'v' },
        { "console", 1, NULL, 'c' },
        { "handshakefd", 1, NULL, 's' },
        { "help", 0, NULL, 'h' },
        { 0, 0, 0, 0 },
    };
    int *ttyFDs = NULL;
    size_t nttyFDs = 0;

    if (setlocale(LC_ALL, "") == NULL ||
        bindtextdomain(PACKAGE, LOCALEDIR) == NULL ||
        textdomain(PACKAGE) == NULL) {
        fprintf(stderr, _("%s: initialization failed\n"), argv[0]);
        exit(EXIT_FAILURE);
    }

    while (1) {
        int c;

        c = getopt_long(argc, argv, "dn:v:m:c:s:h",
                       options, NULL);

        if (c == -1)
            break;

        switch (c) {
        case 'b':
            bg = 1;
            break;

        case 'n':
            if ((name = strdup(optarg)) == NULL) {
                virReportOOMError();
                goto cleanup;
            }
            break;

        case 'v':
            if (VIR_REALLOC_N(veths, nveths+1) < 0) {
                virReportOOMError();
                goto cleanup;
            }
            if ((veths[nveths++] = strdup(optarg)) == NULL) {
                virReportOOMError();
                goto cleanup;
            }
            break;

        case 'c':
            if (VIR_REALLOC_N(ttyFDs, nttyFDs + 1) < 0) {
                virReportOOMError();
                goto cleanup;
            }
            if (virStrToLong_i(optarg, NULL, 10, &ttyFDs[nttyFDs++]) < 0) {
                fprintf(stderr, "malformed --console argument '%s'", optarg);
                goto cleanup;
            }
            break;

        case 's':
            if (virStrToLong_i(optarg, NULL, 10, &handshakefd) < 0) {
                fprintf(stderr, "malformed --handshakefd argument '%s'",
                        optarg);
                goto cleanup;
            }
            break;

        case 'h':
        case '?':
            fprintf(stderr, "\n");
            fprintf(stderr, "syntax: %s [OPTIONS]\n", argv[0]);
            fprintf(stderr, "\n");
            fprintf(stderr, "Options\n");
            fprintf(stderr, "\n");
            fprintf(stderr, "  -b, --background\n");
            fprintf(stderr, "  -n NAME, --name NAME\n");
            fprintf(stderr, "  -c FD, --console FD\n");
            fprintf(stderr, "  -v VETH, --veth VETH\n");
            fprintf(stderr, "  -s FD, --handshakefd FD\n");
            fprintf(stderr, "  -h, --help\n");
            fprintf(stderr, "\n");
            goto cleanup;
        }
    }


    if (name == NULL) {
        fprintf(stderr, "%s: missing --name argument for configuration\n", argv[0]);
        goto cleanup;
    }

    if (handshakefd < 0) {
        fprintf(stderr, "%s: missing --handshake argument for container PTY\n",
                argv[0]);
        goto cleanup;
    }

    if (getuid() != 0) {
        fprintf(stderr, "%s: must be run as the 'root' user\n", argv[0]);
        goto cleanup;
    }

    virEventRegisterDefaultImpl();

    if ((caps = lxcCapsInit()) == NULL)
        goto cleanup;

    if ((configFile = virDomainConfigFile(LXC_STATE_DIR,
                                          name)) == NULL)
        goto cleanup;

    if ((def = virDomainDefParseFile(caps, configFile,
                                     1 << VIR_DOMAIN_VIRT_LXC,
                                     VIR_DOMAIN_XML_INACTIVE)) == NULL)
        goto cleanup;

    if (def->nnets != nveths) {
        fprintf(stderr, "%s: expecting %d veths, but got %d\n",
                argv[0], def->nnets, nveths);
        goto cleanup;
    }

    if ((sockpath = lxcMonitorPath(def)) == NULL)
        goto cleanup;

    if ((monitor = lxcMonitorServer(sockpath)) < 0)
        goto cleanup;

    if (bg) {
        if ((pid = fork()) < 0)
            goto cleanup;

        if (pid > 0) {
            if ((rc = virPidFileWrite(LXC_STATE_DIR, name, pid)) < 0) {
                virReportSystemError(-rc,
                                     _("Unable to write pid file '%s/%s.pid'"),
                                     LXC_STATE_DIR, name);
                _exit(1);
            }

            /* First child now exits, allowing original caller
             * (ie libvirtd's LXC driver to complete their
             * waitpid & continue */
            _exit(0);
        }

        /* Don't hold onto any cwd we inherit from libvirtd either */
        if (chdir("/") < 0) {
            virReportSystemError(errno, "%s",
                                 _("Unable to change to root dir"));
            goto cleanup;
        }

        if (setsid() < 0) {
            virReportSystemError(errno, "%s",
                                 _("Unable to become session leader"));
            goto cleanup;
        }
    }

    /* Initialize logging */
    virLogSetFromEnv();

    /* Accept initial client which is the libvirtd daemon */
    if ((client = accept(monitor, NULL, 0)) < 0) {
        virReportSystemError(errno, "%s",
                             _("Failed to accept a connection from driver"));
        goto cleanup;
    }

    rc = lxcControllerRun(def, nveths, veths, monitor, client,
                          ttyFDs, nttyFDs, handshakefd);


cleanup:
    if (def)
        virPidFileDelete(LXC_STATE_DIR, def->name);
    lxcControllerCleanupInterfaces(nveths, veths);
    if (sockpath)
        unlink(sockpath);
    VIR_FREE(sockpath);

    return rc ? EXIT_FAILURE : EXIT_SUCCESS;
}