static int testCompareXMLToArgvFiles(const char *xml, const char *cmdline, virQEMUCapsPtr extraFlags, const char *migrateFrom, int migrateFd, bool json, bool expectError) { char *expectargv = NULL; int len; char *actualargv = NULL; int ret = -1; virDomainDefPtr vmdef = NULL; virDomainChrSourceDef monitor_chr; virConnectPtr conn; char *log = NULL; char *emulator = NULL; virCommandPtr cmd = NULL; if (!(conn = virGetConnect())) goto fail; len = virtTestLoadFile(cmdline, &expectargv); if (len < 0) goto fail; if (len && expectargv[len - 1] == '\n') expectargv[len - 1] = '\0'; if (!(vmdef = virDomainDefParseFile(xml, driver.caps, driver.xmlopt, QEMU_EXPECTED_VIRT_TYPES, VIR_DOMAIN_DEF_PARSE_INACTIVE))) goto fail; if (!virDomainDefCheckABIStability(vmdef, vmdef)) { fprintf(stderr, "ABI stability check failed on %s", xml); goto fail; } /* * For test purposes, we may want to fake emulator's output by providing * our own script instead of a real emulator. For this to work we need to * specify a relative path in <emulator/> element, which, however, is not * allowed by RelaxNG schema for domain XML. To work around it we add an * extra '/' at the beginning of relative emulator path so that it looks * like, e.g., "/./qemu.sh" or "/../emulator/qemu.sh" instead of * "./qemu.sh" or "../emulator/qemu.sh" respectively. The following code * detects such paths, strips the extra '/' and makes the path absolute. */ if (vmdef->emulator && STRPREFIX(vmdef->emulator, "/.")) { if (VIR_STRDUP(emulator, vmdef->emulator + 1) < 0) goto fail; VIR_FREE(vmdef->emulator); vmdef->emulator = NULL; if (virAsprintf(&vmdef->emulator, "%s/qemuxml2argvdata/%s", abs_srcdir, emulator) < 0) goto fail; } if (virQEMUCapsGet(extraFlags, QEMU_CAPS_DOMID)) vmdef->id = 6; else vmdef->id = -1; memset(&monitor_chr, 0, sizeof(monitor_chr)); monitor_chr.type = VIR_DOMAIN_CHR_TYPE_UNIX; monitor_chr.data.nix.path = (char *)"/tmp/test-monitor"; monitor_chr.data.nix.listen = true; virQEMUCapsSetList(extraFlags, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, QEMU_CAPS_NO_ACPI, QEMU_CAPS_LAST); if (virQEMUCapsGet(extraFlags, QEMU_CAPS_DEVICE)) qemuDomainAssignAddresses(vmdef, extraFlags, NULL); log = virtTestLogContentAndReset(); VIR_FREE(log); virResetLastError(); if (vmdef->os.arch == VIR_ARCH_X86_64 || vmdef->os.arch == VIR_ARCH_I686) { virQEMUCapsSet(extraFlags, QEMU_CAPS_PCI_MULTIBUS); } if (qemuAssignDeviceAliases(vmdef, extraFlags) < 0) goto fail; if (!(cmd = qemuBuildCommandLine(conn, &driver, vmdef, &monitor_chr, json, extraFlags, migrateFrom, migrateFd, NULL, VIR_NETDEV_VPORT_PROFILE_OP_NO_OP, &testCallbacks, false, false, NULL))) goto fail; if (!virtTestOOMActive()) { if (!!virGetLastError() != expectError) { if (virTestGetDebug() && (log = virtTestLogContentAndReset())) fprintf(stderr, "\n%s", log); goto fail; } if (expectError) { /* need to suppress the errors */ virResetLastError(); } } if (!(actualargv = virCommandToString(cmd))) goto fail; if (emulator) { /* Skip the abs_srcdir portion of replacement emulator. */ char *start_skip = strstr(actualargv, abs_srcdir); char *end_skip = strstr(actualargv, emulator); if (!start_skip || !end_skip) goto fail; memmove(start_skip, end_skip, strlen(end_skip) + 1); } if (STRNEQ(expectargv, actualargv)) { virtTestDifference(stderr, expectargv, actualargv); goto fail; } ret = 0; fail: VIR_FREE(log); VIR_FREE(emulator); VIR_FREE(expectargv); VIR_FREE(actualargv); virCommandFree(cmd); virDomainDefFree(vmdef); virObjectUnref(conn); return ret; }
static int daemonConfigLoadOptions(struct daemonConfig *data, const char *filename, virConfPtr conf) { GET_CONF_UINT(conf, filename, listen_tcp); GET_CONF_UINT(conf, filename, listen_tls); GET_CONF_STR(conf, filename, tls_port); GET_CONF_STR(conf, filename, tcp_port); GET_CONF_STR(conf, filename, listen_addr); if (remoteConfigGetAuth(conf, "auth_unix_rw", &data->auth_unix_rw, filename) < 0) goto error; #if WITH_POLKIT /* Change default perms to be wide-open if PolicyKit is enabled. * Admin can always override in config file */ if (data->auth_unix_rw == REMOTE_AUTH_POLKIT) { VIR_FREE(data->unix_sock_rw_perms); if (VIR_STRDUP(data->unix_sock_rw_perms, "0777") < 0) goto error; } #endif if (remoteConfigGetAuth(conf, "auth_unix_ro", &data->auth_unix_ro, filename) < 0) goto error; if (remoteConfigGetAuth(conf, "auth_tcp", &data->auth_tcp, filename) < 0) goto error; if (remoteConfigGetAuth(conf, "auth_tls", &data->auth_tls, filename) < 0) goto error; if (remoteConfigGetStringList(conf, "access_drivers", &data->access_drivers, filename) < 0) goto error; GET_CONF_STR(conf, filename, unix_sock_group); GET_CONF_STR(conf, filename, unix_sock_admin_perms); GET_CONF_STR(conf, filename, unix_sock_ro_perms); GET_CONF_STR(conf, filename, unix_sock_rw_perms); GET_CONF_STR(conf, filename, unix_sock_dir); GET_CONF_UINT(conf, filename, mdns_adv); GET_CONF_STR(conf, filename, mdns_name); GET_CONF_UINT(conf, filename, tls_no_sanity_certificate); GET_CONF_UINT(conf, filename, tls_no_verify_certificate); GET_CONF_STR(conf, filename, key_file); GET_CONF_STR(conf, filename, cert_file); GET_CONF_STR(conf, filename, ca_file); GET_CONF_STR(conf, filename, crl_file); if (remoteConfigGetStringList(conf, "tls_allowed_dn_list", &data->tls_allowed_dn_list, filename) < 0) goto error; if (remoteConfigGetStringList(conf, "sasl_allowed_username_list", &data->sasl_allowed_username_list, filename) < 0) goto error; GET_CONF_UINT(conf, filename, min_workers); GET_CONF_UINT(conf, filename, max_workers); GET_CONF_UINT(conf, filename, max_clients); GET_CONF_UINT(conf, filename, max_queued_clients); GET_CONF_UINT(conf, filename, max_anonymous_clients); GET_CONF_UINT(conf, filename, prio_workers); GET_CONF_INT(conf, filename, max_requests); GET_CONF_UINT(conf, filename, max_client_requests); GET_CONF_UINT(conf, filename, admin_min_workers); GET_CONF_UINT(conf, filename, admin_max_workers); GET_CONF_UINT(conf, filename, admin_max_clients); GET_CONF_UINT(conf, filename, admin_max_queued_clients); GET_CONF_UINT(conf, filename, admin_max_client_requests); GET_CONF_UINT(conf, filename, audit_level); GET_CONF_UINT(conf, filename, audit_logging); GET_CONF_STR(conf, filename, host_uuid); GET_CONF_UINT(conf, filename, log_level); GET_CONF_STR(conf, filename, log_filters); GET_CONF_STR(conf, filename, log_outputs); GET_CONF_INT(conf, filename, keepalive_interval); GET_CONF_UINT(conf, filename, keepalive_count); GET_CONF_INT(conf, filename, admin_keepalive_interval); GET_CONF_UINT(conf, filename, admin_keepalive_count); return 0; error: return -1; }
static int virStorageBackendZFSParseVol(virStoragePoolObjPtr pool, virStorageVolDefPtr vol, const char *volume_string) { int ret = -1; char **tokens; size_t count; char **name_tokens = NULL; char *vol_name; bool is_new_vol = false; virStorageVolDefPtr volume = NULL; virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool); if (!(tokens = virStringSplitCount(volume_string, "\t", 0, &count))) return -1; if (count != 3) goto cleanup; if (!(name_tokens = virStringSplit(tokens[0], "/", 2))) goto cleanup; vol_name = name_tokens[1]; if (vol == NULL) volume = virStorageVolDefFindByName(pool, vol_name); else volume = vol; if (volume == NULL) { if (VIR_ALLOC(volume) < 0) goto cleanup; is_new_vol = true; volume->type = VIR_STORAGE_VOL_BLOCK; if (VIR_STRDUP(volume->name, vol_name) < 0) goto cleanup; } if (!volume->key && VIR_STRDUP(volume->key, tokens[0]) < 0) goto cleanup; if (volume->target.path == NULL) { if (virAsprintf(&volume->target.path, "%s/%s", def->target.path, volume->name) < 0) goto cleanup; } if (virStrToLong_ull(tokens[1], NULL, 10, &volume->target.capacity) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed volsize reported")); goto cleanup; } if (virStrToLong_ull(tokens[2], NULL, 10, &volume->target.allocation) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed refreservation reported")); goto cleanup; } if (volume->target.allocation < volume->target.capacity) volume->target.sparse = true; if (is_new_vol && virStoragePoolObjAddVol(pool, volume) < 0) goto cleanup; volume = NULL; ret = 0; cleanup: virStringListFree(tokens); virStringListFree(name_tokens); if (is_new_vol) virStorageVolDefFree(volume); return ret; }
/** * virAdmConnectOpen: * @name: uri of the daemon to connect to, NULL for default * @flags: bitwise-OR of virConnectFlags; so far the only supported flag is * VIR_CONNECT_NO_ALIASES * * Opens connection to admin interface of the daemon. * * Returns @virAdmConnectPtr object or NULL on error */ virAdmConnectPtr virAdmConnectOpen(const char *name, unsigned int flags) { char *sock_path = NULL; char *alias = NULL; virAdmConnectPtr conn = NULL; virConfPtr conf = NULL; char *uristr = NULL; if (virAdmInitialize() < 0) goto error; VIR_DEBUG("flags=%x", flags); virResetLastError(); if (!(conn = virAdmConnectNew())) goto error; if (virConfLoadConfig(&conf, "libvirt-admin.conf") < 0) goto error; if (name) { if (VIR_STRDUP(uristr, name) < 0) goto error; } else { if (virAdmGetDefaultURI(conf, &uristr) < 0) goto error; } if ((!(flags & VIR_CONNECT_NO_ALIASES) && virURIResolveAlias(conf, uristr, &alias) < 0)) goto error; if (alias) { VIR_FREE(uristr); uristr = alias; } if (!(conn->uri = virURIParse(uristr))) goto error; if (!(sock_path = getSocketPath(conn->uri))) goto error; if (!(conn->privateData = remoteAdminPrivNew(sock_path))) goto error; conn->privateDataFreeFunc = remoteAdminPrivFree; if (remoteAdminConnectOpen(conn, flags) < 0) goto error; cleanup: VIR_FREE(sock_path); VIR_FREE(uristr); virConfFree(conf); return conn; error: virDispatchError(NULL); virObjectUnref(conn); conn = NULL; goto cleanup; }
/** * virObjectEventCallbackListAddID: * @conn: pointer to the connection * @cbList: the list * @key: the optional key of the object to filter on * @filter: optional last-ditch filter callback * @filter_opaque: opaque data to pass to @filter * @klass: the base event class * @eventID: the event ID * @callback: the callback to add * @opaque: opaque data to pass to @callback * @freecb: callback to free @opaque * @legacy: true if callback is tracked by function instead of callbackID * @callbackID: filled with callback ID * @serverFilter: true if server supports object filtering * * Internal function to add a callback from a virObjectEventCallbackListPtr */ static int virObjectEventCallbackListAddID(virConnectPtr conn, virObjectEventCallbackListPtr cbList, const char *key, virObjectEventCallbackFilter filter, void *filter_opaque, virClassPtr klass, int eventID, virConnectObjectEventGenericCallback callback, void *opaque, virFreeCallback freecb, bool legacy, int *callbackID, bool serverFilter) { virObjectEventCallbackPtr cb; int ret = -1; int remoteID = -1; VIR_DEBUG("conn=%p cblist=%p key=%p filter=%p filter_opaque=%p " "klass=%p eventID=%d callback=%p opaque=%p " "legacy=%d callbackID=%p serverFilter=%d", conn, cbList, key, filter, filter_opaque, klass, eventID, callback, opaque, legacy, callbackID, serverFilter); /* Check incoming */ if (!cbList) return -1; /* If there is no additional filtering, then check if we already * have this callback on our list. */ if (!filter && virObjectEventCallbackLookup(conn, cbList, key, klass, eventID, callback, legacy, serverFilter ? &remoteID : NULL) != -1) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("event callback already tracked")); return -1; } /* Allocate new cb */ if (VIR_ALLOC(cb) < 0) goto cleanup; cb->conn = virObjectRef(conn); *callbackID = cb->callbackID = cbList->nextID++; cb->cb = callback; cb->klass = klass; cb->eventID = eventID; cb->opaque = opaque; cb->freecb = freecb; cb->remoteID = remoteID; if (key) { cb->key_filter = true; if (VIR_STRDUP(cb->key, key) < 0) goto cleanup; } cb->filter = filter; cb->filter_opaque = filter_opaque; cb->legacy = legacy; if (VIR_APPEND_ELEMENT(cbList->callbacks, cbList->count, cb) < 0) goto cleanup; /* When additional filtering is being done, every client callback * is matched to exactly one server callback. */ if (filter) { ret = 1; } else { ret = virObjectEventCallbackListCount(conn, cbList, klass, eventID, key, serverFilter); if (serverFilter && remoteID < 0) ret++; } cleanup: virObjectEventCallbackFree(cb); return ret; }
static char* virBhyveTapGetRealDeviceName(char *name) { /* This is an ugly hack, because if we rename * tap device to vnet%d, its device name will be * still /dev/tap%d, and bhyve tries to open /dev/tap%d, * so we have to find the real name */ char *ret = NULL; struct dirent *dp; char *devpath = NULL; int fd; DIR *dirp = opendir("/dev"); if (dirp == NULL) { virReportSystemError(errno, _("Failed to opendir path '%s'"), "/dev"); return NULL; } while ((dp = readdir(dirp)) != NULL) { if (STRPREFIX(dp->d_name, "tap")) { struct ifreq ifr; if (virAsprintf(&devpath, "/dev/%s", dp->d_name) < 0) { goto cleanup; } if ((fd = open(devpath, O_RDWR)) < 0) { virReportSystemError(errno, _("Unable to open '%s'"), devpath); goto cleanup; } if (ioctl(fd, TAPGIFNAME, (void *)&ifr) < 0) { virReportSystemError(errno, "%s", _("Unable to query tap interface name")); goto cleanup; } if (STREQ(name, ifr.ifr_name)) { /* we can ignore the return value * because we still have nothing * to do but return; */ ignore_value(VIR_STRDUP(ret, dp->d_name)); goto cleanup; } VIR_FREE(devpath); VIR_FORCE_CLOSE(fd); } errno = 0; } if (errno != 0) virReportSystemError(errno, "%s", _("Unable to iterate over TAP devices")); cleanup: VIR_FREE(devpath); VIR_FORCE_CLOSE(fd); closedir(dirp); return ret; }
int vmwareLoadDomains(struct vmware_driver *driver) { virDomainDefPtr vmdef = NULL; virDomainObjPtr vm = NULL; char *vmxPath = NULL; char *vmx = NULL; vmwareDomainPtr pDomain; char *directoryName = NULL; char *fileName = NULL; int ret = -1; virVMXContext ctx; char *outbuf = NULL; char *str; char *saveptr = NULL; virCommandPtr cmd; ctx.parseFileName = vmwareCopyVMXFileName; ctx.formatFileName = NULL; ctx.autodetectSCSIControllerModel = NULL; ctx.datacenterPath = NULL; cmd = virCommandNewArgList(driver->vmrun, "-T", vmwareDriverTypeToString(driver->type), "list", NULL); virCommandSetOutputBuffer(cmd, &outbuf); if (virCommandRun(cmd, NULL) < 0) goto cleanup; for (str = outbuf; (vmxPath = strtok_r(str, "\n", &saveptr)) != NULL; str = NULL) { if (vmxPath[0] != '/') continue; if (virFileReadAll(vmxPath, 10000, &vmx) < 0) goto cleanup; if ((vmdef = virVMXParseConfig(&ctx, driver->xmlopt, driver->caps, vmx)) == NULL) { goto cleanup; } if (!(vm = virDomainObjListAdd(driver->domains, vmdef, driver->xmlopt, 0, NULL))) goto cleanup; pDomain = vm->privateData; if (VIR_STRDUP(pDomain->vmxPath, vmxPath) < 0) goto cleanup; vmwareDomainConfigDisplay(pDomain, vmdef); if ((vm->def->id = vmwareExtractPid(vmxPath)) < 0) goto cleanup; /* vmrun list only reports running vms */ virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN); vm->persistent = 1; virObjectUnlock(vm); vmdef = NULL; vm = NULL; } ret = 0; cleanup: virCommandFree(cmd); VIR_FREE(outbuf); virDomainDefFree(vmdef); VIR_FREE(directoryName); VIR_FREE(fileName); VIR_FREE(vmx); virObjectUnref(vm); return ret; }
virCapsPtr virQEMUDriverCreateCapabilities(virQEMUDriverPtr driver) { size_t i, j; virCapsPtr caps; virSecurityManagerPtr *sec_managers = NULL; /* Security driver data */ const char *doi, *model, *lbl, *type; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); const int virtTypes[] = {VIR_DOMAIN_VIRT_KVM, VIR_DOMAIN_VIRT_QEMU,}; /* Basic host arch / guest machine capabilities */ if (!(caps = virQEMUCapsInit(driver->qemuCapsCache))) goto error; if (virGetHostUUID(caps->host.host_uuid)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot get the host uuid")); goto error; } /* access sec drivers and create a sec model for each one */ if (!(sec_managers = virSecurityManagerGetNested(driver->securityManager))) goto error; /* calculate length */ for (i = 0; sec_managers[i]; i++) ; caps->host.nsecModels = i; if (VIR_ALLOC_N(caps->host.secModels, caps->host.nsecModels) < 0) goto error; for (i = 0; sec_managers[i]; i++) { virCapsHostSecModelPtr sm = &caps->host.secModels[i]; doi = virSecurityManagerGetDOI(sec_managers[i]); model = virSecurityManagerGetModel(sec_managers[i]); if (VIR_STRDUP(sm->model, model) < 0 || VIR_STRDUP(sm->doi, doi) < 0) goto error; for (j = 0; j < ARRAY_CARDINALITY(virtTypes); j++) { lbl = virSecurityManagerGetBaseLabel(sec_managers[i], virtTypes[j]); type = virDomainVirtTypeToString(virtTypes[j]); if (lbl && virCapabilitiesHostSecModelAddBaseLabel(sm, type, lbl) < 0) goto error; } VIR_DEBUG("Initialized caps for security driver \"%s\" with " "DOI \"%s\"", model, doi); } VIR_FREE(sec_managers); virObjectUnref(cfg); return caps; error: VIR_FREE(sec_managers); virObjectUnref(caps); virObjectUnref(cfg); return NULL; }
static int testInfoSet(struct testInfo *info, const char *name, bool different, int when) { if (virAsprintf(&info->inName, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", abs_srcdir, name) < 0) goto error; if (virtTestLoadFile(info->inName, &info->inFile) < 0) goto error; if (when & WHEN_INACTIVE) { if (different) { if (virAsprintf(&info->outInactiveName, "%s/qemuxml2xmloutdata/qemuxml2xmlout-%s-inactive.xml", abs_srcdir, name) < 0) goto error; if (!virFileExists(info->outInactiveName)) { VIR_FREE(info->outInactiveName); if (virAsprintf(&info->outInactiveName, "%s/qemuxml2xmloutdata/qemuxml2xmlout-%s.xml", abs_srcdir, name) < 0) goto error; } } else { if (VIR_STRDUP(info->outInactiveName, info->inName) < 0) goto error; } if (virtTestLoadFile(info->outInactiveName, &info->outInactiveFile) < 0) goto error; } if (when & WHEN_ACTIVE) { if (different) { if (virAsprintf(&info->outActiveName, "%s/qemuxml2xmloutdata/qemuxml2xmlout-%s-active.xml", abs_srcdir, name) < 0) goto error; if (!virFileExists(info->outActiveName)) { VIR_FREE(info->outActiveName); if (virAsprintf(&info->outActiveName, "%s/qemuxml2xmloutdata/qemuxml2xmlout-%s.xml", abs_srcdir, name) < 0) goto error; } } else { if (VIR_STRDUP(info->outActiveName, info->inName) < 0) goto error; } if (virtTestLoadFile(info->outActiveName, &info->outActiveFile) < 0) goto error; } return 0; error: testInfoFree(info); return -1; }
virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged) { virQEMUDriverConfigPtr cfg; if (virQEMUConfigInitialize() < 0) return NULL; if (!(cfg = virObjectNew(virQEMUDriverConfigClass))) return NULL; cfg->privileged = privileged; cfg->uri = privileged ? "qemu:///system" : "qemu:///session"; if (privileged) { if (virGetUserID(QEMU_USER, &cfg->user) < 0) goto error; if (virGetGroupID(QEMU_GROUP, &cfg->group) < 0) goto error; } else { cfg->user = (uid_t)-1; cfg->group = (gid_t)-1; } cfg->dynamicOwnership = privileged; cfg->cgroupControllers = -1; /* -1 == auto-detect */ if (privileged) { if (virAsprintf(&cfg->logDir, "%s/log/libvirt/qemu", LOCALSTATEDIR) < 0) goto error; if (VIR_STRDUP(cfg->configBaseDir, SYSCONFDIR "/libvirt") < 0) goto error; if (virAsprintf(&cfg->stateDir, "%s/run/libvirt/qemu", LOCALSTATEDIR) < 0) goto error; if (virAsprintf(&cfg->libDir, "%s/lib/libvirt/qemu", LOCALSTATEDIR) < 0) goto error; if (virAsprintf(&cfg->cacheDir, "%s/cache/libvirt/qemu", LOCALSTATEDIR) < 0) goto error; if (virAsprintf(&cfg->saveDir, "%s/lib/libvirt/qemu/save", LOCALSTATEDIR) < 0) goto error; if (virAsprintf(&cfg->snapshotDir, "%s/lib/libvirt/qemu/snapshot", LOCALSTATEDIR) < 0) goto error; if (virAsprintf(&cfg->autoDumpPath, "%s/lib/libvirt/qemu/dump", LOCALSTATEDIR) < 0) goto error; } else { char *rundir; char *cachedir; cachedir = virGetUserCacheDirectory(); if (!cachedir) goto error; if (virAsprintf(&cfg->logDir, "%s/qemu/log", cachedir) < 0) { VIR_FREE(cachedir); goto error; } if (virAsprintf(&cfg->cacheDir, "%s/qemu/cache", cachedir) < 0) { VIR_FREE(cachedir); goto error; } VIR_FREE(cachedir); rundir = virGetUserRuntimeDirectory(); if (!rundir) goto error; if (virAsprintf(&cfg->stateDir, "%s/qemu/run", rundir) < 0) { VIR_FREE(rundir); goto error; } VIR_FREE(rundir); if (!(cfg->configBaseDir = virGetUserConfigDirectory())) goto error; if (virAsprintf(&cfg->libDir, "%s/qemu/lib", cfg->configBaseDir) < 0) goto error; if (virAsprintf(&cfg->saveDir, "%s/qemu/save", cfg->configBaseDir) < 0) goto error; if (virAsprintf(&cfg->snapshotDir, "%s/qemu/snapshot", cfg->configBaseDir) < 0) goto error; if (virAsprintf(&cfg->autoDumpPath, "%s/qemu/dump", cfg->configBaseDir) < 0) goto error; } if (virAsprintf(&cfg->configDir, "%s/qemu", cfg->configBaseDir) < 0) goto error; if (virAsprintf(&cfg->autostartDir, "%s/qemu/autostart", cfg->configBaseDir) < 0) goto error; if (VIR_STRDUP(cfg->vncListen, "127.0.0.1") < 0) goto error; if (VIR_STRDUP(cfg->vncTLSx509certdir, SYSCONFDIR "/pki/libvirt-vnc") < 0) goto error; if (VIR_STRDUP(cfg->spiceListen, "127.0.0.1") < 0) goto error; if (VIR_STRDUP(cfg->spiceTLSx509certdir , SYSCONFDIR "/pki/libvirt-spice") < 0) goto error; cfg->remotePortMin = QEMU_REMOTE_PORT_MIN; cfg->remotePortMax = QEMU_REMOTE_PORT_MAX; cfg->webSocketPortMin = QEMU_WEBSOCKET_PORT_MIN; cfg->webSocketPortMax = QEMU_WEBSOCKET_PORT_MAX; cfg->migrationPortMin = QEMU_MIGRATION_PORT_MIN; cfg->migrationPortMax = QEMU_MIGRATION_PORT_MAX; #if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R /* For privileged driver, try and find hugepage mount automatically. * Non-privileged driver requires admin to create a dir for the * user, chown it, and then let user configure it manually */ if (privileged && !(cfg->hugetlbfsMount = virFileFindMountPoint("hugetlbfs"))) { if (errno != ENOENT) { virReportSystemError(errno, "%s", _("unable to find hugetlbfs mountpoint")); goto error; } } #endif if (VIR_STRDUP(cfg->bridgeHelperName, "/usr/libexec/qemu-bridge-helper") < 0) goto error; cfg->clearEmulatorCapabilities = true; cfg->securityDefaultConfined = true; cfg->securityRequireConfined = false; cfg->keepAliveInterval = 5; cfg->keepAliveCount = 5; cfg->seccompSandbox = -1; return cfg; error: virObjectUnref(cfg); return NULL; }
int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, const char *filename) { virConfPtr conf = NULL; virConfValuePtr p; int ret = -1; size_t i; /* Just check the file is readable before opening it, otherwise * libvirt emits an error. */ if (access(filename, R_OK) == -1) { VIR_INFO("Could not read qemu config file %s", filename); return 0; } if (!(conf = virConfReadFile(filename, 0))) goto cleanup; #define CHECK_TYPE(name,typ) \ if (p && p->type != (typ)) { \ virReportError(VIR_ERR_INTERNAL_ERROR, \ "%s: %s: expected type " #typ, \ filename, (name)); \ goto cleanup; \ } #define GET_VALUE_LONG(NAME, VAR) \ p = virConfGetValue(conf, NAME); \ CHECK_TYPE(NAME, VIR_CONF_LONG); \ if (p) \ VAR = p->l; #define GET_VALUE_BOOL(NAME, VAR) \ p = virConfGetValue(conf, NAME); \ CHECK_TYPE(NAME, VIR_CONF_LONG); \ if (p) \ VAR = p->l != 0; #define GET_VALUE_STR(NAME, VAR) \ p = virConfGetValue(conf, NAME); \ CHECK_TYPE(NAME, VIR_CONF_STRING); \ if (p && p->str) { \ VIR_FREE(VAR); \ if (VIR_STRDUP(VAR, p->str) < 0) \ goto cleanup; \ } GET_VALUE_BOOL("vnc_auto_unix_socket", cfg->vncAutoUnixSocket); GET_VALUE_BOOL("vnc_tls", cfg->vncTLS); GET_VALUE_BOOL("vnc_tls_x509_verify", cfg->vncTLSx509verify); GET_VALUE_STR("vnc_tls_x509_cert_dir", cfg->vncTLSx509certdir); GET_VALUE_STR("vnc_listen", cfg->vncListen); GET_VALUE_STR("vnc_password", cfg->vncPassword); GET_VALUE_BOOL("vnc_sasl", cfg->vncSASL); GET_VALUE_STR("vnc_sasl_dir", cfg->vncSASLdir); GET_VALUE_BOOL("vnc_allow_host_audio", cfg->vncAllowHostAudio); GET_VALUE_BOOL("nographics_allow_host_audio", cfg->nogfxAllowHostAudio); p = virConfGetValue(conf, "security_driver"); if (p && p->type == VIR_CONF_LIST) { size_t len; virConfValuePtr pp; /* Calc length and check items */ for (len = 0, pp = p->list; pp; len++, pp = pp->next) { if (pp->type != VIR_CONF_STRING) { virReportError(VIR_ERR_CONF_SYNTAX, "%s", _("security_driver must be a list of strings")); goto cleanup; } } if (VIR_ALLOC_N(cfg->securityDriverNames, len + 1) < 0) goto cleanup; for (i = 0, pp = p->list; pp; i++, pp = pp->next) { if (VIR_STRDUP(cfg->securityDriverNames[i], pp->str) < 0) goto cleanup; } cfg->securityDriverNames[len] = NULL; } else { CHECK_TYPE("security_driver", VIR_CONF_STRING); if (p && p->str) { if (VIR_ALLOC_N(cfg->securityDriverNames, 2) < 0) goto cleanup; if (VIR_STRDUP(cfg->securityDriverNames[0], p->str) < 0) goto cleanup; cfg->securityDriverNames[1] = NULL; } } GET_VALUE_BOOL("security_default_confined", cfg->securityDefaultConfined); GET_VALUE_BOOL("security_require_confined", cfg->securityRequireConfined); GET_VALUE_BOOL("spice_tls", cfg->spiceTLS); GET_VALUE_STR("spice_tls_x509_cert_dir", cfg->spiceTLSx509certdir); GET_VALUE_BOOL("spice_sasl", cfg->spiceSASL); GET_VALUE_STR("spice_sasl_dir", cfg->spiceSASLdir); GET_VALUE_STR("spice_listen", cfg->spiceListen); GET_VALUE_STR("spice_password", cfg->spicePassword); GET_VALUE_LONG("remote_websocket_port_min", cfg->webSocketPortMin); if (cfg->webSocketPortMin < QEMU_WEBSOCKET_PORT_MIN) { /* if the port is too low, we can't get the display name * to tell to vnc (usually subtract 5700, e.g. localhost:1 * for port 5701) */ virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_websocket_port_min: port must be greater " "than or equal to %d"), filename, QEMU_WEBSOCKET_PORT_MIN); goto cleanup; } GET_VALUE_LONG("remote_websocket_port_max", cfg->webSocketPortMax); if (cfg->webSocketPortMax > QEMU_WEBSOCKET_PORT_MAX || cfg->webSocketPortMax < cfg->webSocketPortMin) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_websocket_port_max: port must be between " "the minimal port and %d"), filename, QEMU_WEBSOCKET_PORT_MAX); goto cleanup; } if (cfg->webSocketPortMin > cfg->webSocketPortMax) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_websocket_port_min: min port must not be " "greater than max port"), filename); goto cleanup; } GET_VALUE_LONG("remote_display_port_min", cfg->remotePortMin); if (cfg->remotePortMin < QEMU_REMOTE_PORT_MIN) { /* if the port is too low, we can't get the display name * to tell to vnc (usually subtract 5900, e.g. localhost:1 * for port 5901) */ virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_display_port_min: port must be greater " "than or equal to %d"), filename, QEMU_REMOTE_PORT_MIN); goto cleanup; } GET_VALUE_LONG("remote_display_port_max", cfg->remotePortMax); if (cfg->remotePortMax > QEMU_REMOTE_PORT_MAX || cfg->remotePortMax < cfg->remotePortMin) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_display_port_max: port must be between " "the minimal port and %d"), filename, QEMU_REMOTE_PORT_MAX); goto cleanup; } if (cfg->remotePortMin > cfg->remotePortMax) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_display_port_min: min port must not be " "greater than max port"), filename); goto cleanup; } GET_VALUE_LONG("migration_port_min", cfg->migrationPortMin); if (cfg->migrationPortMin <= 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: migration_port_min: port must be greater than 0"), filename); goto cleanup; } GET_VALUE_LONG("migration_port_max", cfg->migrationPortMax); if (cfg->migrationPortMax > 65535 || cfg->migrationPortMax < cfg->migrationPortMin) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: migration_port_max: port must be between " "the minimal port %d and 65535"), filename, cfg->migrationPortMin); goto cleanup; } p = virConfGetValue(conf, "user"); CHECK_TYPE("user", VIR_CONF_STRING); if (p && p->str && virGetUserID(p->str, &cfg->user) < 0) goto cleanup; p = virConfGetValue(conf, "group"); CHECK_TYPE("group", VIR_CONF_STRING); if (p && p->str && virGetGroupID(p->str, &cfg->group) < 0) goto cleanup; GET_VALUE_BOOL("dynamic_ownership", cfg->dynamicOwnership); p = virConfGetValue(conf, "cgroup_controllers"); CHECK_TYPE("cgroup_controllers", VIR_CONF_LIST); if (p) { cfg->cgroupControllers = 0; virConfValuePtr pp; for (i = 0, pp = p->list; pp; ++i, pp = pp->next) { int ctl; if (pp->type != VIR_CONF_STRING) { virReportError(VIR_ERR_CONF_SYNTAX, "%s", _("cgroup_controllers must be a " "list of strings")); goto cleanup; } if ((ctl = virCgroupControllerTypeFromString(pp->str)) < 0) { virReportError(VIR_ERR_CONF_SYNTAX, _("Unknown cgroup controller '%s'"), pp->str); goto cleanup; } cfg->cgroupControllers |= (1 << ctl); } } p = virConfGetValue(conf, "cgroup_device_acl"); CHECK_TYPE("cgroup_device_acl", VIR_CONF_LIST); if (p) { int len = 0; virConfValuePtr pp; for (pp = p->list; pp; pp = pp->next) len++; if (VIR_ALLOC_N(cfg->cgroupDeviceACL, 1+len) < 0) goto cleanup; for (i = 0, pp = p->list; pp; ++i, pp = pp->next) { if (pp->type != VIR_CONF_STRING) { virReportError(VIR_ERR_CONF_SYNTAX, "%s", _("cgroup_device_acl must be a " "list of strings")); goto cleanup; } if (VIR_STRDUP(cfg->cgroupDeviceACL[i], pp->str) < 0) goto cleanup; } cfg->cgroupDeviceACL[i] = NULL; } GET_VALUE_STR("save_image_format", cfg->saveImageFormat); GET_VALUE_STR("dump_image_format", cfg->dumpImageFormat); GET_VALUE_STR("snapshot_image_format", cfg->snapshotImageFormat); GET_VALUE_STR("auto_dump_path", cfg->autoDumpPath); GET_VALUE_BOOL("auto_dump_bypass_cache", cfg->autoDumpBypassCache); GET_VALUE_BOOL("auto_start_bypass_cache", cfg->autoStartBypassCache); GET_VALUE_STR("hugetlbfs_mount", cfg->hugetlbfsMount); GET_VALUE_STR("bridge_helper", cfg->bridgeHelperName); GET_VALUE_BOOL("mac_filter", cfg->macFilter); GET_VALUE_BOOL("relaxed_acs_check", cfg->relaxedACS); GET_VALUE_BOOL("clear_emulator_capabilities", cfg->clearEmulatorCapabilities); GET_VALUE_BOOL("allow_disk_format_probing", cfg->allowDiskFormatProbing); GET_VALUE_BOOL("set_process_name", cfg->setProcessName); GET_VALUE_LONG("max_processes", cfg->maxProcesses); GET_VALUE_LONG("max_files", cfg->maxFiles); GET_VALUE_STR("lock_manager", cfg->lockManagerName); GET_VALUE_LONG("max_queued", cfg->maxQueuedJobs); GET_VALUE_LONG("keepalive_interval", cfg->keepAliveInterval); GET_VALUE_LONG("keepalive_count", cfg->keepAliveCount); GET_VALUE_LONG("seccomp_sandbox", cfg->seccompSandbox); GET_VALUE_STR("migration_address", cfg->migrationAddress); ret = 0; cleanup: virConfFree(conf); return ret; }
static int testInfoSet(struct testInfo *info, const char *name, bool different, int when) { if (!(info->qemuCaps = virQEMUCapsNew())) goto error; if (qemuTestCapsCacheInsert(driver.qemuCapsCache, name, info->qemuCaps) < 0) goto error; if (virAsprintf(&info->inName, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", abs_srcdir, name) < 0) goto error; if (when & WHEN_INACTIVE) { if (different) { if (virAsprintf(&info->outInactiveName, "%s/qemuxml2xmloutdata/qemuxml2xmlout-%s-inactive.xml", abs_srcdir, name) < 0) goto error; if (!virFileExists(info->outInactiveName)) { VIR_FREE(info->outInactiveName); if (virAsprintf(&info->outInactiveName, "%s/qemuxml2xmloutdata/qemuxml2xmlout-%s.xml", abs_srcdir, name) < 0) goto error; } } else { if (VIR_STRDUP(info->outInactiveName, info->inName) < 0) goto error; } } if (when & WHEN_ACTIVE) { if (different) { if (virAsprintf(&info->outActiveName, "%s/qemuxml2xmloutdata/qemuxml2xmlout-%s-active.xml", abs_srcdir, name) < 0) goto error; if (!virFileExists(info->outActiveName)) { VIR_FREE(info->outActiveName); if (virAsprintf(&info->outActiveName, "%s/qemuxml2xmloutdata/qemuxml2xmlout-%s.xml", abs_srcdir, name) < 0) goto error; } } else { if (VIR_STRDUP(info->outActiveName, info->inName) < 0) goto error; } } return 0; error: testInfoFree(info); return -1; }
static int bhyveBuildNetArgStr(const virDomainDef *def, virDomainNetDefPtr net, virCommandPtr cmd, bool dryRun) { char macaddr[VIR_MAC_STRING_BUFLEN]; char *realifname = NULL; char *brname = NULL; int actualType = virDomainNetGetActualType(net); if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) { if (VIR_STRDUP(brname, virDomainNetGetActualBridgeName(net)) < 0) return -1; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Network type %d is not supported"), virDomainNetGetActualType(net)); return -1; } if (!net->ifname || STRPREFIX(net->ifname, VIR_NET_GENERATED_PREFIX) || strchr(net->ifname, '%')) { VIR_FREE(net->ifname); if (VIR_STRDUP(net->ifname, VIR_NET_GENERATED_PREFIX "%d") < 0) { VIR_FREE(brname); return -1; } } if (!dryRun) { if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac, def->uuid, NULL, 0, virDomainNetGetActualVirtPortProfile(net), virDomainNetGetActualVlan(net), VIR_NETDEV_TAP_CREATE_IFUP | VIR_NETDEV_TAP_CREATE_PERSIST) < 0) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } realifname = virNetDevTapGetRealDeviceName(net->ifname); if (realifname == NULL) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } VIR_DEBUG("%s -> %s", net->ifname, realifname); /* hack on top of other hack: we need to set * interface to 'UP' again after re-opening to find its * name */ if (virNetDevSetOnline(net->ifname, true) != 0) { VIR_FREE(realifname); VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } } else { if (VIR_STRDUP(realifname, "tap0") < 0) return -1; } virCommandAddArg(cmd, "-s"); virCommandAddArgFormat(cmd, "%d:0,virtio-net,%s,mac=%s", net->info.addr.pci.slot, realifname, virMacAddrFormat(&net->mac, macaddr)); VIR_FREE(realifname); return 0; }
unsigned long long virMemoryMaxValue(bool capped ATTRIBUTE_UNUSED) { return LLONG_MAX; } char * virSCSIDeviceGetSgName(const char *sysfs_prefix ATTRIBUTE_UNUSED, const char *adapter ATTRIBUTE_UNUSED, unsigned int bus ATTRIBUTE_UNUSED, unsigned int target ATTRIBUTE_UNUSED, unsigned long long unit ATTRIBUTE_UNUSED) { char *ret; ignore_value(VIR_STRDUP(ret, "sg0")); return ret; } int virSCSIVHostOpenVhostSCSI(int *vhostfd) { *vhostfd = STDERR_FILENO + 1; return 0; } int virNetDevTapCreate(char **ifname, const char *tunpath ATTRIBUTE_UNUSED, int *tapfd,
static virStorageVolPtr parallelsStorageVolCreateXMLFrom(virStoragePoolPtr pool, const char *xmldesc, virStorageVolPtr clonevol, unsigned int flags) { parallelsConnPtr privconn = pool->conn->privateData; virStoragePoolObjPtr privpool; virStorageVolDefPtr privvol = NULL, origvol = NULL; virStorageVolPtr ret = NULL; virCheckFlags(0, NULL); parallelsDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); parallelsDriverUnlock(privconn); if (privpool == NULL) { parallelsPoolNotFoundError(pool->name); goto cleanup; } if (!virStoragePoolObjIsActive(privpool)) { virReportError(VIR_ERR_OPERATION_INVALID, _("storage pool '%s' is not active"), pool->name); goto cleanup; } privvol = virStorageVolDefParseString(privpool->def, xmldesc); if (privvol == NULL) goto cleanup; if (virStorageVolDefFindByName(privpool, privvol->name)) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("storage vol already exists")); goto cleanup; } origvol = virStorageVolDefFindByName(privpool, clonevol->name); if (!origvol) { virReportError(VIR_ERR_NO_STORAGE_VOL, _("no storage vol with matching name '%s'"), clonevol->name); goto cleanup; } /* Make sure enough space */ if ((privpool->def->allocation + privvol->allocation) > privpool->def->capacity) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Not enough free space in pool for volume '%s'"), privvol->name); goto cleanup; } privpool->def->available = (privpool->def->capacity - privpool->def->allocation); if (VIR_REALLOC_N(privpool->volumes.objs, privpool->volumes.count + 1) < 0) { virReportOOMError(); goto cleanup; } if (virAsprintf(&privvol->target.path, "%s/%s", privpool->def->target.path, privvol->name) == -1) { virReportOOMError(); goto cleanup; } if (VIR_STRDUP(privvol->key, privvol->target.path) < 0) goto cleanup; privpool->def->allocation += privvol->allocation; privpool->def->available = (privpool->def->capacity - privpool->def->allocation); privpool->volumes.objs[privpool->volumes.count++] = privvol; ret = virGetStorageVol(pool->conn, privpool->def->name, privvol->name, privvol->key, NULL, NULL); privvol = NULL; cleanup: virStorageVolDefFree(privvol); if (privpool) virStoragePoolObjUnlock(privpool); return ret; }
static int udevListInterfacesByStatus(virConnectPtr conn, char **const names, int names_len, virUdevStatus status, virInterfaceObjListFilter filter) { struct udev_iface_driver *driverState = conn->interfacePrivateData; struct udev *udev = udev_ref(driverState->udev); struct udev_enumerate *enumerate = NULL; struct udev_list_entry *devices; struct udev_list_entry *dev_entry; int count = 0; enumerate = udevGetDevices(udev, status); if (!enumerate) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to get list of %s interfaces on host"), virUdevStatusString(status)); goto error; } /* Do the scan to load up the enumeration */ udev_enumerate_scan_devices(enumerate); /* Get a list we can walk */ devices = udev_enumerate_get_list_entry(enumerate); /* For each item so we can count */ udev_list_entry_foreach(dev_entry, devices) { struct udev_device *dev; const char *path; virInterfaceDefPtr def; /* Ensure we won't exceed the size of our array */ if (count > names_len) break; path = udev_list_entry_get_name(dev_entry); dev = udev_device_new_from_syspath(udev, path); def = udevGetMinimalDefForDevice(dev); if (filter(conn, def)) { if (VIR_STRDUP(names[count], udev_device_get_sysname(dev)) < 0) { udev_device_unref(dev); virInterfaceDefFree(def); goto error; } count++; } udev_device_unref(dev); virInterfaceDefFree(def); } udev_enumerate_unref(enumerate); udev_unref(udev); return count; error: if (enumerate) udev_enumerate_unref(enumerate); udev_unref(udev); for (names_len = 0; names_len < count; names_len++) VIR_FREE(names[names_len]); return -1; }
static int bhyveBuildNetArgStr(const virDomainDef *def, virCommandPtr cmd) { virDomainNetDefPtr net = NULL; char *brname = NULL; char *realifname = NULL; int *tapfd = NULL; if (def->nnets != 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("domain should have one and only one net defined")); return -1; } net = def->nets[0]; if (net) { int actualType = virDomainNetGetActualType(net); if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) { if (VIR_STRDUP(brname, virDomainNetGetActualBridgeName(net)) < 0) return -1; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Network type %d is not supported"), virDomainNetGetActualType(net)); return -1; } if (!net->ifname || STRPREFIX(net->ifname, VIR_NET_GENERATED_PREFIX) || strchr(net->ifname, '%')) { VIR_FREE(net->ifname); if (VIR_STRDUP(net->ifname, VIR_NET_GENERATED_PREFIX "%d") < 0) { VIR_FREE(brname); return -1; } } if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac, def->uuid, tapfd, 1, virDomainNetGetActualVirtPortProfile(net), virDomainNetGetActualVlan(net), VIR_NETDEV_TAP_CREATE_IFUP | VIR_NETDEV_TAP_CREATE_PERSIST) < 0) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } } realifname = virBhyveTapGetRealDeviceName(net->ifname); if (realifname == NULL) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } VIR_DEBUG("%s -> %s", net->ifname, realifname); /* hack on top of other hack: we need to set * interface to 'UP' again after re-opening to find its * name */ if (virNetDevSetOnline(net->ifname, true) != 0) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } virCommandAddArgList(cmd, "-s", "0:0,hostbridge", NULL); virCommandAddArg(cmd, "-s"); virCommandAddArgFormat(cmd, "1:0,virtio-net,%s", realifname); return 0; }
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK udevGetIfaceDefBond(struct udev *udev, struct udev_device *dev, const char *name, virInterfaceDef *ifacedef) { struct dirent **slave_list = NULL; int slave_count = 0; size_t i; const char *tmp_str; int tmp_int; /* Initial defaults */ ifacedef->data.bond.target = NULL; ifacedef->data.bond.nbItf = 0; ifacedef->data.bond.itf = NULL; /* Set the bond specifics */ tmp_str = udev_device_get_sysattr_value(dev, "bonding/downdelay"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/downdelay' for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str, NULL, 10, &tmp_int) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bonding/downdelay' '%s' for '%s'"), tmp_str, name); goto error; } ifacedef->data.bond.downdelay = tmp_int; tmp_str = udev_device_get_sysattr_value(dev, "bonding/updelay"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/updelay' for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str, NULL, 10, &tmp_int) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bonding/updelay' '%s' for '%s'"), tmp_str, name); goto error; } ifacedef->data.bond.updelay = tmp_int; tmp_str = udev_device_get_sysattr_value(dev, "bonding/miimon"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/miimon' for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str, NULL, 10, &tmp_int) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bonding/miimon' '%s' for '%s'"), tmp_str, name); goto error; } ifacedef->data.bond.frequency = tmp_int; tmp_str = udev_device_get_sysattr_value(dev, "bonding/arp_interval"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/arp_interval' for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str, NULL, 10, &tmp_int) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bonding/arp_interval' '%s' for '%s'"), tmp_str, name); goto error; } ifacedef->data.bond.interval = tmp_int; /* bonding/mode is in the format: "balance-rr 0" so we find the * space and increment the pointer to get the number and convert * it to an interger. libvirt uses 1 through 7 while the raw * number is 0 through 6 so increment it by 1. */ tmp_str = udev_device_get_sysattr_value(dev, "bonding/mode"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/mode' for '%s'"), name); goto error; } tmp_str = strchr(tmp_str, ' '); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid format for 'bonding/mode' for '%s'"), name); goto error; } if (strlen(tmp_str) < 2) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unable to find correct value in 'bonding/mode' for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str + 1, NULL, 10, &tmp_int) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bonding/mode' '%s' for '%s'"), tmp_str, name); goto error; } ifacedef->data.bond.mode = tmp_int + 1; /* bonding/arp_validate is in the format: "none 0" so we find the * space and increment the pointer to get the number and convert * it to an interger. */ tmp_str = udev_device_get_sysattr_value(dev, "bonding/arp_validate"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/arp_validate' for '%s'"), name); goto error; } tmp_str = strchr(tmp_str, ' '); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid format for 'bonding/arp_validate' for '%s'"), name); goto error; } if (strlen(tmp_str) < 2) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unable to find correct value in 'bonding/arp_validate' " "for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str + 1, NULL, 10, &tmp_int) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bonding/arp_validate' '%s' for '%s'"), tmp_str, name); goto error; } ifacedef->data.bond.validate = tmp_int; /* bonding/use_carrier is 0 or 1 and libvirt stores it as 1 or 2. */ tmp_str = udev_device_get_sysattr_value(dev, "bonding/use_carrier"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/use_carrier' for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str, NULL, 10, &tmp_int) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bonding/use_carrier' '%s' for '%s'"), tmp_str, name); goto error; } ifacedef->data.bond.carrier = tmp_int + 1; /* MII or ARP Monitoring is based on arp_interval and miimon. * if arp_interval > 0 then ARP monitoring is in play, if * miimon > 0 then MII monitoring is in play. */ if (ifacedef->data.bond.interval > 0) ifacedef->data.bond.monit = VIR_INTERFACE_BOND_MONIT_ARP; else if (ifacedef->data.bond.frequency > 0) ifacedef->data.bond.monit = VIR_INTERFACE_BOND_MONIT_MII; else ifacedef->data.bond.monit = VIR_INTERFACE_BOND_MONIT_NONE; tmp_str = udev_device_get_sysattr_value(dev, "bonding/arp_ip_target"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/arp_ip_target' for '%s'"), name); goto error; } if (VIR_STRDUP(ifacedef->data.bond.target, tmp_str) < 0) goto error; /* Slaves of the bond */ /* Get each slave in the bond */ slave_count = scandir(udev_device_get_syspath(dev), &slave_list, udevBondScanDirFilter, alphasort); if (slave_count < 0) { virReportSystemError(errno, _("Could not get slaves of bond '%s'"), name); goto error; } /* Allocate our list of slave devices */ if (VIR_ALLOC_N(ifacedef->data.bond.itf, slave_count) < 0) goto error; ifacedef->data.bond.nbItf = slave_count; for (i = 0; i < slave_count; i++) { /* Names are slave_interface. e.g. slave_eth0 * so we use the part after the _ */ tmp_str = strchr(slave_list[i]->d_name, '_'); if (!tmp_str || strlen(tmp_str) < 2) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid enslaved interface name '%s' seen for " "bond '%s'"), slave_list[i]->d_name, name); goto error; } /* go past the _ */ tmp_str++; ifacedef->data.bond.itf[i] = udevGetIfaceDef(udev, tmp_str); if (!ifacedef->data.bond.itf[i]) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not get interface information for '%s', which is " "a enslaved in bond '%s'"), slave_list[i]->d_name, name); goto error; } VIR_FREE(slave_list[i]); } VIR_FREE(slave_list); return 0; error: for (i = 0; slave_count != -1 && i < slave_count; i++) { VIR_FREE(slave_list[i]); } VIR_FREE(slave_list); return -1; }
/* Create a VM record from the XML description */ int createVMRecordFromXml(virConnectPtr conn, virDomainDefPtr def, xen_vm_record **record, xen_vm *vm) { char uuidStr[VIR_UUID_STRING_BUFLEN]; xen_string_string_map *strings = NULL; int device_number = 0; size_t i; *record = xen_vm_record_alloc(); if (VIR_STRDUP((*record)->name_label, def->name) < 0) goto error; if (def->uuid) { virUUIDFormat(def->uuid, uuidStr); if (VIR_STRDUP((*record)->uuid, uuidStr) < 0) goto error; } if (STREQ(def->os.type, "hvm")) { char *boot_order = NULL; if (VIR_STRDUP((*record)->hvm_boot_policy, "BIOS order") < 0) goto error; if (def->os.nBootDevs != 0) boot_order = createXenAPIBootOrderString(def->os.nBootDevs, &def->os.bootDevs[0]); if (boot_order != NULL) { xen_string_string_map *hvm_boot_params = NULL; allocStringMap(&hvm_boot_params, (char *)"order", boot_order); (*record)->hvm_boot_params = hvm_boot_params; VIR_FREE(boot_order); } } else if (STREQ(def->os.type, "xen")) { if (VIR_STRDUP((*record)->pv_bootloader, "pygrub") < 0) goto error; if (def->os.kernel) { if (VIR_STRDUP((*record)->pv_kernel, def->os.kernel) < 0) goto error; } if (def->os.initrd) { if (VIR_STRDUP((*record)->pv_ramdisk, def->os.initrd) < 0) goto error; } if (def->os.cmdline) { if (VIR_STRDUP((*record)->pv_args, def->os.cmdline) < 0) goto error; } (*record)->hvm_boot_params = xen_string_string_map_alloc(0); } if (def->os.bootloaderArgs) if (VIR_STRDUP((*record)->pv_bootloader_args, def->os.bootloaderArgs) < 0) goto error; if (def->mem.cur_balloon) (*record)->memory_static_max = (int64_t) (def->mem.cur_balloon * 1024); if (def->mem.max_balloon) (*record)->memory_dynamic_max = (int64_t) (def->mem.max_balloon * 1024); else (*record)->memory_dynamic_max = (*record)->memory_static_max; if (def->maxvcpus) { (*record)->vcpus_max = (int64_t) def->maxvcpus; (*record)->vcpus_at_startup = (int64_t) def->vcpus; } if (def->onPoweroff) (*record)->actions_after_shutdown = actionShutdownLibvirt2XenapiEnum(def->onPoweroff); if (def->onReboot) (*record)->actions_after_reboot = actionShutdownLibvirt2XenapiEnum(def->onReboot); if (def->onCrash) (*record)->actions_after_crash = actionCrashLibvirt2XenapiEnum(def->onCrash); if (def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_DOMAIN_FEATURE_STATE_ON) allocStringMap(&strings, (char *)"acpi", (char *)"true"); if (def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_DOMAIN_FEATURE_STATE_ON) allocStringMap(&strings, (char *)"apic", (char *)"true"); if (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_DOMAIN_FEATURE_STATE_ON) allocStringMap(&strings, (char *)"pae", (char *)"true"); if (def->features[VIR_DOMAIN_FEATURE_HAP] == VIR_DOMAIN_FEATURE_STATE_ON) allocStringMap(&strings, (char *)"hap", (char *)"true"); if (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] == VIR_DOMAIN_FEATURE_STATE_ON) allocStringMap(&strings, (char *)"viridian", (char *)"true"); if (strings != NULL) (*record)->platform = strings; (*record)->vcpus_params = xen_string_string_map_alloc(0); (*record)->other_config = xen_string_string_map_alloc(0); (*record)->last_boot_cpu_flags = xen_string_string_map_alloc(0); (*record)->xenstore_data = xen_string_string_map_alloc(0); (*record)->hvm_shadow_multiplier = 1.000; if (!xen_vm_create(((struct _xenapiPrivate *)(conn->privateData))->session, vm, *record)) { xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL); return -1; } for (i = 0; i < def->nnets; i++) { if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE && def->nets[i]->data.bridge.brname) { char *mac; if (VIR_ALLOC_N(mac, VIR_MAC_STRING_BUFLEN) < 0) goto error; virMacAddrFormat(&def->nets[i]->mac, mac); if (createVifNetwork(conn, *vm, device_number, def->nets[i]->data.bridge.brname, mac) < 0) { VIR_FREE(mac); virReportOOMError(); goto error; } device_number++; } } return 0; error: xen_vm_record_free(*record); return -1; }
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK udevGetIfaceDefBridge(struct udev *udev, struct udev_device *dev, const char *name, virInterfaceDef *ifacedef) { struct dirent **member_list = NULL; int member_count = 0; char *member_path; const char *tmp_str; int stp; size_t i; /* Set our type to Bridge */ ifacedef->type = VIR_INTERFACE_TYPE_BRIDGE; /* Retrieve the forward delay */ tmp_str = udev_device_get_sysattr_value(dev, "bridge/forward_delay"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bridge/forward_delay' for '%s'"), name); goto error; } if (VIR_STRDUP(ifacedef->data.bridge.delay, tmp_str) < 0) goto error; /* Retrieve Spanning Tree State. Valid values = -1, 0, 1 */ tmp_str = udev_device_get_sysattr_value(dev, "bridge/stp_state"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bridge/stp_state' for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str, NULL, 10, &stp) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bridge/stp_state' '%s' for '%s'"), tmp_str, name); goto error; } switch (stp) { case -1: case 0: case 1: ifacedef->data.bridge.stp = stp; break; default: virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid STP state value %d received for '%s'. Must be " "-1, 0, or 1."), stp, name); goto error; } /* Members of the bridge */ if (virAsprintf(&member_path, "%s/%s", udev_device_get_syspath(dev), "brif") < 0) goto error; /* Get each member of the bridge */ member_count = scandir(member_path, &member_list, udevBridgeScanDirFilter, alphasort); /* Don't need the path anymore */ VIR_FREE(member_path); if (member_count < 0) { virReportSystemError(errno, _("Could not get members of bridge '%s'"), name); goto error; } /* Allocate our list of member devices */ if (VIR_ALLOC_N(ifacedef->data.bridge.itf, member_count) < 0) goto error; ifacedef->data.bridge.nbItf = member_count; /* Get the interface defintions for each member of the bridge */ for (i = 0; i < member_count; i++) { ifacedef->data.bridge.itf[i] = udevGetIfaceDef(udev, member_list[i]->d_name); if (!ifacedef->data.bridge.itf[i]) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not get interface information for '%s', which is " "a member of bridge '%s'"), member_list[i]->d_name, name); goto error; } VIR_FREE(member_list[i]); } VIR_FREE(member_list); return 0; error: for (i = 0; member_count != -1 && i < member_count; i++) { VIR_FREE(member_list[i]); } VIR_FREE(member_list); return -1; }
static virIdentityPtr virNetServerClientCreateIdentity(virNetServerClientPtr client) { char *processid = NULL; char *processtime = NULL; char *username = NULL; char *userid = NULL; char *groupname = NULL; char *groupid = NULL; #if WITH_SASL char *saslname = NULL; #endif #if WITH_GNUTLS char *x509dname = NULL; #endif char *seccontext = NULL; virIdentityPtr ret = NULL; if (client->sock && virNetSocketIsLocal(client->sock)) { gid_t gid; uid_t uid; pid_t pid; unsigned long long timestamp; if (virNetSocketGetUNIXIdentity(client->sock, &uid, &gid, &pid, ×tamp) < 0) goto cleanup; if (!(username = virGetUserName(uid))) goto cleanup; if (virAsprintf(&userid, "%d", (int)uid) < 0) goto cleanup; if (!(groupname = virGetGroupName(gid))) goto cleanup; if (virAsprintf(&groupid, "%d", (int)gid) < 0) goto cleanup; if (virAsprintf(&processid, "%llu", (unsigned long long)pid) < 0) goto cleanup; if (virAsprintf(&processtime, "%llu", timestamp) < 0) goto cleanup; } #if WITH_SASL if (client->sasl) { const char *identity = virNetSASLSessionGetIdentity(client->sasl); if (VIR_STRDUP(saslname, identity) < 0) goto cleanup; } #endif #if WITH_GNUTLS if (client->tls) { const char *identity = virNetTLSSessionGetX509DName(client->tls); if (VIR_STRDUP(x509dname, identity) < 0) goto cleanup; } #endif if (client->sock && virNetSocketGetSELinuxContext(client->sock, &seccontext) < 0) goto cleanup; if (!(ret = virIdentityNew())) goto cleanup; if (username && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_USER_NAME, username) < 0) goto error; if (userid && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_USER_ID, userid) < 0) goto error; if (groupname && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_GROUP_NAME, groupname) < 0) goto error; if (groupid && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_GROUP_ID, groupid) < 0) goto error; if (processid && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_PROCESS_ID, processid) < 0) goto error; if (processtime && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_PROCESS_TIME, processtime) < 0) goto error; #if WITH_SASL if (saslname && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_SASL_USER_NAME, saslname) < 0) goto error; #endif #if WITH_GNUTLS if (x509dname && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_X509_DISTINGUISHED_NAME, x509dname) < 0) goto error; #endif if (seccontext && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_SELINUX_CONTEXT, seccontext) < 0) goto error; cleanup: VIR_FREE(username); VIR_FREE(userid); VIR_FREE(groupname); VIR_FREE(groupid); VIR_FREE(processid); VIR_FREE(processtime); VIR_FREE(seccontext); #if WITH_SASL VIR_FREE(saslname); #endif #if WITH_GNUTLS VIR_FREE(x509dname); #endif return ret; error: virObjectUnref(ret); ret = NULL; goto cleanup; }
/* Functions */ virCapsPtr virLXCDriverCapsInit(virLXCDriverPtr driver) { virCapsPtr caps; virCapsGuestPtr guest; virArch altArch; char *lxc_path = NULL; if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL) goto error; /* Some machines have problematic NUMA toplogy causing * unexpected failures. We don't want to break the lxc * driver in this scenario, so log errors & carry on */ if (nodeCapsInitNUMA(caps) < 0) { virCapabilitiesFreeNUMAInfo(caps); VIR_WARN("Failed to query host NUMA topology, disabling NUMA capabilities"); } /* Only probe for power management capabilities in the driver, * not in the emulator */ if (driver && virNodeSuspendGetTargetMask(&caps->host.powerMgmt) < 0) VIR_WARN("Failed to get host power management capabilities"); if (virGetHostUUID(caps->host.host_uuid)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot get the host uuid")); goto error; } if (!(lxc_path = virFileFindResource("libvirt_lxc", "src", LIBEXECDIR))) goto error; if ((guest = virCapabilitiesAddGuest(caps, "exe", caps->host.arch, lxc_path, NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, "lxc", NULL, NULL, 0, NULL) == NULL) goto error; /* On 64-bit hosts, we can use personality() to request a 32bit process */ if ((altArch = lxcContainerGetAlt32bitArch(caps->host.arch)) != VIR_ARCH_NONE) { if ((guest = virCapabilitiesAddGuest(caps, "exe", altArch, lxc_path, NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, "lxc", NULL, NULL, 0, NULL) == NULL) goto error; } VIR_FREE(lxc_path); if (driver) { /* Security driver data */ const char *doi, *model, *label, *type; doi = virSecurityManagerGetDOI(driver->securityManager); model = virSecurityManagerGetModel(driver->securityManager); label = virSecurityManagerGetBaseLabel(driver->securityManager, VIR_DOMAIN_VIRT_LXC); type = virDomainVirtTypeToString(VIR_DOMAIN_VIRT_LXC); /* Allocate the primary security driver for LXC. */ if (VIR_ALLOC(caps->host.secModels) < 0) goto error; caps->host.nsecModels = 1; if (VIR_STRDUP(caps->host.secModels[0].model, model) < 0) goto error; if (VIR_STRDUP(caps->host.secModels[0].doi, doi) < 0) goto error; if (label && virCapabilitiesHostSecModelAddBaseLabel(&caps->host.secModels[0], type, label) < 0) goto error; VIR_DEBUG("Initialized caps for security driver \"%s\" with " "DOI \"%s\"", model, doi); } else { VIR_INFO("No driver, not initializing security driver"); } return caps; error: VIR_FREE(lxc_path); virObjectUnref(caps); return NULL; }
/** * virSystemdCreateMachine: * @name: driver unique name of the machine * @drivername: name of the virt driver * @privileged: whether driver is running privileged or per user * @uuid: globally unique UUID of the machine * @rootdir: root directory of machine filesystem * @pidleader: PID of the leader process * @iscontainer: true if a container, false if a VM * @nnicindexes: number of network interface indexes in list * @nicindexes: list of network interface indexes * @partition: name of the slice to place the machine in * * Returns 0 on success, -1 on fatal error, or -2 if systemd-machine is not available */ int virSystemdCreateMachine(const char *name, const char *drivername, const unsigned char *uuid, const char *rootdir, pid_t pidleader, bool iscontainer, size_t nnicindexes, int *nicindexes, const char *partition) { int ret; DBusConnection *conn; char *creatorname = NULL; char *slicename = NULL; static int hasCreateWithNetwork = 1; if ((ret = virSystemdHasMachined()) < 0) return ret; if (!(conn = virDBusGetSystemBus())) return -1; ret = -1; if (virAsprintf(&creatorname, "libvirt-%s", drivername) < 0) goto cleanup; if (partition) { if (!(slicename = virSystemdMakeSliceName(partition))) goto cleanup; } else { if (VIR_STRDUP(slicename, "") < 0) goto cleanup; } /* * The systemd DBus APIs we're invoking have the * following signature(s) * * CreateMachineWithNetwork(in s name, * in ay id, * in s service, * in s class, * in u leader, * in s root_directory, * in ai nicindexes * in a(sv) scope_properties, * out o path); * * CreateMachine(in s name, * in ay id, * in s service, * in s class, * in u leader, * in s root_directory, * in a(sv) scope_properties, * out o path); * * @name a host unique name for the machine. shows up * in 'ps' listing & similar * * @id: a UUID of the machine, ideally matching /etc/machine-id * for containers * * @service: identifier of the client ie "libvirt-lxc" * * @class: either the string "container" or "vm" depending * on the type of machine * * @leader: main PID of the machine, either the host emulator * process, or the 'init' PID of the container * * @root_directory: the root directory of the container, if * this is known & visible in the host filesystem, or empty string * * @nicindexes: list of network interface indexes for the * host end of the VETH device pairs. * * @scope_properties:an array (not a dict!) of properties that are * passed on to PID 1 when creating a scope unit for your machine. * Will allow initial settings for the cgroup & similar. * * @path: a bus path returned for the machine object created, to * allow further API calls to be made against the object. * */ VIR_DEBUG("Attempting to create machine via systemd"); if (virAtomicIntGet(&hasCreateWithNetwork)) { virError error; memset(&error, 0, sizeof(error)); if (virDBusCallMethod(conn, NULL, &error, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "CreateMachineWithNetwork", "sayssusa&ia(sv)", name, 16, uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15], creatorname, iscontainer ? "container" : "vm", (unsigned int)pidleader, NULLSTR_EMPTY(rootdir), nnicindexes, nicindexes, 3, "Slice", "s", slicename, "After", "as", 1, "libvirtd.service", "Before", "as", 1, "virt-guest-shutdown.target") < 0) goto cleanup; if (error.level == VIR_ERR_ERROR) { if (virDBusErrorIsUnknownMethod(&error)) { VIR_INFO("CreateMachineWithNetwork isn't supported, switching " "to legacy CreateMachine method for systemd-machined"); virResetError(&error); virAtomicIntSet(&hasCreateWithNetwork, 0); /* Could re-structure without Using goto, but this * avoids another atomic read which would trigger * another memory barrier */ goto fallback; } virReportErrorObject(&error); virResetError(&error); goto cleanup; } } else { fallback: if (virDBusCallMethod(conn, NULL, NULL, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "CreateMachine", "sayssusa(sv)", name, 16, uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15], creatorname, iscontainer ? "container" : "vm", (unsigned int)pidleader, NULLSTR_EMPTY(rootdir), 3, "Slice", "s", slicename, "After", "as", 1, "libvirtd.service", "Before", "as", 1, "virt-guest-shutdown.target") < 0) goto cleanup; } ret = 0; cleanup: VIR_FREE(creatorname); VIR_FREE(slicename); return ret; }
static virDrvOpenStatus hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags) { virDrvOpenStatus result = VIR_DRV_OPEN_ERROR; char *plus; hypervPrivate *priv = NULL; char *username = NULL; char *password = NULL; virBuffer query = VIR_BUFFER_INITIALIZER; Msvm_ComputerSystem *computerSystem = NULL; virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR); /* Decline if the URI is NULL or the scheme is NULL */ if (conn->uri == NULL || conn->uri->scheme == NULL) return VIR_DRV_OPEN_DECLINED; /* Decline if the scheme is not hyperv */ plus = strchr(conn->uri->scheme, '+'); if (plus == NULL) { if (STRCASENEQ(conn->uri->scheme, "hyperv")) return VIR_DRV_OPEN_DECLINED; } else { if (plus - conn->uri->scheme != 6 || STRCASENEQLEN(conn->uri->scheme, "hyperv", 6)) { return VIR_DRV_OPEN_DECLINED; } virReportError(VIR_ERR_INVALID_ARG, _("Transport '%s' in URI scheme is not supported, try again " "without the transport part"), plus + 1); return VIR_DRV_OPEN_ERROR; } /* Require server part */ if (conn->uri->server == NULL) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("URI is missing the server part")); return VIR_DRV_OPEN_ERROR; } /* Require auth */ if (auth == NULL || auth->cb == NULL) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("Missing or invalid auth pointer")); return VIR_DRV_OPEN_ERROR; } /* Allocate per-connection private data */ if (VIR_ALLOC(priv) < 0) goto cleanup; if (hypervParseUri(&priv->parsedUri, conn->uri) < 0) goto cleanup; /* Set the port dependent on the transport protocol if no port is * specified. This allows us to rely on the port parameter being * correctly set when building URIs later on, without the need to * distinguish between the situations port == 0 and port != 0 */ if (conn->uri->port == 0) { if (STRCASEEQ(priv->parsedUri->transport, "https")) { conn->uri->port = 5986; } else { conn->uri->port = 5985; } } /* Request credentials */ if (conn->uri->user != NULL) { if (VIR_STRDUP(username, conn->uri->user) < 0) goto cleanup; } else { username = virAuthGetUsername(conn, auth, "hyperv", "administrator", conn->uri->server); if (username == NULL) { virReportError(VIR_ERR_AUTH_FAILED, "%s", _("Username request failed")); goto cleanup; } } password = virAuthGetPassword(conn, auth, "hyperv", username, conn->uri->server); if (password == NULL) { virReportError(VIR_ERR_AUTH_FAILED, "%s", _("Password request failed")); goto cleanup; } /* Initialize the openwsman connection */ priv->client = wsmc_create(conn->uri->server, conn->uri->port, "/wsman", priv->parsedUri->transport, username, password); if (priv->client == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create openwsman client")); goto cleanup; } if (wsmc_transport_init(priv->client, NULL) != 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not initialize openwsman transport")); goto cleanup; } /* FIXME: Currently only basic authentication is supported */ wsman_transport_set_auth_method(priv->client, "basic"); /* Check if the connection can be established and if the server has the * Hyper-V role installed. If the call to hypervGetMsvmComputerSystemList * succeeds than the connection has been established. If the returned list * is empty than the server isn't a Hyper-V server. */ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT); virBufferAddLit(&query, "where "); virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_PHYSICAL); if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) goto cleanup; if (computerSystem == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s is not a Hyper-V server"), conn->uri->server); goto cleanup; } conn->privateData = priv; priv = NULL; result = VIR_DRV_OPEN_SUCCESS; cleanup: hypervFreePrivate(&priv); VIR_FREE(username); VIR_FREE(password); hypervFreeObject(priv, (hypervObject *)computerSystem); return result; }
struct daemonConfig* daemonConfigNew(bool privileged ATTRIBUTE_UNUSED) { struct daemonConfig *data; char *localhost; int ret; if (VIR_ALLOC(data) < 0) return NULL; data->listen_tls = 1; data->listen_tcp = 0; if (VIR_STRDUP(data->tls_port, LIBVIRTD_TLS_PORT) < 0 || VIR_STRDUP(data->tcp_port, LIBVIRTD_TCP_PORT) < 0) goto error; /* Only default to PolicyKit if running as root */ #if WITH_POLKIT if (privileged) { data->auth_unix_rw = REMOTE_AUTH_POLKIT; data->auth_unix_ro = REMOTE_AUTH_POLKIT; } else { #endif data->auth_unix_rw = REMOTE_AUTH_NONE; data->auth_unix_ro = REMOTE_AUTH_NONE; #if WITH_POLKIT } #endif if (VIR_STRDUP(data->unix_sock_rw_perms, data->auth_unix_rw == REMOTE_AUTH_POLKIT ? "0777" : "0700") < 0 || VIR_STRDUP(data->unix_sock_ro_perms, "0777") < 0 || VIR_STRDUP(data->unix_sock_admin_perms, "0700") < 0) goto error; #if WITH_SASL data->auth_tcp = REMOTE_AUTH_SASL; #else data->auth_tcp = REMOTE_AUTH_NONE; #endif data->auth_tls = REMOTE_AUTH_NONE; data->mdns_adv = 0; data->min_workers = 5; data->max_workers = 20; data->max_clients = 5000; data->max_queued_clients = 1000; data->max_anonymous_clients = 20; data->prio_workers = 5; data->max_requests = 20; data->max_client_requests = 5; data->audit_level = 1; data->audit_logging = 0; data->keepalive_interval = 5; data->keepalive_count = 5; data->admin_min_workers = 5; data->admin_max_workers = 20; data->admin_max_clients = 5000; data->admin_max_queued_clients = 20; data->admin_max_client_requests = 5; data->admin_keepalive_interval = 5; data->admin_keepalive_count = 5; localhost = virGetHostname(); if (localhost == NULL) { /* we couldn't resolve the hostname; assume that we are * running in disconnected operation, and report a less * useful Avahi string */ ret = VIR_STRDUP(data->mdns_name, "Virtualization Host"); } else { char *tmp; /* Extract the host part of the potentially FQDN */ if ((tmp = strchr(localhost, '.'))) *tmp = '\0'; ret = virAsprintf(&data->mdns_name, "Virtualization Host %s", localhost); } VIR_FREE(localhost); if (ret < 0) goto error; return data; error: daemonConfigFree(data); return NULL; }
static char * hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags) { char *xml = NULL; hypervPrivate *priv = domain->conn->privateData; virDomainDefPtr def = NULL; char uuid_string[VIR_UUID_STRING_BUFLEN]; virBuffer query = VIR_BUFFER_INITIALIZER; Msvm_ComputerSystem *computerSystem = NULL; Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL; Msvm_ProcessorSettingData *processorSettingData = NULL; Msvm_MemorySettingData *memorySettingData = NULL; /* Flags checked by virDomainDefFormat */ if (VIR_ALLOC(def) < 0) goto cleanup; virUUIDFormat(domain->uuid, uuid_string); /* Get Msvm_ComputerSystem */ if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) goto cleanup; /* Get Msvm_VirtualSystemSettingData */ virBufferAsprintf(&query, "associators of " "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\"," "Name=\"%s\"} " "where AssocClass = Msvm_SettingsDefineState " "ResultClass = Msvm_VirtualSystemSettingData", uuid_string); if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query, &virtualSystemSettingData) < 0) { goto cleanup; } if (virtualSystemSettingData == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s for domain %s"), "Msvm_VirtualSystemSettingData", computerSystem->data->ElementName); goto cleanup; } /* Get Msvm_ProcessorSettingData */ virBufferAsprintf(&query, "associators of " "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} " "where AssocClass = Msvm_VirtualSystemSettingDataComponent " "ResultClass = Msvm_ProcessorSettingData", virtualSystemSettingData->data->InstanceID); if (hypervGetMsvmProcessorSettingDataList(priv, &query, &processorSettingData) < 0) { goto cleanup; } if (processorSettingData == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s for domain %s"), "Msvm_ProcessorSettingData", computerSystem->data->ElementName); goto cleanup; } /* Get Msvm_MemorySettingData */ virBufferAsprintf(&query, "associators of " "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} " "where AssocClass = Msvm_VirtualSystemSettingDataComponent " "ResultClass = Msvm_MemorySettingData", virtualSystemSettingData->data->InstanceID); if (hypervGetMsvmMemorySettingDataList(priv, &query, &memorySettingData) < 0) { goto cleanup; } if (memorySettingData == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s for domain %s"), "Msvm_MemorySettingData", computerSystem->data->ElementName); goto cleanup; } /* Fill struct */ def->virtType = VIR_DOMAIN_VIRT_HYPERV; if (hypervIsMsvmComputerSystemActive(computerSystem, NULL)) { def->id = computerSystem->data->ProcessID; } else { def->id = -1; } if (virUUIDParse(computerSystem->data->Name, def->uuid) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse UUID from string '%s'"), computerSystem->data->Name); return NULL; } if (VIR_STRDUP(def->name, computerSystem->data->ElementName) < 0) goto cleanup; if (VIR_STRDUP(def->description, virtualSystemSettingData->data->Notes) < 0) goto cleanup; virDomainDefSetMemoryInitial(def, memorySettingData->data->Limit * 1024); /* megabyte to kilobyte */ def->mem.cur_balloon = memorySettingData->data->VirtualQuantity * 1024; /* megabyte to kilobyte */ def->vcpus = processorSettingData->data->VirtualQuantity; def->maxvcpus = processorSettingData->data->VirtualQuantity; def->os.type = VIR_DOMAIN_OSTYPE_HVM; /* FIXME: devices section is totally missing */ xml = virDomainDefFormat(def, virDomainDefFormatConvertXMLFlags(flags)); cleanup: virDomainDefFree(def); hypervFreeObject(priv, (hypervObject *)computerSystem); hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); hypervFreeObject(priv, (hypervObject *)processorSettingData); hypervFreeObject(priv, (hypervObject *)memorySettingData); return xml; }
/* Allocate an array of malloc'd strings from the config file, filename * (used only in diagnostics), using handle "conf". Upon error, return -1 * and free any allocated memory. Otherwise, save the array in *list_arg * and return 0. */ static int remoteConfigGetStringList(virConfPtr conf, const char *key, char ***list_arg, const char *filename) { char **list; virConfValuePtr p = virConfGetValue(conf, key); if (!p) return 0; switch (p->type) { case VIR_CONF_STRING: if (VIR_ALLOC_N(list, 2) < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("failed to allocate memory for %s config list"), key); return -1; } if (VIR_STRDUP(list[0], p->str) < 0) { VIR_FREE(list); return -1; } list[1] = NULL; break; case VIR_CONF_LIST: { int len = 0; size_t i; virConfValuePtr pp; for (pp = p->list; pp; pp = pp->next) len++; if (VIR_ALLOC_N(list, 1+len) < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("failed to allocate memory for %s config list"), key); return -1; } for (i = 0, pp = p->list; pp; ++i, pp = pp->next) { if (pp->type != VIR_CONF_STRING) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("remoteReadConfigFile: %s: %s:" " must be a string or list of strings"), filename, key); VIR_FREE(list); return -1; } if (VIR_STRDUP(list[i], pp->str) < 0) { size_t j; for (j = 0; j < i; j++) VIR_FREE(list[j]); VIR_FREE(list); return -1; } } list[i] = NULL; break; } default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("remoteReadConfigFile: %s: %s:" " must be a string or list of strings"), filename, key); return -1; } *list_arg = list; return 0; }
static virStorageVolDefPtr parallelsStorageVolDefineXML(virStoragePoolObjPtr pool, const char *xmldesc, const char *xmlfile, bool is_new) { virStorageVolDefPtr privvol = NULL; virStorageVolDefPtr ret = NULL; char *xml_path = NULL; if (xmlfile) privvol = virStorageVolDefParseFile(pool->def, xmlfile); else privvol = virStorageVolDefParseString(pool->def, xmldesc); if (privvol == NULL) goto cleanup; if (virStorageVolDefFindByName(pool, privvol->name)) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("storage vol already exists")); goto cleanup; } if (is_new) { /* Make sure enough space */ if ((pool->def->allocation + privvol->allocation) > pool->def->capacity) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Not enough free space in pool for volume '%s'"), privvol->name); goto cleanup; } } if (VIR_REALLOC_N(pool->volumes.objs, pool->volumes.count + 1) < 0) { virReportOOMError(); goto cleanup; } if (virAsprintf(&privvol->target.path, "%s/%s", pool->def->target.path, privvol->name) < 0) { virReportOOMError(); goto cleanup; } if (VIR_STRDUP(privvol->key, privvol->target.path) < 0) goto cleanup; if (is_new) { xml_path = parallelsAddFileExt(privvol->target.path, ".xml"); if (!xml_path) goto cleanup; if (virXMLSaveFile(xml_path, NULL, "volume-create", xmldesc)) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Can't create file with volume description")); goto cleanup; } pool->def->allocation += privvol->allocation; pool->def->available = (pool->def->capacity - pool->def->allocation); } pool->volumes.objs[pool->volumes.count++] = privvol; ret = privvol; privvol = NULL; cleanup: virStorageVolDefFree(privvol); VIR_FREE(xml_path); return ret; }
static int virStorageBackendZFSCreateVol(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, virStorageVolDefPtr vol) { virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool); virCommandPtr cmd = NULL; int ret = -1; int volmode_needed = -1; if (vol->target.encryption != NULL) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("storage pool does not support encrypted " "volumes")); return -1; } vol->type = VIR_STORAGE_VOL_BLOCK; VIR_FREE(vol->target.path); if (virAsprintf(&vol->target.path, "%s/%s", def->target.path, vol->name) < 0) return -1; if (VIR_STRDUP(vol->key, vol->target.path) < 0) goto cleanup; volmode_needed = virStorageBackendZFSVolModeNeeded(); if (volmode_needed < 0) goto cleanup; /** * $ zfs create -o volmode=dev -V 10240K test/volname * $ zfs create -o volmode=dev -s -V 10240K test/volname * $ zfs create -o volmode=dev -s -o refreservation=1024K -V 10240K test/volname * * -o volmode=dev -- we want to get volumes exposed as cdev * devices. If we don't specify that zfs * will lookup vfs.zfs.vol.mode sysctl value * -s -- create a sparse volume * -o refreservation -- reserve the specified amount of space * -V -- tells to create a volume with the specified size */ cmd = virCommandNewArgList(ZFS, "create", NULL); if (volmode_needed) virCommandAddArgList(cmd, "-o", "volmode=dev", NULL); if (vol->target.capacity != vol->target.allocation) { virCommandAddArg(cmd, "-s"); if (vol->target.allocation > 0) { virCommandAddArg(cmd, "-o"); virCommandAddArgFormat(cmd, "refreservation=%lluK", VIR_DIV_UP(vol->target.allocation, 1024)); } vol->target.sparse = true; } virCommandAddArg(cmd, "-V"); virCommandAddArgFormat(cmd, "%lluK", VIR_DIV_UP(vol->target.capacity, 1024)); virCommandAddArgFormat(cmd, "%s/%s", def->source.name, vol->name); if (virCommandRun(cmd, NULL) < 0) goto cleanup; if (virStorageBackendZFSFindVols(pool, vol) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); return ret; }
static int qemuInitCgroup(virQEMUDriverPtr driver, virDomainObjPtr vm, size_t nnicindexes, int *nicindexes) { int ret = -1; qemuDomainObjPrivatePtr priv = vm->privateData; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); if (!virQEMUDriverIsPrivileged(driver)) goto done; if (!virCgroupAvailable()) goto done; virCgroupFree(&priv->cgroup); 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 (vm->def->resource->partition[0] != '/') { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Resource partition '%s' must start with '/'"), vm->def->resource->partition); goto cleanup; } /* * We need to do this because of systemd-machined, because * CreateMachine requires the name to be a valid hostname. */ priv->machineName = virSystemdMakeMachineName("qemu", vm->def->id, vm->def->name, virQEMUDriverIsPrivileged(driver)); if (!priv->machineName) goto cleanup; if (virCgroupNewMachine(priv->machineName, "qemu", vm->def->uuid, NULL, vm->pid, false, nnicindexes, nicindexes, vm->def->resource->partition, cfg->cgroupControllers, &priv->cgroup) < 0) { if (virCgroupNewIgnoreError()) goto done; goto cleanup; } done: ret = 0; cleanup: virObjectUnref(cfg); return ret; }