mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 11:22:23 +00:00
* include/libvirt/libvirt.h include/libvirt/libvirt.h.in
src/driver.h src/libvirt.c src/libvirt_sym.version src/proxy_internal.c src/test.c src/xen_internal.c src/xend_internal.c src/xml.c src/xml.h src/xs_internal.c: intagrated patch from Michel Ponceau to add hot-plug devices support to the API, integrated in driver API and fixed a few small things. Still a TODO in src/xml.c about moving xenstore direct accesses to a new routine. Daniel
This commit is contained in:
parent
df1e7c9967
commit
dc28f35f11
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
||||
Thu Nov 16 18:18:12 CET 2006 Daniel Veillard <veillard@redhat.com>
|
||||
|
||||
* include/libvirt/libvirt.h include/libvirt/libvirt.h.in
|
||||
src/driver.h src/libvirt.c src/libvirt_sym.version
|
||||
src/proxy_internal.c src/test.c src/xen_internal.c
|
||||
src/xend_internal.c src/xml.c src/xml.h src/xs_internal.c:
|
||||
intagrated patch from Michel Ponceau to add hot-plug devices
|
||||
support to the API, integrated in driver API and fixed
|
||||
a few small things. Still a TODO in src/xml.c about
|
||||
moving xenstore direct accesses to a new routine.
|
||||
|
||||
Wed Nov 15 18:23:13 EST 2006 Daniel Berrange <berrange@redhat.com>
|
||||
|
||||
* python/generator.py, python/libvir.c, python/libvirt-python-api.xml:
|
||||
|
@ -415,6 +415,8 @@ int virDomainGetVcpus (virDomainPtr domain,
|
||||
*/
|
||||
#define VIR_GET_CPUMAP(cpumaps,maplen,vcpu) &(cpumaps[(vcpu)*(maplen)])
|
||||
|
||||
int virDomainAttachDevice(virDomainPtr domain, char *xml);
|
||||
int virDomainDetachDevice(virDomainPtr domain, char *xml);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -415,6 +415,8 @@ int virDomainGetVcpus (virDomainPtr domain,
|
||||
*/
|
||||
#define VIR_GET_CPUMAP(cpumaps,maplen,vcpu) &(cpumaps[(vcpu)*(maplen)])
|
||||
|
||||
int virDomainAttachDevice(virDomainPtr domain, char *xml);
|
||||
int virDomainDetachDevice(virDomainPtr domain, char *xml);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -133,6 +133,12 @@ typedef int
|
||||
int maxinfo,
|
||||
unsigned char *cpumaps,
|
||||
int maplen);
|
||||
typedef int
|
||||
(*virDrvDomainAttachDevice) (virDomainPtr domain,
|
||||
char *xml);
|
||||
typedef int
|
||||
(*virDrvDomainDetachDevice) (virDomainPtr domain,
|
||||
char *xml);
|
||||
|
||||
typedef struct _virDriver virDriver;
|
||||
typedef virDriver *virDriverPtr;
|
||||
@ -184,6 +190,8 @@ struct _virDriver {
|
||||
virDrvDomainCreate domainCreate;
|
||||
virDrvDomainDefineXML domainDefineXML;
|
||||
virDrvDomainUndefine domainUndefine;
|
||||
virDrvDomainAttachDevice domainAttachDevice;
|
||||
virDrvDomainDetachDevice domainDetachDevice;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1899,3 +1899,85 @@ virDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo,
|
||||
virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* virDomainAttachDevice:
|
||||
* @domain: pointer to domain object
|
||||
* @xml: pointer to XML description of one device
|
||||
*
|
||||
* Create a virtual device attachment to backend.
|
||||
*
|
||||
* Returns 0 in case of success, -1 in case of failure.
|
||||
*/
|
||||
int
|
||||
virDomainAttachDevice(virDomainPtr domain, char *xml)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
virConnectPtr conn;
|
||||
|
||||
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
|
||||
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
if (domain->conn->flags & VIR_CONNECT_RO) {
|
||||
virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
conn = domain->conn;
|
||||
|
||||
/*
|
||||
* Go though the driver registered entry points
|
||||
*/
|
||||
for (i = 0;i < conn->nb_drivers;i++) {
|
||||
if ((conn->drivers[i] != NULL) &&
|
||||
(conn->drivers[i]->domainAttachDevice != NULL)) {
|
||||
ret = conn->drivers[i]->domainAttachDevice(domain, xml);
|
||||
if (ret >= 0)
|
||||
return(ret);
|
||||
}
|
||||
}
|
||||
virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* virDomainDetachDevice:
|
||||
* @domain: pointer to domain object
|
||||
* @xml: pointer to XML description of one device
|
||||
*
|
||||
* Destroy a virtual device attachment to backend.
|
||||
*
|
||||
* Returns 0 in case of success, -1 in case of failure.
|
||||
*/
|
||||
int
|
||||
virDomainDetachDevice(virDomainPtr domain, char *xml)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
virConnectPtr conn;
|
||||
|
||||
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
|
||||
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
if (domain->conn->flags & VIR_CONNECT_RO) {
|
||||
virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
conn = domain->conn;
|
||||
|
||||
/*
|
||||
* Go though the driver registered entry points
|
||||
*/
|
||||
for (i = 0;i < conn->nb_drivers;i++) {
|
||||
if ((conn->drivers[i] != NULL) &&
|
||||
(conn->drivers[i]->domainDetachDevice != NULL)) {
|
||||
ret = conn->drivers[i]->domainDetachDevice(domain, xml);
|
||||
if (ret >= 0)
|
||||
return(ret);
|
||||
}
|
||||
}
|
||||
virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
|
@ -53,5 +53,8 @@
|
||||
virDomainSetVcpus;
|
||||
virDomainPinVcpu;
|
||||
virDomainGetVcpus;
|
||||
|
||||
virDomainAttachDevice;
|
||||
virDomainDetachDevice;
|
||||
local: *;
|
||||
};
|
||||
|
@ -83,6 +83,8 @@ static virDriver xenProxyDriver = {
|
||||
NULL, /* domainCreate */
|
||||
NULL, /* domainDefineXML */
|
||||
NULL, /* domainUndefine */
|
||||
NULL, /* domainAttachDevice */
|
||||
NULL, /* domainDetachDevice */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -63,6 +63,8 @@ static virDriver testDriver = {
|
||||
NULL, /* domainCreate */
|
||||
NULL, /* domainDefineXML */
|
||||
NULL, /* domainUndefine */
|
||||
NULL, /* domainAttachDevice */
|
||||
NULL, /* domainDetachDevice */
|
||||
};
|
||||
|
||||
/* Amount of time it takes to shutdown */
|
||||
|
@ -458,6 +458,8 @@ static virDriver xenHypervisorDriver = {
|
||||
NULL, /* domainCreate */
|
||||
NULL, /* domainDefineXML */
|
||||
NULL, /* domainUndefine */
|
||||
NULL, /* domainAttachDevice */
|
||||
NULL, /* domainDetachDevice */
|
||||
};
|
||||
#endif /* !PROXY */
|
||||
|
||||
|
@ -47,6 +47,8 @@ static virDomainPtr xenDaemonLookupByUUID(virConnectPtr conn,
|
||||
static virDomainPtr xenDaemonCreateLinux(virConnectPtr conn,
|
||||
const char *xmlDesc,
|
||||
unsigned int flags);
|
||||
static int xenDaemonAttachDevice(virDomainPtr domain, char *xml);
|
||||
static int xenDaemonDetachDevice(virDomainPtr domain, char *xml);
|
||||
#endif /* PROXY */
|
||||
|
||||
#ifndef PROXY
|
||||
@ -93,6 +95,8 @@ static virDriver xenDaemonDriver = {
|
||||
NULL, /* domainCreate */
|
||||
NULL, /* domainDefineXML */
|
||||
NULL, /* domainUndefine */
|
||||
xenDaemonAttachDevice, /* domainAttachDevice */
|
||||
xenDaemonDetachDevice /* domainDetachDevice */
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2957,6 +2961,73 @@ xenDaemonCreateLinux(virConnectPtr conn, const char *xmlDesc,
|
||||
free(name);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* xenDaemonAttachDevice:
|
||||
* @domain: pointer to domain object
|
||||
* @xml: pointer to XML description of device
|
||||
*
|
||||
* Create a virtual device attachment to backend.
|
||||
* XML description is translated into S-expression.
|
||||
*
|
||||
* Returns 0 in case of success, -1 in case of failure.
|
||||
*/
|
||||
static int
|
||||
xenDaemonAttachDevice(virDomainPtr domain, char *xml)
|
||||
{
|
||||
char *sexpr, *conf;
|
||||
int xendConfigVersion, hvm = 0, ret;
|
||||
|
||||
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
|
||||
virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
|
||||
__FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
if ((xendConfigVersion = xend_get_config_version(domain->conn)) < 0) {
|
||||
virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
|
||||
"cannot determine xend config version");
|
||||
return (-1);
|
||||
}
|
||||
if (strcmp(virDomainGetOSType(domain), "linux"))
|
||||
hvm = 1;
|
||||
sexpr = virParseXMLDevice(xml, hvm, xendConfigVersion);
|
||||
if (sexpr == NULL)
|
||||
return (-1);
|
||||
if (!memcmp(sexpr, "(device ", 8)) {
|
||||
conf = sexpr + 8;
|
||||
*(conf + strlen(conf) -1) = 0; /* suppress final ) */
|
||||
}
|
||||
else conf = sexpr;
|
||||
ret = xend_op(domain->conn, domain->name, "op", "device_create",
|
||||
"config", conf, NULL);
|
||||
free(sexpr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* xenDaemonDetachDevice:
|
||||
* @domain: pointer to domain object
|
||||
* @xml: pointer to XML description of device
|
||||
*
|
||||
* Destroy a virtual device attachment to backend.
|
||||
*
|
||||
* Returns 0 in case of success, -1 in case of failure.
|
||||
*/
|
||||
static int
|
||||
xenDaemonDetachDevice(virDomainPtr domain, char *xml)
|
||||
{
|
||||
char class[8], ref[80];
|
||||
|
||||
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
|
||||
virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
|
||||
__FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
if (virDomainXMLDevID(domain, xml, class, ref))
|
||||
return (-1);
|
||||
return(xend_op(domain->conn, domain->name, "op", "device_destroy",
|
||||
"type", class, "dev", ref, NULL));
|
||||
}
|
||||
#endif /* ! PROXY */
|
||||
|
||||
/*
|
||||
|
147
src/xml.c
147
src/xml.c
@ -1488,6 +1488,153 @@ error:
|
||||
return(dst_uuid);
|
||||
}
|
||||
|
||||
#ifndef PROXY
|
||||
/**
|
||||
* virParseXMLDevice:
|
||||
* @xmldesc: string with the XML description
|
||||
* @hvm: 1 for fully virtualized guest, 0 for paravirtualized
|
||||
* @xendConfigVersion: xend configuration file format
|
||||
*
|
||||
* Parse the XML description and turn it into the xend sexp needed to
|
||||
* create the device. This is a temporary interface as the S-Expr interface
|
||||
* will be replaced by XML-RPC in the future. However the XML format should
|
||||
* stay valid over time.
|
||||
*
|
||||
* Returns the 0-terminated S-Expr string, or NULL in case of error.
|
||||
* the caller must free() the returned value.
|
||||
*/
|
||||
char *
|
||||
virParseXMLDevice(char *xmldesc, int hvm, int xendConfigVersion)
|
||||
{
|
||||
xmlDocPtr xml = NULL;
|
||||
xmlNodePtr node;
|
||||
virBuffer buf;
|
||||
|
||||
buf.content = malloc(1000);
|
||||
if (buf.content == NULL)
|
||||
return (NULL);
|
||||
buf.size = 1000;
|
||||
buf.use = 0;
|
||||
xml = xmlReadDoc((const xmlChar *) xmldesc, "domain.xml", NULL,
|
||||
XML_PARSE_NOENT | XML_PARSE_NONET |
|
||||
XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
|
||||
if (xml == NULL)
|
||||
goto error;
|
||||
node = xmlDocGetRootElement(xml);
|
||||
if (node == NULL)
|
||||
goto error;
|
||||
if (xmlStrEqual(node->name, BAD_CAST "disk")) {
|
||||
if (virDomainParseXMLDiskDesc(node, &buf, hvm, xendConfigVersion) != 0)
|
||||
goto error;
|
||||
}
|
||||
else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
|
||||
if (virDomainParseXMLIfDesc(node, &buf, hvm) != 0)
|
||||
goto error;
|
||||
}
|
||||
cleanup:
|
||||
if (xml != NULL)
|
||||
xmlFreeDoc(xml);
|
||||
return buf.content;
|
||||
error:
|
||||
free(buf.content);
|
||||
buf.content = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/**
|
||||
* virDomainXMLDevID:
|
||||
* @domain: pointer to domain object
|
||||
* @xmldesc: string with the XML description
|
||||
* @class: Xen device class "vbd" or "vif" (OUT)
|
||||
* @ref: Xen device reference (OUT)
|
||||
*
|
||||
* Set class according to XML root, and:
|
||||
* - if disk, copy in ref the target name from description
|
||||
* - if network, get MAC address from description, scan XenStore and
|
||||
* copy in ref the corresponding vif number.
|
||||
*
|
||||
* Returns 0 in case of success, -1 in case of failure.
|
||||
*/
|
||||
int
|
||||
virDomainXMLDevID(virDomainPtr domain, char *xmldesc, char *class, char *ref)
|
||||
{
|
||||
xmlDocPtr xml = NULL;
|
||||
xmlNodePtr node, cur;
|
||||
xmlChar *attr = NULL;
|
||||
char dir[80], path[128], **list = NULL, *mac = NULL;
|
||||
int ret = 0, num, i, len;
|
||||
|
||||
xml = xmlReadDoc((const xmlChar *) xmldesc, "domain.xml", NULL,
|
||||
XML_PARSE_NOENT | XML_PARSE_NONET |
|
||||
XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
|
||||
if (xml == NULL)
|
||||
goto error;
|
||||
node = xmlDocGetRootElement(xml);
|
||||
if (node == NULL)
|
||||
goto error;
|
||||
if (xmlStrEqual(node->name, BAD_CAST "disk")) {
|
||||
strcpy(class, "vbd");
|
||||
for (cur = node->children; cur != NULL; cur = cur->next) {
|
||||
if ((cur->type != XML_ELEMENT_NODE) ||
|
||||
(!xmlStrEqual(cur->name, BAD_CAST "target"))) continue;
|
||||
attr = xmlGetProp(cur, BAD_CAST "dev");
|
||||
if (attr == NULL)
|
||||
goto error;
|
||||
strcpy(ref, attr);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
|
||||
strcpy(class, "vif");
|
||||
for (cur = node->children; cur != NULL; cur = cur->next) {
|
||||
if ((cur->type != XML_ELEMENT_NODE) ||
|
||||
(!xmlStrEqual(cur->name, BAD_CAST "mac"))) continue;
|
||||
attr = xmlGetProp(cur, BAD_CAST "address");
|
||||
if (attr == NULL)
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* TODO: this part need to be isolated as a high level routine in
|
||||
* xs_internal.[ch]
|
||||
*/
|
||||
sprintf(dir, "/local/domain/0/backend/vif/%d", domain->handle);
|
||||
list = xs_directory(domain->conn->xshandle, 0, dir, &num);
|
||||
if (list == NULL)
|
||||
goto error;
|
||||
for (i = 0; i < num; i++) {
|
||||
sprintf(path, "%s/%s/%s", dir, list[i], "mac");
|
||||
mac = xs_read(domain->conn->xshandle, 0, path, &len);
|
||||
if (mac == NULL)
|
||||
goto error;
|
||||
if ((strlen(attr) != len) || memcmp(attr, mac, len)) {
|
||||
free(mac);
|
||||
mac = NULL;
|
||||
continue;
|
||||
}
|
||||
strcpy(ref, list[i]);
|
||||
goto cleanup;
|
||||
}
|
||||
/*
|
||||
* end of TODO block
|
||||
*/
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
error:
|
||||
ret = -1;
|
||||
cleanup:
|
||||
if (xml != NULL)
|
||||
xmlFreeDoc(xml);
|
||||
if (attr != NULL)
|
||||
xmlFree(attr);
|
||||
if (list != NULL)
|
||||
free(list);
|
||||
if (mac != NULL)
|
||||
free(mac);
|
||||
return ret;
|
||||
}
|
||||
#endif /* !PROXY */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* indent-tabs-mode: nil
|
||||
|
@ -31,6 +31,8 @@ int virBufferVSprintf(virBufferPtr buf, const char *format, ...);
|
||||
int virBufferStrcat(virBufferPtr buf, ...);
|
||||
char *virDomainParseXMLDesc(const char *xmldesc, char **name, int xendConfigVersion);
|
||||
unsigned char *virParseUUID(char **ptr, const char *uuid);
|
||||
char *virParseXMLDevice(char *xmldesc, int hvm, int xendConfigVersion);
|
||||
int virDomainXMLDevID(virDomainPtr domain, char *xmldesc, char *class, char *ref);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -77,6 +77,8 @@ static virDriver xenStoreDriver = {
|
||||
NULL, /* domainCreate */
|
||||
NULL, /* domainDefineXML */
|
||||
NULL, /* domainUndefine */
|
||||
NULL, /* domainAttachDevice */
|
||||
NULL, /* domainDetachDevice */
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user