/* XXX add an incremental streaming parser - yajl trivially supports it */ virJSONValuePtr virJSONValueFromString(const char *jsonstring) { yajl_handle hand; virJSONParser parser = { NULL, NULL, 0 }; virJSONValuePtr ret = NULL; # ifndef WITH_YAJL2 yajl_parser_config cfg = { 1, 1 }; # endif VIR_DEBUG("string=%s", jsonstring); # ifdef WITH_YAJL2 hand = yajl_alloc(&parserCallbacks, NULL, &parser); if (hand) { yajl_config(hand, yajl_allow_comments, 1); yajl_config(hand, yajl_dont_validate_strings, 0); } # else hand = yajl_alloc(&parserCallbacks, &cfg, NULL, &parser); # endif if (!hand) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to create JSON parser")); goto cleanup; } if (yajl_parse(hand, (const unsigned char *)jsonstring, strlen(jsonstring)) != yajl_status_ok) { unsigned char *errstr = yajl_get_error(hand, 1, (const unsigned char*)jsonstring, strlen(jsonstring)); virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot parse json %s: %s"), jsonstring, (const char*) errstr); VIR_FREE(errstr); virJSONValueFree(parser.head); goto cleanup; } if (parser.nstate != 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot parse json %s: unterminated string/map/array"), jsonstring); virJSONValueFree(parser.head); } else { ret = parser.head; } cleanup: yajl_free(hand); if (parser.nstate) { size_t i; for (i = 0; i < parser.nstate; i++) VIR_FREE(parser.state[i].key); VIR_FREE(parser.state); } VIR_DEBUG("result=%p", parser.head); return ret; }
static int virLXCControllerSetupNUMAPolicy(virLXCControllerPtr ctrl) { nodemask_t mask; int mode = -1; int node = -1; int ret = -1; int i = 0; int maxnode = 0; bool warned = false; if (!ctrl->def->numatune.memory.nodemask) return 0; VIR_DEBUG("Setting NUMA memory policy"); if (numa_available() < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Host kernel is not aware of NUMA.")); return -1; } maxnode = numa_max_node() + 1; /* Convert nodemask to NUMA bitmask. */ nodemask_zero(&mask); i = -1; while ((i = virBitmapNextSetBit(ctrl->def->numatune.memory.nodemask, i)) >= 0) { if (i > NUMA_NUM_NODES) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Host cannot support NUMA node %d"), i); return -1; } if (i > maxnode && !warned) { VIR_WARN("nodeset is out of range, there is only %d NUMA " "nodes on host", maxnode); warned = true; } nodemask_set(&mask, i); } mode = ctrl->def->numatune.memory.mode; if (mode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) { numa_set_bind_policy(1); numa_set_membind(&mask); numa_set_bind_policy(0); } else if (mode == VIR_DOMAIN_NUMATUNE_MEM_PREFERRED) { int nnodes = 0; for (i = 0; i < NUMA_NUM_NODES; i++) { if (nodemask_isset(&mask, i)) { node = i; nnodes++; } } if (nnodes != 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("NUMA memory tuning in 'preferred' mode " "only supports single node")); goto cleanup; } numa_set_bind_policy(0); numa_set_preferred(node); } else if (mode == VIR_DOMAIN_NUMATUNE_MEM_INTERLEAVE) { numa_set_interleave_mask(&mask); } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unable to set NUMA policy %s"), virDomainNumatuneMemModeTypeToString(mode)); goto cleanup; } ret = 0; cleanup: return ret; }
static int virJSONValueToStringOne(virJSONValuePtr object, yajl_gen g) { size_t i; VIR_DEBUG("object=%p type=%d gen=%p", object, object->type, g); switch (object->type) { case VIR_JSON_TYPE_OBJECT: if (yajl_gen_map_open(g) != yajl_gen_status_ok) return -1; for (i = 0; i < object->data.object.npairs; i++) { if (yajl_gen_string(g, (unsigned char *)object->data.object.pairs[i].key, strlen(object->data.object.pairs[i].key)) != yajl_gen_status_ok) return -1; if (virJSONValueToStringOne(object->data.object.pairs[i].value, g) < 0) return -1; } if (yajl_gen_map_close(g) != yajl_gen_status_ok) return -1; break; case VIR_JSON_TYPE_ARRAY: if (yajl_gen_array_open(g) != yajl_gen_status_ok) return -1; for (i = 0; i < object->data.array.nvalues; i++) { if (virJSONValueToStringOne(object->data.array.values[i], g) < 0) return -1; } if (yajl_gen_array_close(g) != yajl_gen_status_ok) return -1; break; case VIR_JSON_TYPE_STRING: if (yajl_gen_string(g, (unsigned char *)object->data.string, strlen(object->data.string)) != yajl_gen_status_ok) return -1; break; case VIR_JSON_TYPE_NUMBER: if (yajl_gen_number(g, object->data.number, strlen(object->data.number)) != yajl_gen_status_ok) return -1; break; case VIR_JSON_TYPE_BOOLEAN: if (yajl_gen_bool(g, object->data.boolean) != yajl_gen_status_ok) return -1; break; case VIR_JSON_TYPE_NULL: if (yajl_gen_null(g) != yajl_gen_status_ok) return -1; break; default: return -1; } return 0; }
static int nodeDeviceVportCreateDelete(const int parent_host, const char *wwpn, const char *wwnn, int operation) { int retval = 0; char *operation_path = NULL, *vport_name = NULL; const char *operation_file = NULL; struct stat st; switch (operation) { case VPORT_CREATE: operation_file = LINUX_SYSFS_VPORT_CREATE_POSTFIX; break; case VPORT_DELETE: operation_file = LINUX_SYSFS_VPORT_DELETE_POSTFIX; break; default: virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid vport operation (%d)"), operation); retval = -1; goto cleanup; break; } if (virAsprintf(&operation_path, "%shost%d%s", LINUX_SYSFS_FC_HOST_PREFIX, parent_host, operation_file) < 0) { virReportOOMError(); retval = -1; goto cleanup; } if (stat(operation_path, &st) != 0) { VIR_FREE(operation_path); if (virAsprintf(&operation_path, "%shost%d%s", LINUX_SYSFS_SCSI_HOST_PREFIX, parent_host, operation_file) < 0) { virReportOOMError(); retval = -1; goto cleanup; } if (stat(operation_path, &st) != 0) { VIR_ERROR(_("No vport operation path found for host%d"), parent_host); retval = -1; goto cleanup; } } VIR_DEBUG("Vport operation path is '%s'", operation_path); if (virAsprintf(&vport_name, "%s:%s", wwpn, wwnn) < 0) { virReportOOMError(); retval = -1; goto cleanup; } if (virFileWriteStr(operation_path, vport_name, 0) == -1) { virReportSystemError(errno, _("Write of '%s' to '%s' during " "vport create/delete failed"), vport_name, operation_path); retval = -1; } cleanup: VIR_FREE(vport_name); VIR_FREE(operation_path); VIR_DEBUG("%s", _("Vport operation complete")); return retval; }
static void virLXCControllerClientPrivateFree(void *data) { virLXCControllerPtr ctrl = data; VIR_DEBUG("Got private data free %p", ctrl); }
static int virStorageBackendIQNFound(const char *initiatoriqn, char **ifacename) { int ret = IQN_MISSING, fd = -1; char ebuf[64]; FILE *fp = NULL; char *line = NULL, *newline = NULL, *iqn = NULL, *token = NULL; virCommandPtr cmd = virCommandNewArgList(ISCSIADM, "--mode", "iface", NULL); if (VIR_ALLOC_N(line, LINE_SIZE) != 0) { ret = IQN_ERROR; virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not allocate memory for output of '%s'"), ISCSIADM); goto out; } memset(line, 0, LINE_SIZE); virCommandSetOutputFD(cmd, &fd); if (virCommandRunAsync(cmd, NULL) < 0) { ret = IQN_ERROR; goto out; } if ((fp = VIR_FDOPEN(fd, "r")) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to open stream for file descriptor " "when reading output from '%s': '%s'"), ISCSIADM, virStrerror(errno, ebuf, sizeof(ebuf))); ret = IQN_ERROR; goto out; } while (fgets(line, LINE_SIZE, fp) != NULL) { newline = strrchr(line, '\n'); if (newline == NULL) { ret = IQN_ERROR; virReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected line > %d characters " "when parsing output of '%s'"), LINE_SIZE, ISCSIADM); goto out; } *newline = '\0'; iqn = strrchr(line, ','); if (iqn == NULL) { continue; } iqn++; if (STREQ(iqn, initiatoriqn)) { token = strchr(line, ' '); if (!token) { ret = IQN_ERROR; virReportError(VIR_ERR_INTERNAL_ERROR, _("Missing space when parsing output " "of '%s'"), ISCSIADM); goto out; } if (VIR_STRNDUP(*ifacename, line, token - line) < 0) { ret = IQN_ERROR; goto out; } VIR_DEBUG("Found interface '%s' with IQN '%s'", *ifacename, iqn); ret = IQN_FOUND; break; } } if (virCommandWait(cmd, NULL) < 0) ret = IQN_ERROR; out: if (ret == IQN_MISSING) { VIR_DEBUG("Could not find interface with IQN '%s'", iqn); } VIR_FREE(line); VIR_FORCE_FCLOSE(fp); VIR_FORCE_CLOSE(fd); virCommandFree(cmd); return ret; }
static virNetSocketPtr virNetSocketNew(virSocketAddrPtr localAddr, virSocketAddrPtr remoteAddr, bool isClient, int fd, int errfd, pid_t pid) { virNetSocketPtr sock; int no_slow_start = 1; VIR_DEBUG("localAddr=%p remoteAddr=%p fd=%d errfd=%d pid=%lld", localAddr, remoteAddr, fd, errfd, (long long) pid); if (virSetCloseExec(fd) < 0) { virReportSystemError(errno, "%s", _("Unable to set close-on-exec flag")); return NULL; } if (virSetNonBlock(fd) < 0) { virReportSystemError(errno, "%s", _("Unable to enable non-blocking flag")); return NULL; } if (VIR_ALLOC(sock) < 0) { virReportOOMError(); return NULL; } if (virMutexInit(&sock->lock) < 0) { virReportSystemError(errno, "%s", _("Unable to initialize mutex")); VIR_FREE(sock); return NULL; } sock->refs = 1; if (localAddr) sock->localAddr = *localAddr; if (remoteAddr) sock->remoteAddr = *remoteAddr; sock->fd = fd; sock->errfd = errfd; sock->pid = pid; /* Disable nagle for TCP sockets */ if (sock->localAddr.data.sa.sa_family == AF_INET || sock->localAddr.data.sa.sa_family == AF_INET6) { if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &no_slow_start, sizeof(no_slow_start)) < 0) { virReportSystemError(errno, "%s", _("Unable to disable nagle algorithm")); goto error; } } if (localAddr && !(sock->localAddrStr = virSocketAddrFormatFull(localAddr, true, ";"))) goto error; if (remoteAddr && !(sock->remoteAddrStr = virSocketAddrFormatFull(remoteAddr, true, ";"))) goto error; sock->client = isClient; PROBE(RPC_SOCKET_NEW, "sock=%p refs=%d fd=%d errfd=%d pid=%lld localAddr=%s, remoteAddr=%s", sock, sock->refs, fd, errfd, (long long) pid, NULLSTR(sock->localAddrStr), NULLSTR(sock->remoteAddrStr)); return sock; error: sock->fd = sock->errfd = -1; /* Caller owns fd/errfd on failure */ virNetSocketFree(sock); return NULL; }
int virLXCProcessStop(virLXCDriverPtr driver, virDomainObjPtr vm, virDomainShutoffReason reason) { int rc; virLXCDomainObjPrivatePtr priv; VIR_DEBUG("Stopping VM name=%s pid=%d reason=%d", vm->def->name, (int)vm->pid, (int)reason); if (!virDomainObjIsActive(vm)) { VIR_DEBUG("VM '%s' not active", vm->def->name); return 0; } priv = vm->privateData; if (vm->pid <= 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid PID %d for container"), vm->pid); return -1; } virSecurityManagerRestoreAllLabel(driver->securityManager, vm->def, false); virSecurityManagerReleaseLabel(driver->securityManager, vm->def); /* Clear out dynamically assigned labels */ if (vm->def->nseclabels && vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC) { VIR_FREE(vm->def->seclabels[0]->model); VIR_FREE(vm->def->seclabels[0]->label); VIR_FREE(vm->def->seclabels[0]->imagelabel); } /* If the LXC domain is suspended we send all processes a SIGKILL * and thaw them. Upon wakeup the process sees the pending signal * and dies immediately. It is guaranteed that priv->cgroup != NULL * here because the domain has aleady been suspended using the * freezer cgroup. */ if (reason == VIR_DOMAIN_SHUTOFF_DESTROYED && virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) { if (virCgroupKillRecursive(priv->cgroup, SIGKILL) <= 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to kill all processes")); return -1; } if (virCgroupSetFreezerState(priv->cgroup, "THAWED") < 0) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Unable to thaw all processes")); return -1; } goto cleanup; } if (priv->cgroup) { rc = virCgroupKillPainfully(priv->cgroup); if (rc < 0) return -1; if (rc > 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Some processes refused to die")); return -1; } } else { /* If cgroup doesn't exist, just try cleaning up the * libvirt_lxc process */ if (virProcessKillPainfully(vm->pid, true) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Processes %d refused to die"), (int)vm->pid); return -1; } } cleanup: virLXCProcessCleanup(driver, vm, reason); return 0; }
/** * xenStoreOpen: * @conn: pointer to the connection block * @name: URL for the target, NULL for local * @flags: combination of virDrvOpenFlag(s) * * Connects to the Xen hypervisor. * * Returns 0 or -1 in case of error. */ int xenStoreOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, unsigned int flags) { xenUnifiedPrivatePtr priv = conn->privateData; virCheckFlags(VIR_CONNECT_RO, -1); if (flags & VIR_CONNECT_RO) priv->xshandle = xs_daemon_open_readonly(); else priv->xshandle = xs_daemon_open(); if (priv->xshandle == NULL) { /* * not being able to connect via the socket as an unprivileged * user is rather normal, this should fallback to the proxy (or * remote) mechanism. */ if (xenHavePrivilege()) { virReportError(VIR_ERR_NO_XEN, "%s", _("failed to connect to Xen Store")); } return -1; } /* Init activeDomainList */ if (VIR_ALLOC(priv->activeDomainList) < 0) return -1; /* Init watch list before filling in domInfoList, so we can know if it is the first time through when the callback fires */ if (VIR_ALLOC(priv->xsWatchList) < 0) return -1; /* This will get called once at start */ if (xenStoreAddWatch(conn, "@releaseDomain", "releaseDomain", xenStoreDomainReleased, priv) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("adding watch @releaseDomain")); return -1; } /* The initial call of this will fill domInfoList */ if (xenStoreAddWatch(conn, "@introduceDomain", "introduceDomain", xenStoreDomainIntroduced, priv) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("adding watch @introduceDomain")); return -1; } /* Add an event handle */ if ((priv->xsWatch = virEventAddHandle(xs_fileno(priv->xshandle), VIR_EVENT_HANDLE_READABLE, xenStoreWatchEvent, conn, NULL)) < 0) VIR_DEBUG("Failed to add event handle, disabling events"); return 0; }
static int virLXCProcessReconnectDomain(virDomainObjPtr vm, void *opaque) { virLXCDriverPtr driver = opaque; virLXCDomainObjPrivatePtr priv; int ret = -1; virObjectLock(vm); VIR_DEBUG("Reconnect id=%d pid=%d state=%d", vm->def->id, vm->pid, vm->state.state); priv = vm->privateData; if (vm->pid != 0) { vm->def->id = vm->pid; virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN); if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback) driver->inhibitCallback(true, driver->inhibitOpaque); if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm))) goto error; if (virCgroupNewDetectMachine(vm->def->name, "lxc", vm->pid, -1, &priv->cgroup) < 0) goto error; if (!priv->cgroup) { virReportError(VIR_ERR_INTERNAL_ERROR, _("No valid cgroup for machine %s"), vm->def->name); goto error; } if (virLXCUpdateActiveUSBHostdevs(driver, vm->def) < 0) goto error; if (virSecurityManagerReserveLabel(driver->securityManager, vm->def, vm->pid) < 0) goto error; /* now that we know it's reconnected call the hook if present */ if (virHookPresent(VIR_HOOK_DRIVER_LXC)) { char *xml = virDomainDefFormat(vm->def, 0); int hookret; /* we can't stop the operation even if the script raised an error */ hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name, VIR_HOOK_LXC_OP_RECONNECT, VIR_HOOK_SUBOP_BEGIN, NULL, xml, NULL); VIR_FREE(xml); if (hookret < 0) goto error; } } else { vm->def->id = -1; } ret = 0; cleanup: virObjectUnlock(vm); return ret; error: virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED); virDomainAuditStop(vm, "failed"); goto cleanup; }
/** * virLXCProcessCleanup: * @driver: pointer to driver structure * @vm: pointer to VM to clean up * @reason: reason for switching the VM to shutoff state * * Cleanout resources associated with the now dead VM * */ static void virLXCProcessCleanup(virLXCDriverPtr driver, virDomainObjPtr vm, virDomainShutoffReason reason) { size_t i; virLXCDomainObjPrivatePtr priv = vm->privateData; virNetDevVPortProfilePtr vport = NULL; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); VIR_DEBUG("Cleanup VM name=%s pid=%d reason=%d", vm->def->name, (int)vm->pid, (int)reason); /* now that we know it's stopped call the hook if present */ if (virHookPresent(VIR_HOOK_DRIVER_LXC)) { char *xml = virDomainDefFormat(vm->def, 0); /* we can't stop the operation even if the script raised an error */ virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name, VIR_HOOK_LXC_OP_STOPPED, VIR_HOOK_SUBOP_END, NULL, xml, NULL); VIR_FREE(xml); } /* Stop autodestroy in case guest is restarted */ virCloseCallbacksUnset(driver->closeCallbacks, vm, lxcProcessAutoDestroy); if (priv->monitor) { virLXCMonitorClose(priv->monitor); virObjectUnref(priv->monitor); priv->monitor = NULL; } virPidFileDelete(cfg->stateDir, vm->def->name); lxcProcessRemoveDomainStatus(cfg, vm); virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason); vm->pid = -1; vm->def->id = -1; if (virAtomicIntDecAndTest(&driver->nactive) && driver->inhibitCallback) driver->inhibitCallback(false, driver->inhibitOpaque); virLXCDomainReAttachHostDevices(driver, vm->def); for (i = 0; i < vm->def->nnets; i++) { virDomainNetDefPtr iface = vm->def->nets[i]; vport = virDomainNetGetActualVirtPortProfile(iface); if (iface->ifname) { if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) ignore_value(virNetDevOpenvswitchRemovePort( virDomainNetGetActualBridgeName(iface), iface->ifname)); ignore_value(virNetDevVethDelete(iface->ifname)); } networkReleaseActualDevice(vm->def, iface); } virDomainConfVMNWFilterTeardown(vm); if (priv->cgroup) { virCgroupRemove(priv->cgroup); virCgroupFree(&priv->cgroup); } /* Get machined to terminate the machine as it may not have cleaned it * properly. See https://bugs.freedesktop.org/show_bug.cgi?id=68370 for * the bug we are working around here. */ virSystemdTerminateMachine(vm->def->name, "lxc", true); /* The "release" hook cleans up additional resources */ if (virHookPresent(VIR_HOOK_DRIVER_LXC)) { char *xml = virDomainDefFormat(vm->def, 0); /* we can't stop the operation even if the script raised an error */ virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name, VIR_HOOK_LXC_OP_RELEASE, VIR_HOOK_SUBOP_END, NULL, xml, NULL); VIR_FREE(xml); } if (vm->newDef) { virDomainDefFree(vm->def); vm->def = vm->newDef; vm->def->id = -1; vm->newDef = NULL; } virObjectUnref(cfg); }
/** * virLXCProcessStart: * @conn: pointer to connection * @driver: pointer to driver structure * @vm: pointer to virtual machine structure * @autoDestroy: mark the domain for auto destruction * @reason: reason for switching vm to running state * * Starts a vm * * Returns 0 on success or -1 in case of error */ int virLXCProcessStart(virConnectPtr conn, virLXCDriverPtr driver, virDomainObjPtr vm, unsigned int nfiles, int *files, bool autoDestroy, virDomainRunningReason reason) { int rc = -1, r; size_t nttyFDs = 0; int *ttyFDs = NULL; size_t i; char *logfile = NULL; int logfd = -1; size_t nveths = 0; char **veths = NULL; int handshakefds[2] = { -1, -1 }; off_t pos = -1; char ebuf[1024]; char *timestamp; virCommandPtr cmd = NULL; virLXCDomainObjPrivatePtr priv = vm->privateData; virCapsPtr caps = NULL; virErrorPtr err = NULL; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); virCgroupPtr selfcgroup; int status; char *pidfile = NULL; bool clearSeclabel = false; bool need_stop = false; if (virCgroupNewSelf(&selfcgroup) < 0) return -1; if (!virCgroupHasController(selfcgroup, VIR_CGROUP_CONTROLLER_CPUACCT)) { virCgroupFree(&selfcgroup); virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to find 'cpuacct' cgroups controller mount")); return -1; } if (!virCgroupHasController(selfcgroup, VIR_CGROUP_CONTROLLER_DEVICES)) { virCgroupFree(&selfcgroup); virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to find 'devices' cgroups controller mount")); return -1; } if (!virCgroupHasController(selfcgroup, VIR_CGROUP_CONTROLLER_MEMORY)) { virCgroupFree(&selfcgroup); virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to find 'memory' cgroups controller mount")); return -1; } virCgroupFree(&selfcgroup); if (vm->def->nconsoles == 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("At least one PTY console is required")); return -1; } for (i = 0; i < vm->def->nconsoles; i++) { if (vm->def->consoles[i]->source.type != VIR_DOMAIN_CHR_TYPE_PTY) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Only PTY console types are supported")); return -1; } } if (virFileMakePath(cfg->logDir) < 0) { virReportSystemError(errno, _("Cannot create log directory '%s'"), cfg->logDir); return -1; } if (!vm->def->resource) { virDomainResourceDefPtr res; if (VIR_ALLOC(res) < 0) goto cleanup; if (VIR_STRDUP(res->partition, "/machine") < 0) { VIR_FREE(res); goto cleanup; } vm->def->resource = res; } if (virAsprintf(&logfile, "%s/%s.log", cfg->logDir, vm->def->name) < 0) goto cleanup; if (!(pidfile = virPidFileBuildPath(cfg->stateDir, vm->def->name))) goto cleanup; if (!(caps = virLXCDriverGetCapabilities(driver, false))) goto cleanup; /* Do this up front, so any part of the startup process can add * runtime state to vm->def that won't be persisted. This let's us * report implicit runtime defaults in the XML, like vnc listen/socket */ VIR_DEBUG("Setting current domain def as transient"); if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, true) < 0) goto cleanup; /* Run an early hook to set-up missing devices */ if (virHookPresent(VIR_HOOK_DRIVER_LXC)) { char *xml = virDomainDefFormat(vm->def, 0); int hookret; hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name, VIR_HOOK_LXC_OP_PREPARE, VIR_HOOK_SUBOP_BEGIN, NULL, xml, NULL); VIR_FREE(xml); /* * If the script raised an error abort the launch */ if (hookret < 0) goto cleanup; } if (virLXCProcessEnsureRootFS(vm) < 0) goto cleanup; /* Must be run before security labelling */ VIR_DEBUG("Preparing host devices"); if (virLXCPrepareHostDevices(driver, vm->def) < 0) goto cleanup; /* Here we open all the PTYs we need on the host OS side. * The LXC controller will open the guest OS side PTYs * and forward I/O between them. */ nttyFDs = vm->def->nconsoles; if (VIR_ALLOC_N(ttyFDs, nttyFDs) < 0) goto cleanup; for (i = 0; i < vm->def->nconsoles; i++) ttyFDs[i] = -1; /* If you are using a SecurityDriver with dynamic labelling, then generate a security label for isolation */ VIR_DEBUG("Generating domain security label (if required)"); clearSeclabel = vm->def->nseclabels == 0 || vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DEFAULT; if (vm->def->nseclabels && vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DEFAULT) vm->def->seclabels[0]->type = VIR_DOMAIN_SECLABEL_NONE; if (virSecurityManagerCheckAllLabel(driver->securityManager, vm->def) < 0) goto cleanup; if (virSecurityManagerGenLabel(driver->securityManager, vm->def) < 0) { virDomainAuditSecurityLabel(vm, false); goto cleanup; } virDomainAuditSecurityLabel(vm, true); VIR_DEBUG("Setting domain security labels"); if (virSecurityManagerSetAllLabel(driver->securityManager, vm->def, NULL) < 0) goto cleanup; VIR_DEBUG("Setting up consoles"); for (i = 0; i < vm->def->nconsoles; i++) { char *ttyPath; if (virFileOpenTty(&ttyFDs[i], &ttyPath, 1) < 0) { virReportSystemError(errno, "%s", _("Failed to allocate tty")); goto cleanup; } VIR_FREE(vm->def->consoles[i]->source.data.file.path); vm->def->consoles[i]->source.data.file.path = ttyPath; VIR_FREE(vm->def->consoles[i]->info.alias); if (virAsprintf(&vm->def->consoles[i]->info.alias, "console%zu", i) < 0) goto cleanup; } VIR_DEBUG("Setting up Interfaces"); if (virLXCProcessSetupInterfaces(conn, vm->def, &nveths, &veths) < 0) goto cleanup; VIR_DEBUG("Preparing to launch"); if ((logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR|S_IWUSR)) < 0) { virReportSystemError(errno, _("Failed to open '%s'"), logfile); goto cleanup; } if (pipe(handshakefds) < 0) { virReportSystemError(errno, "%s", _("Unable to create pipe")); goto cleanup; } if (!(cmd = virLXCProcessBuildControllerCmd(driver, vm, nveths, veths, ttyFDs, nttyFDs, files, nfiles, handshakefds[1], &logfd, pidfile))) goto cleanup; /* now that we know it is about to start call the hook if present */ if (virHookPresent(VIR_HOOK_DRIVER_LXC)) { char *xml = virDomainDefFormat(vm->def, 0); int hookret; hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name, VIR_HOOK_LXC_OP_START, VIR_HOOK_SUBOP_BEGIN, NULL, xml, NULL); VIR_FREE(xml); /* * If the script raised an error abort the launch */ if (hookret < 0) goto cleanup; } /* Log timestamp */ if ((timestamp = virTimeStringNow()) == NULL) goto cleanup; if (safewrite(logfd, timestamp, strlen(timestamp)) < 0 || safewrite(logfd, START_POSTFIX, strlen(START_POSTFIX)) < 0) { VIR_WARN("Unable to write timestamp to logfile: %s", virStrerror(errno, ebuf, sizeof(ebuf))); } VIR_FREE(timestamp); /* Log generated command line */ virCommandWriteArgLog(cmd, logfd); if ((pos = lseek(logfd, 0, SEEK_END)) < 0) VIR_WARN("Unable to seek to end of logfile: %s", virStrerror(errno, ebuf, sizeof(ebuf))); VIR_DEBUG("Launching container"); virCommandRawStatus(cmd); if (virCommandRun(cmd, &status) < 0) goto cleanup; if (status != 0) { if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf, sizeof(ebuf)) <= 0) { if (WIFEXITED(status)) snprintf(ebuf, sizeof(ebuf), _("unexpected exit status %d"), WEXITSTATUS(status)); else snprintf(ebuf, sizeof(ebuf), "%s", _("terminated abnormally")); } virReportError(VIR_ERR_INTERNAL_ERROR, _("guest failed to start: %s"), ebuf); goto cleanup; } /* It has started running, so get its pid */ if ((r = virPidFileReadPath(pidfile, &vm->pid)) < 0) { if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf, sizeof(ebuf)) > 0) virReportError(VIR_ERR_INTERNAL_ERROR, _("guest failed to start: %s"), ebuf); else virReportSystemError(-r, _("Failed to read pid file %s"), pidfile); goto cleanup; } need_stop = true; priv->stopReason = VIR_DOMAIN_EVENT_STOPPED_FAILED; priv->wantReboot = false; vm->def->id = vm->pid; virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason); priv->doneStopEvent = false; if (VIR_CLOSE(handshakefds[1]) < 0) { virReportSystemError(errno, "%s", _("could not close handshake fd")); goto cleanup; } if (virCommandHandshakeWait(cmd) < 0) goto cleanup; /* Write domain status to disk for the controller to * read when it starts */ if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) goto cleanup; /* Allow the child to exec the controller */ if (virCommandHandshakeNotify(cmd) < 0) goto cleanup; if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback) driver->inhibitCallback(true, driver->inhibitOpaque); if (lxcContainerWaitForContinue(handshakefds[0]) < 0) { char out[1024]; if (!(virLXCProcessReadLogOutput(vm, logfile, pos, out, 1024) < 0)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("guest failed to start: %s"), out); } goto cleanup; } /* We know the cgroup must exist by this synchronization * point so lets detect that first, since it gives us a * more reliable way to kill everything off if something * goes wrong from here onwards ... */ if (virCgroupNewDetectMachine(vm->def->name, "lxc", vm->pid, -1, &priv->cgroup) < 0) goto cleanup; if (!priv->cgroup) { virReportError(VIR_ERR_INTERNAL_ERROR, _("No valid cgroup for machine %s"), vm->def->name); goto cleanup; } /* And we can get the first monitor connection now too */ if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm))) { /* Intentionally overwrite the real monitor error message, * since a better one is almost always found in the logs */ if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf, sizeof(ebuf)) > 0) { virResetLastError(); virReportError(VIR_ERR_INTERNAL_ERROR, _("guest failed to start: %s"), ebuf); } goto cleanup; } if (autoDestroy && virCloseCallbacksSet(driver->closeCallbacks, vm, conn, lxcProcessAutoDestroy) < 0) goto cleanup; if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, false) < 0) goto cleanup; /* We don't need the temporary NIC names anymore, clear them */ virLXCProcessCleanInterfaces(vm->def); /* finally we can call the 'started' hook script if any */ if (virHookPresent(VIR_HOOK_DRIVER_LXC)) { char *xml = virDomainDefFormat(vm->def, 0); int hookret; hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name, VIR_HOOK_LXC_OP_STARTED, VIR_HOOK_SUBOP_BEGIN, NULL, xml, NULL); VIR_FREE(xml); /* * If the script raised an error abort the launch */ if (hookret < 0) goto cleanup; } rc = 0; cleanup: if (VIR_CLOSE(logfd) < 0) { virReportSystemError(errno, "%s", _("could not close logfile")); rc = -1; } if (rc != 0) { err = virSaveLastError(); if (need_stop) { virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED); } else { virSecurityManagerRestoreAllLabel(driver->securityManager, vm->def, false); virSecurityManagerReleaseLabel(driver->securityManager, vm->def); /* Clear out dynamically assigned labels */ if (vm->def->nseclabels && (vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC || clearSeclabel)) { VIR_FREE(vm->def->seclabels[0]->model); VIR_FREE(vm->def->seclabels[0]->label); VIR_FREE(vm->def->seclabels[0]->imagelabel); VIR_DELETE_ELEMENT(vm->def->seclabels, 0, vm->def->nseclabels); } virLXCProcessCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED); } } virCommandFree(cmd); for (i = 0; i < nveths; i++) VIR_FREE(veths[i]); for (i = 0; i < nttyFDs; i++) VIR_FORCE_CLOSE(ttyFDs[i]); VIR_FREE(ttyFDs); VIR_FORCE_CLOSE(handshakefds[0]); VIR_FORCE_CLOSE(handshakefds[1]); VIR_FREE(pidfile); VIR_FREE(logfile); virObjectUnref(cfg); virObjectUnref(caps); if (err) { virSetError(err); virFreeError(err); } return rc; }
qemuMigrationCookiePtr qemuMigrationEatCookie(virQEMUDriverPtr driver, virDomainObjPtr dom, const char *cookiein, int cookieinlen, unsigned int flags) { qemuDomainObjPrivatePtr priv = dom->privateData; qemuMigrationCookiePtr mig = NULL; /* Parse & validate incoming cookie (if any) */ if (cookiein && cookieinlen && cookiein[cookieinlen-1] != '\0') { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Migration cookie was not NULL terminated")); goto error; } VIR_DEBUG("cookielen=%d cookie='%s'", cookieinlen, NULLSTR(cookiein)); if (!(mig = qemuMigrationCookieNew(dom))) return NULL; if (cookiein && cookieinlen && qemuMigrationCookieXMLParseStr(mig, driver, cookiein, flags) < 0) goto error; if (flags & QEMU_MIGRATION_COOKIE_PERSISTENT && mig->persistent && STRNEQ(dom->def->name, mig->persistent->name)) { VIR_FREE(mig->persistent->name); if (VIR_STRDUP(mig->persistent->name, dom->def->name) < 0) goto error; } if (mig->flags & QEMU_MIGRATION_COOKIE_LOCKSTATE) { if (!mig->lockDriver) { if (virLockManagerPluginUsesState(driver->lockManager)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Missing %s lock state for migration cookie"), virLockManagerPluginGetName(driver->lockManager)); goto error; } } else if (STRNEQ(mig->lockDriver, virLockManagerPluginGetName(driver->lockManager))) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Source host lock driver %s different from target %s"), mig->lockDriver, virLockManagerPluginGetName(driver->lockManager)); goto error; } } if (flags & QEMU_MIGRATION_COOKIE_STATS && mig->jobInfo) mig->jobInfo->operation = priv->job.current->operation; return mig; error: qemuMigrationCookieFree(mig); return NULL; }
int virNetSocketNewListenTCP(const char *nodename, const char *service, virNetSocketPtr **retsocks, size_t *nretsocks) { virNetSocketPtr *socks = NULL; size_t nsocks = 0; struct addrinfo *ai = NULL; struct addrinfo hints; int fd = -1; int i; int addrInUse = false; *retsocks = NULL; *nretsocks = 0; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; hints.ai_socktype = SOCK_STREAM; int e = getaddrinfo(nodename, service, &hints, &ai); if (e != 0) { virNetError(VIR_ERR_SYSTEM_ERROR, _("Unable to resolve address '%s' service '%s': %s"), nodename, service, gai_strerror(e)); return -1; } struct addrinfo *runp = ai; while (runp) { virSocketAddr addr; memset(&addr, 0, sizeof(addr)); if ((fd = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol)) < 0) { virReportSystemError(errno, "%s", _("Unable to create socket")); goto error; } int opt = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { virReportSystemError(errno, "%s", _("Unable to enable port reuse")); goto error; } #ifdef IPV6_V6ONLY if (runp->ai_family == PF_INET6) { int on = 1; /* * Normally on Linux an INET6 socket will bind to the INET4 * address too. If getaddrinfo returns results with INET4 * first though, this will result in INET6 binding failing. * We can trivially cope with multiple server sockets, so * we force it to only listen on IPv6 */ if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&on, sizeof(on)) < 0) { virReportSystemError(errno, "%s", _("Unable to force bind to IPv6 only")); goto error; } } #endif if (bind(fd, runp->ai_addr, runp->ai_addrlen) < 0) { if (errno != EADDRINUSE) { virReportSystemError(errno, "%s", _("Unable to bind to port")); goto error; } addrInUse = true; VIR_FORCE_CLOSE(fd); runp = runp->ai_next; continue; } addr.len = sizeof(addr.data); if (getsockname(fd, &addr.data.sa, &addr.len) < 0) { virReportSystemError(errno, "%s", _("Unable to get local socket name")); goto error; } VIR_DEBUG("%p f=%d f=%d", &addr, runp->ai_family, addr.data.sa.sa_family); if (VIR_EXPAND_N(socks, nsocks, 1) < 0) { virReportOOMError(); goto error; } if (!(socks[nsocks-1] = virNetSocketNew(&addr, NULL, false, fd, -1, 0))) goto error; runp = runp->ai_next; fd = -1; } if (nsocks == 0 && addrInUse) { virReportSystemError(EADDRINUSE, "%s", _("Unable to bind to port")); goto error; } freeaddrinfo(ai); *retsocks = socks; *nretsocks = nsocks; return 0; error: for (i = 0 ; i < nsocks ; i++) virNetSocketFree(socks[i]); VIR_FREE(socks); freeaddrinfo(ai); VIR_FORCE_CLOSE(fd); return -1; }
static void xenInotifyEvent(int watch ATTRIBUTE_UNUSED, int fd, int events ATTRIBUTE_UNUSED, void *data) { char buf[1024]; char fname[1024]; struct inotify_event *e; int got; char *tmp, *name; virConnectPtr conn = data; xenUnifiedPrivatePtr priv = NULL; VIR_DEBUG("got inotify event"); if( conn && conn->privateData ) { priv = conn->privateData; } else { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("conn, or private data is NULL")); return; } xenUnifiedLock(priv); reread: got = read(fd, buf, sizeof(buf)); if (got == -1) { if (errno == EINTR) goto reread; goto cleanup; } tmp = buf; while (got) { if (got < sizeof(struct inotify_event)) goto cleanup; /* bad */ e = (struct inotify_event *)tmp; tmp += sizeof(struct inotify_event); got -= sizeof(struct inotify_event); if (got < e->len) goto cleanup; tmp += e->len; got -= e->len; name = (char *)&(e->name); snprintf(fname, 1024, "%s/%s", priv->configDir, name); if (e->mask & (IN_DELETE | IN_MOVED_FROM)) { virDomainEventPtr event = xenInotifyDomainEventFromFile(conn, fname, VIR_DOMAIN_EVENT_UNDEFINED, VIR_DOMAIN_EVENT_UNDEFINED_REMOVED); if (event) xenUnifiedDomainEventDispatch(conn->privateData, event); else virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("looking up dom")); if (xenInotifyRemoveDomainConfigInfo(conn, fname) < 0 ) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Error adding file to config cache")); goto cleanup; } } else if (e->mask & ( IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO) ) { virDomainEventPtr event; if (xenInotifyAddDomainConfigInfo(conn, fname) < 0 ) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Error adding file to config cache")); goto cleanup; } event = xenInotifyDomainEventFromFile(conn, fname, VIR_DOMAIN_EVENT_DEFINED, VIR_DOMAIN_EVENT_DEFINED_ADDED); if (event) xenUnifiedDomainEventDispatch(conn->privateData, event); else virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("looking up dom")); } } cleanup: xenUnifiedUnlock(priv); }
static int testCorrupt(const void *opaque) { const struct testCorruptData *data = opaque; struct daemonConfig *conf = daemonConfigNew(false); int ret = 0; int type = VIR_CONF_NONE; char *newdata = munge_param(data->filedata, data->params, data->paramnum, &type); virErrorPtr err = NULL; if (!newdata) return -1; //VIR_DEBUG("New config [%s]", newdata); if (daemonConfigLoadData(conf, data->filename, newdata) != -1) { VIR_DEBUG("Did not see a failure"); ret = -1; goto cleanup; } err = virGetLastError(); if (!err || !err->message) { VIR_DEBUG("No error or message %p", err); ret = -1; goto cleanup; } #if !WITH_SASL if (strstr(err->message, "unsupported auth sasl")) { VIR_DEBUG("sasl unsupported, skipping this config"); goto cleanup; } #endif switch (type) { case VIR_CONF_LONG: if (!strstr(err->message, "invalid type: got string; expected long")) { VIR_DEBUG("Wrong error for long: '%s'", err->message); ret = -1; } break; case VIR_CONF_STRING: if (!strstr(err->message, "invalid type: got long; expected string")) { VIR_DEBUG("Wrong error for string: '%s'", err->message); ret = -1; } break; case VIR_CONF_LIST: if (!strstr(err->message, "must be a string or list of strings")) { VIR_DEBUG("Wrong error for list: '%s'", err->message); ret = -1; } break; } cleanup: VIR_FREE(newdata); daemonConfigFree(conf); return ret; }
/** * 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. */ virDrvOpenStatus xenInotifyOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, unsigned int flags) { DIR *dh; struct dirent *ent; char *path; xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData; virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR); 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) { virReportOOMError(); 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; }
static int testURIParse(const void *args) { int ret = -1; virURIPtr uri = NULL; const struct URIParseData *data = args; char *uristr = NULL; size_t i; if (!(uri = virURIParse(data->uri))) goto cleanup; if (!STREQ(uri->scheme, data->scheme)) { VIR_DEBUG("Expected scheme '%s', actual '%s'", data->scheme, uri->scheme); goto cleanup; } if (!STREQ(uri->server, data->server)) { VIR_DEBUG("Expected server '%s', actual '%s'", data->server, uri->server); goto cleanup; } if (uri->port != data->port) { VIR_DEBUG("Expected port '%d', actual '%d'", data->port, uri->port); goto cleanup; } if (!STREQ_NULLABLE(uri->path, data->path)) { VIR_DEBUG("Expected path '%s', actual '%s'", data->path, uri->path); goto cleanup; } if (!STREQ_NULLABLE(uri->query, data->query)) { VIR_DEBUG("Expected query '%s', actual '%s'", data->query, uri->query); goto cleanup; } if (!STREQ_NULLABLE(uri->fragment, data->fragment)) { VIR_DEBUG("Expected fragment '%s', actual '%s'", data->fragment, uri->fragment); goto cleanup; } for (i = 0 ; data->params && data->params[i].name && i < uri->paramsCount ; i++) { if (!STREQ_NULLABLE(data->params[i].name, uri->params[i].name)) { VIR_DEBUG("Expected param name %zu '%s', actual '%s'", i, data->params[i].name, uri->params[i].name); goto cleanup; } if (!STREQ_NULLABLE(data->params[i].value, uri->params[i].value)) { VIR_DEBUG("Expected param value %zu '%s', actual '%s'", i, data->params[i].value, uri->params[i].value); goto cleanup; } } if (data->params && data->params[i].name) { VIR_DEBUG("Missing parameter %zu %s=%s", i, data->params[i].name, data->params[i].value); goto cleanup; } if (i != uri->paramsCount) { VIR_DEBUG("Unexpected parameter %zu %s=%s", i, uri->params[i].name, uri->params[i].value); goto cleanup; } VIR_FREE(uri->query); uri->query = virURIFormatParams(uri); if (!(uristr = virURIFormat(uri))) goto cleanup; if (!STREQ(uristr, data->uri_out)) { VIR_DEBUG("URI did not roundtrip, expect '%s', actual '%s'", data->uri_out, uristr); goto cleanup; } ret = 0; cleanup: VIR_FREE(uristr); virURIFree(uri); return ret; }
static int virStorageBackendCreateIfaceIQN(const char *initiatoriqn, char **ifacename) { int ret = -1, exitstatus = -1; char *temp_ifacename; virCommandPtr cmd = NULL; if (virAsprintf(&temp_ifacename, "libvirt-iface-%08llx", (unsigned long long)virRandomBits(30)) < 0) return -1; VIR_DEBUG("Attempting to create interface '%s' with IQN '%s'", temp_ifacename, initiatoriqn); cmd = virCommandNewArgList(ISCSIADM, "--mode", "iface", "--interface", temp_ifacename, "--op", "new", NULL); /* Note that we ignore the exitstatus. Older versions of iscsiadm * tools returned an exit status of > 0, even if they succeeded. * We will just rely on whether the interface got created * properly. */ if (virCommandRun(cmd, &exitstatus) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to run command '%s' to create new iscsi interface"), ISCSIADM); goto cleanup; } virCommandFree(cmd); cmd = virCommandNewArgList(ISCSIADM, "--mode", "iface", "--interface", temp_ifacename, "--op", "update", "--name", "iface.initiatorname", "--value", initiatoriqn, NULL); /* Note that we ignore the exitstatus. Older versions of iscsiadm tools * returned an exit status of > 0, even if they succeeded. We will just * rely on whether iface file got updated properly. */ if (virCommandRun(cmd, &exitstatus) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to run command '%s' to update iscsi interface with IQN '%s'"), ISCSIADM, initiatoriqn); goto cleanup; } /* Check again to make sure the interface was created. */ if (virStorageBackendIQNFound(initiatoriqn, ifacename) != IQN_FOUND) { VIR_DEBUG("Failed to find interface '%s' with IQN '%s' " "after attempting to create it", &temp_ifacename[0], initiatoriqn); goto cleanup; } else { VIR_DEBUG("Interface '%s' with IQN '%s' was created successfully", *ifacename, initiatoriqn); } ret = 0; cleanup: virCommandFree(cmd); VIR_FREE(temp_ifacename); if (ret != 0) VIR_FREE(*ifacename); return ret; }
int virAuthGetConfigFilePathURI(virURIPtr uri, char **path) { int ret = -1; size_t i; const char *authenv = virGetEnvBlockSUID("LIBVIRT_AUTH_FILE"); char *userdir = NULL; *path = NULL; VIR_DEBUG("Determining auth config file path"); if (authenv) { VIR_DEBUG("Using path from env '%s'", authenv); if (VIR_STRDUP(*path, authenv) < 0) goto cleanup; return 0; } if (uri) { for (i = 0; i < uri->paramsCount; i++) { if (STREQ_NULLABLE(uri->params[i].name, "authfile") && uri->params[i].value) { VIR_DEBUG("Using path from URI '%s'", uri->params[i].value); if (VIR_STRDUP(*path, uri->params[i].value) < 0) goto cleanup; return 0; } } } if (!(userdir = virGetUserConfigDirectory())) goto cleanup; if (virAsprintf(path, "%s/auth.conf", userdir) < 0) goto cleanup; VIR_DEBUG("Checking for readability of '%s'", *path); if (access(*path, R_OK) == 0) goto done; VIR_FREE(*path); if (VIR_STRDUP(*path, SYSCONFDIR "/libvirt/auth.conf") < 0) goto cleanup; VIR_DEBUG("Checking for readability of '%s'", *path); if (access(*path, R_OK) == 0) goto done; VIR_FREE(*path); done: ret = 0; VIR_DEBUG("Using auth file '%s'", NULLSTR(*path)); cleanup: VIR_FREE(userdir); return ret; }