[libvirt] PATCH: Fix misc bugs in QEMU ARGV -> XML convertor

Daniel P. Berrange berrange at redhat.com
Thu May 28 09:47:14 UTC 2009


Having just tried out the QEMU ARGV -> XML convertor on a random set of
args posted on the mailing list I found a few bugs. It didn't cope with
a -net arg without a vlan=XX option set - this should assume vlan=0 if
not set. It didn't cope with quoting of args with spaces in them. It
finally did not generate a random UUID or MAC address if omitted.

Regards,
Daniel

diff -r eb060781cfb9 src/qemu_conf.c
--- a/src/qemu_conf.c	Wed May 27 21:07:37 2009 +0100
+++ b/src/qemu_conf.c	Wed May 27 22:56:55 2009 +0100
@@ -1565,14 +1565,27 @@ static int qemuStringToArgvEnv(const cha
     /* Iterate over string, splitting on sequences of ' ' */
     while (curr && *curr != '\0') {
         char *arg;
-        const char *next = strchr(curr, ' ');
+        const char *next;
+        if (*curr == '\'') {
+            curr++;
+            next = strchr(curr, '\'');
+        } else if (*curr == '"') {
+            curr++;
+            next = strchr(curr, '"');
+        } else {
+            next = strchr(curr, ' ');
+        }
         if (!next)
             next = strchr(curr, '\n');
 
-        if (next)
+        if (next) {
             arg = strndup(curr, next-curr);
-        else
+            if (*next == '\'' ||
+                *next == '"')
+                next++;
+        } else {
             arg = strdup(curr);
+        }
 
         if (!arg)
             goto no_memory;
@@ -1644,7 +1657,7 @@ static const char *qemuFindEnv(const cha
     int i;
     int len = strlen(name);
 
-    for (i = 0 ; progenv[i] ; i++) {
+    for (i = 0 ; progenv && progenv[i] ; i++) {
         if (STREQLEN(progenv[i], name, len) &&
             progenv[i][len] == '=')
             return progenv[i] + len + 1;
@@ -1883,8 +1896,10 @@ qemuFindNICForVLAN(virConnectPtr conn,
         int gotvlan;
         const char *tmp = strstr(nics[i], "vlan=");
         char *end;
-        if (tmp)
-            tmp += strlen("vlan=");
+        if (!tmp)
+            continue;
+
+        tmp += strlen("vlan=");
 
         if (virStrToLong_i(tmp, &end, 10, &gotvlan) < 0) {
             qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
@@ -1896,6 +1911,9 @@ qemuFindNICForVLAN(virConnectPtr conn,
             return nics[i];
     }
 
+    if (wantvlan == 0 && nnics > 0)
+        return nics[0];
+
     qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                      _("cannot find NIC definition for vlan %d"), wantvlan);
     return NULL;
@@ -1909,32 +1927,33 @@ qemuFindNICForVLAN(virConnectPtr conn,
  */
 static virDomainNetDefPtr
 qemuParseCommandLineNet(virConnectPtr conn,
+                        virCapsPtr caps,
                         const char *val,
                         int nnics,
                         const char **nics)
 {
     virDomainNetDefPtr def = NULL;
-    char **keywords;
-    char **values;
+    char **keywords = NULL;
+    char **values = NULL;
     int nkeywords;
     const char *nic;
     int wantvlan = 0;
     const char *tmp;
+    int genmac = 1;
     int i;
 
     tmp = strchr(val, ',');
-    if (!tmp) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("cannot extract NIC type from '%s'"), val);
-        return NULL;
+
+    if (tmp) {
+        if ((nkeywords = qemuParseCommandLineKeywords(conn,
+                                                      tmp+1,
+                                                      &keywords,
+                                                      &values)) < 0)
+            return NULL;
+    } else {
+        nkeywords = 0;
     }
 
-    if ((nkeywords = qemuParseCommandLineKeywords(conn,
-                                                  tmp+1,
-                                                  &keywords,
-                                                  &values)) < 0)
-        return NULL;
-
     if (VIR_ALLOC(def) < 0) {
         virReportOOMError(conn);
         goto cleanup;
@@ -1983,7 +2002,9 @@ qemuParseCommandLineNet(virConnectPtr co
         goto cleanup;
     }
 
-    if (!STRPREFIX(nic, "nic,")) {
+    if (!STRPREFIX(nic, "nic")) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                         _("cannot parse NIC definition '%s'"), nic);
         virDomainNetDefFree(def);
         def = NULL;
         goto cleanup;
@@ -1996,17 +2017,22 @@ qemuParseCommandLineNet(virConnectPtr co
     VIR_FREE(keywords);
     VIR_FREE(values);
 
-    if ((nkeywords = qemuParseCommandLineKeywords(conn,
-                                                  nic + strlen("nic,"),
-                                                  &keywords,
-                                                  &values)) < 0) {
-        virDomainNetDefFree(def);
-        def = NULL;
-        goto cleanup;
+    if (STRPREFIX(nic, "nic,")) {
+        if ((nkeywords = qemuParseCommandLineKeywords(conn,
+                                                      nic + strlen("nic,"),
+                                                      &keywords,
+                                                      &values)) < 0) {
+            virDomainNetDefFree(def);
+            def = NULL;
+            goto cleanup;
+        }
+    } else {
+        nkeywords = 0;
     }
 
     for (i = 0 ; i < nkeywords ; i++) {
         if (STREQ(keywords[i], "macaddr")) {
+            genmac = 0;
             virParseMacAddr(values[i], def->mac);
         } else if (STREQ(keywords[i], "model")) {
             def->model = values[i];
@@ -2014,6 +2040,9 @@ qemuParseCommandLineNet(virConnectPtr co
         }
     }
 
+    if (genmac)
+        virCapabilitiesGenerateMac(caps, def->mac);
+
 cleanup:
     for (i = 0 ; i < nkeywords ; i++) {
         VIR_FREE(keywords[i]);
@@ -2283,6 +2312,7 @@ error:
  * as is practical. This is not an exact science....
  */
 virDomainDefPtr qemuParseCommandLine(virConnectPtr conn,
+                                     virCapsPtr caps,
                                      const char **progenv,
                                      const char **progargv)
 {
@@ -2303,6 +2333,8 @@ virDomainDefPtr qemuParseCommandLine(vir
     if (VIR_ALLOC(def) < 0)
         goto no_memory;
 
+    virUUIDGenerate(def->uuid);
+
     def->id = -1;
     def->memory = def->maxmem = 64 * 1024;
     def->vcpus = 1;
@@ -2604,7 +2636,7 @@ virDomainDefPtr qemuParseCommandLine(vir
             WANT_VALUE();
             if (!STRPREFIX(val, "nic") && STRNEQ(val, "none")) {
                 virDomainNetDefPtr net;
-                if (!(net = qemuParseCommandLineNet(conn, val, nnics, nics)))
+                if (!(net = qemuParseCommandLineNet(conn, caps, val, nnics, nics)))
                     goto error;
                 if (VIR_REALLOC_N(def->nets, def->nnets+1) < 0) {
                     virDomainNetDefFree(net);
@@ -2741,6 +2773,7 @@ error:
 
 
 virDomainDefPtr qemuParseCommandLineString(virConnectPtr conn,
+                                           virCapsPtr caps,
                                            const char *args)
 {
     const char **progenv = NULL;
@@ -2751,7 +2784,7 @@ virDomainDefPtr qemuParseCommandLineStri
     if (qemuStringToArgvEnv(args, &progenv, &progargv) < 0)
         goto cleanup;
 
-    def = qemuParseCommandLine(conn, progenv, progargv);
+    def = qemuParseCommandLine(conn, caps, progenv, progargv);
 
 cleanup:
     for (i = 0 ; progargv && progargv[i] ; i++)
diff -r eb060781cfb9 src/qemu_conf.h
--- a/src/qemu_conf.h	Wed May 27 21:07:37 2009 +0100
+++ b/src/qemu_conf.h	Wed May 27 22:56:55 2009 +0100
@@ -127,9 +127,11 @@ int         qemudBuildCommandLine       
                                          const char *migrateFrom);
 
 virDomainDefPtr qemuParseCommandLine(virConnectPtr conn,
+                                     virCapsPtr caps,
                                      const char **progenv,
                                      const char **progargv);
 virDomainDefPtr qemuParseCommandLineString(virConnectPtr conn,
+                                           virCapsPtr caps,
                                            const char *args);
 
 #endif /* __QEMUD_CONF_H */
diff -r eb060781cfb9 src/qemu_driver.c
--- a/src/qemu_driver.c	Wed May 27 21:07:37 2009 +0100
+++ b/src/qemu_driver.c	Wed May 27 22:56:55 2009 +0100
@@ -3418,6 +3418,7 @@ static char *qemuDomainXMLFromNative(vir
                                      const char *format,
                                      const char *config,
                                      unsigned int flags ATTRIBUTE_UNUSED) {
+    struct qemud_driver *driver = conn->privateData;
     virDomainDefPtr def = NULL;
     char *xml = NULL;
 
@@ -3427,7 +3428,7 @@ static char *qemuDomainXMLFromNative(vir
         goto cleanup;
     }
 
-    def = qemuParseCommandLineString(conn, config);
+    def = qemuParseCommandLineString(conn, driver->caps, config);
     if (!def)
         goto cleanup;
 
diff -r eb060781cfb9 tests/qemuargv2xmltest.c
--- a/tests/qemuargv2xmltest.c	Wed May 27 21:07:37 2009 +0100
+++ b/tests/qemuargv2xmltest.c	Wed May 27 22:56:55 2009 +0100
@@ -49,7 +49,7 @@ static int testCompareXMLToArgvFiles(con
     if (virtTestLoadFile(xml, &expectxml, MAX_FILE) < 0)
         goto fail;
 
-    if (!(vmdef = qemuParseCommandLineString(NULL, cmd)))
+    if (!(vmdef = qemuParseCommandLineString(NULL, driver.caps, cmd)))
         goto fail;
 
     if (!(actualxml = virDomainDefFormat(NULL, vmdef, 0)))
@@ -109,6 +109,8 @@ mymain(int argc, char **argv)
     if (!abs_srcdir)
         abs_srcdir = getcwd(cwd, sizeof(cwd));
 
+    virRandomInitialize(0);
+
     if ((driver.caps = testQemuCapsInit()) == NULL)
         return EXIT_FAILURE;
     if((driver.stateDir = strdup("/nowhere")) == NULL)


-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list