]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
* include/libvirt/libvirt.h include/libvirt/libvirt.h.in
authorDaniel Veillard <veillard@redhat.com>
Thu, 16 Nov 2006 18:11:28 +0000 (18:11 +0000)
committerDaniel Veillard <veillard@redhat.com>
Thu, 16 Nov 2006 18:11:28 +0000 (18:11 +0000)
  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

13 files changed:
ChangeLog
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

index 362f3765bb29294ce7ce96bf724d8039e6806063..7389c25252485dfbde560b3140136fb15460a1f1 100644 (file)
--- a/ChangeLog
+++ b/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:
index 133091f5e9a0f4e1cd230f55c02296914ed845b7..dabe35ceb1fc4d52ac81a3ccea0b5958b1044311 100644 (file)
@@ -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
 }
index 9e9a8b57d59277d44d3014d5549b15ecb3606077..92f1feb906b6479c2677bbabc25dec0e3f485ec8 100644 (file)
@@ -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
 }
index 627121f03e205b41ae2a47b0e81f70f75385261e..e2ae5c6fababd0daea04e26afe66441e7d14ce43 100644 (file)
@@ -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;
 };
 
 
index 12e3116c8c873c8edadc2c5922ee08e71cef9aaf..85410c920cf27ba5fc962dfeb719ce3f0f448d69 100644 (file)
@@ -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);
+}
index 13c743905d8895f6dfbddff88fd5814d57e86821..5a40207f8e63737d3340780077c865de20afe091 100644 (file)
@@ -53,5 +53,8 @@
        virDomainSetVcpus;
        virDomainPinVcpu;
        virDomainGetVcpus;
+
+    virDomainAttachDevice;
+    virDomainDetachDevice;
     local: *;
 };
index b945e002343dcf60757f9cf1f0b57fe3d6f6e8b8..ce8d96b60452b09a0c4ac8fe0581dd4a38ac06b0 100644 (file)
@@ -83,6 +83,8 @@ static virDriver xenProxyDriver = {
     NULL, /* domainCreate */
     NULL, /* domainDefineXML */
     NULL, /* domainUndefine */
+    NULL, /* domainAttachDevice */
+    NULL, /* domainDetachDevice */
 };
 
 /**
index f3d8191d87df20784362e9d0f11b1e665c57d7a6..51ba18a572ececc2602ae7b9d1ae4b785c822039 100644 (file)
@@ -63,6 +63,8 @@ static virDriver testDriver = {
   NULL, /* domainCreate */
   NULL, /* domainDefineXML */
   NULL, /* domainUndefine */
+  NULL, /* domainAttachDevice */
+  NULL, /* domainDetachDevice */
 };
 
 /* Amount of time it takes to shutdown */
index 908f695d43551f34194c6a1b75ec4da847841638..abbf75c31415928e6bb8a69af533ba6828e8b94a 100644 (file)
@@ -458,6 +458,8 @@ static virDriver xenHypervisorDriver = {
     NULL, /* domainCreate */
     NULL, /* domainDefineXML */
     NULL, /* domainUndefine */
+    NULL, /* domainAttachDevice */
+    NULL, /* domainDetachDevice */
 };
 #endif /* !PROXY */
 
index d58ac0dd4a0f3d9cd6a389ef8856d1afbc270b47..9e73faaed634a4d6f3687f29730d771930bfe137 100644 (file)
@@ -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 */
 
 /*
index 2a7725115b632af9272a423e5a87115d01fb42a3..59b0c297fffd1aa699ae40fb3e3d9fa30994b594 100644 (file)
--- a/src/xml.c
+++ b/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
index 5e91abec1b37b4cef7ab40a51c44f1f09d6ddfc2..9cae3c368f327ee67533952156d7e75377bde5f7 100644 (file)
--- a/src/xml.h
+++ b/src/xml.h
@@ -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
 }
index 8630426e3b100c796f8c9804e706e7d8cf76b2d7..6ad145e48930cd5223a21a3402906d8cc498e9d6 100644 (file)
@@ -77,6 +77,8 @@ static virDriver xenStoreDriver = {
     NULL, /* domainCreate */
     NULL, /* domainDefineXML */
     NULL, /* domainUndefine */
+    NULL, /* domainAttachDevice */
+    NULL, /* domainDetachDevice */
 };
 
 /**