]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
Implement support for inactive domains from Xen 3.0.4
authorDaniel P. Berrange <berrange@redhat.com>
Thu, 14 Dec 2006 01:56:14 +0000 (01:56 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Thu, 14 Dec 2006 01:56:14 +0000 (01:56 +0000)
ChangeLog
src/internal.h
src/xend_internal.c
src/xend_internal.h
src/xm_internal.c

index 5112d1c7e92c75787f4518f86d2c852d3e67391b..f52cead3d178393e06d3edf84b97ce78af30351c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,16 @@
-Thu Dec 12 09:05:03 EST 2006 Daniel Berrange <berrange@redhat.com>
+Wed Dec 13 17:24:03 EST 2006 Daniel Berrange <berrange@redhat.com>
+
+       * src/xend_internal.c: Implement the ListDefinedDomains, NumOfDefinedDomains,
+       DomainCreate ,DomainDefineXML, DomainUndefine APIs to manage inactive domains
+       when running with Xen 3.0.4.  Make GetMaxMemory,  SetMaxMemory, SetMemory,
+       GetInfo, SetVCPUs & DumpXML work with inactive domains. Cache xendConfigVersion
+       when first connecting to Xend.
+       * src/xend_internal.h: Prototypes for new APIs
+       * src/xm_internal.c: Updated for new way of getting xendConfigVersion
+       data
+       * src/internal.h: Added xendConfigVersion field for virConnect struct
+
+Tue Dec 12 09:05:03 EST 2006 Daniel Berrange <berrange@redhat.com>
 
        * src/xend_internal.c: Added support for vnclisten parameter
        in generated XML
index c8a284a6b9eea7175ad4f3e3949d0352fb68bec6..9b94b27381fcc8a85ea11326e9b2c2f5af4b7034 100644 (file)
@@ -108,6 +108,7 @@ struct _virConnect {
     int handle;             /* internal handle used for hypercall */
     struct xs_handle *xshandle;/* handle to talk to the xenstore */
     int proxy;              /* file descriptor if using the proxy */
+    int xendConfigVersion;  /* XenD config version */
 
     /* connection to xend */
     int type;               /* PF_UNIX or PF_INET */
index 3cf1dd6fa826563bae413298c94a8000a721db64..ee630aeecd0685643c87ac0bba089aa8af03e704 100644 (file)
@@ -41,6 +41,8 @@
 static const char * xenDaemonGetType(virConnectPtr conn);
 static int xenDaemonListDomains(virConnectPtr conn, int *ids, int maxids);
 static int xenDaemonNumOfDomains(virConnectPtr conn);
+static int xenDaemonListDefinedDomains(virConnectPtr conn, const char **names, int maxnames);
+static int xenDaemonNumOfDefinedDomains(virConnectPtr conn);
 static virDomainPtr xenDaemonLookupByID(virConnectPtr conn, int id);
 static virDomainPtr xenDaemonLookupByUUID(virConnectPtr conn,
                                           const unsigned char *uuid);
@@ -93,11 +95,11 @@ static virDriver xenDaemonDriver = {
     xenDaemonDomainPinVcpu, /* domainPinVcpu */
     xenDaemonDomainGetVcpus, /* domainGetVcpus */
     xenDaemonDomainDumpXML, /* domainDumpXML */
-    NULL, /* listDefinedDomains */
-    NULL, /* numOfDefinedDomains */
-    NULL, /* domainCreate */
-    NULL, /* domainDefineXML */
-    NULL, /* domainUndefine */
+    xenDaemonListDefinedDomains, /* listDefinedDomains */
+    xenDaemonNumOfDefinedDomains, /* numOfDefinedDomains */
+    xenDaemonDomainCreate, /* domainCreate */
+    xenDaemonDomainDefineXML, /* domainDefineXML */
+    xenDaemonDomainUndefine, /* domainUndefine */
     xenDaemonAttachDevice, /* domainAttachDevice */
     xenDaemonDetachDevice /* domainDetachDevice */
 };
@@ -702,6 +704,7 @@ sexpr_int(struct sexpr *sexpr, const char *name)
     return 0;
 }
 
+
 /**
  * sexpr_float:
  * @sexpr: an S-Expression
@@ -1273,8 +1276,8 @@ xend_get_node(virConnectPtr xend)
     return node;
 }
 
-int
-xend_get_config_version(virConnectPtr conn) {
+static int
+xend_detect_config_version(virConnectPtr conn) {
     struct sexpr *root;
     const char *value;
 
@@ -1286,23 +1289,20 @@ xend_get_config_version(virConnectPtr conn) {
     root = sexpr_get(conn, "/xend/node/");
     if (root == NULL)
         return (-1);
-
+    
     value = sexpr_node(root, "node/xend_config_format");
-
+    
     if (value) {
-        int version = strtol(value, NULL, 10);
-        sexpr_free(root);
-        return version;
-    } 
-
+        conn->xendConfigVersion = strtol(value, NULL, 10);
+    }  else {
+        /* Xen prior to 3.0.3 did not have the xend_config_format
+           field, and is implicitly version 1. */
+        conn->xendConfigVersion = 1;
+    }
     sexpr_free(root);
-
-    /* Xen prior to 3.0.3 did not have the xend_config_format
-       field, and is implicitly version 1. */
-    return 1;
+    return conn->xendConfigVersion;
 }
 
-
 #ifndef PROXY
 /**
  * xend_node_shutdown:
@@ -1853,7 +1853,7 @@ xend_parse_domain_sexp(virConnectPtr conn, char *sexpr, int xendConfigVersion) {
  * Returns 0 in case of success, -1 in case of error
  */
 static int
-sexpr_to_xend_domain_info(struct sexpr *root, virDomainInfoPtr info)
+sexpr_to_xend_domain_info(virDomainPtr domain, struct sexpr *root, virDomainInfoPtr info)
 {
     const char *flags;
 
@@ -1879,7 +1879,12 @@ sexpr_to_xend_domain_info(struct sexpr *root, virDomainInfoPtr info)
         else if (strchr(flags, 'r'))
             info->state = VIR_DOMAIN_RUNNING;
     } else {
-        info->state = VIR_DOMAIN_NOSTATE;
+        /* Inactive domains don't have a state reported, so
+           mark them SHUTOFF, rather than NOSTATE */
+        if (domain->handle < 0)
+            info->state = VIR_DOMAIN_SHUTOFF;
+        else
+            info->state = VIR_DOMAIN_NOSTATE;
     }
     info->cpuTime = sexpr_float(root, "domain/cpu_time") * 1000000000;
     info->nrVirtCpu = sexpr_int(root, "domain/vcpus");
@@ -1940,6 +1945,7 @@ sexpr_to_domain(virConnectPtr conn, struct sexpr *root)
     char *dst_uuid = NULL;
     char uuid[16];
     const char *name;
+    const char *tmp;
 
     if ((conn == NULL) || (root == NULL))
         return(NULL);
@@ -1954,12 +1960,20 @@ sexpr_to_domain(virConnectPtr conn, struct sexpr *root)
     ret = virGetDomain(conn, name, (const unsigned char *) &uuid[0]);
     if (ret == NULL) {
         virXendError(conn, VIR_ERR_NO_MEMORY, _("allocating domain"));
-       return(NULL);
+        return(NULL);
     }
-    ret->handle = sexpr_int(root, "domain/domid");
-    if (ret->handle < 0)
+    tmp = sexpr_node(root, "domain/domid");
+    /* New 3.0.4 XenD will not report a domid for inactive domains,
+     * so only error out for old XenD
+     */
+    if (!tmp && conn->xendConfigVersion < 3)
         goto error;
 
+    if (tmp)
+        ret->handle = sexpr_int(root, "domain/domid");
+    else
+        ret->handle = -1; /* An inactive domain */
+
     return (ret);
 
 error:
@@ -2062,6 +2076,15 @@ try_http:
     }
 
 done:
+    /* The XenD config version is used to determine
+     * which APIs / features to activate. Lookup & cache
+     * it now to avoid repeated HTTP calls
+     */
+    if (xend_detect_config_version(conn) < 0) {
+        virXendError(conn, VIR_ERR_INTERNAL_ERROR, "cannot determine xend config version");
+        goto failed;
+    }
+
     if (uri != NULL)
         xmlFreeURI(uri);
     return(ret);
@@ -2302,7 +2325,7 @@ xenDaemonDomainGetMaxMemory(virDomainPtr domain)
                     __FUNCTION__);
         return(-1);
     }
-    if (domain->handle < 0)
+    if (domain->handle < 0 && domain->conn->xendConfigVersion < 3)
         return(-1);
 
     /* can we ask for a subset ? worth it ? */
@@ -2338,7 +2361,7 @@ xenDaemonDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
                     __FUNCTION__);
         return(-1);
     }
-    if (domain->handle < 0)
+    if (domain->handle < 0 && domain->conn->xendConfigVersion < 3)
         return(-1);
 
     snprintf(buf, sizeof(buf), "%lu", memory >> 10);
@@ -2372,7 +2395,7 @@ xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory)
                     __FUNCTION__);
         return(-1);
     }
-    if (domain->handle < 0)
+    if (domain->handle < 0 && domain->conn->xendConfigVersion < 3)
         return(-1);
 
     snprintf(buf, sizeof(buf), "%lu", memory >> 10);
@@ -2382,23 +2405,36 @@ xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory)
 
 #endif /* ! PROXY */
 
+/* XXX change proxy to use Name instead of ID, then
+   dumpxml will work over proxy for inactive domains
+   and this can be removed */
 char *
 xenDaemonDomainDumpXMLByID(virConnectPtr conn, int domid)
 {
     char *ret = NULL;
     struct sexpr *root;
-    int xendConfigVersion;
 
     root = sexpr_get(conn, "/xend/domain/%d?detail=1", domid);
     if (root == NULL)
         return (NULL);
 
-    if ((xendConfigVersion = xend_get_config_version(conn)) < 0) {
-        virXendError(conn, VIR_ERR_INTERNAL_ERROR, "cannot determine xend config version");
+    ret = xend_parse_sexp_desc(conn, root, conn->xendConfigVersion);
+    sexpr_free(root);
+
+    return (ret);
+}
+
+char *
+xenDaemonDomainDumpXMLByName(virConnectPtr conn, const char *name)
+{
+    char *ret = NULL;
+    struct sexpr *root;
+
+    root = sexpr_get(conn, "/xend/domain/%s?detail=1", name);
+    if (root == NULL)
         return (NULL);
-    }
 
-    ret = xend_parse_sexp_desc(conn, root, xendConfigVersion);
+    ret = xend_parse_sexp_desc(conn, root, conn->xendConfigVersion);
     sexpr_free(root);
 
     return (ret);
@@ -2423,10 +2459,12 @@ xenDaemonDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED)
                     __FUNCTION__);
         return(NULL);
     }
-    if (domain->handle < 0)
+    if (domain->handle < 0 && domain->conn->xendConfigVersion < 3)
         return(NULL);
-
-    return xenDaemonDomainDumpXMLByID(domain->conn, domain->handle);
+    if (domain->handle < 0)
+        return xenDaemonDomainDumpXMLByName(domain->conn, domain->name);
+    else
+        return xenDaemonDomainDumpXMLByID(domain->conn, domain->handle);
 }
 #endif /* !PROXY */
 
@@ -2452,14 +2490,14 @@ xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
                     __FUNCTION__);
         return(-1);
     }
-    if (domain->handle < 0)
+    if (domain->handle < 0 && domain->conn->xendConfigVersion < 3)
         return(-1);
 
     root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
     if (root == NULL)
         return (-1);
 
-    ret = sexpr_to_xend_domain_info(root, info);
+    ret = sexpr_to_xend_domain_info(domain, root, info);
     sexpr_free(root);
     return (ret);
 }
@@ -2484,8 +2522,9 @@ xenDaemonDomainLookupByName(virConnectPtr conn, const char *domname)
 
     if ((conn == NULL) || (domname == NULL)) {
         virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-       return(NULL);
+        return(NULL);
     }
+
     root = sexpr_get(conn, "/xend/domain/%s?detail=1", domname);
     if (root == NULL)
         goto error;
@@ -2735,7 +2774,7 @@ xenDaemonDomainSetVcpus(virDomainPtr domain, unsigned int vcpus)
                     __FUNCTION__);
         return (-1);
     }
-    if (domain->handle < 0)
+    if (domain->handle < 0 && domain->conn->xendConfigVersion < 3)
         return(-1);
 
     snprintf(buf, sizeof(buf), "%d", vcpus);
@@ -2955,7 +2994,6 @@ xenDaemonCreateLinux(virConnectPtr conn, const char *xmlDesc,
     char *sexpr;
     char *name = NULL;
     virDomainPtr dom;
-    int xendConfigVersion;
 
     if (!VIR_IS_CONNECT(conn)) {
         virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
@@ -2966,13 +3004,7 @@ xenDaemonCreateLinux(virConnectPtr conn, const char *xmlDesc,
         return (NULL);
     }
 
-    if ((xendConfigVersion = xend_get_config_version(conn)) < 0) {
-        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                    "cannot determine xend config version");
-        return (NULL);
-    }
-
-    sexpr = virDomainParseXMLDesc(xmlDesc, &name, xendConfigVersion);
+    sexpr = virDomainParseXMLDesc(xmlDesc, &name, conn->xendConfigVersion);
     if ((sexpr == NULL) || (name == NULL)) {
         virXendError(conn, VIR_ERR_XML_ERROR, "domain");
         if (sexpr != NULL)
@@ -3032,21 +3064,17 @@ static int
 xenDaemonAttachDevice(virDomainPtr domain, char *xml)
 {
     char *sexpr, *conf;
-    int xendConfigVersion, hvm = 0, ret;
+    int 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);
+    sexpr = virParseXMLDevice(xml, hvm, domain->conn->xendConfigVersion);
     if (sexpr == NULL)
         return (-1);
     if (!memcmp(sexpr, "(device ", 8)) {
@@ -3084,8 +3112,144 @@ xenDaemonDetachDevice(virDomainPtr domain, char *xml)
     return(xend_op(domain->conn, domain->name, "op", "device_destroy",
         "type", class, "dev", ref, NULL));
 }
+
+
+virDomainPtr xenDaemonDomainDefineXML(virConnectPtr conn, const char *xmlDesc) {
+    int ret;
+    char *sexpr;
+    char *name = NULL;
+    virDomainPtr dom;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (xmlDesc == NULL) {
+        virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    sexpr = virDomainParseXMLDesc(xmlDesc, &name, conn->xendConfigVersion);
+    if ((sexpr == NULL) || (name == NULL)) {
+        virXendError(conn, VIR_ERR_XML_ERROR, "domain");
+        if (sexpr != NULL)
+            free(sexpr);
+        if (name != NULL)
+            free(name);
+
+        return (NULL);
+    }
+
+    ret = xend_op(conn, "", "op", "new", "config", sexpr, NULL);
+    free(sexpr);
+    if (ret != 0) {
+        fprintf(stderr, _("Failed to create inactive domain %s\n"), name);
+        goto error;
+    }
+
+    dom = virDomainLookupByName(conn, name);
+    if (dom == NULL) {
+        goto error;
+    }
+
+    return (dom);
+  error:
+    if (name != NULL)
+        free(name);
+    return (NULL);
+}
+int xenDaemonDomainCreate(virDomainPtr domain) {
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                    __FUNCTION__);
+        return(-1);
+    }
+    if (domain->conn->xendConfigVersion < 3)
+        return(-1);
+
+    return xend_op(domain->conn, domain->name, "op", "start", NULL);
+}
+
+int xenDaemonDomainUndefine(virDomainPtr domain) {
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                    __FUNCTION__);
+        return(-1);
+    }
+    if (domain->conn->xendConfigVersion < 3)
+        return(-1);
+
+    return xend_op(domain->conn, domain->name, "op", "delete", NULL);
+}
+
+/**
+ * xenDaemonNumOfDomains:
+ * @conn: pointer to the hypervisor connection
+ *
+ * Provides the number of active domains.
+ *
+ * Returns the number of domain found or -1 in case of error
+ */
+static int
+xenDaemonNumOfDefinedDomains(virConnectPtr conn)
+{
+    struct sexpr *root = NULL;
+    int ret = -1;
+    struct sexpr *_for_i, *node;
+
+    root = sexpr_get(conn, "/xend/domain?state=halted");
+    if (root == NULL)
+        goto error;
+
+    ret = 0;
+
+    for (_for_i = root, node = root->car; _for_i->kind == SEXPR_CONS;
+         _for_i = _for_i->cdr, node = _for_i->car) {
+        if (node->kind != SEXPR_VALUE)
+            continue;
+        ret++;
+    }
+
+error:
+    if (root != NULL)
+        sexpr_free(root);
+    return(ret);
+}
+
+int xenDaemonListDefinedDomains(virConnectPtr conn, const char **names, int maxnames) {
+    struct sexpr *root = NULL;
+    int ret = -1;
+    struct sexpr *_for_i, *node;
+
+    if ((names == NULL) || (maxnames <= 0))
+        goto error;
+    root = sexpr_get(conn, "/xend/domain?state=halted");
+    if (root == NULL)
+        goto error;
+
+    ret = 0;
+
+    for (_for_i = root, node = root->car; _for_i->kind == SEXPR_CONS;
+         _for_i = _for_i->cdr, node = _for_i->car) {
+        if (node->kind != SEXPR_VALUE)
+            continue;
+
+        names[ret++] = strdup(node->value);
+        if (ret >= maxnames)
+            break;
+    }
+
+error:
+    if (root != NULL)
+        sexpr_free(root);
+    return(ret);
+}
+
 #endif /* ! PROXY */
 
+
+
+
 /*
  * Local variables:
  *  indent-tabs-mode: nil
index 8f2197754fcf95f78df9189f81b72b7ace3d6eaf..95daf9087dc4464a311d67a4652e111b437747cd 100644 (file)
@@ -551,6 +551,9 @@ int xenDaemonDomainLookupByID(virConnectPtr xend,
 char *xenDaemonDomainDumpXMLByID(virConnectPtr xend,
                                 int domid);
 
+char *xenDaemonDomainDumpXMLByName(virConnectPtr xend,
+                                  const char *name);
+
 /**
  * \brief Lookup information about the host machine
  * \param xend A xend instance
@@ -613,7 +616,6 @@ char *xenDaemonDomainDumpXMLByID(virConnectPtr xend,
  */
     int xend_log(virConnectPtr xend, char *buffer, size_t n_buffer);
 
-  int xend_get_config_version(virConnectPtr conn);
   char *xend_parse_domain_sexp(virConnectPtr conn,  char *root, int xendConfigVersion);
 
 /* refactored ones */
@@ -637,6 +639,10 @@ virDomainPtr xenDaemonDomainLookupByName(virConnectPtr conn, const char *domname
 unsigned long xenDaemonDomainGetMaxMemory(virDomainPtr domain);
 char **xenDaemonListDomainsOld(virConnectPtr xend);
 
+virDomainPtr xenDaemonDomainDefineXML(virConnectPtr xend, const char *sexpr);
+int xenDaemonDomainCreate(virDomainPtr domain);
+int xenDaemonDomainUndefine(virDomainPtr domain);
+
 int    xenDaemonDomainSetVcpus         (virDomainPtr domain,
                                         unsigned int vcpus);
 int    xenDaemonDomainPinVcpu          (virDomainPtr domain,
index 530c6f8ec7e115d1461c61803dabac673f566465..36651072269377bb90ac88e7aa2682eb6660a3be 100644 (file)
@@ -994,7 +994,7 @@ virDomainPtr xenXMDomainLookupByUUID(virConnectPtr conn,
 int xenXMDomainCreate(virDomainPtr domain) {
     char *xml;
     char *sexpr;
-    int ret, xendConfigVersion;
+    int ret;
     unsigned char uuid[16];
 
     if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
@@ -1011,12 +1011,7 @@ int xenXMDomainCreate(virDomainPtr domain) {
     if (!(xml = xenXMDomainDumpXML(domain, 0)))
         return (-1);
 
-    if ((xendConfigVersion = xend_get_config_version(domain->conn)) < 0) {
-        xenXMError(domain->conn, VIR_ERR_INTERNAL_ERROR, "cannot determine xend config version");
-        return (-1);
-    }
-
-    if (!(sexpr = virDomainParseXMLDesc(xml, NULL, xendConfigVersion))) {
+    if (!(sexpr = virDomainParseXMLDesc(xml, NULL, domain->conn->xendConfigVersion))) {
         free(xml);
         return (-1);
     }