libvirt/src/ch/ch_driver.c
Michal Privoznik 42cc2f9396 ch_driver: Drop needless fwd declaration
In ch_driver.c there are two forward declarations that are not
needed. Drop them.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2021-11-01 16:04:11 +01:00

1008 lines
26 KiB
C

/*
* Copyright Intel Corp. 2020-2021
*
* ch_driver.c: Core Cloud-Hypervisor driver functions
*
* 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
* <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include "ch_conf.h"
#include "ch_domain.h"
#include "ch_driver.h"
#include "ch_monitor.h"
#include "ch_process.h"
#include "datatypes.h"
#include "driver.h"
#include "viraccessapicheck.h"
#include "viralloc.h"
#include "virbuffer.h"
#include "virchrdev.h"
#include "vircommand.h"
#include "virerror.h"
#include "virfile.h"
#include "virlog.h"
#include "virnetdevtap.h"
#include "virobject.h"
#include "virstring.h"
#include "virtypedparam.h"
#include "viruri.h"
#include "virutil.h"
#include "viruuid.h"
#define VIR_FROM_THIS VIR_FROM_CH
VIR_LOG_INIT("ch.ch_driver");
virCHDriver *ch_driver = NULL;
static virDomainObj *
chDomObjFromDomain(virDomain *domain)
{
virDomainObj *vm;
virCHDriver *driver = domain->conn->privateData;
char uuidstr[VIR_UUID_STRING_BUFLEN];
vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
if (!vm) {
virUUIDFormat(domain->uuid, uuidstr);
virReportError(VIR_ERR_NO_DOMAIN,
_("no domain with matching uuid '%s' (%s)"),
uuidstr, domain->name);
return NULL;
}
return vm;
}
/* Functions */
static int
chConnectURIProbe(char **uri)
{
if (ch_driver == NULL)
return 0;
*uri = g_strdup("ch:///system");
return 1;
}
static virDrvOpenStatus chConnectOpen(virConnectPtr conn,
virConnectAuthPtr auth G_GNUC_UNUSED,
virConf *conf G_GNUC_UNUSED,
unsigned int flags)
{
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
/* URI was good, but driver isn't active */
if (ch_driver == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("Cloud-Hypervisor state driver is not active"));
return VIR_DRV_OPEN_ERROR;
}
if (virConnectOpenEnsureACL(conn) < 0)
return VIR_DRV_OPEN_ERROR;
conn->privateData = ch_driver;
return VIR_DRV_OPEN_SUCCESS;
}
static int chConnectClose(virConnectPtr conn)
{
conn->privateData = NULL;
return 0;
}
static const char *chConnectGetType(virConnectPtr conn)
{
if (virConnectGetTypeEnsureACL(conn) < 0)
return NULL;
return "CH";
}
static int chConnectGetVersion(virConnectPtr conn,
unsigned long *version)
{
virCHDriver *driver = conn->privateData;
if (virConnectGetVersionEnsureACL(conn) < 0)
return -1;
chDriverLock(driver);
*version = driver->version;
chDriverUnlock(driver);
return 0;
}
static char *chConnectGetHostname(virConnectPtr conn)
{
if (virConnectGetHostnameEnsureACL(conn) < 0)
return NULL;
return virGetHostname();
}
static int chConnectNumOfDomains(virConnectPtr conn)
{
virCHDriver *driver = conn->privateData;
if (virConnectNumOfDomainsEnsureACL(conn) < 0)
return -1;
return virDomainObjListNumOfDomains(driver->domains, true,
virConnectNumOfDomainsCheckACL, conn);
}
static int chConnectListDomains(virConnectPtr conn, int *ids, int nids)
{
virCHDriver *driver = conn->privateData;
if (virConnectListDomainsEnsureACL(conn) < 0)
return -1;
return virDomainObjListGetActiveIDs(driver->domains, ids, nids,
virConnectListDomainsCheckACL, conn);
}
static int
chConnectListAllDomains(virConnectPtr conn,
virDomainPtr **domains,
unsigned int flags)
{
virCHDriver *driver = conn->privateData;
virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
if (virConnectListAllDomainsEnsureACL(conn) < 0)
return -1;
return virDomainObjListExport(driver->domains, conn, domains,
virConnectListAllDomainsCheckACL, flags);
}
static int chNodeGetInfo(virConnectPtr conn,
virNodeInfoPtr nodeinfo)
{
if (virNodeGetInfoEnsureACL(conn) < 0)
return -1;
return virCapabilitiesGetNodeInfo(nodeinfo);
}
static char *chConnectGetCapabilities(virConnectPtr conn)
{
virCHDriver *driver = conn->privateData;
virCaps *caps;
char *xml;
if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
return NULL;
if (!(caps = virCHDriverGetCapabilities(driver, true)))
return NULL;
xml = virCapabilitiesFormatXML(caps);
virObjectUnref(caps);
return xml;
}
/**
* chDomainCreateXML:
* @conn: pointer to connection
* @xml: XML definition of domain
* @flags: bitwise-OR of supported virDomainCreateFlags
*
* Creates a domain based on xml and starts it
*
* Returns a new domain object or NULL in case of failure.
*/
static virDomainPtr
chDomainCreateXML(virConnectPtr conn,
const char *xml,
unsigned int flags)
{
virCHDriver *driver = conn->privateData;
virDomainDef *vmdef = NULL;
virDomainObj *vm = NULL;
virDomainPtr dom = NULL;
unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);
if (flags & VIR_DOMAIN_START_VALIDATE)
parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
if ((vmdef = virDomainDefParseString(xml, driver->xmlopt,
NULL, parse_flags)) == NULL)
goto cleanup;
if (virDomainCreateXMLEnsureACL(conn, vmdef) < 0)
goto cleanup;
if (!(vm = virDomainObjListAdd(driver->domains,
vmdef,
driver->xmlopt,
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
vmdef = NULL;
if (virCHDomainObjBeginJob(vm, CH_JOB_MODIFY) < 0)
goto cleanup;
if (virCHProcessStart(driver, vm, VIR_DOMAIN_RUNNING_BOOTED) < 0)
goto cleanup;
dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
virCHDomainObjEndJob(vm);
cleanup:
if (vm && !dom) {
virDomainObjListRemove(driver->domains, vm);
}
virDomainDefFree(vmdef);
virDomainObjEndAPI(&vm);
chDriverUnlock(driver);
return dom;
}
static int
chDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
{
virCHDriver *driver = dom->conn->privateData;
virDomainObj *vm;
int ret = -1;
virCheckFlags(0, -1);
if (!(vm = chDomObjFromDomain(dom)))
goto cleanup;
if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0)
goto cleanup;
if (virCHDomainObjBeginJob(vm, CH_JOB_MODIFY) < 0)
goto cleanup;
ret = virCHProcessStart(driver, vm, VIR_DOMAIN_RUNNING_BOOTED);
virCHDomainObjEndJob(vm);
cleanup:
virDomainObjEndAPI(&vm);
return ret;
}
static int
chDomainCreate(virDomainPtr dom)
{
return chDomainCreateWithFlags(dom, 0);
}
static virDomainPtr
chDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
{
virCHDriver *driver = conn->privateData;
virDomainDef *vmdef = NULL;
virDomainObj *vm = NULL;
virDomainPtr dom = NULL;
unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
if (flags & VIR_DOMAIN_START_VALIDATE)
parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
if ((vmdef = virDomainDefParseString(xml, driver->xmlopt,
NULL, parse_flags)) == NULL)
goto cleanup;
if (virXMLCheckIllegalChars("name", vmdef->name, "\n") < 0)
goto cleanup;
if (virDomainDefineXMLFlagsEnsureACL(conn, vmdef) < 0)
goto cleanup;
if (!(vm = virDomainObjListAdd(driver->domains, vmdef,
driver->xmlopt,
0, NULL)))
goto cleanup;
vmdef = NULL;
vm->persistent = 1;
dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
cleanup:
virDomainDefFree(vmdef);
virDomainObjEndAPI(&vm);
return dom;
}
static virDomainPtr
chDomainDefineXML(virConnectPtr conn, const char *xml)
{
return chDomainDefineXMLFlags(conn, xml, 0);
}
static int
chDomainUndefineFlags(virDomainPtr dom,
unsigned int flags)
{
virCHDriver *driver = dom->conn->privateData;
virDomainObj *vm;
int ret = -1;
virCheckFlags(0, -1);
if (!(vm = chDomObjFromDomain(dom)))
goto cleanup;
if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0)
goto cleanup;
if (!vm->persistent) {
virReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("Cannot undefine transient domain"));
goto cleanup;
}
if (virDomainObjIsActive(vm)) {
vm->persistent = 0;
} else {
virDomainObjListRemove(driver->domains, vm);
}
ret = 0;
cleanup:
virDomainObjEndAPI(&vm);
return ret;
}
static int
chDomainUndefine(virDomainPtr dom)
{
return chDomainUndefineFlags(dom, 0);
}
static int chDomainIsActive(virDomainPtr dom)
{
virCHDriver *driver = dom->conn->privateData;
virDomainObj *vm;
int ret = -1;
chDriverLock(driver);
if (!(vm = chDomObjFromDomain(dom)))
goto cleanup;
if (virDomainIsActiveEnsureACL(dom->conn, vm->def) < 0)
goto cleanup;
ret = virDomainObjIsActive(vm);
cleanup:
virDomainObjEndAPI(&vm);
chDriverUnlock(driver);
return ret;
}
static int
chDomainShutdownFlags(virDomainPtr dom,
unsigned int flags)
{
virCHDomainObjPrivate *priv;
virDomainObj *vm;
virDomainState state;
int ret = -1;
virCheckFlags(VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN, -1);
if (!(vm = chDomObjFromDomain(dom)))
goto cleanup;
priv = vm->privateData;
if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
goto cleanup;
if (virCHDomainObjBeginJob(vm, CH_JOB_MODIFY) < 0)
goto cleanup;
if (virDomainObjCheckActive(vm) < 0)
goto endjob;
state = virDomainObjGetState(vm, NULL);
if (state != VIR_DOMAIN_RUNNING && state != VIR_DOMAIN_PAUSED) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("only can shutdown running/paused domain"));
goto endjob;
} else {
if (virCHMonitorShutdownVM(priv->monitor) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to shutdown guest VM"));
goto endjob;
}
}
virDomainObjSetState(vm, VIR_DOMAIN_SHUTDOWN, VIR_DOMAIN_SHUTDOWN_USER);
ret = 0;
endjob:
virCHDomainObjEndJob(vm);
cleanup:
virDomainObjEndAPI(&vm);
return ret;
}
static int
chDomainShutdown(virDomainPtr dom)
{
return chDomainShutdownFlags(dom, 0);
}
static int
chDomainReboot(virDomainPtr dom, unsigned int flags)
{
virCHDomainObjPrivate *priv;
virDomainObj *vm;
virDomainState state;
int ret = -1;
virCheckFlags(VIR_DOMAIN_REBOOT_ACPI_POWER_BTN, -1);
if (!(vm = chDomObjFromDomain(dom)))
goto cleanup;
priv = vm->privateData;
if (virDomainRebootEnsureACL(dom->conn, vm->def, flags) < 0)
goto cleanup;
if (virCHDomainObjBeginJob(vm, CH_JOB_MODIFY) < 0)
goto cleanup;
if (virDomainObjCheckActive(vm) < 0)
goto endjob;
state = virDomainObjGetState(vm, NULL);
if (state != VIR_DOMAIN_RUNNING && state != VIR_DOMAIN_PAUSED) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
_("only can reboot running/paused domain"));
goto endjob;
} else {
if (virCHMonitorRebootVM(priv->monitor) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to reboot domain"));
goto endjob;
}
}
if (state == VIR_DOMAIN_RUNNING)
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED);
else
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNPAUSED);
ret = 0;
endjob:
virCHDomainObjEndJob(vm);
cleanup:
virDomainObjEndAPI(&vm);
return ret;
}
static int
chDomainSuspend(virDomainPtr dom)
{
virCHDomainObjPrivate *priv;
virDomainObj *vm;
int ret = -1;
if (!(vm = chDomObjFromDomain(dom)))
goto cleanup;
priv = vm->privateData;
if (virDomainSuspendEnsureACL(dom->conn, vm->def) < 0)
goto cleanup;
if (virCHDomainObjBeginJob(vm, CH_JOB_MODIFY) < 0)
goto cleanup;
if (virDomainObjCheckActive(vm) < 0)
goto endjob;
if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
_("only can suspend running domain"));
goto endjob;
} else {
if (virCHMonitorSuspendVM(priv->monitor) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to suspend domain"));
goto endjob;
}
}
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
ret = 0;
endjob:
virCHDomainObjEndJob(vm);
cleanup:
virDomainObjEndAPI(&vm);
return ret;
}
static int
chDomainResume(virDomainPtr dom)
{
virCHDomainObjPrivate *priv;
virDomainObj *vm;
int ret = -1;
if (!(vm = chDomObjFromDomain(dom)))
goto cleanup;
priv = vm->privateData;
if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0)
goto cleanup;
if (virCHDomainObjBeginJob(vm, CH_JOB_MODIFY) < 0)
goto cleanup;
if (virDomainObjCheckActive(vm) < 0)
goto endjob;
if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
_("only can resume paused domain"));
goto endjob;
} else {
if (virCHMonitorResumeVM(priv->monitor) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to resume domain"));
goto endjob;
}
}
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNPAUSED);
ret = 0;
endjob:
virCHDomainObjEndJob(vm);
cleanup:
virDomainObjEndAPI(&vm);
return ret;
}
/**
* chDomainDestroyFlags:
* @dom: pointer to domain to destroy
* @flags: extra flags; not used yet.
*
* Sends SIGKILL to Cloud-Hypervisor process to terminate it
*
* Returns 0 on success or -1 in case of error
*/
static int
chDomainDestroyFlags(virDomainPtr dom, unsigned int flags)
{
virCHDriver *driver = dom->conn->privateData;
virDomainObj *vm;
int ret = -1;
virCheckFlags(0, -1);
if (!(vm = chDomObjFromDomain(dom)))
goto cleanup;
if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
goto cleanup;
if (virCHDomainObjBeginJob(vm, CH_JOB_DESTROY) < 0)
goto cleanup;
if (virDomainObjCheckActive(vm) < 0)
goto endjob;
ret = virCHProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED);
endjob:
virCHDomainObjEndJob(vm);
if (!vm->persistent)
virDomainObjListRemove(driver->domains, vm);
cleanup:
virDomainObjEndAPI(&vm);
return ret;
}
static int
chDomainDestroy(virDomainPtr dom)
{
return chDomainDestroyFlags(dom, 0);
}
static virDomainPtr chDomainLookupByID(virConnectPtr conn,
int id)
{
virCHDriver *driver = conn->privateData;
virDomainObj *vm;
virDomainPtr dom = NULL;
chDriverLock(driver);
vm = virDomainObjListFindByID(driver->domains, id);
chDriverUnlock(driver);
if (!vm) {
virReportError(VIR_ERR_NO_DOMAIN,
_("no domain with matching id '%d'"), id);
goto cleanup;
}
if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0)
goto cleanup;
dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
cleanup:
virDomainObjEndAPI(&vm);
return dom;
}
static virDomainPtr chDomainLookupByName(virConnectPtr conn,
const char *name)
{
virCHDriver *driver = conn->privateData;
virDomainObj *vm;
virDomainPtr dom = NULL;
chDriverLock(driver);
vm = virDomainObjListFindByName(driver->domains, name);
chDriverUnlock(driver);
if (!vm) {
virReportError(VIR_ERR_NO_DOMAIN,
_("no domain with matching name '%s'"), name);
goto cleanup;
}
if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0)
goto cleanup;
dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
cleanup:
virDomainObjEndAPI(&vm);
return dom;
}
static virDomainPtr chDomainLookupByUUID(virConnectPtr conn,
const unsigned char *uuid)
{
virCHDriver *driver = conn->privateData;
virDomainObj *vm;
virDomainPtr dom = NULL;
chDriverLock(driver);
vm = virDomainObjListFindByUUID(driver->domains, uuid);
chDriverUnlock(driver);
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(uuid, uuidstr);
virReportError(VIR_ERR_NO_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0)
goto cleanup;
dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
cleanup:
virDomainObjEndAPI(&vm);
return dom;
}
static int
chDomainGetState(virDomainPtr dom,
int *state,
int *reason,
unsigned int flags)
{
virDomainObj *vm;
int ret = -1;
virCheckFlags(0, -1);
if (!(vm = chDomObjFromDomain(dom)))
goto cleanup;
if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0)
goto cleanup;
*state = virDomainObjGetState(vm, reason);
ret = 0;
cleanup:
virDomainObjEndAPI(&vm);
return ret;
}
static char *chDomainGetXMLDesc(virDomainPtr dom,
unsigned int flags)
{
virCHDriver *driver = dom->conn->privateData;
virDomainObj *vm;
char *ret = NULL;
virCheckFlags(VIR_DOMAIN_XML_COMMON_FLAGS, NULL);
if (!(vm = chDomObjFromDomain(dom)))
goto cleanup;
if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
goto cleanup;
ret = virDomainDefFormat(vm->def, driver->xmlopt,
virDomainDefFormatConvertXMLFlags(flags));
cleanup:
virDomainObjEndAPI(&vm);
return ret;
}
static int chDomainGetInfo(virDomainPtr dom,
virDomainInfoPtr info)
{
virDomainObj *vm;
int ret = -1;
if (!(vm = chDomObjFromDomain(dom)))
goto cleanup;
if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0)
goto cleanup;
info->state = virDomainObjGetState(vm, NULL);
info->cpuTime = 0;
info->maxMem = virDomainDefGetMemoryTotal(vm->def);
info->memory = vm->def->mem.cur_balloon;
info->nrVirtCpu = virDomainDefGetVcpus(vm->def);
ret = 0;
cleanup:
virDomainObjEndAPI(&vm);
return ret;
}
static int
chDomainOpenConsole(virDomainPtr dom,
const char *dev_name,
virStreamPtr st,
unsigned int flags)
{
virDomainObj *vm = NULL;
int ret = -1;
size_t i;
virDomainChrDef *chr = NULL;
virCHDomainObjPrivate *priv;
virCheckFlags(VIR_DOMAIN_CONSOLE_SAFE | VIR_DOMAIN_CONSOLE_FORCE, -1);
if (!(vm = chDomObjFromDomain(dom)))
goto cleanup;
if (virDomainOpenConsoleEnsureACL(dom->conn, vm->def) < 0)
goto cleanup;
if (virDomainObjCheckActive(vm) < 0)
goto cleanup;
priv = vm->privateData;
if (dev_name) {
for (i = 0; !chr && i < vm->def->nconsoles; i++) {
if (vm->def->consoles[i]->info.alias &&
STREQ(dev_name, vm->def->consoles[i]->info.alias))
chr = vm->def->consoles[i];
}
for (i = 0; !chr && i < vm->def->nserials; i++) {
if (STREQ(dev_name, vm->def->serials[i]->info.alias))
chr = vm->def->serials[i];
}
} else {
if (vm->def->nconsoles &&
vm->def->consoles[0]->source->type == VIR_DOMAIN_CHR_TYPE_PTY)
chr = vm->def->consoles[0];
else if (vm->def->nserials &&
vm->def->serials[0]->source->type == VIR_DOMAIN_CHR_TYPE_PTY)
chr = vm->def->serials[0];
}
if (!chr) {
virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot find character device %s"),
NULLSTR(dev_name));
goto cleanup;
}
if (chr->source->type != VIR_DOMAIN_CHR_TYPE_PTY) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("character device %s is not using a PTY"),
dev_name ? dev_name : NULLSTR(chr->info.alias));
goto cleanup;
}
/* handle mutually exclusive access to console devices */
ret = virChrdevOpen(priv->chrdevs, chr->source, st,
(flags & VIR_DOMAIN_CONSOLE_FORCE) != 0);
if (ret == 1) {
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
_("Active console session exists for this domain"));
ret = -1;
}
cleanup:
virDomainObjEndAPI(&vm);
return ret;
}
static int chStateCleanup(void)
{
if (ch_driver == NULL)
return -1;
virObjectUnref(ch_driver->domains);
virObjectUnref(ch_driver->xmlopt);
virObjectUnref(ch_driver->caps);
virObjectUnref(ch_driver->config);
virMutexDestroy(&ch_driver->lock);
g_free(ch_driver);
ch_driver = NULL;
return 0;
}
static int chStateInitialize(bool privileged,
const char *root,
virStateInhibitCallback callback G_GNUC_UNUSED,
void *opaque G_GNUC_UNUSED)
{
int ret = VIR_DRV_STATE_INIT_ERROR;
int rv;
if (root != NULL) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
_("Driver does not support embedded mode"));
return -1;
}
ch_driver = g_new0(virCHDriver, 1);
if (virMutexInit(&ch_driver->lock) < 0) {
g_free(ch_driver);
return VIR_DRV_STATE_INIT_ERROR;
}
if (!(ch_driver->domains = virDomainObjListNew()))
goto cleanup;
if (!(ch_driver->caps = virCHDriverCapsInit()))
goto cleanup;
if (!(ch_driver->xmlopt = chDomainXMLConfInit(ch_driver)))
goto cleanup;
if (!(ch_driver->config = virCHDriverConfigNew(privileged)))
goto cleanup;
if ((rv = chExtractVersion(ch_driver)) < 0) {
if (rv == -2)
ret = VIR_DRV_STATE_INIT_SKIPPED;
goto cleanup;
}
ret = VIR_DRV_STATE_INIT_COMPLETE;
cleanup:
if (ret != VIR_DRV_STATE_INIT_COMPLETE)
chStateCleanup();
return ret;
}
/* Function Tables */
static virHypervisorDriver chHypervisorDriver = {
.name = "CH",
.connectURIProbe = chConnectURIProbe,
.connectOpen = chConnectOpen, /* 7.5.0 */
.connectClose = chConnectClose, /* 7.5.0 */
.connectGetType = chConnectGetType, /* 7.5.0 */
.connectGetVersion = chConnectGetVersion, /* 7.5.0 */
.connectGetHostname = chConnectGetHostname, /* 7.5.0 */
.connectNumOfDomains = chConnectNumOfDomains, /* 7.5.0 */
.connectListAllDomains = chConnectListAllDomains, /* 7.5.0 */
.connectListDomains = chConnectListDomains, /* 7.5.0 */
.connectGetCapabilities = chConnectGetCapabilities, /* 7.5.0 */
.domainCreateXML = chDomainCreateXML, /* 7.5.0 */
.domainCreate = chDomainCreate, /* 7.5.0 */
.domainCreateWithFlags = chDomainCreateWithFlags, /* 7.5.0 */
.domainShutdown = chDomainShutdown, /* 7.5.0 */
.domainShutdownFlags = chDomainShutdownFlags, /* 7.5.0 */
.domainReboot = chDomainReboot, /* 7.5.0 */
.domainSuspend = chDomainSuspend, /* 7.5.0 */
.domainResume = chDomainResume, /* 7.5.0 */
.domainDestroy = chDomainDestroy, /* 7.5.0 */
.domainDestroyFlags = chDomainDestroyFlags, /* 7.5.0 */
.domainDefineXML = chDomainDefineXML, /* 7.5.0 */
.domainDefineXMLFlags = chDomainDefineXMLFlags, /* 7.5.0 */
.domainUndefine = chDomainUndefine, /* 7.5.0 */
.domainUndefineFlags = chDomainUndefineFlags, /* 7.5.0 */
.domainLookupByID = chDomainLookupByID, /* 7.5.0 */
.domainLookupByUUID = chDomainLookupByUUID, /* 7.5.0 */
.domainLookupByName = chDomainLookupByName, /* 7.5.0 */
.domainGetState = chDomainGetState, /* 7.5.0 */
.domainGetXMLDesc = chDomainGetXMLDesc, /* 7.5.0 */
.domainGetInfo = chDomainGetInfo, /* 7.5.0 */
.domainIsActive = chDomainIsActive, /* 7.5.0 */
.domainOpenConsole = chDomainOpenConsole, /* 7.8.0 */
.nodeGetInfo = chNodeGetInfo, /* 7.5.0 */
};
static virConnectDriver chConnectDriver = {
.localOnly = true,
.uriSchemes = (const char *[]){"ch", NULL},
.hypervisorDriver = &chHypervisorDriver,
};
static virStateDriver chStateDriver = {
.name = "cloud-hypervisor",
.stateInitialize = chStateInitialize,
.stateCleanup = chStateCleanup,
};
int chRegister(void)
{
if (virRegisterConnectDriver(&chConnectDriver, true) < 0)
return -1;
if (virRegisterStateDriver(&chStateDriver) < 0)
return -1;
return 0;
}