/** * virNetlinkEventServiceStop: * * stop the monitor to receive netlink messages for libvirtd. * This removes the netlink socket fd from the event handler. * * @protocol: netlink protocol * * Returns -1 if the monitor cannot be unregistered, 0 upon success */ int virNetlinkEventServiceStop(unsigned int protocol) { if (protocol >= MAX_LINKS) return -EINVAL; virNetlinkEventSrvPrivatePtr srv = server[protocol]; int i; VIR_INFO("stopping netlink event service"); if (!server[protocol]) return 0; virNetlinkEventServerLock(srv); nl_close(srv->netlinknh); virNetlinkFree(srv->netlinknh); virEventRemoveHandle(srv->eventwatch); /* free any remaining clients on the list */ for (i = 0; i < srv->handlesCount; i++) { if (srv->handles[i].deleted == VIR_NETLINK_HANDLE_VALID) virNetlinkEventRemoveClientPrimitive(i, protocol); } server[protocol] = NULL; virNetlinkEventServerUnlock(srv); virMutexDestroy(&srv->lock); VIR_FREE(srv); return 0; }
/* This function allocates memory from the heap for the property * value. That memory must be later freed by some other code. */ static int udevGetDeviceProperty(struct udev_device *udev_device, const char *property_key, char **property_value) { const char *udev_value = NULL; int ret = PROPERTY_FOUND; udev_value = udev_device_get_property_value(udev_device, property_key); if (udev_value == NULL) { VIR_INFO(_("udev reports device '%s' does not have property '%s'"), udev_device_get_sysname(udev_device), property_key); ret = PROPERTY_MISSING; goto out; } /* If this allocation is changed, the comment at the beginning * of the function must also be changed. */ *property_value = strdup(udev_value); if (*property_value == NULL) { VIR_ERROR(_("Failed to allocate memory for property value for " "property key '%s' on device with sysname '%s'"), property_key, udev_device_get_sysname(udev_device)); virReportOOMError(); ret = PROPERTY_ERROR; goto out; } VIR_DEBUG("Found property key '%s' value '%s' " "for device with sysname '%s'", property_key, *property_value, udev_device_get_sysname(udev_device)); out: return ret; }
/* This method shouldn't raise errors, since they'll overwrite * errors that the caller(s) are already dealing with */ static int SELinuxRestoreSecurityFileLabel(const char *path) { struct stat buf; security_context_t fcon = NULL; int rc = -1; char *newpath = NULL; char ebuf[1024]; VIR_INFO("Restoring SELinux context on '%s'", path); if (virFileResolveLink(path, &newpath) < 0) { VIR_WARN("cannot resolve symlink %s: %s", path, virStrerror(errno, ebuf, sizeof(ebuf))); goto err; } if (stat(newpath, &buf) != 0) { VIR_WARN("cannot stat %s: %s", newpath, virStrerror(errno, ebuf, sizeof(ebuf))); goto err; } if (getContext(newpath, buf.st_mode, &fcon) < 0) { VIR_WARN("cannot lookup default selinux label for %s", newpath); } else { rc = SELinuxSetFilecon(newpath, fcon); } err: freecon(fcon); VIR_FREE(newpath); return rc; }
/* This function allocates memory from the heap for the property * value. That memory must be later freed by some other code. */ static int udevGetDeviceSysfsAttr(struct udev_device *udev_device, const char *attr_name, char **attr_value) { const char *udev_value = NULL; int ret = PROPERTY_FOUND; udev_value = udev_device_get_sysattr_value(udev_device, attr_name); if (udev_value == NULL) { VIR_INFO(_("udev reports device '%s' does not have sysfs attr '%s'"), udev_device_get_sysname(udev_device), attr_name); ret = PROPERTY_MISSING; goto out; } /* If this allocation is changed, the comment at the beginning * of the function must also be changed. */ *attr_value = strdup(udev_value); if (*attr_value == NULL) { VIR_ERROR(_("Failed to allocate memory for sysfs attribute value for " "sysfs attribute '%s' on device with sysname '%s'"), attr_name, udev_device_get_sysname(udev_device)); virReportOOMError(); ret = PROPERTY_ERROR; goto out; } VIR_DEBUG("Found sysfs attribute '%s' value '%s' " "for device with sysname '%s'", attr_name, *attr_value, udev_device_get_sysname(udev_device)); out: return ret; }
static int virIpTablesOnceInit(void) { virCommandPtr cmd; int status; #if HAVE_FIREWALLD firewall_cmd_path = virFindFileInPath("firewall-cmd"); if (!firewall_cmd_path) { VIR_INFO("firewall-cmd not found on system. " "firewalld support disabled for iptables."); } else { cmd = virCommandNew(firewall_cmd_path); virCommandAddArgList(cmd, "--state", NULL); /* don't log non-zero status */ if (virCommandRun(cmd, &status) < 0 || status != 0) { VIR_INFO("firewall-cmd found but disabled for iptables"); VIR_FREE(firewall_cmd_path); firewall_cmd_path = NULL; } else { VIR_INFO("using firewalld for iptables commands"); } virCommandFree(cmd); } if (firewall_cmd_path) return 0; #endif cmd = virCommandNew(IPTABLES_PATH); virCommandAddArgList(cmd, "-w", "-L", "-n", NULL); /* don't log non-zero status */ if (virCommandRun(cmd, &status) < 0 || status != 0) { VIR_INFO("xtables locking not supported by your iptables"); } else { VIR_INFO("using xtables locking for iptables"); iptables_supports_xlock = true; } virCommandFree(cmd); return 0; }
static void virNetServerHandleJob(void *jobOpaque, void *opaque) { virNetServerPtr srv = opaque; virNetServerJobPtr job = jobOpaque; VIR_DEBUG("server=%p client=%p message=%p prog=%p", srv, job->client, job->msg, job->prog); if (!job->prog) { /* Only send back an error for type == CALL. Other * message types are not expecting replies, so we * must just log it & drop them */ if (job->msg->header.type == VIR_NET_CALL || job->msg->header.type == VIR_NET_CALL_WITH_FDS) { if (virNetServerProgramUnknownError(job->client, job->msg, &job->msg->header) < 0) goto error; } else { VIR_INFO("Dropping client mesage, unknown program %d version %d type %d proc %d", job->msg->header.prog, job->msg->header.vers, job->msg->header.type, job->msg->header.proc); /* Send a dummy reply to free up 'msg' & unblock client rx */ virNetMessageClear(job->msg); job->msg->header.type = VIR_NET_REPLY; if (virNetServerClientSendMessage(job->client, job->msg) < 0) goto error; } goto cleanup; } if (virNetServerProgramDispatch(job->prog, srv, job->client, job->msg) < 0) goto error; virNetServerLock(srv); virNetServerProgramFree(job->prog); virNetServerUnlock(srv); cleanup: virNetServerClientFree(job->client); VIR_FREE(job); return; error: virNetServerProgramFree(job->prog); virNetMessageFree(job->msg); virNetServerClientClose(job->client); virNetServerClientFree(job->client); VIR_FREE(job); }
static int SELinuxFSetFilecon(int fd, char *tcon) { security_context_t econ; VIR_INFO("Setting SELinux context on fd %d to '%s'", fd, tcon); if (fsetfilecon(fd, tcon) < 0) { int fsetfilecon_errno = errno; if (fgetfilecon(fd, &econ) >= 0) { if (STREQ(tcon, econ)) { freecon(econ); /* It's alright, there's nothing to change anyway. */ return 0; } freecon(econ); } /* if the error complaint is related to an image hosted on * an nfs mount, or a usbfs/sysfs filesystem not supporting * labelling, then just ignore it & hope for the best. * The user hopefully set one of the necessary SELinux * virt_use_{nfs,usb,pci} boolean tunables to allow it... */ if (fsetfilecon_errno != EOPNOTSUPP) { virReportSystemError(fsetfilecon_errno, _("unable to set security context '%s' on fd %d"), tcon, fd); if (security_getenforce() == 1) return -1; } else { VIR_INFO("Setting security context '%s' on fd %d not supported", tcon, fd); } } return 0; }
static int virEbTablesOnceInit(void) { firewall_cmd_path = virFindFileInPath("firewall-cmd"); if (!firewall_cmd_path) { VIR_INFO("firewall-cmd not found on system. " "firewalld support disabled for ebtables."); } else { virCommandPtr cmd = virCommandNew(firewall_cmd_path); int status; virCommandAddArgList(cmd, "--state", NULL); if (virCommandRun(cmd, &status) < 0 || status != 0) { VIR_INFO("firewall-cmd found but disabled for ebtables"); VIR_FREE(firewall_cmd_path); firewall_cmd_path = NULL; } else { VIR_INFO("using firewalld for ebtables commands"); } virCommandFree(cmd); } return 0; }
static int dnsmasqCapsSetFromBuffer(dnsmasqCapsPtr caps, const char *buf) { const char *p; caps->noRefresh = true; p = STRSKIP(buf, DNSMASQ_VERSION_STR); if (!p) goto fail; virSkipSpaces(&p); if (virParseVersionString(p, &caps->version, true) < 0) goto fail; if (strstr(buf, "--bind-dynamic")) dnsmasqCapsSet(caps, DNSMASQ_CAPS_BIND_DYNAMIC); /* if this string is a part of the --version output, dnsmasq * has been patched to use SO_BINDTODEVICE when listening, * so that it will only accept requests that arrived on the * listening interface(s) */ if (strstr(buf, "--bind-interfaces with SO_BINDTODEVICE")) dnsmasqCapsSet(caps, DNSMASQ_CAPS_BINDTODEVICE); if (strstr(buf, "--ra-param")) dnsmasqCapsSet(caps, DNSMASQ_CAPS_RA_PARAM); VIR_INFO("dnsmasq version is %d.%d, --bind-dynamic is %spresent, " "SO_BINDTODEVICE is %sin use, --ra-param is %spresent", (int)caps->version / 1000000, (int)(caps->version % 1000000) / 1000, dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC) ? "" : "NOT ", dnsmasqCapsGet(caps, DNSMASQ_CAPS_BINDTODEVICE) ? "" : "NOT ", dnsmasqCapsGet(caps, DNSMASQ_CAPS_RA_PARAM) ? "" : "NOT "); return 0; fail: p = strchrnul(buf, '\n'); virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot parse %s version number in '%.*s'"), caps->binaryPath, (int) (p - buf), buf); return -1; }
static void * virDriverLoadModuleFile(const char *file) { void *handle = NULL; VIR_DEBUG("Load module file '%s'", file); if (access(file, R_OK) < 0) { VIR_INFO("Module %s not accessible", file); return NULL; } virUpdateSelfLastChanged(file); if (!(handle = dlopen(file, RTLD_NOW | RTLD_GLOBAL))) VIR_ERROR(_("failed to load module %s %s"), file, dlerror()); return handle; }
static int virNetServerProcessMsg(virNetServerPtr srv, virNetServerClientPtr client, virNetServerProgramPtr prog, virNetMessagePtr msg) { int ret = -1; if (!prog) { /* Only send back an error for type == CALL. Other * message types are not expecting replies, so we * must just log it & drop them */ if (msg->header.type == VIR_NET_CALL || msg->header.type == VIR_NET_CALL_WITH_FDS) { if (virNetServerProgramUnknownError(client, msg, &msg->header) < 0) goto cleanup; } else { VIR_INFO("Dropping client mesage, unknown program %d version %d type %d proc %d", msg->header.prog, msg->header.vers, msg->header.type, msg->header.proc); /* Send a dummy reply to free up 'msg' & unblock client rx */ virNetMessageClear(msg); msg->header.type = VIR_NET_REPLY; if (virNetServerClientSendMessage(client, msg) < 0) goto cleanup; } goto done; } if (virNetServerProgramDispatch(prog, srv, client, msg) < 0) goto cleanup; done: ret = 0; cleanup: return ret; }
/* * Returns: * -1 if fatal error occurred * 0 if message was fully processed * 1 if message is still being processed */ static int daemonStreamHandleWriteData(virNetServerClientPtr client, daemonClientStream *stream, virNetMessagePtr msg) { int ret; VIR_DEBUG("client=%p, stream=%p, proc=%d, serial=%d, len=%zu, offset=%zu", client, stream, msg->header.proc, msg->header.serial, msg->bufferLength, msg->bufferOffset); ret = virStreamSend(stream->st, msg->buffer + msg->bufferOffset, msg->bufferLength - msg->bufferOffset); if (ret > 0) { msg->bufferOffset += ret; /* Partial write, so indicate we have more todo later */ if (msg->bufferOffset < msg->bufferLength) return 1; } else if (ret == -2) { /* Blocking, so indicate we have more todo later */ return 1; } else { virNetMessageError rerr; memset(&rerr, 0, sizeof(rerr)); VIR_INFO("Stream send failed"); stream->closed = 1; return virNetServerProgramSendReplyError(stream->prog, client, msg, &rerr, &msg->header); } return 0; }
/** * virNetDevMacVLanReleaseID: * @id: id 0 - MACVLAN_MAX_ID+1 to release * * Returns 0 for success or -1 for failure. */ static int virNetDevMacVLanReleaseID(int id, unsigned int flags) { virBitmapPtr bitmap; if (virNetDevMacVLanInitialize() < 0) return 0; bitmap = (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) ? macvtapIDs : macvlanIDs; if (id > MACVLAN_MAX_ID) { virReportError(VIR_ERR_INTERNAL_ERROR, _("can't free name %s%d - out of range 0-%d"), (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) ? MACVTAP_NAME_PREFIX : MACVLAN_NAME_PREFIX, id, MACVLAN_MAX_ID); return -1; } if (id < 0) return 0; VIR_INFO("releasing %sdevice %s%d", virBitmapIsBitSet(bitmap, id) ? "" : "unreserved", (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) ? MACVTAP_NAME_PREFIX : MACVLAN_NAME_PREFIX, id); if (virBitmapClearBit(bitmap, id) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("couldn't mark %s%d as unused"), (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) ? MACVTAP_NAME_PREFIX : MACVLAN_NAME_PREFIX, id); return -1; } return 0; }
static virStoragePoolProbeResult virStorageBackendFileSystemProbe(const char *device, const char *format) { virStoragePoolProbeResult ret = FILESYSTEM_PROBE_ERROR; blkid_probe probe = NULL; const char *fstype = NULL; char *names[2], *libblkid_format = NULL; VIR_DEBUG("Probing for existing filesystem of type %s on device %s", format, device); if (blkid_known_fstype(format) == 0) { virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, _("Not capable of probing for " "filesystem of type %s"), format); goto error; } probe = blkid_new_probe_from_filename(device); if (probe == NULL) { virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, _("Failed to create filesystem probe " "for device %s"), device); goto error; } if ((libblkid_format = strdup(format)) == NULL) { virReportOOMError(); goto error; } names[0] = libblkid_format; names[1] = NULL; blkid_probe_filter_superblocks_type(probe, BLKID_FLTR_ONLYIN, names); if (blkid_do_probe(probe) != 0) { VIR_INFO("No filesystem of type '%s' found on device '%s'", format, device); ret = FILESYSTEM_PROBE_NOT_FOUND; } else if (blkid_probe_lookup_value(probe, "TYPE", &fstype, NULL) == 0) { virStorageReportError(VIR_ERR_STORAGE_POOL_BUILT, _("Existing filesystem of type '%s' found on " "device '%s'"), fstype, device); ret = FILESYSTEM_PROBE_FOUND; } if (blkid_do_probe(probe) != 1) { virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, _("Found additional probes to run, " "filesystem probing may be incorrect")); ret = FILESYSTEM_PROBE_ERROR; } error: VIR_FREE(libblkid_format); if (probe != NULL) { blkid_free_probe(probe); } return ret; }
int qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev, bool mandatory, usbDevice **usb) { unsigned vendor = hostdev->source.subsys.u.usb.vendor; unsigned product = hostdev->source.subsys.u.usb.product; unsigned bus = hostdev->source.subsys.u.usb.bus; unsigned device = hostdev->source.subsys.u.usb.device; bool autoAddress = hostdev->source.subsys.u.usb.autoAddress; int rc; *usb = NULL; if (vendor && bus) { rc = usbFindDevice(vendor, product, bus, device, autoAddress ? false : mandatory, usb); if (rc < 0) { return -1; } else if (!autoAddress) { goto out; } else { VIR_INFO("USB device %x:%x could not be found at previous" " address (bus:%u device:%u)", vendor, product, bus, device); } } /* When vendor is specified, its USB address is either unspecified or the * device could not be found at the USB device where it had been * automatically found before. */ if (vendor) { usbDeviceList *devs; rc = usbFindDeviceByVendor(vendor, product, mandatory, &devs); if (rc < 0) return -1; if (rc == 1) { *usb = usbDeviceListGet(devs, 0); usbDeviceListSteal(devs, *usb); } usbDeviceListFree(devs); if (rc == 0) { goto out; } else if (rc > 1) { if (autoAddress) { virReportError(VIR_ERR_OPERATION_FAILED, _("Multiple USB devices for %x:%x were found," " but none of them is at bus:%u device:%u"), vendor, product, bus, device); } else { virReportError(VIR_ERR_OPERATION_FAILED, _("Multiple USB devices for %x:%x, " "use <address> to specify one"), vendor, product); } return -1; } hostdev->source.subsys.u.usb.bus = usbDeviceGetBus(*usb); hostdev->source.subsys.u.usb.device = usbDeviceGetDevno(*usb); hostdev->source.subsys.u.usb.autoAddress = true; if (autoAddress) { VIR_INFO("USB device %x:%x found at bus:%u device:%u (moved" " from bus:%u device:%u)", vendor, product, hostdev->source.subsys.u.usb.bus, hostdev->source.subsys.u.usb.device, bus, device); } } else if (!vendor && bus) { if (usbFindDeviceByBus(bus, device, mandatory, usb) < 0) return -1; } out: if (!*usb) hostdev->missing = 1; return 0; }
/* * @server: the unlocked server object * @client: the unlocked client object * @msg: the complete incoming message packet, with header already decoded * * This function is intended to be called from worker threads * when an incoming message is ready to be dispatched for * execution. * * Upon successful return the '@msg' instance will be released * by this function (or more often, reused to send a reply). * Upon failure, the '@msg' must be freed by the caller. * * Returns 0 if the message was dispatched, -1 upon fatal error */ int virNetServerProgramDispatch(virNetServerProgramPtr prog, virNetServerPtr server, virNetServerClientPtr client, virNetMessagePtr msg) { int ret = -1; virNetMessageError rerr; memset(&rerr, 0, sizeof(rerr)); VIR_DEBUG("prog=%d ver=%d type=%d status=%d serial=%u proc=%d", msg->header.prog, msg->header.vers, msg->header.type, msg->header.status, msg->header.serial, msg->header.proc); /* Check version, etc. */ if (msg->header.prog != prog->program) { virReportError(VIR_ERR_RPC, _("program mismatch (actual %x, expected %x)"), msg->header.prog, prog->program); goto error; } if (msg->header.vers != prog->version) { virReportError(VIR_ERR_RPC, _("version mismatch (actual %x, expected %x)"), msg->header.vers, prog->version); goto error; } switch (msg->header.type) { case VIR_NET_CALL: case VIR_NET_CALL_WITH_FDS: ret = virNetServerProgramDispatchCall(prog, server, client, msg); break; case VIR_NET_STREAM: /* Since stream data is non-acked, async, we may continue to receive * stream packets after we closed down a stream. Just drop & ignore * these. */ VIR_INFO("Ignoring unexpected stream data serial=%u proc=%d status=%d", msg->header.serial, msg->header.proc, msg->header.status); /* Send a dummy reply to free up 'msg' & unblock client rx */ virNetMessageClear(msg); msg->header.type = VIR_NET_REPLY; if (virNetServerClientSendMessage(client, msg) < 0) { ret = -1; goto cleanup; } ret = 0; break; default: virReportError(VIR_ERR_RPC, _("Unexpected message type %u"), msg->header.type); goto error; } return ret; error: if (msg->header.type == VIR_NET_CALL || msg->header.type == VIR_NET_CALL_WITH_FDS) { ret = virNetServerProgramSendReplyError(prog, client, msg, &rerr, &msg->header); } else { /* Send a dummy reply to free up 'msg' & unblock client rx */ virNetMessageClear(msg); msg->header.type = VIR_NET_REPLY; if (virNetServerClientSendMessage(client, msg) < 0) { ret = -1; goto cleanup; } ret = 0; } cleanup: return ret; }
/** * virNetlinkEventServiceStart: * * start a monitor to receive netlink messages for libvirtd. * This registers a netlink socket with the event interface. * * Returns -1 if the monitor cannot be registered, 0 upon success */ int virNetlinkEventServiceStart(void) { virNetlinkEventSrvPrivatePtr srv; int fd; int ret = -1; if (server) return 0; VIR_INFO("starting netlink event service"); if (VIR_ALLOC(srv) < 0) { virReportOOMError(); return -1; } if (virMutexInit(&srv->lock) < 0) { VIR_FREE(srv); return -1; } virNetlinkEventServerLock(srv); /* Allocate a new socket and get fd */ srv->netlinknh = virNetlinkAlloc(); if (!srv->netlinknh) { virReportSystemError(errno, "%s", _("cannot allocate nlhandle for virNetlinkEvent server")); goto error_locked; } if (nl_connect(srv->netlinknh, NETLINK_ROUTE) < 0) { virReportSystemError(errno, "%s", _("cannot connect to netlink socket")); goto error_server; } fd = nl_socket_get_fd(srv->netlinknh); if (fd < 0) { virReportSystemError(errno, "%s", _("cannot get netlink socket fd")); goto error_server; } if (nl_socket_set_nonblocking(srv->netlinknh)) { virReportSystemError(errno, "%s", _("cannot set netlink socket nonblocking")); goto error_server; } if ((srv->eventwatch = virEventAddHandle(fd, VIR_EVENT_HANDLE_READABLE, virNetlinkEventCallback, srv, NULL)) < 0) { netlinkError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to add netlink event handle watch")); goto error_server; } srv->netlinkfd = fd; VIR_DEBUG("netlink event listener on fd: %i running", fd); ret = 0; server = srv; error_server: if (ret < 0) { nl_close(srv->netlinknh); virNetlinkFree(srv->netlinknh); } error_locked: virNetlinkEventServerUnlock(srv); if (ret < 0) { virMutexDestroy(&srv->lock); VIR_FREE(srv); } return ret; }
/** * virNetlinkEventServiceStart: * * start a monitor to receive netlink messages for libvirtd. * This registers a netlink socket with the event interface. * * @protocol: netlink protocol * @groups: broadcast groups to join in * Returns -1 if the monitor cannot be registered, 0 upon success */ int virNetlinkEventServiceStart(unsigned int protocol, unsigned int groups) { virNetlinkEventSrvPrivatePtr srv; int fd; int ret = -1; if (protocol >= MAX_LINKS) { virReportSystemError(EINVAL, _("invalid protocol argument: %d"), protocol); return -EINVAL; } if (server[protocol]) return 0; VIR_INFO("starting netlink event service with protocol %d", protocol); if (VIR_ALLOC(srv) < 0) return -1; if (virMutexInit(&srv->lock) < 0) { VIR_FREE(srv); return -1; } virNetlinkEventServerLock(srv); /* Allocate a new socket and get fd */ if (!(srv->netlinknh = virNetlinkCreateSocket(protocol))) goto error_locked; fd = nl_socket_get_fd(srv->netlinknh); if (fd < 0) { virReportSystemError(errno, "%s", _("cannot get netlink socket fd")); goto error_server; } if (groups && nl_socket_add_membership(srv->netlinknh, groups) < 0) { virReportSystemError(errno, "%s", _("cannot add netlink membership")); goto error_server; } if (nl_socket_set_nonblocking(srv->netlinknh)) { virReportSystemError(errno, "%s", _("cannot set netlink socket nonblocking")); goto error_server; } if ((srv->eventwatch = virEventAddHandle(fd, VIR_EVENT_HANDLE_READABLE, virNetlinkEventCallback, srv, NULL)) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to add netlink event handle watch")); goto error_server; } srv->netlinkfd = fd; VIR_DEBUG("netlink event listener on fd: %i running", fd); ret = 0; server[protocol] = srv; error_server: if (ret < 0) { nl_close(srv->netlinknh); virNetlinkFree(srv->netlinknh); } error_locked: virNetlinkEventServerUnlock(srv); if (ret < 0) { virMutexDestroy(&srv->lock); VIR_FREE(srv); } return ret; }
/* Functions */ virCapsPtr virLXCDriverCapsInit(virLXCDriverPtr driver) { virCapsPtr caps; virCapsGuestPtr guest; virArch altArch; char *lxc_path = NULL; if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL) goto error; /* Some machines have problematic NUMA toplogy causing * unexpected failures. We don't want to break the lxc * driver in this scenario, so log errors & carry on */ if (nodeCapsInitNUMA(caps) < 0) { virCapabilitiesFreeNUMAInfo(caps); VIR_WARN("Failed to query host NUMA topology, disabling NUMA capabilities"); } /* Only probe for power management capabilities in the driver, * not in the emulator */ if (driver && virNodeSuspendGetTargetMask(&caps->host.powerMgmt) < 0) VIR_WARN("Failed to get host power management capabilities"); if (virGetHostUUID(caps->host.host_uuid)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot get the host uuid")); goto error; } if (!(lxc_path = virFileFindResource("libvirt_lxc", abs_topbuilddir "/src", LIBEXECDIR))) goto error; if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_EXE, caps->host.arch, lxc_path, NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_LXC, NULL, NULL, 0, NULL) == NULL) goto error; /* On 64-bit hosts, we can use personality() to request a 32bit process */ if ((altArch = lxcContainerGetAlt32bitArch(caps->host.arch)) != VIR_ARCH_NONE) { if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_EXE, altArch, lxc_path, NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_LXC, NULL, NULL, 0, NULL) == NULL) goto error; } VIR_FREE(lxc_path); if (driver) { /* Security driver data */ const char *doi, *model, *label, *type; doi = virSecurityManagerGetDOI(driver->securityManager); model = virSecurityManagerGetModel(driver->securityManager); label = virSecurityManagerGetBaseLabel(driver->securityManager, VIR_DOMAIN_VIRT_LXC); type = virDomainVirtTypeToString(VIR_DOMAIN_VIRT_LXC); /* Allocate the primary security driver for LXC. */ if (VIR_ALLOC(caps->host.secModels) < 0) goto error; caps->host.nsecModels = 1; if (VIR_STRDUP(caps->host.secModels[0].model, model) < 0) goto error; if (VIR_STRDUP(caps->host.secModels[0].doi, doi) < 0) goto error; if (label && virCapabilitiesHostSecModelAddBaseLabel(&caps->host.secModels[0], type, label) < 0) goto error; VIR_DEBUG("Initialized caps for security driver \"%s\" with " "DOI \"%s\"", model, doi); } else { VIR_INFO("No driver, not initializing security driver"); } return caps; error: VIR_FREE(lxc_path); virObjectUnref(caps); return NULL; }
int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, const char *filename) { virConfPtr conf = NULL; virConfValuePtr p; int ret = -1; size_t i; /* Just check the file is readable before opening it, otherwise * libvirt emits an error. */ if (access(filename, R_OK) == -1) { VIR_INFO("Could not read qemu config file %s", filename); return 0; } if (!(conf = virConfReadFile(filename, 0))) goto cleanup; #define CHECK_TYPE(name,typ) \ if (p && p->type != (typ)) { \ virReportError(VIR_ERR_INTERNAL_ERROR, \ "%s: %s: expected type " #typ, \ filename, (name)); \ goto cleanup; \ } #define GET_VALUE_LONG(NAME, VAR) \ p = virConfGetValue(conf, NAME); \ CHECK_TYPE(NAME, VIR_CONF_LONG); \ if (p) \ VAR = p->l; #define GET_VALUE_BOOL(NAME, VAR) \ p = virConfGetValue(conf, NAME); \ CHECK_TYPE(NAME, VIR_CONF_LONG); \ if (p) \ VAR = p->l != 0; #define GET_VALUE_STR(NAME, VAR) \ p = virConfGetValue(conf, NAME); \ CHECK_TYPE(NAME, VIR_CONF_STRING); \ if (p && p->str) { \ VIR_FREE(VAR); \ if (VIR_STRDUP(VAR, p->str) < 0) \ goto cleanup; \ } GET_VALUE_BOOL("vnc_auto_unix_socket", cfg->vncAutoUnixSocket); GET_VALUE_BOOL("vnc_tls", cfg->vncTLS); GET_VALUE_BOOL("vnc_tls_x509_verify", cfg->vncTLSx509verify); GET_VALUE_STR("vnc_tls_x509_cert_dir", cfg->vncTLSx509certdir); GET_VALUE_STR("vnc_listen", cfg->vncListen); GET_VALUE_STR("vnc_password", cfg->vncPassword); GET_VALUE_BOOL("vnc_sasl", cfg->vncSASL); GET_VALUE_STR("vnc_sasl_dir", cfg->vncSASLdir); GET_VALUE_BOOL("vnc_allow_host_audio", cfg->vncAllowHostAudio); GET_VALUE_BOOL("nographics_allow_host_audio", cfg->nogfxAllowHostAudio); p = virConfGetValue(conf, "security_driver"); if (p && p->type == VIR_CONF_LIST) { size_t len; virConfValuePtr pp; /* Calc length and check items */ for (len = 0, pp = p->list; pp; len++, pp = pp->next) { if (pp->type != VIR_CONF_STRING) { virReportError(VIR_ERR_CONF_SYNTAX, "%s", _("security_driver must be a list of strings")); goto cleanup; } } if (VIR_ALLOC_N(cfg->securityDriverNames, len + 1) < 0) goto cleanup; for (i = 0, pp = p->list; pp; i++, pp = pp->next) { if (VIR_STRDUP(cfg->securityDriverNames[i], pp->str) < 0) goto cleanup; } cfg->securityDriverNames[len] = NULL; } else { CHECK_TYPE("security_driver", VIR_CONF_STRING); if (p && p->str) { if (VIR_ALLOC_N(cfg->securityDriverNames, 2) < 0) goto cleanup; if (VIR_STRDUP(cfg->securityDriverNames[0], p->str) < 0) goto cleanup; cfg->securityDriverNames[1] = NULL; } } GET_VALUE_BOOL("security_default_confined", cfg->securityDefaultConfined); GET_VALUE_BOOL("security_require_confined", cfg->securityRequireConfined); GET_VALUE_BOOL("spice_tls", cfg->spiceTLS); GET_VALUE_STR("spice_tls_x509_cert_dir", cfg->spiceTLSx509certdir); GET_VALUE_BOOL("spice_sasl", cfg->spiceSASL); GET_VALUE_STR("spice_sasl_dir", cfg->spiceSASLdir); GET_VALUE_STR("spice_listen", cfg->spiceListen); GET_VALUE_STR("spice_password", cfg->spicePassword); GET_VALUE_LONG("remote_websocket_port_min", cfg->webSocketPortMin); if (cfg->webSocketPortMin < QEMU_WEBSOCKET_PORT_MIN) { /* if the port is too low, we can't get the display name * to tell to vnc (usually subtract 5700, e.g. localhost:1 * for port 5701) */ virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_websocket_port_min: port must be greater " "than or equal to %d"), filename, QEMU_WEBSOCKET_PORT_MIN); goto cleanup; } GET_VALUE_LONG("remote_websocket_port_max", cfg->webSocketPortMax); if (cfg->webSocketPortMax > QEMU_WEBSOCKET_PORT_MAX || cfg->webSocketPortMax < cfg->webSocketPortMin) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_websocket_port_max: port must be between " "the minimal port and %d"), filename, QEMU_WEBSOCKET_PORT_MAX); goto cleanup; } if (cfg->webSocketPortMin > cfg->webSocketPortMax) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_websocket_port_min: min port must not be " "greater than max port"), filename); goto cleanup; } GET_VALUE_LONG("remote_display_port_min", cfg->remotePortMin); if (cfg->remotePortMin < QEMU_REMOTE_PORT_MIN) { /* if the port is too low, we can't get the display name * to tell to vnc (usually subtract 5900, e.g. localhost:1 * for port 5901) */ virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_display_port_min: port must be greater " "than or equal to %d"), filename, QEMU_REMOTE_PORT_MIN); goto cleanup; } GET_VALUE_LONG("remote_display_port_max", cfg->remotePortMax); if (cfg->remotePortMax > QEMU_REMOTE_PORT_MAX || cfg->remotePortMax < cfg->remotePortMin) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_display_port_max: port must be between " "the minimal port and %d"), filename, QEMU_REMOTE_PORT_MAX); goto cleanup; } if (cfg->remotePortMin > cfg->remotePortMax) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_display_port_min: min port must not be " "greater than max port"), filename); goto cleanup; } GET_VALUE_LONG("migration_port_min", cfg->migrationPortMin); if (cfg->migrationPortMin <= 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: migration_port_min: port must be greater than 0"), filename); goto cleanup; } GET_VALUE_LONG("migration_port_max", cfg->migrationPortMax); if (cfg->migrationPortMax > 65535 || cfg->migrationPortMax < cfg->migrationPortMin) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: migration_port_max: port must be between " "the minimal port %d and 65535"), filename, cfg->migrationPortMin); goto cleanup; } p = virConfGetValue(conf, "user"); CHECK_TYPE("user", VIR_CONF_STRING); if (p && p->str && virGetUserID(p->str, &cfg->user) < 0) goto cleanup; p = virConfGetValue(conf, "group"); CHECK_TYPE("group", VIR_CONF_STRING); if (p && p->str && virGetGroupID(p->str, &cfg->group) < 0) goto cleanup; GET_VALUE_BOOL("dynamic_ownership", cfg->dynamicOwnership); p = virConfGetValue(conf, "cgroup_controllers"); CHECK_TYPE("cgroup_controllers", VIR_CONF_LIST); if (p) { cfg->cgroupControllers = 0; virConfValuePtr pp; for (i = 0, pp = p->list; pp; ++i, pp = pp->next) { int ctl; if (pp->type != VIR_CONF_STRING) { virReportError(VIR_ERR_CONF_SYNTAX, "%s", _("cgroup_controllers must be a " "list of strings")); goto cleanup; } if ((ctl = virCgroupControllerTypeFromString(pp->str)) < 0) { virReportError(VIR_ERR_CONF_SYNTAX, _("Unknown cgroup controller '%s'"), pp->str); goto cleanup; } cfg->cgroupControllers |= (1 << ctl); } } p = virConfGetValue(conf, "cgroup_device_acl"); CHECK_TYPE("cgroup_device_acl", VIR_CONF_LIST); if (p) { int len = 0; virConfValuePtr pp; for (pp = p->list; pp; pp = pp->next) len++; if (VIR_ALLOC_N(cfg->cgroupDeviceACL, 1+len) < 0) goto cleanup; for (i = 0, pp = p->list; pp; ++i, pp = pp->next) { if (pp->type != VIR_CONF_STRING) { virReportError(VIR_ERR_CONF_SYNTAX, "%s", _("cgroup_device_acl must be a " "list of strings")); goto cleanup; } if (VIR_STRDUP(cfg->cgroupDeviceACL[i], pp->str) < 0) goto cleanup; } cfg->cgroupDeviceACL[i] = NULL; } GET_VALUE_STR("save_image_format", cfg->saveImageFormat); GET_VALUE_STR("dump_image_format", cfg->dumpImageFormat); GET_VALUE_STR("snapshot_image_format", cfg->snapshotImageFormat); GET_VALUE_STR("auto_dump_path", cfg->autoDumpPath); GET_VALUE_BOOL("auto_dump_bypass_cache", cfg->autoDumpBypassCache); GET_VALUE_BOOL("auto_start_bypass_cache", cfg->autoStartBypassCache); GET_VALUE_STR("hugetlbfs_mount", cfg->hugetlbfsMount); GET_VALUE_STR("bridge_helper", cfg->bridgeHelperName); GET_VALUE_BOOL("mac_filter", cfg->macFilter); GET_VALUE_BOOL("relaxed_acs_check", cfg->relaxedACS); GET_VALUE_BOOL("clear_emulator_capabilities", cfg->clearEmulatorCapabilities); GET_VALUE_BOOL("allow_disk_format_probing", cfg->allowDiskFormatProbing); GET_VALUE_BOOL("set_process_name", cfg->setProcessName); GET_VALUE_LONG("max_processes", cfg->maxProcesses); GET_VALUE_LONG("max_files", cfg->maxFiles); GET_VALUE_STR("lock_manager", cfg->lockManagerName); GET_VALUE_LONG("max_queued", cfg->maxQueuedJobs); GET_VALUE_LONG("keepalive_interval", cfg->keepAliveInterval); GET_VALUE_LONG("keepalive_count", cfg->keepAliveCount); GET_VALUE_LONG("seccomp_sandbox", cfg->seccompSandbox); GET_VALUE_STR("migration_address", cfg->migrationAddress); ret = 0; cleanup: virConfFree(conf); return ret; }
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; }
static void bhyveMonitorIO(int watch, int kq, int events ATTRIBUTE_UNUSED, void *opaque) { const struct timespec zerowait = { 0, 0 }; virDomainObjPtr vm = opaque; bhyveDomainObjPrivatePtr priv = vm->privateData; bhyveMonitorPtr mon = priv->mon; struct kevent kev; int rc, status; if (watch != mon->watch || kq != mon->kq) { virReportError(VIR_ERR_INTERNAL_ERROR, _("event from unexpected fd %d!=%d / watch %d!=%d"), mon->kq, kq, mon->watch, watch); return; } rc = kevent(kq, NULL, 0, &kev, 1, &zerowait); if (rc < 0) { virReportSystemError(errno, "%s", _("Unable to query kqueue")); return; } if (rc == 0) return; if ((kev.flags & EV_ERROR) != 0) { virReportSystemError(kev.data, "%s", _("Unable to query kqueue")); return; } if (kev.filter == EVFILT_PROC && (kev.fflags & NOTE_EXIT) != 0) { if ((pid_t)kev.ident != vm->pid) { virReportError(VIR_ERR_INTERNAL_ERROR, _("event from unexpected proc %ju!=%ju"), (uintmax_t)vm->pid, (uintmax_t)kev.ident); return; } status = kev.data; if (WIFSIGNALED(status) && WCOREDUMP(status)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Guest %s got signal %d and crashed"), vm->def->name, WTERMSIG(status)); virBhyveProcessStop(mon->driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED); } else if (WIFEXITED(status)) { if (WEXITSTATUS(status) == 0) { /* 0 - reboot */ /* TODO: Implementing reboot is a little more complicated. */ VIR_INFO("Guest %s rebooted; destroying domain.", vm->def->name); virBhyveProcessStop(mon->driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); } else if (WEXITSTATUS(status) < 3) { /* 1 - shutdown, 2 - halt, 3 - triple fault. others - error */ VIR_INFO("Guest %s shut itself down; destroying domain.", vm->def->name); virBhyveProcessStop(mon->driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); } else { VIR_INFO("Guest %s had an error and exited with status %d; destroying domain.", vm->def->name, WEXITSTATUS(status)); virBhyveProcessStop(mon->driver, vm, VIR_DOMAIN_SHUTOFF_UNKNOWN); } } } }
/* * virPolkitCheckAuth: * @actionid: permission to check * @pid: client process ID * @startTime: process start time, or 0 * @uid: client process user ID * @details: NULL terminated (key, value) pair list * @allowInteraction: true if auth prompts are allowed * * Check if a client is authenticated with polkit * * Returns 0 on success, -1 on failure, -2 on auth denied */ int virPolkitCheckAuth(const char *actionid, pid_t pid, unsigned long long startTime, uid_t uid, const char **details, bool allowInteraction) { DBusConnection *sysbus; DBusMessage *reply = NULL; char **retdetails = NULL; size_t nretdetails = 0; bool is_authorized; bool is_challenge; bool is_dismissed = false; size_t i; int ret = -1; if (!(sysbus = virDBusGetSystemBus())) goto cleanup; VIR_INFO("Checking PID %lld running as %d", (long long) pid, uid); if (virDBusCallMethod(sysbus, &reply, NULL, "org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority", "org.freedesktop.PolicyKit1.Authority", "CheckAuthorization", "(sa{sv})sa&{ss}us", "unix-process", 3, "pid", "u", (unsigned int)pid, "start-time", "t", startTime, "uid", "i", (int)uid, actionid, virStringListLength(details) / 2, details, allowInteraction, "" /* cancellation ID */) < 0) goto cleanup; if (virDBusMessageRead(reply, "(bba&{ss})", &is_authorized, &is_challenge, &nretdetails, &retdetails) < 0) goto cleanup; for (i = 0; i < (nretdetails / 2); i++) { if (STREQ(retdetails[(i * 2)], "polkit.dismissed") && STREQ(retdetails[(i * 2) + 1], "true")) is_dismissed = true; } VIR_DEBUG("is auth %d is challenge %d", is_authorized, is_challenge); if (is_authorized) { ret = 0; } else { ret = -2; if (is_dismissed) virReportError(VIR_ERR_AUTH_CANCELLED, "%s", _("user cancelled authentication process")); else if (is_challenge) virReportError(VIR_ERR_AUTH_UNAVAILABLE, _("no polkit agent available to authenticate " "action '%s'"), actionid); else virReportError(VIR_ERR_AUTH_FAILED, "%s", _("access denied by policy")); } cleanup: virStringFreeListCount(retdetails, nretdetails); return ret; }
int virPolkitCheckAuth(const char *actionid, pid_t pid, unsigned long long startTime ATTRIBUTE_UNUSED, uid_t uid, const char **details, bool allowInteraction ATTRIBUTE_UNUSED) { PolKitCaller *pkcaller = NULL; PolKitAction *pkaction = NULL; PolKitContext *pkcontext = NULL; PolKitError *pkerr = NULL; PolKitResult pkresult; DBusError err; DBusConnection *sysbus; int ret = -1; if (details) { virReportError(VIR_ERR_AUTH_FAILED, "%s", _("Details not supported with polkit v0")); return -1; } if (!(sysbus = virDBusGetSystemBus())) goto cleanup; VIR_INFO("Checking PID %lld running as %d", (long long) pid, uid); dbus_error_init(&err); if (!(pkcaller = polkit_caller_new_from_pid(sysbus, pid, &err))) { VIR_DEBUG("Failed to lookup policy kit caller: %s", err.message); dbus_error_free(&err); goto cleanup; } if (!(pkaction = polkit_action_new())) { char ebuf[1024]; VIR_DEBUG("Failed to create polkit action %s", virStrerror(errno, ebuf, sizeof(ebuf))); goto cleanup; } polkit_action_set_action_id(pkaction, actionid); if (!(pkcontext = polkit_context_new()) || !polkit_context_init(pkcontext, &pkerr)) { char ebuf[1024]; VIR_DEBUG("Failed to create polkit context %s", (pkerr ? polkit_error_get_error_message(pkerr) : virStrerror(errno, ebuf, sizeof(ebuf)))); if (pkerr) polkit_error_free(pkerr); dbus_error_free(&err); goto cleanup; } # if HAVE_POLKIT_CONTEXT_IS_CALLER_AUTHORIZED pkresult = polkit_context_is_caller_authorized(pkcontext, pkaction, pkcaller, 0, &pkerr); if (pkerr && polkit_error_is_set(pkerr)) { VIR_DEBUG("Policy kit failed to check authorization %d %s", polkit_error_get_error_code(pkerr), polkit_error_get_error_message(pkerr)); goto cleanup; } # else pkresult = polkit_context_can_caller_do_action(pkcontext, pkaction, pkcaller); # endif if (pkresult != POLKIT_RESULT_YES) { VIR_DEBUG("Policy kit denied action %s from pid %lld, uid %d, result: %s", actionid, (long long) pid, uid, polkit_result_to_string_representation(pkresult)); ret = -2; goto cleanup; } VIR_DEBUG("Policy allowed action %s from pid %lld, uid %d", actionid, (long long)pid, (int)uid); ret = 0; cleanup: if (ret < 0) { virResetLastError(); virReportError(VIR_ERR_AUTH_FAILED, "%s", _("authentication failed")); } if (pkcontext) polkit_context_unref(pkcontext); if (pkcaller) polkit_caller_unref(pkcaller); if (pkaction) polkit_action_unref(pkaction); return ret; }
void * virDriverLoadModule(const char *name) { char *modfile = NULL, *regfunc = NULL, *fixedname = NULL; char *tmp; void *handle = NULL; int (*regsym)(void); VIR_DEBUG("Module load %s", name); if (!(modfile = virFileFindResourceFull(name, "libvirt_driver_", ".so", abs_topbuilddir "/src/.libs", DEFAULT_DRIVER_DIR, "LIBVIRT_DRIVER_DIR"))) return NULL; if (access(modfile, R_OK) < 0) { VIR_INFO("Module %s not accessible", modfile); goto cleanup; } virUpdateSelfLastChanged(modfile); handle = dlopen(modfile, RTLD_NOW | RTLD_GLOBAL); if (!handle) { VIR_ERROR(_("failed to load module %s %s"), modfile, dlerror()); goto cleanup; } if (VIR_STRDUP_QUIET(fixedname, name) < 0) { VIR_ERROR(_("out of memory")); goto cleanup; } /* convert something_like_this into somethingLikeThis */ while ((tmp = strchr(fixedname, '_'))) { memmove(tmp, tmp + 1, strlen(tmp)); *tmp = c_toupper(*tmp); } if (virAsprintfQuiet(®func, "%sRegister", fixedname) < 0) goto cleanup; regsym = dlsym(handle, regfunc); if (!regsym) { VIR_ERROR(_("Missing module registration symbol %s"), regfunc); goto cleanup; } if ((*regsym)() < 0) { VIR_ERROR(_("Failed module registration %s"), regfunc); goto cleanup; } VIR_FREE(modfile); VIR_FREE(regfunc); VIR_FREE(fixedname); return handle; cleanup: VIR_FREE(modfile); VIR_FREE(regfunc); VIR_FREE(fixedname); if (handle) dlclose(handle); return NULL; }
int qemudLoadDriverConfig(struct qemud_driver *driver, const char *filename) { virConfPtr conf; virConfValuePtr p; char *user; char *group; int i; /* Setup critical defaults */ driver->securityDefaultConfined = true; driver->securityRequireConfined = false; driver->dynamicOwnership = 1; driver->clearEmulatorCapabilities = 1; if (!(driver->vncListen = strdup("127.0.0.1"))) { virReportOOMError(); return -1; } driver->remotePortMin = QEMU_REMOTE_PORT_MIN; driver->remotePortMax = QEMU_REMOTE_PORT_MAX; if (!(driver->vncTLSx509certdir = strdup(SYSCONFDIR "/pki/libvirt-vnc"))) { virReportOOMError(); return -1; } if (!(driver->spiceListen = strdup("127.0.0.1"))) { virReportOOMError(); return -1; } if (!(driver->spiceTLSx509certdir = strdup(SYSCONFDIR "/pki/libvirt-spice"))) { virReportOOMError(); return -1; } #if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R /* For privileged driver, try and find hugepage mount automatically. * Non-privileged driver requires admin to create a dir for the * user, chown it, and then let user configure it manually */ if (driver->privileged && !(driver->hugetlbfs_mount = virFileFindMountPoint("hugetlbfs"))) { if (errno != ENOENT) { virReportSystemError(errno, "%s", _("unable to find hugetlbfs mountpoint")); return -1; } } #endif if (!(driver->lockManager = virLockManagerPluginNew("nop", NULL, 0))) return -1; driver->keepAliveInterval = 5; driver->keepAliveCount = 5; /* 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; } conf = virConfReadFile (filename, 0); if (!conf) { return -1; } #define CHECK_TYPE(name,typ) if (p && p->type != (typ)) { \ virReportError(VIR_ERR_INTERNAL_ERROR, \ "%s: %s: expected type " #typ, \ filename, (name)); \ virConfFree(conf); \ return -1; \ } p = virConfGetValue (conf, "vnc_auto_unix_socket"); CHECK_TYPE ("vnc_auto_unix_socket", VIR_CONF_LONG); if (p) driver->vncAutoUnixSocket = p->l; p = virConfGetValue (conf, "vnc_tls"); CHECK_TYPE ("vnc_tls", VIR_CONF_LONG); if (p) driver->vncTLS = p->l; p = virConfGetValue (conf, "vnc_tls_x509_verify"); CHECK_TYPE ("vnc_tls_x509_verify", VIR_CONF_LONG); if (p) driver->vncTLSx509verify = p->l; p = virConfGetValue (conf, "vnc_tls_x509_cert_dir"); CHECK_TYPE ("vnc_tls_x509_cert_dir", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->vncTLSx509certdir); if (!(driver->vncTLSx509certdir = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "vnc_listen"); CHECK_TYPE ("vnc_listen", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->vncListen); if (!(driver->vncListen = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "vnc_password"); CHECK_TYPE ("vnc_password", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->vncPassword); if (!(driver->vncPassword = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "security_driver"); if (p && p->type == VIR_CONF_LIST) { size_t len; virConfValuePtr pp; /* Calc lenght and check items */ for (len = 0, pp = p->list; pp; len++, pp = pp->next) { if (pp->type != VIR_CONF_STRING) { VIR_ERROR(_("security_driver be a list of strings")); virConfFree(conf); return -1; } } if (VIR_ALLOC_N(driver->securityDriverNames, len + 1) < 0) { virReportOOMError(); virConfFree(conf); return -1; } for (i = 0, pp = p->list; pp; i++, pp = pp->next) { driver->securityDriverNames[i] = strdup(pp->str); if (driver->securityDriverNames == NULL) { virReportOOMError(); virConfFree(conf); return -1; } } driver->securityDriverNames[len] = NULL; } else { CHECK_TYPE ("security_driver", VIR_CONF_STRING); if (p && p->str) { if (VIR_ALLOC_N(driver->securityDriverNames, 2) < 0 || !(driver->securityDriverNames[0] = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } driver->securityDriverNames[1] = NULL; } } p = virConfGetValue (conf, "security_default_confined"); CHECK_TYPE ("security_default_confined", VIR_CONF_LONG); if (p) driver->securityDefaultConfined = p->l; p = virConfGetValue (conf, "security_require_confined"); CHECK_TYPE ("security_require_confined", VIR_CONF_LONG); if (p) driver->securityRequireConfined = p->l; p = virConfGetValue (conf, "vnc_sasl"); CHECK_TYPE ("vnc_sasl", VIR_CONF_LONG); if (p) driver->vncSASL = p->l; p = virConfGetValue (conf, "vnc_sasl_dir"); CHECK_TYPE ("vnc_sasl_dir", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->vncSASLdir); if (!(driver->vncSASLdir = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "spice_tls"); CHECK_TYPE ("spice_tls", VIR_CONF_LONG); if (p) driver->spiceTLS = p->l; p = virConfGetValue (conf, "spice_tls_x509_cert_dir"); CHECK_TYPE ("spice_tls_x509_cert_dir", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->spiceTLSx509certdir); if (!(driver->spiceTLSx509certdir = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "spice_listen"); CHECK_TYPE ("spice_listen", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->spiceListen); if (!(driver->spiceListen = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "spice_password"); CHECK_TYPE ("spice_password", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->spicePassword); if (!(driver->spicePassword = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "remote_display_port_min"); CHECK_TYPE ("remote_display_port_min", VIR_CONF_LONG); if (p) { if (p->l < 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); virConfFree(conf); return -1; } driver->remotePortMin = p->l; } p = virConfGetValue (conf, "remote_display_port_max"); CHECK_TYPE ("remote_display_port_max", VIR_CONF_LONG); if (p) { if (p->l > QEMU_REMOTE_PORT_MAX || p->l < driver->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); virConfFree(conf); return -1; } /* increasing the value by 1 makes all the loops going through the bitmap (i = remotePortMin; i < remotePortMax; i++), work as expected. */ driver->remotePortMax = p->l + 1; } if (driver->remotePortMin > driver->remotePortMax) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_display_port_min: min port must not be greater than max port"), filename); virConfFree(conf); return -1; } p = virConfGetValue (conf, "user"); CHECK_TYPE ("user", VIR_CONF_STRING); if (!(user = strdup(p && p->str ? p->str : QEMU_USER))) { virReportOOMError(); virConfFree(conf); return -1; } if (virGetUserID(user, &driver->user) < 0) { VIR_FREE(user); virConfFree(conf); return -1; } VIR_FREE(user); p = virConfGetValue (conf, "group"); CHECK_TYPE ("group", VIR_CONF_STRING); if (!(group = strdup(p && p->str ? p->str : QEMU_GROUP))) { virReportOOMError(); virConfFree(conf); return -1; } if (virGetGroupID(group, &driver->group) < 0) { VIR_FREE(group); virConfFree(conf); return -1; } VIR_FREE(group); p = virConfGetValue (conf, "dynamic_ownership"); CHECK_TYPE ("dynamic_ownership", VIR_CONF_LONG); if (p) driver->dynamicOwnership = p->l; p = virConfGetValue (conf, "cgroup_controllers"); CHECK_TYPE ("cgroup_controllers", VIR_CONF_LIST); if (p) { virConfValuePtr pp; for (i = 0, pp = p->list; pp; ++i, pp = pp->next) { int ctl; if (pp->type != VIR_CONF_STRING) { VIR_ERROR(_("cgroup_controllers must be a list of strings")); virConfFree(conf); return -1; } ctl = virCgroupControllerTypeFromString(pp->str); if (ctl < 0) { VIR_ERROR(_("Unknown cgroup controller '%s'"), pp->str); virConfFree(conf); return -1; } driver->cgroupControllers |= (1 << ctl); } } else { driver->cgroupControllers = (1 << VIR_CGROUP_CONTROLLER_CPU) | (1 << VIR_CGROUP_CONTROLLER_DEVICES) | (1 << VIR_CGROUP_CONTROLLER_MEMORY) | (1 << VIR_CGROUP_CONTROLLER_BLKIO) | (1 << VIR_CGROUP_CONTROLLER_CPUSET) | (1 << VIR_CGROUP_CONTROLLER_CPUACCT); } for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) { if (driver->cgroupControllers & (1 << i)) { VIR_INFO("Configured cgroup controller '%s'", virCgroupControllerTypeToString(i)); } } 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(driver->cgroupDeviceACL, 1+len) < 0) { virReportOOMError(); virConfFree(conf); return -1; } for (i = 0, pp = p->list; pp; ++i, pp = pp->next) { if (pp->type != VIR_CONF_STRING) { VIR_ERROR(_("cgroup_device_acl must be a list of strings")); virConfFree(conf); return -1; } driver->cgroupDeviceACL[i] = strdup (pp->str); if (driver->cgroupDeviceACL[i] == NULL) { virReportOOMError(); virConfFree(conf); return -1; } } driver->cgroupDeviceACL[i] = NULL; } p = virConfGetValue (conf, "save_image_format"); CHECK_TYPE ("save_image_format", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->saveImageFormat); if (!(driver->saveImageFormat = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "dump_image_format"); CHECK_TYPE ("dump_image_format", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->dumpImageFormat); if (!(driver->dumpImageFormat = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "auto_dump_path"); CHECK_TYPE ("auto_dump_path", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->autoDumpPath); if (!(driver->autoDumpPath = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "auto_dump_bypass_cache"); CHECK_TYPE ("auto_dump_bypass_cache", VIR_CONF_LONG); if (p) driver->autoDumpBypassCache = true; p = virConfGetValue (conf, "auto_start_bypass_cache"); CHECK_TYPE ("auto_start_bypass_cache", VIR_CONF_LONG); if (p) driver->autoStartBypassCache = true; p = virConfGetValue (conf, "hugetlbfs_mount"); CHECK_TYPE ("hugetlbfs_mount", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->hugetlbfs_mount); if (!(driver->hugetlbfs_mount = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "mac_filter"); CHECK_TYPE ("mac_filter", VIR_CONF_LONG); if (p && p->l) { driver->macFilter = p->l; if (!(driver->ebtables = ebtablesContextNew("qemu"))) { driver->macFilter = 0; virReportSystemError(errno, _("failed to enable mac filter in '%s'"), __FILE__); virConfFree(conf); return -1; } if ((errno = networkDisableAllFrames(driver))) { virReportSystemError(errno, _("failed to add rule to drop all frames in '%s'"), __FILE__); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "relaxed_acs_check"); CHECK_TYPE ("relaxed_acs_check", VIR_CONF_LONG); if (p) driver->relaxedACS = p->l; p = virConfGetValue (conf, "vnc_allow_host_audio"); CHECK_TYPE ("vnc_allow_host_audio", VIR_CONF_LONG); if (p) driver->vncAllowHostAudio = p->l; p = virConfGetValue (conf, "clear_emulator_capabilities"); CHECK_TYPE ("clear_emulator_capabilities", VIR_CONF_LONG); if (p) driver->clearEmulatorCapabilities = p->l; p = virConfGetValue (conf, "allow_disk_format_probing"); CHECK_TYPE ("allow_disk_format_probing", VIR_CONF_LONG); if (p) driver->allowDiskFormatProbing = p->l; p = virConfGetValue (conf, "set_process_name"); CHECK_TYPE ("set_process_name", VIR_CONF_LONG); if (p) driver->setProcessName = p->l; p = virConfGetValue(conf, "max_processes"); CHECK_TYPE("max_processes", VIR_CONF_LONG); if (p) driver->maxProcesses = p->l; p = virConfGetValue(conf, "max_files"); CHECK_TYPE("max_files", VIR_CONF_LONG); if (p) driver->maxFiles = p->l; p = virConfGetValue (conf, "lock_manager"); CHECK_TYPE ("lock_manager", VIR_CONF_STRING); if (p && p->str) { char *lockConf; virLockManagerPluginUnref(driver->lockManager); if (virAsprintf(&lockConf, "%s/libvirt/qemu-%s.conf", SYSCONFDIR, p->str) < 0) { virReportOOMError(); virConfFree(conf); return -1; } if (!(driver->lockManager = virLockManagerPluginNew(p->str, lockConf, 0))) VIR_ERROR(_("Failed to load lock manager %s"), p->str); VIR_FREE(lockConf); } p = virConfGetValue(conf, "max_queued"); CHECK_TYPE("max_queued", VIR_CONF_LONG); if (p) driver->max_queued = p->l; p = virConfGetValue(conf, "keepalive_interval"); CHECK_TYPE("keepalive_interval", VIR_CONF_LONG); if (p) driver->keepAliveInterval = p->l; p = virConfGetValue(conf, "keepalive_count"); CHECK_TYPE("keepalive_count", VIR_CONF_LONG); if (p) driver->keepAliveCount = p->l; virConfFree (conf); return 0; }
/** * virSystemdCreateMachine: * @name: driver unique name of the machine * @drivername: name of the virt driver * @privileged: whether driver is running privileged or per user * @uuid: globally unique UUID of the machine * @rootdir: root directory of machine filesystem * @pidleader: PID of the leader process * @iscontainer: true if a container, false if a VM * @nnicindexes: number of network interface indexes in list * @nicindexes: list of network interface indexes * @partition: name of the slice to place the machine in * * Returns 0 on success, -1 on fatal error, or -2 if systemd-machine is not available */ int virSystemdCreateMachine(const char *name, const char *drivername, bool privileged, const unsigned char *uuid, const char *rootdir, pid_t pidleader, bool iscontainer, size_t nnicindexes, int *nicindexes, const char *partition) { int ret; DBusConnection *conn; char *machinename = NULL; char *creatorname = NULL; char *slicename = NULL; static int hasCreateWithNetwork = 1; ret = virDBusIsServiceEnabled("org.freedesktop.machine1"); if (ret < 0) return ret; if ((ret = virDBusIsServiceRegistered("org.freedesktop.systemd1")) < 0) return ret; if (!(conn = virDBusGetSystemBus())) return -1; ret = -1; if (!(machinename = virSystemdMakeMachineName(name, drivername, privileged))) goto cleanup; if (virAsprintf(&creatorname, "libvirt-%s", drivername) < 0) goto cleanup; if (partition) { if (!(slicename = virSystemdMakeSliceName(partition))) goto cleanup; } else { if (VIR_STRDUP(slicename, "") < 0) goto cleanup; } /* * The systemd DBus APIs we're invoking have the * following signature(s) * * CreateMachineWithNetwork(in s name, * in ay id, * in s service, * in s class, * in u leader, * in s root_directory, * in ai nicindexes * in a(sv) scope_properties, * out o path); * * CreateMachine(in s name, * in ay id, * in s service, * in s class, * in u leader, * in s root_directory, * in a(sv) scope_properties, * out o path); * * @name a host unique name for the machine. shows up * in 'ps' listing & similar * * @id: a UUID of the machine, ideally matching /etc/machine-id * for containers * * @service: identifier of the client ie "libvirt-lxc" * * @class: either the string "container" or "vm" depending * on the type of machine * * @leader: main PID of the machine, either the host emulator * process, or the 'init' PID of the container * * @root_directory: the root directory of the container, if * this is known & visible in the host filesystem, or empty string * * @nicindexes: list of network interface indexes for the * host end of the VETH device pairs. * * @scope_properties:an array (not a dict!) of properties that are * passed on to PID 1 when creating a scope unit for your machine. * Will allow initial settings for the cgroup & similar. * * @path: a bus path returned for the machine object created, to * allow further API calls to be made against the object. * */ VIR_DEBUG("Attempting to create machine via systemd"); if (virAtomicIntGet(&hasCreateWithNetwork)) { virError error; memset(&error, 0, sizeof(error)); if (virDBusCallMethod(conn, NULL, &error, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "CreateMachineWithNetwork", "sayssusa&ia(sv)", machinename, 16, uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15], creatorname, iscontainer ? "container" : "vm", (unsigned int)pidleader, rootdir ? rootdir : "", nnicindexes, nicindexes, 3, "Slice", "s", slicename, "After", "as", 1, "libvirtd.service", "Before", "as", 1, "libvirt-guests.service") < 0) goto cleanup; if (error.level == VIR_ERR_ERROR) { if (virDBusErrorIsUnknownMethod(&error)) { VIR_INFO("CreateMachineWithNetwork isn't supported, switching " "to legacy CreateMachine method for systemd-machined"); virResetError(&error); virAtomicIntSet(&hasCreateWithNetwork, 0); /* Could re-structure without Using goto, but this * avoids another atomic read which would trigger * another memory barrier */ goto fallback; } virReportErrorObject(&error); virResetError(&error); goto cleanup; } } else { fallback: if (virDBusCallMethod(conn, NULL, NULL, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "CreateMachine", "sayssusa(sv)", machinename, 16, uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15], creatorname, iscontainer ? "container" : "vm", (unsigned int)pidleader, rootdir ? rootdir : "", 3, "Slice", "s", slicename, "After", "as", 1, "libvirtd.service", "Before", "as", 1, "libvirt-guests.service") < 0) goto cleanup; } ret = 0; cleanup: VIR_FREE(creatorname); VIR_FREE(machinename); VIR_FREE(slicename); return ret; }
static int vzCheckDiskUnsupportedParams(virDomainDiskDefPtr disk) { if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK && disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Only hard disks and cdroms are supported " "by vz driver.")); return -1; } if (disk->blockio.logical_block_size || disk->blockio.physical_block_size) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Setting disk block sizes is not " "supported by vz driver.")); return -1; } if (disk->blkdeviotune.total_bytes_sec || disk->blkdeviotune.read_bytes_sec || disk->blkdeviotune.write_bytes_sec || disk->blkdeviotune.total_iops_sec || disk->blkdeviotune.read_iops_sec || disk->blkdeviotune.write_iops_sec) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Setting disk io limits is not " "supported by vz driver yet.")); return -1; } if (disk->serial) { VIR_INFO("%s", _("Setting disk serial number is not " "supported by vz driver.")); } if (disk->wwn) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Setting disk wwn id is not " "supported by vz driver.")); return -1; } if (disk->vendor) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Setting disk vendor is not " "supported by vz driver.")); return -1; } if (disk->product) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Setting disk product id is not " "supported by vz driver.")); return -1; } if (disk->error_policy != VIR_DOMAIN_DISK_ERROR_POLICY_DEFAULT) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Setting disk error policy is not " "supported by vz driver.")); return -1; } if (disk->iomode != VIR_DOMAIN_DISK_IO_DEFAULT && disk->iomode != VIR_DOMAIN_DISK_IO_NATIVE) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Only native iomode is " "supported by vz driver.")); return -1; } if (disk->copy_on_read) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Disk copy_on_read is not " "supported by vz driver.")); return -1; } if (disk->startupPolicy != VIR_DOMAIN_STARTUP_POLICY_DEFAULT) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Setting up disk startup policy is not " "supported by vz driver.")); return -1; } if (disk->transient) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Transient disks are not " "supported by vz driver.")); return -1; } if (disk->discard) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Setting up disk discard parameter is not " "supported by vz driver.")); return -1; } if (disk->iothread) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Setting up disk io thread # is not " "supported by vz driver.")); return -1; } if (disk->src->type != VIR_STORAGE_TYPE_FILE && disk->src->type != VIR_STORAGE_TYPE_BLOCK) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Only disk and block storage types are " "supported by vz driver.")); return -1; } return 0; }
int qemudLoadDriverConfig(struct qemud_driver *driver, const char *filename) { virConfPtr conf; virConfValuePtr p; char *user; char *group; int i; /* Setup critical defaults */ driver->dynamicOwnership = 1; driver->clearEmulatorCapabilities = 1; if (!(driver->vncListen = strdup("127.0.0.1"))) { virReportOOMError(); return -1; } if (!(driver->vncTLSx509certdir = strdup(SYSCONFDIR "/pki/libvirt-vnc"))) { virReportOOMError(); return -1; } if (!(driver->spiceListen = strdup("127.0.0.1"))) { virReportOOMError(); return -1; } if (!(driver->spiceTLSx509certdir = strdup(SYSCONFDIR "/pki/libvirt-spice"))) { virReportOOMError(); return -1; } #if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R /* For privileged driver, try and find hugepage mount automatically. * Non-privileged driver requires admin to create a dir for the * user, chown it, and then let user configure it manually */ if (driver->privileged && !(driver->hugetlbfs_mount = virFileFindMountPoint("hugetlbfs"))) { if (errno != ENOENT) { virReportSystemError(errno, "%s", _("unable to find hugetlbfs mountpoint")); return -1; } } #endif /* 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; } conf = virConfReadFile (filename, 0); if (!conf) { return -1; } #define CHECK_TYPE(name,typ) if (p && p->type != (typ)) { \ qemuReportError(VIR_ERR_INTERNAL_ERROR, \ "%s: %s: expected type " #typ, \ filename, (name)); \ virConfFree(conf); \ return -1; \ } p = virConfGetValue (conf, "vnc_auto_unix_socket"); CHECK_TYPE ("vnc_auto_unix_socket", VIR_CONF_LONG); if (p) driver->vncAutoUnixSocket = p->l; p = virConfGetValue (conf, "vnc_tls"); CHECK_TYPE ("vnc_tls", VIR_CONF_LONG); if (p) driver->vncTLS = p->l; p = virConfGetValue (conf, "vnc_tls_x509_verify"); CHECK_TYPE ("vnc_tls_x509_verify", VIR_CONF_LONG); if (p) driver->vncTLSx509verify = p->l; p = virConfGetValue (conf, "vnc_tls_x509_cert_dir"); CHECK_TYPE ("vnc_tls_x509_cert_dir", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->vncTLSx509certdir); if (!(driver->vncTLSx509certdir = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "vnc_listen"); CHECK_TYPE ("vnc_listen", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->vncListen); if (!(driver->vncListen = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "vnc_password"); CHECK_TYPE ("vnc_password", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->vncPassword); if (!(driver->vncPassword = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "security_driver"); CHECK_TYPE ("security_driver", VIR_CONF_STRING); if (p && p->str) { if (!(driver->securityDriverName = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "vnc_sasl"); CHECK_TYPE ("vnc_sasl", VIR_CONF_LONG); if (p) driver->vncSASL = p->l; p = virConfGetValue (conf, "vnc_sasl_dir"); CHECK_TYPE ("vnc_sasl_dir", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->vncSASLdir); if (!(driver->vncSASLdir = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "spice_tls"); CHECK_TYPE ("spice_tls", VIR_CONF_LONG); if (p) driver->spiceTLS = p->l; p = virConfGetValue (conf, "spice_tls_x509_cert_dir"); CHECK_TYPE ("spice_tls_x509_cert_dir", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->spiceTLSx509certdir); if (!(driver->spiceTLSx509certdir = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "spice_listen"); CHECK_TYPE ("spice_listen", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->spiceListen); if (!(driver->spiceListen = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "spice_password"); CHECK_TYPE ("spice_password", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->spicePassword); if (!(driver->spicePassword = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "user"); CHECK_TYPE ("user", VIR_CONF_STRING); if (!(user = strdup(p && p->str ? p->str : QEMU_USER))) { virReportOOMError(); virConfFree(conf); return -1; } if (virGetUserID(user, &driver->user) < 0) { VIR_FREE(user); virConfFree(conf); return -1; } VIR_FREE(user); p = virConfGetValue (conf, "group"); CHECK_TYPE ("group", VIR_CONF_STRING); if (!(group = strdup(p && p->str ? p->str : QEMU_GROUP))) { virReportOOMError(); virConfFree(conf); return -1; } if (virGetGroupID(group, &driver->group) < 0) { VIR_FREE(group); virConfFree(conf); return -1; } VIR_FREE(group); p = virConfGetValue (conf, "dynamic_ownership"); CHECK_TYPE ("dynamic_ownership", VIR_CONF_LONG); if (p) driver->dynamicOwnership = p->l; p = virConfGetValue (conf, "cgroup_controllers"); CHECK_TYPE ("cgroup_controllers", VIR_CONF_LIST); if (p) { virConfValuePtr pp; for (i = 0, pp = p->list; pp; ++i, pp = pp->next) { int ctl; if (pp->type != VIR_CONF_STRING) { VIR_ERROR0(_("cgroup_controllers must be a list of strings")); virConfFree(conf); return -1; } ctl = virCgroupControllerTypeFromString(pp->str); if (ctl < 0) { VIR_ERROR(_("Unknown cgroup controller '%s'"), pp->str); virConfFree(conf); return -1; } driver->cgroupControllers |= (1 << ctl); } } else { driver->cgroupControllers = (1 << VIR_CGROUP_CONTROLLER_CPU) | (1 << VIR_CGROUP_CONTROLLER_DEVICES) | (1 << VIR_CGROUP_CONTROLLER_MEMORY) | (1 << VIR_CGROUP_CONTROLLER_BLKIO); } for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) { if (driver->cgroupControllers & (1 << i)) { VIR_INFO("Configured cgroup controller '%s'", virCgroupControllerTypeToString(i)); } } 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(driver->cgroupDeviceACL, 1+len) < 0) { virReportOOMError(); virConfFree(conf); return -1; } for (i = 0, pp = p->list; pp; ++i, pp = pp->next) { if (pp->type != VIR_CONF_STRING) { VIR_ERROR0(_("cgroup_device_acl must be a list of strings")); virConfFree(conf); return -1; } driver->cgroupDeviceACL[i] = strdup (pp->str); if (driver->cgroupDeviceACL[i] == NULL) { virReportOOMError(); virConfFree(conf); return -1; } } driver->cgroupDeviceACL[i] = NULL; } p = virConfGetValue (conf, "save_image_format"); CHECK_TYPE ("save_image_format", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->saveImageFormat); if (!(driver->saveImageFormat = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "dump_image_format"); CHECK_TYPE ("dump_image_format", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->dumpImageFormat); if (!(driver->dumpImageFormat = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "auto_dump_path"); CHECK_TYPE ("auto_dump_path", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->autoDumpPath); if (!(driver->autoDumpPath = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "hugetlbfs_mount"); CHECK_TYPE ("hugetlbfs_mount", VIR_CONF_STRING); if (p && p->str) { VIR_FREE(driver->hugetlbfs_mount); if (!(driver->hugetlbfs_mount = strdup(p->str))) { virReportOOMError(); virConfFree(conf); return -1; } } p = virConfGetValue (conf, "mac_filter"); CHECK_TYPE ("mac_filter", VIR_CONF_LONG); if (p && p->l) { driver->macFilter = p->l; if (!(driver->ebtables = ebtablesContextNew("qemu"))) { driver->macFilter = 0; virReportSystemError(errno, _("failed to enable mac filter in '%s'"), __FILE__); } if ((errno = networkDisableAllFrames(driver))) { virReportSystemError(errno, _("failed to add rule to drop all frames in '%s'"), __FILE__); } } p = virConfGetValue (conf, "relaxed_acs_check"); CHECK_TYPE ("relaxed_acs_check", VIR_CONF_LONG); if (p) driver->relaxedACS = p->l; p = virConfGetValue (conf, "vnc_allow_host_audio"); CHECK_TYPE ("vnc_allow_host_audio", VIR_CONF_LONG); if (p) driver->vncAllowHostAudio = p->l; p = virConfGetValue (conf, "clear_emulator_capabilities"); CHECK_TYPE ("clear_emulator_capabilities", VIR_CONF_LONG); if (p) driver->clearEmulatorCapabilities = p->l; p = virConfGetValue (conf, "allow_disk_format_probing"); CHECK_TYPE ("allow_disk_format_probing", VIR_CONF_LONG); if (p) driver->allowDiskFormatProbing = p->l; p = virConfGetValue (conf, "set_process_name"); CHECK_TYPE ("set_process_name", VIR_CONF_LONG); if (p) driver->setProcessName = p->l; p = virConfGetValue(conf, "max_processes"); CHECK_TYPE("max_processes", VIR_CONF_LONG); if (p) driver->maxProcesses = p->l; virConfFree (conf); return 0; }
/* Functions */ virCapsPtr lxcCapsInit(virLXCDriverPtr driver) { virCapsPtr caps; virCapsGuestPtr guest; virArch altArch; if ((caps = virCapabilitiesNew(virArchFromHost(), 0, 0)) == NULL) goto error; /* Some machines have problematic NUMA toplogy causing * unexpected failures. We don't want to break the QEMU * driver in this scenario, so log errors & carry on */ if (nodeCapsInitNUMA(caps) < 0) { virCapabilitiesFreeNUMAInfo(caps); VIR_WARN("Failed to query host NUMA topology, disabling NUMA capabilities"); } if (virNodeSuspendGetTargetMask(&caps->host.powerMgmt) < 0) VIR_WARN("Failed to get host power management capabilities"); if (virGetHostUUID(caps->host.host_uuid)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot get the host uuid")); goto error; } if ((guest = virCapabilitiesAddGuest(caps, "exe", caps->host.arch, LIBEXECDIR "/libvirt_lxc", NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, "lxc", NULL, NULL, 0, NULL) == NULL) goto error; /* On 64-bit hosts, we can use personality() to request a 32bit process */ if ((altArch = lxcContainerGetAlt32bitArch(caps->host.arch)) != VIR_ARCH_NONE) { if ((guest = virCapabilitiesAddGuest(caps, "exe", altArch, LIBEXECDIR "/libvirt_lxc", NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, "lxc", NULL, NULL, 0, NULL) == NULL) goto error; } if (driver) { /* Security driver data */ const char *doi, *model; doi = virSecurityManagerGetDOI(driver->securityManager); model = virSecurityManagerGetModel(driver->securityManager); if (STRNEQ(model, "none")) { /* Allocate just the primary security driver for LXC. */ if (VIR_ALLOC(caps->host.secModels) < 0) goto no_memory; caps->host.nsecModels = 1; if (VIR_STRDUP(caps->host.secModels[0].model, model) < 0) goto error; if (VIR_STRDUP(caps->host.secModels[0].doi, doi) < 0) goto error; } VIR_DEBUG("Initialized caps for security driver \"%s\" with " "DOI \"%s\"", model, doi); } else { VIR_INFO("No driver, not initializing security driver"); } return caps; no_memory: virReportOOMError(); error: virObjectUnref(caps); return NULL; }