static int lxcContainerMountBasicFS(virDomainFSDefPtr root) { const struct { const char *src; const char *dst; const char *type; } mnts[] = { { "/dev", "/dev", "tmpfs" }, { "/proc", "/proc", "proc" }, { "/sys", "/sys", "sysfs" }, #if WITH_SELINUX { "none", "/selinux", "selinuxfs" }, #endif }; int i, rc = -1; char *devpts; if (virAsprintf(&devpts, "/.oldroot%s/dev/pts", root->src) < 0) { virReportOOMError(); return rc; } for (i = 0 ; i < ARRAY_CARDINALITY(mnts) ; i++) { if (virFileMakePath(mnts[i].dst) != 0) { virReportSystemError(errno, _("Failed to mkdir %s"), mnts[i].src); goto cleanup; } if (mount(mnts[i].src, mnts[i].dst, mnts[i].type, 0, NULL) < 0) { virReportSystemError(errno, _("Failed to mount %s on %s"), mnts[i].type, mnts[i].type); goto cleanup; } } if ((rc = virFileMakePath("/dev/pts") != 0)) { virReportSystemError(rc, "%s", _("Cannot create /dev/pts")); goto cleanup; } VIR_DEBUG("Trying to move %s to %s", devpts, "/dev/pts"); if ((rc = mount(devpts, "/dev/pts", NULL, MS_MOVE, NULL)) < 0) { virReportSystemError(errno, "%s", _("Failed to mount /dev/pts in container")); goto cleanup; } rc = 0; cleanup: VIR_FREE(devpts); return rc; }
static int lxcContainerMountFSDevPTS(virDomainFSDefPtr root) { char *devpts = NULL; int rc = -1; if (virAsprintf(&devpts, "/.oldroot%s/dev/pts", root->src) < 0) { virReportOOMError(); goto cleanup; } if (virFileMakePath("/dev/pts") < 0) { virReportSystemError(errno, "%s", _("Cannot create /dev/pts")); goto cleanup; } VIR_DEBUG("Trying to move %s to %s", devpts, "/dev/pts"); if ((rc = mount(devpts, "/dev/pts", NULL, MS_MOVE, NULL)) < 0) { virReportSystemError(errno, "%s", _("Failed to mount /dev/pts in container")); goto cleanup; } rc = 0; cleanup: VIR_FREE(devpts); return rc; }
static int virLogDaemonUnixSocketPaths(bool privileged, char **sockfile) { if (privileged) { if (VIR_STRDUP(*sockfile, LOCALSTATEDIR "/run/libvirt/virtlogd-sock") < 0) goto error; } else { char *rundir = NULL; mode_t old_umask; if (!(rundir = virGetUserRuntimeDirectory())) goto error; old_umask = umask(077); if (virFileMakePath(rundir) < 0) { umask(old_umask); VIR_FREE(rundir); goto error; } umask(old_umask); if (virAsprintf(sockfile, "%s/virtlogd-sock", rundir) < 0) { VIR_FREE(rundir); goto error; } VIR_FREE(rundir); } return 0; error: return -1; }
static int daemonPidFilePath(bool privileged, char **pidfile) { if (privileged) { if (VIR_STRDUP(*pidfile, LOCALSTATEDIR "/run/libvirtd.pid") < 0) goto error; } else { char *rundir = NULL; mode_t old_umask; if (!(rundir = virGetUserRuntimeDirectory())) goto error; old_umask = umask(077); if (virFileMakePath(rundir) < 0) { umask(old_umask); goto error; } umask(old_umask); if (virAsprintf(pidfile, "%s/libvirtd.pid", rundir) < 0) { VIR_FREE(rundir); goto error; } VIR_FREE(rundir); } return 0; error: return -1; }
static int testUserXattrEnabled(void) { int ret = -1; ssize_t len; const char *con_value = "system_u:object_r:svirt_image_t:s0:c41,c264"; char *path = NULL; if (virAsprintf(&path, "%s/securityselinuxlabeldata/testxattr", abs_builddir) < 0) goto cleanup; if (virFileMakePath(abs_builddir "/securityselinuxlabeldata") < 0 || virFileTouch(path, 0600) < 0) goto cleanup; len = setxattr(path, "user.libvirt.selinux", con_value, strlen(con_value), 0); if (len < 0) { if (errno == EOPNOTSUPP) ret = 0; goto cleanup; } ret = 1; cleanup: unlink(path); rmdir(abs_builddir "/securityselinuxlabeldata"); VIR_FREE(path); return ret; }
int virPidFileWrite(const char *dir, const char *name, pid_t pid) { int rc; char *pidfile = NULL; if (name == NULL || dir == NULL) { rc = -EINVAL; goto cleanup; } if (virFileMakePath(dir) < 0) { rc = -errno; goto cleanup; } if (!(pidfile = virPidFileBuildPath(dir, name))) { rc = -ENOMEM; goto cleanup; } rc = virPidFileWritePath(pidfile, pid); cleanup: VIR_FREE(pidfile); return rc; }
static dnsmasqHostsfile * hostsfileNew(const char *name, const char *config_dir) { int err; dnsmasqHostsfile *hostsfile; if (VIR_ALLOC(hostsfile) < 0) { virReportOOMError(); return NULL; } hostsfile->hosts = NULL; hostsfile->nhosts = 0; if (virAsprintf(&hostsfile->path, "%s/%s.%s", config_dir, name, DNSMASQ_HOSTSFILE_SUFFIX) < 0) { virReportOOMError(); goto error; } if ((err = virFileMakePath(config_dir))) { virReportSystemError(err, _("cannot create config directory '%s'"), config_dir); goto error; } return hostsfile; error: hostsfileFree(hostsfile); return NULL; }
static int daemonUnixSocketPaths(struct daemonConfig *config, bool privileged, char **sockfile, char **rosockfile, char **admsockfile) { if (config->unix_sock_dir) { if (virAsprintf(sockfile, "%s/libvirt-sock", config->unix_sock_dir) < 0) goto error; if (privileged) { if (virAsprintf(rosockfile, "%s/libvirt-sock-ro", config->unix_sock_dir) < 0) goto error; if (virAsprintf(admsockfile, "%s/libvirt-admin-sock", config->unix_sock_dir) < 0) goto error; } } else { if (privileged) { if (VIR_STRDUP(*sockfile, LOCALSTATEDIR "/run/libvirt/libvirt-sock") < 0 || VIR_STRDUP(*rosockfile, LOCALSTATEDIR "/run/libvirt/libvirt-sock-ro") < 0 || VIR_STRDUP(*admsockfile, LOCALSTATEDIR "/run/libvirt/libvirt-admin-sock") < 0) goto error; } else { char *rundir = NULL; mode_t old_umask; if (!(rundir = virGetUserRuntimeDirectory())) goto error; old_umask = umask(077); if (virFileMakePath(rundir) < 0) { umask(old_umask); goto error; } umask(old_umask); if (virAsprintf(sockfile, "%s/libvirt-sock", rundir) < 0 || virAsprintf(admsockfile, "%s/libvirt-admin-sock", rundir) < 0) { VIR_FREE(rundir); goto error; } VIR_FREE(rundir); } } return 0; error: return -1; }
static int testSELinuxCreateDisks(testSELinuxFile *files, size_t nfiles) { size_t i; if (virFileMakePath(abs_builddir "/securityselinuxlabeldata/nfs") < 0) return -1; for (i = 0; i < nfiles; i++) { if (virFileTouch(files[i].file, 0600) < 0) return -1; } return 0; }
static int testCompareXMLtoXMLFiles(const char *xml) { char *xmlData = NULL; char *actual = NULL; char *pathResult = NULL; int ret = -1; virVBoxSnapshotConfMachinePtr machine = NULL; if (VIR_STRDUP(pathResult, abs_builddir "/vboxsnapshotxmldata/testResult.vbox") < 0) return -1; if (virFileMakePath(abs_builddir "/vboxsnapshotxmldata") < 0) goto cleanup; if (virTestLoadFile(xml, &xmlData) < 0) goto cleanup; if (!(machine = virVBoxSnapshotConfLoadVboxFile(xml, (char*)""))) goto cleanup; if (virVBoxSnapshotConfSaveVboxFile(machine, pathResult) < 0) goto cleanup; if (virTestLoadFile(pathResult, &actual) < 0) goto cleanup; if (!(actual = testFilterXML(actual))) goto cleanup; if (!(xmlData = testFilterXML(xmlData))) goto cleanup; if (STRNEQ(actual, xmlData)) { virTestDifference(stderr, xmlData, actual); goto cleanup; } ret = 0; cleanup: unlink(pathResult); rmdir(abs_builddir "/vboxsnapshotxmldata"); VIR_FREE(xmlData); VIR_FREE(actual); virVBoxSnapshotConfMachineFree(machine); VIR_FREE(pathResult); return ret; }
static int myInit(void) { size_t i; for (i = 0; i < nhostdevs; i++) { virDomainHostdevSubsys subsys; hostdevs[i] = virDomainHostdevDefAlloc(); if (!hostdevs[i]) goto cleanup; hostdevs[i]->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI; subsys.u.pci.addr.domain = 0; subsys.u.pci.addr.bus = 0; subsys.u.pci.addr.slot = i + 1; subsys.u.pci.addr.function = 0; subsys.u.pci.backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM; hostdevs[i]->source.subsys = subsys; } for (i = 0; i < nhostdevs; i++) { if (!(dev[i] = virPCIDeviceNew(0, 0, i + 1, 0))) goto cleanup; virPCIDeviceSetStubDriver(dev[i], VIR_PCI_STUB_DRIVER_KVM); } if (VIR_ALLOC(mgr) < 0) goto cleanup; if ((mgr->activePCIHostdevs = virPCIDeviceListNew()) == NULL) goto cleanup; if ((mgr->activeUSBHostdevs = virUSBDeviceListNew()) == NULL) goto cleanup; if ((mgr->inactivePCIHostdevs = virPCIDeviceListNew()) == NULL) goto cleanup; if ((mgr->activeSCSIHostdevs = virSCSIDeviceListNew()) == NULL) goto cleanup; if (VIR_STRDUP(mgr->stateDir, TEST_STATE_DIR) < 0) goto cleanup; if (virFileMakePath(mgr->stateDir) < 0) goto cleanup; return 0; cleanup: myCleanup(); return -1; }
static int daemonUnixSocketPaths(struct daemonConfig *config, bool privileged, char **sockfile, char **rosockfile) { if (config->unix_sock_dir) { if (virAsprintf(sockfile, "%s/libvirt-sock", config->unix_sock_dir) < 0) goto no_memory; if (privileged && virAsprintf(rosockfile, "%s/libvirt-sock-ro", config->unix_sock_dir) < 0) goto no_memory; } else { if (privileged) { if (!(*sockfile = strdup(LOCALSTATEDIR "/run/libvirt/libvirt-sock"))) goto no_memory; if (!(*rosockfile = strdup(LOCALSTATEDIR "/run/libvirt/libvirt-sock-ro"))) goto no_memory; } else { char *rundir = NULL; mode_t old_umask; if (!(rundir = virGetUserRuntimeDirectory())) goto error; old_umask = umask(077); if (virFileMakePath(rundir) < 0) { umask(old_umask); goto error; } umask(old_umask); if (virAsprintf(sockfile, "%s/libvirt-sock", rundir) < 0) { VIR_FREE(rundir); goto no_memory; } VIR_FREE(rundir); } } return 0; no_memory: virReportOOMError(); error: return -1; }
static void init_sysfs(void) { if (fakerootdir && fakesysfscgroupdir) return; if (!(fakerootdir = getenv("LIBVIRT_FAKE_ROOT_DIR"))) { fprintf(stderr, "Missing LIBVIRT_FAKE_ROOT_DIR env variable\n"); abort(); } if (virAsprintfQuiet(&fakesysfscgroupdir, "%s%s", fakerootdir, SYSFS_CGROUP_PREFIX) < 0) abort(); if (virFileMakePath(fakesysfscgroupdir) < 0) { fprintf(stderr, "Cannot create %s\n", fakesysfscgroupdir); abort(); } # define MAKE_CONTROLLER(subpath) \ do { \ char *path; \ if (asprintf(&path, "%s/%s", fakesysfscgroupdir, subpath) < 0) \ abort(); \ if (make_controller(path, 0755) < 0) { \ fprintf(stderr, "Cannot initialize %s\n", path); \ free(path); \ abort(); \ } \ free(path); \ } while (0) MAKE_CONTROLLER("cpu"); MAKE_CONTROLLER("cpuacct"); MAKE_CONTROLLER("cpu,cpuacct"); MAKE_CONTROLLER("cpu,cpuacct/system"); MAKE_CONTROLLER("cpuset"); MAKE_CONTROLLER("blkio"); MAKE_CONTROLLER("memory"); MAKE_CONTROLLER("freezer"); if (make_file(fakesysfscgroupdir, SYSFS_CPU_PRESENT_MOCKED, "8-23,48-159\n") < 0) abort(); }
/** * dnsmasqSave: * @ctx: pointer to the dnsmasq context for each network * * Saves all the configurations associated with a context to disk. */ int dnsmasqSave(const dnsmasqContext *ctx) { int ret = 0; if (virFileMakePath(ctx->config_dir) < 0) { virReportSystemError(errno, _("cannot create config directory '%s'"), ctx->config_dir); return -1; } if (ctx->hostsfile) ret = hostsfileSave(ctx->hostsfile); if (ret == 0) { if (ctx->addnhostsfile) ret = addnhostsSave(ctx->addnhostsfile); } return ret; }
static int lxcContainerMountFSBind(virDomainFSDefPtr fs, const char *srcprefix) { char *src = NULL; int ret = -1; if (virAsprintf(&src, "%s%s", srcprefix, fs->src) < 0) { virReportOOMError(); goto cleanup; } if (virFileMakePath(fs->dst) < 0) { virReportSystemError(errno, _("Failed to create %s"), fs->dst); goto cleanup; } if (mount(src, fs->dst, NULL, MS_BIND, NULL) < 0) { virReportSystemError(errno, _("Failed to bind mount directory %s to %s"), src, fs->dst); goto cleanup; } if (fs->readonly) { VIR_DEBUG("Binding %s readonly", fs->dst); if (mount(fs->dst, fs->dst, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) { virReportSystemError(errno, _("Failed to make directory %s readonly"), fs->dst); } } ret = 0; cleanup: VIR_FREE(src); return ret; }
static int lxcContainerMountNewFS(virDomainDefPtr vmDef) { int i; /* Pull in rest of container's mounts */ for (i = 0 ; i < vmDef->nfss ; i++) { char *src; if (STREQ(vmDef->fss[i]->dst, "/")) continue; // XXX fix if (vmDef->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT) continue; if (virAsprintf(&src, "/.oldroot/%s", vmDef->fss[i]->src) < 0) { virReportOOMError(); return -1; } if (virFileMakePath(vmDef->fss[i]->dst) != 0) { virReportSystemError(errno, _("Failed to create %s"), vmDef->fss[i]->dst); VIR_FREE(src); return -1; } if (mount(src, vmDef->fss[i]->dst, NULL, MS_BIND, NULL) < 0) { virReportSystemError(errno, _("Failed to mount %s at %s"), src, vmDef->fss[i]->dst); VIR_FREE(src); return -1; } VIR_FREE(src); } return 0; }
/** * @conn connection to report errors against * @pool storage pool to build * * Build a directory or FS based storage pool. * * - If it is a FS based pool, mounts the unlying source device on the pool * * Returns 0 on success, -1 on error */ static int virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, unsigned int flags ATTRIBUTE_UNUSED) { int err, ret = -1; char *parent; char *p; if ((parent = strdup(pool->def->target.path)) == NULL) { virReportOOMError(); goto error; } if (!(p = strrchr(parent, '/'))) { virStorageReportError(VIR_ERR_INVALID_ARG, _("path '%s' is not absolute"), pool->def->target.path); goto error; } if (p != parent) { /* assure all directories in the path prior to the final dir * exist, with default uid/gid/mode. */ *p = '\0'; if ((err = virFileMakePath(parent)) != 0) { virReportSystemError(err, _("cannot create path '%s'"), parent); goto error; } } /* Now create the final dir in the path with the uid/gid/mode * requested in the config. If the dir already exists, just set * the perms. */ struct stat st; if ((stat(pool->def->target.path, &st) < 0) || (pool->def->target.perms.uid != -1)) { uid_t uid = (pool->def->target.perms.uid == -1) ? getuid() : pool->def->target.perms.uid; gid_t gid = (pool->def->target.perms.gid == -1) ? getgid() : pool->def->target.perms.gid; if ((err = virDirCreate(pool->def->target.path, pool->def->target.perms.mode, uid, gid, VIR_DIR_CREATE_FORCE_PERMS | VIR_DIR_CREATE_ALLOW_EXIST | (pool->def->type == VIR_STORAGE_POOL_NETFS ? VIR_DIR_CREATE_AS_UID : 0)) != 0)) { virReportSystemError(err, _("cannot create path '%s'"), pool->def->target.path); goto error; } } ret = 0; error: VIR_FREE(parent); return ret; }
static int lxcContainerMountBasicFS(const char *srcprefix, bool pivotRoot) { const struct { bool needPrefix; const char *src; const char *dst; const char *type; const char *opts; int mflags; } mnts[] = { /* When we want to make a bind mount readonly, for unknown reasons, * it is currently necessary to bind it once, and then remount the * bind with the readonly flag. If this is not done, then the original * mount point in the main OS becomes readonly too which is not what * we want. Hence some things have two entries here. */ { false, "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV }, { false, "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND }, { false, "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY }, { true, "/sys", "/sys", NULL, NULL, MS_BIND }, { true, "/sys", "/sys", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY }, { true, "/selinux", "/selinux", NULL, NULL, MS_BIND }, { true, "/selinux", "/selinux", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY }, }; int i, rc = -1; char *opts = NULL; #if HAVE_SELINUX security_context_t con; #else bool con = false; #endif VIR_DEBUG("Mounting basic filesystems %s pivotRoot=%d", NULLSTR(srcprefix), pivotRoot); for (i = 0 ; i < ARRAY_CARDINALITY(mnts) ; i++) { char *src = NULL; const char *srcpath = NULL; VIR_DEBUG("Processing %s -> %s", mnts[i].src, mnts[i].dst); if (virFileMakePath(mnts[i].dst) < 0) { virReportSystemError(errno, _("Failed to mkdir %s"), mnts[i].src); goto cleanup; } if (mnts[i].needPrefix && srcprefix) { if (virAsprintf(&src, "%s%s", srcprefix, mnts[i].src) < 0) { virReportOOMError(); goto cleanup; } srcpath = src; } else { srcpath = mnts[i].src; } /* Skip if mount doesn't exist in source */ if ((srcpath[0] == '/') && (access(srcpath, R_OK) < 0)) { VIR_FREE(src); continue; } VIR_DEBUG("Mount %s on %s type=%s flags=%x, opts=%s", srcpath, mnts[i].dst, mnts[i].type, mnts[i].mflags, mnts[i].opts); if (mount(srcpath, mnts[i].dst, mnts[i].type, mnts[i].mflags, mnts[i].opts) < 0) { VIR_FREE(src); virReportSystemError(errno, _("Failed to mount %s on %s type %s"), mnts[i].src, mnts[i].dst, NULLSTR(mnts[i].type)); goto cleanup; } VIR_FREE(src); } if (pivotRoot) { #if HAVE_SELINUX if (getfilecon("/", &con) < 0 && errno != ENOTSUP) { virReportSystemError(errno, "%s", _("Failed to query file context on /")); goto cleanup; } #endif /* * tmpfs is limited to 64kb, since we only have device nodes in there * and don't want to DOS the entire OS RAM usage */ if (virAsprintf(&opts, "mode=755,size=65536%s%s%s", con ? ",context=\"" : "", con ? (const char *)con : "", con ? "\"" : "") < 0) { virReportOOMError(); goto cleanup; } VIR_DEBUG("Mount devfs on /dev type=tmpfs flags=%x, opts=%s", MS_NOSUID, opts); if (mount("devfs", "/dev", "tmpfs", MS_NOSUID, opts) < 0) { virReportSystemError(errno, _("Failed to mount %s on %s type %s"), "devfs", "/dev", "tmpfs"); goto cleanup; } } rc = 0; cleanup: VIR_DEBUG("rc=%d", rc); VIR_FREE(opts); return rc; }
static int testPrepImages(void) { int ret = EXIT_FAILURE; virCommandPtr cmd = NULL; char *buf = NULL; bool compat = false; qemuimg = virFindFileInPath("kvm-img"); if (!qemuimg) qemuimg = virFindFileInPath("qemu-img"); if (!qemuimg) goto skip; /* Clean up from any earlier failed tests */ virFileDeleteTree(datadir); /* See if qemu-img supports '-o compat=xxx'. If so, we force the * use of both v2 and v3 files; if not, it is v2 only but the test * still works. */ cmd = virCommandNewArgList(qemuimg, "create", "-f", "qcow2", "-o?", "/dev/null", NULL); virCommandSetOutputBuffer(cmd, &buf); if (virCommandRun(cmd, NULL) < 0) goto skip; if (strstr(buf, "compat ")) compat = true; VIR_FREE(buf); if (virAsprintf(&absraw, "%s/raw", datadir) < 0 || virAsprintf(&absqcow2, "%s/qcow2", datadir) < 0 || virAsprintf(&abswrap, "%s/wrap", datadir) < 0 || virAsprintf(&absqed, "%s/qed", datadir) < 0 || virAsprintf(&absdir, "%s/dir", datadir) < 0 || virAsprintf(&abslink2, "%s/sub/link2", datadir) < 0) goto cleanup; if (virFileMakePath(datadir "/sub") < 0) { fprintf(stderr, "unable to create directory %s\n", datadir "/sub"); goto cleanup; } if (virFileMakePath(datadir "/dir") < 0) { fprintf(stderr, "unable to create directory %s\n", datadir "/dir"); goto cleanup; } if (!(canondir = canonicalize_file_name(absdir))) { virReportOOMError(); goto cleanup; } if (chdir(datadir) < 0) { fprintf(stderr, "unable to test relative backing chains\n"); goto cleanup; } if (virAsprintf(&buf, "%1024d", 0) < 0 || virFileWriteStr("raw", buf, 0600) < 0) { fprintf(stderr, "unable to create raw file\n"); goto cleanup; } if (!(canonraw = canonicalize_file_name(absraw))) { virReportOOMError(); goto cleanup; } /* Create a qcow2 wrapping relative raw; later on, we modify its * metadata to test other configurations */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "create", "-f", "qcow2", NULL); virCommandAddArgFormat(cmd, "-obacking_file=raw,backing_fmt=raw%s", compat ? ",compat=0.10" : ""); virCommandAddArg(cmd, "qcow2"); if (virCommandRun(cmd, NULL) < 0) goto skip; /* Make sure our later uses of 'qemu-img rebase' will work */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2", "-F", "raw", "-b", "raw", "qcow2", NULL); if (virCommandRun(cmd, NULL) < 0) goto skip; if (!(canonqcow2 = canonicalize_file_name(absqcow2))) { virReportOOMError(); goto cleanup; } /* Create a second qcow2 wrapping the first, to be sure that we * can correctly avoid insecure probing. */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "create", "-f", "qcow2", NULL); virCommandAddArgFormat(cmd, "-obacking_file=%s,backing_fmt=qcow2%s", absqcow2, compat ? ",compat=1.1" : ""); virCommandAddArg(cmd, "wrap"); if (virCommandRun(cmd, NULL) < 0) goto skip; if (!(canonwrap = canonicalize_file_name(abswrap))) { virReportOOMError(); goto cleanup; } /* Create a qed file. */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "create", "-f", "qed", NULL); virCommandAddArgFormat(cmd, "-obacking_file=%s,backing_fmt=raw", absraw); virCommandAddArg(cmd, "qed"); if (virCommandRun(cmd, NULL) < 0) goto skip; if (!(canonqed = canonicalize_file_name(absqed))) { virReportOOMError(); goto cleanup; } #ifdef HAVE_SYMLINK /* Create some symlinks in a sub-directory. */ if (symlink("../qcow2", datadir "/sub/link1") < 0 || symlink("../wrap", datadir "/sub/link2") < 0) { fprintf(stderr, "unable to create symlink"); goto cleanup; } #endif ret = 0; cleanup: VIR_FREE(buf); virCommandFree(cmd); if (ret) testCleanupImages(); return ret; skip: fputs("qemu-img is too old; skipping this test\n", stderr); ret = EXIT_AM_SKIP; goto cleanup; }
static int lxcControllerRun(virDomainDefPtr def, unsigned int nveths, char **veths, int monitor, int client, int appPty) { int rc = -1; int control[2] = { -1, -1}; int containerPty = -1; char *containerPtyPath = NULL; pid_t container = -1; virDomainFSDefPtr root; char *devpts = NULL; char *devptmx = NULL; if (socketpair(PF_UNIX, SOCK_STREAM, 0, control) < 0) { virReportSystemError(errno, "%s", _("sockpair failed")); goto cleanup; } root = virDomainGetRootFilesystem(def); if (lxcSetContainerResources(def) < 0) goto cleanup; /* * If doing a chroot style setup, we need to prepare * a private /dev/pts for the child now, which they * will later move into position. * * This is complex because 'virsh console' needs to * use /dev/pts from the host OS, and the guest OS * needs to use /dev/pts from the guest. * * This means that we (libvirt_lxc) need to see and * use both /dev/pts instances. We're running in the * host OS context though and don't want to expose * the guest OS /dev/pts there. * * Thus we call unshare(CLONE_NS) so that we can see * the guest's new /dev/pts, without it becoming * visible to the host OS. We also put the root FS * into slave mode, just in case it was currently * marked as shared */ if (root) { VIR_DEBUG0("Setting up private /dev/pts"); if (unshare(CLONE_NEWNS) < 0) { virReportSystemError(errno, "%s", _("Cannot unshare mount namespace")); goto cleanup; } if (mount("", "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) { virReportSystemError(errno, "%s", _("Failed to switch root mount into slave mode")); goto cleanup; } if (virAsprintf(&devpts, "%s/dev/pts", root->src) < 0 || virAsprintf(&devptmx, "%s/dev/pts/ptmx", root->src) < 0) { virReportOOMError(); goto cleanup; } if (virFileMakePath(devpts) != 0) { virReportSystemError(errno, _("Failed to make path %s"), devpts); goto cleanup; } VIR_DEBUG("Mouting 'devpts' on %s", devpts); if (mount("devpts", devpts, "devpts", 0, "newinstance,ptmxmode=0666,mode=0620,gid=5") < 0) { virReportSystemError(errno, _("Failed to mount devpts on %s"), devpts); goto cleanup; } if (access(devptmx, R_OK) < 0) { VIR_WARN0("Kernel does not support private devpts, using shared devpts"); VIR_FREE(devptmx); } } if (devptmx) { VIR_DEBUG("Opening tty on private %s", devptmx); if (virFileOpenTtyAt(devptmx, &containerPty, &containerPtyPath, 0) < 0) { virReportSystemError(errno, "%s", _("Failed to allocate tty")); goto cleanup; } } else { VIR_DEBUG0("Opening tty on shared /dev/ptmx"); if (virFileOpenTty(&containerPty, &containerPtyPath, 0) < 0) { virReportSystemError(errno, "%s", _("Failed to allocate tty")); goto cleanup; } } if (lxcSetPersonality(def) < 0) goto cleanup; if ((container = lxcContainerStart(def, nveths, veths, control[1], containerPtyPath)) < 0) goto cleanup; VIR_FORCE_CLOSE(control[1]); if (lxcControllerMoveInterfaces(nveths, veths, container) < 0) goto cleanup; if (lxcContainerSendContinue(control[0]) < 0) goto cleanup; /* Now the container is running, there's no need for us to keep any elevated capabilities */ if (lxcControllerClearCapabilities() < 0) goto cleanup; rc = lxcControllerMain(monitor, client, appPty, containerPty, container); cleanup: VIR_FREE(devptmx); VIR_FREE(devpts); VIR_FORCE_CLOSE(control[0]); VIR_FORCE_CLOSE(control[1]); VIR_FREE(containerPtyPath); VIR_FORCE_CLOSE(containerPty); if (container > 1) { int status; kill(container, SIGTERM); if (!(waitpid(container, &status, WNOHANG) == 0 && WIFEXITED(status))) kill(container, SIGKILL); waitpid(container, NULL, 0); } return rc; }
libxlDriverConfigPtr libxlDriverConfigNew(void) { libxlDriverConfigPtr cfg; char *log_file = NULL; char ebuf[1024]; unsigned int free_mem; if (libxlConfigInitialize() < 0) return NULL; if (!(cfg = virObjectNew(libxlDriverConfigClass))) return NULL; if (VIR_STRDUP(cfg->configDir, LIBXL_CONFIG_DIR) < 0) goto error; if (VIR_STRDUP(cfg->autostartDir, LIBXL_AUTOSTART_DIR) < 0) goto error; if (VIR_STRDUP(cfg->logDir, LIBXL_LOG_DIR) < 0) goto error; if (VIR_STRDUP(cfg->stateDir, LIBXL_STATE_DIR) < 0) goto error; if (VIR_STRDUP(cfg->libDir, LIBXL_LIB_DIR) < 0) goto error; if (VIR_STRDUP(cfg->saveDir, LIBXL_SAVE_DIR) < 0) goto error; if (VIR_STRDUP(cfg->autoDumpDir, LIBXL_DUMP_DIR) < 0) goto error; if (virAsprintf(&log_file, "%s/libxl-driver.log", cfg->logDir) < 0) goto error; if (virFileMakePath(cfg->logDir) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to create log dir '%s': %s"), cfg->logDir, virStrerror(errno, ebuf, sizeof(ebuf))); goto error; } if ((cfg->logger_file = fopen(log_file, "a")) == NULL) { VIR_ERROR(_("Failed to create log file '%s': %s"), log_file, virStrerror(errno, ebuf, sizeof(ebuf))); goto error; } VIR_FREE(log_file); cfg->logger = (xentoollog_logger *)xtl_createlogger_stdiostream(cfg->logger_file, XTL_DEBUG, 0); if (!cfg->logger) { VIR_ERROR(_("cannot create logger for libxenlight, disabling driver")); goto error; } if (libxl_ctx_alloc(&cfg->ctx, LIBXL_VERSION, 0, cfg->logger)) { VIR_ERROR(_("cannot initialize libxenlight context, probably not " "running in a Xen Dom0, disabling driver")); goto error; } if ((cfg->verInfo = libxl_get_version_info(cfg->ctx)) == NULL) { VIR_ERROR(_("cannot version information from libxenlight, " "disabling driver")); goto error; } cfg->version = (cfg->verInfo->xen_version_major * 1000000) + (cfg->verInfo->xen_version_minor * 1000); /* This will fill xenstore info about free and dom0 memory if missing, * should be called before starting first domain */ if (libxl_get_free_memory(cfg->ctx, &free_mem)) { VIR_ERROR(_("Unable to configure libxl's memory management parameters")); goto error; } /* setup autoballoon */ if (libxlGetAutoballoonConf(cfg, &cfg->autoballoon) < 0) goto error; return cfg; error: VIR_FREE(log_file); virObjectUnref(cfg); return NULL; }
/** * virLXCProcessStart: * @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 */ int virLXCProcessStart(virConnectPtr conn, virLXCDriverPtr driver, virDomainObjPtr vm, unsigned int nfiles, int *files, bool autoDestroy, virDomainRunningReason reason) { int rc = -1, r; size_t nttyFDs = 0; int *ttyFDs = NULL; size_t i; char *logfile = NULL; int logfd = -1; size_t nveths = 0; char **veths = NULL; int handshakefds[2] = { -1, -1 }; off_t pos = -1; char ebuf[1024]; char *timestamp; virCommandPtr cmd = NULL; virLXCDomainObjPrivatePtr priv = vm->privateData; virCapsPtr caps = NULL; virErrorPtr err = NULL; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); virCgroupPtr selfcgroup; int status; if (virCgroupNewSelf(&selfcgroup) < 0) return -1; if (!virCgroupHasController(selfcgroup, VIR_CGROUP_CONTROLLER_CPUACCT)) { virCgroupFree(&selfcgroup); virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to find 'cpuacct' cgroups controller mount")); return -1; } if (!virCgroupHasController(selfcgroup, VIR_CGROUP_CONTROLLER_DEVICES)) { virCgroupFree(&selfcgroup); virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to find 'devices' cgroups controller mount")); return -1; } if (!virCgroupHasController(selfcgroup, VIR_CGROUP_CONTROLLER_MEMORY)) { virCgroupFree(&selfcgroup); virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to find 'memory' cgroups controller mount")); return -1; } virCgroupFree(&selfcgroup); if (virFileMakePath(cfg->logDir) < 0) { virReportSystemError(errno, _("Cannot create log directory '%s'"), cfg->logDir); return -1; } if (!vm->def->resource) { virDomainResourceDefPtr res; if (VIR_ALLOC(res) < 0) goto cleanup; if (VIR_STRDUP(res->partition, "/machine") < 0) { VIR_FREE(res); goto cleanup; } vm->def->resource = res; } if (virAsprintf(&logfile, "%s/%s.log", cfg->logDir, vm->def->name) < 0) return -1; if (!(caps = virLXCDriverGetCapabilities(driver, false))) goto cleanup; /* 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"); if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, true) < 0) 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; } if (virLXCProcessEnsureRootFS(vm) < 0) goto cleanup; /* Must be run before security labelling */ VIR_DEBUG("Preparing host devices"); if (virLXCPrepareHostDevices(driver, vm->def) < 0) goto cleanup; /* 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; if (VIR_ALLOC_N(ttyFDs, nttyFDs) < 0) goto cleanup; for (i = 0; i < vm->def->nconsoles; i++) ttyFDs[i] = -1; /* If you are using a SecurityDriver with dynamic labelling, then generate a security label for isolation */ VIR_DEBUG("Generating domain security label (if required)"); if (vm->def->nseclabels && vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DEFAULT) vm->def->seclabels[0]->type = VIR_DOMAIN_SECLABEL_NONE; 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; for (i = 0; i < vm->def->nconsoles; i++) { char *ttyPath; if (vm->def->consoles[i]->source.type != VIR_DOMAIN_CHR_TYPE_PTY) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Only PTY console types are supported")); 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); if (virAsprintf(&vm->def->consoles[i]->info.alias, "console%zu", i) < 0) goto cleanup; } if (virLXCProcessSetupInterfaces(conn, vm->def, &nveths, &veths) < 0) goto cleanup; /* Save the configuration for the controller */ if (virDomainSaveConfig(cfg->stateDir, vm->def) < 0) 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; } if (!(cmd = virLXCProcessBuildControllerCmd(driver, vm, nveths, veths, ttyFDs, nttyFDs, files, nfiles, handshakefds[1]))) 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 */ if ((timestamp = virTimeStringNow()) == NULL) 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))); virCommandRawStatus(cmd); if (virCommandRun(cmd, &status) < 0) goto cleanup; if (status != 0) { if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf, sizeof(ebuf)) <= 0) { if (WIFEXITED(status)) snprintf(ebuf, sizeof(ebuf), _("unexpected exit status %d"), WEXITSTATUS(status)); else snprintf(ebuf, sizeof(ebuf), "%s", _("terminated abnormally")); } virReportError(VIR_ERR_INTERNAL_ERROR, _("guest failed to start: %s"), ebuf); 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 & created their cgroup */ if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm))) { /* Intentionally overwrite the real monitor error message, * since a better one is almost always found in the logs */ if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf, sizeof(ebuf)) > 0) { virResetLastError(); virReportError(VIR_ERR_INTERNAL_ERROR, _("guest failed to start: %s"), ebuf); } goto cleanup; } /* And get its pid */ if ((r = virPidFileRead(cfg->stateDir, vm->def->name, &vm->pid)) < 0) { if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf, sizeof(ebuf)) > 0) virReportError(VIR_ERR_INTERNAL_ERROR, _("guest failed to start: %s"), ebuf); else virReportSystemError(-r, _("Failed to read pid file %s/%s.pid"), cfg->stateDir, vm->def->name); goto cleanup; } if (virCgroupNewDetectMachine(vm->def->name, "lxc", vm->pid, vm->def->resource ? vm->def->resource->partition : NULL, -1, &priv->cgroup) < 0) goto error; if (!priv->cgroup) { virReportError(VIR_ERR_INTERNAL_ERROR, _("No valid cgroup for machine %s"), vm->def->name); goto error; } priv->stopReason = VIR_DOMAIN_EVENT_STOPPED_FAILED; priv->wantReboot = false; vm->def->id = vm->pid; virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason); priv->doneStopEvent = false; if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback) driver->inhibitCallback(true, driver->inhibitOpaque); if (lxcContainerWaitForContinue(handshakefds[0]) < 0) { char out[1024]; if (!(virLXCProcessReadLogOutput(vm, logfile, pos, out, 1024) < 0)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("guest failed to start: %s"), out); } goto error; } if (autoDestroy && virCloseCallbacksSet(driver->closeCallbacks, vm, conn, lxcProcessAutoDestroy) < 0) goto error; if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, false) < 0) 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 */ if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) 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; } for (i = 0; i < nveths; i++) { if (rc != 0 && veths[i]) ignore_value(virNetDevVethDelete(veths[i])); VIR_FREE(veths[i]); } if (rc != 0) { if (vm->newDef) { virDomainDefFree(vm->newDef); vm->newDef = NULL; } if (priv->monitor) { virObjectUnref(priv->monitor); priv->monitor = NULL; } virDomainConfVMNWFilterTeardown(vm); virSecurityManagerRestoreAllLabel(driver->securityManager, vm->def, false); virSecurityManagerReleaseLabel(driver->securityManager, vm->def); /* Clear out dynamically assigned labels */ 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); } } for (i = 0; i < nttyFDs; i++) VIR_FORCE_CLOSE(ttyFDs[i]); VIR_FREE(ttyFDs); VIR_FORCE_CLOSE(handshakefds[0]); VIR_FORCE_CLOSE(handshakefds[1]); VIR_FREE(logfile); virObjectUnref(cfg); virObjectUnref(caps); if (err) { virSetError(err); virFreeError(err); } return rc; error: err = virSaveLastError(); virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED); goto cleanup; }
static int lxcContainerPivotRoot(virDomainFSDefPtr root) { int rc, ret; char *oldroot = NULL, *newroot = NULL; ret = -1; /* root->parent must be private, so make / private. */ if (mount("", "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0) { virReportSystemError(errno, "%s", _("Failed to make root private")); goto err; } if (virAsprintf(&oldroot, "%s/.oldroot", root->src) < 0) { virReportOOMError(); goto err; } if ((rc = virFileMakePath(oldroot)) != 0) { virReportSystemError(rc, _("Failed to create %s"), oldroot); goto err; } /* Create a tmpfs root since old and new roots must be * on separate filesystems */ if (mount("tmprootfs", oldroot, "tmpfs", 0, NULL) < 0) { virReportSystemError(errno, _("Failed to mount empty tmpfs at %s"), oldroot); goto err; } /* Create a directory called 'new' in tmpfs */ if (virAsprintf(&newroot, "%s/new", oldroot) < 0) { virReportOOMError(); goto err; } if ((rc = virFileMakePath(newroot)) != 0) { virReportSystemError(rc, _("Failed to create %s"), newroot); goto err; } /* ... and mount our root onto it */ if (mount(root->src, newroot, NULL, MS_BIND|MS_REC, NULL) < 0) { virReportSystemError(errno, _("Failed to bind new root %s into tmpfs"), root->src); goto err; } /* Now we chroot into the tmpfs, then pivot into the * root->src bind-mounted onto '/new' */ if (chdir(newroot) < 0) { virReportSystemError(errno, _("Failed to chroot into %s"), newroot); goto err; } /* The old root directory will live at /.oldroot after * this and will soon be unmounted completely */ if (pivot_root(".", ".oldroot") < 0) { virReportSystemError(errno, "%s", _("Failed to pivot root")); goto err; } /* CWD is undefined after pivot_root, so go to / */ if (chdir("/") < 0) goto err; ret = 0; err: VIR_FREE(oldroot); VIR_FREE(newroot); return ret; }
static int bhyveDomainSetAutostart(virDomainPtr domain, int autostart) { virDomainObjPtr vm; char *configFile = NULL; char *autostartLink = NULL; int ret = -1; if (!(vm = bhyveDomObjFromDomain(domain))) goto cleanup; if (virDomainSetAutostartEnsureACL(domain->conn, vm->def) < 0) goto cleanup; if (!vm->persistent) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot set autostart for transient domain")); goto cleanup; } autostart = (autostart != 0); if (vm->autostart != autostart) { if ((configFile = virDomainConfigFile(BHYVE_CONFIG_DIR, vm->def->name)) == NULL) goto cleanup; if ((autostartLink = virDomainConfigFile(BHYVE_AUTOSTART_DIR, vm->def->name)) == NULL) goto cleanup; if (autostart) { if (virFileMakePath(BHYVE_AUTOSTART_DIR) < 0) { virReportSystemError(errno, _("cannot create autostart directory %s"), BHYVE_AUTOSTART_DIR); goto cleanup; } if (symlink(configFile, autostartLink) < 0) { virReportSystemError(errno, _("Failed to create symlink '%s' to '%s'"), autostartLink, configFile); goto cleanup; } } else { if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) { virReportSystemError(errno, _("Failed to delete symlink '%s'"), autostartLink); goto cleanup; } } vm->autostart = autostart; } ret = 0; cleanup: VIR_FREE(configFile); VIR_FREE(autostartLink); if (vm) virObjectUnlock(vm); return ret; }
/* * Set up the logging environment * By default if daemonized all errors go to the logfile libvirtd.log, * but if verbose or error debugging is asked for then also output * informational and debug messages. Default size if 64 kB. */ static int daemonSetupLogging(struct daemonConfig *config, bool privileged, bool verbose, bool godaemon) { virLogReset(); /* * Libvirtd's order of precedence is: * cmdline > environment > config * * In order to achieve this, we must process configuration in * different order for the log level versus the filters and * outputs. Because filters and outputs append, we have to look at * the environment first and then only check the config file if * there was no result from the environment. The default output is * then applied only if there was no setting from either of the * first two. Because we don't have a way to determine if the log * level has been set, we must process variables in the opposite * order, each one overriding the previous. */ if (config->log_level != 0) virLogSetDefaultPriority(config->log_level); virLogSetFromEnv(); if (virLogGetNbFilters() == 0) virLogParseFilters(config->log_filters); if (virLogGetNbOutputs() == 0) virLogParseOutputs(config->log_outputs); /* * If no defined outputs, and either running * as daemon or not on a tty, then first try * to direct it to the systemd journal * (if it exists).... */ if (virLogGetNbOutputs() == 0 && (godaemon || !isatty(STDIN_FILENO))) { char *tmp; if (access("/run/systemd/journal/socket", W_OK) >= 0) { if (virAsprintf(&tmp, "%d:journald", virLogGetDefaultPriority()) < 0) goto error; virLogParseOutputs(tmp); VIR_FREE(tmp); } } /* * otherwise direct to libvirtd.log when running * as daemon. Otherwise the default output is stderr. */ if (virLogGetNbOutputs() == 0) { char *tmp = NULL; if (godaemon) { if (privileged) { if (virAsprintf(&tmp, "%d:file:%s/log/libvirt/libvirtd.log", virLogGetDefaultPriority(), LOCALSTATEDIR) == -1) goto error; } else { char *logdir = virGetUserCacheDirectory(); mode_t old_umask; if (!logdir) goto error; old_umask = umask(077); if (virFileMakePath(logdir) < 0) { umask(old_umask); goto error; } umask(old_umask); if (virAsprintf(&tmp, "%d:file:%s/libvirtd.log", virLogGetDefaultPriority(), logdir) == -1) { VIR_FREE(logdir); goto error; } VIR_FREE(logdir); } } else { if (virAsprintf(&tmp, "%d:stderr", virLogGetDefaultPriority()) < 0) goto error; } virLogParseOutputs(tmp); VIR_FREE(tmp); } /* * Command line override for --verbose */ if ((verbose) && (virLogGetDefaultPriority() > VIR_LOG_INFO)) virLogSetDefaultPriority(VIR_LOG_INFO); return 0; error: return -1; }
static int testPrepImages(void) { int ret = EXIT_FAILURE; virCommandPtr cmd = NULL; qemuimg = virFindFileInPath("kvm-img"); if (!qemuimg) qemuimg = virFindFileInPath("qemu-img"); if (!qemuimg) goto skip; if (virAsprintf(&absraw, "%s/raw", datadir) < 0 || virAsprintf(&absqcow2, "%s/qcow2", datadir) < 0 || virAsprintf(&abswrap, "%s/wrap", datadir) < 0 || virAsprintf(&absqed, "%s/qed", datadir) < 0 || virAsprintf(&abslink2, "%s/sub/link2", datadir) < 0) { virReportOOMError(); goto cleanup; } if (virFileMakePath(datadir "/sub") < 0) { fprintf(stderr, "unable to create directory %s\n", datadir "/sub"); goto cleanup; } if (chdir(datadir) < 0) { fprintf(stderr, "unable to test relative backing chains\n"); goto cleanup; } /* I'm lazy enough to use a shell one-liner instead of open/write/close */ virCommandFree(cmd); cmd = virCommandNewArgList("sh", "-c", "printf %1024d 0 > raw", NULL); if (virCommandRun(cmd, NULL) < 0) { fprintf(stderr, "unable to create raw file\n"); goto cleanup; } if (!(canonraw = canonicalize_file_name(absraw))) { virReportOOMError(); goto cleanup; } /* Create a qcow2 wrapping relative raw; later on, we modify its * metadata to test other configurations */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "create", "-f", "qcow2", "-obacking_file=raw,backing_fmt=raw", "qcow2", NULL); if (virCommandRun(cmd, NULL) < 0) goto skip; /* Make sure our later uses of 'qemu-img rebase' will work */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2", "-F", "raw", "-b", "raw", "qcow2", NULL); if (virCommandRun(cmd, NULL) < 0) goto skip; if (!(canonqcow2 = canonicalize_file_name(absqcow2))) { virReportOOMError(); goto cleanup; } /* Create a second qcow2 wrapping the first, to be sure that we * can correctly avoid insecure probing. */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "create", "-f", "qcow2", NULL); virCommandAddArgFormat(cmd, "-obacking_file=%s,backing_fmt=qcow2", absqcow2); virCommandAddArg(cmd, "wrap"); if (virCommandRun(cmd, NULL) < 0) goto skip; /* Create a qed file. */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "create", "-f", "qed", NULL); virCommandAddArgFormat(cmd, "-obacking_file=%s,backing_fmt=raw", absraw); virCommandAddArg(cmd, "qed"); if (virCommandRun(cmd, NULL) < 0) goto skip; /* Create some symlinks in a sub-directory. */ if (symlink("../qcow2", datadir "/sub/link1") < 0 || symlink("../wrap", datadir "/sub/link2") < 0) { fprintf(stderr, "unable to create symlink"); goto cleanup; } ret = 0; cleanup: virCommandFree(cmd); if (ret) testCleanupImages(); return ret; skip: fputs("qemu-img is too old; skipping this test\n", stderr); ret = EXIT_AM_SKIP; goto cleanup; }
static int lxcControllerRun(virDomainDefPtr def, unsigned int nveths, char **veths, int monitor, int client, int *ttyFDs, size_t nttyFDs, int handshakefd) { int rc = -1; int control[2] = { -1, -1}; int containerhandshake[2] = { -1, -1 }; int *containerTtyFDs = NULL; char **containerTtyPaths = NULL; pid_t container = -1; virDomainFSDefPtr root; char *devpts = NULL; char *devptmx = NULL; size_t nloopDevs = 0; int *loopDevs = NULL; size_t i; if (VIR_ALLOC_N(containerTtyFDs, nttyFDs) < 0) { virReportOOMError(); goto cleanup; } if (VIR_ALLOC_N(containerTtyPaths, nttyFDs) < 0) { virReportOOMError(); goto cleanup; } if (socketpair(PF_UNIX, SOCK_STREAM, 0, control) < 0) { virReportSystemError(errno, "%s", _("sockpair failed")); goto cleanup; } if (socketpair(PF_UNIX, SOCK_STREAM, 0, containerhandshake) < 0) { virReportSystemError(errno, "%s", _("socketpair failed")); goto cleanup; } if (lxcSetupLoopDevices(def, &nloopDevs, &loopDevs) < 0) goto cleanup; root = virDomainGetRootFilesystem(def); if (lxcSetContainerResources(def) < 0) goto cleanup; /* * If doing a chroot style setup, we need to prepare * a private /dev/pts for the child now, which they * will later move into position. * * This is complex because 'virsh console' needs to * use /dev/pts from the host OS, and the guest OS * needs to use /dev/pts from the guest. * * This means that we (libvirt_lxc) need to see and * use both /dev/pts instances. We're running in the * host OS context though and don't want to expose * the guest OS /dev/pts there. * * Thus we call unshare(CLONE_NS) so that we can see * the guest's new /dev/pts, without it becoming * visible to the host OS. We also put the root FS * into slave mode, just in case it was currently * marked as shared */ if (root) { VIR_DEBUG("Setting up private /dev/pts"); if (!virFileExists(root->src)) { virReportSystemError(errno, _("root source %s does not exist"), root->src); goto cleanup; } if (unshare(CLONE_NEWNS) < 0) { virReportSystemError(errno, "%s", _("Cannot unshare mount namespace")); goto cleanup; } if (mount("", "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) { virReportSystemError(errno, "%s", _("Failed to switch root mount into slave mode")); goto cleanup; } if (virAsprintf(&devpts, "%s/dev/pts", root->src) < 0 || virAsprintf(&devptmx, "%s/dev/pts/ptmx", root->src) < 0) { virReportOOMError(); goto cleanup; } if (virFileMakePath(devpts) < 0) { virReportSystemError(errno, _("Failed to make path %s"), devpts); goto cleanup; } /* XXX should we support gid=X for X!=5 for distros which use * a different gid for tty? */ VIR_DEBUG("Mounting 'devpts' on %s", devpts); if (mount("devpts", devpts, "devpts", 0, "newinstance,ptmxmode=0666,mode=0620,gid=5") < 0) { virReportSystemError(errno, _("Failed to mount devpts on %s"), devpts); goto cleanup; } if (access(devptmx, R_OK) < 0) { VIR_WARN("Kernel does not support private devpts, using shared devpts"); VIR_FREE(devptmx); } } else { if (nttyFDs != -1) { lxcError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Expected exactly one TTY fd")); goto cleanup; } } for (i = 0 ; i < nttyFDs ; i++) { if (devptmx) { VIR_DEBUG("Opening tty on private %s", devptmx); if (lxcCreateTty(devptmx, &containerTtyFDs[i], &containerTtyPaths[i]) < 0) { virReportSystemError(errno, "%s", _("Failed to allocate tty")); goto cleanup; } } else { VIR_DEBUG("Opening tty on shared /dev/ptmx"); if (virFileOpenTty(&containerTtyFDs[i], &containerTtyPaths[i], 0) < 0) { virReportSystemError(errno, "%s", _("Failed to allocate tty")); goto cleanup; } } } if (lxcSetPersonality(def) < 0) goto cleanup; if ((container = lxcContainerStart(def, nveths, veths, control[1], containerhandshake[1], containerTtyPaths, nttyFDs)) < 0) goto cleanup; VIR_FORCE_CLOSE(control[1]); VIR_FORCE_CLOSE(containerhandshake[1]); if (lxcControllerMoveInterfaces(nveths, veths, container) < 0) goto cleanup; if (lxcContainerSendContinue(control[0]) < 0) { virReportSystemError(errno, "%s", _("Unable to send container continue message")); goto cleanup; } if (lxcContainerWaitForContinue(containerhandshake[0]) < 0) { virReportSystemError(errno, "%s", _("error receiving signal from container")); goto cleanup; } /* Now the container is fully setup... */ /* ...we can close the loop devices... */ for (i = 0 ; i < nloopDevs ; i++) VIR_FORCE_CLOSE(loopDevs[i]); /* ...and reduce our privileges */ if (lxcControllerClearCapabilities() < 0) goto cleanup; if (lxcContainerSendContinue(handshakefd) < 0) { virReportSystemError(errno, "%s", _("error sending continue signal to parent")); goto cleanup; } VIR_FORCE_CLOSE(handshakefd); if (virSetBlocking(monitor, false) < 0 || virSetBlocking(client, false) < 0) { virReportSystemError(errno, "%s", _("Unable to set file descriptor non blocking")); goto cleanup; } for (i = 0 ; i < nttyFDs ; i++) { if (virSetBlocking(ttyFDs[i], false) < 0 || virSetBlocking(containerTtyFDs[i], false) < 0) { virReportSystemError(errno, "%s", _("Unable to set file descriptor non blocking")); goto cleanup; } } rc = lxcControllerMain(monitor, client, ttyFDs, containerTtyFDs, nttyFDs, container); monitor = client = -1; cleanup: VIR_FREE(devptmx); VIR_FREE(devpts); VIR_FORCE_CLOSE(control[0]); VIR_FORCE_CLOSE(control[1]); VIR_FORCE_CLOSE(handshakefd); VIR_FORCE_CLOSE(containerhandshake[0]); VIR_FORCE_CLOSE(containerhandshake[1]); for (i = 0 ; i < nttyFDs ; i++) VIR_FREE(containerTtyPaths[i]); VIR_FREE(containerTtyPaths); for (i = 0 ; i < nttyFDs ; i++) VIR_FORCE_CLOSE(containerTtyFDs[i]); VIR_FREE(containerTtyFDs); for (i = 0 ; i < nloopDevs ; i++) VIR_FORCE_CLOSE(loopDevs[i]); VIR_FREE(loopDevs); virPidAbort(container); return rc; }