コード例 #1
0
ファイル: libxl_bootloader.c プロジェクト: nypdmax/RT-Xen
static void bootloader_disk_attached_cb(libxl__egc *egc,
                                        libxl__disk_local_state *dls,
                                        int rc)
{
    STATE_AO_GC(dls->ao);
    libxl__bootloader_state *bl = CONTAINER_OF(dls, *bl, dls);
    const libxl_domain_build_info *info = bl->info;
    const char *bootloader;

    if (rc) {
        LOG(ERROR, "failed to attach local disk for bootloader execution");
        goto out;
    }

    LOG(DEBUG, "Config bootloader value: %s", info->u.pv.bootloader);

    if ( !strcmp(info->u.pv.bootloader, "/usr/bin/pygrub") )
        LOG(WARN, "bootloader='/usr/bin/pygrub' is deprecated; use " \
            "bootloader='pygrub' instead");

    bootloader = info->u.pv.bootloader;

    /* If the full path is not specified, check in the libexec path */
    if ( bootloader[0] != '/' ) {
        const char *bltmp;
        struct stat st;

        bltmp = libxl__abs_path(gc, bootloader, libxl__private_bindir_path());
        /* Check to see if the file exists in this location; if not,
         * fall back to checking the path */
        LOG(DEBUG, "Checking for bootloader in libexec path: %s", bltmp);

        if ( lstat(bltmp, &st) )
            LOG(DEBUG, "%s doesn't exist, falling back to config path",
                bltmp);
        else
            bootloader = bltmp;
    }

    make_bootloader_args(gc, bl, bootloader);

    bl->openpty.ao = ao;
    bl->openpty.callback = bootloader_gotptys;
    bl->openpty.count = 2;
    bl->openpty.results = bl->ptys;
    rc = libxl__openptys(&bl->openpty, 0,0);
    if (rc) goto out;

    return;

out:
    assert(rc);
    bootloader_callback(egc, bl, rc);
}
コード例 #2
0
int libxl_run_bootloader(libxl_ctx *ctx,
                         libxl_domain_build_info *info,
                         libxl_device_disk *disk,
                         uint32_t domid)
{
    libxl__gc gc = LIBXL_INIT_GC(ctx);
    int ret, rc = 0;
    char *fifo = NULL;
    char *diskpath = NULL;
    char **args = NULL;

    char tempdir_template[] = "/var/run/libxl/bl.XXXXXX";
    char *tempdir;

    char *dom_console_xs_path;
    char dom_console_slave_tty_path[PATH_MAX];

    int xenconsoled_fd = -1, xenconsoled_slave = -1;
    int bootloader_fd = -1, fifo_fd = -1;

    int blrc;
    pid_t pid;
    char *blout;

    struct stat st_buf;

    if (info->hvm || !info->u.pv.bootloader)
        goto out;

    rc = ERROR_INVAL;
    if (!disk)
        goto out;

    rc = ERROR_FAIL;
    ret = mkdir("/var/run/libxl/", S_IRWXU);
    if (ret < 0 && errno != EEXIST)
        goto out;

    ret = stat("/var/run/libxl/", &st_buf);
    if (ret < 0)
        goto out;

    if (!S_ISDIR(st_buf.st_mode))
        goto out;

    tempdir = mkdtemp(tempdir_template);
    if (tempdir == NULL)
        goto out;

    ret = asprintf(&fifo, "%s/fifo", tempdir);
    if (ret < 0) {
        fifo = NULL;
        goto out_close;
    }

    ret = mkfifo(fifo, 0600);
    if (ret < 0) {
        goto out_close;
    }

    diskpath = libxl_device_disk_local_attach(ctx, disk);
    if (!diskpath) {
        goto out_close;
    }

    args = make_bootloader_args(&gc, info, domid, fifo, diskpath);
    if (args == NULL) {
        rc = ERROR_NOMEM;
        goto out_close;
    }

    /*
     * We need to present the bootloader's tty as a pty slave that xenconsole
     * can access.  Since the bootloader itself needs a pty slave,
     * we end up with a connection like this:
     *
     * xenconsole -- (slave pty1 master) <-> (master pty2 slave) -- bootloader
     *
     * where we copy characters between the two master fds, as well as
     * listening on the bootloader's fifo for the results.
     */
    ret = open_xenconsoled_pty(&xenconsoled_fd, &xenconsoled_slave,
                               &dom_console_slave_tty_path[0],
                               sizeof(dom_console_slave_tty_path));
    if (ret < 0) {
        goto out_close;
    }

    dom_console_xs_path = libxl__sprintf(&gc, "%s/console/tty", libxl__xs_get_dompath(&gc, domid));
    libxl__xs_write(&gc, XBT_NULL, dom_console_xs_path, "%s", dom_console_slave_tty_path);

    pid = fork_exec_bootloader(&bootloader_fd, info->u.pv.bootloader, args);
    if (pid < 0) {
        goto out_close;
    }

    while (1) {
        fifo_fd = open(fifo, O_RDONLY);
        if (fifo_fd > -1)
            break;

        if (errno == EINTR)
            continue;

        goto out_close;
    }

    fcntl(fifo_fd, F_SETFL, O_NDELAY);

    blout = bootloader_interact(&gc, xenconsoled_fd, bootloader_fd, fifo_fd);
    if (blout == NULL) {
        goto out_close;
    }

    pid = waitpid(pid, &blrc, 0);
    if (pid == -1 || (pid > 0 && WIFEXITED(blrc) && WEXITSTATUS(blrc) != 0)) {
        goto out_close;
    }

    parse_bootloader_result(ctx, info, blout);

    rc = 0;
out_close:
    if (diskpath) {
        libxl_device_disk_local_detach(ctx, disk);
        free(diskpath);
    }
    if (fifo_fd > -1)
        close(fifo_fd);
    if (bootloader_fd > -1)
        close(bootloader_fd);
    if (xenconsoled_fd > -1)
        close(xenconsoled_fd);
    if (xenconsoled_slave > -1)
        close(xenconsoled_slave);

    if (fifo) {
        unlink(fifo);
        free(fifo);
    }

    rmdir(tempdir);

    free(args);

out:
    libxl__free_all(&gc);
    return rc;
}