/* * Copyright Intel Corp. 2020-2021 * * ch_conf.c: functions for Cloud-Hypervisor configuration * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see * . */ #include #include "configmake.h" #include "vircommand.h" #include "virlog.h" #include "virobject.h" #include "virstring.h" #include "virutil.h" #include "ch_conf.h" #include "ch_domain.h" #define VIR_FROM_THIS VIR_FROM_CH VIR_LOG_INIT("ch.ch_conf"); static virClass *virCHDriverConfigClass; static void virCHDriverConfigDispose(void *obj); static int virCHConfigOnceInit(void) { if (!VIR_CLASS_NEW(virCHDriverConfig, virClassForObject())) return -1; return 0; } VIR_ONCE_GLOBAL_INIT(virCHConfig); /* Functions */ virCaps *virCHDriverCapsInit(void) { g_autoptr(virCaps) caps = NULL; virCapsGuest *guest; if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL) return NULL; if (!(caps->host.numa = virCapabilitiesHostNUMANewHost())) return NULL; if (virCapabilitiesInitCaches(caps) < 0) return NULL; guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, caps->host.arch, NULL, NULL, 0, NULL); virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_KVM, NULL, NULL, 0, NULL); return g_steal_pointer(&caps); } /** * virCHDriverGetCapabilities: * * Get a reference to the virCaps instance for the * driver. If @refresh is true, the capabilities will be * rebuilt first * * The caller must release the reference with virObjetUnref * * Returns: a reference to a virCaps instance or NULL */ virCaps *virCHDriverGetCapabilities(virCHDriver *driver, bool refresh) { virCaps *ret = NULL; virCaps *caps = NULL; if (refresh && !(caps = virCHDriverCapsInit())) return NULL; VIR_WITH_MUTEX_LOCK_GUARD(&driver->lock) { if (refresh) { virObjectUnref(driver->caps); driver->caps = caps; } ret = virObjectRef(driver->caps); } return ret; } virDomainXMLOption * chDomainXMLConfInit(virCHDriver *driver) { virCHDriverDomainDefParserConfig.priv = driver; return virDomainXMLOptionNew(&virCHDriverDomainDefParserConfig, &virCHDriverPrivateDataCallbacks, NULL, NULL, NULL, NULL); } virCHDriverConfig * virCHDriverConfigNew(bool privileged) { virCHDriverConfig *cfg; if (virCHConfigInitialize() < 0) return NULL; if (!(cfg = virObjectNew(virCHDriverConfigClass))) return NULL; cfg->cgroupControllers = -1; /* Auto detect */ if (privileged) { if (virGetUserID(CH_USER, &cfg->user) < 0) return NULL; if (virGetGroupID(CH_GROUP, &cfg->group) < 0) return NULL; } else { cfg->user = (uid_t)-1; cfg->group = (gid_t)-1; } if (privileged) { cfg->logDir = g_strdup_printf("%s/log/libvirt/ch", LOCALSTATEDIR); cfg->stateDir = g_strdup_printf("%s/libvirt/ch", RUNSTATEDIR); } else { g_autofree char *rundir = NULL; g_autofree char *cachedir = NULL; cachedir = virGetUserCacheDirectory(); cfg->logDir = g_strdup_printf("%s/ch/log", cachedir); rundir = virGetUserRuntimeDirectory(); cfg->stateDir = g_strdup_printf("%s/ch/run", rundir); } return cfg; } virCHDriverConfig *virCHDriverGetConfig(virCHDriver *driver) { VIR_LOCK_GUARD lock = virLockGuardLock(&driver->lock); return virObjectRef(driver->config); } static void virCHDriverConfigDispose(void *obj) { virCHDriverConfig *cfg = obj; g_free(cfg->stateDir); g_free(cfg->logDir); } #define MIN_VERSION ((15 * 1000000) + (0 * 1000) + (0)) int chExtractVersion(virCHDriver *driver) { unsigned long long version; g_autofree char *help = NULL; char *tmp = NULL; g_autofree char *ch_cmd = g_find_program_in_path(CH_CMD); g_autoptr(virCommand) cmd = NULL; if (!ch_cmd) return -2; cmd = virCommandNewArgList(ch_cmd, "--version", NULL); virCommandAddEnvString(cmd, "LC_ALL=C"); virCommandSetOutputBuffer(cmd, &help); if (virCommandRun(cmd, NULL) < 0) return -1; tmp = help; /* expected format: cloud-hypervisor v.. */ if ((tmp = STRSKIP(tmp, "cloud-hypervisor v")) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unexpected output of cloud-hypervisor binary")); return -1; } if (virStringParseVersion(&version, tmp, true) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unable to parse cloud-hypervisor version: %1$s"), tmp); return -1; } if (version < MIN_VERSION) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Cloud-Hypervisor version is too old (v15.0 is the minimum supported version)")); return -1; } driver->version = version; return 0; }