/* Debian/Ubuntu install disks are easy ... * * These files are added by the debian-cd program, and it is worth * looking at the source code to determine exact values, in * particular '/usr/share/debian-cd/tools/start_new_disc' * * XXX Architecture? We could parse it out of the product name * string, but that seems quite hairy. We could look for the names * of packages. Also note that some Debian install disks are * multiarch. */ static int check_debian_installer_root (guestfs_h *g, struct inspect_fs *fs) { fs->product_name = guestfs_int_first_line_of_file (g, "/.disk/info"); if (!fs->product_name) return -1; fs->type = OS_TYPE_LINUX; if (STRPREFIX (fs->product_name, "Ubuntu")) fs->distro = OS_DISTRO_UBUNTU; else if (STRPREFIX (fs->product_name, "Debian")) fs->distro = OS_DISTRO_DEBIAN; (void) guestfs_int_parse_major_minor (g, fs); if (guestfs_is_file (g, "/.disk/cd_type") > 0) { CLEANUP_FREE char *cd_type = guestfs_int_first_line_of_file (g, "/.disk/cd_type"); if (!cd_type) return -1; if (STRPREFIX (cd_type, "dvd/single") || STRPREFIX (cd_type, "full_cd/single")) { fs->is_multipart_disk = 0; fs->is_netinst_disk = 0; } else if (STRPREFIX (cd_type, "dvd") || STRPREFIX (cd_type, "full_cd")) { fs->is_multipart_disk = 1; fs->is_netinst_disk = 0; } else if (STRPREFIX (cd_type, "not_complete")) { fs->is_multipart_disk = 0; fs->is_netinst_disk = 1; } } return 0; }
static int xenParseXLDiskSrc(virDomainDiskDefPtr disk, char *srcstr) { char *tmpstr = NULL; int ret = -1; if (STRPREFIX(srcstr, "rbd:")) { if (!(tmpstr = virStringReplace(srcstr, "\\\\", "\\"))) goto cleanup; virDomainDiskSetType(disk, VIR_STORAGE_TYPE_NETWORK); disk->src->protocol = VIR_STORAGE_NET_PROTOCOL_RBD; ret = virStorageSourceParseRBDColonString(tmpstr, disk->src); } else { if (virDomainDiskSetSource(disk, srcstr) < 0) goto cleanup; ret = 0; } cleanup: VIR_FREE(tmpstr); return ret; }
static bool qemuHostdevHostSupportsPassthroughVFIO(void) { DIR *iommuDir = NULL; struct dirent *iommuGroup = NULL; bool ret = false; /* condition 1 - /sys/kernel/iommu_groups/ contains entries */ if (!(iommuDir = opendir("/sys/kernel/iommu_groups/"))) goto cleanup; while ((iommuGroup = readdir(iommuDir))) { /* skip ./ ../ */ if (STRPREFIX(iommuGroup->d_name, ".")) continue; /* assume we found a group */ break; } if (!iommuGroup) goto cleanup; /* okay, iommu is on and recognizes groups */ /* condition 2 - /dev/vfio/vfio exists */ if (!virFileExists("/dev/vfio/vfio")) goto cleanup; ret = true; cleanup: if (iommuDir) closedir(iommuDir); return ret; }
/* Split "/dev/VG/LV" into "VG" and "LV". This function should * probably do more checks. */ int vg_lv_parse (const char *device, char **vg, char **lv) { if (STRPREFIX (device, "/dev/")) device += 5; const char *p = strchr (device, '/'); if (p == NULL) return -1; if (vg) { *vg = strndup (device, p - device); if (*vg == NULL) error (EXIT_FAILURE, errno, "strndup"); } if (lv) { *lv = strdup (p+1); if (*lv == NULL) error (EXIT_FAILURE, errno, "strndup"); } return 0; }
/** * virNumaGetPages: * @node: NUMA node id * @pages_size: list of pages supported on @node * @pages_avail: list of the pool sizes on @node * @pages_free: list of free pages on @node * @npages: the lists size * * For given NUMA node fetch info on pages. The size of pages * (e.g. 4K, 2M, 1G) is stored into @pages_size, the size of the * pool is then stored into @pages_avail and the number of free * pages in the pool is stored into @pages_free. * * If you're interested only in some lists, pass NULL to the * other ones. * * As a special case, if @node == -1, overall info is fetched * from the system. * * Returns 0 on success, -1 otherwise. */ int virNumaGetPages(int node, unsigned int **pages_size, unsigned int **pages_avail, unsigned int **pages_free, size_t *npages) { int ret = -1; char *path = NULL; DIR *dir = NULL; int direrr = 0; struct dirent *entry; unsigned int *tmp_size = NULL, *tmp_avail = NULL, *tmp_free = NULL; unsigned int ntmp = 0; size_t i; bool exchange; long system_page_size; unsigned long long huge_page_sum = 0; /* sysconf() returns page size in bytes, * but we are storing the page size in kibibytes. */ system_page_size = virGetSystemPageSizeKB(); /* Query huge pages at first. * On Linux systems, the huge pages pool cuts off the available memory and * is always shown as used memory. Here, however, we want to report * slightly different information. So we take the total memory on a node * and subtract memory taken by the huge pages. */ if (virNumaGetHugePageInfoPath(&path, node, 0, NULL) < 0) goto cleanup; if (!(dir = opendir(path))) { /* It's okay if the @path doesn't exist. Maybe we are running on * system without huge pages support where the path may not exist. */ if (errno != ENOENT) { virReportSystemError(errno, _("unable to open path: %s"), path); goto cleanup; } } while (dir && (direrr = virDirRead(dir, &entry, path)) > 0) { const char *page_name = entry->d_name; unsigned int page_size, page_avail = 0, page_free = 0; char *end; /* Just to give you a hint, we're dealing with this: * hugepages-2048kB/ or hugepages-1048576kB/ */ if (!STRPREFIX(entry->d_name, HUGEPAGES_PREFIX)) continue; page_name += strlen(HUGEPAGES_PREFIX); if (virStrToLong_ui(page_name, &end, 10, &page_size) < 0 || STRCASENEQ(end, "kB")) { virReportError(VIR_ERR_INTERNAL_ERROR, _("unable to parse %s"), entry->d_name); goto cleanup; } if (virNumaGetHugePageInfo(node, page_size, &page_avail, &page_free) < 0) goto cleanup; if (VIR_REALLOC_N(tmp_size, ntmp + 1) < 0 || VIR_REALLOC_N(tmp_avail, ntmp + 1) < 0 || VIR_REALLOC_N(tmp_free, ntmp + 1) < 0) goto cleanup; tmp_size[ntmp] = page_size; tmp_avail[ntmp] = page_avail; tmp_free[ntmp] = page_free; ntmp++; /* page_size is in kibibytes while we want huge_page_sum * in just bytes. */ huge_page_sum += 1024 * page_size * page_avail; } if (direrr < 0) goto cleanup; /* Now append the ordinary system pages */ if (VIR_REALLOC_N(tmp_size, ntmp + 1) < 0 || VIR_REALLOC_N(tmp_avail, ntmp + 1) < 0 || VIR_REALLOC_N(tmp_free, ntmp + 1) < 0) goto cleanup; if (virNumaGetPageInfo(node, system_page_size, huge_page_sum, &tmp_avail[ntmp], &tmp_free[ntmp]) < 0) goto cleanup; tmp_size[ntmp] = system_page_size; ntmp++; /* Just to produce nice output, sort the arrays by increasing page size */ do { exchange = false; for (i = 0; i < ntmp -1; i++) { if (tmp_size[i] > tmp_size[i + 1]) { exchange = true; SWAP(tmp_size[i], tmp_size[i + 1]); SWAP(tmp_avail[i], tmp_avail[i + 1]); SWAP(tmp_free[i], tmp_free[i + 1]); } } } while (exchange); if (pages_size) { *pages_size = tmp_size; tmp_size = NULL; } if (pages_avail) { *pages_avail = tmp_avail; tmp_avail = NULL; } if (pages_free) { *pages_free = tmp_free; tmp_free = NULL; } *npages = ntmp; ret = 0; cleanup: VIR_FREE(tmp_free); VIR_FREE(tmp_avail); VIR_FREE(tmp_size); if (dir) closedir(dir); VIR_FREE(path); return ret; }
static int xenParseXLUSB(virConfPtr conf, virDomainDefPtr def) { virConfValuePtr list = virConfGetValue(conf, "usbdev"); virDomainHostdevDefPtr hostdev = NULL; if (list && list->type == VIR_CONF_LIST) { list = list->list; while (list) { char bus[3]; char device[3]; char *key; int busNum; int devNum; bus[0] = device[0] = '\0'; if ((list->type != VIR_CONF_STRING) || (list->str == NULL)) goto skipusb; /* usbdev=['hostbus=1,hostaddr=3'] */ key = list->str; while (key) { char *data; char *nextkey = strchr(key, ','); if (!(data = strchr(key, '='))) goto skipusb; data++; if (STRPREFIX(key, "hostbus=")) { int len = nextkey ? (nextkey - data) : sizeof(bus) - 1; if (virStrncpy(bus, data, len, sizeof(bus)) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("bus %s too big for destination"), data); goto skipusb; } } else if (STRPREFIX(key, "hostaddr=")) { int len = nextkey ? (nextkey - data) : sizeof(device) - 1; if (virStrncpy(device, data, len, sizeof(device)) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("device %s too big for destination"), data); goto skipusb; } } while (nextkey && (nextkey[0] == ',' || nextkey[0] == ' ' || nextkey[0] == '\t')) nextkey++; key = nextkey; } if (virStrToLong_i(bus, NULL, 16, &busNum) < 0) goto skipusb; if (virStrToLong_i(device, NULL, 16, &devNum) < 0) goto skipusb; if (!(hostdev = virDomainHostdevDefAlloc(NULL))) return -1; hostdev->managed = false; hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB; hostdev->source.subsys.u.usb.bus = busNum; hostdev->source.subsys.u.usb.device = devNum; if (VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, hostdev) < 0) { virDomainHostdevDefFree(hostdev); return -1; } skipusb: list = list->next; } } return 0; }
static int virLockManagerLockDaemonAddResource(virLockManagerPtr lock, unsigned int type, const char *name, size_t nparams, virLockManagerParamPtr params, unsigned int flags) { virLockManagerLockDaemonPrivatePtr priv = lock->privateData; char *newName = NULL; char *newLockspace = NULL; bool autoCreate = false; virCheckFlags(VIR_LOCK_MANAGER_RESOURCE_READONLY | VIR_LOCK_MANAGER_RESOURCE_SHARED, -1); if (flags & VIR_LOCK_MANAGER_RESOURCE_READONLY) return 0; switch (type) { case VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK: if (params || nparams) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unexpected parameters for disk resource")); return -1; } if (!driver->autoDiskLease) { if (!(flags & (VIR_LOCK_MANAGER_RESOURCE_SHARED | VIR_LOCK_MANAGER_RESOURCE_READONLY))) priv->hasRWDisks = true; return 0; } /* XXX we should somehow pass in TYPE=BLOCK info * from the domain_lock code, instead of assuming /dev */ if (STRPREFIX(name, "/dev") && driver->lvmLockSpaceDir) { VIR_DEBUG("Trying to find an LVM UUID for %s", name); if (virStorageFileGetLVMKey(name, &newName) < 0) goto error; if (newName) { VIR_DEBUG("Got an LVM UUID %s for %s", newName, name); if (!(newLockspace = strdup(driver->lvmLockSpaceDir))) goto no_memory; autoCreate = true; break; } virResetLastError(); /* Fallback to generic non-block code */ } if (STRPREFIX(name, "/dev") && driver->scsiLockSpaceDir) { VIR_DEBUG("Trying to find an SCSI ID for %s", name); if (virStorageFileGetSCSIKey(name, &newName) < 0) goto error; if (newName) { VIR_DEBUG("Got an SCSI ID %s for %s", newName, name); if (!(newLockspace = strdup(driver->scsiLockSpaceDir))) goto no_memory; autoCreate = true; break; } virResetLastError(); /* Fallback to generic non-block code */ } if (driver->fileLockSpaceDir) { if (!(newLockspace = strdup(driver->fileLockSpaceDir))) goto no_memory; if (!(newName = virLockManagerLockDaemonDiskLeaseName(name))) goto no_memory; autoCreate = true; VIR_DEBUG("Using indirect lease %s for %s", newName, name); } else { if (!(newLockspace = strdup(""))) goto no_memory; if (!(newName = strdup(name))) goto no_memory; VIR_DEBUG("Using direct lease for %s", name); } break; case VIR_LOCK_MANAGER_RESOURCE_TYPE_LEASE: { size_t i; char *path = NULL; char *lockspace = NULL; for (i = 0 ; i < nparams ; i++) { if (STREQ(params[i].key, "offset")) { if (params[i].value.ul != 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Offset must be zero for this lock manager")); return -1; } } else if (STREQ(params[i].key, "lockspace")) { lockspace = params[i].value.str; } else if (STREQ(params[i].key, "path")) { path = params[i].value.str; } else { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected parameter %s for lease resource"), params[i].key); return -1; } } if (!path || !lockspace) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing path or lockspace for lease resource")); return -1; } if (virAsprintf(&newLockspace, "%s/%s", path, lockspace) < 0) { virReportOOMError(); return -1; } if (!(newName = strdup(name))) goto no_memory; } break; default: virReportError(VIR_ERR_INTERNAL_ERROR, _("Unknown lock manager object type %d"), type); return -1; } if (VIR_EXPAND_N(priv->resources, priv->nresources, 1) < 0) goto no_memory; priv->resources[priv->nresources-1].lockspace = newLockspace; priv->resources[priv->nresources-1].name = newName; if (flags & VIR_LOCK_MANAGER_RESOURCE_SHARED) priv->resources[priv->nresources-1].flags |= VIR_LOCK_SPACE_PROTOCOL_ACQUIRE_RESOURCE_SHARED; if (autoCreate) priv->resources[priv->nresources-1].flags |= VIR_LOCK_SPACE_PROTOCOL_ACQUIRE_RESOURCE_AUTOCREATE; return 0; no_memory: virReportOOMError(); error: VIR_FREE(newLockspace); VIR_FREE(newName); return -1; }
static int testCompareXMLToArgvFiles(const char *xml, const char *cmdline, virBitmapPtr 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(driver.caps, xml, QEMU_EXPECTED_VIRT_TYPES, VIR_DOMAIN_XML_INACTIVE))) 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 (!(emulator = strdup(vmdef->emulator + 1))) goto fail; free(vmdef->emulator); vmdef->emulator = NULL; if (virAsprintf(&vmdef->emulator, "%s/qemuxml2argvdata/%s", abs_srcdir, emulator) < 0) goto fail; } if (qemuCapsGet(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; qemuCapsSetList(extraFlags, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, QEMU_CAPS_LAST); if (qemudCanonicalizeMachine(&driver, vmdef) < 0) goto fail; if (qemuCapsGet(extraFlags, QEMU_CAPS_DEVICE)) { qemuDomainPCIAddressSetPtr pciaddrs; if (!(pciaddrs = qemuDomainPCIAddressSetCreate(vmdef))) goto fail; if (qemuAssignDevicePCISlots(vmdef, pciaddrs) < 0) goto fail; qemuDomainPCIAddressSetFree(pciaddrs); } free(virtTestLogContentAndReset()); virResetLastError(); /* We do not call qemuCapsExtractVersionInfo() before calling * qemuBuildCommandLine(), so we should set QEMU_CAPS_PCI_MULTIBUS for * x86_64 and i686 architectures here. */ if (STREQLEN(vmdef->os.arch, "x86_64", 6) || STREQLEN(vmdef->os.arch, "i686", 4)) { qemuCapsSet(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_VM_OP_NO_OP))) goto fail; 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: free(log); free(emulator); free(expectargv); free(actualargv); virCommandFree(cmd); virDomainDefFree(vmdef); virUnrefConnect(conn); return ret; }
static virStorageVolPtr esxStorageVolLookupByKey(virConnectPtr conn, const char *key) { virStorageVolPtr volume = NULL; esxPrivate *priv = conn->privateData; esxVI_String *propertyNameList = NULL; esxVI_ObjectContent *datastoreList = NULL; esxVI_ObjectContent *datastore = NULL; char *datastoreName = NULL; esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL; esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL; char *directoryAndFileName = NULL; size_t length; char *datastorePath = NULL; char *volumeName = NULL; esxVI_FileInfo *fileInfo = NULL; char *uuid_string = NULL; char key_candidate[VIR_UUID_STRING_BUFLEN] = ""; if (STRPREFIX(key, "[")) { /* Key is probably a datastore path */ return esxStorageVolLookupByPath(conn, key); } if (!priv->primary->hasQueryVirtualDiskUuid) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("QueryVirtualDiskUuid not available, " "cannot lookup storage volume by UUID")); return NULL; } /* Lookup all datastores */ if (esxVI_String_AppendValueToList(&propertyNameList, "summary.name") < 0 || esxVI_LookupDatastoreList(priv->primary, propertyNameList, &datastoreList) < 0) { goto cleanup; } for (datastore = datastoreList; datastore; datastore = datastore->_next) { datastoreName = NULL; if (esxVI_GetStringValue(datastore, "summary.name", &datastoreName, esxVI_Occurrence_RequiredItem) < 0) { goto cleanup; } /* Lookup datastore content */ esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList); if (esxVI_LookupDatastoreContentByDatastoreName (priv->primary, datastoreName, &searchResultsList) < 0) { goto cleanup; } /* Interpret search result */ for (searchResults = searchResultsList; searchResults; searchResults = searchResults->_next) { VIR_FREE(directoryAndFileName); if (esxUtil_ParseDatastorePath(searchResults->folderPath, NULL, NULL, &directoryAndFileName) < 0) { goto cleanup; } /* Strip trailing separators */ length = strlen(directoryAndFileName); while (length > 0 && directoryAndFileName[length - 1] == '/') { directoryAndFileName[length - 1] = '\0'; --length; } /* Build datastore path and query the UUID */ for (fileInfo = searchResults->file; fileInfo; fileInfo = fileInfo->_next) { VIR_FREE(datastorePath); if (length < 1) { if (VIR_STRDUP(volumeName, fileInfo->path) < 0) goto cleanup; } else if (virAsprintf(&volumeName, "%s/%s", directoryAndFileName, fileInfo->path) < 0) { goto cleanup; } if (virAsprintf(&datastorePath, "[%s] %s", datastoreName, volumeName) < 0) goto cleanup; if (!esxVI_VmDiskFileInfo_DynamicCast(fileInfo)) { /* Only a VirtualDisk has a UUID */ continue; } VIR_FREE(uuid_string); if (esxVI_QueryVirtualDiskUuid (priv->primary, datastorePath, priv->primary->datacenter->_reference, &uuid_string) < 0) { goto cleanup; } if (esxUtil_ReformatUuid(uuid_string, key_candidate) < 0) goto cleanup; if (STREQ(key, key_candidate)) { /* Found matching UUID */ volume = virGetStorageVol(conn, datastoreName, volumeName, key, &esxStorageBackendVMFS, NULL); goto cleanup; } } } } cleanup: esxVI_String_Free(&propertyNameList); esxVI_ObjectContent_Free(&datastoreList); esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList); VIR_FREE(directoryAndFileName); VIR_FREE(datastorePath); VIR_FREE(volumeName); VIR_FREE(uuid_string); return volume; }
/* ppc64 parser. * Format : PowerPC <machine> <description> */ static int qemuCapsParsePPCModels(const char *output, unsigned int *retcount, const char ***retcpus) { const char *p = output; const char *next; unsigned int count = 0; const char **cpus = NULL; int i, ret = -1; do { const char *t; if ((next = strchr(p, '\n'))) next++; if (!STRPREFIX(p, "PowerPC ")) continue; /* Skip the preceding sub-string "PowerPC " */ p += 8; /*Malformed string, does not obey the format 'PowerPC <model> <desc>'*/ if (!(t = strchr(p, ' ')) || (next && t >= next)) continue; if (*p == '\0') break; if (*p == '\n') continue; if (retcpus) { unsigned int len; if (VIR_REALLOC_N(cpus, count + 1) < 0) { virReportOOMError(); goto cleanup; } len = t - p - 1; if (!(cpus[count] = strndup(p, len))) { virReportOOMError(); goto cleanup; } } count++; } while ((p = next)); if (retcount) *retcount = count; if (retcpus) { *retcpus = cpus; cpus = NULL; } ret = 0; cleanup: if (cpus) { for (i = 0; i < count; i++) VIR_FREE(cpus[i]); VIR_FREE(cpus); } return ret; }
/* Format is: * <machine> <desc> [(default)|(alias of <canonical>)] */ static int qemuCapsParseMachineTypesStr(const char *output, virCapsGuestMachinePtr **machines, int *nmachines) { const char *p = output; const char *next; virCapsGuestMachinePtr *list = NULL; int nitems = 0; do { const char *t; virCapsGuestMachinePtr machine; if ((next = strchr(p, '\n'))) ++next; if (STRPREFIX(p, "Supported machines are:")) continue; if (!(t = strchr(p, ' ')) || (next && t >= next)) continue; if (VIR_ALLOC(machine) < 0) goto no_memory; if (!(machine->name = strndup(p, t - p))) { VIR_FREE(machine); goto no_memory; } if (VIR_REALLOC_N(list, nitems + 1) < 0) { VIR_FREE(machine->name); VIR_FREE(machine); goto no_memory; } p = t; if (!(t = strstr(p, "(default)")) || (next && t >= next)) { list[nitems++] = machine; } else { /* put the default first in the list */ memmove(list + 1, list, sizeof(*list) * nitems); list[0] = machine; nitems++; } if ((t = strstr(p, "(alias of ")) && (!next || t < next)) { p = t + strlen("(alias of "); if (!(t = strchr(p, ')')) || (next && t >= next)) continue; if (!(machine->canonical = strndup(p, t - p))) goto no_memory; } } while ((p = next)); *machines = list; *nmachines = nitems; return 0; no_memory: virReportOOMError(); virCapabilitiesFreeMachines(list, nitems); return -1; }
int linuxNodeGetCPUStats(FILE *procstat, int cpuNum, virNodeCPUStatsPtr params, int *nparams) { int ret = -1; char line[1024]; unsigned long long usr, ni, sys, idle, iowait; unsigned long long irq, softirq, steal, guest, guest_nice; char cpu_header[3 + INT_BUFSIZE_BOUND(cpuNum)]; if ((*nparams) == 0) { /* Current number of cpu stats supported by linux */ *nparams = LINUX_NB_CPU_STATS; ret = 0; goto cleanup; } if ((*nparams) != LINUX_NB_CPU_STATS) { nodeReportError(VIR_ERR_INVALID_ARG, "%s", _("Invalid parameter count")); goto cleanup; } if (cpuNum == VIR_NODE_CPU_STATS_ALL_CPUS) { strcpy(cpu_header, "cpu"); } else { snprintf(cpu_header, sizeof(cpu_header), "cpu%d", cpuNum); } while (fgets(line, sizeof(line), procstat) != NULL) { char *buf = line; if (STRPREFIX(buf, cpu_header)) { /* aka logical CPU time */ int i; if (sscanf(buf, "%*s %llu %llu %llu %llu %llu" // user ~ iowait "%llu %llu %llu %llu %llu", // irq ~ guest_nice &usr, &ni, &sys, &idle, &iowait, &irq, &softirq, &steal, &guest, &guest_nice) < 4) { continue; } for (i = 0; i < *nparams; i++) { virNodeCPUStatsPtr param = ¶ms[i]; switch (i) { case 0: /* fill kernel cpu time here */ if (virStrcpyStatic(param->field, VIR_NODE_CPU_STATS_KERNEL) == NULL) { nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Field kernel cpu time too long for destination")); goto cleanup; } param->value = (sys + irq + softirq) * TICK_TO_NSEC; break; case 1: /* fill user cpu time here */ if (virStrcpyStatic(param->field, VIR_NODE_CPU_STATS_USER) == NULL) { nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Field kernel cpu time too long for destination")); goto cleanup; } param->value = (usr + ni) * TICK_TO_NSEC; break; case 2: /* fill idle cpu time here */ if (virStrcpyStatic(param->field, VIR_NODE_CPU_STATS_IDLE) == NULL) { nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Field kernel cpu time too long for destination")); goto cleanup; } param->value = idle * TICK_TO_NSEC; break; case 3: /* fill iowait cpu time here */ if (virStrcpyStatic(param->field, VIR_NODE_CPU_STATS_IOWAIT) == NULL) { nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Field kernel cpu time too long for destination")); goto cleanup; } param->value = iowait * TICK_TO_NSEC; break; default: break; /* should not hit here */ } } ret = 0; goto cleanup; } } nodeReportError(VIR_ERR_INVALID_ARG, "%s", _("Invalid cpu number")); cleanup: return ret; }
int linuxNodeInfoCPUPopulate(FILE *cpuinfo, const char *sysfs_cpudir, virNodeInfoPtr nodeinfo) { char line[1024]; DIR *cpudir = NULL; struct dirent *cpudirent = NULL; unsigned int cpu; unsigned long core, sock, cur_threads; cpu_set_t core_mask; cpu_set_t socket_mask; int online; nodeinfo->cpus = 0; nodeinfo->mhz = 0; nodeinfo->cores = 0; nodeinfo->nodes = 1; # if HAVE_NUMACTL if (numa_available() >= 0) nodeinfo->nodes = numa_max_node() + 1; # endif if (!virStrcpyStatic(sysfs_path, sysfs_cpudir)) { virReportSystemError(errno, _("cannot copy %s"), sysfs_cpudir); return -1; } /* NB: It is impossible to fill our nodes, since cpuinfo * has no knowledge of NUMA nodes */ /* NOTE: hyperthreads are ignored here; they are parsed out of /sys */ while (fgets(line, sizeof(line), cpuinfo) != NULL) { # if defined(__x86_64__) || \ defined(__amd64__) || \ defined(__i386__) char *buf = line; if (STRPREFIX(buf, "cpu MHz")) { char *p; unsigned int ui; buf += 9; while (*buf && c_isspace(*buf)) buf++; if (*buf != ':' || !buf[1]) { nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("parsing cpuinfo cpu MHz")); return -1; } if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 /* Accept trailing fractional part. */ && (*p == '\0' || *p == '.' || c_isspace(*p))) nodeinfo->mhz = ui; } # elif defined(__powerpc__) || \ defined(__powerpc64__) char *buf = line; if (STRPREFIX(buf, "clock")) { char *p; unsigned int ui; buf += 5; while (*buf && c_isspace(*buf)) buf++; if (*buf != ':' || !buf[1]) { nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("parsing cpuinfo cpu MHz")); return -1; } if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 /* Accept trailing fractional part. */ && (*p == '\0' || *p == '.' || c_isspace(*p))) nodeinfo->mhz = ui; /* No other interesting infos are available in /proc/cpuinfo. * However, there is a line identifying processor's version, * identification and machine, but we don't want it to be caught * and parsed in next iteration, because it is not in expected * format and thus lead to error. */ } # else # warning Parser for /proc/cpuinfo needs to be adapted for your architecture # endif } /* OK, we've parsed clock speed out of /proc/cpuinfo. Get the core, socket * thread and topology information from /sys */ cpudir = opendir(sysfs_cpudir); if (cpudir == NULL) { virReportSystemError(errno, _("cannot opendir %s"), sysfs_cpudir); return -1; } CPU_ZERO(&core_mask); CPU_ZERO(&socket_mask); while ((cpudirent = readdir(cpudir))) { if (sscanf(cpudirent->d_name, "cpu%u", &cpu) != 1) continue; online = cpu_online(cpu); if (online < 0) { closedir(cpudir); return -1; } if (!online) continue; nodeinfo->cpus++; /* Parse core */ core = parse_core(cpu); if (!CPU_ISSET(core, &core_mask)) { CPU_SET(core, &core_mask); nodeinfo->cores++; } /* Parse socket */ sock = parse_socket(cpu); if (!CPU_ISSET(sock, &socket_mask)) { CPU_SET(sock, &socket_mask); nodeinfo->sockets++; } cur_threads = count_thread_siblings(cpu); if (cur_threads == 0) { closedir(cpudir); return -1; } if (cur_threads > nodeinfo->threads) nodeinfo->threads = cur_threads; } if (errno) { virReportSystemError(errno, _("problem reading %s"), sysfs_path); closedir(cpudir); return -1; } closedir(cpudir); /* there should always be at least one cpu, socket and one thread */ if (nodeinfo->cpus == 0) { nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no CPUs found")); return -1; } if (nodeinfo->sockets == 0) { nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no sockets found")); return -1; } if (nodeinfo->threads == 0) { nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no threads found")); return -1; } /* nodeinfo->sockets is supposed to be a number of sockets per NUMA node, * however if NUMA nodes are not composed of whole sockets, we just lie * about the number of NUMA nodes and force apps to check capabilities XML * for the actual NUMA topology. */ if (nodeinfo->sockets % nodeinfo->nodes == 0) nodeinfo->sockets /= nodeinfo->nodes; else nodeinfo->nodes = 1; return 0; }
/** * xenInotifyOpen: * @conn: pointer to the connection block * @name: URL for the target, NULL for local * @flags: combination of virDrvOpenFlag(s) * * Connects and starts listening for inotify events * * Returns 0 or -1 in case of error. */ int xenInotifyOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, unsigned int flags) { DIR *dh; struct dirent *ent; char *path; xenUnifiedPrivatePtr priv = conn->privateData; virCheckFlags(VIR_CONNECT_RO, -1); if (priv->configDir) { priv->useXenConfigCache = 1; } else { /* /var/lib/xend/domains/<uuid>/config.sxp */ priv->configDir = XEND_DOMAINS_DIR; priv->useXenConfigCache = 0; if (VIR_ALLOC(priv->configInfoList) < 0) return -1; /* populate initial list */ if (!(dh = opendir(priv->configDir))) { virReportSystemError(errno, _("cannot open directory: %s"), priv->configDir); return -1; } while ((ent = readdir(dh))) { if (STRPREFIX(ent->d_name, ".")) continue; /* Build the full file path */ if (!(path = virFileBuildPath(priv->configDir, ent->d_name, NULL))) { closedir(dh); return -1; } if (xenInotifyAddDomainConfigInfo(conn, path) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Error adding file to config list")); closedir(dh); VIR_FREE(path); return -1; } VIR_FREE(path); } closedir(dh); } if ((priv->inotifyFD = inotify_init()) < 0) { virReportSystemError(errno, "%s", _("initializing inotify")); return -1; } VIR_DEBUG("Adding a watch on %s", priv->configDir); if (inotify_add_watch(priv->inotifyFD, priv->configDir, IN_CREATE | IN_CLOSE_WRITE | IN_DELETE | IN_MOVED_TO | IN_MOVED_FROM) < 0) { virReportSystemError(errno, _("adding watch on %s"), priv->configDir); return -1; } VIR_DEBUG("Building initial config cache"); if (priv->useXenConfigCache && xenXMConfigCacheRefresh(conn) < 0) { VIR_DEBUG("Failed to enable XM config cache %s", conn->err.message); return -1; } VIR_DEBUG("Registering with event loop"); /* Add the handle for monitoring */ if ((priv->inotifyWatch = virEventAddHandle(priv->inotifyFD, VIR_EVENT_HANDLE_READABLE, xenInotifyEvent, conn, NULL)) < 0) { VIR_DEBUG("Failed to add inotify handle, disabling events"); } return 0; }
int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, const char *filename) { virConfPtr conf = NULL; virConfValuePtr p; int ret = -1; size_t i; char *stdioHandler = NULL; /* 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 CHECK_TYPE_ALT(name, type1, type2) \ if (p && (p->type != (type1) && p->type != (type2))) { \ virReportError(VIR_ERR_INTERNAL_ERROR, \ "%s: %s: expected type " #type1, \ filename, (name)); \ goto cleanup; \ } #define GET_VALUE_LONG(NAME, VAR) \ p = virConfGetValue(conf, NAME); \ CHECK_TYPE_ALT(NAME, VIR_CONF_LONG, VIR_CONF_ULONG); \ if (p) \ VAR = p->l; #define GET_VALUE_ULONG(NAME, VAR) \ p = virConfGetValue(conf, NAME); \ CHECK_TYPE(NAME, VIR_CONF_ULONG); \ if (p) \ VAR = p->l; #define GET_VALUE_BOOL(NAME, VAR) \ p = virConfGetValue(conf, NAME); \ CHECK_TYPE(NAME, VIR_CONF_ULONG); \ 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, j; 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) { for (j = 0; j < i; j++) { if (STREQ(pp->str, cfg->securityDriverNames[j])) { virReportError(VIR_ERR_CONF_SYNTAX, _("Duplicate security driver %s"), pp->str); goto cleanup; } } 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_BOOL("spice_auto_unix_socket", cfg->spiceAutoUnixSocket); GET_VALUE_ULONG("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_ULONG("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_ULONG("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_ULONG("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_ULONG("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_ULONG("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); /* Some crazy backcompat. Back in the old days, this was just a pure * string. We must continue supporting it. These days however, this may be * an array of strings. */ p = virConfGetValue(conf, "hugetlbfs_mount"); if (p) { /* There already might be something autodetected. Avoid leaking it. */ while (cfg->nhugetlbfs) { cfg->nhugetlbfs--; VIR_FREE(cfg->hugetlbfs[cfg->nhugetlbfs].mnt_dir); } VIR_FREE(cfg->hugetlbfs); if (p->type == VIR_CONF_LIST) { size_t len = 0; virConfValuePtr pp = p->list; /* Calc length and check items */ while (pp) { if (pp->type != VIR_CONF_STRING) { virReportError(VIR_ERR_CONF_SYNTAX, "%s", _("hugetlbfs_mount must be a list of strings")); goto cleanup; } len++; pp = pp->next; } if (len && VIR_ALLOC_N(cfg->hugetlbfs, len) < 0) goto cleanup; cfg->nhugetlbfs = len; pp = p->list; len = 0; while (pp) { if (virQEMUDriverConfigHugeTLBFSInit(&cfg->hugetlbfs[len], pp->str, !len) < 0) goto cleanup; len++; pp = pp->next; } } else { CHECK_TYPE("hugetlbfs_mount", VIR_CONF_STRING); if (STRNEQ(p->str, "")) { if (VIR_ALLOC_N(cfg->hugetlbfs, 1) < 0) goto cleanup; cfg->nhugetlbfs = 1; if (virQEMUDriverConfigHugeTLBFSInit(&cfg->hugetlbfs[0], p->str, true) < 0) goto cleanup; } } } 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_ULONG("max_processes", cfg->maxProcesses); GET_VALUE_ULONG("max_files", cfg->maxFiles); GET_VALUE_STR("lock_manager", cfg->lockManagerName); GET_VALUE_STR("stdio_handler", stdioHandler); if (stdioHandler) { if (STREQ(stdioHandler, "logd")) { cfg->stdioLogD = true; } else if (STREQ(stdioHandler, "file")) { cfg->stdioLogD = false; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unknown stdio handler %s"), stdioHandler); VIR_FREE(stdioHandler); goto cleanup; } VIR_FREE(stdioHandler); } GET_VALUE_ULONG("max_queued", cfg->maxQueuedJobs); GET_VALUE_LONG("keepalive_interval", cfg->keepAliveInterval); GET_VALUE_ULONG("keepalive_count", cfg->keepAliveCount); GET_VALUE_LONG("seccomp_sandbox", cfg->seccompSandbox); GET_VALUE_STR("migration_host", cfg->migrateHost); virStringStripIPv6Brackets(cfg->migrateHost); if (cfg->migrateHost && (STRPREFIX(cfg->migrateHost, "localhost") || virSocketAddrIsNumericLocalhost(cfg->migrateHost))) { virReportError(VIR_ERR_CONF_SYNTAX, _("migration_host must not be the address of" " the local machine: %s"), cfg->migrateHost); goto cleanup; } GET_VALUE_STR("migration_address", cfg->migrationAddress); virStringStripIPv6Brackets(cfg->migrationAddress); if (cfg->migrationAddress && (STRPREFIX(cfg->migrationAddress, "localhost") || virSocketAddrIsNumericLocalhost(cfg->migrationAddress))) { virReportError(VIR_ERR_CONF_SYNTAX, _("migration_address must not be the address of" " the local machine: %s"), cfg->migrationAddress); goto cleanup; } GET_VALUE_BOOL("log_timestamp", cfg->logTimestamp); if ((p = virConfGetValue(conf, "nvram"))) { size_t len; virConfValuePtr pp; CHECK_TYPE("nvram", VIR_CONF_LIST); virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares); /* 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", _("nvram must be a list of strings")); goto cleanup; } } if (len && VIR_ALLOC_N(cfg->firmwares, len) < 0) goto cleanup; cfg->nfirmwares = len; for (i = 0, pp = p->list; pp; i++, pp = pp->next) { if (VIR_ALLOC(cfg->firmwares[i]) < 0) goto cleanup; if (virFirmwareParse(pp->str, cfg->firmwares[i]) < 0) goto cleanup; } } ret = 0; cleanup: virConfFree(conf); return ret; }
/* Helper for ANIM_add_driver_with_target - Adds the actual driver */ static int add_driver_with_target(ReportList *UNUSED(reports), ID *dst_id, const char dst_path[], int dst_index, ID *src_id, const char src_path[], int src_index, PointerRNA *dst_ptr, PropertyRNA *dst_prop, PointerRNA *src_ptr, PropertyRNA *src_prop, short flag, int driver_type) { FCurve *fcu; short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1; const char *prop_name = RNA_property_identifier(src_prop); /* Create F-Curve with Driver */ fcu = verify_driver_fcurve(dst_id, dst_path, dst_index, add_mode); if (fcu && fcu->driver) { ChannelDriver *driver = fcu->driver; DriverVar *dvar; /* Set the type of the driver */ driver->type = driver_type; /* Set driver expression, so that the driver works out of the box * * The following checks define a bit of "autodetection magic" we use * to ensure that the drivers will behave as expected out of the box * when faced with properties with different units. */ /* XXX: if we have N-1 mapping, should we include all those in the expression? */ if ((RNA_property_unit(dst_prop) == PROP_UNIT_ROTATION) && (RNA_property_unit(src_prop) != PROP_UNIT_ROTATION)) { /* Rotation Destination: normal -> radians, so convert src to radians * (However, if both input and output is a rotation, don't apply such corrections) */ BLI_strncpy(driver->expression, "radians(var)", sizeof(driver->expression)); } else if ((RNA_property_unit(src_prop) == PROP_UNIT_ROTATION) && (RNA_property_unit(dst_prop) != PROP_UNIT_ROTATION)) { /* Rotation Source: radians -> normal, so convert src to degrees * (However, if both input and output is a rotation, don't apply such corrections) */ BLI_strncpy(driver->expression, "degrees(var)", sizeof(driver->expression)); } else { /* Just a normal property without any unit problems */ BLI_strncpy(driver->expression, "var", sizeof(driver->expression)); } /* Create a driver variable for the target * - For transform properties, we want to automatically use "transform channel" instead * (The only issue is with quat rotations vs euler channels...) * - To avoid problems with transform properties depending on the final transform that they * control (thus creating pseudo-cycles - see T48734), we don't use transform channels * when both the source and destinations are in same places. */ dvar = driver_add_new_variable(driver); if (ELEM(src_ptr->type, &RNA_Object, &RNA_PoseBone) && (STREQ(prop_name, "location") || STREQ(prop_name, "scale") || STRPREFIX(prop_name, "rotation_")) && (src_ptr->data != dst_ptr->data)) { /* Transform Channel */ DriverTarget *dtar; driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN); dtar = &dvar->targets[0]; /* Bone or Object target? */ dtar->id = src_id; dtar->idtype = GS(src_id->name); if (src_ptr->type == &RNA_PoseBone) { RNA_string_get(src_ptr, "name", dtar->pchan_name); } /* Transform channel depends on type */ if (STREQ(prop_name, "location")) { if (src_index == 2) { dtar->transChan = DTAR_TRANSCHAN_LOCZ; } else if (src_index == 1) { dtar->transChan = DTAR_TRANSCHAN_LOCY; } else { dtar->transChan = DTAR_TRANSCHAN_LOCX; } } else if (STREQ(prop_name, "scale")) { if (src_index == 2) { dtar->transChan = DTAR_TRANSCHAN_SCALEZ; } else if (src_index == 1) { dtar->transChan = DTAR_TRANSCHAN_SCALEY; } else { dtar->transChan = DTAR_TRANSCHAN_SCALEX; } } else { /* XXX: With quaternions and axis-angle, this mapping might not be correct... * But since those have 4 elements instead, there's not much we can do */ if (src_index == 2) { dtar->transChan = DTAR_TRANSCHAN_ROTZ; } else if (src_index == 1) { dtar->transChan = DTAR_TRANSCHAN_ROTY; } else { dtar->transChan = DTAR_TRANSCHAN_ROTX; } } } else { /* Single RNA Property */ DriverTarget *dtar = &dvar->targets[0]; /* ID is as-is */ dtar->id = src_id; dtar->idtype = GS(src_id->name); /* Need to make a copy of the path (or build one with array index built in) */ if (RNA_property_array_check(src_prop)) { dtar->rna_path = BLI_sprintfN("%s[%d]", src_path, src_index); } else { dtar->rna_path = BLI_strdup(src_path); } } } /* set the done status */ return (fcu != NULL); }
int linuxNodeInfoCPUPopulate(FILE *cpuinfo, const char *sysfs_dir, virNodeInfoPtr nodeinfo) { char line[1024]; DIR *nodedir = NULL; struct dirent *nodedirent = NULL; int cpus, cores, socks, threads, offline = 0; unsigned int node; int ret = -1; char *sysfs_nodedir = NULL; char *sysfs_cpudir = NULL; /* Start with parsing CPU clock speed from /proc/cpuinfo */ while (fgets(line, sizeof(line), cpuinfo) != NULL) { # if defined(__x86_64__) || \ defined(__amd64__) || \ defined(__i386__) char *buf = line; if (STRPREFIX(buf, "cpu MHz")) { char *p; unsigned int ui; buf += 7; while (*buf && c_isspace(*buf)) buf++; if (*buf != ':' || !buf[1]) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("parsing cpu MHz from cpuinfo")); goto cleanup; } if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 && /* Accept trailing fractional part. */ (*p == '\0' || *p == '.' || c_isspace(*p))) nodeinfo->mhz = ui; } # elif defined(__powerpc__) || \ defined(__powerpc64__) char *buf = line; if (STRPREFIX(buf, "clock")) { char *p; unsigned int ui; buf += 5; while (*buf && c_isspace(*buf)) buf++; if (*buf != ':' || !buf[1]) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("parsing cpu MHz from cpuinfo")); goto cleanup; } if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 && /* Accept trailing fractional part. */ (*p == '\0' || *p == '.' || c_isspace(*p))) nodeinfo->mhz = ui; /* No other interesting infos are available in /proc/cpuinfo. * However, there is a line identifying processor's version, * identification and machine, but we don't want it to be caught * and parsed in next iteration, because it is not in expected * format and thus lead to error. */ } # elif defined(__arm__) char *buf = line; if (STRPREFIX(buf, "BogoMIPS")) { char *p; unsigned int ui; buf += 8; while (*buf && c_isspace(*buf)) buf++; if (*buf != ':' || !buf[1]) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("parsing cpu MHz from cpuinfo")); goto cleanup; } if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 /* Accept trailing fractional part. */ && (*p == '\0' || *p == '.' || c_isspace(*p))) nodeinfo->mhz = ui; } # elif defined(__s390__) || \ defined(__s390x__) /* s390x has no realistic value for CPU speed, * assign a value of zero to signify this */ nodeinfo->mhz = 0; # else # warning Parser for /proc/cpuinfo needs to be adapted for your architecture # endif } /* OK, we've parsed clock speed out of /proc/cpuinfo. Get the * core, node, socket, thread and topology information from /sys */ if (virAsprintf(&sysfs_nodedir, "%s/node", sysfs_dir) < 0) goto cleanup; if (!(nodedir = opendir(sysfs_nodedir))) { /* the host isn't probably running a NUMA architecture */ goto fallback; } errno = 0; while ((nodedirent = readdir(nodedir))) { if (sscanf(nodedirent->d_name, "node%u", &node) != 1) continue; nodeinfo->nodes++; if (virAsprintf(&sysfs_cpudir, "%s/node/%s", sysfs_dir, nodedirent->d_name) < 0) goto cleanup; if ((cpus = virNodeParseNode(sysfs_cpudir, &socks, &cores, &threads, &offline)) < 0) goto cleanup; VIR_FREE(sysfs_cpudir); nodeinfo->cpus += cpus; if (socks > nodeinfo->sockets) nodeinfo->sockets = socks; if (cores > nodeinfo->cores) nodeinfo->cores = cores; if (threads > nodeinfo->threads) nodeinfo->threads = threads; errno = 0; } if (errno) { virReportSystemError(errno, _("problem reading %s"), sysfs_nodedir); goto cleanup; } if (nodeinfo->cpus && nodeinfo->nodes) goto done; fallback: VIR_FREE(sysfs_cpudir); if (virAsprintf(&sysfs_cpudir, "%s/cpu", sysfs_dir) < 0) goto cleanup; if ((cpus = virNodeParseNode(sysfs_cpudir, &socks, &cores, &threads, &offline)) < 0) goto cleanup; nodeinfo->nodes = 1; nodeinfo->cpus = cpus; nodeinfo->sockets = socks; nodeinfo->cores = cores; nodeinfo->threads = threads; done: /* There should always be at least one cpu, socket, node, and thread. */ if (nodeinfo->cpus == 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no CPUs found")); goto cleanup; } if (nodeinfo->sockets == 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no sockets found")); goto cleanup; } if (nodeinfo->threads == 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no threads found")); goto cleanup; } /* Now check if the topology makes sense. There are machines that don't * expose their real number of nodes or for example the AMD Bulldozer * architecture that exposes their Clustered integer core modules as both * threads and cores. This approach throws off our detection. Unfortunately * the nodeinfo structure isn't designed to carry the full topology so * we're going to lie about the detected topology to notify the user * to check the host capabilities for the actual topology. */ if ((nodeinfo->nodes * nodeinfo->sockets * nodeinfo->cores * nodeinfo->threads) != (nodeinfo->cpus + offline)) { nodeinfo->nodes = 1; nodeinfo->sockets = 1; nodeinfo->cores = nodeinfo->cpus + offline; nodeinfo->threads = 1; } ret = 0; cleanup: /* don't shadow a more serious error */ if (nodedir && closedir(nodedir) < 0 && ret >= 0) { virReportSystemError(errno, _("problem closing %s"), sysfs_nodedir); ret = -1; } VIR_FREE(sysfs_nodedir); VIR_FREE(sysfs_cpudir); return ret; }
static int virHostMemGetStatsLinux(FILE *meminfo, int cellNum, virNodeMemoryStatsPtr params, int *nparams) { int ret = -1; size_t i = 0, j = 0, k = 0; int found = 0; int nr_param; char line[1024]; char meminfo_hdr[VIR_NODE_MEMORY_STATS_FIELD_LENGTH]; unsigned long val; struct field_conv { const char *meminfo_hdr; /* meminfo header */ const char *field; /* MemoryStats field name */ } field_conv[] = { {"MemTotal:", VIR_NODE_MEMORY_STATS_TOTAL}, {"MemFree:", VIR_NODE_MEMORY_STATS_FREE}, {"Buffers:", VIR_NODE_MEMORY_STATS_BUFFERS}, {"Cached:", VIR_NODE_MEMORY_STATS_CACHED}, {NULL, NULL} }; if (cellNum == VIR_NODE_MEMORY_STATS_ALL_CELLS) { nr_param = LINUX_NB_MEMORY_STATS_ALL; } else { nr_param = LINUX_NB_MEMORY_STATS_CELL; } if ((*nparams) == 0) { /* Current number of memory stats supported by linux */ *nparams = nr_param; ret = 0; goto cleanup; } if ((*nparams) != nr_param) { virReportInvalidArg(nparams, _("nparams in %s must be %d"), __FUNCTION__, nr_param); goto cleanup; } while (fgets(line, sizeof(line), meminfo) != NULL) { char *buf = line; if (STRPREFIX(buf, "Node ")) { /* * /sys/devices/system/node/nodeX/meminfo format is below. * So, skip prefix "Node XX ". * * Node 0 MemTotal: 8386980 kB * Node 0 MemFree: 5300920 kB * : */ char *p; p = buf; for (i = 0; i < 2; i++) { p = strchr(p, ' '); if (p == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no prefix found")); goto cleanup; } p++; } buf = p; } if (sscanf(buf, "%s %lu kB", meminfo_hdr, &val) < 2) continue; for (j = 0; field_conv[j].meminfo_hdr != NULL; j++) { struct field_conv *convp = &field_conv[j]; if (STREQ(meminfo_hdr, convp->meminfo_hdr)) { virNodeMemoryStatsPtr param = ¶ms[k++]; if (virStrcpyStatic(param->field, convp->field) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Field kernel memory too long for destination")); goto cleanup; } param->value = val; found++; break; } } if (found >= nr_param) break; } if (found == 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no available memory line found")); goto cleanup; } ret = 0; cleanup: return ret; }
static int make_controller(const char *path, mode_t mode) { int ret = -1; const char *controller; if (!STRPREFIX(path, fakesysfscgroupdir)) { errno = EINVAL; return -1; } controller = path + strlen(fakesysfscgroupdir) + 1; if (STREQ(controller, "cpu")) return symlink("cpu,cpuacct", path); if (STREQ(controller, "cpuacct")) return symlink("cpu,cpuacct", path); if (real_mkdir(path, mode) < 0) goto cleanup; # define MAKE_FILE(name, value) \ do { \ if (make_file(path, name, value) < 0) \ goto cleanup; \ } while (0) if (STRPREFIX(controller, "cpu,cpuacct")) { MAKE_FILE("cpu.cfs_period_us", "100000\n"); MAKE_FILE("cpu.cfs_quota_us", "-1\n"); MAKE_FILE("cpu.rt_period_us", "1000000\n"); MAKE_FILE("cpu.rt_runtime_us", "950000\n"); MAKE_FILE("cpu.shares", "1024\n"); MAKE_FILE("cpu.stat", "nr_periods 0\n" "nr_throttled 0\n" "throttled_time 0\n"); MAKE_FILE("cpuacct.stat", "user 216687025\n" "system 43421396\n"); MAKE_FILE("cpuacct.usage", "2787788855799582\n"); MAKE_FILE("cpuacct.usage_percpu", "7059492996 0 0 0 0 0 0 0 4180532496 0 0 0 0 0 0 0 " "1957541268 0 0 0 0 0 0 0 2065932204 0 0 0 0 0 0 0 " "18228689414 0 0 0 0 0 0 0 4245525148 0 0 0 0 0 0 0 " "2911161568 0 0 0 0 0 0 0 1407758136 0 0 0 0 0 0 0 " "1836807700 0 0 0 0 0 0 0 1065296618 0 0 0 0 0 0 0 " "2046213266 0 0 0 0 0 0 0 747889778 0 0 0 0 0 0 0 " "709566900 0 0 0 0 0 0 0 444777342 0 0 0 0 0 0 0 " "5683512916 0 0 0 0 0 0 0 635751356 0 0 0 0 0 0 0\n"); } else if (STRPREFIX(controller, "cpuset")) { MAKE_FILE("cpuset.cpu_exclusive", "1\n"); if (STREQ(controller, "cpuset")) MAKE_FILE("cpuset.cpus", "0-1"); else MAKE_FILE("cpuset.cpus", ""); /* Values don't inherit */ MAKE_FILE("cpuset.mem_exclusive", "1\n"); MAKE_FILE("cpuset.mem_hardwall", "0\n"); MAKE_FILE("cpuset.memory_migrate", "0\n"); MAKE_FILE("cpuset.memory_pressure", "0\n"); MAKE_FILE("cpuset.memory_pressure_enabled", "0\n"); MAKE_FILE("cpuset.memory_spread_page", "0\n"); MAKE_FILE("cpuset.memory_spread_slab", "0\n"); if (STREQ(controller, "cpuset")) MAKE_FILE("cpuset.mems", "0"); else MAKE_FILE("cpuset.mems", ""); /* Values don't inherit */ MAKE_FILE("cpuset.sched_load_balance", "1\n"); MAKE_FILE("cpuset.sched_relax_domain_level", "-1\n"); } else if (STRPREFIX(controller, "memory")) { MAKE_FILE("memory.failcnt", "0\n"); MAKE_FILE("memory.force_empty", ""); /* Write only */ MAKE_FILE("memory.kmem.tcp.failcnt", "0\n"); MAKE_FILE("memory.kmem.tcp.limit_in_bytes", "9223372036854775807\n"); MAKE_FILE("memory.kmem.tcp.max_usage_in_bytes", "0\n"); MAKE_FILE("memory.kmem.tcp.usage_in_bytes", "16384\n"); MAKE_FILE("memory.limit_in_bytes", "9223372036854775807\n"); MAKE_FILE("memory.max_usage_in_bytes", "0\n"); MAKE_FILE("memory.memsw.failcnt", ""); /* Not supported */ MAKE_FILE("memory.memsw.limit_in_bytes", ""); /* Not supported */ MAKE_FILE("memory.memsw.max_usage_in_bytes", ""); /* Not supported */ MAKE_FILE("memory.memsw.usage_in_bytes", ""); /* Not supported */ MAKE_FILE("memory.move_charge_at_immigrate", "0\n"); MAKE_FILE("memory.numa_stat", "total=367664 N0=367664\n" "file=314764 N0=314764\n" "anon=51999 N0=51999\n" "unevictable=901 N0=901\n"); MAKE_FILE("memory.oom_control", "oom_kill_disable 0\n" "under_oom 0\n"); MAKE_FILE("memory.soft_limit_in_bytes", "9223372036854775807\n"); MAKE_FILE("memory.stat", "cache 1336619008\n" "rss 97792000\n" "mapped_file 42090496\n" "pgpgin 13022605027\n" "pgpgout 13023820533\n" "pgfault 54429417056\n" "pgmajfault 315715\n" "inactive_anon 145887232\n" "active_anon 67100672\n" "inactive_file 627400704\n" "active_file 661872640\n" "unevictable 3690496\n" "hierarchical_memory_limit 9223372036854775807\n" "total_cache 1336635392\n" "total_rss 118689792\n" "total_mapped_file 42106880\n" "total_pgpgin 13022606816\n" "total_pgpgout 13023820793\n" "total_pgfault 54429422313\n" "total_pgmajfault 315715\n" "total_inactive_anon 145891328\n" "total_active_anon 88010752\n" "total_inactive_file 627400704\n" "total_active_file 661872640\n" "total_unevictable 3690496\n" "recent_rotated_anon 112807028\n" "recent_rotated_file 2547948\n" "recent_scanned_anon 113796164\n" "recent_scanned_file 8199863\n"); MAKE_FILE("memory.swappiness", "60\n"); MAKE_FILE("memory.usage_in_bytes", "1455321088\n"); MAKE_FILE("memory.use_hierarchy", "0\n"); } else if (STRPREFIX(controller, "freezer")) { MAKE_FILE("freezer.state", "THAWED"); } else if (STRPREFIX(controller, "blkio")) { MAKE_FILE("blkio.io_merged", "8:0 Read 1100949\n" "8:0 Write 2248076\n" "8:0 Sync 63063\n" "8:0 Async 3285962\n" "8:0 Total 3349025\n"); MAKE_FILE("blkio.io_queued", "8:0 Read 0\n" "8:0 Write 0\n" "8:0 Sync 0\n" "8:0 Async 0\n" "8:0 Total 0\n"); MAKE_FILE("blkio.io_service_bytes", "8:0 Read 59542078464\n" "8:0 Write 397369182208\n" "8:0 Sync 234080922624\n" "8:0 Async 222830338048\n" "8:0 Total 456911260672\n"); MAKE_FILE("blkio.io_serviced", "8:0 Read 3402504\n" "8:0 Write 14966516\n" "8:0 Sync 12064031\n" "8:0 Async 6304989\n" "8:0 Total 18369020\n"); MAKE_FILE("blkio.io_service_time", "8:0 Read 10747537542349\n" "8:0 Write 9200028590575\n" "8:0 Sync 6449319855381\n" "8:0 Async 13498246277543\n" "8:0 Total 19947566132924\n"); MAKE_FILE("blkio.io_wait_time", "8:0 Read 14687514824889\n" "8:0 Write 357748452187691\n" "8:0 Sync 55296974349413\n" "8:0 Async 317138992663167\n" "8:0 Total 372435967012580\n"); MAKE_FILE("blkio.reset_stats", ""); /* Write only */ MAKE_FILE("blkio.sectors", "8:0 892404806\n"); MAKE_FILE("blkio.throttle.io_service_bytes", "8:0 Read 59542107136\n" "8:0 Write 411440480256\n" "8:0 Sync 248486822912\n" "8:0 Async 222495764480\n" "8:0 Total 470982587392\n" "9:0 Read 59542107137\n" "9:0 Write 411440480257\n" "9:0 Sync 248486822912\n" "9:0 Async 222495764480\n" "9:0 Total 470982587392\n"); MAKE_FILE("blkio.throttle.io_serviced", "8:0 Read 4832583\n" "8:0 Write 36641903\n" "8:0 Sync 30723171\n" "8:0 Async 10751315\n" "8:0 Total 41474486\n" "9:0 Read 4832584\n" "9:0 Write 36641904\n" "9:0 Sync 30723171\n" "9:0 Async 10751315\n" "9:0 Total 41474486\n"); MAKE_FILE("blkio.throttle.read_bps_device", ""); MAKE_FILE("blkio.throttle.read_iops_device", ""); MAKE_FILE("blkio.throttle.write_bps_device", ""); MAKE_FILE("blkio.throttle.write_iops_device", ""); MAKE_FILE("blkio.time", "8:0 61019089\n"); MAKE_FILE("blkio.weight", "1000\n"); MAKE_FILE("blkio.weight_device", ""); } else { errno = EINVAL; goto cleanup; } ret = 0; cleanup: return ret; }
static int hypervNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) { int result = -1; hypervPrivate *priv = conn->privateData; virBuffer query = VIR_BUFFER_INITIALIZER; Win32_ComputerSystem *computerSystem = NULL; Win32_Processor *processorList = NULL; Win32_Processor *processor = NULL; char *tmp; memset(info, 0, sizeof(*info)); virBufferAddLit(&query, WIN32_COMPUTERSYSTEM_WQL_SELECT); /* Get Win32_ComputerSystem */ if (hypervGetWin32ComputerSystemList(priv, &query, &computerSystem) < 0) { goto cleanup; } if (computerSystem == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s"), "Win32_ComputerSystem"); goto cleanup; } /* Get Win32_Processor list */ virBufferAsprintf(&query, "associators of " "{Win32_ComputerSystem.Name=\"%s\"} " "where AssocClass = Win32_ComputerSystemProcessor " "ResultClass = Win32_Processor", computerSystem->data->Name); if (hypervGetWin32ProcessorList(priv, &query, &processorList) < 0) { goto cleanup; } if (processorList == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s"), "Win32_Processor"); goto cleanup; } /* Strip the string to fit more relevant information in 32 chars */ tmp = processorList->data->Name; while (*tmp != '\0') { if (STRPREFIX(tmp, " ")) { memmove(tmp, tmp + 1, strlen(tmp + 1) + 1); continue; } else if (STRPREFIX(tmp, "(R)") || STRPREFIX(tmp, "(C)")) { memmove(tmp, tmp + 3, strlen(tmp + 3) + 1); continue; } else if (STRPREFIX(tmp, "(TM)")) { memmove(tmp, tmp + 4, strlen(tmp + 4) + 1); continue; } ++tmp; } /* Fill struct */ if (virStrncpy(info->model, processorList->data->Name, sizeof(info->model) - 1, sizeof(info->model)) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("CPU model %s too long for destination"), processorList->data->Name); goto cleanup; } info->memory = computerSystem->data->TotalPhysicalMemory / 1024; /* byte to kilobyte */ info->mhz = processorList->data->MaxClockSpeed; info->nodes = 1; info->sockets = 0; for (processor = processorList; processor != NULL; processor = processor->next) { ++info->sockets; } info->cores = processorList->data->NumberOfCores; info->threads = info->cores / processorList->data->NumberOfLogicalProcessors; info->cpus = info->sockets * info->cores; result = 0; cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); hypervFreeObject(priv, (hypervObject *)processorList); return result; }
/* Format: * <arch> <model> * qemu-0.13 encloses some model names in []: * <arch> [<model>] */ static int qemuCapsParseX86Models(const char *output, unsigned int *retcount, const char ***retcpus) { const char *p = output; const char *next; unsigned int count = 0; const char **cpus = NULL; int i; do { const char *t; if ((next = strchr(p, '\n'))) next++; if (!(t = strchr(p, ' ')) || (next && t >= next)) continue; if (!STRPREFIX(p, "x86")) continue; p = t; while (*p == ' ') p++; if (*p == '\0' || *p == '\n') continue; if (retcpus) { unsigned int len; if (VIR_REALLOC_N(cpus, count + 1) < 0) { virReportOOMError(); goto error; } if (next) len = next - p - 1; else len = strlen(p); if (len > 2 && *p == '[' && p[len - 1] == ']') { p++; len -= 2; } if (!(cpus[count] = strndup(p, len))) { virReportOOMError(); goto error; } } count++; } while ((p = next)); if (retcount) *retcount = count; if (retcpus) *retcpus = cpus; return 0; error: if (cpus) { for (i = 0; i < count; i++) VIR_FREE(cpus[i]); } VIR_FREE(cpus); return -1; }
int main(int argc, char **argv) { int i, n; char **origenv; char **newenv; char *cwd; FILE *log = fopen(abs_builddir "/commandhelper.log", "w"); if (!log) goto error; for (i = 1 ; i < argc ; i++) { fprintf(log, "ARG:%s\n", argv[i]); } origenv = environ; n = 0; while (*origenv != NULL) { n++; origenv++; } if (VIR_ALLOC_N(newenv, n) < 0) { exit(EXIT_FAILURE); } origenv = environ; n = i = 0; while (*origenv != NULL) { newenv[i++] = *origenv; n++; origenv++; } qsort(newenv, n, sizeof(newenv[0]), envsort); for (i = 0 ; i < n ; i++) { /* Ignore the variables used to instruct the loader into * behaving differently, as they could throw the tests off. */ if (!STRPREFIX(newenv[i], "LD_")) fprintf(log, "ENV:%s\n", newenv[i]); } for (i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++) { int f; int closed; if (i == fileno(log)) continue; closed = fcntl(i, F_GETFD, &f) == -1 && errno == EBADF; if (!closed) fprintf(log, "FD:%d\n", i); } fprintf(log, "DAEMON:%s\n", getpgrp() == getsid(0) ? "yes" : "no"); if (!(cwd = getcwd(NULL, 0))) return EXIT_FAILURE; if (strlen(cwd) > strlen(".../commanddata") && STREQ(cwd + strlen(cwd) - strlen("/commanddata"), "/commanddata")) strcpy(cwd, ".../commanddata"); fprintf(log, "CWD:%s\n", cwd); VIR_FREE(cwd); VIR_FORCE_FCLOSE(log); if (argc > 1 && STREQ(argv[1], "--close-stdin")) { if (freopen("/dev/null", "r", stdin) != stdin) goto error; usleep(100*1000); } char buf[1024]; ssize_t got; fprintf(stdout, "BEGIN STDOUT\n"); fflush(stdout); fprintf(stderr, "BEGIN STDERR\n"); fflush(stderr); for (;;) { got = read(STDIN_FILENO, buf, sizeof(buf)); if (got < 0) goto error; if (got == 0) break; if (safewrite(STDOUT_FILENO, buf, got) != got) goto error; if (safewrite(STDERR_FILENO, buf, got) != got) goto error; } fprintf(stdout, "END STDOUT\n"); fflush(stdout); fprintf(stderr, "END STDERR\n"); fflush(stderr); return EXIT_SUCCESS; error: return EXIT_FAILURE; }
guestfs_h * guestfs_create_flags (unsigned flags, ...) { guestfs_h *g; g = calloc (1, sizeof (*g)); if (!g) return NULL; g->state = CONFIG; g->conn = NULL; guestfs_int_init_error_handler (g); g->abort_cb = abort; g->recovery_proc = 1; g->autosync = 1; g->memsize = DEFAULT_MEMSIZE; /* Start with large serial numbers so they are easy to spot * inside the protocol. */ g->msg_next_serial = 0x00123400; /* Default is uniprocessor appliance. */ g->smp = 1; g->path = strdup (GUESTFS_DEFAULT_PATH); if (!g->path) goto error; #ifdef QEMU g->hv = strdup (QEMU); #else /* configure --without-qemu, so set QEMU to something which will * definitely fail. The user is expected to override the hypervisor * by setting an environment variable or calling set_hv. */ g->hv = strdup ("false"); #endif if (!g->hv) goto error; /* Get program name. */ #if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME == 1 if (STRPREFIX (program_invocation_short_name, "lt-")) /* Remove libtool (lt-*) prefix from short name. */ g->program = strdup (program_invocation_short_name + 3); else g->program = strdup (program_invocation_short_name); #else g->program = strdup (""); #endif if (!g->program) goto error; g->identifier = strdup (""); if (!g->identifier) goto error; if (guestfs_int_set_backend (g, DEFAULT_BACKEND) == -1) { warning (g, _("libguestfs was built with an invalid default backend, using 'direct' instead")); if (guestfs_int_set_backend (g, "direct") == -1) { warning (g, _("'direct' backend does not work")); goto error; } } if (!(flags & GUESTFS_CREATE_NO_ENVIRONMENT)) ignore_value (guestfs_parse_environment (g)); if (!(flags & GUESTFS_CREATE_NO_CLOSE_ON_EXIT)) { g->close_on_exit = true; /* Link the handles onto a global list. */ gl_lock_lock (handles_lock); g->next = handles; handles = g; if (!atexit_handler_set) { atexit (close_handles); atexit_handler_set = 1; } gl_lock_unlock (handles_lock); } debug (g, "create: flags = %u, handle = %p, program = %s", flags, g, g->program); return g; error: guestfs_int_free_string_list (g->backend_settings); free (g->backend); free (g->identifier); free (g->program); free (g->path); free (g->hv); free (g->append); free (g); return NULL; }
/* * Constructs a argv suitable for launching uml with config defined * for a given virtual machine. */ virCommandPtr umlBuildCommandLine(virConnectPtr conn, struct uml_driver *driver, virDomainObjPtr vm) { size_t i, j; virCommandPtr cmd; cmd = virCommandNew(vm->def->os.kernel); virCommandAddEnvPassCommon(cmd); //virCommandAddArgPair(cmd, "con0", "fd:0,fd:1"); virCommandAddArgFormat(cmd, "mem=%lluK", vm->def->mem.cur_balloon); virCommandAddArgPair(cmd, "umid", vm->def->name); virCommandAddArgPair(cmd, "uml_dir", driver->monitorDir); if (vm->def->os.root) virCommandAddArgPair(cmd, "root", vm->def->os.root); for (i = 0; i < vm->def->ndisks; i++) { virDomainDiskDefPtr disk = vm->def->disks[i]; if (!STRPREFIX(disk->dst, "ubd")) { virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported disk type '%s'"), disk->dst); goto error; } virCommandAddArgPair(cmd, disk->dst, virDomainDiskGetSource(disk)); } for (i = 0; i < vm->def->nnets; i++) { char *ret = umlBuildCommandLineNet(conn, vm->def, vm->def->nets[i], i); if (!ret) goto error; virCommandAddArg(cmd, ret); VIR_FREE(ret); } for (i = 0; i < UML_MAX_CHAR_DEVICE; i++) { virDomainChrDefPtr chr = NULL; char *ret = NULL; for (j = 0; j < vm->def->nconsoles; j++) if (vm->def->consoles[j]->target.port == i) chr = vm->def->consoles[j]; if (chr) ret = umlBuildCommandLineChr(chr, "con", cmd); if (!ret) if (virAsprintf(&ret, "con%zu=none", i) < 0) goto error; virCommandAddArg(cmd, ret); VIR_FREE(ret); } for (i = 0; i < UML_MAX_CHAR_DEVICE; i++) { virDomainChrDefPtr chr = NULL; char *ret = NULL; for (j = 0; j < vm->def->nserials; j++) if (vm->def->serials[j]->target.port == i) chr = vm->def->serials[j]; if (chr) ret = umlBuildCommandLineChr(chr, "ssl", cmd); if (!ret) if (virAsprintf(&ret, "ssl%zu=none", i) < 0) goto error; virCommandAddArg(cmd, ret); VIR_FREE(ret); } if (vm->def->os.cmdline) { char *args, *next_arg; char *cmdline; if (VIR_STRDUP(cmdline, vm->def->os.cmdline) < 0) goto error; args = cmdline; while (*args == ' ') args++; while (*args) { next_arg = umlNextArg(args); virCommandAddArg(cmd, args); args = next_arg; } VIR_FREE(cmdline); } return cmd; error: virCommandFree(cmd); return NULL; }
static int libxlCapsInitGuests(libxl_ctx *ctx, virCapsPtr caps) { const libxl_version_info *ver_info; int err; regex_t regex; char *str, *token; regmatch_t subs[4]; char *saveptr = NULL; size_t i; virArch hostarch = caps->host.arch; struct guest_arch guest_archs[32]; int nr_guest_archs = 0; memset(guest_archs, 0, sizeof(guest_archs)); if ((ver_info = libxl_get_version_info(ctx)) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to get version info from libxenlight")); return -1; } err = regcomp(®ex, XEN_CAP_REGEX, REG_EXTENDED); if (err != 0) { char error[100]; regerror(err, ®ex, error, sizeof(error)); virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to compile regex %s"), error); return -1; } /* Format of capabilities string is documented in the code in * xen-unstable.hg/xen/arch/.../setup.c. * * It is a space-separated list of supported guest architectures. * * For x86: * TYP-VER-ARCH[p] * ^ ^ ^ ^ * | | | +-- PAE supported * | | +------- x86_32 or x86_64 * | +----------- the version of Xen, eg. "3.0" * +--------------- "xen" or "hvm" for para or full virt respectively * * For IA64: * TYP-VER-ARCH[be] * ^ ^ ^ ^ * | | | +-- Big-endian supported * | | +------- always "ia64" * | +----------- the version of Xen, eg. "3.0" * +--------------- "xen" or "hvm" for para or full virt respectively */ /* Split capabilities string into tokens. strtok_r is OK here because * we "own" the buffer. Parse out the features from each token. */ for (str = ver_info->capabilities, nr_guest_archs = 0; nr_guest_archs < sizeof(guest_archs) / sizeof(guest_archs[0]) && (token = strtok_r(str, " ", &saveptr)) != NULL; str = NULL) { if (regexec(®ex, token, sizeof(subs) / sizeof(subs[0]), subs, 0) == 0) { int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm"); virArch arch; int pae = 0, nonpae = 0, ia64_be = 0; if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) { arch = VIR_ARCH_I686; if (subs[3].rm_so != -1 && STRPREFIX(&token[subs[3].rm_so], "p")) pae = 1; else nonpae = 1; } else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) { arch = VIR_ARCH_X86_64; } else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) { arch = VIR_ARCH_ITANIUM; if (subs[3].rm_so != -1 && STRPREFIX(&token[subs[3].rm_so], "be")) ia64_be = 1; } else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) { arch = VIR_ARCH_PPC64; } else if (STRPREFIX(&token[subs[2].rm_so], "armv7l")) { arch = VIR_ARCH_ARMV7L; } else if (STRPREFIX(&token[subs[2].rm_so], "aarch64")) { arch = VIR_ARCH_AARCH64; } else { continue; } /* Search for existing matching (model,hvm) tuple */ for (i = 0; i < nr_guest_archs; i++) { if ((guest_archs[i].arch == arch) && guest_archs[i].hvm == hvm) break; } /* Too many arch flavours - highly unlikely ! */ if (i >= ARRAY_CARDINALITY(guest_archs)) continue; /* Didn't find a match, so create a new one */ if (i == nr_guest_archs) nr_guest_archs++; guest_archs[i].arch = arch; guest_archs[i].hvm = hvm; /* Careful not to overwrite a previous positive setting with a negative one here - some archs can do both pae & non-pae, but Xen reports separately capabilities so we're merging archs */ if (pae) guest_archs[i].pae = pae; if (nonpae) guest_archs[i].nonpae = nonpae; if (ia64_be) guest_archs[i].ia64_be = ia64_be; } } regfree(®ex); for (i = 0; i < nr_guest_archs; ++i) { virCapsGuestPtr guest; char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" : "xenpv"}; virCapsGuestMachinePtr *machines; if ((machines = virCapabilitiesAllocMachines(xen_machines, 1)) == NULL) return -1; if ((guest = virCapabilitiesAddGuest(caps, guest_archs[i].hvm ? "hvm" : "xen", guest_archs[i].arch, "qemu-dm", (guest_archs[i].hvm ? "hvmloader" : NULL), 1, machines)) == NULL) { virCapabilitiesFreeMachines(machines, 1); return -1; } machines = NULL; if (virCapabilitiesAddGuestDomain(guest, "xen", NULL, NULL, 0, NULL) == NULL) return -1; if (guest_archs[i].pae && virCapabilitiesAddGuestFeature(guest, "pae", 1, 0) == NULL) return -1; if (guest_archs[i].nonpae && virCapabilitiesAddGuestFeature(guest, "nonpae", 1, 0) == NULL) return -1; if (guest_archs[i].ia64_be && virCapabilitiesAddGuestFeature(guest, "ia64_be", 1, 0) == NULL) return -1; if (guest_archs[i].hvm) { if (virCapabilitiesAddGuestFeature(guest, "acpi", 1, 1) == NULL) return -1; if (virCapabilitiesAddGuestFeature(guest, "apic", 1, 0) == NULL) return -1; if (virCapabilitiesAddGuestFeature(guest, "hap", 0, 1) == NULL) return -1; } } return 0; }
/* qemuInterfaceBridgeConnect: * @def: the definition of the VM * @driver: qemu driver data * @net: pointer to the VM's interface description * @tapfd: array of file descriptor return value for the new device * @tapfdsize: number of file descriptors in @tapfd * * Called *only* called if actualType is VIR_DOMAIN_NET_TYPE_NETWORK or * VIR_DOMAIN_NET_TYPE_BRIDGE (i.e. if the connection is made with a tap * device connecting to a bridge device) */ int qemuInterfaceBridgeConnect(virDomainDefPtr def, virQEMUDriverPtr driver, virDomainNetDefPtr net, int *tapfd, size_t *tapfdSize) { const char *brname; int ret = -1; unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP; bool template_ifname = false; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); const char *tunpath = "/dev/net/tun"; if (net->backend.tap) { tunpath = net->backend.tap; if (!(virQEMUDriverIsPrivileged(driver))) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("cannot use custom tap device in session mode")); goto cleanup; } } if (!(brname = virDomainNetGetActualBridgeName(net))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing bridge name")); goto cleanup; } 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) goto cleanup; /* avoid exposing vnet%d in getXMLDesc or error outputs */ template_ifname = true; } if (net->model && STREQ(net->model, "virtio")) tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR; if (virQEMUDriverIsPrivileged(driver)) { if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac, def->uuid, tunpath, tapfd, *tapfdSize, virDomainNetGetActualVirtPortProfile(net), virDomainNetGetActualVlan(net), tap_create_flags) < 0) { virDomainAuditNetDevice(def, net, tunpath, false); goto cleanup; } if (virDomainNetGetActualBridgeMACTableManager(net) == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) { /* libvirt is managing the FDB of the bridge this device * is attaching to, so we need to turn off learning and * unicast_flood on the device to prevent the kernel from * adding any FDB entries for it. We will add add an fdb * entry ourselves (during qemuInterfaceStartDevices(), * using the MAC address from the interface config. */ if (virNetDevBridgePortSetLearning(brname, net->ifname, false) < 0) goto cleanup; if (virNetDevBridgePortSetUnicastFlood(brname, net->ifname, false) < 0) goto cleanup; } } else { if (qemuCreateInBridgePortWithHelper(cfg, brname, &net->ifname, tapfd, tap_create_flags) < 0) { virDomainAuditNetDevice(def, net, tunpath, false); goto cleanup; } /* qemuCreateInBridgePortWithHelper can only create a single FD */ if (*tapfdSize > 1) { VIR_WARN("Ignoring multiqueue network request"); *tapfdSize = 1; } } virDomainAuditNetDevice(def, net, tunpath, true); if (cfg->macFilter && ebtablesAddForwardAllowIn(driver->ebtables, net->ifname, &net->mac) < 0) goto cleanup; if (net->filter && virDomainConfNWFilterInstantiate(def->uuid, net) < 0) { goto cleanup; } ret = 0; cleanup: if (ret < 0) { size_t i; for (i = 0; i < *tapfdSize && tapfd[i] >= 0; i++) VIR_FORCE_CLOSE(tapfd[i]); if (template_ifname) VIR_FREE(net->ifname); } virObjectUnref(cfg); return ret; }
/* qemuInterfaceEthernetConnect: * @def: the definition of the VM * @driver: qemu driver data * @net: pointer to the VM's interface description * @tapfd: array of file descriptor return value for the new device * @tapfdsize: number of file descriptors in @tapfd * * Called *only* called if actualType is VIR_DOMAIN_NET_TYPE_ETHERNET * (i.e. if the connection is made with a tap device) */ int qemuInterfaceEthernetConnect(virDomainDefPtr def, virQEMUDriverPtr driver, virDomainNetDefPtr net, int *tapfd, size_t tapfdSize) { virMacAddr tapmac; int ret = -1; unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP; bool template_ifname = false; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); const char *tunpath = "/dev/net/tun"; if (net->backend.tap) { tunpath = net->backend.tap; if (!virQEMUDriverIsPrivileged(driver)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("cannot use custom tap device in session mode")); goto cleanup; } } 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) goto cleanup; /* avoid exposing vnet%d in getXMLDesc or error outputs */ template_ifname = true; } if (net->model && STREQ(net->model, "virtio")) tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR; if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize, tap_create_flags) < 0) { virDomainAuditNetDevice(def, net, tunpath, false); goto cleanup; } virDomainAuditNetDevice(def, net, tunpath, true); virMacAddrSet(&tapmac, &net->mac); tapmac.addr[0] = 0xFE; if (virNetDevSetMAC(net->ifname, &tapmac) < 0) goto cleanup; if (virNetDevSetOnline(net->ifname, true) < 0) goto cleanup; if (net->script && virNetDevRunEthernetScript(net->ifname, net->script) < 0) goto cleanup; if (cfg->macFilter && ebtablesAddForwardAllowIn(driver->ebtables, net->ifname, &net->mac) < 0) goto cleanup; if (net->filter && virDomainConfNWFilterInstantiate(def->uuid, net) < 0) { goto cleanup; } ret = 0; cleanup: if (ret < 0) { size_t i; for (i = 0; i < tapfdSize && tapfd[i] >= 0; i++) VIR_FORCE_CLOSE(tapfd[i]); if (template_ifname) VIR_FREE(net->ifname); } virObjectUnref(cfg); return ret; }
static int do_make_fs (const char *input, const char *output_str) { const char *dev, *options; CLEANUP_UNLINK_FREE char *output = NULL; uint64_t estimate, size; struct guestfs_disk_create_argv optargs; CLEANUP_FREE char *ifmt = NULL; CLEANUP_FREE char *ifile = NULL; pid_t pid; int status, fd; /* Use of CLEANUP_UNLINK_FREE *output ensures the output file is * deleted unless we successfully reach the end of this function. */ output = strdup (output_str); if (output == NULL) { perror ("strdup"); return -1; } /* Input. What is it? Estimate how much space it will need. */ if (estimate_input (input, &estimate, &ifmt) == -1) return -1; if (verbose) { fprintf (stderr, "input format = %s\n", ifmt); fprintf (stderr, "estimate = %" PRIu64 " bytes " "(%" PRIu64 " 1K blocks, %" PRIu64 " 4K blocks)\n", estimate, estimate / 1024, estimate / 4096); } estimate += 256 * 1024; /* For superblocks &c. */ if (STRPREFIX (type, "ext") && type[3] >= '3') { /* For ext3+, add some more for the journal. */ estimate += 1024 * 1024; } else if (STREQ (type, "ntfs")) { estimate += 4 * 1024 * 1024; /* NTFS journal. */ } else if (STREQ (type, "btrfs")) { /* For BTRFS, the minimum metadata allocation is 256MB, with data * additional to that. Note that we disable data and metadata * duplication below. */ estimate += 256 * 1024 * 1024; } /* Add 10%, see above. */ estimate *= 1.10; /* Calculate the output size. */ if (size_str == NULL) size = estimate; else if (parse_size (size_str, estimate, &size) == -1) return -1; /* Create the output disk. */ optargs.bitmask = 0; if (STREQ (format, "qcow2")) { optargs.bitmask |= GUESTFS_DISK_CREATE_PREALLOCATION_BITMASK; optargs.preallocation = "metadata"; } if (guestfs_disk_create_argv (g, output, format, size, &optargs) == -1) return -1; if (guestfs_add_drive_opts (g, output, GUESTFS_ADD_DRIVE_OPTS_FORMAT, format, -1) == -1) return -1; if (guestfs_launch (g) == -1) return -1; if (check_ntfs_available () == -1) return -1; /* Partition the disk. */ dev = "/dev/sda"; if (partition) { int mbr_id = 0; if (STREQ (partition, "")) partition = "mbr"; if (guestfs_part_disk (g, dev, partition) == -1) return -1; dev = "/dev/sda1"; /* Set the partition type byte if it's MBR and the filesystem type * is one that we know about. */ if (STREQ (partition, "mbr") || STREQ (partition, "msdos")) { if (STREQ (type, "msdos")) /* According to Wikipedia. However I have not actually tried this. */ mbr_id = 0x1; else if (STREQ (type, "vfat") || STREQ (type, "fat")) mbr_id = 0xb; else if (STREQ (type, "ntfs")) mbr_id = 0x7; else if (STRPREFIX (type, "ext")) mbr_id = 0x83; else if (STREQ (type, "minix")) mbr_id = 0x81; } if (mbr_id != 0) { if (guestfs_part_set_mbr_id (g, "/dev/sda", 1, mbr_id) == -1) return -1; } } if (verbose) fprintf (stderr, "creating %s filesystem on %s ...\n", type, dev); /* Create the filesystem. */ if (STRNEQ (type, "btrfs")) { int r; struct guestfs_mkfs_opts_argv optargs = { .bitmask = 0 }; if (label) { optargs.label = label; optargs.bitmask |= GUESTFS_MKFS_OPTS_LABEL_BITMASK; } guestfs_push_error_handler (g, NULL, NULL); r = guestfs_mkfs_opts_argv (g, type, dev, &optargs); guestfs_pop_error_handler (g); if (r == -1) { /* Provide more guidance in the error message (RHBZ#823883). */ fprintf (stderr, "%s: 'mkfs' (create filesystem) operation failed: %s\n", guestfs_int_program_name, guestfs_last_error (g)); if (STREQ (type, "fat")) fprintf (stderr, "Instead of 'fat', try 'vfat' (long filenames) or 'msdos' (short filenames).\n"); else fprintf (stderr, "Is '%s' a correct filesystem type?\n", type); return -1; } } else {
static guestfs_int_isoinfo * parse_isoinfo (char **lines) { guestfs_int_isoinfo *ret; size_t i; ret = calloc (1, sizeof *ret); if (ret == NULL) { reply_with_perror ("calloc"); return NULL; } /* Default each int field in the struct to -1. */ ret->iso_volume_space_size = (uint32_t) -1; ret->iso_volume_set_size = (uint32_t) -1; ret->iso_volume_sequence_number = (uint32_t) -1; ret->iso_logical_block_size = (uint32_t) -1; ret->iso_volume_creation_t = -1; ret->iso_volume_modification_t = -1; ret->iso_volume_expiration_t = -1; ret->iso_volume_effective_t = -1; for (i = 0; lines[i] != NULL; ++i) { if (STRPREFIX (lines[i], "System id: ")) { ret->iso_system_id = strdup (&lines[i][11]); if (ret->iso_system_id == NULL) goto error; } else if (STRPREFIX (lines[i], "Volume id: ")) { ret->iso_volume_id = strdup (&lines[i][11]); if (ret->iso_volume_id == NULL) goto error; } else if (STRPREFIX (lines[i], "Volume set id: ")) { ret->iso_volume_set_id = strdup (&lines[i][15]); if (ret->iso_volume_set_id == NULL) goto error; } else if (STRPREFIX (lines[i], "Publisher id: ")) { ret->iso_publisher_id = strdup (&lines[i][14]); if (ret->iso_publisher_id == NULL) goto error; } else if (STRPREFIX (lines[i], "Data preparer id: ")) { ret->iso_data_preparer_id = strdup (&lines[i][18]); if (ret->iso_data_preparer_id == NULL) goto error; } else if (STRPREFIX (lines[i], "Application id: ")) { ret->iso_application_id = strdup (&lines[i][16]); if (ret->iso_application_id == NULL) goto error; } else if (STRPREFIX (lines[i], "Copyright File id: ")) { ret->iso_copyright_file_id = strdup (&lines[i][19]); if (ret->iso_copyright_file_id == NULL) goto error; } else if (STRPREFIX (lines[i], "Abstract File id: ")) { ret->iso_abstract_file_id = strdup (&lines[i][18]); if (ret->iso_abstract_file_id == NULL) goto error; } else if (STRPREFIX (lines[i], "Bibliographic File id: ")) { ret->iso_bibliographic_file_id = strdup (&lines[i][23]); if (ret->iso_bibliographic_file_id == NULL) goto error; } else if (STRPREFIX (lines[i], "Volume size is: ")) { if (parse_uint32 (&ret->iso_volume_space_size, &lines[i][16]) == -1) goto error; } else if (STRPREFIX (lines[i], "Volume set size is: ")) { if (parse_uint32 (&ret->iso_volume_set_size, &lines[i][20]) == -1) goto error; } else if (STRPREFIX (lines[i], "Volume set sequence number is: ")) { if (parse_uint32 (&ret->iso_volume_sequence_number, &lines[i][31]) == -1) goto error; } else if (STRPREFIX (lines[i], "Logical block size is: ")) { if (parse_uint32 (&ret->iso_logical_block_size, &lines[i][23]) == -1) goto error; } else if (STRPREFIX (lines[i], "Creation Date: ")) { if (parse_time_t (&ret->iso_volume_creation_t, &lines[i][19]) == -1) goto error; } else if (STRPREFIX (lines[i], "Modification Date: ")) { if (parse_time_t (&ret->iso_volume_modification_t, &lines[i][19]) == -1) goto error; } else if (STRPREFIX (lines[i], "Expiration Date: ")) { if (parse_time_t (&ret->iso_volume_expiration_t, &lines[i][19]) == -1) goto error; } else if (STRPREFIX (lines[i], "Effective Date: ")) { if (parse_time_t (&ret->iso_volume_effective_t, &lines[i][19]) == -1) goto error; } } /* Any string fields which were not set above will be NULL. However * we cannot return NULL fields in structs, so we convert these to * empty strings here. */ if (ret->iso_system_id == NULL) { ret->iso_system_id = strdup (""); if (ret->iso_system_id == NULL) goto error; } if (ret->iso_volume_id == NULL) { ret->iso_volume_id = strdup (""); if (ret->iso_volume_id == NULL) goto error; } if (ret->iso_volume_set_id == NULL) { ret->iso_volume_set_id = strdup (""); if (ret->iso_volume_set_id == NULL) goto error; } if (ret->iso_publisher_id == NULL) { ret->iso_publisher_id = strdup (""); if (ret->iso_publisher_id == NULL) goto error; } if (ret->iso_data_preparer_id == NULL) { ret->iso_data_preparer_id = strdup (""); if (ret->iso_data_preparer_id == NULL) goto error; } if (ret->iso_application_id == NULL) { ret->iso_application_id = strdup (""); if (ret->iso_application_id == NULL) goto error; } if (ret->iso_copyright_file_id == NULL) { ret->iso_copyright_file_id = strdup (""); if (ret->iso_copyright_file_id == NULL) goto error; } if (ret->iso_abstract_file_id == NULL) { ret->iso_abstract_file_id = strdup (""); if (ret->iso_abstract_file_id == NULL) goto error; } if (ret->iso_bibliographic_file_id == NULL) { ret->iso_bibliographic_file_id = strdup (""); if (ret->iso_bibliographic_file_id == NULL) goto error; } return ret; error: free (ret->iso_system_id); free (ret->iso_volume_id); free (ret->iso_volume_set_id); free (ret->iso_publisher_id); free (ret->iso_data_preparer_id); free (ret->iso_application_id); free (ret->iso_copyright_file_id); free (ret->iso_abstract_file_id); free (ret->iso_bibliographic_file_id); free (ret); return NULL; }
/* * For details on xl disk config syntax, see * docs/misc/xl-disk-configuration.txt in the Xen sources. The important * section of text is: * * More formally, the string is a series of comma-separated keyword/value * pairs, flags and positional parameters. Parameters which are not bare * keywords and which do not contain "=" symbols are assigned to the * so-far-unspecified positional parameters, in the order below. The * positional parameters may also be specified explicitly by name. * * Each parameter may be specified at most once, either as a positional * parameter or a named parameter. Default values apply if the parameter * is not specified, or if it is specified with an empty value (whether * positionally or explicitly). * * Whitespace may appear before each parameter and will be ignored. * * The order of the positional parameters mentioned in the quoted text is: * * target,format,vdev,access * * The following options must be specified by key=value: * * devtype=<devtype> * backendtype=<backend-type> * * The following options are currently not supported: * * backend=<domain-name> * script=<script> * direct-io-safe * */ static int xenParseXLDisk(virConfPtr conf, virDomainDefPtr def) { int ret = -1; virConfValuePtr list = virConfGetValue(conf, "disk"); XLU_Config *xluconf; libxl_device_disk *libxldisk; virDomainDiskDefPtr disk = NULL; if (VIR_ALLOC(libxldisk) < 0) return -1; if (!(xluconf = xlu_cfg_init(stderr, "command line"))) goto cleanup; if (list && list->type == VIR_CONF_LIST) { list = list->list; while (list) { const char *disk_spec = list->str; if (list->type != VIR_CONF_STRING || list->str == NULL) goto skipdisk; libxl_device_disk_init(libxldisk); if (xlu_disk_parse(xluconf, 1, &disk_spec, libxldisk)) goto fail; if (!(disk = virDomainDiskDefNew(NULL))) goto fail; if (xenParseXLDiskSrc(disk, libxldisk->pdev_path) < 0) goto fail; if (VIR_STRDUP(disk->dst, libxldisk->vdev) < 0) goto fail; disk->src->readonly = !libxldisk->readwrite; disk->removable = libxldisk->removable; if (libxldisk->is_cdrom) { if (virDomainDiskSetDriver(disk, "qemu") < 0) goto fail; virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE); disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; if (!disk->src->path || STREQ(disk->src->path, "")) disk->src->format = VIR_STORAGE_FILE_NONE; else disk->src->format = VIR_STORAGE_FILE_RAW; } else { switch (libxldisk->format) { case LIBXL_DISK_FORMAT_QCOW: disk->src->format = VIR_STORAGE_FILE_QCOW; break; case LIBXL_DISK_FORMAT_QCOW2: disk->src->format = VIR_STORAGE_FILE_QCOW2; break; case LIBXL_DISK_FORMAT_VHD: disk->src->format = VIR_STORAGE_FILE_VHD; break; case LIBXL_DISK_FORMAT_RAW: case LIBXL_DISK_FORMAT_UNKNOWN: disk->src->format = VIR_STORAGE_FILE_RAW; break; case LIBXL_DISK_FORMAT_EMPTY: break; } switch (libxldisk->backend) { case LIBXL_DISK_BACKEND_QDISK: case LIBXL_DISK_BACKEND_UNKNOWN: if (virDomainDiskSetDriver(disk, "qemu") < 0) goto fail; if (virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_NONE) virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE); break; case LIBXL_DISK_BACKEND_TAP: if (virDomainDiskSetDriver(disk, "tap") < 0) goto fail; virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE); break; case LIBXL_DISK_BACKEND_PHY: if (virDomainDiskSetDriver(disk, "phy") < 0) goto fail; virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK); break; } } if (STRPREFIX(libxldisk->vdev, "xvd") || def->os.type != VIR_DOMAIN_OSTYPE_HVM) disk->bus = VIR_DOMAIN_DISK_BUS_XEN; else if (STRPREFIX(libxldisk->vdev, "sd")) disk->bus = VIR_DOMAIN_DISK_BUS_SCSI; else disk->bus = VIR_DOMAIN_DISK_BUS_IDE; if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0) goto fail; libxl_device_disk_dispose(libxldisk); skipdisk: list = list->next; } } ret = 0; cleanup: virDomainDiskDefFree(disk); xlu_cfg_destroy(xluconf); VIR_FREE(libxldisk); return ret; fail: libxl_device_disk_dispose(libxldisk); goto cleanup; }