提交 dc28f35f 编写于 作者: D Daniel Veillard

* 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
上级 df1e7c99
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 */
/*
......
......@@ -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 */
};
/**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册