Convert Xen domain create/define/getxml/migration APIs to use virDomainDefPtr

Introduce use of a virDomainDefPtr in the domain create, migrate,
getxml, & define APIs to simplify introduction of ACL security
checks. The virDomainPtr cannot be safely used, since the app
may have supplied mis-matching name/uuid/id fields. eg
the name points to domain X, while the uuid points to
domain Y. Resolving the virDomainPtr to a virDomainDefPtr
ensures a consistent name/uuid/id set.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2013-05-01 14:15:10 +01:00
parent 0a6fc8ab09
commit 18b14012e4
5 changed files with 200 additions and 154 deletions

View File

@ -647,11 +647,30 @@ xenUnifiedConnectNumOfDomains(virConnectPtr conn)
static virDomainPtr
xenUnifiedDomainCreateXML(virConnectPtr conn,
const char *xmlDesc, unsigned int flags)
const char *xml,
unsigned int flags)
{
xenUnifiedPrivatePtr priv = conn->privateData;
virDomainDefPtr def = NULL;
virDomainPtr ret = NULL;
virCheckFlags(0, NULL);
return xenDaemonCreateXML(conn, xmlDesc);
if (!(def = virDomainDefParseString(xml, priv->caps, priv->xmlopt,
1 << VIR_DOMAIN_VIRT_XEN,
VIR_DOMAIN_XML_INACTIVE)))
goto cleanup;
if (xenDaemonCreateXML(conn, def) < 0)
goto cleanup;
ret = virGetDomain(conn, def->name, def->uuid);
if (ret)
ret->id = def->id;
cleanup:
virDomainDefFree(def);
return ret;
}
static virDomainPtr
@ -1292,18 +1311,31 @@ static char *
xenUnifiedDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr minidef = NULL;
virDomainDefPtr def = NULL;
char *ret = NULL;
if (!(minidef = xenGetDomainDefForDom(dom)))
goto cleanup;
if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
return xenXMDomainGetXMLDesc(dom, flags);
def = xenXMDomainGetXMLDesc(dom->conn, minidef);
} else {
char *cpus, *res;
char *cpus;
xenUnifiedLock(priv);
cpus = xenDomainUsedCpus(dom);
xenUnifiedUnlock(priv);
res = xenDaemonDomainGetXMLDesc(dom, flags, cpus);
def = xenDaemonDomainGetXMLDesc(dom->conn, minidef, cpus);
VIR_FREE(cpus);
return res;
}
if (def)
ret = virDomainDefFormat(def, flags);
cleanup:
virDomainDefFree(def);
virDomainDefFree(minidef);
return ret;
}
@ -1436,10 +1468,21 @@ xenUnifiedDomainMigratePerform(virDomainPtr dom,
const char *dname,
unsigned long resource)
{
virDomainDefPtr def = NULL;
int ret = -1;
virCheckFlags(XEN_MIGRATION_FLAGS, -1);
return xenDaemonDomainMigratePerform(dom, cookie, cookielen, uri,
flags, dname, resource);
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
ret = xenDaemonDomainMigratePerform(dom->conn, def,
cookie, cookielen, uri,
flags, dname, resource);
cleanup:
virDomainDefFree(def);
return ret;
}
static virDomainPtr
@ -1450,45 +1493,37 @@ xenUnifiedDomainMigrateFinish(virConnectPtr dconn,
const char *uri ATTRIBUTE_UNUSED,
unsigned long flags)
{
virDomainPtr dom = NULL;
char *domain_xml = NULL;
virDomainPtr dom_new = NULL;
xenUnifiedPrivatePtr priv = dconn->privateData;
virDomainPtr ret = NULL;
virDomainDefPtr minidef = NULL;
virDomainDefPtr def = NULL;
virCheckFlags(XEN_MIGRATION_FLAGS, NULL);
if (!(dom = xenUnifiedDomainLookupByName(dconn, dname)))
return NULL;
if (!(minidef = xenGetDomainDefForName(dconn, dname)))
goto cleanup;
if (flags & VIR_MIGRATE_PERSIST_DEST) {
domain_xml = xenDaemonDomainGetXMLDesc(dom, 0, NULL);
if (! domain_xml) {
virReportError(VIR_ERR_MIGRATE_PERSIST_FAILED,
"%s", _("failed to get XML representation of migrated domain"));
goto error;
}
if (!(def = xenDaemonDomainGetXMLDesc(dconn, minidef, NULL)))
goto cleanup;
dom_new = xenDaemonDomainDefineXML(dconn, domain_xml);
if (! dom_new) {
virReportError(VIR_ERR_MIGRATE_PERSIST_FAILED,
"%s", _("failed to define domain on destination host"));
goto error;
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
if (xenXMDomainDefineXML(dconn, def) < 0)
goto cleanup;
} else {
if (xenDaemonDomainDefineXML(dconn, def) < 0)
goto cleanup;
}
/* Free additional reference added by Define */
virDomainFree(dom_new);
}
VIR_FREE(domain_xml);
ret = virGetDomain(dconn, minidef->name, minidef->uuid);
if (ret)
ret->id = minidef->id;
return dom;
error:
virDomainFree(dom);
VIR_FREE(domain_xml);
return NULL;
cleanup:
virDomainDefFree(def);
virDomainDefFree(minidef);
return ret;
}
static int
@ -1563,23 +1598,52 @@ static virDomainPtr
xenUnifiedDomainDefineXML(virConnectPtr conn, const char *xml)
{
xenUnifiedPrivatePtr priv = conn->privateData;
virDomainDefPtr def = NULL;
virDomainPtr ret = NULL;
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
return xenXMDomainDefineXML(conn, xml);
else
return xenDaemonDomainDefineXML(conn, xml);
if (!(def = virDomainDefParseString(xml, priv->caps, priv->xmlopt,
1 << VIR_DOMAIN_VIRT_XEN,
VIR_DOMAIN_XML_INACTIVE)))
goto cleanup;
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
if (xenXMDomainDefineXML(conn, def) < 0)
goto cleanup;
def = NULL; /* XM driver owns it now */
} else {
if (xenDaemonDomainDefineXML(conn, def) < 0)
goto cleanup;
}
ret = virGetDomain(conn, def->name, def->uuid);
if (ret)
ret->id = -1;
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainUndefineFlags(virDomainPtr dom, unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr def = NULL;
int ret = -1;
virCheckFlags(0, -1);
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
return xenXMDomainUndefine(dom);
ret = xenXMDomainUndefine(dom->conn, def);
else
return xenDaemonDomainUndefine(dom);
ret = xenDaemonDomainUndefine(dom->conn, def);
cleanup:
virDomainDefFree(def);
return ret;
}
static int

View File

@ -1614,35 +1614,21 @@ cleanup:
/**
* xenDaemonDomainGetXMLDesc:
* @domain: a domain object
* @flags: potential dump flags
* @cpus: list of cpu the domain is pinned to.
*
* Provide an XML description of the domain.
* Get the XML description of the domain as a structure.
*
* Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error.
* the caller must free() the returned value.
* Returns a virDomainDefPtr instance, or NULL in case of error.
*/
char *
xenDaemonDomainGetXMLDesc(virDomainPtr domain,
unsigned int flags,
virDomainDefPtr
xenDaemonDomainGetXMLDesc(virConnectPtr conn,
virDomainDefPtr minidef,
const char *cpus)
{
virDomainDefPtr def;
char *xml;
/* Flags checked by virDomainDefFormat */
if (!(def = xenDaemonDomainFetch(domain->conn,
domain->id,
domain->name,
cpus)))
return NULL;
xml = virDomainDefFormat(def, flags);
virDomainDefFree(def);
return xml;
return xenDaemonDomainFetch(conn,
minidef->id,
minidef->name,
cpus);
}
@ -2142,7 +2128,7 @@ xenDaemonLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
/**
* xenDaemonCreateXML:
* @conn: pointer to the hypervisor connection
* @xmlDesc: an XML description of the domain
* @def: domain configuration
* @flags: an optional set of virDomainFlags
*
* Launch a new Linux guest domain, based on an XML description similar
@ -2151,25 +2137,25 @@ xenDaemonLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
*
* Returns a new domain object or NULL in case of failure
*/
virDomainPtr
xenDaemonCreateXML(virConnectPtr conn, const char *xmlDesc)
int
xenDaemonCreateXML(virConnectPtr conn, virDomainDefPtr def)
{
int ret;
char *sexpr;
virDomainPtr dom = NULL;
const char *tmp;
struct sexpr *root;
xenUnifiedPrivatePtr priv = conn->privateData;
virDomainDefPtr def;
if (!(def = virDomainDefParseString(xmlDesc, priv->caps, priv->xmlopt,
1 << VIR_DOMAIN_VIRT_XEN,
VIR_DOMAIN_XML_INACTIVE)))
return NULL;
if (!(sexpr = xenFormatSxpr(conn, def, priv->xendConfigVersion))) {
virDomainDefFree(def);
return NULL;
if (def->id != -1) {
virReportError(VIR_ERR_OPERATION_INVALID,
_("Domain %s is already running"),
def->name);
return -1;
}
if (!(sexpr = xenFormatSxpr(conn, def, priv->xendConfigVersion)))
return -1;
ret = xenDaemonDomainCreateXML(conn, sexpr);
VIR_FREE(sexpr);
if (ret != 0) {
@ -2178,9 +2164,20 @@ xenDaemonCreateXML(virConnectPtr conn, const char *xmlDesc)
/* This comes before wait_for_devices, to ensure that latter
cleanup will destroy the domain upon failure */
if (!(dom = virDomainLookupByName(conn, def->name)))
root = sexpr_get(conn, "/xend/domain/%s?detail=1", def->name);
if (root == NULL)
goto error;
tmp = sexpr_node(root, "domain/domid");
if (!tmp) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Domain %s did not start"),
def->name);
goto error;
}
if (tmp)
def->id = sexpr_int(root, "domain/domid");
if (xend_wait_for_devices(conn, def->name) < 0)
goto error;
@ -2188,16 +2185,13 @@ xenDaemonCreateXML(virConnectPtr conn, const char *xmlDesc)
goto error;
virDomainDefFree(def);
return dom;
return 0;
error:
/* Make sure we don't leave a still-born domain around */
if (dom != NULL) {
if (def->id != -1)
xenDaemonDomainDestroy(conn, def);
virObjectUnref(dom);
}
virDomainDefFree(def);
return NULL;
return -1;
}
/**
@ -2667,7 +2661,8 @@ xenDaemonDomainMigratePrepare(virConnectPtr dconn ATTRIBUTE_UNUSED,
}
int
xenDaemonDomainMigratePerform(virDomainPtr domain,
xenDaemonDomainMigratePerform(virConnectPtr conn,
virDomainDefPtr def,
const char *cookie ATTRIBUTE_UNUSED,
int cookielen ATTRIBUTE_UNUSED,
const char *uri,
@ -2811,7 +2806,7 @@ xenDaemonDomainMigratePerform(virDomainPtr domain,
* to our advantage since all parameters supported and required
* by current xend can be included without breaking older xend.
*/
ret = xend_op(domain->conn, domain->name,
ret = xend_op(conn, def->name,
"op", "migrate",
"destination", hostname,
"live", live,
@ -2824,34 +2819,24 @@ xenDaemonDomainMigratePerform(virDomainPtr domain,
VIR_FREE(hostname);
if (ret == 0 && undefined_source)
xenDaemonDomainUndefine(domain);
xenDaemonDomainUndefine(conn, def);
VIR_DEBUG("migration done");
return ret;
}
virDomainPtr
xenDaemonDomainDefineXML(virConnectPtr conn, const char *xmlDesc)
int
xenDaemonDomainDefineXML(virConnectPtr conn, virDomainDefPtr def)
{
int ret;
int ret = -1;
char *sexpr;
virDomainPtr dom;
xenUnifiedPrivatePtr priv = conn->privateData;
virDomainDefPtr def;
if (!(def = virDomainDefParseString(xmlDesc, priv->caps, priv->xmlopt,
1 << VIR_DOMAIN_VIRT_XEN,
VIR_DOMAIN_XML_INACTIVE))) {
virReportError(VIR_ERR_XML_ERROR,
"%s", _("failed to parse domain description"));
return NULL;
}
if (!(sexpr = xenFormatSxpr(conn, def, priv->xendConfigVersion))) {
virReportError(VIR_ERR_XML_ERROR,
"%s", _("failed to build sexpr"));
goto error;
goto cleanup;
}
ret = xend_op(conn, "", "op", "new", "config", sexpr, NULL);
@ -2859,20 +2844,15 @@ xenDaemonDomainDefineXML(virConnectPtr conn, const char *xmlDesc)
if (ret != 0) {
virReportError(VIR_ERR_XEN_CALL,
_("Failed to create inactive domain %s"), def->name);
goto error;
goto cleanup;
}
dom = virDomainLookupByName(conn, def->name);
if (dom == NULL) {
goto error;
}
virDomainDefFree(def);
return dom;
ret = 0;
error:
virDomainDefFree(def);
return NULL;
cleanup:
return ret;
}
int
xenDaemonDomainCreate(virConnectPtr conn,
virDomainDefPtr def)
@ -2892,9 +2872,9 @@ xenDaemonDomainCreate(virConnectPtr conn,
}
int
xenDaemonDomainUndefine(virDomainPtr domain)
xenDaemonDomainUndefine(virConnectPtr conn, virDomainDefPtr def)
{
return xend_op(domain->conn, domain->name, "op", "delete", NULL);
return xend_op(conn, def->name, "op", "delete", NULL);
}
/**

View File

@ -118,8 +118,9 @@ int xenDaemonDomainGetState(virConnectPtr conn,
virDomainDefPtr def,
int *state,
int *reason);
char *xenDaemonDomainGetXMLDesc(virDomainPtr domain, unsigned int flags,
const char *cpus);
virDomainDefPtr xenDaemonDomainGetXMLDesc(virConnectPtr conn,
virDomainDefPtr def,
const char *cpus);
unsigned long long xenDaemonDomainGetMaxMemory(virConnectPtr conn,
virDomainDefPtr def);
char **xenDaemonListDomainsOld(virConnectPtr xend);
@ -139,10 +140,12 @@ int xenDaemonDetachDeviceFlags(virDomainPtr domain,
const char *xml,
unsigned int flags);
virDomainPtr xenDaemonDomainDefineXML(virConnectPtr xend, const char *sexpr);
int xenDaemonDomainDefineXML(virConnectPtr conn,
virDomainDefPtr def);
int xenDaemonDomainCreate(virConnectPtr conn,
virDomainDefPtr def);
int xenDaemonDomainUndefine(virDomainPtr domain);
int xenDaemonDomainUndefine(virConnectPtr conn,
virDomainDefPtr def);
int xenDaemonDomainSetVcpus (virDomainPtr domain,
unsigned int vcpus);
@ -167,11 +170,18 @@ int xenDaemonDomainGetAutostart (virDomainPtr dom,
int xenDaemonDomainSetAutostart (virDomainPtr domain,
int autostart);
virDomainPtr xenDaemonCreateXML(virConnectPtr conn, const char *xmlDesc);
int xenDaemonCreateXML(virConnectPtr conn, virDomainDefPtr def);
virDomainDefPtr xenDaemonLookupByUUID(virConnectPtr conn, const unsigned char *uuid);
virDomainDefPtr xenDaemonLookupByName(virConnectPtr conn, const char *domname);
int xenDaemonDomainMigratePrepare (virConnectPtr dconn, char **cookie, int *cookielen, const char *uri_in, char **uri_out, unsigned long flags, const char *dname, unsigned long resource);
int xenDaemonDomainMigratePerform (virDomainPtr domain, const char *cookie, int cookielen, const char *uri, unsigned long flags, const char *dname, unsigned long resource);
int xenDaemonDomainMigratePrepare (virConnectPtr dconn,
char **cookie, int *cookielen,
const char *uri_in, char **uri_out,
unsigned long flags, const char *dname, unsigned long resource);
int xenDaemonDomainMigratePerform (virConnectPtr conn,
virDomainDefPtr def,
const char *cookie, int cookielen,
const char *uri, unsigned long flags,
const char *dname, unsigned long resource);
int xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path, unsigned long long offset, size_t size, void *buffer);

View File

@ -501,28 +501,29 @@ error:
* Turn a config record into a lump of XML describing the
* domain, suitable for later feeding for virDomainCreateXML
*/
char *
xenXMDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
virDomainDefPtr
xenXMDomainGetXMLDesc(virConnectPtr conn,
virDomainDefPtr def)
{
xenUnifiedPrivatePtr priv = domain->conn->privateData;
xenUnifiedPrivatePtr priv = conn->privateData;
const char *filename;
xenXMConfCachePtr entry;
char *ret = NULL;
virDomainDefPtr ret = NULL;
/* Flags checked by virDomainDefFormat */
if (domain->id != -1)
return NULL;
xenUnifiedLock(priv);
if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
if (!(filename = virHashLookup(priv->nameConfigMap, def->name)))
goto cleanup;
if (!(entry = virHashLookup(priv->configCache, filename)))
goto cleanup;
ret = virDomainDefFormat(entry->def, flags);
ret = virDomainDefCopy(entry->def,
priv->caps,
priv->xmlopt,
false);
cleanup:
xenUnifiedUnlock(priv);
@ -946,13 +947,11 @@ xenXMDomainCreate(virConnectPtr conn,
* Create a config file for a domain, based on an XML
* document describing its config
*/
virDomainPtr
xenXMDomainDefineXML(virConnectPtr conn, const char *xml)
int
xenXMDomainDefineXML(virConnectPtr conn, virDomainDefPtr def)
{
virDomainPtr ret;
char *filename = NULL;
const char *oldfilename;
virDomainDefPtr def = NULL;
virConfPtr conf = NULL;
xenXMConfCachePtr entry = NULL;
xenUnifiedPrivatePtr priv = conn->privateData;
@ -961,14 +960,7 @@ xenXMDomainDefineXML(virConnectPtr conn, const char *xml)
if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh(conn) < 0) {
xenUnifiedUnlock(priv);
return NULL;
}
if (!(def = virDomainDefParseString(xml, priv->caps, priv->xmlopt,
1 << VIR_DOMAIN_VIRT_XEN,
VIR_DOMAIN_XML_INACTIVE))) {
xenUnifiedUnlock(priv);
return NULL;
return -1;
}
if (!(conf = xenFormatXM(conn, def, priv->xendConfigVersion)))
@ -1062,10 +1054,9 @@ xenXMDomainDefineXML(virConnectPtr conn, const char *xml)
goto error;
}
ret = virGetDomain(conn, def->name, def->uuid);
xenUnifiedUnlock(priv);
VIR_FREE(filename);
return ret;
return 0;
error:
VIR_FREE(filename);
@ -1073,25 +1064,25 @@ xenXMDomainDefineXML(virConnectPtr conn, const char *xml)
VIR_FREE(entry->filename);
VIR_FREE(entry);
virConfFree(conf);
virDomainDefFree(def);
xenUnifiedUnlock(priv);
return NULL;
return -1;
}
/*
* Delete a domain from disk
*/
int
xenXMDomainUndefine(virDomainPtr domain)
xenXMDomainUndefine(virConnectPtr conn,
virDomainDefPtr def)
{
xenUnifiedPrivatePtr priv = domain->conn->privateData;
xenUnifiedPrivatePtr priv = conn->privateData;
const char *filename;
xenXMConfCachePtr entry;
int ret = -1;
xenUnifiedLock(priv);
if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
if (!(filename = virHashLookup(priv->nameConfigMap, def->name)))
goto cleanup;
if (!(entry = virHashLookup(priv->configCache, filename)))
@ -1101,7 +1092,7 @@ xenXMDomainUndefine(virDomainPtr domain)
goto cleanup;
/* Remove the name -> filename mapping */
if (virHashRemoveEntry(priv->nameConfigMap, domain->name) < 0)
if (virHashRemoveEntry(priv->nameConfigMap, def->name) < 0)
goto cleanup;
/* Remove the config record itself */

View File

@ -44,7 +44,8 @@ int xenXMDomainGetState(virConnectPtr conn,
virDomainDefPtr def,
int *state,
int *reason);
char *xenXMDomainGetXMLDesc(virDomainPtr domain, unsigned int flags);
virDomainDefPtr xenXMDomainGetXMLDesc(virConnectPtr conn,
virDomainDefPtr def);
int xenXMDomainSetMemory(virConnectPtr conn,
virDomainDefPtr def,
unsigned long memory);
@ -67,8 +68,8 @@ int xenXMNumOfDefinedDomains(virConnectPtr conn);
int xenXMDomainCreate(virConnectPtr conn,
virDomainDefPtr def);
virDomainPtr xenXMDomainDefineXML(virConnectPtr con, const char *xml);
int xenXMDomainUndefine(virDomainPtr domain);
int xenXMDomainDefineXML(virConnectPtr con, virDomainDefPtr def);
int xenXMDomainUndefine(virConnectPtr conn, virDomainDefPtr def);
int xenXMDomainBlockPeek (virDomainPtr dom, const char *path, unsigned long long offset, size_t size, void *buffer);