From 1b0f541704d0172fdbc4c0e075b37dc2e196d4cc Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 19 Jan 2007 20:23:37 +0000 Subject: [PATCH] Finished off XML parsing & XM config file generation for all supported guest configs --- ChangeLog | 6 + src/xm_internal.c | 1514 ++++++++++++++++++++++++++++++++++----------- src/xm_internal.h | 25 +- 3 files changed, 1163 insertions(+), 382 deletions(-) diff --git a/ChangeLog b/ChangeLog index ce4ec79075..5a92b114a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Fri Jan 19 15:23:13 EST 2007 Daniel Berrange + + * src/xm_internal.c: Finished off the conversion from XML + to XM config files, and the reverse, to deal with all known + libvirt guest config options. + Fri Jan 19 15:07:13 EST 2007 Daniel Berrange * src/conf.c: Free stored config parameters, when free'ing diff --git a/src/xm_internal.c b/src/xm_internal.c index 4b37c702d3..e60fd1827e 100644 --- a/src/xm_internal.c +++ b/src/xm_internal.c @@ -1,13 +1,25 @@ /* * xm_internal.h: helper routines for dealing with inactive domains * - * Copyright (C) 2006 + * Copyright (C) 2006-2007 Red Hat + * Copyright (C) 2006 Daniel P. Berrange * - * Daniel Berrange + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange * - * This file is subject to the terms and conditions of the GNU Lesser General - * Public License. See the file COPYING.LIB in the main directory of this - * archive for more details. */ #include @@ -493,7 +505,7 @@ int xenXMClose(virConnectPtr conn ATTRIBUTE_UNUSED) { return (0); } -/* +/* * Our backend type */ const char *xenXMGetType(virConnectPtr conn ATTRIBUTE_UNUSED) { @@ -502,7 +514,7 @@ const char *xenXMGetType(virConnectPtr conn ATTRIBUTE_UNUSED) { /* * Since these are all offline domains, we only return info about - * VCPUs and memory. + * VCPUs and memory. */ int xenXMDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) { const char *filename; @@ -548,14 +560,13 @@ int xenXMDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) { } +#define MAX_VFB 1024 /* * Turn a config record into a lump of XML describing the * domain, suitable for later feeding for virDomainCreateLinux */ -char *xenXMDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED) { +char *xenXMDomainFormatXML(virConnectPtr conn, virConfPtr conf) { virBufferPtr buf; - const char *filename; - xenXMConfCachePtr entry; char *xml; const char *name; unsigned char uuid[16]; @@ -563,6 +574,421 @@ char *xenXMDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED) { int hvm = 0; long val; virConfValuePtr list; + int vnc = 0, sdl = 0; + char vfb[MAX_VFB]; + long vncdisplay; + long vncunused = 1; + const char *vnclisten = NULL; + const char *vncpasswd = NULL; + + if (xenXMConfigGetString(conf, "name", &name) < 0) + return (NULL); + if (xenXMConfigGetUUID(conf, "uuid", uuid) < 0) + return (NULL); + + buf = virBufferNew(4096); + + virBufferAdd(buf, "\n", -1); + virBufferVSprintf(buf, " %s\n", name); + virBufferVSprintf(buf, + " %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + uuid[0], uuid[1], uuid[2], uuid[3], + uuid[4], uuid[5], uuid[6], uuid[7], + uuid[8], uuid[9], uuid[10], uuid[11], + uuid[12], uuid[13], uuid[14], uuid[15]); + + if ((xenXMConfigGetString(conf, "builder", &str) == 0) && + !strcmp(str, "hvm")) + hvm = 1; + + if (hvm) { + const char *boot; + virBufferAdd(buf, " \n", -1); + virBufferAdd(buf, " hvm\n", -1); + if (xenXMConfigGetString(conf, "kernel", &str) == 0) + virBufferVSprintf(buf, " %s\n", str); + + if (xenXMConfigGetString(conf, "boot", &boot) < 0) + boot = "c"; + + while (*boot) { + const char *dev; + switch (*boot) { + case 'a': + dev = "fd"; + break; + case 'd': + dev = "cdrom"; + break; + case 'c': + default: + dev = "hd"; + break; + } + virBufferVSprintf(buf, " %s\n", dev); + boot++; + } + + virBufferAdd(buf, " \n", -1); + } else { + + if (xenXMConfigGetString(conf, "bootloader", &str) == 0) + virBufferVSprintf(buf, " %s\n", str); + if (xenXMConfigGetString(conf, "kernel", &str) == 0) { + virBufferAdd(buf, " \n", -1); + virBufferAdd(buf, " linux\n", -1); + virBufferVSprintf(buf, " %s\n", str); + if (xenXMConfigGetString(conf, "ramdisk", &str) == 0) + virBufferVSprintf(buf, " %s\n", str); + if (xenXMConfigGetString(conf, "extra", &str) == 0) + virBufferVSprintf(buf, " %s\n", str); + virBufferAdd(buf, " \n", -1); + } + } + + if (xenXMConfigGetInt(conf, "memory", &val) < 0) + val = 64; + virBufferVSprintf(buf, " %ld\n", val * 1024); + + if (xenXMConfigGetInt(conf, "maxmem", &val) < 0) + if (xenXMConfigGetInt(conf, "memory", &val) < 0) + val = 64; + virBufferVSprintf(buf, " %ld\n", val * 1024); + + + if (xenXMConfigGetInt(conf, "vcpus", &val) < 0) + val = 1; + virBufferVSprintf(buf, " %ld\n", val); + + + + if (xenXMConfigGetString(conf, "on_poweroff", &str) < 0) + str = "destroy"; + virBufferVSprintf(buf, " %s\n", str); + + if (xenXMConfigGetString(conf, "on_reboot", &str) < 0) + str = "restart"; + virBufferVSprintf(buf, " %s\n", str); + + if (xenXMConfigGetString(conf, "on_crash", &str) < 0) + str = "restart"; + virBufferVSprintf(buf, " %s\n", str); + + + if (hvm) { + virBufferAdd(buf, " \n", -1); + if (xenXMConfigGetInt(conf, "pae", &val) == 0 && + val) + virBufferAdd(buf, " \n", -1); + if (xenXMConfigGetInt(conf, "acpi", &val) == 0 && + val) + virBufferAdd(buf, " \n", -1); + if (xenXMConfigGetInt(conf, "apic", &val) == 0 && + val) + virBufferAdd(buf, " \n", -1); + virBufferAdd(buf, " \n", -1); + } + + virBufferAdd(buf, " \n", -1); + + if (hvm) { + if (xenXMConfigGetString(conf, "device_model", &str) == 0) + virBufferVSprintf(buf, " %s\n", str); + } + + list = virConfGetValue(conf, "disk"); + if (list && list->type == VIR_CONF_LIST) { + list = list->list; + while (list) { + int block = 0; + int cdrom = 0; + char src[PATH_MAX]; + char dev[NAME_MAX]; + char drvName[NAME_MAX] = ""; + char drvType[NAME_MAX] = ""; + char *head; + char *offset; + char *tmp, *tmp1; + + if ((list->type != VIR_CONF_STRING) || (list->str == NULL)) + goto skipdisk; + head = list->str; + + /* + * Disks have 3 components, SOURCE,DEST-DEVICE,MODE + * eg, phy:/dev/HostVG/XenGuest1,xvda,w + * The SOURCE is usually prefixed with a driver type, + * and optionally driver sub-type + * The DEST-DEVICE is optionally post-fixed with disk type + */ + + /* Extract the source */ + if (!(offset = index(head, ',')) || offset[0] == '\0') + goto skipdisk; + if ((offset - head) >= (PATH_MAX-1)) + goto skipdisk; + strncpy(src, head, (offset - head)); + src[(offset-head)] = '\0'; + head = offset + 1; + + /* Extract the dest */ + if (!(offset = index(head, ',')) || offset[0] == '\0') + goto skipdisk; + if ((offset - head) >= (PATH_MAX-1)) + goto skipdisk; + strncpy(dev, head, (offset - head)); + dev[(offset-head)] = '\0'; + head = offset + 1; + + + /* Extract source driver type */ + if (!(tmp = index(src, ':')) || !tmp[0]) + goto skipdisk; + strncpy(drvName, src, (tmp-src)); + drvName[tmp-src] = '\0'; + + /* And the source driver sub-type */ + if (!strncmp(drvName, "tap", 3)) { + if (!(tmp1 = index(tmp+1, ':')) || !tmp1[0]) + goto skipdisk; + strncpy(drvType, tmp+1, (tmp1-(tmp+1))); + memmove(src, src+(tmp1-src)+1, strlen(src)-(tmp1-src)); + } else { + drvType[0] = '\0'; + memmove(src, src+(tmp-src)+1, strlen(src)-(tmp-src)); + } + + /* phy: type indicates a block device */ + if (!strcmp(drvName, "phy")) { + block = 1; + } + + /* Remove legacy ioemu: junk */ + if (!strncmp(dev, "ioemu:", 6)) { + memmove(dev, dev+6, strlen(dev)-5); + } + + /* Check for a :cdrom/:disk postfix */ + if ((tmp = index(dev, ':')) != NULL) { + if (!strcmp(tmp, ":cdrom")) + cdrom = 1; + tmp[0] = '\0'; + } + + virBufferVSprintf(buf, " \n", + block ? "block" : "file", + cdrom ? "cdrom" : "disk"); + if (drvType[0]) + virBufferVSprintf(buf, " \n", drvName, drvType); + else + virBufferVSprintf(buf, " \n", drvName); + virBufferVSprintf(buf, " \n", block ? "dev" : "file", src); + virBufferVSprintf(buf, " \n", dev); + if (!strcmp(head, "r") || + !strcmp(head, "ro")) + virBufferAdd(buf, " \n", -1); + virBufferAdd(buf, " \n", -1); + + skipdisk: + list = list->next; + } + } + + if (hvm && conn->xendConfigVersion == 1) { + if (xenXMConfigGetString(conf, "cdrom", &str) == 0) { + virBufferAdd(buf, " \n", -1); + virBufferAdd(buf, " \n", -1); + virBufferVSprintf(buf, " \n", str); + virBufferAdd(buf, " \n", -1); + virBufferAdd(buf, " \n", -1); + virBufferAdd(buf, " \n", -1); + } + } + + list = virConfGetValue(conf, "vif"); + if (list && list->type == VIR_CONF_LIST) { + list = list->list; + while (list) { + int type = -1; + char script[PATH_MAX]; + char ip[16]; + char mac[18]; + char *key; + + mac[0] = '\0'; + script[0] = '\0'; + ip[0] = '\0'; + + if ((list->type != VIR_CONF_STRING) || (list->str == NULL)) + goto skipnic; + + key = list->str; + while (key) { + char *data; + char *nextkey = index(key, ','); + + if (!(data = index(key, '=')) || (data[0] == '\0')) + goto skipnic; + data++; + + if (!strncmp(key, "mac=", 4)) { + int len = nextkey ? (nextkey - data) : 17; + if (len > 17) + len = 17; + strncpy(mac, data, len); + mac[len] = '\0'; + } else if (!strncmp(key, "bridge=", 7)) { + type = 1; + } else if (!strncmp(key, "script=", 7)) { + int len = nextkey ? (nextkey - data) : PATH_MAX-1; + if (len > (PATH_MAX-1)) + len = PATH_MAX-1; + strncpy(script, data, len); + script[len] = '\0'; + } else if (!strncmp(key, "ip=", 3)) { + int len = nextkey ? (nextkey - data) : 15; + if (len > 15) + len = 15; + strncpy(ip, data, len); + ip[len] = '\0'; + } + + while (nextkey && (nextkey[0] == ',' || + nextkey[0] == ' ' || + nextkey[0] == '\t')) + nextkey++; + key = nextkey; + } + + /* XXX Forcing to pretend its a bridge */ + if (type == -1) { + type = 1; + } + + virBufferAdd(buf, " \n", -1); + if (mac[0]) + virBufferVSprintf(buf, " \n", mac); + if (script[0]) + virBufferVSprintf(buf, "