Devel
Threads by month
- ----- 2026 -----
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- 17 participants
- 40169 discussions
Hi,
In the TODO list I find this line:
- event on big domain state change (create, crashed, paused, shutdown,
destroy)
Because this is a feature that is very useful, I first wonder how libvirt
reliably get 'events' itself for example from Xen? From what I can read
from xen_internal there is a xenHypervisorGetDomInfo function, but this
function should be scheduled in order to see event changes. Even if so,
can we be 'quick' enough to detect a destroy? Or determine the difference
between a shutdown and a destroy?
Stefan
3
3
By accident I ran a second instance of libvirtd. This second instance did
not terminate the first instance nor did it detect there was already a
running instance. By killing the second instance the first did not work
anymore.
Next to this, why does libvirtd terminate its iSCSI connections upon stop?
I saw it cannot gracefully 'reuse' existing sessions, but it is absurd
that restarting libvirtd would kill all running VMs on a host using iSCSI,
or not able to get a storage pool up because it is already logged in to
it.
Stefan
2
1
Hi,
Mainly because I think Daniel always gives good feedback and comments,
plus I don't want to be a troll on this list, I decided the time had come
to spend some minutes to hack up a patch :)
It has been tested:
tcp 0 0 192.168.0.5:16509 *:* LISTEN
vs
tcp 0 0 *:16509 *:* LISTEN
Only lefts me:
By making a contribution to this project, I, Stefan de Konink, certify
that:
(a) The contribution was created in whole or in part by me and I have the
right to submit it under the open source license indicated in the file; or
(b) The contribution is based upon previous work that, to the best of my
knowledge, is covered under an appropriate open source license and I have
the right under that license to submit that work with modifications,
whether created in whole or in part by me, under the same open source
license (unless I am permitted to submit under a different license), as
indicated in the file; or
(c) The contribution was provided directly to me by some other person who
certified (a), (b) or (c) and I have not modified it; and
(d) In the case of each of (a), (b), or (c), I understand and agree that
this project and the contribution are public and that a record of the
contribution (including all personal information I submit with it,
including my sign-off) is maintained indefinitely and may be redistributed
consistent with this project or the open source license indicated in the
file.
Signed-off-by: Stefan de Konink <dekonink(a)kinkrsoftware.nl>
Yours Sincerely,
Stefan de Konink
2
11
This patch removes all use of strcmp, strncmp, strcasecmp and strncasecmp
in favour of the equality macros we have defined in internal.h, eg STREQ,
STRNEQ, STRNEQLEN, STREQLEN, etc, etc
The only strcasecmp left is in virsh where it is used in a sort function
so does genuinely need the -1, 0, +1 tristate return value rather than a
simple boolean for equality.
This brings all code into compliance with string comparison guidelines in
the HACKING file.
proxy/libvirt_proxy.c | 4 -
src/conf.c | 4 -
src/hash.c | 12 ++---
src/iptables.c | 6 +-
src/libvirt.c | 4 -
src/openvz_conf.c | 10 ++--
src/qemu_conf.c | 62 ++++++++++++++---------------
src/remote_internal.c | 10 ++--
src/sexpr.c | 4 -
src/test.c | 14 +++---
src/util.c | 8 +--
src/virsh.c | 30 +++++++-------
src/xen_unified.c | 6 +-
src/xend_internal.c | 40 +++++++++----------
src/xm_internal.c | 104 +++++++++++++++++++++++++-------------------------
src/xml.c | 22 +++++-----
src/xmlrpc.c | 2
tests/virshtest.c | 6 +-
tests/xml2sexprtest.c | 2
tests/xmlrpctest.c | 2
20 files changed, 177 insertions(+), 175 deletions(-)
Dan.
Index: proxy/libvirt_proxy.c
===================================================================
RCS file: /data/cvs/libvirt/proxy/libvirt_proxy.c,v
retrieving revision 1.33
diff -u -p -u -p -r1.33 libvirt_proxy.c
--- proxy/libvirt_proxy.c 24 Apr 2008 09:17:29 -0000 1.33
+++ proxy/libvirt_proxy.c 9 May 2008 21:08:07 -0000
@@ -802,9 +802,9 @@ int main(int argc, char **argv) {
}
for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "-v")) {
+ if (STREQ(argv[i], "-v")) {
debug++;
- } else if (!strcmp(argv[i], "-no-timeout")) {
+ } else if (STREQ(argv[i], "-no-timeout")) {
persist = 1;
} else {
usage(argv[0]);
Index: src/conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/conf.c,v
retrieving revision 1.26
diff -u -p -u -p -r1.26 conf.c
--- src/conf.c 28 Apr 2008 15:14:59 -0000 1.26
+++ src/conf.c 9 May 2008 21:08:08 -0000
@@ -800,7 +800,7 @@ __virConfGetValue(virConfPtr conf, const
cur = conf->entries;
while (cur != NULL) {
- if ((cur->name != NULL) && (!strcmp(cur->name, setting)))
+ if ((cur->name != NULL) && (STREQ(cur->name, setting)))
return(cur->value);
cur = cur->next;
}
@@ -829,7 +829,7 @@ __virConfSetValue (virConfPtr conf,
cur = conf->entries;
while (cur != NULL) {
- if ((cur->name != NULL) && (!strcmp(cur->name, setting))) {
+ if ((cur->name != NULL) && (STREQ(cur->name, setting))) {
break;
}
prev = cur;
Index: src/hash.c
===================================================================
RCS file: /data/cvs/libvirt/src/hash.c,v
retrieving revision 1.39
diff -u -p -u -p -r1.39 hash.c
--- src/hash.c 29 Apr 2008 13:48:41 -0000 1.39
+++ src/hash.c 9 May 2008 21:08:08 -0000
@@ -270,11 +270,11 @@ virHashAddEntry(virHashTablePtr table, c
} else {
for (insert = &(table->table[key]); insert->next != NULL;
insert = insert->next) {
- if (!strcmp(insert->name, name))
+ if (STREQ(insert->name, name))
return (-1);
len++;
}
- if (!strcmp(insert->name, name))
+ if (STREQ(insert->name, name))
return (-1);
}
@@ -335,14 +335,14 @@ virHashUpdateEntry(virHashTablePtr table
} else {
for (insert = &(table->table[key]); insert->next != NULL;
insert = insert->next) {
- if (!strcmp(insert->name, name)) {
+ if (STREQ(insert->name, name)) {
if (f)
f(insert->payload, insert->name);
insert->payload = userdata;
return (0);
}
}
- if (!strcmp(insert->name, name)) {
+ if (STREQ(insert->name, name)) {
if (f)
f(insert->payload, insert->name);
insert->payload = userdata;
@@ -393,7 +393,7 @@ virHashLookup(virHashTablePtr table, con
if (table->table[key].valid == 0)
return (NULL);
for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
- if (!strcmp(entry->name, name))
+ if (STREQ(entry->name, name))
return (entry->payload);
}
return (NULL);
@@ -445,7 +445,7 @@ virHashRemoveEntry(virHashTablePtr table
} else {
for (entry = &(table->table[key]); entry != NULL;
entry = entry->next) {
- if (!strcmp(entry->name, name)) {
+ if (STREQ(entry->name, name)) {
if ((f != NULL) && (entry->payload != NULL))
f(entry->payload, entry->name);
entry->payload = NULL;
Index: src/iptables.c
===================================================================
RCS file: /data/cvs/libvirt/src/iptables.c,v
retrieving revision 1.26
diff -u -p -u -p -r1.26 iptables.c
--- src/iptables.c 10 Apr 2008 16:53:29 -0000 1.26
+++ src/iptables.c 9 May 2008 21:08:08 -0000
@@ -114,7 +114,7 @@ stripLine(char *str, int len, const char
s = str;
while ((p = strchr(s, '\n'))) {
- if (p == s || strncmp(s, line, p - s) != 0) {
+ if (p == s || STRNEQLEN(s, line, p - s)) {
s = ++p;
continue;
}
@@ -125,7 +125,7 @@ stripLine(char *str, int len, const char
changed = 1;
}
- if (strcmp(s, line) == 0) {
+ if (STREQ(s, line)) {
*s = '\0';
changed = 1;
}
@@ -310,7 +310,7 @@ iptRulesRemove(iptRules *rules,
int i;
for (i = 0; i < rules->nrules; i++)
- if (!strcmp(rules->rules[i].rule, rule))
+ if (STREQ(rules->rules[i].rule, rule))
break;
if (i >= rules->nrules)
Index: src/libvirt.c
===================================================================
RCS file: /data/cvs/libvirt/src/libvirt.c,v
retrieving revision 1.137
diff -u -p -u -p -r1.137 libvirt.c
--- src/libvirt.c 10 Apr 2008 16:54:54 -0000 1.137
+++ src/libvirt.c 9 May 2008 21:08:08 -0000
@@ -644,7 +644,7 @@ virGetVersion(unsigned long *libVer, con
type = "Xen";
for (i = 0;i < virDriverTabCount;i++) {
if ((virDriverTab[i] != NULL) &&
- (!strcasecmp(virDriverTab[i]->name, type))) {
+ (STRCASEEQ(virDriverTab[i]->name, type))) {
*typeVer = virDriverTab[i]->ver;
break;
}
@@ -710,7 +710,7 @@ do_open (const char *name,
}
/* Convert xen -> xen:/// for back compat */
- if (!strcasecmp(name, "xen"))
+ if (STRCASEEQ(name, "xen"))
name = "xen:///";
/* Convert xen:// -> xen:/// because xmlParseURI cannot parse the
Index: src/openvz_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/openvz_conf.c,v
retrieving revision 1.22
diff -u -p -u -p -r1.22 openvz_conf.c
--- src/openvz_conf.c 10 Apr 2008 16:54:54 -0000 1.22
+++ src/openvz_conf.c 9 May 2008 21:08:08 -0000
@@ -107,7 +107,7 @@ struct openvz_vm
struct openvz_vm *vm = driver->vms;
while (vm) {
- if (!strcmp(vm->vmdef->name, name))
+ if (STREQ(vm->vmdef->name, name))
return vm;
vm = vm->next;
}
@@ -324,7 +324,7 @@ static struct openvz_vm_def
goto bail_out;
}
- if (strcmp((char *)prop, "openvz")){
+ if (STRNEQ((char *)prop, "openvz")){
error(conn, VIR_ERR_INTERNAL_ERROR, _("invalid domain type attribute"));
goto bail_out;
}
@@ -553,7 +553,7 @@ openvzGetVPSInfo(virConnectPtr conn) {
_("Failed to parse vzlist output"));
goto error;
}
- if(strcmp(status, "stopped")) {
+ if(STRNEQ(status, "stopped")) {
(*pnext)->status = VIR_DOMAIN_RUNNING;
driver->num_active ++;
(*pnext)->vpsid = veid;
@@ -673,7 +673,7 @@ openvzGetVPSUUID(int vpsid, char *uuidst
}
sscanf(line, "%s %s\n", iden, uuidbuf);
- if(!strcmp(iden, "#UUID:")) {
+ if(STREQ(iden, "#UUID:")) {
strncpy(uuidstr, uuidbuf, VIR_UUID_STRING_BUFLEN);
break;
}
@@ -747,7 +747,7 @@ int openvzAssignUUIDs(void)
while((dent = readdir(dp))) {
res = sscanf(dent->d_name, "%d.%5s", &vpsid, ext);
- if(!(res == 2 && !strcmp(ext, "conf")))
+ if(!(res == 2 && STREQ(ext, "conf")))
continue;
if(vpsid > 0) /* '0.conf' belongs to the host, ignore it */
openvzSetUUID(vpsid);
Index: src/qemu_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_conf.c,v
retrieving revision 1.55
diff -u -p -u -p -r1.55 qemu_conf.c
--- src/qemu_conf.c 9 May 2008 16:41:20 -0000 1.55
+++ src/qemu_conf.c 9 May 2008 21:08:08 -0000
@@ -166,7 +166,7 @@ struct qemud_vm *qemudFindVMByName(const
struct qemud_vm *vm = driver->vms;
while (vm) {
- if (!strcmp(vm->def->name, name))
+ if (STREQ(vm->def->name, name))
return vm;
vm = vm->next;
}
@@ -192,7 +192,7 @@ struct qemud_network *qemudFindNetworkBy
struct qemud_network *network = driver->networks;
while (network) {
- if (!strcmp(network->def->name, name))
+ if (STREQ(network->def->name, name))
return network;
network = network->next;
}
@@ -644,30 +644,30 @@ static int qemudParseDiskXML(virConnectP
}
if (device &&
- !strcmp((const char *)device, "floppy") &&
- strcmp((const char *)target, "fda") &&
- strcmp((const char *)target, "fdb")) {
+ STREQ((const char *)device, "floppy") &&
+ STRNEQ((const char *)target, "fda") &&
+ STRNEQ((const char *)target, "fdb")) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("Invalid floppy device name: %s"), target);
goto error;
}
if (device &&
- !strcmp((const char *)device, "cdrom") &&
- strcmp((const char *)target, "hdc")) {
+ STREQ((const char *)device, "cdrom") &&
+ STRNEQ((const char *)target, "hdc")) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("Invalid cdrom device name: %s"), target);
goto error;
}
if (device &&
- !strcmp((const char *)device, "cdrom"))
+ STREQ((const char *)device, "cdrom"))
disk->readonly = 1;
- if ((!device || !strcmp((const char *)device, "disk")) &&
- strncmp((const char *)target, "hd", 2) &&
- strncmp((const char *)target, "sd", 2) &&
- strncmp((const char *)target, "vd", 2)) {
+ if ((!device || STREQ((const char *)device, "disk")) &&
+ !STRPREFIX((const char *)target, "hd") &&
+ !STRPREFIX((const char *)target, "sd") &&
+ !STRPREFIX((const char *)target, "vd")) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("Invalid harddisk device name: %s"), target);
goto error;
@@ -682,11 +682,11 @@ static int qemudParseDiskXML(virConnectP
if (!device)
disk->device = QEMUD_DISK_DISK;
- else if (!strcmp((const char *)device, "disk"))
+ else if (STREQ((const char *)device, "disk"))
disk->device = QEMUD_DISK_DISK;
- else if (!strcmp((const char *)device, "cdrom"))
+ else if (STREQ((const char *)device, "cdrom"))
disk->device = QEMUD_DISK_CDROM;
- else if (!strcmp((const char *)device, "floppy"))
+ else if (STREQ((const char *)device, "floppy"))
disk->device = QEMUD_DISK_FLOPPY;
else {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
@@ -1376,9 +1376,9 @@ static int qemudParseInputXML(virConnect
goto error;
}
- if (!strcmp((const char *)type, "mouse")) {
+ if (STREQ((const char *)type, "mouse")) {
input->type = QEMU_INPUT_TYPE_MOUSE;
- } else if (!strcmp((const char *)type, "tablet")) {
+ } else if (STREQ((const char *)type, "tablet")) {
input->type = QEMU_INPUT_TYPE_TABLET;
} else {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
@@ -1388,7 +1388,7 @@ static int qemudParseInputXML(virConnect
}
if (bus) {
- if (!strcmp((const char*)bus, "ps2")) { /* Only allow mouse */
+ if (STREQ((const char*)bus, "ps2")) { /* Only allow mouse */
if (input->type == QEMU_INPUT_TYPE_TABLET) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("ps2 bus does not support %s input device"),
@@ -1396,7 +1396,7 @@ static int qemudParseInputXML(virConnect
goto error;
}
input->bus = QEMU_INPUT_BUS_PS2;
- } else if (!strcmp((const char *)bus, "usb")) { /* Allow mouse & keyboard */
+ } else if (STREQ((const char *)bus, "usb")) { /* Allow mouse & keyboard */
input->bus = QEMU_INPUT_BUS_USB;
} else {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
@@ -1537,11 +1537,11 @@ static struct qemud_vm_def *qemudParseXM
goto error;
}
- if (!strcmp((char *)prop, "qemu"))
+ if (STREQ((char *)prop, "qemu"))
def->virtType = QEMUD_VIRT_QEMU;
- else if (!strcmp((char *)prop, "kqemu"))
+ else if (STREQ((char *)prop, "kqemu"))
def->virtType = QEMUD_VIRT_KQEMU;
- else if (!strcmp((char *)prop, "kvm"))
+ else if (STREQ((char *)prop, "kvm"))
def->virtType = QEMUD_VIRT_KVM;
else {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
@@ -1654,7 +1654,7 @@ static struct qemud_vm_def *qemudParseXM
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
def->noReboot = 0;
} else {
- if (!strcmp((char*)obj->stringval, "destroy"))
+ if (STREQ((char*)obj->stringval, "destroy"))
def->noReboot = 1;
else
def->noReboot = 0;
@@ -1667,7 +1667,7 @@ static struct qemud_vm_def *qemudParseXM
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
def->localtime = 0;
} else {
- if (!strcmp((char*)obj->stringval, "localtime"))
+ if (STREQ((char*)obj->stringval, "localtime"))
def->localtime = 1;
else
def->localtime = 0;
@@ -1791,13 +1791,13 @@ static struct qemud_vm_def *qemudParseXM
for (i = 0; i < obj->nodesetval->nodeNr && i < QEMUD_MAX_BOOT_DEVS ; i++) {
if (!(prop = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "dev")))
continue;
- if (!strcmp((char *)prop, "hd")) {
+ if (STREQ((char *)prop, "hd")) {
def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_DISK;
- } else if (!strcmp((char *)prop, "fd")) {
+ } else if (STREQ((char *)prop, "fd")) {
def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_FLOPPY;
- } else if (!strcmp((char *)prop, "cdrom")) {
+ } else if (STREQ((char *)prop, "cdrom")) {
def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_CDROM;
- } else if (!strcmp((char *)prop, "network")) {
+ } else if (STREQ((char *)prop, "network")) {
def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_NET;
} else {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
@@ -1849,7 +1849,7 @@ static struct qemud_vm_def *qemudParseXM
(obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0)) {
def->graphicsType = QEMUD_GRAPHICS_NONE;
} else if ((prop = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "type"))) {
- if (!strcmp((char *)prop, "vnc")) {
+ if (STREQ((char *)prop, "vnc")) {
xmlChar *vncport, *vnclisten;
def->graphicsType = QEMUD_GRAPHICS_VNC;
vncport = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "port");
@@ -1868,7 +1868,7 @@ static struct qemud_vm_def *qemudParseXM
def->keymap = (char *) xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "keymap");
xmlFree(vncport);
xmlFree(vnclisten);
- } else if (!strcmp((char *)prop, "sdl")) {
+ } else if (STREQ((char *)prop, "sdl")) {
def->graphicsType = QEMUD_GRAPHICS_SDL;
} else {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
@@ -2318,7 +2318,7 @@ int qemudBuildCommandLine(virConnectPtr
* 3. The qemu binary has the -no-kqemu flag
*/
if ((vm->qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) &&
- !strcmp(ut.machine, vm->def->os.arch) &&
+ STREQ(ut.machine, vm->def->os.arch) &&
vm->def->virtType == QEMUD_VIRT_QEMU)
disableKQEMU = 1;
Index: src/remote_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/remote_internal.c,v
retrieving revision 1.71
diff -u -p -u -p -r1.71 remote_internal.c
--- src/remote_internal.c 1 May 2008 18:11:03 -0000 1.71
+++ src/remote_internal.c 9 May 2008 21:08:09 -0000
@@ -316,15 +316,15 @@ doRemoteOpen (virConnectPtr conn,
trans_tcp,
} transport;
- if (!transport_str || strcasecmp (transport_str, "tls") == 0)
+ if (!transport_str || STRCASEEQ (transport_str, "tls"))
transport = trans_tls;
- else if (strcasecmp (transport_str, "unix") == 0)
+ else if (STRCASEEQ (transport_str, "unix"))
transport = trans_unix;
- else if (strcasecmp (transport_str, "ssh") == 0)
+ else if (STRCASEEQ (transport_str, "ssh"))
transport = trans_ssh;
- else if (strcasecmp (transport_str, "ext") == 0)
+ else if (STRCASEEQ (transport_str, "ext"))
transport = trans_ext;
- else if (strcasecmp (transport_str, "tcp") == 0)
+ else if (STRCASEEQ (transport_str, "tcp"))
transport = trans_tcp;
else {
error (conn, VIR_ERR_INVALID_ARG,
Index: src/sexpr.c
===================================================================
RCS file: /data/cvs/libvirt/src/sexpr.c,v
retrieving revision 1.19
diff -u -p -u -p -r1.19 sexpr.c
--- src/sexpr.c 9 May 2008 13:50:14 -0000 1.19
+++ src/sexpr.c 9 May 2008 21:08:09 -0000
@@ -433,7 +433,7 @@ sexpr_lookup_key(const struct sexpr *sex
return NULL;
}
- if (strcmp(sexpr->u.s.car->u.value, token) != 0) {
+ if (STRNEQ(sexpr->u.s.car->u.value, token)) {
return NULL;
}
@@ -451,7 +451,7 @@ sexpr_lookup_key(const struct sexpr *sex
continue;
}
- if (strcmp(i->u.s.car->u.s.car->u.value, token) == 0) {
+ if (STREQ(i->u.s.car->u.s.car->u.value, token)) {
sexpr = i->u.s.car;
break;
}
Index: src/test.c
===================================================================
RCS file: /data/cvs/libvirt/src/test.c,v
retrieving revision 1.73
diff -u -p -u -p -r1.73 test.c
--- src/test.c 28 Apr 2008 15:14:59 -0000 1.73
+++ src/test.c 9 May 2008 21:08:09 -0000
@@ -196,13 +196,13 @@ testError(virConnectPtr con,
}
static int testRestartStringToFlag(const char *str) {
- if (!strcmp(str, "restart")) {
+ if (STREQ(str, "restart")) {
return VIR_DOMAIN_RESTART;
- } else if (!strcmp(str, "destroy")) {
+ } else if (STREQ(str, "destroy")) {
return VIR_DOMAIN_DESTROY;
- } else if (!strcmp(str, "preserve")) {
+ } else if (STREQ(str, "preserve")) {
return VIR_DOMAIN_PRESERVE;
- } else if (!strcmp(str, "rename-restart")) {
+ } else if (STREQ(str, "rename-restart")) {
return VIR_DOMAIN_RENAME_RESTART;
} else {
return (0);
@@ -914,7 +914,7 @@ static int testOpen(virConnectPtr conn,
if (!uri)
return VIR_DRV_OPEN_DECLINED;
- if (!uri->scheme || strcmp(uri->scheme, "test") != 0)
+ if (!uri->scheme || STRNEQ(uri->scheme, "test"))
return VIR_DRV_OPEN_DECLINED;
/* Remote driver should handle these. */
@@ -1170,7 +1170,7 @@ static virDomainPtr testLookupDomainByNa
for (i = 0 ; i < MAX_DOMAINS ; i++) {
if (privconn->domains[i].active &&
- strcmp(name, privconn->domains[i].name) == 0) {
+ STREQ(name, privconn->domains[i].name)) {
idx = i;
break;
}
@@ -1767,7 +1767,7 @@ static virNetworkPtr testLookupNetworkBy
for (i = 0 ; i < MAX_NETWORKS ; i++) {
if (privconn->networks[i].active &&
- strcmp(name, privconn->networks[i].name) == 0) {
+ STREQ(name, privconn->networks[i].name)) {
idx = i;
break;
}
Index: src/util.c
===================================================================
RCS file: /data/cvs/libvirt/src/util.c,v
retrieving revision 1.36
diff -u -p -u -p -r1.36 util.c
--- src/util.c 9 May 2008 16:41:20 -0000 1.36
+++ src/util.c 9 May 2008 21:08:09 -0000
@@ -384,8 +384,8 @@ int virFileMatchesNameSuffix(const char
int suffixlen = strlen(suffix);
if (filelen == (namelen + suffixlen) &&
- !strncmp(file, name, namelen) &&
- !strncmp(file + namelen, suffix, suffixlen))
+ STREQLEN(file, name, namelen) &&
+ STREQLEN(file + namelen, suffix, suffixlen))
return 1;
else
return 0;
@@ -400,7 +400,7 @@ int virFileHasSuffix(const char *str,
if (len < suffixlen)
return 0;
- return strcmp(str + len - suffixlen, suffix) == 0;
+ return STREQ(str + len - suffixlen, suffix);
}
#ifndef __MINGW32__
@@ -479,7 +479,7 @@ int virFileLinkPointsTo(const char *chec
}
/* compare */
- if (strcmp(checkReal, real) != 0) {
+ if (STRNEQ(checkReal, real)) {
virLog("Link '%s' does not point to '%s', ignoring",
checkLink, checkReal);
return 0;
Index: src/virsh.c
===================================================================
RCS file: /data/cvs/libvirt/src/virsh.c,v
retrieving revision 1.149
diff -u -p -u -p -r1.149 virsh.c
--- src/virsh.c 9 May 2008 13:50:14 -0000 1.149
+++ src/virsh.c 9 May 2008 21:08:09 -0000
@@ -4351,7 +4351,7 @@ cmdVNCDisplay(vshControl * ctl, vshCmd *
obj = xmlXPathEval(BAD_CAST "string(/domain/devices/graphics[@type='vnc']/@listen)", ctxt);
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
(obj->stringval == NULL) || (obj->stringval[0] == 0) ||
- !strcmp((const char*)obj->stringval, "0.0.0.0")) {
+ STREQ((const char*)obj->stringval, "0.0.0.0")) {
vshPrint(ctl, ":%d\n", port-5900);
} else {
vshPrint(ctl, "%s:%d\n", (const char *)obj->stringval, port-5900);
@@ -4587,9 +4587,9 @@ cmdAttachInterface(vshControl * ctl, vsh
script = vshCommandOptString(cmd, "script", NULL);
/* check interface type */
- if (strcmp(type, "network") == 0) {
+ if (STREQ(type, "network")) {
typ = 1;
- } else if (strcmp(type, "bridge") == 0) {
+ } else if (STREQ(type, "bridge")) {
typ = 2;
} else {
vshError(ctl, FALSE, _("No support %s in command 'attach-interface'"), type);
@@ -4824,23 +4824,23 @@ cmdAttachDisk(vshControl * ctl, vshCmd *
mode = vshCommandOptString(cmd, "mode", NULL);
if (type) {
- if (strcmp(type, "cdrom") && strcmp(type, "disk")) {
+ if (STRNEQ(type, "cdrom") && STRNEQ(type, "disk")) {
vshError(ctl, FALSE, _("No support %s in command 'attach-disk'"), type);
goto cleanup;
}
}
if (driver) {
- if (!strcmp(driver, "file") || !strcmp(driver, "tap")) {
+ if (STREQ(driver, "file") || STREQ(driver, "tap")) {
isFile = 1;
- } else if (strcmp(driver, "phy")) {
+ } else if (STRNEQ(driver, "phy")) {
vshError(ctl, FALSE, _("No support %s in command 'attach-disk'"), driver);
goto cleanup;
}
}
if (mode) {
- if (strcmp(mode, "readonly") && strcmp(mode, "shareable")) {
+ if (STRNEQ(mode, "readonly") && STRNEQ(mode, "shareable")) {
vshError(ctl, FALSE, _("No support %s in command 'attach-disk'"), mode);
goto cleanup;
}
@@ -5171,7 +5171,7 @@ vshCmddefGetInfo(vshCmdDef * cmd, const
vshCmdInfo *info;
for (info = cmd->info; info && info->name; info++) {
- if (strcmp(info->name, name) == 0)
+ if (STREQ(info->name, name))
return info->data;
}
return NULL;
@@ -5183,7 +5183,7 @@ vshCmddefGetOption(vshCmdDef * cmd, cons
vshCmdOptDef *opt;
for (opt = cmd->opts; opt && opt->name; opt++)
- if (strcmp(opt->name, name) == 0)
+ if (STREQ(opt->name, name))
return opt;
return NULL;
}
@@ -5244,7 +5244,7 @@ vshCmddefSearch(const char *cmdname)
vshCmdDef *c;
for (c = commands; c->name; c++)
- if (strcmp(c->name, cmdname) == 0)
+ if (STREQ(c->name, cmdname))
return c;
return NULL;
}
@@ -5343,7 +5343,7 @@ vshCommandOpt(vshCmd * cmd, const char *
vshCmdOpt *opt = cmd->opts;
while (opt) {
- if (opt->def && strcmp(opt->def->name, name) == 0)
+ if (opt->def && STREQ(opt->def->name, name))
return opt;
opt = opt->next;
}
@@ -5617,7 +5617,7 @@ vshCommandRun(vshControl * ctl, vshCmd *
if (ctl->timing)
GETTIMEOFDAY(&after);
- if (strcmp(cmd->def->name, "quit") == 0) /* hack ... */
+ if (STREQ(cmd->def->name, "quit")) /* hack ... */
return ret;
if (ctl->timing)
@@ -6213,7 +6213,7 @@ vshReadlineCommandGenerator(const char *
*/
while ((name = commands[list_index].name)) {
list_index++;
- if (strncmp(name, text, len) == 0)
+ if (STREQLEN(name, text, len))
return vshStrdup(NULL, name);
}
@@ -6262,7 +6262,7 @@ vshReadlineOptionsGenerator(const char *
continue;
if (len > 2) {
- if (strncmp(name, text + 2, len - 2))
+ if (STRNEQLEN(name, text + 2, len - 2))
continue;
}
res = vshMalloc(NULL, strlen(name) + 3);
@@ -6435,7 +6435,7 @@ vshParseArgv(vshControl * ctl, int argc,
if (sz == 2 && *(last + 1) == o->val)
/* valid virsh short option */
valid = TRUE;
- else if (sz > 2 && strcmp(o->name, last + 2) == 0)
+ else if (sz > 2 && STREQ(o->name, last + 2))
/* valid virsh long option */
valid = TRUE;
}
Index: src/xen_unified.c
===================================================================
RCS file: /data/cvs/libvirt/src/xen_unified.c,v
retrieving revision 1.43
diff -u -p -u -p -r1.43 xen_unified.c
--- src/xen_unified.c 9 May 2008 08:17:19 -0000 1.43
+++ src/xen_unified.c 9 May 2008 21:08:09 -0000
@@ -245,8 +245,8 @@ xenUnifiedOpen (virConnectPtr conn, xmlU
/* Refuse any scheme which isn't "xen://" or "http://". */
if (uri->scheme &&
- strcasecmp(uri->scheme, "xen") != 0 &&
- strcasecmp(uri->scheme, "http") != 0)
+ STRCASENEQ(uri->scheme, "xen") &&
+ STRCASENEQ(uri->scheme, "http"))
return VIR_DRV_OPEN_DECLINED;
/* xmlParseURI will parse a naked string like "foo" as a URI with
@@ -258,7 +258,7 @@ xenUnifiedOpen (virConnectPtr conn, xmlU
return VIR_DRV_OPEN_DECLINED;
/* Refuse any xen:// URI with a server specified - allow remote to do it */
- if (uri->scheme && strcasecmp(uri->scheme, "xen") == 0 && uri->server)
+ if (uri->scheme && STRCASEEQ(uri->scheme, "xen") && uri->server)
return VIR_DRV_OPEN_DECLINED;
/* Allocate per-connection private data. */
Index: src/xend_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xend_internal.c,v
retrieving revision 1.189
diff -u -p -u -p -r1.189 xend_internal.c
--- src/xend_internal.c 9 May 2008 13:50:14 -0000 1.189
+++ src/xend_internal.c 9 May 2008 21:08:09 -0000
@@ -403,7 +403,7 @@ sreads(virConnectPtr xend, int fd, char
static int
istartswith(const char *haystack, const char *needle)
{
- return (strncasecmp(haystack, needle, strlen(needle)) == 0);
+ return STRCASEEQLEN(haystack, needle, strlen(needle));
}
@@ -426,7 +426,7 @@ xend_req(virConnectPtr xend, int fd, cha
int retcode = 0;
while (sreads(xend, fd, buffer, sizeof(buffer)) > 0) {
- if (strcmp(buffer, "\r\n") == 0)
+ if (STREQ(buffer, "\r\n"))
break;
if (istartswith(buffer, "Content-Length: "))
@@ -487,7 +487,7 @@ xend_get(virConnectPtr xend, const char
close(s);
if (((ret < 0) || (ret >= 300)) &&
- ((ret != 404) || (strncmp(path, "/xend/domain/", 13)))) {
+ ((ret != 404) || (STRNEQLEN(path, "/xend/domain/", 13)))) {
virXendError(xend, VIR_ERR_GET_FAILED, content);
}
@@ -1882,7 +1882,7 @@ xend_parse_sexp_desc(virConnectPtr conn,
/* There is a case without the uname to the CD-ROM device */
offset = strchr(dst, ':');
if (offset) {
- if (hvm && !strcmp( offset , ":cdrom")) {
+ if (hvm && STREQ( offset , ":cdrom")) {
isNoSrcCdrom = 1;
}
offset[0] = '\0';
@@ -1913,7 +1913,7 @@ xend_parse_sexp_desc(virConnectPtr conn,
src = offset + 1;
- if (!strcmp(drvName, "tap")) {
+ if (STREQ(drvName, "tap")) {
offset = strchr(src, ':');
if (!offset) {
virXendError(conn, VIR_ERR_INTERNAL_ERROR,
@@ -1936,23 +1936,23 @@ xend_parse_sexp_desc(virConnectPtr conn,
omnipotent, we can revisit this, perhaps stat()'ing
the src file in question */
isBlock = 0;
- } else if (!strcmp(drvName, "phy")) {
+ } else if (STREQ(drvName, "phy")) {
isBlock = 1;
- } else if (!strcmp(drvName, "file")) {
+ } else if (STREQ(drvName, "file")) {
isBlock = 0;
}
}
- if (!strncmp(dst, "ioemu:", 6))
+ if (STREQLEN(dst, "ioemu:", 6))
dst += 6;
/* New style disk config from Xen >= 3.0.3 */
if (xendConfigVersion > 1) {
offset = strrchr(dst, ':');
if (offset) {
- if (!strcmp(offset, ":cdrom")) {
+ if (STREQ(offset, ":cdrom")) {
cdrom = 1;
- } else if (!strcmp(offset, ":disk")) {
+ } else if (STREQ(offset, ":disk")) {
/* The default anyway */
} else {
/* Unknown, lets pretend its a disk too */
@@ -1993,9 +1993,9 @@ xend_parse_sexp_desc(virConnectPtr conn,
/* XXX should we force mode == r, if cdrom==1, or assume
xend has already done this ? */
- if ((mode != NULL) && (!strcmp(mode, "r")))
+ if ((mode != NULL) && (STREQ(mode, "r")))
virBufferAddLit(&buf, " <readonly/>\n");
- else if ((mode != NULL) && (!strcmp(mode, "w!")))
+ else if ((mode != NULL) && (STREQ(mode, "w!")))
virBufferAddLit(&buf, " <shareable/>\n");
virBufferAddLit(&buf, " </disk>\n");
@@ -2046,11 +2046,11 @@ xend_parse_sexp_desc(virConnectPtr conn,
* or for HVM guests in >= 3.0.5 */
tmp = sexpr_node(node, "device/vfb/type");
- if (tmp && !strcmp(tmp, "sdl")) {
+ if (tmp && STREQ(tmp, "sdl")) {
vfb = 1;
virBufferVSprintf(&buf, " <input type='mouse' bus='%s'/>\n", hvm ? "ps2": "xen");
virBufferAddLit(&buf, " <graphics type='sdl'/>\n");
- } else if (tmp && !strcmp(tmp, "vnc")) {
+ } else if (tmp && STREQ(tmp, "vnc")) {
int port = xenStoreDomainGetVNCPort(conn, domid);
const char *listenAddr = sexpr_node(node, "device/vfb/vnclisten");
const char *vncPasswd = NULL;
@@ -2109,9 +2109,9 @@ xend_parse_sexp_desc(virConnectPtr conn,
if (sexpr_lookup(node, "usbdevice")) {
tmp = sexpr_node(node, "usbdevice");
if (tmp && *tmp) {
- if (!strcmp(tmp, "tablet"))
+ if (STREQ(tmp, "tablet"))
virBufferAddLit(&buf, " <input type='tablet' bus='usb'/>\n");
- else if (!strcmp(tmp, "mouse"))
+ else if (STREQ(tmp, "mouse"))
virBufferAddLit(&buf, " <input type='mouse' bus='usb'/>\n");
}
}
@@ -2399,7 +2399,7 @@ sexpr_to_xend_topology(virConnectPtr con
goto parse_error;
cur++;
virSkipSpaces(&cur);
- if (!strncmp(cur, "no cpus", 7)) {
+ if (STREQLEN(cur, "no cpus", 7)) {
nb_cpus = 0;
for (cpu = 0; cpu < numCpus; cpu++)
cpuset[cpu] = 0;
@@ -3460,7 +3460,7 @@ xenDaemonDomainGetVcpus(virDomainPtr dom
for (s = root; s->kind == SEXPR_CONS; s = s->u.s.cdr) {
if ((s->u.s.car->kind == SEXPR_CONS) &&
(s->u.s.car->u.s.car->kind == SEXPR_VALUE) &&
- !strcmp(s->u.s.car->u.s.car->u.value, "vcpu")) {
+ STREQ(s->u.s.car->u.s.car->u.value, "vcpu")) {
t = s->u.s.car;
vcpu = ipt->number = sexpr_int(t, "vcpu/number");
if ((oln = sexpr_int(t, "vcpu/online")) != 0) {
@@ -3481,7 +3481,7 @@ xenDaemonDomainGetVcpus(virDomainPtr dom
for (t = t->u.s.cdr; t->kind == SEXPR_CONS; t = t->u.s.cdr)
if ((t->u.s.car->kind == SEXPR_CONS) &&
(t->u.s.car->u.s.car->kind == SEXPR_VALUE) &&
- !strcmp(t->u.s.car->u.s.car->u.value, "cpumap") &&
+ STREQ(t->u.s.car->u.s.car->u.value, "cpumap") &&
(t->u.s.car->u.s.cdr->kind == SEXPR_CONS)) {
for (t = t->u.s.car->u.s.cdr->u.s.car; t->kind == SEXPR_CONS; t = t->u.s.cdr)
if (t->u.s.car->kind == SEXPR_VALUE
@@ -3677,7 +3677,7 @@ xenDaemonAttachDevice(virDomainPtr domai
return (-1);
str = virDomainGetOSType(domain);
- if (strcmp(str, "linux"))
+ if (STREQ(str, "hvm"))
hvm = 1;
free(str);
sexpr = virParseXMLDevice(domain->conn, xml, hvm, priv->xendConfigVersion);
Index: src/xm_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xm_internal.c,v
retrieving revision 1.76
diff -u -p -u -p -r1.76 xm_internal.c
--- src/xm_internal.c 8 May 2008 14:41:56 -0000 1.76
+++ src/xm_internal.c 9 May 2008 21:08:10 -0000
@@ -304,7 +304,7 @@ static int xenXMConfigReaper(const void
is currently mapped as owner of a named domain. */
if (xenXMConfigGetString(entry->conf, "name", &olddomname) != -1) {
char *nameowner = (char *)virHashLookup(nameConfigMap, olddomname);
- if (nameowner && !strcmp(nameowner, key)) {
+ if (nameowner && STREQ(nameowner, key)) {
virHashRemoveEntry(nameConfigMap, olddomname, NULL);
}
}
@@ -353,19 +353,19 @@ static int xenXMConfigCacheRefresh (virC
*/
/* Like 'dot' files... */
- if (!strncmp(ent->d_name, ".", 1))
+ if (STREQLEN(ent->d_name, ".", 1))
continue;
/* ...and the XenD server config file */
- if (!strncmp(ent->d_name, XEND_CONFIG_FILE, strlen(XEND_CONFIG_FILE)))
+ if (STREQLEN(ent->d_name, XEND_CONFIG_FILE, strlen(XEND_CONFIG_FILE)))
continue;
/* ...and random PCI config cruft */
- if (!strncmp(ent->d_name, XEND_PCI_CONFIG_PREFIX, strlen(XEND_PCI_CONFIG_PREFIX)))
+ if (STREQLEN(ent->d_name, XEND_PCI_CONFIG_PREFIX, strlen(XEND_PCI_CONFIG_PREFIX)))
continue;
/* ...and the example domain configs */
- if (!strncmp(ent->d_name, XM_EXAMPLE_PREFIX, strlen(XM_EXAMPLE_PREFIX)))
+ if (STREQLEN(ent->d_name, XM_EXAMPLE_PREFIX, strlen(XM_EXAMPLE_PREFIX)))
continue;
/* ...and the QEMU networking script */
- if (!strncmp(ent->d_name, QEMU_IF_SCRIPT, strlen(QEMU_IF_SCRIPT)))
+ if (STREQLEN(ent->d_name, QEMU_IF_SCRIPT, strlen(QEMU_IF_SCRIPT)))
continue;
/* ...and editor backups */
@@ -401,7 +401,7 @@ static int xenXMConfigCacheRefresh (virC
re-acquire it later - just in case it was renamed */
if (xenXMConfigGetString(entry->conf, "name", &olddomname) != -1) {
char *nameowner = (char *)virHashLookup(nameConfigMap, olddomname);
- if (nameowner && !strcmp(nameowner, path)) {
+ if (nameowner && STREQ(nameowner, path)) {
virHashRemoveEntry(nameConfigMap, olddomname, NULL);
}
}
@@ -607,7 +607,7 @@ char *xenXMDomainFormatXML(virConnectPtr
virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr);
if ((xenXMConfigGetString(conf, "builder", &str) == 0) &&
- !strcmp(str, "hvm"))
+ STREQ(str, "hvm"))
hvm = 1;
if (hvm) {
@@ -778,7 +778,7 @@ char *xenXMDomainFormatXML(virConnectPtr
}
/* And the source driver sub-type */
- if (!strncmp(drvName, "tap", 3)) {
+ if (STREQLEN(drvName, "tap", 3)) {
if (!(tmp1 = strchr(tmp+1, ':')) || !tmp1[0])
goto skipdisk;
strncpy(drvType, tmp+1, (tmp1-(tmp+1)));
@@ -790,18 +790,18 @@ char *xenXMDomainFormatXML(virConnectPtr
}
/* phy: type indicates a block device */
- if (!strcmp(drvName, "phy")) {
+ if (STREQ(drvName, "phy")) {
block = 1;
}
/* Remove legacy ioemu: junk */
- if (!strncmp(dev, "ioemu:", 6)) {
+ if (STREQLEN(dev, "ioemu:", 6)) {
memmove(dev, dev+6, strlen(dev)-5);
}
/* Check for a :cdrom/:disk postfix */
if ((tmp = strchr(dev, ':')) != NULL) {
- if (!strcmp(tmp, ":cdrom"))
+ if (STREQ(tmp, ":cdrom"))
cdrom = 1;
tmp[0] = '\0';
}
@@ -824,11 +824,11 @@ char *xenXMDomainFormatXML(virConnectPtr
if (src[0])
virBufferVSprintf(&buf, " <source %s='%s'/>\n", block ? "dev" : "file", src);
virBufferVSprintf(&buf, " <target dev='%s' bus='%s'/>\n", dev, bus);
- if (!strcmp(head, "r") ||
- !strcmp(head, "ro"))
+ if (STREQ(head, "r") ||
+ STREQ(head, "ro"))
virBufferAddLit(&buf, " <readonly/>\n");
- else if ((!strcmp(head, "w!")) ||
- (!strcmp(head, "!")))
+ else if ((STREQ(head, "w!")) ||
+ (STREQ(head, "!")))
virBufferAddLit(&buf, " <shareable/>\n");
virBufferAddLit(&buf, " </disk>\n");
@@ -878,32 +878,32 @@ char *xenXMDomainFormatXML(virConnectPtr
goto skipnic;
data++;
- if (!strncmp(key, "mac=", 4)) {
+ if (STRPREFIX(key, "mac=")) {
int len = nextkey ? (nextkey - data) : 17;
if (len > 17)
len = 17;
strncpy(mac, data, len);
mac[len] = '\0';
- } else if (!strncmp(key, "bridge=", 7)) {
+ } else if (STRPREFIX(key, "bridge=")) {
int len = nextkey ? (nextkey - data) : sizeof(bridge)-1;
type = 1;
if (len > (sizeof(bridge)-1))
len = sizeof(bridge)-1;
strncpy(bridge, data, len);
bridge[len] = '\0';
- } else if (!strncmp(key, "script=", 7)) {
+ } else if (STRPREFIX(key, "script=")) {
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, "model=", 6)) {
+ } else if (STRPREFIX(key, "model=")) {
int len = nextkey ? (nextkey - data) : sizeof(model)-1;
if (len > (sizeof(model)-1))
len = sizeof(model)-1;
strncpy(model, data, len);
model[len] = '\0';
- } else if (!strncmp(key, "ip=", 3)) {
+ } else if (STRPREFIX(key, "ip=")) {
int len = nextkey ? (nextkey - data) : 15;
if (len > 15)
len = 15;
@@ -943,9 +943,9 @@ char *xenXMDomainFormatXML(virConnectPtr
if (hvm) {
if (xenXMConfigGetString(conf, "usbdevice", &str) == 0 && str) {
- if (!strcmp(str, "tablet"))
+ if (STREQ(str, "tablet"))
virBufferAddLit(&buf, " <input type='tablet' bus='usb'/>\n");
- else if (!strcmp(str, "mouse"))
+ else if (STREQ(str, "mouse"))
virBufferAddLit(&buf, " <input type='mouse' bus='usb'/>\n");
/* Ignore else branch - probably some other non-input device we don't
support in libvirt yet */
@@ -993,19 +993,19 @@ char *xenXMDomainFormatXML(virConnectPtr
break;
data++;
- if (!strncmp(key, "type=sdl", 8)) {
+ if (STRPREFIX(key, "type=sdl")) {
sdl = 1;
- } else if (!strncmp(key, "type=vnc", 8)) {
+ } else if (STRPREFIX(key, "type=vnc")) {
vnc = 1;
- } else if (!strncmp(key, "vncunused=", 10)) {
+ } else if (STRPREFIX(key, "vncunused=")) {
vncunused = strtol(key+10, NULL, 10);
- } else if (!strncmp(key, "vnclisten=", 10)) {
+ } else if (STRPREFIX(key, "vnclisten=")) {
vnclisten = key + 10;
- } else if (!strncmp(key, "vncpasswd=", 10)) {
+ } else if (STRPREFIX(key, "vncpasswd=")) {
vncpasswd = key + 10;
- } else if (!strncmp(key, "keymap=", 7)) {
+ } else if (STRPREFIX(key, "keymap=")) {
keymap = key + 7;
- } else if (!strncmp(key, "vncdisplay=", 11)) {
+ } else if (STRPREFIX(key, "vncdisplay=")) {
vncdisplay = strtol(key+11, NULL, 10);
}
@@ -1682,7 +1682,7 @@ static int xenXMParseXMLDisk(xmlNodePtr
} else if ((drvName == NULL) &&
(xmlStrEqual(cur->name, BAD_CAST "driver"))) {
drvName = xmlGetProp(cur, BAD_CAST "name");
- if (drvName && !strcmp((const char *)drvName, "tap"))
+ if (drvName && STREQ((const char *)drvName, "tap"))
drvType = xmlGetProp(cur, BAD_CAST "type");
} else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
readonly = 1;
@@ -1704,7 +1704,7 @@ static int xenXMParseXMLDisk(xmlNodePtr
*/
if (hvm &&
device &&
- !strcmp((const char *)device, "floppy")) {
+ STREQ((const char *)device, "floppy")) {
ret = 0;
goto cleanup;
}
@@ -1712,7 +1712,7 @@ static int xenXMParseXMLDisk(xmlNodePtr
/* Xend <= 3.0.2 doesn't include cdrom config here */
if (hvm &&
device &&
- !strcmp((const char *)device, "cdrom")) {
+ STREQ((const char *)device, "cdrom")) {
if (xendConfigVersion == 1) {
ret = 0;
goto cleanup;
@@ -1729,7 +1729,7 @@ static int xenXMParseXMLDisk(xmlNodePtr
if (drvName) {
buflen += strlen((const char*)drvName) + 1;
- if (!strcmp((const char*)drvName, "tap")) {
+ if (STREQ((const char*)drvName, "tap")) {
if (drvType)
buflen += strlen((const char*)drvType) + 1;
else
@@ -1761,7 +1761,7 @@ static int xenXMParseXMLDisk(xmlNodePtr
if(source) {
if (drvName) {
strcpy(buf, (const char*)drvName);
- if (!strcmp((const char*)drvName, "tap")) {
+ if (STREQ((const char*)drvName, "tap")) {
strcat(buf, ":");
if (drvType)
strcat(buf, (const char*)drvType);
@@ -2024,7 +2024,7 @@ virConfPtr xenXMParseXMLToConfig(virConn
obj = xmlXPathEval(BAD_CAST "string(/domain/os/type)", ctxt);
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
- (obj->stringval != NULL) && !strcmp((char*)obj->stringval, "hvm"))
+ (obj->stringval != NULL) && STREQ((char*)obj->stringval, "hvm"))
hvm = 1;
xmlXPathFreeObject(obj);
@@ -2043,11 +2043,11 @@ virConfPtr xenXMParseXMLToConfig(virConn
obj = xmlXPathEval(BAD_CAST "string(/domain/os/boot/@dev)", ctxt);
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
(obj->stringval != NULL)) {
- if (!strcmp((const char*)obj->stringval, "fd"))
+ if (STREQ((const char*)obj->stringval, "fd"))
boot = "a";
- else if (!strcmp((const char*)obj->stringval, "hd"))
+ else if (STREQ((const char*)obj->stringval, "hd"))
boot = "c";
- else if (!strcmp((const char*)obj->stringval, "cdrom"))
+ else if (STREQ((const char*)obj->stringval, "cdrom"))
boot = "d";
}
xmlXPathFreeObject(obj);
@@ -2069,7 +2069,7 @@ virConfPtr xenXMParseXMLToConfig(virConn
obj = xmlXPathEval(BAD_CAST "string(/domain/clock/@offset)", ctxt);
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
(obj->stringval != NULL)) {
- if (!strcmp((const char*)obj->stringval, "localtime"))
+ if (STREQ((const char*)obj->stringval, "localtime"))
clockLocal = 1;
}
xmlXPathFreeObject(obj);
@@ -2173,15 +2173,15 @@ virConfPtr xenXMParseXMLToConfig(virConn
if (!(type = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "type"))) {
continue;
}
- if (!strcmp((const char*)type, "sdl")) {
+ if (STREQ((const char*)type, "sdl")) {
val = strdup("type=sdl");
- } else if (!strcmp((const char*)type, "vnc")) {
+ } else if (STREQ((const char*)type, "vnc")) {
int len = 8 + 1; /* type=vnc & NULL */
xmlChar *vncport = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "port");
xmlChar *vnclisten = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "listen");
xmlChar *vncpasswd = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "passwd");
xmlChar *keymap = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "keymap");
- int vncunused = vncport ? (!strcmp((const char*)vncport, "-1") ? 1 : 0) : 1;
+ int vncunused = vncport ? (STREQ((const char*)vncport, "-1") ? 1 : 0) : 1;
if (vncunused)
len += 12;
else
@@ -2743,9 +2743,9 @@ xenXMAttachDisk(virDomainPtr domain, xml
xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR);
goto cleanup;
}
- if (!strcmp((const char *) type, "block"))
+ if (STREQ((const char *) type, "block"))
source = xmlGetProp(node, BAD_CAST "dev");
- else if (!strcmp((const char *) type, "file"))
+ else if (STREQ((const char *) type, "file"))
source = xmlGetProp(node, BAD_CAST "file");
else {
xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR);
@@ -2788,7 +2788,7 @@ xenXMAttachDisk(virDomainPtr domain, xml
head = offset + 1;
/* Remove legacy ioemu: junk */
- if (!strncmp(domdev, "ioemu:", 6)) {
+ if (STRPREFIX(domdev, "ioemu:")) {
memmove(domdev, domdev+6, strlen(domdev)-5);
}
@@ -2796,7 +2796,7 @@ xenXMAttachDisk(virDomainPtr domain, xml
if ((tmp = strchr(domdev, ':')))
tmp[0] = '\0';
- if (!(strcmp(domdev, (const char *) target)))
+ if (STREQ(domdev, (const char *) target))
break;
skip:
prev = list_val;
@@ -2895,7 +2895,7 @@ xenXMAttachInterface(virDomainPtr domain
goto skip;
data++;
- if (!strncmp(key, "mac=", 4)) {
+ if (STRPREFIX(key, "mac=")) {
int len = nextkey ? (nextkey - data) : 17;
if (len > 17)
len = 17;
@@ -3114,7 +3114,7 @@ xenXMDomainDetachDevice(virDomainPtr dom
else if (list_ptr && list_ptr->type == VIR_CONF_LIST) {
list_val = list_ptr->list;
while (list_val) {
- if (!(strcmp(device, "disk"))) {
+ if (STREQ(device, "disk")) {
char domdev[NAME_MAX];
char *head;
char *offset;
@@ -3141,7 +3141,7 @@ xenXMDomainDetachDevice(virDomainPtr dom
head = offset + 1;
/* Remove legacy ioemu: junk */
- if (!strncmp(domdev, "ioemu:", 6)) {
+ if (STRPREFIX(domdev, "ioemu:")) {
memmove(domdev, domdev+6, strlen(domdev)-5);
}
@@ -3149,7 +3149,7 @@ xenXMDomainDetachDevice(virDomainPtr dom
if ((tmp = strchr(domdev, ':')))
tmp[0] = '\0';
- if (!(strcmp(domdev, (const char *) key)))
+ if (STREQ(domdev, (const char *) key))
break;
} else {
char dommac[18];
@@ -3169,7 +3169,7 @@ xenXMDomainDetachDevice(virDomainPtr dom
goto skip;
data++;
- if (!strncmp(mac, "mac=", 4)) {
+ if (STRPREFIX(mac, "mac=")) {
int len = nextmac ? (nextmac - data) : 17;
if (len > 17)
len = 17;
Index: src/xml.c
===================================================================
RCS file: /data/cvs/libvirt/src/xml.c,v
retrieving revision 1.123
diff -u -p -u -p -r1.123 xml.c
--- src/xml.c 7 May 2008 18:50:23 -0000 1.123
+++ src/xml.c 9 May 2008 21:08:10 -0000
@@ -1083,9 +1083,9 @@ virDomainParseXMLOSDescHVM(virConnectPtr
if (!itype) {
goto error;
}
- if (!strcmp((const char *) itype, "tablet"))
+ if (STREQ((const char *) itype, "tablet"))
isMouse = 0;
- else if (strcmp((const char *) itype, "mouse")) {
+ else if (STRNEQ((const char *) itype, "mouse")) {
xmlFree(itype);
virXMLError(conn, VIR_ERR_XML_ERROR,
_("invalid input device"), 0);
@@ -1101,7 +1101,7 @@ virDomainParseXMLOSDescHVM(virConnectPtr
virBufferAddLit(buf, "(usbdevice tablet)");
}
} else {
- if (!strcmp((const char *) bus, "ps2")) {
+ if (STREQ((const char *) bus, "ps2")) {
if (!isMouse) {
xmlFree(bus);
virXMLError(conn, VIR_ERR_XML_ERROR,
@@ -1109,7 +1109,7 @@ virDomainParseXMLOSDescHVM(virConnectPtr
goto error;
}
/* Nothing - implicit ps2 */
- } else if (!strcmp((const char *) bus, "usb")) {
+ } else if (STREQ((const char *) bus, "usb")) {
if (isMouse)
virBufferAddLit(buf, "(usbdevice mouse)");
else
@@ -1320,7 +1320,7 @@ virDomainParseXMLDiskDesc(virConnectPtr
} else if ((drvName == NULL) &&
(xmlStrEqual(cur->name, BAD_CAST "driver"))) {
drvName = xmlGetProp(cur, BAD_CAST "name");
- if (drvName && !strcmp((const char *) drvName, "tap"))
+ if (drvName && STREQ((const char *) drvName, "tap"))
drvType = xmlGetProp(cur, BAD_CAST "type");
} else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
ro = 1;
@@ -1335,7 +1335,7 @@ virDomainParseXMLDiskDesc(virConnectPtr
/* There is a case without the source
* to the CD-ROM device
*/
- if (hvm && device && !strcmp((const char *) device, "cdrom")) {
+ if (hvm && device && STREQ((const char *) device, "cdrom")) {
isNoSrcCdrom = 1;
}
if (!isNoSrcCdrom) {
@@ -1353,12 +1353,12 @@ virDomainParseXMLDiskDesc(virConnectPtr
/* Xend (all versions) put the floppy device config
* under the hvm (image (os)) block
*/
- if (hvm && device && !strcmp((const char *) device, "floppy")) {
+ if (hvm && device && STREQ((const char *) device, "floppy")) {
goto cleanup;
}
/* Xend <= 3.0.2 doesn't include cdrom config here */
- if (hvm && device && !strcmp((const char *) device, "cdrom")) {
+ if (hvm && device && STREQ((const char *) device, "cdrom")) {
if (xendConfigVersion == 1)
goto cleanup;
else
@@ -1370,7 +1370,7 @@ virDomainParseXMLDiskDesc(virConnectPtr
/* Normally disks are in a (device (vbd ...)) block
* but blktap disks ended up in a differently named
* (device (tap ....)) block.... */
- if (drvName && !strcmp((const char *) drvName, "tap")) {
+ if (drvName && STREQ((const char *) drvName, "tap")) {
virBufferAddLit(buf, "(tap ");
} else {
virBufferAddLit(buf, "(vbd ");
@@ -1380,7 +1380,7 @@ virDomainParseXMLDiskDesc(virConnectPtr
char *tmp = (char *) target;
/* Just in case user mistakenly still puts ioemu: in their XML */
- if (!strncmp((const char *) tmp, "ioemu:", 6))
+ if (STRPREFIX((const char *) tmp, "ioemu:"))
tmp += 6;
/* Xend <= 3.0.2 wants a ioemu: prefix on devices for HVM */
@@ -1393,7 +1393,7 @@ virDomainParseXMLDiskDesc(virConnectPtr
virBufferVSprintf(buf, "(dev '%s')", (const char *) target);
if (drvName && !isNoSrcCdrom) {
- if (!strcmp((const char *) drvName, "tap")) {
+ if (STREQ((const char *) drvName, "tap")) {
virBufferVSprintf(buf, "(uname '%s:%s:%s')",
(const char *) drvName,
(drvType ? (const char *) drvType : "aio"),
Index: src/xmlrpc.c
===================================================================
RCS file: /data/cvs/libvirt/src/xmlrpc.c,v
retrieving revision 1.14
diff -u -p -u -p -r1.14 xmlrpc.c
--- src/xmlrpc.c 28 Apr 2008 15:14:59 -0000 1.14
+++ src/xmlrpc.c 9 May 2008 21:08:10 -0000
@@ -429,7 +429,7 @@ static char *xmlRpcCallRaw(const char *u
goto error;
}
- if (contentType && strcmp(contentType, "text/xml") != 0) {
+ if (contentType && STRNEQ(contentType, "text/xml")) {
errno = EINVAL;
xmlRpcError(VIR_ERR_POST_FAILED, _("unexpected mime type"), 0);
goto error;
Index: tests/virshtest.c
===================================================================
RCS file: /data/cvs/libvirt/tests/virshtest.c,v
retrieving revision 1.11
diff -u -p -u -p -r1.11 virshtest.c
--- tests/virshtest.c 10 Apr 2008 16:54:54 -0000 1.11
+++ tests/virshtest.c 9 May 2008 21:08:10 -0000
@@ -52,8 +52,10 @@ static int testCompareOutput(const char
printf("Expect %d '%s'\n", (int)strlen(expectData), expectData);
printf("Actual %d '%s'\n", (int)strlen(actualData), actualData);
}
- if (strcmp(expectData, actualData))
- return -1;
+ if (STRNEQ(expectData, actualData)) {
+ virtTestDifference(stderr, expectData, actualData);
+ return -1;
+ }
return 0;
}
Index: tests/xml2sexprtest.c
===================================================================
RCS file: /data/cvs/libvirt/tests/xml2sexprtest.c,v
retrieving revision 1.27
diff -u -p -u -p -r1.27 xml2sexprtest.c
--- tests/xml2sexprtest.c 7 May 2008 14:04:41 -0000 1.27
+++ tests/xml2sexprtest.c 9 May 2008 21:08:10 -0000
@@ -43,7 +43,7 @@ static int testCompareFiles(const char *
goto fail;
}
- if (strcmp(name, gotname)) {
+ if (STRNEQ(name, gotname)) {
printf("Got wrong name: expected %s, got %s\n", name, gotname);
goto fail;
}
Index: tests/xmlrpctest.c
===================================================================
RCS file: /data/cvs/libvirt/tests/xmlrpctest.c,v
retrieving revision 1.12
diff -u -p -u -p -r1.12 xmlrpctest.c
--- tests/xmlrpctest.c 28 Apr 2008 15:14:59 -0000 1.12
+++ tests/xmlrpctest.c 9 May 2008 21:08:10 -0000
@@ -108,7 +108,7 @@ checkRequestValue(const char *xmlstr, co
break;
case XML_RPC_STRING:
if ((obj->type != XPATH_STRING) ||
- (strcmp((const char *)obj->stringval, (const char *)expected)))
+ (STRNEQ((const char *)obj->stringval, (const char *)expected)))
goto error;
break;
default:
--
|: Red Hat, Engineering, Boston -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 :|
2
8
[libvirt] [PATCH] exempt gnulib/ from "make syntax-check" strcmp prohibition
by Jim Meyering 14 May '08
by Jim Meyering 14 May '08
14 May '08
"make syntax-check" was failing. This fixed it:
exempt gnulib/ from "make syntax-check" strcmp prohibition
* .x-sc_prohibit_strcmp: New file.
* Makefile.am (EXTRA_DIST): Add .x-sc_prohibit_strcmp.
---
.x-sc_prohibit_strcmp | 1 +
Makefile.am | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
create mode 100644 .x-sc_prohibit_strcmp
diff --git a/.x-sc_prohibit_strcmp b/.x-sc_prohibit_strcmp
new file mode 100644
index 0000000..b7c456e
--- /dev/null
+++ b/.x-sc_prohibit_strcmp
@@ -0,0 +1 @@
+^gnulib/
diff --git a/Makefile.am b/Makefile.am
index e32033a..73552a4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,6 +10,7 @@ EXTRA_DIST = \
libvirt.pc libvirt.pc.in \
$(man_MANS) autobuild.sh \
.x-sc_avoid_if_before_free \
+ .x-sc_prohibit_strcmp \
.x-sc_require_config_h
man_MANS = virsh.1
--
1.5.5.1.216.g33c73
2
1
Libvirt currently returns '1' when asked for the maximum number of VCPUs
supported for KVM guests. KVM long long ago gained SMP support, so this
patch fixes it to return 16, whcih is the current supported number. I
don't bother trying to detect old versions of KVM which are UP only
because I find it hard to believe anyone will be using them.
qemu_driver.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
Dan.
diff -r b644023b5657 src/qemu_driver.c
--- a/src/qemu_driver.c Sat May 10 13:12:04 2008 -0400
+++ b/src/qemu_driver.c Sat May 10 13:12:18 2008 -0400
@@ -1572,10 +1572,8 @@
if (STRCASEEQ(type, "qemu"))
return 16;
- /* XXX future KVM will support SMP. Need to probe
- kernel to figure out KVM module version i guess */
if (STRCASEEQ(type, "kvm"))
- return 1;
+ return 16;
if (STRCASEEQ(type, "kqemu"))
return 1;
--
|: Red Hat, Engineering, Boston -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 :|
3
7
FYI, I've just checked in this change:
avoid "not a string literal..." warnings
* src/qemu_conf.c (qemudParseInterfaceXML): Add "%s".
(qemudBuildCommandLine, qemudGenerateXML): Likewise.
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index 2a29382..9772721 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -1006,7 +1006,7 @@ static int qemudParseInterfaceXML(virConnectPtr conn,
(model[i] >= 'a' && model[i] <= 'z') ||
(model[i] >= 'A' && model[i] <= 'Z') || model[i] == '_';
if (!char_ok) {
- qemudReportError (conn, NULL, NULL, VIR_ERR_INVALID_ARG,
+ qemudReportError (conn, NULL, NULL, VIR_ERR_INVALID_ARG, "%s",
_("Model name contains invalid characters"));
goto error;
}
@@ -2751,9 +2751,9 @@ int qemudBuildCommandLine(virConnectPtr conn,
while(sound && size > 0) {
const char *model = qemudSoundModelToString(sound->model);
if (!model) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("invalid sound model"));
- goto error;
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("invalid sound model"));
+ goto error;
}
strncat(modstr, model, size);
size -= strlen(model);
@@ -3988,7 +3988,7 @@ char *qemudGenerateXML(virConnectPtr conn,
const char *model = qemudSoundModelToString(sound->model);
if (!model) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("invalid sound model"));
+ "%s", _("invalid sound model"));
goto cleanup;
}
virBufferVSprintf(&buf, " <sound model='%s'/>\n", model);
--
1.5.5.1.212.g8559
1
0
We never really settled on the XML format for container network interfaces. I
know a little more about what these look like now and have been working on the
code so would like to get this sorted out.
With network namespaces enabled, processes within the container will not be able
to see any network devices outside of the container. A veth device pair will be
used to transport traffic into and out off the container. One end of the veth
pair will be attached to a bridge in the parent namespace. The other end of
will be moved into the container namespace. We need to be able to represent the
following in the XML:
Network or bridge name
Name for parent side veth device
Name for container side veth device
inet address for container side veth device
So this should end up looking quite a bit like the formats for Virtual network
and Bridge to LAN with a couple new items. The formats I've been kicking around
are:
Virtual network
<devices>
<interface type='network'>
<source network='default' dev='veth0'/>
<target dev='veth1' address='192.168.0.150'/>
</interface>
</devices>
Bridge to LAN
<devices>
<interface type='bridge'>
<source bridge='virbr0' dev='veth4'/>
<target dev='veth5' address='192.168.0.155'/>
</interface>
</devices>
All comments welcome.
Thanks!
--
Best Regards,
Dave Leskovec
IBM Linux Technology Center
Open Virtualization
4
6
Following up on this thread:
http://thread.gmane.org/gmane.comp.emulators.libvirt/6338/focus=6349
This change removes all uses of ctype macros and ensures
that no new ones will be added.
The other changes I mentioned will come later.
>From 3966a3ebaaacc14b4f330677fd2ed8f8546c6f4a Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering(a)redhat.com>
Date: Fri, 9 May 2008 12:55:29 +0200
Subject: [PATCH] Use gnulib's c-ctype.h, not <ctype.h>.
re=$(man isspace|grep is.....,.is|sed 's/ -.*//' \
|tr -s ', \n' \||sed 's/^|//;s/|$//')
git grep -l -E "$re"|grep -Ev 'Chan|gnulib' \
|xargs perl -pi -e 's/\b('"$re"')\b/c_$1/g'
git grep -l to_uchar|xargs perl -pi -e 's/to_uchar\((.*?)\)/$1/g'
* src/util.h (to_uchar): Remove definition.
(TOLOWER): Remove definition.
(__virMacAddrCompare): Use c_tolower, not TOLOWER.
Globally:
Where needed, change <ctype.h> to <c-ctype.h>.
Remove unnecessary inclusion of <ctype.h>.
Ensure the global changes are never needed again:
* Makefile.maint (sc_avoid_ctype_macros): Prohibit use of ctype
macros. Recommend c-ctype.h instead.
(sc_prohibit_c_ctype_without_use): New rule.
(sc_prohibit_ctype_h): New rule. Disallow use of <ctype.h>.
---
Makefile.maint | 16 +++++++++++++---
qemud/remote.c | 1 -
src/buf.c | 3 +--
src/nodeinfo.c | 12 ++++++------
src/openvz_driver.c | 1 -
src/qemu_driver.c | 4 ++--
src/sexpr.c | 4 ++--
src/stats_linux.c | 8 ++++----
src/util.c | 15 ++++++---------
src/util.h | 5 -----
src/virsh.c | 8 ++++----
src/xend_internal.c | 1 -
12 files changed, 38 insertions(+), 40 deletions(-)
diff --git a/Makefile.maint b/Makefile.maint
index bab8e1d..0f79ed7 100644
--- a/Makefile.maint
+++ b/Makefile.maint
@@ -157,6 +157,16 @@ sc_prohibit_quotearg_without_use:
sc_prohibit_quote_without_use:
@h='"quote.h"' re='\<quote(_n)? *\(' $(_header_without_use)
+# Prohibit the inclusion of c-ctype.h without an actual use.
+sc_prohibit_c_ctype_without_use:
+ @h='[<"]c-ctype.h[">]' re='\<c_($(ctype_re)) *\(' $(_header_without_use)
+
+# Prohibit the inclusion of <ctype.h>.
+sc_prohibit_ctype_h:
+ @grep -E '^# *include *<ctype\.h>' $$($(VC_LIST_EXCEPT)) && \
+ { echo "$(ME): don't use ctype.h; instead, use c-ctype.h" \
+ 1>&2; exit 1; } || :
+
sc_obsolete_symbols:
@grep -nE '\<(HAVE''_FCNTL_H|O''_NDELAY)\>' \
$$($(VC_LIST_EXCEPT)) && \
@@ -305,10 +315,10 @@ sc_TAB_in_indentation:
ctype_re = isalnum|isalpha|isascii|isblank|iscntrl|isdigit|isgraph|islower\
|isprint|ispunct|isspace|isupper|isxdigit|tolower|toupper
-sc_risky_ctype_macros:
+sc_avoid_ctype_macros:
@grep -E '\b($(ctype_re)) *\(' /dev/null \
- $$($(VC_LIST_EXCEPT)) | grep -v to_uchar && \
- { echo '$(ME): found ctype macro use without to_uchar' \
+ $$($(VC_LIST_EXCEPT)) && \
+ { echo "$(ME): don't use ctype macros (use c-ctype.h)" \
1>&2; exit 1; } || :
# Match lines like the following, but where there is only one space
diff --git a/qemud/remote.c b/qemud/remote.c
index e249529..22dd86e 100644
--- a/qemud/remote.c
+++ b/qemud/remote.c
@@ -41,7 +41,6 @@
#include <syslog.h>
#include <string.h>
#include <errno.h>
-#include <ctype.h>
#include <fnmatch.h>
#ifdef HAVE_POLKIT
diff --git a/src/buf.c b/src/buf.c
index 2e17fbb..b56a9c1 100644
--- a/src/buf.c
+++ b/src/buf.c
@@ -1,7 +1,7 @@
/*
* buf.c: buffers for libvirt
*
- * Copyright (C) 2005-2007 Red Hat, Inc.
+ * Copyright (C) 2005-2008 Red Hat, Inc.
*
* See COPYING.LIB for the License of this software
*
@@ -16,7 +16,6 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
-#include <ctype.h>
#define __VIR_BUFFER_C__
diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index c1e8013..e227c69 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -27,7 +27,7 @@
#include <string.h>
#include <stdlib.h>
#include <errno.h>
-#include <ctype.h>
+#include <c-ctype.h>
#ifdef HAVE_SYS_UTSNAME_H
#include <sys/utsname.h>
@@ -59,7 +59,7 @@ int linuxNodeInfoCPUPopulate(virConnectPtr conn, FILE *cpuinfo, virNodeInfoPtr n
char *buf = line;
if (STREQLEN(buf, "processor", 9)) { /* aka a single logical CPU */
buf += 9;
- while (*buf && isspace(to_uchar(*buf)))
+ while (*buf && c_isspace(*buf))
buf++;
if (*buf != ':') {
__virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR,
@@ -72,7 +72,7 @@ int linuxNodeInfoCPUPopulate(virConnectPtr conn, FILE *cpuinfo, virNodeInfoPtr n
char *p;
unsigned int ui;
buf += 9;
- while (*buf && isspace(to_uchar(*buf)))
+ while (*buf && c_isspace(*buf))
buf++;
if (*buf != ':' || !buf[1]) {
__virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR,
@@ -82,13 +82,13 @@ int linuxNodeInfoCPUPopulate(virConnectPtr conn, FILE *cpuinfo, virNodeInfoPtr n
}
if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
/* Accept trailing fractional part. */
- && (*p == '\0' || *p == '.' || isspace(to_uchar(*p))))
+ && (*p == '\0' || *p == '.' || c_isspace(*p)))
nodeinfo->mhz = ui;
} else if (STREQLEN(buf, "cpu cores", 9)) { /* aka cores */
char *p;
unsigned int id;
buf += 9;
- while (*buf && isspace(to_uchar(*buf)))
+ while (*buf && c_isspace(*buf))
buf++;
if (*buf != ':' || !buf[1]) {
__virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR,
@@ -97,7 +97,7 @@ int linuxNodeInfoCPUPopulate(virConnectPtr conn, FILE *cpuinfo, virNodeInfoPtr n
return -1;
}
if (virStrToLong_ui(buf+1, &p, 10, &id) == 0
- && (*p == '\0' || isspace(to_uchar(*p)))
+ && (*p == '\0' || c_isspace(*p))
&& id > nodeinfo->cores)
nodeinfo->cores = id;
}
diff --git a/src/openvz_driver.c b/src/openvz_driver.c
index 0bae4fd..22c898a 100644
--- a/src/openvz_driver.c
+++ b/src/openvz_driver.c
@@ -45,7 +45,6 @@
#include <fcntl.h>
#include <signal.h>
#include <paths.h>
-#include <ctype.h>
#include <pwd.h>
#include <stdio.h>
#include <sys/wait.h>
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index cf52a07..10868c1 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -41,7 +41,7 @@
#include <fcntl.h>
#include <signal.h>
#include <paths.h>
-#include <ctype.h>
+#include <c-ctype.h>
#include <pwd.h>
#include <stdio.h>
#include <sys/wait.h>
@@ -519,7 +519,7 @@ static int qemudExtractMonitorPath(const char *haystack,
*/
tmp = path;
while (*tmp) {
- if (isspace(to_uchar(*tmp))) {
+ if (c_isspace(*tmp)) {
*tmp = '\0';
*offset += (sizeof(needle)-1) + strlen(path);
return 0;
diff --git a/src/sexpr.c b/src/sexpr.c
index 4cb4edf..85b289c 100644
--- a/src/sexpr.c
+++ b/src/sexpr.c
@@ -15,7 +15,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <ctype.h>
+#include <c-ctype.h>
#include <errno.h>
#include "internal.h"
@@ -358,7 +358,7 @@ _string2sexpr(const char *buffer, size_t * end)
} else {
start = ptr;
- while (*ptr && !isspace(to_uchar(*ptr))
+ while (*ptr && !c_isspace(*ptr)
&& *ptr != ')' && *ptr != '(') {
ptr++;
}
diff --git a/src/stats_linux.c b/src/stats_linux.c
index e84e24f..cb647fe 100644
--- a/src/stats_linux.c
+++ b/src/stats_linux.c
@@ -18,7 +18,7 @@
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
-#include <ctype.h>
+#include <c-ctype.h>
#ifdef WITH_XEN
#include <xs.h>
@@ -262,7 +262,7 @@ xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *path)
}
if (path[4] != '\0') {
- if (!isdigit(to_uchar(path[4])) || path[4] == '0' ||
+ if (!c_isdigit(path[4]) || path[4] == '0' ||
virStrToLong_i(path+4, NULL, 10, &part) < 0 ||
part < 1 || part > 15) {
statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
@@ -306,7 +306,7 @@ xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *path)
} else {
p = path + 3;
}
- if (p && (!isdigit(to_uchar(*p)) || *p == '0' ||
+ if (p && (!c_isdigit(*p) || *p == '0' ||
virStrToLong_i(p, NULL, 10, &part) < 0 ||
part < 1 || part > 15)) {
statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
@@ -332,7 +332,7 @@ xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *path)
}
if (path[3] != '\0') {
- if (!isdigit(to_uchar(path[3])) || path[3] == '0' ||
+ if (!c_isdigit(path[3]) || path[3] == '0' ||
virStrToLong_i(path+3, NULL, 10, &part) < 0 ||
part < 1 || part > 63) {
statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
diff --git a/src/util.c b/src/util.c
index 4cef6d2..f354a48 100644
--- a/src/util.c
+++ b/src/util.c
@@ -37,7 +37,7 @@
#include <sys/wait.h>
#endif
#include <string.h>
-#include <ctype.h>
+#include <c-ctype.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
@@ -57,9 +57,6 @@
#define MAX_ERROR_LEN 1024
-#define TOLOWER(Ch) (isupper (to_uchar(Ch)) \
- ? tolower (to_uchar (Ch)) : (to_uchar (Ch)))
-
#define virLog(msg...) fprintf(stderr, msg)
#ifndef PROXY
@@ -705,12 +702,12 @@ __virMacAddrCompare (const char *p, const char *q)
{
unsigned char c, d;
do {
- while (*p == '0' && isxdigit (to_uchar(p[1])))
+ while (*p == '0' && c_isxdigit (p[1]))
++p;
- while (*q == '0' && isxdigit (to_uchar(q[1])))
+ while (*q == '0' && c_isxdigit (q[1]))
++q;
- c = TOLOWER (*p);
- d = TOLOWER (*q);
+ c = c_tolower (*p);
+ d = c_tolower (*q);
if (c == 0 || d == 0)
break;
@@ -750,7 +747,7 @@ virParseMacAddr(const char* str, unsigned char *addr)
/* This is solely to avoid accepting the leading
* space or "+" that strtoul would otherwise accept.
*/
- if (!isxdigit(to_uchar(*str)))
+ if (!c_isxdigit(*str))
break;
result = strtoul(str, &end_ptr, 16);
diff --git a/src/util.h b/src/util.h
index af68bc8..2516504 100644
--- a/src/util.h
+++ b/src/util.h
@@ -27,11 +27,6 @@
#include "internal.h"
#include "util-lib.h"
-/* Convert a possibly-signed character to an unsigned character. This is
- a bit safer than casting to unsigned char, since it catches some type
- errors that the cast doesn't. */
-static inline unsigned char to_uchar (char ch) { return ch; }
-
int virExec(virConnectPtr conn, char **argv, int *retpid,
int infd, int *outfd, int *errfd);
int virExecNonBlock(virConnectPtr conn, char **argv, int *retpid,
diff --git a/src/virsh.c b/src/virsh.c
index 00dbda8..5a35f36 100644
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -26,7 +26,7 @@
#include <getopt.h>
#include <sys/types.h>
#include <sys/time.h>
-#include <ctype.h>
+#include <c-ctype.h>
#include <fcntl.h>
#include <locale.h>
#include <time.h>
@@ -1763,7 +1763,7 @@ cmdVcpupin(vshControl * ctl, vshCmd * cmd)
for (i = 0; cpulist[i]; i++) {
switch (state) {
case expect_num:
- if (!isdigit (to_uchar(cpulist[i]))) {
+ if (!c_isdigit (cpulist[i])) {
vshError( ctl, FALSE, _("cpulist: %s: Invalid format. Expecting digit at position %d (near '%c')."), cpulist, i, cpulist[i]);
virDomainFree (dom);
return FALSE;
@@ -1773,7 +1773,7 @@ cmdVcpupin(vshControl * ctl, vshCmd * cmd)
case expect_num_or_comma:
if (cpulist[i] == ',')
state = expect_num;
- else if (!isdigit (to_uchar(cpulist[i]))) {
+ else if (!c_isdigit (cpulist[i])) {
vshError(ctl, FALSE, _("cpulist: %s: Invalid format. Expecting digit or comma at position %d (near '%c')."), cpulist, i, cpulist[i]);
virDomainFree (dom);
return FALSE;
@@ -5673,7 +5673,7 @@ vshCommandGetToken(vshControl * ctl, char *str, char **end, char **res)
if (tk == VSH_TK_NONE) {
if (*p == '-' && *(p + 1) == '-' && *(p + 2)
- && isalnum(to_uchar(*(p + 2)))) {
+ && c_isalnum(*(p + 2))) {
tk = VSH_TK_OPTION;
p += 2;
} else {
diff --git a/src/xend_internal.c b/src/xend_internal.c
index 0c9f5bc..e964159 100644
--- a/src/xend_internal.c
+++ b/src/xend_internal.c
@@ -30,7 +30,6 @@
#include <arpa/inet.h>
#include <netdb.h>
#include <libxml/uri.h>
-#include <ctype.h>
#include <errno.h>
#include "libvirt/libvirt.h"
--
1.5.5.1.148.gbc1be
2
5
Hi,
I post a typo patch since it reaches 20.
docs/apps.html | 2 +-
docs/apps.html.in | 2 +-
docs/deployment.html | 2 +-
docs/deployment.html.in | 2 +-
docs/index.py | 6 +++---
docs/intro.html | 2 +-
docs/intro.html.in | 2 +-
docs/library.xen | 4 ++--
docs/virsh.pod | 2 +-
include/libvirt/libvirt.h | 2 +-
include/libvirt/libvirt.h.in | 2 +-
proxy/libvirt_proxy.c | 2 +-
qemud/event.c | 2 +-
qemud/qemud.c | 2 +-
qemud/remote.c | 2 +-
src/event.c | 2 +-
src/proxy_internal.c | 2 +-
17 files changed, 20 insertions(+), 20 deletions(-)
Thanks
Atsushi SAKAI
2
1
Hi,
This patch changes libvirtd description,
since libvirtd can control
not only Qemu but also Xen and LXC now.
Thanks
Atsushi SAKAI
2
1
09 May '08
This change demonstrates that the new syntax-check rule's
regexp can be improved. It missed the unsafe tolower use,
since there was already a to_uchar use on that line.
>From 5fc8de9825215e28773f2230ac6c1e1b3d724602 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering(a)redhat.com>
Date: Thu, 8 May 2008 16:11:55 +0200
Subject: [PATCH] avoid one more ctype vs. sign-extension problem
* src/util.c (TOLOWER): Also convert tolower argument.
---
src/util.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/src/util.c b/src/util.c
index 8f3cef9..4cef6d2 100644
--- a/src/util.c
+++ b/src/util.c
@@ -57,7 +57,8 @@
#define MAX_ERROR_LEN 1024
-#define TOLOWER(Ch) (isupper (to_uchar(Ch)) ? tolower (Ch) : (Ch))
+#define TOLOWER(Ch) (isupper (to_uchar(Ch)) \
+ ? tolower (to_uchar (Ch)) : (to_uchar (Ch)))
#define virLog(msg...) fprintf(stderr, msg)
--
1.5.5.1.148.g4c99ee
3
4
The patch below adds xml support for the soundhw option to qemu
and xen. The new xml element takes the form:
<sound driver='drivername'/>
Where driver name can be pcspk, sb16, es1370, or all.
Everything seems to be in working order but I have a few
implementation questions:
1) Should multiple drivers be able to be specified? qemu
accommodates this, allowing '-soundhw sb16,pcspk' for example.
If this should be allowed, what should the xml format be?
2) Should acceptable driver options be hardcoded? The other option
is to just pass the input straight to qemu. This patch has the
options hardcoded.
Also I realize this will probably need to be rediff'd around
Dan's serial + parallel device patch, but I figured I would just
get this out there.
Thanks,
Cole
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index d9b82b2..bfd9ba4 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -1011,6 +1011,41 @@ static int qemudParseInputXML(virConnectPtr conn,
return -1;
}
+/* Sound device helper functions */
+static int qemudSoundDriverFromString(virConnectPtr conn,
+ const char *driver) {
+ if (STREQ(driver, "all")) {
+ return QEMU_SOUND_ALL;
+ } else if (STREQ(driver, "sb16")) {
+ return QEMU_SOUND_SB16;
+ } else if (STREQ(driver, "es1370")) {
+ return QEMU_SOUND_ES1370;
+ } else if (STREQ(driver, "pcspk")) {
+ return QEMU_SOUND_PCSPK;
+ }
+
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_ARG,
+ _("invalid sound driver '%s'"), driver);
+ return -1;
+}
+
+static const char *qemudSoundDriverToString(virConnectPtr conn,
+ const int driver) {
+
+ if (driver == QEMU_SOUND_ALL) {
+ return "all";
+ } else if (driver == QEMU_SOUND_SB16) {
+ return "sb16";
+ } else if (driver == QEMU_SOUND_ES1370) {
+ return "es1370";
+ } else if (driver == QEMU_SOUND_PCSPK) {
+ return "pcspk";
+ }
+
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("invalid sound driver '%d'"), driver);
+ return NULL;
+}
/*
* Parses a libvirt XML definition of a guest, and populates the
@@ -1486,6 +1521,25 @@ static struct qemud_vm_def *qemudParseXML(virConnectPtr conn,
}
}
xmlXPathFreeObject(obj);
+
+ /* Parse sound driver xml */
+ obj = xmlXPathEval(BAD_CAST "/domain/devices/sound", ctxt);
+ if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
+ (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0)) {
+ def->soundDriver = QEMU_SOUND_NONE;
+ } else if ((prop = xmlGetProp(obj->nodesetval->nodeTab[0],
+ BAD_CAST "driver"))) {
+
+ if ((def->soundDriver = qemudSoundDriverFromString(conn,
+ (char *) prop)) < 0)
+ goto error;
+
+ xmlFree(prop);
+ prop = NULL;
+ } else {
+ def->soundDriver = QEMU_SOUND_NONE;
+ }
+ xmlXPathFreeObject(obj);
obj = NULL;
/* If graphics are enabled, there's an implicit PS2 mouse */
@@ -1694,6 +1748,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
(vm->def->os.cmdline[0] ? 2 : 0) + /* cmdline */
(vm->def->graphicsType == QEMUD_GRAPHICS_VNC ? 2 :
(vm->def->graphicsType == QEMUD_GRAPHICS_SDL ? 0 : 1)) + /* graphics */
+ (vm->def->soundDriver == QEMU_SOUND_NONE ? 0 : 2) + /* sound */
(vm->migrateFrom[0] ? 3 : 0); /* migrateFrom */
snprintf(memory, sizeof(memory), "%lu", vm->def->memory/1024);
@@ -1970,6 +2025,14 @@ int qemudBuildCommandLine(virConnectPtr conn,
/* SDL is the default. no args needed */
}
+ /* Add sound hardware */
+ if (vm->def->soundDriver != QEMU_SOUND_NONE) {
+ if (!((*argv)[++n] = strdup("-soundhw")))
+ goto no_memory;
+ if (!((*argv)[++n] = strdup((char *) qemudSoundDriverToString(conn, vm->def->soundDriver))))
+ goto no_memory;
+ }
+
if (vm->migrateFrom[0]) {
if (!((*argv)[++n] = strdup("-S")))
goto no_memory;
@@ -3125,7 +3188,11 @@ char *qemudGenerateXML(virConnectPtr conn,
break;
}
- if (def->graphicsType == QEMUD_GRAPHICS_VNC) {
+ if (def->soundDriver != QEMU_SOUND_NONE) {
+ if (virBufferVSprintf(buf, " <sound driver='%s'/>\n",
+ qemudSoundDriverToString(conn,
+ def->soundDriver)) < 0)
+ goto no_memory;
}
if (virBufferAddLit(buf, " </devices>\n") < 0)
diff --git a/src/qemu_conf.h b/src/qemu_conf.h
index c59b1fa..1383c10 100644
--- a/src/qemu_conf.h
+++ b/src/qemu_conf.h
@@ -136,6 +136,14 @@ struct qemud_vm_input_def {
struct qemud_vm_input_def *next;
};
+enum qemu_vm_sound_driver {
+ QEMU_SOUND_NONE,
+ QEMU_SOUND_ALL,
+ QEMU_SOUND_SB16,
+ QEMU_SOUND_ES1370,
+ QEMU_SOUND_PCSPK,
+};
+
/* Flags for the 'type' field in next struct */
enum qemud_vm_device_type {
QEMUD_DEVICE_DISK,
@@ -214,6 +222,7 @@ struct qemud_vm_def {
int vncActivePort;
char vncListen[BR_INET_ADDR_MAXLEN];
char *keymap;
+ int soundDriver;
int ndisks;
struct qemud_vm_disk_def *disks;
diff --git a/src/xend_internal.c b/src/xend_internal.c
index 6ba4571..b470731 100644
--- a/src/xend_internal.c
+++ b/src/xend_internal.c
@@ -1783,6 +1783,18 @@ xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root,
}
}
}
+
+ if (sexpr_node(root, "domain/image/hvm/soundhw")) {
+ tmp = sexpr_node(root, "domain/image/hvm/soundhw");
+ if (tmp && *tmp) {
+ if (STREQ(tmp, "all") ||
+ STREQ(tmp, "pcspk") ||
+ STREQ(tmp, "sb16") ||
+ STREQ(tmp, "es1370")) {
+ virBufferVSprintf(&buf, " <sound driver='%s'/>\n", tmp);
+ }
+ }
+ }
}
/* Graphics device (HVM <= 3.0.4, or PV <= 3.0.3) vnc config */
diff --git a/src/xm_internal.c b/src/xm_internal.c
index 3d845dc..91c7cf1 100644
--- a/src/xm_internal.c
+++ b/src/xm_internal.c
@@ -934,6 +934,15 @@ char *xenXMDomainFormatXML(virConnectPtr conn, virConfPtr conf) {
/* Ignore else branch - probably some other non-input device we don't
support in libvirt yet */
}
+
+ if ((xenXMConfigGetString(conf, "soundhw", &str) == 0) && str) {
+ if (STREQ(str, "all") ||
+ STREQ(str, "pcspk") ||
+ STREQ(str, "sb16") ||
+ STREQ(str, "es1370")) {
+ virBufferVSprintf(buf, " <sound driver='%s'/>\n", str);
+ }
+ }
}
/* HVM guests, or old PV guests use this config format */
@@ -2081,6 +2090,11 @@ virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml) {
if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "usbdevice", "string(/domain/devices/input[@bus='usb' or (not(@bus) and @type='tablet')]/@type)", 1,
"cannot set the usbdevice parameter") < 0)
goto error;
+
+ if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "soundhw",
+ "string(/domain/devices/sound[@driver]",
+ 1, "cannot set soundhw parameter") < 0)
+ goto error;
}
if (hvm || priv->xendConfigVersion < 3) {
diff --git a/src/xml.c b/src/xml.c
index 8e95103..f4bfb29 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -877,6 +877,14 @@ virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node,
nodes = NULL;
}
+ cur = virXPathNode("/domain/devices/sound", ctxt);
+ if (cur) {
+ xmlChar *driver = NULL;
+ driver = xmlGetProp(cur, (xmlChar *) "driver");
+ if (driver)
+ virBufferVSprintf(buf, "(soundhw '%s')", driver);
+ xmlFree(driver);
+ }
res = virXPathBoolean("count(domain/devices/console) > 0", ctxt);
if (res < 0) {
6
13
The attached patch implements the domain autostart commands for
xen. The xen sexpr (since at least 3.0.4 = 1.5 years) has a
on_xend_start field which can be used to autostart a domain.
A couple things:
1) This works on a running guest, but will only show the
sexpr changes after the guest is restarted. Just curious
if there is any better way to do this?
2) This isn't implemented for the xm config file driver. I
figured this is fine since this is inherently dependent
on inactive domain management.
Any feedback is appreciated.
Thanks,
Cole
diff --git a/src/xen_unified.c b/src/xen_unified.c
index 91502dc..cf0a68d 100644
--- a/src/xen_unified.c
+++ b/src/xen_unified.c
@@ -1128,6 +1128,34 @@ xenUnifiedDomainDetachDevice (virDomainPtr dom, const char *xml)
return -1;
}
+static int
+xenUnifiedDomainGetAutostart (virDomainPtr dom, int *autostart)
+{
+ GET_PRIVATE(dom->conn);
+ int i;
+
+ for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+ if (priv->opened[i] && drivers[i]->domainGetAutostart &&
+ drivers[i]->domainGetAutostart (dom, autostart) == 0)
+ return 0;
+
+ return -1;
+}
+
+static int
+xenUnifiedDomainSetAutostart (virDomainPtr dom, int autostart)
+{
+ GET_PRIVATE(dom->conn);
+ int i;
+
+ for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+ if (priv->opened[i] && drivers[i]->domainSetAutostart &&
+ drivers[i]->domainSetAutostart (dom, autostart) == 0)
+ return 0;
+
+ return -1;
+}
+
static char *
xenUnifiedDomainGetSchedulerType (virDomainPtr dom, int *nparams)
{
@@ -1291,6 +1319,8 @@ static virDriver xenUnifiedDriver = {
.domainUndefine = xenUnifiedDomainUndefine,
.domainAttachDevice = xenUnifiedDomainAttachDevice,
.domainDetachDevice = xenUnifiedDomainDetachDevice,
+ .domainGetAutostart = xenUnifiedDomainGetAutostart,
+ .domainSetAutostart = xenUnifiedDomainSetAutostart,
.domainGetSchedulerType = xenUnifiedDomainGetSchedulerType,
.domainGetSchedulerParameters = xenUnifiedDomainGetSchedulerParameters,
.domainSetSchedulerParameters = xenUnifiedDomainSetSchedulerParameters,
diff --git a/src/xend_internal.c b/src/xend_internal.c
index f9db571..226ba8e 100644
--- a/src/xend_internal.c
+++ b/src/xend_internal.c
@@ -115,8 +115,8 @@ struct xenUnifiedDriver xenDaemonDriver = {
xenDaemonDomainUndefine, /* domainUndefine */
xenDaemonAttachDevice, /* domainAttachDevice */
xenDaemonDetachDevice, /* domainDetachDevice */
- NULL, /* domainGetAutostart */
- NULL, /* domainSetAutostart */
+ xenDaemonDomainGetAutostart, /* domainGetAutostart */
+ xenDaemonDomainSetAutostart, /* domainSetAutostart */
xenDaemonGetSchedulerType, /* domainGetSchedulerType */
xenDaemonGetSchedulerParameters, /* domainGetSchedulerParameters */
xenDaemonSetSchedulerParameters, /* domainSetSchedulerParameters */
@@ -3718,6 +3718,99 @@ xenDaemonDetachDevice(virDomainPtr domain, const char *xml)
"type", class, "dev", ref, "force", "0", "rm_cfg", "1", NULL));
}
+int
+xenDaemonDomainGetAutostart(virDomainPtr domain,
+ int *autostart)
+{
+ struct sexpr *root;
+ const char *tmp;
+
+ if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+ virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+ __FUNCTION__);
+ return (-1);
+ }
+
+ root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
+ if (root == NULL) {
+ virXendError (domain->conn, VIR_ERR_XEN_CALL,
+ _("xenDaemonGetAutostart failed to find this domain"));
+ return (-1);
+ }
+
+ *autostart = 0;
+
+ tmp = sexpr_node(root, "domain/on_xend_start");
+ if (tmp && STREQ(tmp, "start")) {
+ *autostart = 1;
+ }
+
+ sexpr_free(root);
+ return 0;
+}
+
+int
+xenDaemonDomainSetAutostart(virDomainPtr domain,
+ int autostart)
+{
+ struct sexpr *root, *autonode;
+ const char *autostr;
+ char buf[4096];
+ int ret = -1;
+
+ if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+ virXendError((domain ? domain->conn : NULL), VIR_ERR_INTERNAL_ERROR,
+ __FUNCTION__);
+ return (-1);
+ }
+
+ root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
+ if (root == NULL) {
+ virXendError (domain->conn, VIR_ERR_XEN_CALL,
+ _("xenDaemonSetAutostart failed to find this domain"));
+ return (-1);
+ }
+
+ autostr = sexpr_node(root, "domain/on_xend_start");
+ if (autostr) {
+ if (!STREQ(autostr, "ignore") && !STREQ(autostr, "start")) {
+ virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+ _("unexpected value from on_xend_start"));
+ goto error;
+ }
+
+ // Change the autostart value in place, then define the new sexpr
+ autonode = sexpr_lookup(root, "domain/on_xend_start");
+ free(autonode->u.s.car->u.value);
+ autonode->u.s.car->u.value = (autostart ? strdup("start")
+ : strdup("ignore"));
+ if (!(autonode->u.s.car->u.value)) {
+ virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+ _("no memory"));
+ goto error;
+ }
+
+ if (sexpr2string(root, buf, 4096) == 0) {
+ virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+ _("sexpr2string failed"));
+ goto error;
+ }
+ if (xend_op(domain->conn, "", "op", "new", "config", buf, NULL) != 0) {
+ virXendError(domain->conn, VIR_ERR_XEN_CALL,
+ _("Failed to redefine sexpr"));
+ goto error;
+ }
+ } else {
+ virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+ _("on_xend_start not present in sexpr"));
+ goto error;
+ }
+
+ ret = 0;
+ error:
+ sexpr_free(root);
+ return ret;
+}
int
xenDaemonDomainMigratePrepare (virConnectPtr dconn,
diff --git a/src/xend_internal.h b/src/xend_internal.h
index 80ef4f6..97f98f2 100644
--- a/src/xend_internal.h
+++ b/src/xend_internal.h
@@ -229,6 +229,10 @@ int xenDaemonDomainGetVcpus (virDomainPtr domain,
int maxinfo,
unsigned char *cpumaps,
int maplen);
+int xenDaemonDomainGetAutostart (virDomainPtr dom,
+ int *autostart);
+int xenDaemonDomainSetAutostart (virDomainPtr domain,
+ int autostart);
/* xen_unified calls through here. */
extern struct xenUnifiedDriver xenDaemonDriver;
5
8
09 May '08
A follow-up to the patch that introduced to_uchar.
This rule will ensure no new offenders sneak back in.
>From d141d07c7e21cc228fe46d90f21dd86685d7e424 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering(a)redhat.com>
Date: Thu, 8 May 2008 16:18:13 +0200
Subject: [PATCH] sytnax-check: add a check for risky ctype macro use
* Makefile.maint (sc_risky_ctype_macros): New rule.
---
Makefile.maint | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/Makefile.maint b/Makefile.maint
index ddf42bc..bab8e1d 100644
--- a/Makefile.maint
+++ b/Makefile.maint
@@ -302,6 +302,15 @@ sc_TAB_in_indentation:
{ echo '$(ME): found TAB(s) use for indentation; use spaces' \
1>&2; exit 1; } || :
+ctype_re = isalnum|isalpha|isascii|isblank|iscntrl|isdigit|isgraph|islower\
+|isprint|ispunct|isspace|isupper|isxdigit|tolower|toupper
+
+sc_risky_ctype_macros:
+ @grep -E '\b($(ctype_re)) *\(' /dev/null \
+ $$($(VC_LIST_EXCEPT)) | grep -v to_uchar && \
+ { echo '$(ME): found ctype macro use without to_uchar' \
+ 1>&2; exit 1; } || :
+
# Match lines like the following, but where there is only one space
# between the options and the description:
# -D, --all-repeated[=delimit-method] print all duplicate lines\n
--
1.5.5.1.148.gbc1be
2
1
>From fed1a1abfd2b9ece7bd8e44aae13de91eaad4f5d Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering(a)redhat.com>
Date: Wed, 7 May 2008 23:12:13 +0200
Subject: [PATCH] add "const" to file-scoped statics
These were relatively new additions to the list from here:
nm src/*.o|grep ' D '.
This is another test that should be automatic...
---
src/storage_backend_fs.c | 2 +-
src/xend_internal.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/storage_backend_fs.c b/src/storage_backend_fs.c
index d0eb32a..b41b952 100644
--- a/src/storage_backend_fs.c
+++ b/src/storage_backend_fs.c
@@ -79,7 +79,7 @@ enum {
};
/* Either 'magic' or 'extension' *must* be provided */
-struct {
+static const struct {
int type; /* One of the constants above */
const char *magic; /* Optional string of file magic
* to check at head of file */
diff --git a/src/xend_internal.c b/src/xend_internal.c
index f9db571..dd3ade6 100644
--- a/src/xend_internal.c
+++ b/src/xend_internal.c
@@ -854,7 +854,7 @@ urlencode(const char *string)
#endif /* ! PROXY */
/* Applicable sound models */
-const char *sound_models[] = { "sb16", "es1370" };
+static const char *const sound_models[] = { "sb16", "es1370" };
/**
* is_sound_model_valid:
--
1.5.5.1.148.gbc1be
2
2
08 May '08
To complement soren's patch adding a bus attribute to the QEMU driver,
here is a minimal patch adding bus attribute to the Xen drivers. It merely
adds it on when generating the XML. It isn't making any attempt to interpret
it when creating a VM, since Xen does everything based off the disk node
name anyway its (currently) redundant.
The bus types supported are 'xen' for paravirt disks, or 'ide' and 'scsi'
for HVM guests.
NB, if setting up ide / scsi disks with HVM, XenD also sets up a parvirt
disk, but we don't attempt to express this duplication as its an underlying
impl detail.
Regards,
Daniel.
Index: src/xend_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xend_internal.c,v
retrieving revision 1.183
diff -u -p -r1.183 xend_internal.c
--- src/xend_internal.c 30 Apr 2008 12:30:55 -0000 1.183
+++ src/xend_internal.c 7 May 2008 00:14:23 -0000
@@ -1759,6 +1759,7 @@ xend_parse_sexp_desc(virConnectPtr conn,
const char *src = NULL;
const char *dst = NULL;
const char *mode = NULL;
+ const char *bus = NULL;
/* Again dealing with (vbd...) vs (tap ...) differences */
if (sexpr_lookup(node, "device/vbd")) {
@@ -1878,7 +1879,16 @@ xend_parse_sexp_desc(virConnectPtr conn,
/* This case is the cdrom device only */
virBufferAddLit(&buf, " <disk device='cdrom'>\n");
}
- virBufferVSprintf(&buf, " <target dev='%s'/>\n", dst);
+
+ if (STRPREFIX(dst, "xvd") || !hvm) {
+ bus = "xen";
+ } else if (STRPREFIX(dst, "sd")) {
+ bus = "scsi";
+ } else {
+ bus = "ide";
+ }
+ virBufferVSprintf(&buf, " <target dev='%s' bus='%s'/>\n",
+ dst, bus);
/* XXX should we force mode == r, if cdrom==1, or assume
@@ -1967,14 +1977,14 @@ xend_parse_sexp_desc(virConnectPtr conn,
if ((tmp != NULL) && (tmp[0] != 0)) {
virBufferAddLit(&buf, " <disk type='file' device='floppy'>\n");
virBufferVSprintf(&buf, " <source file='%s'/>\n", tmp);
- virBufferAddLit(&buf, " <target dev='fda'/>\n");
+ virBufferAddLit(&buf, " <target dev='fda' bus='fdc'/>\n");
virBufferAddLit(&buf, " </disk>\n");
}
tmp = sexpr_node(root, "domain/image/hvm/fdb");
if ((tmp != NULL) && (tmp[0] != 0)) {
virBufferAddLit(&buf, " <disk type='file' device='floppy'>\n");
virBufferVSprintf(&buf, " <source file='%s'/>\n", tmp);
- virBufferAddLit(&buf, " <target dev='fdb'/>\n");
+ virBufferAddLit(&buf, " <target dev='fdb' bus='fdc'/>\n");
virBufferAddLit(&buf, " </disk>\n");
}
@@ -1985,7 +1995,7 @@ xend_parse_sexp_desc(virConnectPtr conn,
virBufferAddLit(&buf, " <disk type='file' device='cdrom'>\n");
virBufferAddLit(&buf, " <driver name='file'/>\n");
virBufferVSprintf(&buf, " <source file='%s'/>\n", tmp);
- virBufferAddLit(&buf, " <target dev='hdc'/>\n");
+ virBufferAddLit(&buf, " <target dev='hdc' bus='ide'/>\n");
virBufferAddLit(&buf, " <readonly/>\n");
virBufferAddLit(&buf, " </disk>\n");
}
Index: src/xm_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xm_internal.c,v
retrieving revision 1.74
diff -u -p -r1.74 xm_internal.c
--- src/xm_internal.c 30 Apr 2008 12:30:55 -0000 1.74
+++ src/xm_internal.c 7 May 2008 00:14:26 -0000
@@ -733,6 +733,7 @@ char *xenXMDomainFormatXML(virConnectPtr
char *head;
char *offset;
char *tmp, *tmp1;
+ const char *bus;
if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
goto skipdisk;
@@ -805,6 +806,14 @@ char *xenXMDomainFormatXML(virConnectPtr
tmp[0] = '\0';
}
+ if (STRPREFIX(dev, "xvd") || !hvm) {
+ bus = "xen";
+ } else if (STRPREFIX(dev, "sd")) {
+ bus = "scsi";
+ } else {
+ bus = "ide";
+ }
+
virBufferVSprintf(&buf, " <disk type='%s' device='%s'>\n",
block ? "block" : "file",
cdrom ? "cdrom" : "disk");
@@ -814,7 +823,7 @@ char *xenXMDomainFormatXML(virConnectPtr
virBufferVSprintf(&buf, " <driver name='%s'/>\n", drvName);
if (src[0])
virBufferVSprintf(&buf, " <source %s='%s'/>\n", block ? "dev" : "file", src);
- virBufferVSprintf(&buf, " <target dev='%s'/>\n", dev);
+ virBufferVSprintf(&buf, " <target dev='%s' bus='%s'/>\n", dev, bus);
if (!strcmp(head, "r") ||
!strcmp(head, "ro"))
virBufferAddLit(&buf, " <readonly/>\n");
@@ -833,7 +842,7 @@ char *xenXMDomainFormatXML(virConnectPtr
virBufferAddLit(&buf, " <disk type='file' device='cdrom'>\n");
virBufferAddLit(&buf, " <driver name='file'/>\n");
virBufferVSprintf(&buf, " <source file='%s'/>\n", str);
- virBufferAddLit(&buf, " <target dev='hdc'/>\n");
+ virBufferAddLit(&buf, " <target dev='hdc' bus='ide'/>\n");
virBufferAddLit(&buf, " <readonly/>\n");
virBufferAddLit(&buf, " </disk>\n");
}
Index: tests/sexpr2xmltest.c
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmltest.c,v
retrieving revision 1.27
diff -u -p -r1.27 sexpr2xmltest.c
--- tests/sexpr2xmltest.c 30 Apr 2008 12:30:55 -0000 1.27
+++ tests/sexpr2xmltest.c 7 May 2008 00:14:36 -0000
@@ -113,11 +113,11 @@ main(int argc, char **argv)
DO_TEST("disk-drv-blktap-raw", "disk-drv-blktap-raw", 2);
DO_TEST("disk-drv-blktap-qcow", "disk-drv-blktap-qcow", 2);
- DO_TEST("curmem", "curmem", 1);
+ DO_TEST("curmem", "curmem", 2);
DO_TEST("net-routed", "net-routed", 2);
DO_TEST("net-bridged", "net-bridged", 2);
DO_TEST("net-e1000", "net-e1000", 2);
- DO_TEST("no-source-cdrom", "no-source-cdrom", 1);
+ DO_TEST("no-source-cdrom", "no-source-cdrom", 2);
DO_TEST("fv-utc", "fv-utc", 1);
DO_TEST("fv-localtime", "fv-localtime", 1);
Index: tests/sexpr2xmldata/sexpr2xml-curmem.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-curmem.xml,v
retrieving revision 1.5
diff -u -p -r1.5 sexpr2xml-curmem.xml
--- tests/sexpr2xmldata/sexpr2xml-curmem.xml 26 Apr 2008 14:22:02 -0000 1.5
+++ tests/sexpr2xmldata/sexpr2xml-curmem.xml 7 May 2008 00:14:36 -0000
@@ -24,10 +24,10 @@
<disk type='file' device='disk'>
<driver name='tap' type='aio'/>
<source file='/xen/rhel5.img'/>
- <target dev='xvda:disk'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<input type='mouse' bus='xen'/>
- <graphics type='vnc' port='5905'/>
+ <graphics type='vnc' port='-1'/>
<console type='pty'>
<target port='0'/>
</console>
Index: tests/sexpr2xmldata/sexpr2xml-disk-block-shareable.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-disk-block-shareable.xml,v
retrieving revision 1.2
diff -u -p -r1.2 sexpr2xml-disk-block-shareable.xml
--- tests/sexpr2xmldata/sexpr2xml-disk-block-shareable.xml 26 Apr 2008 14:22:02 -0000 1.2
+++ tests/sexpr2xmldata/sexpr2xml-disk-block-shareable.xml 7 May 2008 00:14:36 -0000
@@ -12,7 +12,7 @@
<disk type='file' device='disk'>
<driver name='tap' type='aio'/>
<source file='/var/lib/xen/images/rhel5pv.img'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
<shareable/>
</disk>
<interface type='bridge'>
Index: tests/sexpr2xmldata/sexpr2xml-disk-block.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-disk-block.xml,v
retrieving revision 1.3
diff -u -p -r1.3 sexpr2xml-disk-block.xml
--- tests/sexpr2xmldata/sexpr2xml-disk-block.xml 26 Apr 2008 14:22:02 -0000 1.3
+++ tests/sexpr2xmldata/sexpr2xml-disk-block.xml 7 May 2008 00:14:36 -0000
@@ -16,7 +16,7 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/MainVG/GuestVG'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<console type='pty'>
<target port='0'/>
Index: tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-qcow.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-qcow.xml,v
retrieving revision 1.3
diff -u -p -r1.3 sexpr2xml-disk-drv-blktap-qcow.xml
--- tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-qcow.xml 26 Apr 2008 14:22:02 -0000 1.3
+++ tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-qcow.xml 7 May 2008 00:14:36 -0000
@@ -16,7 +16,7 @@
<disk type='file' device='disk'>
<driver name='tap' type='qcow'/>
<source file='/root/some.img'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<console type='pty'>
<target port='0'/>
Index: tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-raw.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-raw.xml,v
retrieving revision 1.3
diff -u -p -r1.3 sexpr2xml-disk-drv-blktap-raw.xml
--- tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-raw.xml 26 Apr 2008 14:22:02 -0000 1.3
+++ tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-raw.xml 7 May 2008 00:14:36 -0000
@@ -16,7 +16,7 @@
<disk type='file' device='disk'>
<driver name='tap' type='aio'/>
<source file='/root/some.img'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<console type='pty'>
<target port='0'/>
Index: tests/sexpr2xmldata/sexpr2xml-disk-file.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-disk-file.xml,v
retrieving revision 1.3
diff -u -p -r1.3 sexpr2xml-disk-file.xml
--- tests/sexpr2xmldata/sexpr2xml-disk-file.xml 26 Apr 2008 14:22:02 -0000 1.3
+++ tests/sexpr2xmldata/sexpr2xml-disk-file.xml 7 May 2008 00:14:36 -0000
@@ -16,7 +16,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/some.img'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<console type='pty'>
<target port='0'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-kernel.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-kernel.xml,v
retrieving revision 1.2
diff -u -p -r1.2 sexpr2xml-fv-kernel.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-kernel.xml 26 Apr 2008 14:22:02 -0000 1.2
+++ tests/sexpr2xmldata/sexpr2xml-fv-kernel.xml 7 May 2008 00:14:36 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/some.img'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<serial type='pty'>
<target port='0'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-legacy-vfb.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-legacy-vfb.xml,v
retrieving revision 1.1
diff -u -p -r1.1 sexpr2xml-fv-legacy-vfb.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-legacy-vfb.xml 5 Feb 2008 16:21:25 -0000 1.1
+++ tests/sexpr2xmldata/sexpr2xml-fv-legacy-vfb.xml 7 May 2008 00:14:36 -0000
@@ -25,7 +25,7 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/zvol/dsk/export/s10u4-root'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<input type='mouse' bus='ps2'/>
<graphics type='vnc' port='-1' keymap='en-us'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml,v
retrieving revision 1.4
diff -u -p -r1.4 sexpr2xml-fv-localtime.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml 21 Aug 2007 08:54:07 -0000 1.4
+++ tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml 7 May 2008 00:14:36 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
@@ -31,7 +31,7 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='mouse' bus='ps2'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-parallel-tcp.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-parallel-tcp.xml,v
retrieving revision 1.1
diff -u -p -r1.1 sexpr2xml-fv-parallel-tcp.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-parallel-tcp.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/sexpr2xmldata/sexpr2xml-fv-parallel-tcp.xml 7 May 2008 00:14:36 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
@@ -31,7 +31,7 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='mouse' bus='ps2'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-serial-file.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-serial-file.xml,v
retrieving revision 1.1
diff -u -p -r1.1 sexpr2xml-fv-serial-file.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-serial-file.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/sexpr2xmldata/sexpr2xml-fv-serial-file.xml 7 May 2008 00:14:37 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
@@ -31,7 +31,7 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='mouse' bus='ps2'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-serial-null.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-serial-null.xml,v
retrieving revision 1.1
diff -u -p -r1.1 sexpr2xml-fv-serial-null.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-serial-null.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/sexpr2xmldata/sexpr2xml-fv-serial-null.xml 7 May 2008 00:14:37 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
@@ -31,7 +31,7 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='mouse' bus='ps2'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-serial-pipe.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-serial-pipe.xml,v
retrieving revision 1.1
diff -u -p -r1.1 sexpr2xml-fv-serial-pipe.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-serial-pipe.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/sexpr2xmldata/sexpr2xml-fv-serial-pipe.xml 7 May 2008 00:14:37 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
@@ -31,7 +31,7 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='mouse' bus='ps2'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-serial-pty.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-serial-pty.xml,v
retrieving revision 1.1
diff -u -p -r1.1 sexpr2xml-fv-serial-pty.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-serial-pty.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/sexpr2xmldata/sexpr2xml-fv-serial-pty.xml 7 May 2008 00:14:37 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
@@ -31,7 +31,7 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='mouse' bus='ps2'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-serial-stdio.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-serial-stdio.xml,v
retrieving revision 1.1
diff -u -p -r1.1 sexpr2xml-fv-serial-stdio.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-serial-stdio.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/sexpr2xmldata/sexpr2xml-fv-serial-stdio.xml 7 May 2008 00:14:37 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
@@ -31,7 +31,7 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='mouse' bus='ps2'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.xml,v
retrieving revision 1.1
diff -u -p -r1.1 sexpr2xml-fv-serial-tcp-telnet.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.xml 7 May 2008 00:14:37 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
@@ -31,7 +31,7 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='mouse' bus='ps2'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.xml,v
retrieving revision 1.1
diff -u -p -r1.1 sexpr2xml-fv-serial-tcp.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.xml 7 May 2008 00:14:37 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
@@ -31,7 +31,7 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='mouse' bus='ps2'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-serial-udp.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-serial-udp.xml,v
retrieving revision 1.1
diff -u -p -r1.1 sexpr2xml-fv-serial-udp.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-serial-udp.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/sexpr2xmldata/sexpr2xml-fv-serial-udp.xml 7 May 2008 00:14:37 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
@@ -31,7 +31,7 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='mouse' bus='ps2'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.xml,v
retrieving revision 1.1
diff -u -p -r1.1 sexpr2xml-fv-serial-unix.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.xml 7 May 2008 00:14:37 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
@@ -31,7 +31,7 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='mouse' bus='ps2'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-usbmouse.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-usbmouse.xml,v
retrieving revision 1.3
diff -u -p -r1.3 sexpr2xml-fv-usbmouse.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-usbmouse.xml 21 Aug 2007 08:54:07 -0000 1.3
+++ tests/sexpr2xmldata/sexpr2xml-fv-usbmouse.xml 7 May 2008 00:14:37 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
@@ -31,7 +31,7 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='mouse' bus='usb'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-usbtablet.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-usbtablet.xml,v
retrieving revision 1.3
diff -u -p -r1.3 sexpr2xml-fv-usbtablet.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-usbtablet.xml 21 Aug 2007 08:54:07 -0000 1.3
+++ tests/sexpr2xmldata/sexpr2xml-fv-usbtablet.xml 7 May 2008 00:14:37 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
@@ -31,7 +31,7 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='tablet' bus='usb'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-utc.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-utc.xml,v
retrieving revision 1.4
diff -u -p -r1.4 sexpr2xml-fv-utc.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-utc.xml 21 Aug 2007 08:54:07 -0000 1.4
+++ tests/sexpr2xmldata/sexpr2xml-fv-utc.xml 7 May 2008 00:14:37 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
@@ -31,7 +31,7 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='mouse' bus='ps2'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv-v2.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-v2.xml,v
retrieving revision 1.7
diff -u -p -r1.7 sexpr2xml-fv-v2.xml
--- tests/sexpr2xmldata/sexpr2xml-fv-v2.xml 21 Aug 2007 08:54:07 -0000 1.7
+++ tests/sexpr2xmldata/sexpr2xml-fv-v2.xml 7 May 2008 00:14:37 -0000
@@ -20,13 +20,13 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
Index: tests/sexpr2xmldata/sexpr2xml-fv.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv.xml,v
retrieving revision 1.7
diff -u -p -r1.7 sexpr2xml-fv.xml
--- tests/sexpr2xmldata/sexpr2xml-fv.xml 21 Aug 2007 08:54:07 -0000 1.7
+++ tests/sexpr2xmldata/sexpr2xml-fv.xml 7 May 2008 00:14:37 -0000
@@ -20,7 +20,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/foo.img'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
@@ -31,7 +31,7 @@
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='mouse' bus='ps2'/>
Index: tests/sexpr2xmldata/sexpr2xml-net-bridged.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-net-bridged.xml,v
retrieving revision 1.4
diff -u -p -r1.4 sexpr2xml-net-bridged.xml
--- tests/sexpr2xmldata/sexpr2xml-net-bridged.xml 26 Apr 2008 14:22:02 -0000 1.4
+++ tests/sexpr2xmldata/sexpr2xml-net-bridged.xml 7 May 2008 00:14:37 -0000
@@ -16,7 +16,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/some.img'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr2'/>
Index: tests/sexpr2xmldata/sexpr2xml-net-e1000.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-net-e1000.xml,v
retrieving revision 1.1
diff -u -p -r1.1 sexpr2xml-net-e1000.xml
--- tests/sexpr2xmldata/sexpr2xml-net-e1000.xml 30 Apr 2008 12:30:55 -0000 1.1
+++ tests/sexpr2xmldata/sexpr2xml-net-e1000.xml 7 May 2008 00:14:37 -0000
@@ -16,7 +16,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/some.img'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr2'/>
Index: tests/sexpr2xmldata/sexpr2xml-net-routed.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-net-routed.xml,v
retrieving revision 1.4
diff -u -p -r1.4 sexpr2xml-net-routed.xml
--- tests/sexpr2xmldata/sexpr2xml-net-routed.xml 26 Apr 2008 14:22:02 -0000 1.4
+++ tests/sexpr2xmldata/sexpr2xml-net-routed.xml 7 May 2008 00:14:37 -0000
@@ -16,7 +16,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/some.img'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<interface type='ethernet'>
<target dev='vif6.0'/>
Index: tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml,v
retrieving revision 1.9
diff -u -p -r1.9 sexpr2xml-no-source-cdrom.xml
--- tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml 26 Apr 2008 14:22:02 -0000 1.9
+++ tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml 7 May 2008 00:14:37 -0000
@@ -28,14 +28,14 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/sda8'/>
- <target dev='hda:disk'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk device='cdrom'>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<input type='mouse' bus='ps2'/>
- <graphics type='vnc' port='5906'/>
+ <graphics type='vnc' port='-1'/>
<serial type='pty'>
<target port='0'/>
</serial>
Index: tests/sexpr2xmldata/sexpr2xml-pv-bootloader.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-pv-bootloader.xml,v
retrieving revision 1.3
diff -u -p -r1.3 sexpr2xml-pv-bootloader.xml
--- tests/sexpr2xmldata/sexpr2xml-pv-bootloader.xml 26 Apr 2008 14:22:02 -0000 1.3
+++ tests/sexpr2xmldata/sexpr2xml-pv-bootloader.xml 7 May 2008 00:14:37 -0000
@@ -12,7 +12,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/some.img'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<console type='pty'>
<target port='0'/>
Index: tests/sexpr2xmldata/sexpr2xml-pv-vfb-new.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-pv-vfb-new.xml,v
retrieving revision 1.6
diff -u -p -r1.6 sexpr2xml-pv-vfb-new.xml
--- tests/sexpr2xmldata/sexpr2xml-pv-vfb-new.xml 26 Apr 2008 14:22:02 -0000 1.6
+++ tests/sexpr2xmldata/sexpr2xml-pv-vfb-new.xml 7 May 2008 00:14:37 -0000
@@ -16,7 +16,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/some.img'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<input type='mouse' bus='xen'/>
<graphics type='vnc' port='-1' listen='0.0.0.0' keymap='ja'/>
Index: tests/sexpr2xmldata/sexpr2xml-pv-vfb-orig.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-pv-vfb-orig.xml,v
retrieving revision 1.6
diff -u -p -r1.6 sexpr2xml-pv-vfb-orig.xml
--- tests/sexpr2xmldata/sexpr2xml-pv-vfb-orig.xml 26 Apr 2008 14:22:02 -0000 1.6
+++ tests/sexpr2xmldata/sexpr2xml-pv-vfb-orig.xml 7 May 2008 00:14:37 -0000
@@ -16,7 +16,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/some.img'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<input type='mouse' bus='xen'/>
<graphics type='vnc' port='-1' listen='0.0.0.0' keymap='ja'/>
Index: tests/sexpr2xmldata/sexpr2xml-pv.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-pv.xml,v
retrieving revision 1.4
diff -u -p -r1.4 sexpr2xml-pv.xml
--- tests/sexpr2xmldata/sexpr2xml-pv.xml 26 Apr 2008 14:22:02 -0000 1.4
+++ tests/sexpr2xmldata/sexpr2xml-pv.xml 7 May 2008 00:14:37 -0000
@@ -16,7 +16,7 @@
<disk type='file' device='disk'>
<driver name='file'/>
<source file='/root/some.img'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<console type='pty'>
<target port='0'/>
Index: tests/xmconfigdata/test-fullvirt-localtime.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-localtime.xml,v
retrieving revision 1.3
diff -u -p -r1.3 test-fullvirt-localtime.xml
--- tests/xmconfigdata/test-fullvirt-localtime.xml 9 Aug 2007 20:19:12 -0000 1.3
+++ tests/xmconfigdata/test-fullvirt-localtime.xml 7 May 2008 00:14:37 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-new-cdrom.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-new-cdrom.xml,v
retrieving revision 1.6
diff -u -p -r1.6 test-fullvirt-new-cdrom.xml
--- tests/xmconfigdata/test-fullvirt-new-cdrom.xml 9 Aug 2007 20:19:12 -0000 1.6
+++ tests/xmconfigdata/test-fullvirt-new-cdrom.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-old-cdrom.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-old-cdrom.xml,v
retrieving revision 1.6
diff -u -p -r1.6 test-fullvirt-old-cdrom.xml
--- tests/xmconfigdata/test-fullvirt-old-cdrom.xml 9 Aug 2007 20:19:12 -0000 1.6
+++ tests/xmconfigdata/test-fullvirt-old-cdrom.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-parallel-tcp.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-parallel-tcp.xml,v
retrieving revision 1.1
diff -u -p -r1.1 test-fullvirt-parallel-tcp.xml
--- tests/xmconfigdata/test-fullvirt-parallel-tcp.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/xmconfigdata/test-fullvirt-parallel-tcp.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-serial-file.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-serial-file.xml,v
retrieving revision 1.1
diff -u -p -r1.1 test-fullvirt-serial-file.xml
--- tests/xmconfigdata/test-fullvirt-serial-file.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/xmconfigdata/test-fullvirt-serial-file.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-serial-null.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-serial-null.xml,v
retrieving revision 1.1
diff -u -p -r1.1 test-fullvirt-serial-null.xml
--- tests/xmconfigdata/test-fullvirt-serial-null.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/xmconfigdata/test-fullvirt-serial-null.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-serial-pipe.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-serial-pipe.xml,v
retrieving revision 1.1
diff -u -p -r1.1 test-fullvirt-serial-pipe.xml
--- tests/xmconfigdata/test-fullvirt-serial-pipe.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/xmconfigdata/test-fullvirt-serial-pipe.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-serial-pty.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-serial-pty.xml,v
retrieving revision 1.1
diff -u -p -r1.1 test-fullvirt-serial-pty.xml
--- tests/xmconfigdata/test-fullvirt-serial-pty.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/xmconfigdata/test-fullvirt-serial-pty.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-serial-stdio.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-serial-stdio.xml,v
retrieving revision 1.1
diff -u -p -r1.1 test-fullvirt-serial-stdio.xml
--- tests/xmconfigdata/test-fullvirt-serial-stdio.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/xmconfigdata/test-fullvirt-serial-stdio.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml,v
retrieving revision 1.1
diff -u -p -r1.1 test-fullvirt-serial-tcp-telnet.xml
--- tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-serial-tcp.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-serial-tcp.xml,v
retrieving revision 1.1
diff -u -p -r1.1 test-fullvirt-serial-tcp.xml
--- tests/xmconfigdata/test-fullvirt-serial-tcp.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/xmconfigdata/test-fullvirt-serial-tcp.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-serial-udp.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-serial-udp.xml,v
retrieving revision 1.1
diff -u -p -r1.1 test-fullvirt-serial-udp.xml
--- tests/xmconfigdata/test-fullvirt-serial-udp.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/xmconfigdata/test-fullvirt-serial-udp.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-serial-unix.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-serial-unix.xml,v
retrieving revision 1.1
diff -u -p -r1.1 test-fullvirt-serial-unix.xml
--- tests/xmconfigdata/test-fullvirt-serial-unix.xml 26 Apr 2008 14:22:02 -0000 1.1
+++ tests/xmconfigdata/test-fullvirt-serial-unix.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-usbmouse.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-usbmouse.xml,v
retrieving revision 1.2
diff -u -p -r1.2 test-fullvirt-usbmouse.xml
--- tests/xmconfigdata/test-fullvirt-usbmouse.xml 9 Aug 2007 20:19:12 -0000 1.2
+++ tests/xmconfigdata/test-fullvirt-usbmouse.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-usbtablet-no-bus.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-usbtablet-no-bus.xml,v
retrieving revision 1.2
diff -u -p -r1.2 test-fullvirt-usbtablet-no-bus.xml
--- tests/xmconfigdata/test-fullvirt-usbtablet-no-bus.xml 9 Aug 2007 20:19:12 -0000 1.2
+++ tests/xmconfigdata/test-fullvirt-usbtablet-no-bus.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-usbtablet.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-usbtablet.xml,v
retrieving revision 1.2
diff -u -p -r1.2 test-fullvirt-usbtablet.xml
--- tests/xmconfigdata/test-fullvirt-usbtablet.xml 9 Aug 2007 20:19:12 -0000 1.2
+++ tests/xmconfigdata/test-fullvirt-usbtablet.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-fullvirt-utc.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-fullvirt-utc.xml,v
retrieving revision 1.3
diff -u -p -r1.3 test-fullvirt-utc.xml
--- tests/xmconfigdata/test-fullvirt-utc.xml 9 Aug 2007 20:19:12 -0000 1.3
+++ tests/xmconfigdata/test-fullvirt-utc.xml 7 May 2008 00:14:38 -0000
@@ -23,12 +23,12 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest2'/>
- <target dev='hda'/>
+ <target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='file'/>
<source file='/root/boot.iso'/>
- <target dev='hdc'/>
+ <target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
Index: tests/xmconfigdata/test-paravirt-net-e1000.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-paravirt-net-e1000.xml,v
retrieving revision 1.1
diff -u -p -r1.1 test-paravirt-net-e1000.xml
--- tests/xmconfigdata/test-paravirt-net-e1000.xml 30 Apr 2008 12:30:55 -0000 1.1
+++ tests/xmconfigdata/test-paravirt-net-e1000.xml 7 May 2008 00:14:38 -0000
@@ -12,7 +12,7 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest1'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<interface type='bridge'>
<mac address='00:16:3E:66:94:9C'/>
Index: tests/xmconfigdata/test-paravirt-new-pvfb.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-paravirt-new-pvfb.xml,v
retrieving revision 1.4
diff -u -p -r1.4 test-paravirt-new-pvfb.xml
--- tests/xmconfigdata/test-paravirt-new-pvfb.xml 26 Apr 2008 14:22:03 -0000 1.4
+++ tests/xmconfigdata/test-paravirt-new-pvfb.xml 7 May 2008 00:14:38 -0000
@@ -12,7 +12,7 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest1'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<interface type='bridge'>
<mac address='00:16:3E:66:94:9C'/>
Index: tests/xmconfigdata/test-paravirt-old-pvfb.xml
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigdata/test-paravirt-old-pvfb.xml,v
retrieving revision 1.4
diff -u -p -r1.4 test-paravirt-old-pvfb.xml
--- tests/xmconfigdata/test-paravirt-old-pvfb.xml 26 Apr 2008 14:22:03 -0000 1.4
+++ tests/xmconfigdata/test-paravirt-old-pvfb.xml 7 May 2008 00:14:38 -0000
@@ -12,7 +12,7 @@
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/HostVG/XenGuest1'/>
- <target dev='xvda'/>
+ <target dev='xvda' bus='xen'/>
</disk>
<interface type='bridge'>
<mac address='00:16:3E:66:94:9C'/>
--
|: Red Hat, Engineering, Boston -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 :|
3
2
The current domain XML format documentation reference on the website is
very out of date and not well structured since we organically added random
bits to it as we wrote drivers. This patch is starting from a clean slate.
I've removed all existing content and have written a clear & concise
reference for (all?) XML elements we support in the domain XML format.
This is following the style I've used for the storage and network XML
format docs.
Basically I've grouped the difference elements into logically related sets
and then described each one, giving examples and details of all attributes
they support. This also covers the new serial/paralle device syntax I
added recently.
The example configs for Xen, QEMU, etc domains are all in the driver
specific docs already, and linked at the bottom of this page.
The patch isn't particularly nice to review, so I'd recommend applying it
and looking at the resulting 'formatdomain.html' page in your web browser
Regads,
Daniel.
Index: formatdomain.html
===================================================================
RCS file: /data/cvs/libvirt/docs/formatdomain.html,v
retrieving revision 1.6
diff -u -p -r1.6 formatdomain.html
--- formatdomain.html 28 Apr 2008 08:29:35 -0000 1.6
+++ formatdomain.html 6 May 2008 23:56:33 -0000
@@ -114,206 +114,718 @@
</div>
<div id="content">
<h1>Domain XML format</h1>
- <p>This section describes the XML format used to represent domains, there are
-variations on the format based on the kind of domains run and the options
-used to launch them:</p>
- <h3 id="Normal"><a name="Normal1" id="Normal1">Normal paravirtualized Xen
-guests</a>:</h3>
- <p>The root element must be called <code>domain</code> with no namespace, the
-<code>type</code> attribute indicates the kind of hypervisor used, 'xen' is
-the default value. The <code>id</code> attribute gives the domain id at
-runtime (not however that this may change, for example if the domain is saved
-to disk and restored). The domain has a few children whose order is not
-significant:</p>
- <ul><li>name: the domain name, preferably ASCII based</li><li>memory: the maximum memory allocated to the domain in kilobytes</li><li>vcpu: the number of virtual cpu configured for the domain</li><li>os: a block describing the Operating System, its content will be
- dependent on the OS type
- <ul><li>type: indicate the OS type, always linux at this point</li><li>kernel: path to the kernel on the Domain 0 filesystem</li><li>initrd: an optional path for the init ramdisk on the Domain 0
- filesystem</li><li>cmdline: optional command line to the kernel</li><li>root: the root filesystem from the guest viewpoint, it may be
- passed as part of the cmdline content too</li></ul></li><li>devices: a list of <code>disk</code>, <code>interface</code> and
- <code>console</code> descriptions in no special order</li></ul>
- <p>The format of the devices and their type may grow over time, but the
-following should be sufficient for basic use:</p>
- <p>A <code>disk</code> device indicates a block device, it can have two
-values for the type attribute either 'file' or 'block' corresponding to the 2
-options available at the Xen layer. It has two mandatory children, and one
-optional one in no specific order:</p>
- <ul><li>source with a file attribute containing the path in Domain 0 to the
- file or a dev attribute if using a block device, containing the device
- name ('hda5' or '/dev/hda5')</li><li>target indicates in a dev attribute the device where it is mapped in
- the guest</li><li>readonly an optional empty element indicating the device is
- read-only</li><li>shareable an optional empty element indicating the device
- can be used read/write with other domains</li></ul>
- <p>An <code>interface</code> element describes a network device mapped on the
-guest, it also has a type whose value is currently 'bridge', it also have a
-number of children in no specific order:</p>
- <ul><li>source: indicating the bridge name</li><li>mac: the optional mac address provided in the address attribute</li><li>ip: the optional IP address provided in the address attribute</li><li>script: the script used to bridge the interface in the Domain 0</li><li>target: and optional target indicating the device name.</li></ul>
- <p>A <code>console</code> element describes a serial console connection to
-the guest. It has no children, and a single attribute <code>tty</code> which
-provides the path to the Pseudo TTY on which the guest console can be
-accessed</p>
- <p>Life cycle actions for the domain can also be expressed in the XML format,
-they drive what should be happening if the domain crashes, is rebooted or is
-poweroff. There is various actions possible when this happen:</p>
- <ul><li>destroy: The domain is cleaned up (that's the default normal processing
- in Xen)</li><li>restart: A new domain is started in place of the old one with the same
- configuration parameters</li><li>preserve: The domain will remain in memory until it is destroyed
- manually, it won't be running but allows for post-mortem debugging</li><li>rename-restart: a variant of the previous one but where the old domain
- is renamed before being saved to allow a restart</li></ul>
- <p>The following could be used for a Xen production system:</p>
- <pre><domain>
- ...
- <on_reboot>restart</on_reboot>
- <on_poweroff>destroy</on_poweroff>
- <on_crash>rename-restart</on_crash>
- ...
-</domain></pre>
- <p>While the format may be extended in various ways as support for more
-hypervisor types and features are added, it is expected that this core subset
-will remain functional in spite of the evolution of the library.</p>
- <h3 id="Fully">
- <a name="Fully1" id="Fully1">Fully virtualized guests</a>
- </h3>
- <p>There is a few things to notice specifically for HVM domains:</p>
- <ul><li>the optional <code><features></code> block is used to enable
- certain guest CPU / system features. For HVM guests the following
- features are defined:
- <ul><li><code>pae</code> - enable PAE memory addressing</li><li><code>apic</code> - enable IO APIC</li><li><code>acpi</code> - enable ACPI bios</li></ul></li><li>the optional <code><clock></code> element is used to specify
- whether the emulated BIOS clock in the guest is synced to either
- <code>localtime</code> or <code>utc</code>. In general Windows will
- want <code>localtime</code> while all other operating systems will
- want <code>utc</code>. The default is thus <code>utc</code></li><li>the <code><os></code> block description is very different, first
- it indicates that the type is 'hvm' for hardware virtualization, then
- instead of a kernel, boot and command line arguments, it points to an os
- boot loader which will extract the boot information from the boot device
- specified in a separate boot element. The <code>dev</code> attribute on
- the <code>boot</code> tag can be one of:
- <ul><li><code>fd</code> - boot from first floppy device</li><li><code>hd</code> - boot from first harddisk device</li><li><code>cdrom</code> - boot from first cdrom device</li></ul></li><li>the <code><devices></code> section includes an emulator entry
- pointing to an additional program in charge of emulating the devices</li><li>the disk entry indicates in the dev target section that the emulation
- for the drive is the first IDE disk device hda. The list of device names
- supported is dependent on the Hypervisor, but for Xen it can be any IDE
- device <code>hda</code>-<code>hdd</code>, or a floppy device
- <code>fda</code>, <code>fdb</code>. The <code><disk></code> element
- also supports a 'device' attribute to indicate what kinda of hardware to
- emulate. The following values are supported:
- <ul><li><code>floppy</code> - a floppy disk controller</li><li><code>disk</code> - a generic hard drive (the default it
- omitted)</li><li><code>cdrom</code> - a CDROM device</li></ul>
- For Xen 3.0.2 and earlier a CDROM device can only be emulated on the
- <code>hdc</code> channel, while for 3.0.3 and later, it can be emulated
- on any IDE channel.</li><li>the <code><devices></code> section also include at least one
- entry for the graphic device used to render the os. Currently there is
- just 2 types possible 'vnc' or 'sdl'. If the type is 'vnc', then an
- additional <code>port</code> attribute will be present indicating the TCP
- port on which the VNC server is accepting client connections.</li></ul>
- <p>It is likely that the HVM description gets additional optional elements
-and attributes as the support for fully virtualized domain expands,
-especially for the variety of devices emulated and the graphic support
-options offered.</p>
- <h3>
- <a name="Net1" id="Net1">Networking interface options</a>
- </h3>
- <p>The networking support in the QEmu and KVM case is more flexible, and
-support a variety of options:</p>
- <ol><li>Userspace SLIRP stack
- <p>Provides a virtual LAN with NAT to the outside world. The virtual
- network has DHCP & DNS services and will give the guest VM addresses
- starting from <code>10.0.2.15</code>. The default router will be
- <code>10.0.2.2</code> and the DNS server will be <code>10.0.2.3</code>.
- This networking is the only option for unprivileged users who need their
- VMs to have outgoing access. Example configs are:</p>
- <pre><interface type='user'/></pre>
- <pre>
-<interface type='user'>
- <mac address="11:22:33:44:55:66"/>
-</interface>
- </pre>
- </li><li>Virtual network
- <p>Provides a virtual network using a bridge device in the host.
- Depending on the virtual network configuration, the network may be
- totally isolated, NAT'ing to an explicit network device, or NAT'ing to
- the default route. DHCP and DNS are provided on the virtual network in
- all cases and the IP range can be determined by examining the virtual
- network config with '<code>virsh net-dumpxml <network
- name></code>'. There is one virtual network called 'default' setup out
- of the box which does NAT'ing to the default route and has an IP range of
- <code>192.168.22.0/255.255.255.0</code>. Each guest will have an
- associated tun device created with a name of vnetN, which can also be
- overridden with the <target> element. Example configs are:</p>
- <pre><interface type='network'>
- <source network='default'/>
-</interface>
-
-<interface type='network'>
- <source network='default'/>
- <target dev='vnet7'/>
- <mac address="11:22:33:44:55:66"/>
-</interface>
- </pre>
- </li><li>Bridge to to LAN
- <p>Provides a bridge from the VM directly onto the LAN. This assumes
- there is a bridge device on the host which has one or more of the hosts
- physical NICs enslaved. The guest VM will have an associated tun device
- created with a name of vnetN, which can also be overridden with the
- <target> element. The tun device will be enslaved to the bridge.
- The IP range / network configuration is whatever is used on the LAN. This
- provides the guest VM full incoming & outgoing net access just like a
- physical machine. Examples include:</p>
- <pre><interface type='bridge'>
- <source bridge='br0'/>
-</interface>
-
-<interface type='bridge'>
- <source bridge='br0'/>
- <target dev='vnet7'/>
- <mac address="11:22:33:44:55:66"/>
-</interface></pre>
- </li><li>Generic connection to LAN
- <p>Provides a means for the administrator to execute an arbitrary script
- to connect the guest's network to the LAN. The guest will have a tun
- device created with a name of vnetN, which can also be overridden with the
- <target> element. After creating the tun device a shell script will
- be run which is expected to do whatever host network integration is
- required. By default this script is called /etc/qemu-ifup but can be
- overridden.</p>
- <pre><interface type='ethernet'/>
+ <ul><li>
+ <a href="#elements">Element and attribute overview</a>
+ <ul><li>
+ <a href="#elementsMetadata">General metadata</a>
+ </li><li>
+ <a href="#elementsOS">Operating system booting</a>
+ <ul><li>
+ <a href="#elementsOSBIOS">BIOS bootloader</a>
+ </li><li>
+ <a href="#elementsOSBootloader">Host bootloader</a>
+ </li><li>
+ <a href="#elementsOSKernel">Direct kernel boot</a>
+ </li></ul>
+ </li><li>
+ <a href="#elementsResources">Basic resources</a>
+ </li><li>
+ <a href="#elementsLifecycle">Lifecycle control</a>
+ </li><li>
+ <a href="#elementsFeatures">Hypervisor features</a>
+ </li><li>
+ <a href="#elementsTime">Time keeping</a>
+ </li><li>
+ <a href="#elementsDevices">Devices</a>
+ <ul><li>
+ <a href="#elementsDisks">Hard drives, floppy disks, CDROMs</a>
+ </li><li>
+ <a href="#elementsNICS">Network interfaces</a>
+ <ul><li>
+ <a href="#elementsNICSVirtual">Virtual network</a>
+ </li><li>
+ <a href="#elementsNICSBridge">Bridge to to LAN</a>
+ </li><li>
+ <a href="#elementsNICSSlirp">Userspace SLIRP stack</a>
+ </li><li>
+ <a href="#elementsNICSEthernet">Generic ethernet connection</a>
+ </li><li>
+ <a href="#elementsNICSMulticast">Multicast tunnel</a>
+ </li><li>
+ <a href="#elementsNICSTCP">TCP tunnel</a>
+ </li></ul>
+ </li><li>
+ <a href="#elementsInput">Input devices</a>
+ </li><li>
+ <a href="#elementsGraphics">Graphical framebuffers</a>
+ </li><li>
+ <a href="#elementsConsole">Consoles, serial & parallel devices</a>
+ <ul><li>
+ <a href="#elementsCharSTDIO">Domain logfile</a>
+ </li><li>
+ <a href="#elementsCharFle">Device logfile</a>
+ </li><li>
+ <a href="#elementsCharVC">Virtual console</a>
+ </li><li>
+ <a href="#elementsCharNull">Null device</a>
+ </li><li>
+ <a href="#elementsCharPTY">Pseudo TTY</a>
+ </li><li>
+ <a href="#elementsCharHost">Host device proxy</a>
+ </li><li>
+ <a href="#elementsCharTCP">TCP client/server</a>
+ </li><li>
+ <a href="#elementsCharUDP">UDP network console</a>
+ </li><li>
+ <a href="#elementsCharUNIX">UNIX domain socket client/server</a>
+ </li></ul>
+ </li></ul>
+ </li></ul>
+ </li><li>
+ <a href="#examples">Example configs</a>
+ </li></ul>
+ <p>
+ This section describes the XML format used to represent domains, there are
+ variations on the format based on the kind of domains run and the options
+ used to launch them. For hypervisor specific details consult the
+ <a href="drivers.html">driver docs</a>
+ </p>
+ <h2>
+ <a name="elements" id="elements">Element and attribute overview</a>
+ </h2>
+ <p>
+ The root element required for all virtual machines is
+ named <code>domain</code>. It has two attributes, the
+ <code>type</code> specifies the hypervisor used for running
+ the domain. The allowed values are driver specific, but
+ include "xen", "kvm", "qemu", "lxc" and "kqemu". The
+ second attribute is <code>id</code> which is a unique
+ integer identifier for the running guest machine. Inactive
+ machines have no id value.
+ </p>
+ <h3>
+ <a name="elementsMetadata" id="elementsMetadata">General metadata</a>
+ </h3>
+ <pre>
+ <domain type='xen' id='3'>
+ <name>fv0</name>
+ <uuid>4dea22b31d52d8f32516782e98ab3fa0</uuid>
+ ...</pre>
+ <dl><dt><code>name</code></dt><dd>The content of the <code>name</code> element provides
+ a short name for the virtual machine. This name should
+ consist only of alpha-numeric characters and is required
+ to be unique within the scope of a single host. It is
+ often used to form the filename for storing the persistent
+ configuration file. <span class="since">Since 0.0.1</span></dd><dt><code>uuid</code></dt><dd>The content of the <code>uuid</code> element provides
+ a globally unique identifier for the virtual machine.
+ The format must be RFC 4122 compliant, eg <code>3e3fce45-4f53-4fa7-bb32-11f34168b82b</code>.
+ If omitted when defining/creating a new machine, a random
+ UUID is generated. <span class="since">Since 0.0.1</span></dd></dl>
+ <h3>
+ <a name="elementsOS" id="elementsOS">Operating system booting</a>
+ </h3>
+ <p>
+ There are a number of different ways to boot virtual machines
+ each with their own pros and cons.
+ </p>
+ <h4>
+ <a name="elementsOSBIOS" id="elementsOSBIOS">BIOS bootloader</a>
+ </h4>
+ <p>
+ Booting via the BIOS is available for hypervisors supporting
+ full virtualization. In this case the BIOS has a boot order
+ priority (floppy, harddisk, cdrom, network) determining where
+ to obtain/find the boot image.
+ </p>
+ <pre>
+ ...
+ <os>
+ <type>hvm</type>
+ <loader>/usr/lib/xen/boot/hvmloader</loader>
+ <boot dev='hd'/>
+ </os>
+ ...</pre>
+ <dl><dt><code>type</code></dt><dd>The content of the <code>type</code> element specifies the
+ type of operating system to be booted in the virtual machine.
+ <code>hvm</code> indicates that the OS is one designed to run
+ on bare metal, so requires full virtualization. <code>linux</code>
+ (badly named!) refers to an OS that supports the Xen 3 hypervisor
+ guest ABI. There are also two optional attributes, <code>arch</code>
+ specifying the CPU architecture to virtualization, and <code>machine</code>
+ refering to the machine type. The <a href="formatcaps.html">Capabilities XML</a>
+ provides details on allowed values for these. <span class="since">Since 0.0.1</span></dd><dt><code>loader</code></dt><dd>The optional <code>loader</code> tag refers to a firmware blob
+ used to assist the domain creation process. At this time, it is
+ only needed by Xen fullyvirtualized domains. <span class="since">Since 0.1.0</span></dd><dt><code>boot</code></dt><dd>The <code>dev</code> attribute takes one of the values "fd", "hd",
+ "cdrom" or "network" and is used to specify the next boot device
+ to consider. The <code>boot</code> element can be repeated multiple
+ times to setup a priority list of boot devices to try in turn.
+ <span class="since">Since 0.1.3</span>
+ </dd></dl>
+ <h4>
+ <a name="elementsOSBootloader" id="elementsOSBootloader">Host bootloader</a>
+ </h4>
+ <p>
+ Hypervisors employing paravirtualization do not usually emulate
+ a BIOS, and instead the host is responsible to kicking off the
+ operating system boot. This may use a pseduo-bootloader in the
+ host to provide an interface to choose a kernel for the guest.
+ An example is <code>pygrub</code> with Xen.
+ </p>
+ <pre>
+ ...
+ <bootloader>/usr/bin/pygrub</bootloader>
+ <bootloader_args>--append single</bootloader_args>
+ ...</pre>
+ <dl><dt><code>bootloader</code></dt><dd>The content of the <code>bootloader</code> element provides
+ a fullyqualified path to the bootloader executable in the
+ host OS. This bootloader will be run to choose which kernel
+ to boot. The required output of the bootloader is dependant
+ on the hypervisor in use. <span class="since">Since 0.1.0</span></dd><dt><code>bootloader_args</code></dt><dd>The optional <code>bootloader_args</code> element allows
+ command line arguments to be passed to the bootloader.
+ <span class="since">Since 0.2.3</span>
+ </dd></dl>
+ <h4>
+ <a name="elementsOSKernel" id="elementsOSKernel">Direct kernel boot</a>
+ </h4>
+ <p>
+ When installing a new guest OS it is often useful to boot directly
+ from a kernel and initrd stored in the host OS, allowing command
+ line arguments to be passed directly to the installer. This capability
+ is usually available for both para and full virtualized guests.
+ </p>
+ <pre>
+ ...
+ <os>
+ <type>hvm</type>
+ <loader>/usr/lib/xen/boot/hvmloader</loader>
+ <kernel>/root/f8-i386-vmlinuz</kernel>
+ <initrd>/root/f8-i386-initrd</initrd>
+ <cmdline>console=ttyS0 ks=http://example.com/f8-i386/os/</cmdline>
+ </os>
+ ...</pre>
+ <dl><dt><code>type</code></dt><dd>This element has the same semantics as described earlier in the
+ <a href="#elementsOSBIOS">BIOS boot section</a></dd><dt><code>type</code></dt><dd>This element has the same semantics as described earlier in the
+ <a href="#elementsOSBIOS">BIOS boot section</a></dd><dt><code>kernel</code></dt><dd>The contents of this element specify the fully-qualified path
+ to the kernel image in the host OS.</dd><dt><code>initrd</code></dt><dd>The contents of this element specify the fully-qualified path
+ to the (optional) ramdisk image in the host OS.</dd><dt><code>cmdline</code></dt><dd>The contents of this element specify arguments to be passed to
+ the kernel (or installer) at boottime. This is often used to
+ specify an alternate primary console (eg serial port), or the
+ installation media source / kickstart file</dd></dl>
+ <h3>
+ <a name="elementsResources" id="elementsResources">Basic resources</a>
+ </h3>
+ <pre>
+ ...
+ <memory>524288</memory>
+ <currentMemory>524288</currentMemory>
+ <vcpu>1</vcpu>
+ ...</pre>
+ <dl><dt><code>memory</code></dt><dd>The maximum allocation of memory for the guest at boot time.
+ The units for this value are bytes</dd><dt><code>currentMemory</code></dt><dd>The actual allocation of memory for the guest. This value
+ be less than the maximum allocation, to allow for ballooning
+ up the guests memory on the fly. If this is omitted, it defaults
+ to the same value as the <code>memory<code> element</code></code></dd><dt><code>vcpu</code></dt><dd>The content of this element defines the number of virtual
+ CPUs allocated for the guest OS.</dd></dl>
+ <h3>
+ <a name="elementsLifecycle" id="elementsLifecycle">Lifecycle control</a>
+ </h3>
+ <p>
+ It is sometimes neccessary to override the default actions taken
+ when a guest OS triggers a lifecycle operation. The following
+ collections of elements allow the actions to be specified. A
+ common use case is to force a reboot to be treated as a poweroff
+ when doing the initial OS installation. This allows the VM to be
+ re-configured for the first post-install bootup.
+ </p>
+ <pre>
+ ...
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ ...</pre>
+ <dl><dt><code>on_poweroff</code></dt><dd>The content of this element specifies the action to take when
+ the guest requests a poweroff.</dd><dt><code>on_poweroff</code></dt><dd>The content of this element specifies the action to take when
+ the guest requests a reboot.</dd><dt><code>on_poweroff</code></dt><dd>The content of this element specifies the action to take when
+ the guest crashes.</dd></dl>
+ <p>
+ Each of these states allow for the same four possible actions.
+ </p>
+ <dl><dt><code>destroy</code></dt><dd>The domain will be terminated completely and all resources
+ released</dd><dt><code>restart</code></dt><dd>The domain will be terminated, and then restarted with
+ the same configuration</dd><dt><code>preserve</code></dt><dd>The domain will be terminated, and its resource preserved
+ to allow analysis.</dd><dt><code>rename-restart</code></dt><dd>The domain will be terminated, and then restarted with
+ a new name</dd></dl>
+ <h3>
+ <a name="elementsFeatures" id="elementsFeatures">Hypervisor features</a>
+ </h3>
+ <p>
+ Hypervisors may allow certain CPU / machine features to be
+ toggled on/off.
+ </p>
+ <pre>
+ ...
+ <features>
+ <pae/>
+ <acpi/>
+ <apic/>
+ </features>
+ ...</pre>
+ <p>
+ All features are listed within the <code>features</code>
+ element, omitting a togglable feature tag turns it off.
+ The available features can be found by asking
+ for the <a href="formatcaps.html">capabilities XML</a>,
+ but a common set for fully virtualized domains are:
+ </p>
+ <dl><dt><code>pae</code></dt><dd>Physical address extension mode allows 32-bit guests
+ to address more than 4 GB of memory.</dd><dt><code>acpi</code></dt><dd>ACPI is useful for power management, for example, with
+ KVM guests it is required for graceful shutdown to work.
+ </dd></dl>
+ <h3>
+ <a name="elementsTime" id="elementsTime">Time keeping</a>
+ </h3>
+ <p>
+ The guest clock is typically initialized from the host clock.
+ Most operating systems expect the hardware clock to be kept
+ in UTC, and this is the default. Windows, however, expects
+ it to be in so called 'localtime'.
+ </p>
+ <pre>
+ ...
+ <clock sync="localtime"/>
+ ...</pre>
+ <dl><dt><code>clock</code></dt><dd>The <code>sync</code> attribute takes either "utc" or
+ "localtime" to specify how the guest clock is initialized
+ in relation to the host OS.
+ </dd></dl>
+ <h3>
+ <a name="elementsDevices" id="elementsDevices">Devices</a>
+ </h3>
+ <p>
+ The final set of XML elements are all used to descibe devices
+ provided to the guest domain. All devices occur as children
+ of the main <code>devices</code> element.
+ <span class="since">Since 0.1.3</span>
+ </p>
+ <pre>
+ ...
+ <devices>
+ <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
+ ...</pre>
+ <dl><dt><code>emulator</code></dt><dd>
+ The contents of the <code>emulator</code> element specify
+ the fully qualified path to the device model emulator binary.
+ The <a href="formatcaps.html">capabilities XML</a> specifies
+ the recommended default emulator to use for each particular
+ domain type / architecture combination.
+ </dd></dl>
+ <h4>
+ <a name="elementsDisks" id="elementsDisks">Hard drives, floppy disks, CDROMs</a>
+ </h4>
+ <p>
+ Any device that looks like a disk, be it a floppy, harddisk,
+ cdrom, or paravirtualized driver is specified via the <code>disk</code>
+ element.
+ </p>
+ <pre>
+ ...
+ <disk type='file'>
+ <driver name="tap" type="aio">
+ <source file='/var/lib/xen/images/fv0'/>
+ <target dev='hda' bus='ide'/>
+ </disk>
+ ...</pre>
+ <dl><dt><code>disk</code></dt><dd>The <code>disk</code> element is the main container for describing
+ disks. The <code>type</code> attribute is either "file" or "block"
+ and refers to the underlying source for the disk. The optional
+ <code>device</code> attribute indicates how the disk is to be exposed
+ to the guest OS. Possible values for this attribute are "floppy", "disk"
+ and "cdrom", defaulting to "disk".
+ <span class="since">Since 0.0.3; "device" attribute since 0.1.4</span></dd><dt><code>source</code></dt><dd>If the disk <code>type</code> is "file", then the <code>file</code> attribute
+ specifies the fully-qualified path to the file holding the disk. If the disk
+ <code>type</code> is "block", then the <code>dev</code> attribute specifies
+ the path to the host device to serve as the disk. <span class="since">Since 0.0.3</span></dd><dt><code>target</code></dt><dd>The <code>target</code> element controls the bus / device under which the
+ disk is exposed to the guest OS. The <code>dev</code> attribute indicates
+ the "logical" device name. The actual device name specified is not guarenteed to map to
+ the device name in the guest OS. Treat it as a device ordering hint.
+ The optional <code>bus</code> attribute specifies the type of disk device
+ to emulate; possible values are driver specific, with typical values being
+ "ide", "scsi", "virtio", "xen". If omitted, the bus type is inferred from
+ the style of the device name. eg, a device named 'sda' will typically be
+ exported using a SCSI bus.
+ <span class="since">Since 0.0.3; <code>bus</code> attribute since 0.4.3</span></dd><dt><code>driver</code></dt><dd>If the hypervisor supports multiple backend drivers, then the optional
+ <code>driver</code> element allows them to be selected. The <code>name</code>
+ attribute is the primary backend driver name, while the optional <code>type</code>
+ attribute provides the sub-type. <span class="since">Since 0.1.8</span>
+ </dd></dl>
+ <h4>
+ <a name="elementsNICS" id="elementsNICS">Network interfaces</a>
+ </h4>
+ <pre>
+ ...
+ <interface type='bridge'>
+ <source bridge='xenbr0'/>
+ <mac address='00:16:3e:5d:c7:9e'/>
+ <script path='vif-bridge'/>
+ </interface>
+ ...</pre>
+ <h5>
+ <a name="elementsNICSVirtual" id="elementsNICSVirtual">Virtual network</a>
+ </h5>
+ <p>
+ <strong><em>
+ This is the recommended config for general guest connectivity on
+ hosts with dynamic / wireless networking configs
+ </em></strong>
+ </p>
+ <p>
+ Provides a virtual network using a bridge device in the host.
+ Depending on the virtual network configuration, the network may be
+ totally isolated, NAT'ing to an explicit network device, or NAT'ing to
+ the default route. DHCP and DNS are provided on the virtual network in
+ all cases and the IP range can be determined by examining the virtual
+ network config with '<code>virsh net-dumpxml [networkname]</code>'.
+ There is one virtual network called 'default' setup out
+ of the box which does NAT'ing to the default route and has an IP range of
+ <code>192.168.22.0/255.255.255.0</code>. Each guest will have an
+ associated tun device created with a name of vnetN, which can also be
+ overridden with the <target> element.
+ </p>
+ <pre>
+ ...
+ <interface type='network'>
+ <source network='default'/>
+ </interface>
+ ...
+ <interface type='network'>
+ <source network='default'/>
+ <target dev='vnet7'/>
+ <mac address="11:22:33:44:55:66"/>
+ </interface>
+ ...</pre>
+ <h5>
+ <a name="elementsNICSBridge" id="elementsNICSBridge">Bridge to to LAN</a>
+ </h5>
+ <p>
+ <strong><em>
+ This is the recommended config for general guest connectivity on
+ hosts with static wired networking configs
+ </em></strong>
+ </p>
+ <p>
+ Provides a bridge from the VM directly onto the LAN. This assumes
+ there is a bridge device on the host which has one or more of the hosts
+ physical NICs enslaved. The guest VM will have an associated tun device
+ created with a name of vnetN, which can also be overridden with the
+ <target> element. The tun device will be enslaved to the bridge.
+ The IP range / network configuration is whatever is used on the LAN. This
+ provides the guest VM full incoming & outgoing net access just like a
+ physical machine.
+ </p>
+ <pre>
+ ...
+ <interface type='bridge'>
+ <source bridge='br0'/>
+ </interface>
-<interface type='ethernet'>
- <target dev='vnet7'/>
- <script path='/etc/qemu-ifup-mynet'/>
-</interface></pre>
- </li><li>Multicast tunnel
- <p>A multicast group is setup to represent a virtual network. Any VMs
- whose network devices are in the same multicast group can talk to each
- other even across hosts. This mode is also available to unprivileged
- users. There is no default DNS or DHCP support and no outgoing network
- access. To provide outgoing network access, one of the VMs should have a
- 2nd NIC which is connected to one of the first 4 network types and do the
- appropriate routing. The multicast protocol is compatible with that used
- by user mode linux guests too. The source address used must be from the
- multicast address block.</p>
- <pre><interface type='mcast'>
- <source address='230.0.0.1' port='5558'/>
-</interface></pre>
- </li><li>TCP tunnel
- <p>A TCP client/server architecture provides a virtual network. One VM
- provides the server end of the network, all other VMS are configured as
- clients. All network traffic is routed between the VMs via the server.
- This mode is also available to unprivileged users. There is no default
- DNS or DHCP support and no outgoing network access. To provide outgoing
- network access, one of the VMs should have a 2nd NIC which is connected
- to one of the first 4 network types and do the appropriate routing.</p>
- <p>Example server config:</p>
- <pre><interface type='server'>
- <source address='192.168.0.1' port='5558'/>
-</interface></pre>
- <p>Example client config:</p>
- <pre><interface type='client'>
- <source address='192.168.0.1' port='5558'/>
-</interface></pre>
- </li></ol>
- <p>To be noted, options 2, 3, 4 are also supported by Xen VMs, so it is
-possible to use these configs to have networking with both Xen &
-QEMU/KVMs connected to each other.</p>
- <h2>Example configs</h2>
+ <interface type='bridge'>
+ <source bridge='br0'/>
+ <target dev='vnet7'/>
+ <mac address="11:22:33:44:55:66"/>
+ </interface>
+ ...</pre>
+ <h5>
+ <a name="elementsNICSSlirp" id="elementsNICSSlirp">Userspace SLIRP stack</a>
+ </h5>
+ <p>
+ Provides a virtual LAN with NAT to the outside world. The virtual
+ network has DHCP & DNS services and will give the guest VM addresses
+ starting from <code>10.0.2.15</code>. The default router will be
+ <code>10.0.2.2</code> and the DNS server will be <code>10.0.2.3</code>.
+ This networking is the only option for unprivileged users who need their
+ VMs to have outgoing access.
+ </p>
+ <pre>
+ ...
+ <interface type='user'/>
+ ...
+ <interface type='user'>
+ <mac address="11:22:33:44:55:66"/>
+ </interface>
+ ...</pre>
+ <h5>
+ <a name="elementsNICSEthernet" id="elementsNICSEthernet">Generic ethernet connection</a>
+ </h5>
+ <p>
+ Provides a means for the administrator to execute an arbitrary script
+ to connect the guest's network to the LAN. The guest will have a tun
+ device created with a name of vnetN, which can also be overridden with the
+ <target> element. After creating the tun device a shell script will
+ be run which is expected to do whatever host network integration is
+ required. By default this script is called /etc/qemu-ifup but can be
+ overridden.
+ </p>
+ <pre>
+ ...
+ <interface type='ethernet'/>
+ ...
+ <interface type='ethernet'>
+ <target dev='vnet7'/>
+ <script path='/etc/qemu-ifup-mynet'/>
+ </interface>
+ ...</pre>
+ <h5>
+ <a name="elementsNICSMulticast" id="elementsNICSMulticast">Multicast tunnel</a>
+ </h5>
+ <p>
+ A multicast group is setup to represent a virtual network. Any VMs
+ whose network devices are in the same multicast group can talk to each
+ other even across hosts. This mode is also available to unprivileged
+ users. There is no default DNS or DHCP support and no outgoing network
+ access. To provide outgoing network access, one of the VMs should have a
+ 2nd NIC which is connected to one of the first 4 network types and do the
+ appropriate routing. The multicast protocol is compatible with that used
+ by user mode linux guests too. The source address used must be from the
+ multicast address block.
+ </p>
+ <pre>
+ ...
+ <interface type='mcast'>
+ <source address='230.0.0.1' port='5558'/>
+ </interface>
+ ...</pre>
+ <h5>
+ <a name="elementsNICSTCP" id="elementsNICSTCP">TCP tunnel</a>
+ </h5>
+ <p>
+ A TCP client/server architecture provides a virtual network. One VM
+ provides the server end of the network, all other VMS are configured as
+ clients. All network traffic is routed between the VMs via the server.
+ This mode is also available to unprivileged users. There is no default
+ DNS or DHCP support and no outgoing network access. To provide outgoing
+ network access, one of the VMs should have a 2nd NIC which is connected
+ to one of the first 4 network types and do the appropriate routing.</p>
+ <pre>
+ ...
+ <interface type='server'>
+ <source address='192.168.0.1' port='5558'/>
+ </interface>
+ ...
+ <interface type='client'>
+ <source address='192.168.0.1' port='5558'/>
+ </interface>
+ ...</pre>
+ <h4>
+ <a name="elementsInput" id="elementsInput">Input devices</a>
+ </h4>
+ <p>
+ Input devices allow interaction with the graphical framebuffer in the guest
+ virtual machine. When enabling the framebuffer, an input device is automatically
+ provided. It may be possible to add additional devices explicitly, for example,
+ to provide a graphics tablet for absolute cursor movement.
+ </p>
+ <pre>
+ ...
+ <input type='mouse' bus='usb'/>
+ ...</pre>
+ <dl><dt><code>input</code></dt><dd>The <code>input</code> element has one madatory attribute, the <code>type</code>
+ whose value can be either 'mouse' or 'tablet'. The latter provides absolute
+ cursor movement, while the former uses relative movement. The optional
+ <code>bus</code> attribute can be used to refine the exact device type.
+ It takes values "xen" (paravirtualized), "ps2" and "usb".</dd></dl>
+ <h4>
+ <a name="elementsGraphics" id="elementsGraphics">Graphical framebuffers</a>
+ </h4>
+ <p>
+ A graphics device allows for graphical interaction with the
+ guest OS. A guest will typically have either a framebuffer
+ or a text console configured to allow interaction with the
+ admin.
+ </p>
+ <pre>
+ ...
+ <graphics type='vnc' port='5904'/>
+ ...</pre>
+ <dl><dt><code>graphics</code></dt><dd>The <code>graphics</code> element has a mandatory <code>type</code>
+ attribute which takes the value "sdl" or "vnc". The former displays
+ a window on the host desktop, while the latter activates a VNC server.
+ If the latter is used the <code>port</code> attributes specifies the
+ TCP port number (with -1 indicating that it should be auto-allocated).
+ The <code>listen</code> attribute is an IP address for the server to
+ listen on. The <code>password</code> attribute provides a VNC password
+ in clear text.</dd></dl>
+ <h4>
+ <a name="elementsConsole" id="elementsConsole">Consoles, serial & parallel devices</a>
+ </h4>
+ <p>
+ A character device provides a way to interact with the virtual machine.
+ Paravirtualized consoles, serial ports and parallel ports are all
+ classed as character devices and so represented using the same syntax.
+ </p>
+ <pre>
+ ...
+ <parallel type='pty'>
+ <source path='/dev/pts/2'/>
+ <target port='0'/>
+ </parallel>
+ <serial type='pty'>
+ <source path='/dev/pts/3'/>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <source path='/dev/pts/4'/>
+ <target port='0'/>
+ </console>
+ </devices>
+ </domain></pre>
+ <dl><dt><code>parallel</code></dt><dd>Represents a parallel port</dd><dt><code>serial</code></dt><dd>Represents a serial port</dd><dt><code>console</code></dt><dd>Represents the primary console. This can be the paravirtualized
+ console with Xen guests, or duplicates the primary serial port
+ for fully virtualized guests without a paravirtualized console.</dd><dt><code>source</code></dt><dd>The attributes available for the <code>source</code> element
+ vary according to the <code>type</code> attribute on the parent
+ tag. Allowed variations will be described below</dd><dt><code>target</code></dt><dd>The port number of the character device is specified via the
+ <code>port</code> attribute, numbered starting from 1. There is
+ usually only one console device, and 0, 1 or 2 serial devices
+ or parallel devices.
+ </dd></dl>
+ <h5>
+ <a name="elementsCharSTDIO" id="elementsCharSTDIO">Domain logfile</a>
+ </h5>
+ <p>
+ This disables all input on the character device, and sends output
+ into the virtual machine's logfile
+ </p>
+ <pre>
+ ...
+ <console type='stdio'>
+ <target port='1'>
+ </console>
+ ...</pre>
+ <h5>
+ <a name="elementsCharFle" id="elementsCharFle">Device logfile</a>
+ </h5>
+ <p>
+ A file is opened and all data sent to the character
+ device is written to the file.
+ </p>
+ <pre>
+ ...
+ <serial type="file">
+ <source path="/var/log/vm/vm-serial.log"/>
+ <target port="1"/>
+ </serial>
+ ...</pre>
+ <h5>
+ <a name="elementsCharVC" id="elementsCharVC">Virtual console</a>
+ </h5>
+ <p>
+ Connects the character device to the graphical framebuffer in
+ a virtual console. This is typically accessed via a special
+ hotkey sequence such as "ctrl+alt+3"
+ </p>
+ <pre>
+ ...
+ <serial type='vc'>
+ <target port="1"/>
+ </serial>
+ ...</pre>
+ <h5>
+ <a name="elementsCharNull" id="elementsCharNull">Null device</a>
+ </h5>
+ <p>
+ Connects the character device to the void. No data is ever
+ provided to the input. All data written is discarded.
+ </p>
+ <pre>
+ ...
+ <serial type='null'>
+ <target port="1"/>
+ </serial>
+ ...</pre>
+ <h5>
+ <a name="elementsCharPTY" id="elementsCharPTY">Pseudo TTY</a>
+ </h5>
+ <p>
+ A Pseudo TTY is allocated using /dev/ptmx. A suitable client
+ such as 'virsh console' can connect to interact with the
+ serial port locally.
+ </p>
+ <pre>
+ ...
+ <serial type="pty">
+ <source path="/dev/pts/3"/>
+ <target port="1"/>
+ </serial>
+ ...</pre>
+ <p>
+ NB special case if <console type='pty'>, then the TTY
+ path is also duplicated as an attribute tty='/dv/pts/3'
+ on the top level <console> tag. This provides compat
+ with existing syntax for <console> tags.
+ </p>
+ <h5>
+ <a name="elementsCharHost" id="elementsCharHost">Host device proxy</a>
+ </h5>
+ <p>
+ The character device is passed through to the underlying
+ physical character device. The device types must match,
+ eg the emulated serial port should only be connected to
+ a host serial port - dont connect a serial port to a parallel
+ port.
+ </p>
+ <pre>
+ ...
+ <serial type="dev">
+ <source path="/dev/ttyS0"/>
+ <target port="1"/>
+ </serial>
+ ...</pre>
+ <h5>
+ <a name="elementsCharTCP" id="elementsCharTCP">TCP client/server</a>
+ </h5>
+ <p>
+ The character device acts as a TCP client connecting to a
+ remote server, or as a server waiting for a client connection.
+ </p>
+ <pre>
+ ...
+ <serial type="tcp">
+ <source mode="connect" host="0.0.0.0" service="2445"/>
+ <wiremode type="telnet"/>
+ <target port="1"/>
+ </serial>
+ ...</pre>
+ <h5>
+ <a name="elementsCharUDP" id="elementsCharUDP">UDP network console</a>
+ </h5>
+ <p>
+ The character device acts as a UDP netconsole service,
+ sending and receiving packets. This is a lossy service.
+ </p>
+ <pre>
+ ...
+ <serial type="udp">
+ <source mode="bind" host="0.0.0.0" service="2445"/>
+ <source mode="connect" host="0.0.0.0" service="2445"/>
+ <target port="1"/>
+ </serial>
+ ...</pre>
+ <h5>
+ <a name="elementsCharUNIX" id="elementsCharUNIX">UNIX domain socket client/server</a>
+ </h5>
+ <p>
+ The character device acts as a UNIX domain socket server,
+ accepting connections from local clients.
+ </p>
+ <pre>
+ ...
+ <serial type="unix">
+ <source mode="bind" path="/tmp/foo"/>
+ <target port="1"/>
+ </serial>
+ ...</pre>
+ <h2>
+ <a name="examples" id="examples">Example configs</a>
+ </h2>
<p>
Example configurations for each driver are provide on the
driver specific pages listed below
Index: formatdomain.html.in
===================================================================
RCS file: /data/cvs/libvirt/docs/formatdomain.html.in,v
retrieving revision 1.1
diff -u -p -r1.1 formatdomain.html.in
--- formatdomain.html.in 23 Apr 2008 17:08:31 -0000 1.1
+++ formatdomain.html.in 6 May 2008 23:56:34 -0000
@@ -2,245 +2,789 @@
<body>
<h1>Domain XML format</h1>
- <p>This section describes the XML format used to represent domains, there are
-variations on the format based on the kind of domains run and the options
-used to launch them:</p>
-
- <h3 id="Normal"><a name="Normal1" id="Normal1">Normal paravirtualized Xen
-guests</a>:</h3>
-
- <p>The root element must be called <code>domain</code> with no namespace, the
-<code>type</code> attribute indicates the kind of hypervisor used, 'xen' is
-the default value. The <code>id</code> attribute gives the domain id at
-runtime (not however that this may change, for example if the domain is saved
-to disk and restored). The domain has a few children whose order is not
-significant:</p>
- <ul>
- <li>name: the domain name, preferably ASCII based</li>
- <li>memory: the maximum memory allocated to the domain in kilobytes</li>
- <li>vcpu: the number of virtual cpu configured for the domain</li>
- <li>os: a block describing the Operating System, its content will be
- dependent on the OS type
- <ul><li>type: indicate the OS type, always linux at this point</li><li>kernel: path to the kernel on the Domain 0 filesystem</li><li>initrd: an optional path for the init ramdisk on the Domain 0
- filesystem</li><li>cmdline: optional command line to the kernel</li><li>root: the root filesystem from the guest viewpoint, it may be
- passed as part of the cmdline content too</li></ul></li>
- <li>devices: a list of <code>disk</code>, <code>interface</code> and
- <code>console</code> descriptions in no special order</li>
- </ul>
- <p>The format of the devices and their type may grow over time, but the
-following should be sufficient for basic use:</p>
- <p>A <code>disk</code> device indicates a block device, it can have two
-values for the type attribute either 'file' or 'block' corresponding to the 2
-options available at the Xen layer. It has two mandatory children, and one
-optional one in no specific order:</p>
- <ul>
- <li>source with a file attribute containing the path in Domain 0 to the
- file or a dev attribute if using a block device, containing the device
- name ('hda5' or '/dev/hda5')</li>
- <li>target indicates in a dev attribute the device where it is mapped in
- the guest</li>
- <li>readonly an optional empty element indicating the device is
- read-only</li>
- <li>shareable an optional empty element indicating the device
- can be used read/write with other domains</li>
- </ul>
- <p>An <code>interface</code> element describes a network device mapped on the
-guest, it also has a type whose value is currently 'bridge', it also have a
-number of children in no specific order:</p>
- <ul>
- <li>source: indicating the bridge name</li>
- <li>mac: the optional mac address provided in the address attribute</li>
- <li>ip: the optional IP address provided in the address attribute</li>
- <li>script: the script used to bridge the interface in the Domain 0</li>
- <li>target: and optional target indicating the device name.</li>
- </ul>
- <p>A <code>console</code> element describes a serial console connection to
-the guest. It has no children, and a single attribute <code>tty</code> which
-provides the path to the Pseudo TTY on which the guest console can be
-accessed</p>
- <p>Life cycle actions for the domain can also be expressed in the XML format,
-they drive what should be happening if the domain crashes, is rebooted or is
-poweroff. There is various actions possible when this happen:</p>
- <ul>
- <li>destroy: The domain is cleaned up (that's the default normal processing
- in Xen)</li>
- <li>restart: A new domain is started in place of the old one with the same
- configuration parameters</li>
- <li>preserve: The domain will remain in memory until it is destroyed
- manually, it won't be running but allows for post-mortem debugging</li>
- <li>rename-restart: a variant of the previous one but where the old domain
- is renamed before being saved to allow a restart</li>
- </ul>
- <p>The following could be used for a Xen production system:</p>
- <pre><domain>
- ...
- <on_reboot>restart</on_reboot>
- <on_poweroff>destroy</on_poweroff>
- <on_crash>rename-restart</on_crash>
- ...
-</domain></pre>
- <p>While the format may be extended in various ways as support for more
-hypervisor types and features are added, it is expected that this core subset
-will remain functional in spite of the evolution of the library.</p>
+ <ul id="toc"></ul>
- <h3 id="Fully"><a name="Fully1" id="Fully1">Fully virtualized guests</a></h3>
- <p>There is a few things to notice specifically for HVM domains:</p>
- <ul>
- <li>the optional <code><features></code> block is used to enable
- certain guest CPU / system features. For HVM guests the following
- features are defined:
- <ul><li><code>pae</code> - enable PAE memory addressing</li><li><code>apic</code> - enable IO APIC</li><li><code>acpi</code> - enable ACPI bios</li></ul></li>
- <li>the optional <code><clock></code> element is used to specify
- whether the emulated BIOS clock in the guest is synced to either
- <code>localtime</code> or <code>utc</code>. In general Windows will
- want <code>localtime</code> while all other operating systems will
- want <code>utc</code>. The default is thus <code>utc</code></li>
- <li>the <code><os></code> block description is very different, first
- it indicates that the type is 'hvm' for hardware virtualization, then
- instead of a kernel, boot and command line arguments, it points to an os
- boot loader which will extract the boot information from the boot device
- specified in a separate boot element. The <code>dev</code> attribute on
- the <code>boot</code> tag can be one of:
- <ul><li><code>fd</code> - boot from first floppy device</li><li><code>hd</code> - boot from first harddisk device</li><li><code>cdrom</code> - boot from first cdrom device</li></ul></li>
- <li>the <code><devices></code> section includes an emulator entry
- pointing to an additional program in charge of emulating the devices</li>
- <li>the disk entry indicates in the dev target section that the emulation
- for the drive is the first IDE disk device hda. The list of device names
- supported is dependent on the Hypervisor, but for Xen it can be any IDE
- device <code>hda</code>-<code>hdd</code>, or a floppy device
- <code>fda</code>, <code>fdb</code>. The <code><disk></code> element
- also supports a 'device' attribute to indicate what kinda of hardware to
- emulate. The following values are supported:
- <ul><li><code>floppy</code> - a floppy disk controller</li><li><code>disk</code> - a generic hard drive (the default it
- omitted)</li><li><code>cdrom</code> - a CDROM device</li></ul>
- For Xen 3.0.2 and earlier a CDROM device can only be emulated on the
- <code>hdc</code> channel, while for 3.0.3 and later, it can be emulated
- on any IDE channel.</li>
- <li>the <code><devices></code> section also include at least one
- entry for the graphic device used to render the os. Currently there is
- just 2 types possible 'vnc' or 'sdl'. If the type is 'vnc', then an
- additional <code>port</code> attribute will be present indicating the TCP
- port on which the VNC server is accepting client connections.</li>
- </ul>
- <p>It is likely that the HVM description gets additional optional elements
-and attributes as the support for fully virtualized domain expands,
-especially for the variety of devices emulated and the graphic support
-options offered.</p>
-
- <h3>
- <a name="Net1" id="Net1">Networking interface options</a>
- </h3>
- <p>The networking support in the QEmu and KVM case is more flexible, and
-support a variety of options:</p>
- <ol>
- <li>Userspace SLIRP stack
- <p>Provides a virtual LAN with NAT to the outside world. The virtual
- network has DHCP & DNS services and will give the guest VM addresses
- starting from <code>10.0.2.15</code>. The default router will be
- <code>10.0.2.2</code> and the DNS server will be <code>10.0.2.3</code>.
- This networking is the only option for unprivileged users who need their
- VMs to have outgoing access. Example configs are:</p>
- <pre><interface type='user'/></pre>
- <pre>
-<interface type='user'>
- <mac address="11:22:33:44:55:66"/>
-</interface>
- </pre>
- </li>
- <li>Virtual network
- <p>Provides a virtual network using a bridge device in the host.
- Depending on the virtual network configuration, the network may be
- totally isolated, NAT'ing to an explicit network device, or NAT'ing to
- the default route. DHCP and DNS are provided on the virtual network in
- all cases and the IP range can be determined by examining the virtual
- network config with '<code>virsh net-dumpxml <network
- name></code>'. There is one virtual network called 'default' setup out
- of the box which does NAT'ing to the default route and has an IP range of
- <code>192.168.22.0/255.255.255.0</code>. Each guest will have an
- associated tun device created with a name of vnetN, which can also be
- overridden with the <target> element. Example configs are:</p>
- <pre><interface type='network'>
- <source network='default'/>
-</interface>
-
-<interface type='network'>
- <source network='default'/>
- <target dev='vnet7'/>
- <mac address="11:22:33:44:55:66"/>
-</interface>
- </pre>
- </li>
- <li>Bridge to to LAN
- <p>Provides a bridge from the VM directly onto the LAN. This assumes
- there is a bridge device on the host which has one or more of the hosts
- physical NICs enslaved. The guest VM will have an associated tun device
- created with a name of vnetN, which can also be overridden with the
- <target> element. The tun device will be enslaved to the bridge.
- The IP range / network configuration is whatever is used on the LAN. This
- provides the guest VM full incoming & outgoing net access just like a
- physical machine. Examples include:</p>
- <pre><interface type='bridge'>
- <source bridge='br0'/>
-</interface>
-
-<interface type='bridge'>
- <source bridge='br0'/>
- <target dev='vnet7'/>
- <mac address="11:22:33:44:55:66"/>
-</interface></pre>
- </li>
- <li>Generic connection to LAN
- <p>Provides a means for the administrator to execute an arbitrary script
- to connect the guest's network to the LAN. The guest will have a tun
- device created with a name of vnetN, which can also be overridden with the
- <target> element. After creating the tun device a shell script will
- be run which is expected to do whatever host network integration is
- required. By default this script is called /etc/qemu-ifup but can be
- overridden.</p>
- <pre><interface type='ethernet'/>
-
-<interface type='ethernet'>
- <target dev='vnet7'/>
- <script path='/etc/qemu-ifup-mynet'/>
-</interface></pre>
- </li>
- <li>Multicast tunnel
- <p>A multicast group is setup to represent a virtual network. Any VMs
- whose network devices are in the same multicast group can talk to each
- other even across hosts. This mode is also available to unprivileged
- users. There is no default DNS or DHCP support and no outgoing network
- access. To provide outgoing network access, one of the VMs should have a
- 2nd NIC which is connected to one of the first 4 network types and do the
- appropriate routing. The multicast protocol is compatible with that used
- by user mode linux guests too. The source address used must be from the
- multicast address block.</p>
- <pre><interface type='mcast'>
- <source address='230.0.0.1' port='5558'/>
-</interface></pre>
- </li>
- <li>TCP tunnel
- <p>A TCP client/server architecture provides a virtual network. One VM
- provides the server end of the network, all other VMS are configured as
- clients. All network traffic is routed between the VMs via the server.
- This mode is also available to unprivileged users. There is no default
- DNS or DHCP support and no outgoing network access. To provide outgoing
- network access, one of the VMs should have a 2nd NIC which is connected
- to one of the first 4 network types and do the appropriate routing.</p>
- <p>Example server config:</p>
- <pre><interface type='server'>
- <source address='192.168.0.1' port='5558'/>
-</interface></pre>
- <p>Example client config:</p>
- <pre><interface type='client'>
- <source address='192.168.0.1' port='5558'/>
-</interface></pre>
- </li>
- </ol>
- <p>To be noted, options 2, 3, 4 are also supported by Xen VMs, so it is
-possible to use these configs to have networking with both Xen &
-QEMU/KVMs connected to each other.</p>
+ <p>
+ This section describes the XML format used to represent domains, there are
+ variations on the format based on the kind of domains run and the options
+ used to launch them. For hypervisor specific details consult the
+ <a href="drivers.html">driver docs</a>
+ </p>
+
+
+ <h2><a name="elements">Element and attribute overview</a></h2>
+
+ <p>
+ The root element required for all virtual machines is
+ named <code>domain</code>. It has two attributes, the
+ <code>type</code> specifies the hypervisor used for running
+ the domain. The allowed values are driver specific, but
+ include "xen", "kvm", "qemu", "lxc" and "kqemu". The
+ second attribute is <code>id</code> which is a unique
+ integer identifier for the running guest machine. Inactive
+ machines have no id value.
+ </p>
+
+
+ <h3><a name="elementsMetadata">General metadata</a></h3>
+
+ <pre>
+ <domain type='xen' id='3'>
+ <name>fv0</name>
+ <uuid>4dea22b31d52d8f32516782e98ab3fa0</uuid>
+ ...</pre>
+
+ <dl>
+ <dt><code>name</code></dt>
+ <dd>The content of the <code>name</code> element provides
+ a short name for the virtual machine. This name should
+ consist only of alpha-numeric characters and is required
+ to be unique within the scope of a single host. It is
+ often used to form the filename for storing the persistent
+ configuration file. <span class="since">Since 0.0.1</span></dd>
+ <dt><code>uuid</code></dt>
+ <dd>The content of the <code>uuid</code> element provides
+ a globally unique identifier for the virtual machine.
+ The format must be RFC 4122 compliant, eg <code>3e3fce45-4f53-4fa7-bb32-11f34168b82b</code>.
+ If omitted when defining/creating a new machine, a random
+ UUID is generated. <span class="since">Since 0.0.1</span></dd>
+ </dl>
+
+ <h3><a name="elementsOS">Operating system booting</a></h3>
+
+ <p>
+ There are a number of different ways to boot virtual machines
+ each with their own pros and cons.
+ </p>
+
+ <h4><a name="elementsOSBIOS">BIOS bootloader</a></h4>
+
+ <p>
+ Booting via the BIOS is available for hypervisors supporting
+ full virtualization. In this case the BIOS has a boot order
+ priority (floppy, harddisk, cdrom, network) determining where
+ to obtain/find the boot image.
+ </p>
+
+ <pre>
+ ...
+ <os>
+ <type>hvm</type>
+ <loader>/usr/lib/xen/boot/hvmloader</loader>
+ <boot dev='hd'/>
+ </os>
+ ...</pre>
+
+ <dl>
+ <dt><code>type</code></dt>
+ <dd>The content of the <code>type</code> element specifies the
+ type of operating system to be booted in the virtual machine.
+ <code>hvm</code> indicates that the OS is one designed to run
+ on bare metal, so requires full virtualization. <code>linux</code>
+ (badly named!) refers to an OS that supports the Xen 3 hypervisor
+ guest ABI. There are also two optional attributes, <code>arch</code>
+ specifying the CPU architecture to virtualization, and <code>machine</code>
+ refering to the machine type. The <a href="formatcaps.html">Capabilities XML</a>
+ provides details on allowed values for these. <span class="since">Since 0.0.1</span></dd>
+ <dt><code>loader</code></dt>
+ <dd>The optional <code>loader</code> tag refers to a firmware blob
+ used to assist the domain creation process. At this time, it is
+ only needed by Xen fullyvirtualized domains. <span class="since">Since 0.1.0</span></dd>
+ <dt><code>boot</code></dt>
+ <dd>The <code>dev</code> attribute takes one of the values "fd", "hd",
+ "cdrom" or "network" and is used to specify the next boot device
+ to consider. The <code>boot</code> element can be repeated multiple
+ times to setup a priority list of boot devices to try in turn.
+ <span class="since">Since 0.1.3</span>
+ </dd>
+ </dl>
+
+ <h4><a name="elementsOSBootloader">Host bootloader</a></h4>
+
+ <p>
+ Hypervisors employing paravirtualization do not usually emulate
+ a BIOS, and instead the host is responsible to kicking off the
+ operating system boot. This may use a pseduo-bootloader in the
+ host to provide an interface to choose a kernel for the guest.
+ An example is <code>pygrub</code> with Xen.
+ </p>
+
+ <pre>
+ ...
+ <bootloader>/usr/bin/pygrub</bootloader>
+ <bootloader_args>--append single</bootloader_args>
+ ...</pre>
+
+ <dl>
+ <dt><code>bootloader</code></dt>
+ <dd>The content of the <code>bootloader</code> element provides
+ a fullyqualified path to the bootloader executable in the
+ host OS. This bootloader will be run to choose which kernel
+ to boot. The required output of the bootloader is dependant
+ on the hypervisor in use. <span class="since">Since 0.1.0</span></dd>
+ <dt><code>bootloader_args</code></dt>
+ <dd>The optional <code>bootloader_args</code> element allows
+ command line arguments to be passed to the bootloader.
+ <span class="since">Since 0.2.3</span>
+ </dd>
+
+ </dl>
+
+ <h4><a name="elementsOSKernel">Direct kernel boot</a></h4>
+
+ <p>
+ When installing a new guest OS it is often useful to boot directly
+ from a kernel and initrd stored in the host OS, allowing command
+ line arguments to be passed directly to the installer. This capability
+ is usually available for both para and full virtualized guests.
+ </p>
+
+ <pre>
+ ...
+ <os>
+ <type>hvm</type>
+ <loader>/usr/lib/xen/boot/hvmloader</loader>
+ <kernel>/root/f8-i386-vmlinuz</kernel>
+ <initrd>/root/f8-i386-initrd</initrd>
+ <cmdline>console=ttyS0 ks=http://example.com/f8-i386/os/</cmdline>
+ </os>
+ ...</pre>
+
+ <dl>
+ <dt><code>type</code></dt>
+ <dd>This element has the same semantics as described earlier in the
+ <a href="#elementsOSBIOS">BIOS boot section</a></dd>
+ <dt><code>type</code></dt>
+ <dd>This element has the same semantics as described earlier in the
+ <a href="#elementsOSBIOS">BIOS boot section</a></dd>
+ <dt><code>kernel</code></dt>
+ <dd>The contents of this element specify the fully-qualified path
+ to the kernel image in the host OS.</dd>
+ <dt><code>initrd</code></dt>
+ <dd>The contents of this element specify the fully-qualified path
+ to the (optional) ramdisk image in the host OS.</dd>
+ <dt><code>cmdline</code></dt>
+ <dd>The contents of this element specify arguments to be passed to
+ the kernel (or installer) at boottime. This is often used to
+ specify an alternate primary console (eg serial port), or the
+ installation media source / kickstart file</dd>
+ </dl>
+
+ <h3><a name="elementsResources">Basic resources</a></h3>
+
+ <pre>
+ ...
+ <memory>524288</memory>
+ <currentMemory>524288</currentMemory>
+ <vcpu>1</vcpu>
+ ...</pre>
+
+ <dl>
+ <dt><code>memory</code></dt>
+ <dd>The maximum allocation of memory for the guest at boot time.
+ The units for this value are bytes</dd>
+ <dt><code>currentMemory</code></dt>
+ <dd>The actual allocation of memory for the guest. This value
+ be less than the maximum allocation, to allow for ballooning
+ up the guests memory on the fly. If this is omitted, it defaults
+ to the same value as the <code>memory<code> element</dd>
+ <dt><code>vcpu</code></dt>
+ <dd>The content of this element defines the number of virtual
+ CPUs allocated for the guest OS.</dd>
+ </dl>
+
+ <h3><a name="elementsLifecycle">Lifecycle control</a></h3>
+
+ <p>
+ It is sometimes neccessary to override the default actions taken
+ when a guest OS triggers a lifecycle operation. The following
+ collections of elements allow the actions to be specified. A
+ common use case is to force a reboot to be treated as a poweroff
+ when doing the initial OS installation. This allows the VM to be
+ re-configured for the first post-install bootup.
+ </p>
+
+ <pre>
+ ...
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ ...</pre>
+
+ <dl>
+ <dt><code>on_poweroff</code></dt>
+ <dd>The content of this element specifies the action to take when
+ the guest requests a poweroff.</dd>
+ <dt><code>on_poweroff</code></dt>
+ <dd>The content of this element specifies the action to take when
+ the guest requests a reboot.</dd>
+ <dt><code>on_poweroff</code></dt>
+ <dd>The content of this element specifies the action to take when
+ the guest crashes.</dd>
+ </dl>
+
+ <p>
+ Each of these states allow for the same four possible actions.
+ </p>
+
+ <dl>
+ <dt><code>destroy</code></dt>
+ <dd>The domain will be terminated completely and all resources
+ released</dd>
+ <dt><code>restart</code></dt>
+ <dd>The domain will be terminated, and then restarted with
+ the same configuration</dd>
+ <dt><code>preserve</code></dt>
+ <dd>The domain will be terminated, and its resource preserved
+ to allow analysis.</dd>
+ <dt><code>rename-restart</code></dt>
+ <dd>The domain will be terminated, and then restarted with
+ a new name</dd>
+ </dl>
+
+ <h3><a name="elementsFeatures">Hypervisor features</a></h3>
+
+ <p>
+ Hypervisors may allow certain CPU / machine features to be
+ toggled on/off.
+ </p>
+
+ <pre>
+ ...
+ <features>
+ <pae/>
+ <acpi/>
+ <apic/>
+ </features>
+ ...</pre>
+
+ <p>
+ All features are listed within the <code>features</code>
+ element, omitting a togglable feature tag turns it off.
+ The available features can be found by asking
+ for the <a href="formatcaps.html">capabilities XML</a>,
+ but a common set for fully virtualized domains are:
+ </p>
+
+ <dl>
+ <dt><code>pae</code></dt>
+ <dd>Physical address extension mode allows 32-bit guests
+ to address more than 4 GB of memory.</dd>
+ <dt><code>acpi</code></dt>
+ <dd>ACPI is useful for power management, for example, with
+ KVM guests it is required for graceful shutdown to work.
+ </dd>
+ </dl>
+
+ <h3><a name="elementsTime">Time keeping</a></h3>
+
+ <p>
+ The guest clock is typically initialized from the host clock.
+ Most operating systems expect the hardware clock to be kept
+ in UTC, and this is the default. Windows, however, expects
+ it to be in so called 'localtime'.
+ </p>
+
+ <pre>
+ ...
+ <clock sync="localtime"/>
+ ...</pre>
+
+ <dl>
+ <dt><code>clock</code></dt>
+ <dd>The <code>sync</code> attribute takes either "utc" or
+ "localtime" to specify how the guest clock is initialized
+ in relation to the host OS.
+ </dd>
+ </dl>
+
+ <h3><a name="elementsDevices">Devices</a></h3>
+
+ <p>
+ The final set of XML elements are all used to descibe devices
+ provided to the guest domain. All devices occur as children
+ of the main <code>devices</code> element.
+ <span class="since">Since 0.1.3</span>
+ </p>
+
+ <pre>
+ ...
+ <devices>
+ <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
+ ...</pre>
+
+ <dl>
+ <dt><code>emulator</code></dt>
+ <dd>
+ The contents of the <code>emulator</code> element specify
+ the fully qualified path to the device model emulator binary.
+ The <a href="formatcaps.html">capabilities XML</a> specifies
+ the recommended default emulator to use for each particular
+ domain type / architecture combination.
+ </dd>
+ </dl>
+
+ <h4><a name="elementsDisks">Hard drives, floppy disks, CDROMs</a></h4>
+
+ <p>
+ Any device that looks like a disk, be it a floppy, harddisk,
+ cdrom, or paravirtualized driver is specified via the <code>disk</code>
+ element.
+ </p>
+
+ <pre>
+ ...
+ <disk type='file'>
+ <driver name="tap" type="aio">
+ <source file='/var/lib/xen/images/fv0'/>
+ <target dev='hda' bus='ide'/>
+ </disk>
+ ...</pre>
+
+ <dl>
+ <dt><code>disk</code></dt>
+ <dd>The <code>disk</code> element is the main container for describing
+ disks. The <code>type</code> attribute is either "file" or "block"
+ and refers to the underlying source for the disk. The optional
+ <code>device</code> attribute indicates how the disk is to be exposed
+ to the guest OS. Possible values for this attribute are "floppy", "disk"
+ and "cdrom", defaulting to "disk".
+ <span class="since">Since 0.0.3; "device" attribute since 0.1.4</span></dd>
+ <dt><code>source</code></dt>
+ <dd>If the disk <code>type</code> is "file", then the <code>file</code> attribute
+ specifies the fully-qualified path to the file holding the disk. If the disk
+ <code>type</code> is "block", then the <code>dev</code> attribute specifies
+ the path to the host device to serve as the disk. <span class="since">Since 0.0.3</span></dd>
+ <dt><code>target</code></dt>
+ <dd>The <code>target</code> element controls the bus / device under which the
+ disk is exposed to the guest OS. The <code>dev</code> attribute indicates
+ the "logical" device name. The actual device name specified is not guarenteed to map to
+ the device name in the guest OS. Treat it as a device ordering hint.
+ The optional <code>bus</code> attribute specifies the type of disk device
+ to emulate; possible values are driver specific, with typical values being
+ "ide", "scsi", "virtio", "xen". If omitted, the bus type is inferred from
+ the style of the device name. eg, a device named 'sda' will typically be
+ exported using a SCSI bus.
+ <span class="since">Since 0.0.3; <code>bus</code> attribute since 0.4.3</span></dd>
+ <dt><code>driver</code></dt>
+ <dd>If the hypervisor supports multiple backend drivers, then the optional
+ <code>driver</code> element allows them to be selected. The <code>name</code>
+ attribute is the primary backend driver name, while the optional <code>type</code>
+ attribute provides the sub-type. <span class="since">Since 0.1.8</span>
+ </dd>
+ </dl>
+
+ <h4><a name="elementsNICS">Network interfaces</a></h4>
+
+ <pre>
+ ...
+ <interface type='bridge'>
+ <source bridge='xenbr0'/>
+ <mac address='00:16:3e:5d:c7:9e'/>
+ <script path='vif-bridge'/>
+ </interface>
+ ...</pre>
+
+ <h5><a name="elementsNICSVirtual">Virtual network</a></h5>
+
+ <p>
+ <strong><em>
+ This is the recommended config for general guest connectivity on
+ hosts with dynamic / wireless networking configs
+ </em></strong>
+ </p>
+
+ <p>
+ Provides a virtual network using a bridge device in the host.
+ Depending on the virtual network configuration, the network may be
+ totally isolated, NAT'ing to an explicit network device, or NAT'ing to
+ the default route. DHCP and DNS are provided on the virtual network in
+ all cases and the IP range can be determined by examining the virtual
+ network config with '<code>virsh net-dumpxml [networkname]</code>'.
+ There is one virtual network called 'default' setup out
+ of the box which does NAT'ing to the default route and has an IP range of
+ <code>192.168.22.0/255.255.255.0</code>. Each guest will have an
+ associated tun device created with a name of vnetN, which can also be
+ overridden with the <target> element.
+ </p>
+
+ <pre>
+ ...
+ <interface type='network'>
+ <source network='default'/>
+ </interface>
+ ...
+ <interface type='network'>
+ <source network='default'/>
+ <target dev='vnet7'/>
+ <mac address="11:22:33:44:55:66"/>
+ </interface>
+ ...</pre>
+
+ <h5><a name="elementsNICSBridge">Bridge to to LAN</a></h5>
+
+ <p>
+ <strong><em>
+ This is the recommended config for general guest connectivity on
+ hosts with static wired networking configs
+ </em></strong>
+ </p>
+
+ <p>
+ Provides a bridge from the VM directly onto the LAN. This assumes
+ there is a bridge device on the host which has one or more of the hosts
+ physical NICs enslaved. The guest VM will have an associated tun device
+ created with a name of vnetN, which can also be overridden with the
+ <target> element. The tun device will be enslaved to the bridge.
+ The IP range / network configuration is whatever is used on the LAN. This
+ provides the guest VM full incoming & outgoing net access just like a
+ physical machine.
+ </p>
+
+ <pre>
+ ...
+ <interface type='bridge'>
+ <source bridge='br0'/>
+ </interface>
+
+ <interface type='bridge'>
+ <source bridge='br0'/>
+ <target dev='vnet7'/>
+ <mac address="11:22:33:44:55:66"/>
+ </interface>
+ ...</pre>
+
+ <h5><a name="elementsNICSSlirp">Userspace SLIRP stack</a></h5>
+
+ <p>
+ Provides a virtual LAN with NAT to the outside world. The virtual
+ network has DHCP & DNS services and will give the guest VM addresses
+ starting from <code>10.0.2.15</code>. The default router will be
+ <code>10.0.2.2</code> and the DNS server will be <code>10.0.2.3</code>.
+ This networking is the only option for unprivileged users who need their
+ VMs to have outgoing access.
+ </p>
+
+ <pre>
+ ...
+ <interface type='user'/>
+ ...
+ <interface type='user'>
+ <mac address="11:22:33:44:55:66"/>
+ </interface>
+ ...</pre>
+
+
+ <h5><a name="elementsNICSEthernet">Generic ethernet connection</a></h5>
+
+ <p>
+ Provides a means for the administrator to execute an arbitrary script
+ to connect the guest's network to the LAN. The guest will have a tun
+ device created with a name of vnetN, which can also be overridden with the
+ <target> element. After creating the tun device a shell script will
+ be run which is expected to do whatever host network integration is
+ required. By default this script is called /etc/qemu-ifup but can be
+ overridden.
+ </p>
+
+ <pre>
+ ...
+ <interface type='ethernet'/>
+ ...
+ <interface type='ethernet'>
+ <target dev='vnet7'/>
+ <script path='/etc/qemu-ifup-mynet'/>
+ </interface>
+ ...</pre>
+
+ <h5><a name="elementsNICSMulticast">Multicast tunnel</a></h5>
+
+ <p>
+ A multicast group is setup to represent a virtual network. Any VMs
+ whose network devices are in the same multicast group can talk to each
+ other even across hosts. This mode is also available to unprivileged
+ users. There is no default DNS or DHCP support and no outgoing network
+ access. To provide outgoing network access, one of the VMs should have a
+ 2nd NIC which is connected to one of the first 4 network types and do the
+ appropriate routing. The multicast protocol is compatible with that used
+ by user mode linux guests too. The source address used must be from the
+ multicast address block.
+ </p>
+
+ <pre>
+ ...
+ <interface type='mcast'>
+ <source address='230.0.0.1' port='5558'/>
+ </interface>
+ ...</pre>
+
+ <h5><a name="elementsNICSTCP">TCP tunnel</a></h5>
+
+ <p>
+ A TCP client/server architecture provides a virtual network. One VM
+ provides the server end of the network, all other VMS are configured as
+ clients. All network traffic is routed between the VMs via the server.
+ This mode is also available to unprivileged users. There is no default
+ DNS or DHCP support and no outgoing network access. To provide outgoing
+ network access, one of the VMs should have a 2nd NIC which is connected
+ to one of the first 4 network types and do the appropriate routing.</p>
+
+ <pre>
+ ...
+ <interface type='server'>
+ <source address='192.168.0.1' port='5558'/>
+ </interface>
+ ...
+ <interface type='client'>
+ <source address='192.168.0.1' port='5558'/>
+ </interface>
+ ...</pre>
+
+
+ <h4><a name="elementsInput">Input devices</a></h4>
+
+ <p>
+ Input devices allow interaction with the graphical framebuffer in the guest
+ virtual machine. When enabling the framebuffer, an input device is automatically
+ provided. It may be possible to add additional devices explicitly, for example,
+ to provide a graphics tablet for absolute cursor movement.
+ </p>
+
+ <pre>
+ ...
+ <input type='mouse' bus='usb'/>
+ ...</pre>
+
+ <dl>
+ <dt><code>input</code></dt>
+ <dd>The <code>input</code> element has one madatory attribute, the <code>type</code>
+ whose value can be either 'mouse' or 'tablet'. The latter provides absolute
+ cursor movement, while the former uses relative movement. The optional
+ <code>bus</code> attribute can be used to refine the exact device type.
+ It takes values "xen" (paravirtualized), "ps2" and "usb".</dd>
+ </dl>
+
+
+ <h4><a name="elementsGraphics">Graphical framebuffers</a></h4>
+
+ <p>
+ A graphics device allows for graphical interaction with the
+ guest OS. A guest will typically have either a framebuffer
+ or a text console configured to allow interaction with the
+ admin.
+ </p>
+
+ <pre>
+ ...
+ <graphics type='vnc' port='5904'/>
+ ...</pre>
+
+ <dl>
+ <dt><code>graphics</code></dt>
+ <dd>The <code>graphics</code> element has a mandatory <code>type</code>
+ attribute which takes the value "sdl" or "vnc". The former displays
+ a window on the host desktop, while the latter activates a VNC server.
+ If the latter is used the <code>port</code> attributes specifies the
+ TCP port number (with -1 indicating that it should be auto-allocated).
+ The <code>listen</code> attribute is an IP address for the server to
+ listen on. The <code>password</code> attribute provides a VNC password
+ in clear text.</dd>
+ </dl>
+
+ <h4><a name="elementsConsole">Consoles, serial & parallel devices</a></h4>
+
+ <p>
+ A character device provides a way to interact with the virtual machine.
+ Paravirtualized consoles, serial ports and parallel ports are all
+ classed as character devices and so represented using the same syntax.
+ </p>
+
+ <pre>
+ ...
+ <parallel type='pty'>
+ <source path='/dev/pts/2'/>
+ <target port='0'/>
+ </parallel>
+ <serial type='pty'>
+ <source path='/dev/pts/3'/>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <source path='/dev/pts/4'/>
+ <target port='0'/>
+ </console>
+ </devices>
+ </domain></pre>
+
+
+ <dl>
+ <dt><code>parallel</code></dt>
+ <dd>Represents a parallel port</dd>
+ <dt><code>serial</code></dt>
+ <dd>Represents a serial port</dd>
+ <dt><code>console</code></dt>
+ <dd>Represents the primary console. This can be the paravirtualized
+ console with Xen guests, or duplicates the primary serial port
+ for fully virtualized guests without a paravirtualized console.</dd>
+ <dt><code>source</code></dt>
+ <dd>The attributes available for the <code>source</code> element
+ vary according to the <code>type</code> attribute on the parent
+ tag. Allowed variations will be described below</dd>
+ <dt><code>target</code></dt>
+ <dd>The port number of the character device is specified via the
+ <code>port</code> attribute, numbered starting from 1. There is
+ usually only one console device, and 0, 1 or 2 serial devices
+ or parallel devices.
+ </dl>
+
+ <h5><a name="elementsCharSTDIO">Domain logfile</a></h5>
+
+ <p>
+ This disables all input on the character device, and sends output
+ into the virtual machine's logfile
+ </p>
+
+ <pre>
+ ...
+ <console type='stdio'>
+ <target port='1'>
+ </console>
+ ...</pre>
+
+
+ <h5><a name="elementsCharFle">Device logfile</a></h5>
+
+ <p>
+ A file is opened and all data sent to the character
+ device is written to the file.
+ </p>
+
+ <pre>
+ ...
+ <serial type="file">
+ <source path="/var/log/vm/vm-serial.log"/>
+ <target port="1"/>
+ </serial>
+ ...</pre>
+
+ <h5><a name="elementsCharVC">Virtual console</a></h5>
+
+ <p>
+ Connects the character device to the graphical framebuffer in
+ a virtual console. This is typically accessed via a special
+ hotkey sequence such as "ctrl+alt+3"
+ </p>
+
+ <pre>
+ ...
+ <serial type='vc'>
+ <target port="1"/>
+ </serial>
+ ...</pre>
+
+ <h5><a name="elementsCharNull">Null device</a></h5>
+
+ <p>
+ Connects the character device to the void. No data is ever
+ provided to the input. All data written is discarded.
+ </p>
+
+ <pre>
+ ...
+ <serial type='null'>
+ <target port="1"/>
+ </serial>
+ ...</pre>
+
+ <h5><a name="elementsCharPTY">Pseudo TTY</a></h5>
+
+ <p>
+ A Pseudo TTY is allocated using /dev/ptmx. A suitable client
+ such as 'virsh console' can connect to interact with the
+ serial port locally.
+ </p>
+
+ <pre>
+ ...
+ <serial type="pty">
+ <source path="/dev/pts/3"/>
+ <target port="1"/>
+ </serial>
+ ...</pre>
+
+ <p>
+ NB special case if <console type='pty'>, then the TTY
+ path is also duplicated as an attribute tty='/dv/pts/3'
+ on the top level <console> tag. This provides compat
+ with existing syntax for <console> tags.
+ </p>
+
+ <h5><a name="elementsCharHost">Host device proxy</a></h5>
+
+ <p>
+ The character device is passed through to the underlying
+ physical character device. The device types must match,
+ eg the emulated serial port should only be connected to
+ a host serial port - dont connect a serial port to a parallel
+ port.
+ </p>
+
+ <pre>
+ ...
+ <serial type="dev">
+ <source path="/dev/ttyS0"/>
+ <target port="1"/>
+ </serial>
+ ...</pre>
+
+ <h5><a name="elementsCharTCP">TCP client/server</a></h5>
+
+ <p>
+ The character device acts as a TCP client connecting to a
+ remote server, or as a server waiting for a client connection.
+ </p>
+
+ <pre>
+ ...
+ <serial type="tcp">
+ <source mode="connect" host="0.0.0.0" service="2445"/>
+ <wiremode type="telnet"/>
+ <target port="1"/>
+ </serial>
+ ...</pre>
+
+ <h5><a name="elementsCharUDP">UDP network console</a></h5>
+
+ <p>
+ The character device acts as a UDP netconsole service,
+ sending and receiving packets. This is a lossy service.
+ </p>
+
+ <pre>
+ ...
+ <serial type="udp">
+ <source mode="bind" host="0.0.0.0" service="2445"/>
+ <source mode="connect" host="0.0.0.0" service="2445"/>
+ <target port="1"/>
+ </serial>
+ ...</pre>
+
+ <h5><a name="elementsCharUNIX">UNIX domain socket client/server</a></h5>
+
+ <p>
+ The character device acts as a UNIX domain socket server,
+ accepting connections from local clients.
+ </p>
+
+ <pre>
+ ...
+ <serial type="unix">
+ <source mode="bind" path="/tmp/foo"/>
+ <target port="1"/>
+ </serial>
+ ...</pre>
- <h2>Example configs</h2>
+ <h2><a name="examples">Example configs</a></h2>
<p>
Example configurations for each driver are provide on the
Index: page.xsl
===================================================================
RCS file: /data/cvs/libvirt/docs/page.xsl,v
retrieving revision 1.8
diff -u -p -r1.8 page.xsl
--- page.xsl 6 May 2008 23:23:55 -0000 1.8
+++ page.xsl 6 May 2008 23:56:34 -0000
@@ -62,28 +62,30 @@
<xsl:template name="toc">
<ul>
<xsl:for-each select="/html/body/h2[count(a) = 1]">
- <xsl:variable name="thishead" select="."/>
+ <xsl:variable name="thish2" select="."/>
<li>
<a href="#{a/@name}"><xsl:value-of select="a/text()"/></a>
- <xsl:if test="count(./following-sibling::h3[preceding-sibling::h2[1] = $thishead and count(a) = 1]) > 0">
+ <xsl:if test="count(./following-sibling::h3[preceding-sibling::h2[1] = $thish2 and count(a) = 1]) > 0">
<ul>
- <xsl:for-each select="./following-sibling::h3[preceding-sibling::h2[1] = $thishead and count(a) = 1]">
- <xsl:variable name="thissubhead" select="."/>
+ <xsl:for-each select="./following-sibling::h3[preceding-sibling::h2[1] = $thish2 and count(a) = 1]">
+ <xsl:variable name="thish3" select="."/>
<li>
<a href="#{a/@name}"><xsl:value-of select="a/text()"/></a>
- <xsl:if test="count(./following-sibling::h4[preceding-sibling::h3[1] = $thissubhead and count(a) = 1]) > 0">
+ <xsl:if test="count(./following-sibling::h4[preceding-sibling::h3[1] = $thish3 and count(a) = 1]) > 0">
<ul>
- <xsl:for-each select="./following-sibling::h4[preceding-sibling::h3[1] = $thissubhead and count(a) = 1]">
+ <xsl:for-each select="./following-sibling::h4[preceding-sibling::h3[1] = $thish3 and count(a) = 1]">
+ <xsl:variable name="thish4" select="."/>
<li>
<a href="#{a/@name}"><xsl:value-of select="a/text()"/></a>
- <xsl:if test="count(./following-sibling::h5[preceding-sibling::h4[1] = $thissubhead and count(a) = 1]) > 0">
+ <xsl:if test="count(./following-sibling::h5[preceding-sibling::h4[1] = $thish4 and count(a) = 1]) > 0">
<ul>
- <xsl:for-each select="./following-sibling::h5[preceding-sibling::h4[1] = $thissubhead and count(a) = 1]">
+ <xsl:for-each select="./following-sibling::h5[preceding-sibling::h4[1] = $thish4 and count(a) = 1]">
+ <xsl:variable name="thish5" select="."/>
<li>
<a href="#{a/@name}"><xsl:value-of select="a/text()"/></a>
- <xsl:if test="count(./following-sibling::h6[preceding-sibling::h5[1] = $thissubhead and count(a) = 1]) > 0">
+ <xsl:if test="count(./following-sibling::h6[preceding-sibling::h5[1] = $thish5 and count(a) = 1]) > 0">
<ul>
- <xsl:for-each select="./following-sibling::h6[preceding-sibling::h5[1] = $thissubhead and count(a) = 1]">
+ <xsl:for-each select="./following-sibling::h6[preceding-sibling::h5[1] = $thish5 and count(a) = 1]">
<li>
<a href="#{a/@name}"><xsl:value-of select="a/text()"/></a>
</li>
--
|: Red Hat, Engineering, Boston -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 :|
2
1
The current docs showing a possible PolicyKit.conf with the example:
<match action="org.libvirt.unix.manage" user="fred">
<return result="yes"/>
</match>
With PolicyKit-0.6-2.fc8, polkit-config-file-validate complains
about this format. 'man PolicyKit.conf' gives a similar example
with the format:
<match action="org.libvirt.unix.manage">
<match user="fred">
<return result="yes"/>
</match>
</match>
This doesn't cause any complaints and works. The attached patch updates
the docs with this format.
Thanks,
Cole
diff --git a/docs/auth.html.in b/docs/auth.html.in
index 7340360..04b1210 100644
--- a/docs/auth.html.in
+++ b/docs/auth.html.in
@@ -77,11 +77,15 @@ while requiring <code>joe</code> to authenticate with the admin password,
would require adding the following snippet to <code>PolicyKit.conf</code>.
</p>
<pre>
- <match action="org.libvirt.unix.manage" user="fred">
- <return result="yes"/>
+ <match action="org.libvirt.unix.manage">
+ <match user="fred">
+ <return result="yes"/>
+ </match>
</match>
- <match action="org.libvirt.unix.manage" user="joe">
- <return result="auth_admin"/>
+ <match action="org.libvirt.unix.manage">
+ <match user="joe">
+ <return result="auth_admin"/>
+ </match>
</match>
</pre>
<h3><a name="ACL_server_username">Username/password auth</a></h3>
2
1
This patch changes the lxc tty forwarding process to use epoll instead of poll.
This is done to avoid a cpu consuming loop when a user disconnects from the
container console.
During some testing, we found that when the slave end of a tty is closed, calls
to poll() on the master end will return immediately with POLLHUP until the slave
end is opened again. The result of this is that if you connect to the container
console using virsh and then ctrl-] out of it, the container tty process will
chew up the processor handling POLLHUP. This event can't be disabled regardless
of what is set in the events field.
This can be avoided by using epoll. When used in edge triggered mode, you see
the initial EPOLLHUP but will not see another one until someone connects and
then disconnects from the console again. This also drove some changes into how
the regular input data is handled. Once an EPOLLIN is seen from an fd, another
one will not be surfaced until all data has been read from the file (EAGAIN is
returned by read).
--
Best Regards,
Dave Leskovec
IBM Linux Technology Center
Open Virtualization
4
6
Note: I haven't tried building this on Linux yet, so we may have some
#ifdef or Makefile changes on non-Solaris platforms.
Please Cc: Eunice.Moon(a)Sun.COM on any response.
Thanks,
Ryan
LDoms Support
This patch adds the Logical Domains (LDoms) support for the SPARC
platforms. LDoms software is Sun Microsystem's virtualization technology
to subdivide a supported system's resources (CPUs, memory, I/O, and
storage) creating partitions called logical domains. The Logical Domains
Manager is used to create and manage logical domains and maps logical
domains to physical resources. The LDoms Manager provides a command-line
interface and also exports an XML-based control interface. The Libvirt
for LDoms uses this XML interface to communicate with the LDoms Manager
to retrieve the LDoms data for:
- Listing domains
- Requesting CPU and memory resource updates
- Performing life-cycle actions for logical domains
This libvirt patch supports LDoms 1.0.1 and 1.0.2.
This patch will modify the following existing files:
src/libvirt.c
src/virsh.c
src/virterror.c
src/driver.h
src/Makefile.am
include/libvirt/libvirt.h.in
include/libvirt/virterror.h
configure.in
and add the following new files:
src/ldoms_common.h
src/ldoms_internal.h
src/ldoms_internal.c
src/ldoms_intfc.h
src/ldoms_intfc.c
src/ldoms_xml_parse.h
src/ldoms_xml_parse.c
Signed-off-by: Eunice Moon <eunice.moon(a)sun.com>
diff --git a/src/libvirt.c b/src/libvirt.c
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -48,6 +48,9 @@
#ifdef WITH_LXC
#include "lxc_driver.h"
#endif
+#ifdef WITH_LDOMS
+extern int ldomsRegister(void);
+#endif
/*
* TODO:
@@ -267,6 +270,11 @@ virInitialize(void)
* Note that the order is important: the first ones have a higher
* priority when calling virConnectOpen.
*/
+#ifdef WITH_LDOMS
+ if (ldomsRegister() == -1) return -1;
+ /* Don't want to run any other HV with LDoms */
+ return (0);
+#endif
#ifdef WITH_TEST
if (testRegister() == -1) return -1;
#endif
@@ -1794,11 +1802,17 @@ virDomainGetUUID(virDomainPtr domain, un
return (-1);
}
+#ifndef WITH_LDOMS
if (domain->id == 0) {
memset(uuid, 0, VIR_UUID_BUFLEN);
} else {
memcpy(uuid, &domain->uuid[0], VIR_UUID_BUFLEN);
}
+#endif
+
+#ifdef WITH_LDOMS
+ memcpy(uuid, &domain->uuid[0], VIR_UUID_BUFLEN);
+#endif
return (0);
}
@@ -5025,6 +5039,42 @@ virStorageVolGetPath(virStorageVolPtr vo
return NULL;
}
+#ifdef WITH_LDOMS
+/**
+ * virLDomConsole:
+ * @domain: the domain if available
+ *
+ * Opens a terminal window to the console for a domain
+ *
+ * Returns -1 in case of error, LDom console port number in case of success
+ */
+int
+virLDomConsole(virDomainPtr domain)
+{
+ virConnectPtr conn;
+ DEBUG("Starting domain %p", domain);
+
+ if (domain == NULL) {
+ TODO
+ return (-1);
+ }
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ return (-1);
+ }
+ conn = domain->conn;
+ if (conn->flags & VIR_CONNECT_RO) {
+ virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ return (-1);
+ }
+
+ if (conn->driver->ldomConsole)
+ return conn->driver->ldomConsole (domain);
+
+ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+ return -1;
+}
+#endif
/*
* vim: set tabstop=4:
diff --git a/src/virsh.c b/src/virsh.c
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -494,6 +494,11 @@ cmdConsole(vshControl * ctl, vshCmd * cm
virDomainPtr dom;
int ret = FALSE;
char *doc;
+#ifdef WITH_LDOMS
+ int port;
+ char command[80];
+#endif
+
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
@@ -501,6 +506,19 @@ cmdConsole(vshControl * ctl, vshCmd * cm
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
return FALSE;
+#ifdef WITH_LDOMS
+ port = virLDomConsole(dom);
+ if (port > 0) {
+ sprintf(command, "%s %d &",
+ "/usr/X/bin/xterm -sb -sl 1000 -e telnet localhost ", port);
+ system(command);
+ return TRUE;
+ }
+
+ vshError(ctl, FALSE, _("Failed to start console"));
+ return FALSE;
+#endif
+
doc = virDomainGetXMLDesc(dom, 0);
if (!doc)
goto cleanup;
@@ -1003,13 +1021,21 @@ cmdUndefine(vshControl * ctl, vshCmd * c
*/
static vshCmdInfo info_start[] = {
{"syntax", "start <domain>"},
+#ifdef WITH_LDOMS
+ {"help", gettext_noop("start an inactive or bound domain")},
+#else
{"help", gettext_noop("start a (previously defined) inactive domain")},
+#endif
{"desc", gettext_noop("Start a domain.")},
{NULL, NULL}
};
static vshCmdOptDef opts_start[] = {
+#ifdef WITH_LDOMS
+ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("name of the inactive or bound domain")},
+#else
{"name", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("name of the inactive domain")},
+#endif
{NULL, 0, 0, NULL}
};
@@ -1019,17 +1045,26 @@ cmdStart(vshControl * ctl, vshCmd * cmd)
virDomainPtr dom;
int ret = TRUE;
+#ifdef WITH_LDOMS
+ /* Need to send in the 'domain' option name instead of 'name' */
+ if (!(dom = vshCommandOptDomainBy(ctl, cmd, "domain", NULL, VSH_BYNAME)))
+ return FALSE;
+#else
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
+#endif
if (!(dom = vshCommandOptDomainBy(ctl, cmd, "name", NULL, VSH_BYNAME)))
return FALSE;
+ /* Allow LDoms domain state to be inactive or bound */
+#ifndef WITH_LDOMS
if (virDomainGetID(dom) != (unsigned int)-1) {
vshError(ctl, FALSE, "%s", _("Domain is already active"));
virDomainFree(dom);
return FALSE;
}
+#endif
if (virDomainCreate(dom) == 0) {
vshPrint(ctl, _("Domain %s started\n"),
@@ -1660,11 +1695,13 @@ cmdVcpuinfo(vshControl * ctl, vshCmd * c
vshPrint(ctl, "%-15s %.1lfs\n", _("CPU time:"), cpuUsed);
}
+#ifndef WITH_LDOMS
vshPrint(ctl, "%-15s ", _("CPU Affinity:"));
for (m = 0 ; m < VIR_NODEINFO_MAXCPUS(nodeinfo) ; m++) {
vshPrint(ctl, "%c", VIR_CPU_USABLE(cpumap, cpumaplen, n, m) ? 'y' : '-');
}
vshPrint(ctl, "\n");
+#endif
if (n < (ncpus - 1)) {
vshPrint(ctl, "\n");
}
@@ -5087,19 +5124,23 @@ cmdQuit(vshControl * ctl, vshCmd * cmd A
*/
static vshCmdDef commands[] = {
{"help", cmdHelp, opts_help, info_help},
+#ifndef WITH_LDOMS
{"attach-device", cmdAttachDevice, opts_attach_device, info_attach_device},
{"attach-disk", cmdAttachDisk, opts_attach_disk, info_attach_disk},
{"attach-interface", cmdAttachInterface, opts_attach_interface, info_attach_interface},
{"autostart", cmdAutostart, opts_autostart, info_autostart},
{"capabilities", cmdCapabilities, NULL, info_capabilities},
{"connect", cmdConnect, opts_connect, info_connect},
+#endif /* WITH_LDOMS */
{"console", cmdConsole, opts_console, info_console},
{"create", cmdCreate, opts_create, info_create},
{"start", cmdStart, opts_start, info_start},
{"destroy", cmdDestroy, opts_destroy, info_destroy},
+#ifndef WITH_LDOMS
{"detach-device", cmdDetachDevice, opts_detach_device, info_detach_device},
{"detach-disk", cmdDetachDisk, opts_detach_disk, info_detach_disk},
{"detach-interface", cmdDetachInterface, opts_detach_interface, info_detach_interface},
+#endif /* WITH_LDOMS */
{"define", cmdDefine, opts_define, info_define},
{"domid", cmdDomid, opts_domid, info_domid},
{"domuuid", cmdDomuuid, opts_domuuid, info_domuuid},
@@ -5112,7 +5153,9 @@ static vshCmdDef commands[] = {
{"freecell", cmdFreecell, opts_freecell, info_freecell},
{"hostname", cmdHostname, NULL, info_hostname},
{"list", cmdList, opts_list, info_list},
+#ifndef WITH_LDOMS
{"migrate", cmdMigrate, opts_migrate, info_migrate},
+#endif /* WITH_LDOMS */
{"net-autostart", cmdNetworkAutostart, opts_network_autostart, info_network_autostart},
{"net-create", cmdNetworkCreate, opts_network_create, info_network_create},
@@ -5144,20 +5187,28 @@ static vshCmdDef commands[] = {
{"pool-uuid", cmdPoolUuid, opts_pool_uuid, info_pool_uuid},
{"quit", cmdQuit, NULL, info_quit},
+#ifndef WITH_LDOMS
{"reboot", cmdReboot, opts_reboot, info_reboot},
{"restore", cmdRestore, opts_restore, info_restore},
{"resume", cmdResume, opts_resume, info_resume},
{"save", cmdSave, opts_save, info_save},
{"schedinfo", cmdSchedinfo, opts_schedinfo, info_schedinfo},
{"dump", cmdDump, opts_dump, info_dump},
+#endif /* WITH_LDOMS */
{"shutdown", cmdShutdown, opts_shutdown, info_shutdown},
{"setmem", cmdSetmem, opts_setmem, info_setmem},
+#ifndef WITH_LDOMS
{"setmaxmem", cmdSetmaxmem, opts_setmaxmem, info_setmaxmem},
+#endif /* WITH_LDOMS */
{"setvcpus", cmdSetvcpus, opts_setvcpus, info_setvcpus},
+#ifndef WITH_LDOMS
{"suspend", cmdSuspend, opts_suspend, info_suspend},
{"ttyconsole", cmdTTYConsole, opts_ttyconsole, info_ttyconsole},
+#endif /* WITH_LDOMS */
{"undefine", cmdUndefine, opts_undefine, info_undefine},
+#ifndef WITH_LDOMS
{"uri", cmdURI, NULL, info_uri},
+#endif /* WITH_LDOMS */
{"vol-create", cmdVolCreate, opts_vol_create, info_vol_create},
{"vol-create-as", cmdVolCreateAs, opts_vol_create_as, info_vol_create_as},
@@ -5170,9 +5221,13 @@ static vshCmdDef commands[] = {
{"vol-key", cmdVolKey, opts_vol_key, info_vol_key},
{"vcpuinfo", cmdVcpuinfo, opts_vcpuinfo, info_vcpuinfo},
+#ifndef WITH_LDOMS
{"vcpupin", cmdVcpupin, opts_vcpupin, info_vcpupin},
+#endif /* WITH_LDOMS */
{"version", cmdVersion, NULL, info_version},
+#ifndef WITH_LDOMS
{"vncdisplay", cmdVNCDisplay, opts_vncdisplay, info_vncdisplay},
+#endif /* WITH_LDOMS */
{NULL, NULL, NULL, NULL}
};
@@ -5905,6 +5960,10 @@ vshDomainVcpuStateToString(int state)
return gettext_noop("blocked");
case VIR_VCPU_RUNNING:
return gettext_noop("running");
+#ifdef WITH_LDOMS
+ case VIR_VCPU_UNKNOWN:
+ return gettext_noop("unknown");
+#endif
default:
;/*FALLTHROUGH*/
}
diff --git a/src/virterror.c b/src/virterror.c
--- a/src/virterror.c
+++ b/src/virterror.c
@@ -304,7 +304,11 @@ virDefaultErrorFunc(virErrorPtr err)
case VIR_FROM_STORAGE:
dom = "Storage ";
break;
-
+#ifdef WITH_LDOMS
+ case VIR_FROM_LDOMS:
+ dom = "LDoms ";
+ break;
+#endif
}
if ((err->dom != NULL) && (err->code != VIR_ERR_INVALID_DOMAIN)) {
domain = err->dom->name;
@@ -713,6 +717,14 @@ __virErrorMsg(virErrorNumber error, cons
else
errmsg = _("Failed to find a storage driver: %s");
break;
+#ifdef WITH_LDOMS
+ case VIR_ERR_INVALID_OPTION:
+ if (info == NULL)
+ errmsg = _("invalid option");
+ else
+ errmsg = _("invalid option: %s");
+ break;
+#endif
}
return (errmsg);
}
diff --git a/src/driver.h b/src/driver.h
--- a/src/driver.h
+++ b/src/driver.h
@@ -24,7 +24,10 @@ typedef enum {
VIR_DRV_QEMU = 3,
VIR_DRV_REMOTE = 4,
VIR_DRV_OPENVZ = 5,
- VIR_DRV_LXC = 6
+ VIR_DRV_LXC = 6,
+#ifdef WITH_LDOMS
+ VIR_DRV_LDOMS = 7
+#endif
} virDrvNo;
@@ -253,6 +256,11 @@ typedef virDomainPtr
const char *uri,
unsigned long flags);
+#ifdef WITH_LDOMS
+typedef int
+ (*virDrvLDomConsole) (virDomainPtr domain);
+#endif
+
typedef struct _virDriver virDriver;
typedef virDriver *virDriverPtr;
@@ -337,6 +345,9 @@ struct _virDriver {
virDrvDomainInterfaceStats domainInterfaceStats;
virDrvNodeGetCellsFreeMemory nodeGetCellsFreeMemory;
virDrvNodeGetFreeMemory getFreeMemory;
+#ifdef WITH_LDOMS
+ virDrvLDomConsole ldomConsole;
+#endif
};
typedef int
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -549,6 +549,9 @@ typedef enum {
VIR_VCPU_OFFLINE = 0, /* the virtual CPU is offline */
VIR_VCPU_RUNNING = 1, /* the virtual CPU is running */
VIR_VCPU_BLOCKED = 2, /* the virtual CPU is blocked on resource */
+#ifdef WITH_LDOMS
+ VIR_VCPU_UNKNOWN = 3, /* the virtual CPU state is unknown */
+#endif
} virVcpuState;
typedef struct _virVcpuInfo virVcpuInfo;
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -56,6 +56,9 @@ typedef enum {
VIR_FROM_STATS_LINUX, /* Error in the Linux Stats code */
VIR_FROM_LXC, /* Error from Linux Container driver */
VIR_FROM_STORAGE, /* Error from storage driver */
+#ifdef WITH_LDOMS
+ VIR_FROM_LDOMS, /* Error from LDoms driver */
+#endif
} virErrorDomain;
@@ -139,6 +142,9 @@ typedef enum {
VIR_WAR_NO_STORAGE, /* failed to start storage */
VIR_ERR_NO_STORAGE_POOL, /* storage pool not found */
VIR_ERR_NO_STORAGE_VOL, /* storage pool not found */
+#ifdef WITH_LDOMS
+ VIR_ERR_INVALID_OPTION, /* invalid command line option */
+#endif
} virErrorNumber;
/**
diff --git a/src/Makefile.am b/src/Makefile.am
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -89,7 +89,17 @@ else
EXTRA_DIST += storage_backend_disk.h storage_backend_disk.c
endif
-
+if WITH_LDOMS
+CLIENT_SOURCES += ldoms_common.h \
+ ldoms_internal.h ldoms_internal.c \
+ ldoms_intfc.h ldoms_intfc.h \
+ ldoms_xml_parse.h ldoms_xml_parse.c \
+else
+EXTRA_DIST += ldoms_common.h \
+ ldoms_internal.h ldoms_internal.c \
+ ldoms_intfc.h ldoms_intfc.h \
+ ldoms_xml_parse.h ldoms_xml_parse.c \
+endif
libvirt_la_SOURCES = $(CLIENT_SOURCES) $(SERVER_SOURCES)
diff --git a/configure.in b/configure.in
--- a/configure.in
+++ b/configure.in
@@ -246,6 +246,10 @@ if test "$with_remote" = "yes" ; then
LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_REMOTE"
fi
+if test "$with_ldoms" = "yes" ; then
+ LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_LDOMS"
+fi
+
if test "$with_xen" = "yes" ; then
dnl search for the Xen store library
AC_SEARCH_LIBS(xs_read, [xenstore],
diff --git a/src/ldoms_common.h b/src/ldoms_common.h
new file mode 100644
--- /dev/null
+++ b/src/ldoms_common.h
@@ -0,0 +1,80 @@
+/*
+ * ldoms_common.h: LDoms common definitions
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ */
+
+#ifndef __VIR_LDOMS_COMMON_H__
+#define __VIR_LDOMS_COMMON_H__
+
+#ifdef WITH_LDOMS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LDOMS_VERSION_NUMBER 1000001 /* 1.0.1 */
+#define NAME_SIZE 256
+
+/* LDOM memory unit */
+#define LDOMMEMUNIT_BYTES 1
+#define LDOMMEMUNIT_KILOBYTES 2
+#define LDOMMEMUNIT_MEGABYTES 3
+#define LDOMMEMUNIT_GIGABYTES 4
+
+/* LDOM lifecycle actions */
+#define LDOM_START 1
+#define LDOM_STOP 2
+#define LDOM_BIND 3
+#define LDOM_UNBIND 4
+#define LDOM_DELETE 5
+
+/* LDOM States */
+/* binding is to bind (attach) configured resource to a logical domain
+ * unbinding is to release resources bound to configured logical domains
+ */
+#define LDOM_STATE_ACTIVE 1
+#define LDOM_STATE_STOPPING 2
+#define LDOM_STATE_INACTIVE 3
+#define LDOM_STATE_BINDING 4
+#define LDOM_STATE_UNBINDING 5
+#define LDOM_STATE_BOUND 6
+#define LDOM_STATE_STARTING 7
+
+/* resource pool supported */
+#define CPU_RP 1
+#define MEM_RP 2
+#define CRYPTO_RP 3
+#define IOBUS_RP 4
+
+/* capacity or reserved resource */
+#define RP_CAPACITY 1
+#define RP_RESERVED 2
+
+/* Global vars */
+extern unsigned long ldomsFreeMem;
+extern unsigned long ldomsUsedMem;
+extern int ldomsFreeCpu;
+extern int ldomsUsedCpu;
+
+/* Structures */
+
+struct cpuBindings_s {
+ unsigned int virt;
+ int real;
+ struct cpuBindings_s *next;
+};
+typedef struct cpuBindings_s cpuBindings_t;
+
+/* Debug print */
+extern void dprt(const char *template, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WITH_LDOMS */
+#endif /* __VIR_LDOMS_COMMON_H__ */
diff --git a/src/ldoms_internal.h b/src/ldoms_internal.h
new file mode 100644
--- /dev/null
+++ b/src/ldoms_internal.h
@@ -0,0 +1,29 @@
+/*
+ * ldoms_internal.h: internal definitions just used by LDoms driver
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ */
+
+#ifndef __VIR_LDOMS_INTERNAL_H__
+#define __VIR_LDOMS_INTERNAL_H__
+
+#ifdef WITH_LDOMS
+
+#include <libvirt/virterror.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int ldomsRegister(void);
+void ldomsError(virConnectPtr, virDomainPtr, virErrorNumber, const char*, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WITH_LDOMS */
+#endif /* __VIR_LDOMS_INTERNAL_H__ */
diff --git a/src/ldoms_internal.c b/src/ldoms_internal.c
new file mode 100644
--- /dev/null
+++ b/src/ldoms_internal.c
@@ -0,0 +1,2254 @@
+/*
+ * ldoms_internal.c: access to LDoms hypervisor via LDoms Manager (LDM)
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ */
+
+#ifdef WITH_LDOMS
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <sys/processor.h>
+#include <pwd.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/uri.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <values.h>
+#include <limits.h>
+#include <pthread.h>
+
+#include "buf.h"
+#include "internal.h"
+#include "xml.h"
+#include "ldoms_common.h"
+#include "ldoms_internal.h"
+#include "ldoms_intfc.h"
+#include "ldoms_xml_parse.h"
+
+/* Local function prototypes */
+static void refresh_ldom_data();
+static int ldomsNodeGetInfo(virConnectPtr , virNodeInfoPtr );
+static long long getCpuUpTime();
+static long getHypervisorVersion();
+static unsigned long getLDMVersion();
+
+/* Domain state info
+ * LDom State enumerations
+ * 1 = active LDOM_STATE_ACTIVE
+ * 2 = stopping LDOM_STATE_STOPPING
+ * 3 = inactive LDOM_STATE_INACTIVE
+ * 4 = binding LDOM_STATE_BINDING
+ * 5 = unbinding LDOM_STATE_UNBINDING
+ * 6 = bound LDOM_STATE_BOUND
+ * 7 = starting LDOM_STATE_STARTING
+ *
+ * libvirt LDom State enums
+ * typedef enum {
+ * VIR_DOMAIN_NOSTATE = 0, no state
+ * VIR_DOMAIN_RUNNING = 1, the domain is running
+ * VIR_DOMAIN_BLOCKED = 2, the domain is blocked on resource
+ * VIR_DOMAIN_PAUSED = 3, the domain is paused by user
+ * VIR_DOMAIN_SHUTDOWN= 4, the domain is being shut down
+ * VIR_DOMAIN_SHUTOFF = 5, the domain is shut off
+ * VIR_DOMAIN_CRASHED = 6 the domain is crashed
+ * } virDomainState;
+ */
+
+ldominfo_t **ldominfo_list = NULL;
+int ldom_cnt = 0;
+const unsigned char Uuid[] = "" ;
+static long last_ldom_refresh = 0;
+static pthread_rwlock_t update_lock;
+static unsigned long LDMVersion = 1000001;
+
+/* Mem and CPU Free/Used */
+unsigned long ldomsFreeMem;
+unsigned long ldomsUsedMem;
+int ldomsFreeCpu;
+int ldomsUsedCpu;
+
+/* Global vars for debug statement */
+int ldoms_debug = 0;
+int ldoms_detailed_debug = 0;
+
+/* Prototype Structures */
+struct domains {
+ short valid; /* Flag to indicate this Domain is valid */
+ short active; /* Flag to indicate this Domain is valid */
+ char name[30]; /* Domain Name; primary, ldg1, etc */
+ int id; /* ID for the Domain; Used alot by other code to find a Domain */
+ virDomainInfo info; /* Domain name, state */
+ unsigned char uuid[VIR_UUID_BUFLEN]; /* 32 char unique ID */
+};
+
+/* This is global. Need to fill on first call from virsh or VMM */
+virNodeInfo nodeInfo;
+short nodeInfoFilled = 0;
+
+int maxDomID = 0;
+
+/*
+ * General error logging function. This is the exact same
+ * as used by Qemu and Test.
+ */
+void
+ldomsError(virConnectPtr con,
+ virDomainPtr dom,
+ virErrorNumber error,
+ const char *info,
+ int level)
+{
+ const char *errmsg;
+
+ if (error == VIR_ERR_OK) {
+ errmsg = info;
+ /* return; */
+ } else
+ errmsg = __virErrorMsg(error, info);
+
+ __virRaiseError(con, dom, NULL, VIR_FROM_LDOMS, error, level,
+ errmsg, info, NULL, 0, 0, errmsg, info, 0);
+}
+
+/*
+ * getDomainIndex
+ *
+ * What: Get the index for the input Domain for a given connection.
+ * Note: libivrt does not associated an Index with an inactive
+ * Domain. For LDoms, we assign an Index to all Domains.
+ *
+ * Input: domain - A ptr to a virDomain
+ * Output: The Domain ID. -1 if for no ID.
+ */
+static int
+getDomainIndex(virDomainPtr domain)
+{
+ int i, domID;
+
+ /* get the current ldom data from LDM (LDoms Manager) */
+ (void) pthread_rwlock_wrlock(&update_lock);
+ refresh_ldom_data();
+ (void) pthread_rwlock_unlock(&update_lock);
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getDomainIndex(ENTER) domName=%s, domID=%d, ldom_cnt=%d\n",domain->name,domain->id,ldom_cnt);
+
+ if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+ ldomsError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
+ __FUNCTION__, VIR_ERR_ERROR);
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getDomainIndex(EXIT ERROR) domain input not valid\n");
+ return (-1);
+ }
+
+ domID = domain->id;
+ for (i = 0 ; i < ldom_cnt ; i++) {
+ if (domID >= 0) {
+ if (domID == i) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getDomainIndex(EXIT) From ID: domidx=%d\n",i);
+ return (i);
+ }
+ } else {
+ if (!strcmp(domain->name, ldominfo_list[i]->ldomName)) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getDomainIndex(EXIT) From Name:domidx=%d\n",i);
+ return (i);
+ }
+ }
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getDomainIndex(EXIT ERROR) domID=-1\n");
+ return (-1);
+} /* getDomainIndex() */
+
+/*
+ * ldomsOpen
+ *
+ * Open a connection to the LDoms Manager and handshake to
+ * verify the a connection can be made for future XML requests.
+ *
+ * Input: All inputs are ignored at this time.
+ * Output: 0 -> Success, <0 -> Failure
+ */
+static virDrvOpenStatus
+ldomsOpen(virConnectPtr conn, xmlURIPtr uri, virConnectAuthPtr auth ATTRIBUTE_UNUSED, int flags)
+{
+ struct timeval tv;
+ int u, ret, connid;
+ int socketFD;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsOpen(ENTER) \n");
+
+ if (!uri)
+ return VIR_DRV_OPEN_DECLINED;
+
+ if (!uri->scheme || strcmp(uri->scheme, "ldoms") != 0)
+ return VIR_DRV_OPEN_DECLINED;
+
+ if (!uri->scheme || strcmp(uri->scheme, "ldoms")) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsOpen(FAIL): uri scheme NOT correct\n");
+ ldomsError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("URI is not valid for LDoms"), VIR_ERR_ERROR);
+ return (-1);
+ }
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsOpen(): scheme=%s, path=%s\n",
+ (uri->scheme==0) ? "NULL" : uri->scheme,
+ (uri->path==0) ? "NULL" : uri->path);
+
+ /* Verify the LDM (LDoms Manager) can be talked to. Open an socket
+ connection, Handshake, then close the socket. */
+ if ((socketFD = open_ldm_connection()) < 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsOpen(): Cannot talk with LDoms Manager\n");
+ ldomsError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("Cannot open socket to LDMD"), VIR_ERR_ERROR);
+ return(-1);
+ }
+ close_ldm_connection(socketFD);
+
+
+ return(0);
+} /* ldomsOpen() */
+
+static int
+ldomsClose(virConnectPtr conn)
+{
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsClose(ENTER/EXIT)\n");
+ /* Nothing to do */
+ return(0);
+}
+
+/*
+ * ldomsGetMaxVcpus
+ *
+ * What: Just get the total number of free CPUs in the system.
+ * Call get_ldom_total_cpu(), so it will set, as a side effect,
+ * the number of free CPUs and free Memory in the system.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * memory - Size in KiloBytes
+ * Output: function return - Number of Max CPUs supported, or -1 for error
+ */
+int
+ldomsGetMaxVcpus(virConnectPtr conn, const char *type)
+{
+ virNodeInfo nodeInfo;
+ int rc;
+ int totalVcpus;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsGetMaxVcpus(ENTER) \n");
+
+ if (get_ldom_total_cpu(&totalVcpus) < 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsGetMaxVcpus() get_ldom_total_cpu() failed\n");
+ return (0);
+ }
+
+ /* Success */
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsGetMaxVcpus() Free Vcpus = %d\n",ldomsFreeCpu);
+ return (ldomsFreeCpu);
+} /* ldomsGetMaxVcpus() */
+
+/*
+ * ldomsNodeGetInfo
+ *
+ * What: Get the info for a Node, which is the physical
+ * hardware system.
+ *
+ * Input: conn - Pointer to a virConnect struct (Not used)
+ * info - Poiner to a virNodeInfo struct to update
+ * Output: Indirect virNodeInfo struct updated with Node info
+ */
+static int
+ldomsNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
+{
+ int total_cpu;
+ unsigned long total_memory;
+
+ /* to get the CPU frequency and fill the nodeInfo.mhz field
+ *
+ * NOTE:
+ * Since processor_info provides info for the domain on which it
+ * is being called (control domain), the virtual processor id 0 is used
+ * to retrieve the processor speed assuming that the cpu speed
+ * is the same for all Cpus on the system. That is a safe
+ * assumption for single-chip platforms like Ontario and Huron,
+ * but it might not work for multi-chip platforms based on VF or ROCK
+ * chips.
+ */
+ processor_info_t cpu_info;
+ int pid = 0; /* physical processor ID */
+ int p_clock = 1600; /* default processor clock speed in MHz */
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNodeGetInfo(ENTER)\n");
+
+ /*
+ * NOTE: We get the Node info values (number of CPUs and memory)
+ * from the LDM (LDoms Manager) by adding up the total number of CPUs and Memory for all domains.
+ */
+
+ /* if the nodeInfo variable hasn't been filled yet, try to get the
+ * total number of CPUs and memory from the LDM (LDoms Manager).
+ */
+
+
+ if (nodeInfoFilled == 0) {
+
+ strcpy(nodeInfo.model, "SPARC");
+
+ /*
+ * Fill the total amount of memory by sending the LDM list-devices
+ * and list-bindings XML requests and adding up free and bound
+ * memory amounts for all domains. If it fails to retrieve the total
+ * amount of memory from LDM, 64GB (expressed in KB) will be
+ * used as default value.
+ */
+
+ if (get_ldom_total_memory(&total_memory) < 0) {
+ if (ldoms_debug)
+ dprt("LDOMS_DEBUG: ldomsNodeGetInfo() get_ldom_total_memory() failed\n");
+ nodeInfo.memory = 0;
+ } else {
+ if (ldoms_detailed_debug)
+ dprt("LDOMS_DETAILED_DEBUG: ldomsNodeGetInfo() Total Node Memory=%lu\n", total_memory);
+ nodeInfo.memory = total_memory;
+ }
+
+ /*
+ * Fill the total number of CPUs by sending the LDM list-devices
+ * and list-bindings XML requests and adding up free and bound
+ * CPUs for all domains. If it fails to retrieve the total
+ * number of CPUs from LDM, 0 will be used as default value.
+ */
+
+ if (get_ldom_total_cpu(&total_cpu) < 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNodeGetInfo() get_ldom_total_cpu() failed\n");
+ nodeInfo.cpus = 0;
+ } else {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsNodeGetInfo() Total Node CPUs=%d\n", total_cpu);
+ nodeInfo.cpus = total_cpu;
+ }
+
+ /* get the processor clock speed in MHz */
+ while ((pid < 64) && (processor_info(pid++, &cpu_info) != 0) );
+
+ /* Found a pid on the primary domain */
+ if (pid <= 64) {
+ if (ldoms_detailed_debug)
+ dprt("LDOMS_DETAILED_DEBUG: ldomsNodeGetInfo(). processor_info with pid=%d clock=%d\n",
+ pid, cpu_info.pi_clock);
+ p_clock = cpu_info.pi_clock;
+ }
+
+ nodeInfo.mhz = p_clock;
+ nodeInfo.nodes = 1; /* Only 1 node in LDoms */
+ nodeInfo.sockets = 1;
+ nodeInfo.cores = 8; /* 8 cores on N1 and N2. 4 threads on N1 core, 8 on N2 */
+
+ /* If there are more than 32 CPUs, then 8 Threads/Core, else 4 Threads/Core */
+ if (nodeInfo.cpus > 32)
+ nodeInfo.threads = 8; /* This is Threads per Core, not total Threads */
+ else
+ nodeInfo.threads = 4; /* This is Threads per Core, not total Threads */
+
+ /* nodeInfo has been filled */
+ nodeInfoFilled = 1;
+ }
+
+ memcpy(info, &nodeInfo, sizeof(virNodeInfo));
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNodeGetInfo(EXIT)\n");
+ return (0);
+} /* ldomsNodeGetInfo() */
+
+/* Don't really know what to return for this */
+static const char *
+ldomsGetType(virConnectPtr conn)
+{
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsGetType(ENTER)\n");
+ return(strdup("LDoms"));
+}
+
+/* This returns the HV version. Make it the same as the LDoms version */
+static int
+ldomsGetVersion(virConnectPtr conn, unsigned long *hvVer)
+{
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsGetVersion(ENTER/EXIT)\n");
+ *hvVer = getHypervisorVersion();
+ return(0);
+}
+
+static char *
+ldomsGetHostname(virConnectPtr conn)
+{
+
+ int rc;
+ char hostname [MAXHOSTNAMELEN+1];
+ char *host;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsGetHostname(ENTER)\n");
+
+ rc = gethostname (hostname, MAXHOSTNAMELEN);
+ if (rc == -1) {
+ ldomsError (conn, NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno), VIR_ERR_ERROR);
+ return NULL;
+ }
+
+ host = strdup (hostname);
+ if (host == NULL) {
+ ldomsError (conn, NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno), VIR_ERR_ERROR);
+ return NULL;
+ }
+ return host;
+}
+
+/*
+ * ldomsListDomains
+ *
+ * What: Return the array of Domain ID's for all the active Domains.
+ * Send an XML request to LDM (LDoms Manager) for a list of all Domains.
+ *
+ * Yes, this functions does pretty much the same as ldomsNumOfDomains() with
+ * the addition of returning the ID numbers for the valid Domains.
+ *
+ * Input: conn - The Connection structure
+ * maxids - The total number of Domains to look at to
+ * determine what Domain IDs to return.
+ * Output: ids - An array of integers to hold the IDs of the
+ * Domains whose state is other than 'inactive' -
+ * VIR_DOMAIN_SHUTOFF
+ */
+static int
+ldomsListDomains(virConnectPtr conn, int *ids, int maxids)
+{
+ int i,n;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsListDomains(ENTER), Max # of non inactive domains=%d\n",maxids);
+
+ /* Send an LDM request 'list-domains' */
+ if (get_ldom_names(&ldom_cnt, &ldominfo_list) < 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsListDomains() get_ldom_names() failed\n");
+ return (-1);
+ };
+
+ /* The Domain ID will be the index into the ldominfo_list array */
+ for (i=0, n=0; i<ldom_cnt && n<maxids; i++) {
+ if (ldominfo_list[i]->ldomState != LDOM_STATE_INACTIVE) {
+ ids[n++] = i;
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsListDomains(), Active Domain ID=%d\n",i);
+ }
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsListDomains(EXIT), # of non inactive domains=%d\n",n);
+ return(n);
+} /* ldomsListDomains() */
+
+/*
+ * ldomsNumOfDomains
+ *
+ * What: Return the total number of active Domains (not VIR_SHUT_OFF)
+ *
+ * Input: conn - Pointer to a connection structure
+ * Output: function return - # of active Domains
+ */
+static int
+ldomsNumOfDomains(virConnectPtr conn)
+{
+ int rc, i, numActive=0;
+ /* int ldom_cnt; */
+ /* ldominfo_t **ldominfo_list = NULL; */
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNumOfDomains(ENTER) \n");
+ /*
+ * Call LDM with a list-domains cmd to get the total
+ * # of Domains and the basic information of each one.
+ */
+
+ if (get_ldom_names(&ldom_cnt, &ldominfo_list) < 0) {
+ /* Any ldominfo_t memory was freed in get_ldom_names() */
+ free(ldominfo_list);
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNumOfDomains() get_ldom_names() failed\n");
+ return (0);
+ };
+
+ /* Get the number of non inactive domains */
+ for (i=0; i<ldom_cnt; i++) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsNumOfDomains() name=%s\n",ldominfo_list[i]->ldomName);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsNumOfDomains() state=%d\n",ldominfo_list[i]->ldomState);
+ if (ldominfo_list[i]->ldomState != LDOM_STATE_INACTIVE) numActive++;
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNumOfDomains(EXIT) non inactive ldom_cnt=%d\n",numActive);
+ return (numActive);
+
+} /* ldomsNumOfDomains() */
+
+/*
+ * ldomsDomainCreateXML
+ *
+ * What: Create a domain from an XML file so that it is left in the
+ * inactive state. Just call the DefineXML function. The XML input
+ * has to be a complete and valid XML requeset for the LDM. No
+ * modification is done to this file.
+ *
+ * Input: xml - The xml file
+ * Output: function return - A ptr to a virDomain or NULL
+ */
+virDomainPtr
+ldomsDomainCreateXML(virConnectPtr conn, const char *xml, unsigned int flags)
+{
+ virDomainPtr domPtr = NULL;
+ char *domainName = NULL;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainCreateXML(ENTER) \n");
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainCreateXML(ENTER) xmldoc=\n%s\n",xml);
+
+ /* Send the XML file along with the lifecycle action */
+ domainName = send_ldom_create_domain((char *)xml, XML_ADD_DOMAIN);
+
+ /*
+ * If the create/bind domain was successful, then we have to create a DomainInfo
+ * structure to pass back to the caller. We need the Domain name that was
+ * created, and the only way to get that is from parsing the input xml
+ * document. This is done in send_ldom_create_domain() and passed back as the return.
+ * Also we create the uuid for the domain name.
+ */
+ if (domainName != NULL) {
+
+ /*
+ * The UUID is not important, cuz only the Domain name is printed
+ * out in the virsh. So just use the default UUID.
+ */
+ domPtr = virGetDomain(conn, domainName, Uuid);
+ free(domainName);
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainCreateXML(EXIT) \n");
+
+ return (domPtr);
+} /* ldomsDomainCreateXML() */
+
+
+/*
+ * ldomsDomainLookupByID
+ *
+ * What: Given a Domain ID, either malloc or return the existing
+ * virDomain structure for the Domain associated with the ID.
+ *
+ * Input: conn - A connection structure
+ * id - ID of the Domain you want to find
+ * Output: Pointer to a virDomain of the Domain identified by the ID
+ */
+static virDomainPtr
+ldomsDomainLookupByID(virConnectPtr conn, int id)
+{
+
+ virDomainPtr domPtr;
+ int i, idx=-1;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainLookupByID(ENTER) id=%d\n",id);
+
+ /* get the current ldom data from LDM */
+ (void) pthread_rwlock_wrlock(&update_lock);
+ refresh_ldom_data();
+ (void) pthread_rwlock_unlock(&update_lock);
+
+ /* Find the Domain that matches the ID. The index of the ldominfo_list
+ * array is the Domain ID */
+ for (i=0; i<ldom_cnt; i++) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainLookupByID() id=%d, Dom id=%d\n",id,i);
+ if (i == id) {
+ idx = i;
+ break;
+ }
+ }
+
+ /*
+ * If Domain is inactive, then libvirt does not assocaite an ID with an
+ * inactive domain. So check the LDoms domain state and if inactive, log
+ * and return an error.
+ */
+ if ((idx < 0) || (ldominfo_list[idx]->ldomState == LDOM_STATE_INACTIVE)) {
+ ldomsError(conn, NULL, VIR_ERR_NO_DOMAIN, _("no ID match"), VIR_ERR_ERROR);
+ return(NULL);
+ }
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainLookupByID() found id=%d, Dom id=%d\n",id,idx);
+
+ domPtr = virGetDomain(conn, ldominfo_list[id]->ldomName, ldominfo_list[id]->uuid);
+ if (domPtr == NULL) {
+ ldomsError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating domain"), VIR_ERR_ERROR);
+ return(NULL);
+ }
+
+ domPtr->id = id;
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainLookupByID(EXIT) \n");
+ return (domPtr);
+} /* ldomsDomainLookupByID() */
+
+/*
+ * ldomsDomainLookupByUUID
+ *
+ * What: Given a Domain UUID, either malloc or return the existing
+ * virDomain structure for the Domain associated with the UUID.
+ *
+ * Input: conn - A connection structure
+ * id - ID of the Domain you want to find
+ * Output: Pointer to a virDomain of the Domain identified by the UUID
+ */
+static virDomainPtr
+ldomsDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
+{
+
+ virDomainPtr domPtr;
+ int i, idx=-1;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainLookupByUUID(ENTER) \n");
+
+ /* get the current ldom data from LDM */
+ (void) pthread_rwlock_wrlock(&update_lock);
+ refresh_ldom_data();
+ (void) pthread_rwlock_unlock(&update_lock);
+
+
+ /* Find the Domain that matches the UUID. */
+ for (i=0; i<ldom_cnt; i++) {
+ if (memcmp(uuid, ldominfo_list[i]->uuid, VIR_UUID_BUFLEN) == 0) {
+ idx = i;
+ break;
+ }
+ }
+
+ if (idx < 0) {
+ ldomsError(conn, NULL, VIR_ERR_NO_DOMAIN, _("no UUID match"), VIR_ERR_ERROR);
+ return(NULL);
+ }
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainLookupByUUID() found id=%d\n",idx);
+
+ domPtr = virGetDomain(conn, ldominfo_list[idx]->ldomName, ldominfo_list[idx]->uuid);
+ if (domPtr == NULL) {
+ ldomsError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating domain"), VIR_ERR_ERROR);
+ return(NULL);
+ }
+
+ /* If the Domain state is inactive, then the ID must be set to -1 */
+ if (ldominfo_list[idx]->ldomState == LDOM_STATE_INACTIVE) {
+ idx = -1;
+ }
+ domPtr->id = idx;
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainLookupByUUID(EXIT) \n");
+ return (domPtr);
+} /* ldomsDomainLookupByID() */
+
+/*
+ * ldomsDomainLookupByName
+ *
+ * What: Given a Domain Name, either malloc or return the existing
+ * virDomain structure for the Domain associated with the name.
+ * The virDomain will contain the ID and UUID for the domain.
+ * If a Domain is in the inactive state, then we don't set a
+ * ID for it. libvirt considers inactive Domains to have an
+ * ID of -1 until they are moved out of the inactive state.
+ *
+ *
+ * Input: conn - A connection structure
+ * name - Pointer to the Domain name
+ * Output: Pointer to a virDomain of the Domain identified by the name
+ */
+virDomainPtr
+ldomsDomainLookupByName(virConnectPtr conn, const char *name)
+{
+ virDomainPtr domPtr = NULL;
+ int i, uuidIdx, idx = -99;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainLookupByName(ENTER) name=%s\n",name);
+
+ /* get the current ldom data from LDM */
+ (void) pthread_rwlock_wrlock(&update_lock);
+ refresh_ldom_data();
+ (void) pthread_rwlock_unlock(&update_lock);
+
+
+ /* Find the index of our internal ldominfo_list[] that has the Domain data */
+ for (i=0; i<ldom_cnt; i++) {
+ if (strcmp(ldominfo_list[i]->ldomName,name) == 0) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainLookupByName(), Found Domain: ID=%d\n",i);
+
+ /* If the Domain is inactive, then set the index to -1 */
+ if (ldominfo_list[i]->ldomState == LDOM_STATE_INACTIVE) {
+ idx = -1;
+ uuidIdx = i;
+ }
+ else
+ idx = i;
+ break;
+ }
+ }
+
+
+ /* A non-inactive domain was found */
+ if (idx >= 0) {
+ domPtr = virGetDomain(conn, name, ldominfo_list[idx]->uuid);
+ if (domPtr == NULL) {
+ ldomsError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating domain"), VIR_ERR_ERROR);
+ return(NULL);
+ }
+ domPtr->id = idx;
+ }
+
+ /* An inactive domain was found, or worst case, LDM does not know
+ * about the input domain name!! This latter case should not happen
+ */
+ else if (idx == -1) {
+ domPtr = virGetDomain(conn, name, ldominfo_list[uuidIdx]->uuid);
+ if (domPtr == NULL) {
+ ldomsError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating inactive domain"), VIR_ERR_ERROR);
+ return(NULL);
+ }
+ domPtr->id = idx;
+ }
+
+ /* No domain name match was made */
+ else {
+ ldomsError(conn, NULL, VIR_ERR_NO_DOMAIN, _("no domain name match"), VIR_ERR_ERROR);
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainLookupByName(EXIT) ID=%d\n",idx);
+ return (domPtr);
+} /* ldomsDomainLookupByName() */
+
+/*
+ * ldomsDomainSuspend
+ *
+ * What: Given a Domain pointer, suspend/stop/pause the domain.
+ * These 3 actions are equivalent: suspend/stop/pause.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainSuspend(virDomainPtr domain)
+{
+ int rc;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSuspend(ENTER) name=%s\n",domain->name);
+
+ /* get the current ldom data from LDM */
+ (void) pthread_rwlock_wrlock(&update_lock);
+ refresh_ldom_data();
+ (void) pthread_rwlock_unlock(&update_lock);
+
+
+ /*
+ * If the domain state is not active (1), then we can't perform
+ * this action.
+ */
+
+ if (ldominfo_list[domain->id]->ldomState != LDOM_STATE_ACTIVE) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSuspend() Domain state not 'active', aborting request. domain=%s, state=%d\n",domain->name, ldominfo_list[domain->id]->ldomState);
+ return (-1);
+ }
+
+ /* Request LDM to change the state of the LDom */
+ rc = send_ldom_lifecycle_action(domain->name, LDOM_STOP);
+
+ /*
+ * If successful, the domain state changed from active to bound,
+ * so update the status.
+ */
+ if (rc == 0) {
+ ldominfo_list[domain->id]->ldomState = LDOM_STATE_BOUND;
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainSuspend() Domain state changed to 'bound'. domain=%s\n",
+ domain->name);
+ return (0);
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSuspend(EXIT) Domain state change failed. domain=%s\n",domain->name);
+ return (-1);
+} /* ldomsDomainSuspend() */
+
+/*
+ * ldomsDomainResume
+ *
+ * What: Given a Domain pointer, resume/start the domain.
+ * These 2 states are equivalent: resume/start.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainResume(virDomainPtr domain)
+{
+ int rc;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainResume(ENTER) name=%s\n",domain->name);
+
+ /* get the current ldom data from LDM */
+ (void) pthread_rwlock_wrlock(&update_lock);
+ refresh_ldom_data();
+ (void) pthread_rwlock_unlock(&update_lock);
+
+
+ /*
+ * If the domain state is not bound (6), then we can't perform
+ * this action.
+ */
+
+ if (ldominfo_list[domain->id]->ldomState != LDOM_STATE_BOUND) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainResume() Domain state not 'bound', aborting request. domain=%s, state=%d\n",domain->name, ldominfo_list[domain->id]->ldomState);
+ return (0);
+ }
+
+ /* Request LDM to change the state of the LDom */
+ rc = send_ldom_lifecycle_action(domain->name, LDOM_START);
+
+ /*
+ * If successful, the domain state changed from bound to active,
+ * so update the status.
+ */
+ if (rc == 0) {
+ ldominfo_list[domain->id]->ldomState = LDOM_STATE_ACTIVE;
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainResume() Domain state changed to 'active'. domain=%s\n",
+ domain->name);
+ return (0);
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainResume(EXIT) Domain state change failed. domain=%s\n",domain->name);
+ return (-1);
+} /* ldomsDomainResume() */
+
+/*
+ * ldomsDomainShutdown
+ *
+ * What: Given a Domain pointer, shutdown/bind the domain.
+ * The domain can only be in the active state to begin,
+ * and will be put into the bound state.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainShutdown(virDomainPtr domain)
+{
+ int rc = -1;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainShutdown(ENTER) domName=%s, domID=%d\n",
+ domain->name,domain->id);
+
+ /* get the current ldom data from LDM */
+ (void) pthread_rwlock_wrlock(&update_lock);
+ refresh_ldom_data();
+ (void) pthread_rwlock_unlock(&update_lock);
+
+
+ /* If the domain is inactive, then log an error and return */
+ if (domain->id == -1) {
+ ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, _("Domain is inactive"), VIR_ERR_WARNING );
+ return (-1);
+ }
+
+ /* If the domain is already bound, then log an error and return */
+ if (ldominfo_list[domain->id]->ldomState == LDOM_STATE_BOUND) {
+ ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, _("Domain is already bound"), VIR_ERR_WARNING );
+ return (-1);
+ }
+
+
+ /* If the domain state is active, then stop the domain */
+ if (ldominfo_list[domain->id]->ldomState == LDOM_STATE_ACTIVE) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainShutdown() Domain state is 'active', stopping...\n");
+ rc = send_ldom_lifecycle_action(domain->name, LDOM_STOP);
+ }
+
+ /*
+ * If successful, the domain state changed from active to bound,
+ * so update the status.
+ */
+ if (rc == 0) {
+ ldominfo_list[domain->id]->ldomState = LDOM_STATE_BOUND;
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainShutdown() Domain state changed to 'bound'. domain=%s\n",
+ domain->name);
+ return (0);
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainShutdown(EXIT) Domain state change failed. domain=%s\n",domain->name);
+
+ return (-1);
+} /* ldomsDomainShutdown() */
+
+
+/*
+ * ldomsDomainDestroy
+ *
+ * What: Given a Domain pointer, destroy/unbind the domain.
+ * The domain can be in the active or bound state to begin
+ * and will be put into the inactive state.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainDestroy(virDomainPtr domain)
+{
+ int rc = -1;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDestroy(ENTER) domName=%s, domID=%d\n",
+ domain->name,domain->id);
+
+ /* If the domain is already inactive, then log an error and return */
+ if (domain->id == -1) {
+ ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, _("Domain is already inactive"), VIR_ERR_WARNING );
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainDestroy() Domain is already inactive.\n");
+ return (-1);
+ }
+
+ /* get the current ldom data from LDM */
+ (void) pthread_rwlock_wrlock(&update_lock);
+ refresh_ldom_data();
+ (void) pthread_rwlock_unlock(&update_lock);
+
+
+ /* If the domain state is active, then stop the domain */
+ if (ldominfo_list[domain->id]->ldomState == LDOM_STATE_ACTIVE) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainDestroy() Domain state is 'active', stopping...\n");
+ rc = send_ldom_lifecycle_action(domain->name, LDOM_STOP);
+
+ /* Need to tell the next piece of code that a 'stop' was done and
+ * was successful, because the ldom info has not been updated.
+ */
+ if (rc == 0) rc = 1;
+ }
+
+ /* If the domain state is bound (6), then unbind the domain */
+ if ((rc == 1) || (ldominfo_list[domain->id]->ldomState == LDOM_STATE_BOUND)) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainDestroy() Domain state is 'bound' rc=%d, unbinding...\n",rc);
+ rc = send_ldom_lifecycle_action(domain->name, LDOM_UNBIND);
+ }
+
+ /*
+ * If successful, the domain state changed to inactive,
+ * so update the status.
+ */
+ if (rc == 0) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainDestroy() Domain state changed to 'inactive'. domain=%s\n",
+ domain->name);
+ return (0);
+ }
+
+ /*
+ * In case the input domain info is not correct and the domain is really
+ * inactive, log a warning.
+ */
+ if (rc == -1) {
+ ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, _("Domain is already inactive"), VIR_ERR_WARNING );
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainDestroy() Domain state/ID not indicating inactive, ID=%d\n", domain->id);
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDestroy(EXIT) Domain state change failed. domain=%s\n",domain->name);
+
+ return (-1);
+} /* ldomsDomainDestroy() */
+
+/*
+ * ldomsDomainGetOSType
+ *
+ * What: The the OS type for an LDoms domain
+ *
+ * Input: domain - A pointer to the virDomain structure * NOT USED *
+ * Output: String representing the OS type
+ */
+char *
+ldomsDomainGetOSType(virDomainPtr domain)
+{
+ return strdup("Solaris");
+} /* ldomsDomainGetOSType() */
+
+
+/*
+ * ldomsDomainGetMaxMemory
+ *
+ * What:
+ * For LDoms, GetMaxMemory will just get the current memory
+ * allocated to the Domain. There is no concept of Max memory
+ * for a Domain in LDoms.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - The amount of memory in Kilobytes
+ *
+ */
+unsigned long
+ldomsDomainGetMaxMemory(virDomainPtr domain)
+{
+ int domidx;
+ unsigned long memory;
+
+ if ((domidx = getDomainIndex(domain)) < 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetMaxMemory(EXIT) getDomainIndex() failed\n");
+ return (-1);
+ }
+ memory = ldominfo_list[domidx]->ldomMemSize;
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetMaxMemory() MaxMemory=%dKB\n",memory);
+ return (memory);
+} /* ldomsDomainGetMaxMemory() */
+
+/*
+ * ldomsDomainSetMemory
+ *
+ * What: Given a Domain pointer, send an XML request to change
+ * the amount of memory for the domain.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * memory - Size in KiloBytes
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainSetMemory(virDomainPtr domain, unsigned long memory)
+{
+ int rc;
+ int domidx;
+ virDomainInfo domInfo;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSetMemory(ENTER) memory=%d\n",memory);
+
+ if ((domidx = getDomainIndex(domain)) < 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSetMemory(EXIT) getDomainIndex() failed\n");
+ return (-1);
+ }
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainSetMemory: domain=%s, domidx=%d\n",domain->name,domidx);
+
+ /* Send request to LDM to set the memory */
+ rc = send_ldom_set_memory(domain->name, memory);
+
+ if (rc == 0) {
+ ldominfo_list[domidx]->ldomMemSize = memory;
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainSetMemory() memory changed to %dKB\n",memory);
+ }
+ else {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSetMemory(EXIT) memory change failed\n");
+ return (-1);
+ }
+
+ /* Success */
+ return (0);
+} /* ldomsDomainSetMemory() */
+
+/*
+ * ldomsDomainSetMaxMemory
+ *
+ * What:
+ * For LDoms, you cannot set the Maximum memory that a domain can use.
+ * If a domain asks for X memory and it is available, then the domain
+ * will get it when it is bound. Max memory is already calculated for
+ * all domains, just to be able to work with virsh, so this function will
+ * merely return Success to appease virsh.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * memory - Size in KiloBytes
+ * Output: function return - 0 - success
+ *
+ */
+int
+ldomsDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
+{
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSetMaxMemory(ENTER/EXIT) memory=%d\n",memory);
+ return (0);
+} /* ldomsDomainSetMaxMemory() */
+
+/*
+ * ldomsDomainGetInfo
+ *
+ * What: Given a virDomain, get the info for that Domain and return it.
+ * Note: The info.maxMem variable is set to the maximum memory allowed.
+ * We try to get the maximum memory allowed by LDM, by calling
+ * list-devices to get the free memory and by
+ * adding up the total used memory from all domains.
+ * If this fails,
+ * the info.maxMem variable will be set to the maximum value for
+ * a signed long. This is because LDoms does not have a
+ * concept for Max memory for a Domain. However the VMM and
+ * virsh shell do have a Max mem concept and won't let you
+ * change the memory for a Domain if the new amount is
+ * greater than the Maximum. So this is why we set the Max
+ * to the value for a signed long, even though the info.maxMem
+ * data type is an unsigned long.
+ *
+ * Input: domain - Pointer to a virDomain struct
+ * info - Poiner to a virDomainInfo struct to update
+ * Output: Indirect virDomainInfo struct updated with input domain info
+ */
+int
+ldomsDomainGetInfo (virDomainPtr domain, virDomainInfoPtr info)
+{
+ char state;
+ int domidx;
+ struct timeval tv;
+ virDomainInfo domInfo;
+
+ unsigned long maxmem;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetInfo(ENTER) \n");
+
+ if (gettimeofday(&tv, NULL) < 0) {
+ ldomsError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day"), VIR_ERR_WARNING);
+ return (-1);
+ }
+
+ if ((domidx = getDomainIndex(domain)) < 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetInfo(EXIT) getDomainIndex() failed\n");
+ return (-1);
+ }
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetInfo() domain=%s, domidx=%d\n",domain->name,domidx);
+
+/* Convert between LDom Domain state and libvirt Domain state
+ * LDoms
+ * 1 = active
+ * 2 = stopping
+ * 3 = inactive
+ * 4 = binding
+ * 5 = unbinding
+ * 6 = bound
+ * 7 = starting
+ *
+ * libvirt
+ *
+ * VIR_DOMAIN_NOSTATE = 0, no state
+ * VIR_DOMAIN_RUNNING = 1, /* the domain is running
+ * VIR_DOMAIN_BLOCKED = 2, /* the domain is blocked on resource
+ * VIR_DOMAIN_PAUSED = 3, /* the domain is paused by user
+ * VIR_DOMAIN_SHUTDOWN= 4, /* the domain is being shut down
+ * VIR_DOMAIN_SHUTOFF = 5, /* the domain is shut off
+ * VIR_DOMAIN_CRASHED = 6 /* the domain is crashed
+ */
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetInfo() ldomName=%s\n",ldominfo_list[domidx]->ldomName);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetInfo() ldomState=%d\n",ldominfo_list[domidx]->ldomState);
+
+ switch (ldominfo_list[domidx]->ldomState) {
+ case LDOM_STATE_ACTIVE: state = VIR_DOMAIN_RUNNING; break;
+ case LDOM_STATE_STOPPING: state = VIR_DOMAIN_SHUTDOWN; break;
+ case LDOM_STATE_INACTIVE: state = VIR_DOMAIN_SHUTOFF; break;
+ case LDOM_STATE_BINDING: state = VIR_DOMAIN_SHUTDOWN; break;
+ case LDOM_STATE_UNBINDING: state = VIR_DOMAIN_SHUTOFF; break;
+ case LDOM_STATE_BOUND: state = VIR_DOMAIN_SHUTDOWN; break;
+ case LDOM_STATE_STARTING: state = VIR_DOMAIN_RUNNING; break;
+ default: state= VIR_DOMAIN_NOSTATE; break;
+ }
+
+ /* Only name and state are obtained from a list-domain */
+ domInfo.state = state;
+
+ /*
+ * Get the maximum memory that can be allocated for this domain.
+ * For a domain that is bound or active, then it already has that
+ * memory allocated to it. The amount the it can add is only the
+ * amount free in the system, so just add Free + Bound memory.
+ *
+ * For a domain that is inactive, it can request any amount of
+ * memory, even more than what is physically present. Thus we
+ * have to put an upper limit on the Maximum, so again, we just
+ * add the amount of Free system memory to the requested memory.
+ *
+ * Set the dominfo.maxMem to the maximum value for a signed long
+ * if it fails to get the maximum memory allowed from LDM
+ */
+ if (get_free_memory(&maxmem) < 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetInfo() get_free_memory() failed\n");
+ domInfo.maxMem = MAXLONG;
+ } else
+ domInfo.maxMem = maxmem + ldominfo_list[domidx]->ldomMemSize;
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetInfo() MaxMemory=%d\n", maxmem);
+
+ domInfo.memory = ldominfo_list[domidx]->ldomMemSize;
+ domInfo.nrVirtCpu = (unsigned short)ldominfo_list[domidx]->ldomNumVCpu;
+ /* LDM XML does not give the uptime for a Domain, so just set this to 0 */
+ domInfo.cpuTime = 0; /* ((tv.tv_sec * 1000ll * 1000ll * 1000ll * (domidx+1)) + (tv.tv_usec + 100011)); */
+ memcpy(info, &domInfo, sizeof(virDomainInfo));
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetInfo() ldomMemory=%d\n",ldominfo_list[domidx]->ldomMemSize);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetInfo() ldomVcpu=%d\n",ldominfo_list[domidx]->ldomNumVCpu);
+
+
+ return (0);
+} /* ldomsDomainGetInfo() */
+
+/*
+ * ldomsDomainSetVcpus
+ *
+ * What: Given a Domain pointer, send an XML request to change
+ * the number of cpus for the domain.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus)
+{
+ int rc;
+ int domidx;
+ virDomainInfo domInfo;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSetVcpus(ENTER) vcpus=%d\n",nvcpus);
+
+ if ((domidx = getDomainIndex(domain) < 0)) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSetVcpus(EXIT) getDomainIndex() failed\n");
+ return (-1);
+ }
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainSetVcpus: domain=%s, domidx=%d\n",domain->name,domidx);
+ rc = send_ldom_set_vcpu(domain->name, nvcpus);
+
+ if (rc == 0) {
+ ldominfo_list[domidx]->ldomNumVCpu = nvcpus;
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainSetVcpus() vcpus changed to %d\n",nvcpus);
+ }
+ else {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSetVcpus() vcpu change failed\n");
+ return (-1);
+ }
+ return(0);
+
+} /* ldomsDomainSetVcpus() */
+
+/*
+ * ldomsDomainGetVcpus
+ *
+ * What: Given a Domain pointer, send an XML request to get
+ * the CPU bindings for the domain. Then fill in the
+ * input cpuInfo structure with detailed info for each
+ * CPU: virt->phys mapping, State, Uptime. The Affinity
+ * is only Xen specific at this time.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo,
+ unsigned char *cpumaps, int maplen)
+{
+ int i,rc;
+ int domidx;
+ int numCpu;
+ long long upTime;
+ char cpuBits;
+ cpuBindings_t *cpuBindings;
+ processor_info_t pinfo;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetVcpus(ENTER) domName=%s, maxinfo=%d, maplen=%d\n",domain->name, maxinfo, maplen);
+
+ /* Get the Domain index */
+ if ((domidx = getDomainIndex(domain) < 0)) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetVcpus(EXIT) getDomainIndex() failed\n");
+ return (-1);
+ }
+
+ /* The domain must be in the Bound or Active state */
+ if ( (ldominfo_list[domidx]->ldomState == LDOM_STATE_BOUND) ||
+ (ldominfo_list[domidx]->ldomState == LDOM_STATE_ACTIVE) )
+ {
+ if ((numCpu = get_ldom_cpu_bindings(domain->name, &cpuBindings)) < 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetVcpus(EXIT) numCpu=%d failed\n",numCpu);
+ return (-1);
+ }
+ }
+ else {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetVcpus(EXIT) Domain in wrong state %s\n",ldominfo_list[domidx]->ldomState);
+ return (-1);
+ }
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetVcpus() numCpu=%d, cpuBindings=%d \n",numCpu,cpuBindings);
+
+ /* Walk the linked list of CPU bindings and fill in the cpuInfoPtr return structure */
+
+ upTime = getCpuUpTime();
+ while (cpuBindings != NULL) {
+
+ /* Get the CPU state from processor_info(). This will only work for
+ * CPUs in the Control Domain. All other CPUs are in the Guest Domains,
+ * so we set their state to Unknown and Uptime to 0.
+ * TODO unless we can get the State and Uptime from the PRI??
+ */
+
+ if (processor_info(cpuBindings->real, &pinfo) == 0) {
+ switch (pinfo.pi_state) {
+ case 1: info->state = VIR_VCPU_OFFLINE; break;
+ case 2: info->state = VIR_VCPU_RUNNING; break;
+ case 3: info->state = VIR_VCPU_BLOCKED; break;
+ case 4: info->state = VIR_VCPU_OFFLINE; break;
+ case 5: info->state = VIR_VCPU_OFFLINE; break;
+ case 6: info->state = VIR_VCPU_RUNNING; break;
+ case 7: info->state = VIR_VCPU_OFFLINE; break;
+ default: info->state = VIR_VCPU_OFFLINE; break;
+ }
+ info->cpuTime = upTime;
+ } else {
+ info->state = VIR_VCPU_UNKNOWN;
+ info->cpuTime = 0;
+ }
+
+ info->number = cpuBindings->virt;
+ info->cpu = cpuBindings->real;
+
+ /* Got this from libvirt/libvirt.h VIR_CPU_USABLE */
+ /* cpumaps[(info->number) + (info->cpu)/8] = (1<<((info->cpu)%8)); */
+ info++;
+
+ cpuBindings = cpuBindings->next;
+ }
+
+ return (numCpu);
+
+} /* ldomsDomainSetVcpus() */
+
+/*
+ * ldomsDomainGetMaxVcpus
+ *
+ * What: If the domain is inactive, then you can set the cpu constraint
+ * to any number you want, because the CPUs are not reserved until
+ * the domain is bound. Return MAXINT for inactive domains.
+ *
+ * For non-inactive domains, call existing fuctions to get the amount
+ * of Free and Used CPUs in the system. Now since a request is being
+ * made for a domain that already has Vcpus allocated to it, we have
+ * to add that amount of the Free amount, and then return that value.
+ *
+ * Example. Total Vcpus=32; Free Vcpus=10; Domains X has 15.
+ * Now, we want to increase Domain X Vcpus to 17.
+ * Now, if we return the # for Free Vcpus, virsh will not call the
+ * SetVcpu routine, and will report an error instead, because the
+ * request of 17 is greater than the Free amount.
+ * So we add the Free (10) and the current allocated (15) and return
+ * that as the Max # of Vcpus.
+ *
+ *
+ * Input: domain - A pointer to the virDomain structure UNUSED
+ * Output: function return - >=0 # of Free CPUs. <0 error.
+ */
+int
+ldomsDomainGetMaxVcpus(virDomainPtr domain)
+{
+ int freeVcpus;
+ int domainVcpus;
+
+ /* inactive domains can request any amount of vcpus */
+ if (domain->id < 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetMaxVcpus(ENTER) inactive domain=%s, MaxVcpus=%d\n",domain->name,MAXINT);
+ return (MAXINT);
+ }
+
+ /*
+ * For bound and active domains, sum the # of Free Vcpus and the # currently
+ * currently used by the Domain. This is the Max # that can be requested.
+ */
+ freeVcpus = ldomsGetMaxVcpus(NULL, NULL);
+ domainVcpus = ldominfo_list[domain->id]->ldomNumVCpu;
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetMaxVcpus() Domain Vcpus=%d, Free Vcpus=%d\n",ldominfo_list[domain->id]->ldomNumVCpu,freeVcpus);
+
+ return (freeVcpus + domainVcpus);
+
+
+} /* ldomsDomainSetVcpus() */
+
+/*
+ * ldomsDomainDumpXML
+ *
+ * What: Send a list-constraints request to LDM for the domain specified
+ * by the input virDomain.
+ *
+ * Input: domain - Pointer to a virDomain structure
+ * Output: function return - char ptr to the XML data
+ */
+char *
+ldomsDomainDumpXML(virDomainPtr domain, int flags)
+{
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDumpXML(ENTER) domain=%s\n",domain->name);
+
+ xmlDocPtr xml_to_send;
+ xmlDocPtr xml_received;
+ unsigned char *xml;
+ int xmlSize;
+ int domidx;
+
+ if ((domidx = getDomainIndex(domain)) < 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDumpXML(EXIT) getDomainIndex() failed\n");
+ return (NULL);
+ }
+
+ /* Create XML list-constraints request */
+ xml_to_send = create_xml_file_4_ldom_action(domain->name, XML_LIST_CONST);
+ if (xml_to_send == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDumpXML() can not create list-constraints xml file\n");
+ ldomsError(NULL, domain, VIR_ERR_INTERNAL_ERROR, "Could not create XML file", VIR_ERR_ERROR);
+ return (NULL);
+ }
+
+ /* Send request to LDM and receive response */
+ xml_received = send_xml_file_to_ldm(xml_to_send);
+ if (xml_received == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDumpXML() failed to send xml file to ldm and receive xml response\n");
+ ldomsError(NULL, domain, VIR_ERR_OPERATION_FAILED, "Could not create XML file", VIR_ERR_ERROR);
+ xmlFreeDoc(xml_to_send);
+ return (NULL);
+ }
+
+ /* Dump the response to memory */
+ xml = malloc(sizeof(char) * 10000);
+ xmlKeepBlanksDefault(0);
+ xmlDocDumpFormatMemory(xml_received, &xml, &xmlSize, 1);
+ if ( xmlSize > 0 ) {
+ xmlFree(xml_received);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainDumpXML() xml doc size is %d:\n%s\n",xmlSize,xml);
+ return ((char *)xml);
+ }
+
+ return (NULL);
+
+} /* ldomsDomainDumpXML() */
+
+/*
+ * ldomsListDefinedDomains
+ *
+ * What: Return the names of all inactive Domains
+ *
+ * Input: conn - Pointer to a connection structure
+ * names - An array of pointers to chars (Domain names)
+ * maxnames - Total number of inactive Domains
+ * Output: function return - # of inactive Domains found
+ * names - Updated pointers to strdup'd inactive Domain names
+ */
+int ldomsListDefinedDomains(virConnectPtr conn,
+ char **const names,
+ int maxnames)
+{
+
+/* virsh command 'define' creates a domain but leaves it in the bound state.
+ * This routine is finding all inactive domains, but the name of the routine is
+ * ListDefinedDomains. We are just following what test.c does, which is count
+ * the number of Domains in libvirt state SHUTOFF, which is LDoms state inactive.
+ */
+ int n = 0, i;
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsListDefinedDomains(ENTER) maxnames=%d\n",maxnames);
+
+ /* get the current ldom data from LDM */
+ (void) pthread_rwlock_wrlock(&update_lock);
+ refresh_ldom_data();
+ (void) pthread_rwlock_unlock(&update_lock);
+
+
+ /* TODO NOTE: We did not call get_ldom_names() here since the thought
+ * is that ldomsNumOfDefinedDomains() will always be called right
+ * before this is. This may not be the case, but for now we will
+ * leave until we find out otherwise.
+ */
+ for (i = 0, n = 0 ; i < ldom_cnt && n < maxnames ; i++) {
+ if (ldominfo_list[i]->ldomState == LDOM_STATE_INACTIVE) {
+ names[n++] = strdup(ldominfo_list[i]->ldomName);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsListDefinedDomains() inactive domain=%s\n",
+ ldominfo_list[i]->ldomName);
+ }
+ }
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsListDefinedDomains(EXIT) # of inactive domains=%d\n",n);
+ return (n);
+} /* ldomsListDefinedDomains() */
+
+/*
+ * ldomsNumOfDefinedDomains
+ *
+ * What: Return the total number of inactive Domains (VIR_SHUT_OFF)
+ *
+ * Input: conn - Pointer to a connection structure
+ * Output: function return - # of inactive Domains
+ */
+int
+ldomsNumOfDefinedDomains (virConnectPtr conn)
+{
+ int numInactive = 0, i;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNumOfDefinedDomains(ENTER) \n");
+
+ /* Send an LDM request 'list-domains' */
+ if (get_ldom_names(&ldom_cnt, &ldominfo_list) < 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNumOfDefinedDomains() get_ldom_names() failed\n");
+ return (-1);
+ };
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsNumOfDefinedDomains() get_ldom_names(return) ldom_cnt=%d\n",ldom_cnt);
+
+
+ /* The Domain ID will be the index into the ldominfo_list array */
+ for (i=0; i<ldom_cnt; i++) {
+ if (ldominfo_list[i] == NULL) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsNumOfDefinedDomains() ldominfo_list[%d] is NULL\n",i);
+ }
+ else if (ldominfo_list[i]->ldomState == LDOM_STATE_INACTIVE) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsNumOfDefinedDomains() inactive Domain ID=%d \n",i);
+ numInactive++;
+ }
+ }
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNumOfDefinedDomains(EXIT) # of inactive domains=%d \n",numInactive);
+ return (numInactive);
+} /* ldomsNumOfDefinedDomains() */
+
+/*
+ * ldomsDomainStart
+ *
+ * What: Start a previously defined inactive domain.
+ * The domain can be in the inactive or bound state to begin
+ * and will be put into the active state.
+ *
+ * Input: domain - A pointer to a virDomain structure (unused)
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainStart(virDomainPtr domain)
+{
+ int rc = 0;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainStart(ENTER) domName=%s, domID=%d\n",
+ domain->name,domain->id);
+
+ /* get the current ldom data from LDM */
+ (void) pthread_rwlock_wrlock(&update_lock);
+ refresh_ldom_data();
+ (void) pthread_rwlock_unlock(&update_lock);
+
+
+ /* If the domain ID is -1, this means the domain state is 'inactive.
+ * If the domain state is inactive (3), then bind the domain */
+ if ((domain->id == -1) ||
+ (ldominfo_list[domain->id]->ldomState == LDOM_STATE_INACTIVE)) {
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainStart() Domain state is 'inactive', binding...\n");
+ rc = send_ldom_lifecycle_action(domain->name, LDOM_BIND);
+
+ /* Need to tell the next piece of code that a 'bind' was done and
+ * was successful, because the ldom info has not been updated.
+ */
+ if (rc == 0) rc = 1;
+ }
+
+ /* If the domain was inactive and failed to bind, or if the domain was already
+ * active, then we fall into this case.
+ */
+ if (rc < 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainStart(EXIT) Domain state change failed. domain=%s\n",domain->name);
+ return (-1);
+ }
+
+ /* If the domain state is bound (6), then start the domain */
+ if ((rc == 1) || (ldominfo_list[domain->id]->ldomState == LDOM_STATE_BOUND)) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainStart() Domain state is 'bound' rc=%d, starting...\n",rc);
+ rc = send_ldom_lifecycle_action(domain->name, LDOM_START);
+ if (rc == 0) rc = 2;
+ }
+
+ /* If successful, the domain state changed to active */
+ if (rc == 2) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainStart() Domain state changed to 'active'. domain=%s\n",
+ domain->name);
+ return (0);
+ }
+
+ ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, _("Domain is active"), VIR_ERR_WARNING );
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainStart(EXIT) Domain state change failed. domain=%s\n",domain->name);
+ return (-1);
+
+
+} /* ldomsDomainStart() */
+
+/*
+ * ldomsDomainDefineXML
+ *
+ * What: Create a domain from an XML file so that it is left in the
+ * bound state. The XML input must be of the form from the
+ * output of 'ldm list-constraints -x <ldom>'. Any of the
+ * XML can be changed, but the <action> tag will be added by
+ * this code.
+ *
+ * Input: xml - The xml file in a char buffer
+ * Output: function return - A ptr to a virDomain or NULL
+ */
+virDomainPtr
+ldomsDomainDefineXML(virConnectPtr conn, const char *xml)
+{
+ virDomainPtr domPtr = NULL;
+ char *domainName = NULL;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDefineXML(ENTER) \n");
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainDefineXML(ENTER) xmldoc=\n%s\n",xml);
+
+ /* Send the XML file along with the lifecycle action */
+ domainName = send_ldom_create_domain((char *)xml, XML_BIND_DOMAIN);
+
+ /*
+ * If the create domain was successful, then we have to create a DomainInfo
+ * structure to pass back to the caller. We need the Domain name that was
+ * created, and the only way to get that is from parsing the input xml
+ * document. This is done in send_ldom_create_domain() and passed back as the return.
+ * Also we create the uuid for the domain name.
+ */
+ if (domainName != NULL) {
+
+ /*
+ * The UUID is not important, cuz only the Domain name is printed
+ * out in the virsh. So just use the default UUID.
+ */
+ domPtr = virGetDomain(conn, domainName, Uuid);
+ free(domainName);
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDefine(EXIT) \n");
+
+ return (domPtr);
+} /* ldomsDomainDefineXML() */
+
+/*
+ * ldomsDomainUndefine
+ *
+ * What: Given a Domain pointer, undefine/delete the domain.
+ * The domain can only be in the inactive state to begin,
+ * and will be deleted to not exist.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainUndefine(virDomainPtr domain)
+{
+ int rc = -1;
+ int domidx;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainUndefine(ENTER) domName=%s, domID=%d\n",
+ domain->name,domain->id);
+
+ /* If the Domain is inactive, the ID in the input domain will be a -1.
+ * Get the domain index from our ldominfo_list to verify it is indeed inactive
+ * before we try to delete it.
+ */
+ if ((domidx = getDomainIndex(domain)) < 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainUndefine(EXIT) getDomainIndex() failed\n");
+ return (-1);
+ }
+
+ /* If the domain state is inactive, then delete the domain */
+ if ( (ldominfo_list[domidx]->ldomState == LDOM_STATE_INACTIVE) &&
+ (domain->id == -1) )
+ {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainUndefine() Domain state is 'inactive', deleting...\n");
+ rc = send_ldom_lifecycle_action(domain->name, LDOM_DELETE);
+ } else {
+ ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, _("Domain is not inactive"), VIR_ERR_WARNING );
+ return (-1);
+ }
+
+ /* If successful, the domain has been deleted */
+ if (rc == 0) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainUndefine() Domain deleted\n");
+ return (0);
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainUndefine(EXIT) Domain undefine failed\n");
+
+ return (-1);
+} /* ldomsDomainUndefine() */
+
+/*
+ * ldomsDomainConsole
+ *
+ * What: Given a Domain pointer, get the console port number
+ * for the domain.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - <0 is failure, >0 is the domain console port number
+ */
+int
+ldomsDomainConsole(virDomainPtr domain)
+{
+ int rc = 0;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainConsole(ENTER) domName=%s, domID=%d\n",
+ domain->name,domain->id);
+
+ /* get the current ldom data from LDM */
+ (void) pthread_rwlock_wrlock(&update_lock);
+ refresh_ldom_data();
+ (void) pthread_rwlock_unlock(&update_lock);
+
+ /*
+ * If the domain ID is -1, this means the domain state is 'inactive.
+ * If the domain state is inactive (3), then we don't return a port #
+ * Log an error because an inactive domain has no active console port.
+ */
+ if ((domain->id == -1) ||
+ (ldominfo_list[domain->id]->ldomState == LDOM_STATE_INACTIVE)) {
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DEBUG: ldomsDomainConsole(EXIT) Domain state is 'inactive'\n");
+ ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, "Domain is inactive", VIR_ERR_WARNING );
+ return (-1);
+ }
+
+ /*
+ * If the domain is the primary domain, then its console has to be accessed
+ * via the SC and not thru this utility. There is no port number associated
+ * with the primary domain console.
+ */
+ if (strcmp(domain->name, "primary") == 0) {
+ ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, "Must connect to primary console via the SC", VIR_ERR_WARNING );
+ return (-1);
+ }
+
+ /* Else, the console port # is in the ldominfo_list[] for that domain */
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainConsole(EXIT) console=%d\n",
+ ldominfo_list[domain->id]->ldomConsole);
+ return (ldominfo_list[domain->id]->ldomConsole);
+}
+
+void dprt(const char *template, ...)
+{
+ va_list ap;
+ char buf[10240];
+ static int do_open = 1;
+ static FILE * fp;
+
+ va_start(ap, template);
+ (void) vsprintf(buf, template, ap);
+ va_end(ap);
+
+ if (do_open) {
+ do_open = 0;
+
+ fp = fopen("/var/log/libvirt_ldoms.dbg", "w");
+ }
+ fputs(buf, fp);
+ fflush(fp);
+} /* dprt */
+
+/*
+ * refresh_ldom_data
+ *
+ * Send an XML request to LDM for a list of all Domains
+ * and get the basic information of each Domain.
+ *
+ * This function will be called for each commands to
+ * guarantee that we have the current LDom info for any
+ * virsh CLI command.
+ *
+ * Input:
+ * Output:
+ */
+static void
+refresh_ldom_data()
+{
+ struct timeval tv;
+ long delta;
+
+ /* Try and throttle calling the LDM to update the list of
+ * LDoms. If the calls are 2 secs or less apart, then we just
+ * use the current LDoms info. This is because each
+ * command from virsh can turn into several calls into
+ * function in this file, which all call this function
+ * to refresh the LDom data.
+ */
+ if (gettimeofday(&tv, NULL) >= 0) {
+ /* See if the time since the last call to this functions
+ * is less than 3 seconds. If so, just return.
+ */
+ if ((delta=tv.tv_sec - last_ldom_refresh) < 3) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: refresh_ldom_data(NO Refresh) delta=%d\n",
+ delta);
+ return;
+ }
+ last_ldom_refresh = tv.tv_sec;
+ }
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: refresh_ldom_data(Refresh) delta=%d\n",delta);
+
+ /*
+ * Call LDM with a list-domains cmd to get the total
+ * # of Domains and the basic information of each one.
+ */
+
+ if (get_ldom_names(&ldom_cnt, &ldominfo_list) < 0) {
+ /* Any ldominfo_t memory was freed in get_ldom_names() */
+ free(ldominfo_list);
+ if (ldoms_debug) dprt("LDOMS_DEBUG: refresh_ldom_data() get_ldom_names() failed\n");
+ }
+
+} /* refresh_ldom_data() */
+
+/*
+ * getHypervisorVersion()
+ *
+ * Gets the LDoms hypervisor version by parsing the output of
+ * the command 'ldm -V'.
+ *
+ * The output is:
+ * Logical Domain Manager (v 1.0.1)
+ * Hypervisor control protocol v 1.0
+
+ * System PROM:
+ * Hypervisor v. 1.5.1 @(#)Hypervisor 1.5.1 2007/09/14 16:11\015
+ *
+ * OpenBoot v. 4.27.1 @(#)OBP 4.27.1 2007/09/14 15:17
+ *
+ * Output: long representing the value of the hypervisor version in the format
+ * needed by virsh.
+ */
+
+static long
+getHypervisorVersion()
+{
+ FILE *fp = popen("/opt/SUNWldm/bin/ldm -V", "r");
+ char buf[256];
+ char major[8], minor[8], rel[8];
+ char *chp,*chp1;
+ long long hyperVersion;
+ int done = 0;
+ int PROM_line_found = 0;
+ long maj,min,release;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getHypervisorVersion(ENTER)\n");
+
+ /* check the popen for failure */
+ if (fp == NULL)
+ return(0);
+
+ /* Read the input until we find and process the Hypervisor version */
+ while (! done) {
+ chp = fgets(buf,sizeof(buf),fp);
+ if (chp == NULL)
+ return(0);
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getHypervisorVersion() line=%s\n",buf);
+
+ if ( (chp1=strstr(buf,"PROM")) != NULL ) {
+ PROM_line_found = 1;
+ continue;
+ }
+
+ if (((chp1=strstr(buf,"Hypervisor")) != NULL ) && (PROM_line_found)) {
+
+ /*
+ * There are more than 1 lines with 'Hypervisor' in them. Wait until
+ * we find the line with 'System PROM'. The next line with 'Hypervisor'
+ * will be the one we want.
+ */
+
+ /* Step thru to the '.' */
+ while (*chp1 != '.') chp1++;
+ chp1++;
+
+ /* Step to the 1st digit of the version */
+ while ((*chp1 == ' ') || (*chp1 == '\t')) chp1++;
+
+ /* Pointing to 1st digit of version. */
+ if (isdigit(*chp1)) {
+ major[0] = *chp1++;
+ } else {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getHypervisorVersion() Major '%c' is not a digit\n",*chp1);
+ return(0);
+ }
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getHypervisorVersion() major=%c:%d \n",major[0],major[0]);
+
+ /* *chp1 should be a '.' */
+ if (*chp1++ != '.' ) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getHypervisorVersion() No . after major? ch=%c\n",*(--chp1));
+ return(0);
+ }
+ /* Should be pointing to minor version digit */
+ if (isdigit(*chp1)) {
+ minor[0] = *chp1++;
+ } else {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getHypervisorVersion() Minor '%c' is not a digit\n",*chp1);
+ return(0);
+ }
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getHypervisorVersion() minor=%c:%d \n",minor[0],minor[0]);
+
+ /* If we are not pointing to a '.', then there is no rel */
+ if (*chp1++ != '.' ) {
+ rel[0] = '0';
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getHypervisorVersion() Not pointing to a '.' before the release digit. ch=%c\n",*(--chp1));
+ } else {
+ if (isdigit(*chp1)) {
+ rel[0] = *chp1++;
+ } else {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getHypervisorVersion() Release '%c' is not a digit\n",*chp1);
+ rel[0] = '0';
+ }
+ }
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getHypervisorVersion() rel=%c:%d \n",rel[0],rel[0]);
+
+ break; /* out of while */
+ }
+ } /* while */
+
+ /* Now construct the long long that virsh needs to convert to a version number */
+ major[1] = '\0';
+ minor[1] = '\0';
+ rel[1] = '\0';
+
+ maj = atol(major) * 1000000;
+ min = atol(minor) * 1000;
+ release = atol(rel);
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getHypervisorVersion(EXIT) maj=%d, min=%d, rel=%d, version=%d\n",
+ maj,min,release,maj+min+release);
+
+ return (maj + min + release);
+
+} /* getHypervisorVersion() */
+
+
+/*
+ * getLDMVersion()
+ *
+ * Gets the LDoms Manager version by parsing the output of
+ * the command 'ldm -V'.
+ *
+ * The output is:
+ * Logical Domain Manager (v 1.0.1)
+ * ..
+ * Output: long representing the value of the LDoms Manager version in the format
+ * needed by virsh.
+ */
+
+static unsigned long
+getLDMVersion()
+{
+ FILE *fp = popen("/opt/SUNWldm/bin/ldm -V", "r");
+ char buf[256];
+ char major[8], minor[8], rel[8];
+ char *chp,*chp1;
+ int done = 0;
+ int LDM_line_found = 0;
+ unsigned long maj,min,release;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getLDMVersion(ENTER)\n");
+
+ /* check the popen for failure */
+ if (fp == NULL)
+ return(0);
+
+ /* Read the input until we find and process the LDoms Manager version */
+ while (! done) {
+ chp = fgets(buf,sizeof(buf),fp);
+ if (chp == NULL)
+ return(0);
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getLDMVersion() line=%s\n",buf);
+
+
+ if ( (chp1=strstr(buf,"Logical Domain Manager")) != NULL ) {
+ LDM_line_found = 1;
+ }
+
+ if (LDM_line_found) {
+
+ /* Step thru to the 'v' */
+ while (*chp1 != 'v') chp1++;
+ chp1++;
+
+ /* Step to the 1st digit of the version */
+ while ((*chp1 == ' ') || (*chp1 == '\t')) chp1++;
+
+ /* Pointing to 1st digit of version. */
+ if (isdigit(*chp1)) {
+ major[0] = *chp1++;
+ } else {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getLDMVersion() Major '%c' is not a digit\n",*chp1);
+ return(0);
+ }
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getLDMVersion() major=%c:%d \n",major[0],major[0]);
+
+ /* *chp1 should be a '.' */
+ if (*chp1++ != '.' ) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getLDMVersion() No . after major? ch=%c\n",*(--chp1));
+ return(0);
+ }
+ /* Should be pointing to minor version digit */
+ if (isdigit(*chp1)) {
+ minor[0] = *chp1++;
+ } else {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getLDMVersion() Minor '%c' is not a digit\n",*chp1);
+ return(0);
+ }
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getLDMVersion() minor=%c:%d \n",minor[0],minor[0]);
+
+ /* If we are not pointing to a '.', then there is no rel */
+ if (*chp1++ != '.' ) {
+ rel[0] = '0';
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getLDMVersion() Not pointing to a '.' before the release digit. ch=%c\n",*(--chp1));
+ } else {
+ if (isdigit(*chp1)) {
+ rel[0] = *chp1++;
+ } else {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getLDMVersion() Release '%c' is not a digit\n",*chp1);
+ rel[0] = '0';
+ }
+ }
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getLDMVersion() rel=%c:%d \n",rel[0],rel[0]);
+
+ break; /* out of while */
+ }
+ } /* while */
+
+ /* Now construct the long long that virsh needs to convert to a version number */
+ major[1] = '\0';
+ minor[1] = '\0';
+ rel[1] = '\0';
+
+ maj = atol(major) * 1000000;
+ min = atol(minor) * 1000;
+ release = atol(rel);
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: getLDMVersion(EXIT) maj=%d, min=%d, rel=%d, version=%d\n",
+ maj,min,release,maj+min+release);
+
+ return (maj + min + release);
+
+} /* getLDMVersion() */
+
+/*
+ * getCpuUpTime()
+ *
+ * Gets the CPU uptime by parsing the output of the command 'uptime'.
+ *
+ * Output: long representing the value of the cpu up time in nanosecs
+ */
+long long
+getCpuUpTime()
+{
+ FILE *fp = popen("/bin/uptime", "r");
+ char buf[256];
+ char output[256];
+ char day[5];
+ char hour[5];
+ char min[5];
+ char *chp1,*chp2;
+ int d=0,h=0,m=0;
+ long long uptime;
+ long long duptime;
+ long long huptime;
+ long long muptime;
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getCpuUpTime(ENTER) \n");
+
+ /* check the popen for failure */
+ if (fp == NULL)
+ return(0);
+
+ fgets(buf,sizeof(buf),fp);
+ pclose(fp);
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getCpuUpTime() buf=%s \n",buf);
+ /* Find 'up', then advance to the day */
+ /* 6:56am up 6 day(s), 14:46, 10 users, load average: 0.06, 0.14, 0.12 */
+ chp1 = strstr(buf, "up");
+ if (chp1 == NULL)
+ return(0);
+
+ while (*chp1 != ' ') chp1++;
+ chp1++;
+
+ /* Get the day number */
+ /* chp2 is point at the 6 */
+ chp2=chp1;
+ while (*chp2 != ' ') {
+ day[d++] = *chp2;
+ chp2++;
+ }
+ day[d] = '\0';
+ chp2++;
+
+ /* Advance to the 1st digit of the hour */
+ /* chp2 is pointing at the 'd' */
+ while (*chp2 != ' ') chp2++;
+ chp2++;
+
+ /* Get the hour number */
+ /* chp2 is pointing at the '1' */
+ while (*chp2 != ':') { hour[h++] = *chp2; chp2++; }
+ hour[h] = '\0';
+ chp2++;
+
+ /* Get the minute number */
+ /* chp2 is pointing at the '4' after : */
+ while (*chp2 != ',') { min[m++] = *chp2; chp2++; }
+ min[m] = '\0';
+ chp2++;
+
+ strncpy(output, chp1, (chp2 - chp1));
+ output[chp2-chp1] = '\0';
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getCpuUpTime(): Uptime = %s\n",output);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getCpuUpTime(): day=%s, hour=%s, min=%s\n",day,hour,min);
+
+ duptime = atoll(day);
+ duptime = duptime * 60 * 60 * 24;
+ huptime = atoll(hour);
+ huptime = huptime * 60 * 60;
+ muptime = atoll(min);
+ muptime = muptime * 60;
+ uptime = duptime + huptime + muptime;
+ uptime *= 1000000000;
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getCpuUpTime(): Uptime = %lld nanosecs\n",uptime);
+
+ return (uptime);
+
+} /* getCpuUpTime() */
+
+/*
+ * Callback functions for Network actions. These are defined at the end
+ * so we don't have to declare function prototypes at the beginning of
+ * this file.
+ */
+static virNetworkDriver ldomsNtwkDriver = {
+ "LDoms",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*
+ * Callback functions for Domain actions. These are defined at the end
+ * so we don't have to declare function prototypes at the beginning of
+ * this file.
+ */
+static virDriver ldomsDriver = {
+ VIR_DRV_LDOMS, /* Driver number */
+ "LDoms", /* Name of the driver */
+ LDOMS_VERSION_NUMBER, /* Version of LDoms API */
+ ldomsOpen, /* open */
+ ldomsClose, /* close */
+ NULL, /* virDrvSupportsFeature supports_feature; NOT LDOMS SUPPORTED */
+ ldomsGetType, /* type */
+ ldomsGetVersion, /* getVersion */
+ ldomsGetHostname, /* getHostname */
+ NULL, /* virDrvGetURI getURI; NOT LDOMS SUPPORTED */
+ ldomsGetMaxVcpus, /* virDrvGetMaxVcpus TODO need support */
+ ldomsNodeGetInfo, /* nodeGetInfo */
+ NULL, /* virDrvGetCapabilities getCapabilities; NOT LDOMS SUPPORTED */
+ ldomsListDomains, /* listDomains */
+ ldomsNumOfDomains, /* numOfDomains */
+ ldomsDomainCreateXML, /* domainCreateLinux; Create an inactive domain from XML */
+ ldomsDomainLookupByID, /* domainLookupByID */
+ ldomsDomainLookupByUUID, /* domainLookupByUUID */
+ ldomsDomainLookupByName, /* domainLookupByName */
+ ldomsDomainSuspend, /* virDrvDomainSuspend domainSuspend; TODO NOT LDOMS SUPPORTED */
+ ldomsDomainResume, /* virDrvDomainResume domainResume; TODO NOT LDOMS SUPPORTED */
+ ldomsDomainShutdown, /* domainShutdown */
+ NULL, /* virDrvDomainReboot domainReboot; NOT LDOMS SUPPORTED */
+ ldomsDomainDestroy, /* domainDestroy */
+ ldomsDomainGetOSType, /* domainGetOSType */
+ ldomsDomainGetMaxMemory, /* domainGetMaxMemory */
+ ldomsDomainSetMaxMemory, /* domainSetMaxMemory */
+ ldomsDomainSetMemory, /* domainSetMemory */
+ ldomsDomainGetInfo, /* domainGetInfo */
+ NULL, /* virDrvDomainSave domainSave; NOT LDOMS SUPPORTED */
+ NULL, /* virDrvDomainRestore domainRestore; NOT LDOMS SUPPORTED */
+ NULL, /* virDrvDomainCoreDump domainCoreDump; NOT LDOMS SUPPORTED */
+ ldomsDomainSetVcpus, /* domainSetVcpus */
+ NULL, /* virDrvDomainPinVcpu domainPinVcpu; NOT LDOMS SUPPORTED */
+ ldomsDomainGetVcpus, /* domainGetVcpus */
+ ldomsDomainGetMaxVcpus, /* domainGetMaxVcpus; */
+ ldomsDomainDumpXML, /* domainDumpXML */
+ ldomsListDefinedDomains, /* listDefinedDomains */
+ ldomsNumOfDefinedDomains, /* numOfDefinedDomains */
+ ldomsDomainStart, /* domainCreate - Really start an inactive domain */
+ ldomsDomainDefineXML, /* domainDefineXML */
+ ldomsDomainUndefine, /* domainUndefine */
+ NULL, /* virDrvDomainAttachDevice domainAttachDevice; NOT LDOMS SUPPORTED */
+ NULL, /* virDrvDomainDetachDevice domainDetachDevice; NOT LDOMS SUPPORTED */
+ NULL, /* virDrvDomainGetAutostart domainGetAutostart; NOT LDOMS SUPPORTED */
+ NULL, /* virDrvDomainSetAutostart domainSetAutostart; NOT LDOMS SUPPORTED */
+ NULL, /* virDrvDomainGetSchedulerType domainGetSchedulerType; NOT LDOMS SUPPORTED */
+ NULL, /* virDrvDomainGetSchedulerParameters domainGetSchedulerParameters; NOT LDOMS SUPPORTED */
+ NULL, /* virDrvDomainSetSchedulerParameters domainSetSchedulerParameters; NOT LDOMS SUPPORTED */
+ NULL, /* virDrvDomainMigratePrepare domainMigratePrepare; NOT LDOMS SUPPORTED */
+ NULL, /* virDrvDomainMigratePerform domainMigratePerform; NOT LDOMS SUPPORTED */
+ NULL, /* virDrvDomainMigrateFinish domainMigrateFinish; NOT LDOMS SUPPORTED */
+ NULL, /* virDrvDomainBlockStats domainBlockStats; NOT LDOMS SUPPORTED */
+ NULL, /* virDrvDomainInterfaceStats domainInterfaceStats; NOT LDOMS SUPPORTED */
+ NULL, /* virDrvNodeGetCellsFreeMemory nodeGetCellsFreeMemory; NOT LDOMS SUPPORTED */
+ NULL, /* virDrvNodeGetFreeMemory getFreeMemory; NOT LDOMS SUPPORTED */
+ ldomsDomainConsole, /* ldomConsole */
+};
+
+/*
+ * ldomsRegister:
+ *
+ * Registers LDoms in libvirt driver system. This functions goes at the
+ * end so we don't have to declare ldomsDriver or ldomsNtwkDriver ahead of time.
+ */
+int ldomsRegister(void) {
+
+ /* for debug statements */
+#ifdef LDOMS_DEBUG
+ ldoms_debug = 1;
+ dprt("LDOMS_DEBUG on\n");
+#endif
+#ifdef LDOMS_DETAILED_DEBUG
+ ldoms_detailed_debug = 1;
+ dprt("LDOMS_DETAILED_DEBUG on\n");
+#endif
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsRegister(ENTER)\n");
+
+ /* Only root can execute libvirt LDoms */
+ if (geteuid() != 0) return -1;
+
+ /* initialize for a rw-lock to make the code more multithread-safe */
+ (void) pthread_rwlock_init(&update_lock, NULL);
+
+ /* Get the LDoms Manager version number */
+ LDMVersion = getLDMVersion();
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsRegister.. LDoms version used = %u\n", LDMVersion);
+
+ return (virRegisterDriver(&ldomsDriver));
+
+
+}
+
+
+#endif /* WITH_LDOMS */
+
+/*
+ * vim: set tabstop=4:
+ * vim: set shiftwidth=4:
+ * vim: set expandtab:
+ */
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
+
diff --git a/src/ldoms_intfc.h b/src/ldoms_intfc.h
new file mode 100644
--- /dev/null
+++ b/src/ldoms_intfc.h
@@ -0,0 +1,336 @@
+/*
+ * ldoms_intfc.h: LDoms definitions used for interfaces with the LDoms Manager (LDM)
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ */
+
+#ifndef __VIR_LDOMS_INTFC_H__
+#define __VIR_LDOMS_INTFC_H__
+
+#ifdef WITH_LDOMS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/byteorder.h>
+#include <inttypes.h>
+#include <libxml/tree.h>
+
+#include "ldoms_xml_parse.h"
+#include "ldoms_common.h"
+
+#define DEFAULT_PORT 5311
+#define LDOM_INTERFACE_VERSION ((xmlChar *)"1.0")
+#define LDOM_DATA_VERSION ((xmlChar *)"2.0")
+#define VERSION_ATTR ((xmlChar *)"version")
+
+#define XML_VERSION ((xmlChar *)"1.0") /* version of XML used */
+
+#define XML_ADD_DOMAIN ((xmlChar *)"add-domain")
+#define XML_DELETE ((xmlChar *)"remove-domain")
+#define XML_STOP ((xmlChar *)"stop-domain")
+#define XML_START_DOMAIN ((xmlChar *)"start-domain")
+#define XML_BIND_DOMAIN ((xmlChar *)"bind-domain")
+#define XML_UNBIND ((xmlChar *)"unbind-domain")
+#define XML_LIST_CONST ((xmlChar *)"list-constraints")
+#define XML_LIST_BIND ((xmlChar *)"list-bindings")
+#define XML_LIST ((xmlChar *)"list-domain")
+#define XML_LIST_DEVICES ((xmlChar *)"list-devices")
+#define XML_LIST_SERVICES ((xmlChar *)"list-services")
+#define XML_LIST_SETS ((xmlChar *)"list-spconfig")
+#define XML_LIST_VARS ((xmlChar *)"list-variable")
+#define XML_ADD_VCPU ((xmlChar *)"add-vcpu")
+#define XML_ADD_MAU ((xmlChar *)"add-mau")
+#define XML_ADD_MEM ((xmlChar *)"add-memory")
+#define XML_ADD_IO ((xmlChar *)"add-io")
+#define XML_ADD_VAR ((xmlChar *)"add-variable")
+#define XML_ADD_VCONSCON ((xmlChar *)"add-vconscon")
+#define XML_ADD_VDISK ((xmlChar *)"add-vdisk")
+#define XML_ADD_VDS ((xmlChar *)"add-vdiskserver")
+#define XML_ADD_VDSDEV ((xmlChar *)"add-vdiskserverdevice")
+#define XML_ADD_VNET ((xmlChar *)"add-vnet")
+#define XML_ADD_VSW ((xmlChar *)"add-vswitch")
+#define XML_ADD_SPCONFIG ((xmlChar *)"add-spconfig")
+#define XML_ADD_VDPCS ((xmlChar *)"add-vdpcs")
+#define XML_ADD_VDPCC ((xmlChar *)"add-vdpcc")
+#define XML_SET_VCPU ((xmlChar *)"set-vcpu")
+#define XML_SET_MAU ((xmlChar *)"set-mau")
+#define XML_SET_MEM ((xmlChar *)"set-memory")
+#define XML_SET_VAR ((xmlChar *)"set-variable")
+#define XML_SET_VCONSCON ((xmlChar *)"set-vconscon")
+#define XML_SET_VNET ((xmlChar *)"set-vnet")
+#define XML_SET_VSW ((xmlChar *)"set-vswitch")
+#define XML_SET_SPCONFIG ((xmlChar *)"set-spconfig")
+#define XML_SET_VCONSOLE ((xmlChar *)"set-vconsole")
+#define XML_REMOVE_VCPU ((xmlChar *)"remove-vcpu")
+#define XML_REMOVE_MAU ((xmlChar *)"remove-mau")
+#define XML_REMOVE_MEM ((xmlChar *)"remove-memory")
+#define XML_REMOVE_IO ((xmlChar *)"remove-io")
+#define XML_REMOVE_VAR ((xmlChar *)"remove-variable")
+#define XML_REMOVE_VCONSCON ((xmlChar *)"remove-vconscon")
+#define XML_REMOVE_VDISK ((xmlChar *)"remove-vdisk")
+#define XML_REMOVE_VDS ((xmlChar *)"remove-vdiskserver")
+#define XML_REMOVE_VDSDEV ((xmlChar *)"remove-vdiskserverdevice")
+#define XML_REMOVE_VNET ((xmlChar *)"remove-vnet")
+#define XML_REMOVE_VSW ((xmlChar *)"remove-vswitch")
+#define XML_REMOVE_SPCONFIG ((xmlChar *)"remove-spconfig")
+#define XML_REMOVE_RECONF ((xmlChar *)"remove-reconf")
+#define XML_REMOVE_VDPCS ((xmlChar *)"remove-vdpcs")
+#define XML_REMOVE_VDPCC ((xmlChar *)"remove-vdpcc")
+
+#define XML_LDM_INTERFACE ((xmlChar *)"LDM_interface")
+#define XML_ACTION ((xmlChar *)"action")
+#define XML_DATA ((xmlChar *)"data")
+#define XML_SNMP_USER ((xmlChar *)"snmp_user")
+#define XML_CMD ((xmlChar *)"cmd")
+#define XML_LDM_INFO ((xmlChar *)"ldom_info")
+#define XML_LDM_NAME ((xmlChar *)"ldom_name")
+#define XML_RESPONSE ((xmlChar *)"response")
+#define XML_STATUS ((xmlChar *)"status")
+#define XML_RESP_MSG ((xmlChar *)"resp_msg")
+#define XML_BINDING ((xmlChar *)"binding")
+#define XML_FREE ((xmlChar *)"free")
+#define XML_PID ((xmlChar *)"pid")
+#define XML_VID ((xmlChar *)"vid")
+#define XML_STRAND_PERCENT ((xmlChar *)"strand_percent")
+#define XML_REAL_ADDR ((xmlChar *)"real_addr")
+#define XML_PHYS_ADDR ((xmlChar *)"phys_addr")
+#define XML_MODE ((xmlChar *)"mode")
+#define XML_CPUSET ((xmlChar *)"cpuset")
+#define XML_DEV_TYPE ((xmlChar *)"device_type")
+#define XML_PORT ((xmlChar *)"port")
+#define XML_SPCONFIG ((xmlChar *)"spconfig")
+#define XML_SPCONFIG_NAME ((xmlChar *)"spconfig_name")
+#define XML_SPCONFIG_STATUS ((xmlChar *)"spconfig_status")
+#define XML_SERVICE_DOMAIN ((xmlChar *)"service_domain")
+#define XML_PHYSIO_DEVICE ((xmlChar *)"physio_device")
+
+#define XML_CURRENT_STATUS ((xmlChar *)"current")
+#define XML_NEXT_STATUS ((xmlChar *)"next")
+
+#define XML_SUCCESS "success"
+#define XML_FAILURE "failure"
+
+/*
+ * XML node and attribute names
+ */
+#define CONSOLE_INSTANCE_NODE ((xmlChar *)"console_instance")
+#define CONSOLE_NODE ((xmlChar *)"console")
+#define CPU_NODE ((xmlChar *)"cpu")
+#define MAU_NODE ((xmlChar *)"mau")
+#define DEV_PATH_NODE ((xmlChar *)"dev_path")
+#define GROUP_NODE ((xmlChar *)"group")
+#define VCONS_PORT_NODE ((xmlChar *)"port")
+#define INSTANCE_NODE ((xmlChar *)"instance")
+#define LDOM_DATABASE_NODE ((xmlChar *)"ldom_database")
+#define LDOM_NAME_NODE ((xmlChar *)"ldom_name")
+#define LDOM_NODE ((xmlChar *)"ldom")
+#define MAC_ADDRESS_NODE ((xmlChar *)"mac_address")
+#define MAX_PORT_NODE ((xmlChar *)"max_port")
+#define MEMORY_NODE ((xmlChar *)"memory")
+#define MIN_PORT_NODE ((xmlChar *)"min_port")
+#define MTU_NODE ((xmlChar *)"mtu")
+#define NAME_NODE ((xmlChar *)"name")
+#define NUMBER_NODE ((xmlChar *)"number")
+#define PHYSIO_MINOR_NODE ((xmlChar *)"minor")
+#define VOLUME_NAME_NODE ((xmlChar *)"vol_name")
+#define VOLUME_OPTS_NODE ((xmlChar *)"vol_opts")
+#define BLOCKDEV_NODE ((xmlChar *)"block_dev")
+#define PHYSIO_NODE ((xmlChar *)"physio")
+#define SERVICE_NAME_NODE ((xmlChar *)"service_name")
+#define SERVER_INSTANCE_NODE ((xmlChar *)"server_instance")
+#define SERVER_NODE ((xmlChar *)"server")
+#define SHARING_NODE ((xmlChar *)"sharing")
+#define SIZE_NODE ((xmlChar *)"size")
+#define STATE_NODE ((xmlChar *)"state")
+#define VALUE_NODE ((xmlChar *)"value")
+#define VARIABLES_NODE ((xmlChar *)"variables")
+#define VAR_NODE ((xmlChar *)"var")
+#define VCC_INSTANCE_NODE ((xmlChar *)"vcc_instance")
+#define VCC_NODE ((xmlChar *)"vcc")
+#define DISK_INSTANCE_NODE ((xmlChar *)"disk_instance")
+#define DISK_NODE ((xmlChar *)"disk")
+#define VDISK_NAME_NODE ((xmlChar *)"vdisk_name")
+#define VDS_VOLUME_NODE ((xmlChar *)"vds_volume")
+#define VDS_VOLUMES_NODE ((xmlChar *)"vds_volumes")
+#define VDS_INSTANCE_NODE ((xmlChar *)"vds_instance")
+#define VDS_NODE ((xmlChar *)"vds")
+#define VNET_INSTANCE_NODE ((xmlChar *)"network_instance")
+#define VNET_NODE ((xmlChar *)"network")
+#define VNET_NAME_NODE ((xmlChar *)"vnet_name")
+#define VSW_INSTANCE_NODE ((xmlChar *)"vsw_instance")
+#define VSW_POLICIES_NODE ((xmlChar *)"policies")
+#define VSW_NODE ((xmlChar *)"vsw")
+#define IO_INSTANCE_NODE ((xmlChar *)"io_instance")
+#define IO_NODE ((xmlChar *)"io")
+#define IO_NAME_NODE ((xmlChar *)"iodevice")
+#define IO_BYPASS_NODE ((xmlChar *)"bypass_mode")
+#define VLDCC_NODE ((xmlChar *)"vldcc")
+#define TIMEOUT_NODE ((xmlChar *)"timeout")
+
+/*
+ * Protocol version supported.
+ */
+#define LDM_MAJOR_VER 1
+#define LDM_MINOR_VER 0
+
+/* per class version numbers */
+#define LDM_CLI_MAJOR_VER 2
+#define LDM_CLI_MINOR_VER 0
+
+#define LDM_CONTROL_MAJOR_VER 1
+#define LDM_CONTROL_MINOR_VER 0
+
+#define LDM_SUNMC_MAJOR_VER 1
+#define LDM_SUNMC_MINOR_VER 0
+
+enum {
+ LDM_INIT_REQ = 0x0,
+ LDM_INIT_ACK = 0x1,
+ LDM_INIT_NACK = 0x2,
+ LDM_ERROR = 0x3,
+ LDM_OP_REQ = 0x4,
+ LDM_OP_REPLY = 0x5
+};
+
+typedef struct {
+ uint32_t msg_type;
+ uint32_t payload_len;
+} ldm_hdr_t;
+
+enum {
+ LDM_CLASS_CLI = 0x1,
+ LDM_CLASS_CONTROL = 0x2,
+ LDM_CLASS_SUNMC = 0x3
+};
+
+typedef struct {
+ uint32_t client_class;
+ uint16_t major_vers;
+ uint16_t minor_vers;
+} ldm_init_req_t;
+
+typedef struct {
+ uint16_t minor_vers;
+} ldm_init_ack_t;
+
+typedef struct {
+ uint16_t major_vers;
+} ldm_init_nack_t;
+
+enum {
+ LDM_ERROR_UNKNOWN = 0x1,
+ LDM_ERROR_UNEXPECTED = 0x2,
+ LDM_ERROR_INVALID = 0x3
+};
+
+typedef struct {
+ uint32_t error_code;
+} ldm_error_t;
+
+typedef struct {
+ uint32_t rq_len;
+ uint32_t rq_id;
+ uint8_t rq_data[];
+} ldm_op_req_t;
+
+typedef struct {
+ uint32_t rp_len;
+ uint32_t rp_reqid;
+ uint8_t rp_data[];
+} ldm_op_reply_t;
+
+/*
+ * 0-3 are used by the ldm_protocol's initialization calls.
+ */
+enum {
+ LDM_CNTRL_PRI_REQ = 0x4,
+ LDM_CNTRL_PRI_REPLY = 0x5,
+ LDM_CNTRL_XML_REQ = 0x6,
+ LDM_CNTRL_XML_RESP = 0x7
+};
+
+/* used by malloc to allocate memory for an entire msg */
+typedef struct ldm_handshake_msg_s {
+ ldm_hdr_t hdr_msg;
+ ldm_init_req_t msg;
+} ldm_handshake_msg;
+
+typedef struct {
+ int len;
+ char data[];
+} xml_msg_t;
+
+#if defined(_BIG_ENDIAN)
+#define hton8(_x) ((uint8_t)(_x))
+#define hton16(_x) ((uint16_t)(_x))
+#define hton32(_x) ((uint32_t)(_x))
+#define hton64(_x) ((uint64_t)(_x))
+#define ntoh8(_x) ((uint8_t)(_x))
+#define ntoh16(_x) ((uint16_t)(_x))
+#define ntoh32(_x) ((uint32_t)(_x))
+#define ntoh64(_x) ((uint64_t)(_x))
+#else
+#define hton8(_x) ((uint8_t)(_x))
+#define hton16(_x) BSWAP_16((uint16_t)(_x))
+#define hton32(_x) BSWAP_32((uint32_t)(_x))
+#define hton64(_x) BSWAP_64((uint64_t)(_x))
+#define ntoh8(_x) ((uint8_t)(_x))
+#define ntoh16(_x) BSWAP_16((uint16_t)(_x))
+#define ntoh32(_x) BSWAP_32((uint32_t)(_x))
+#define ntoh64(_x) BSWAP_64((uint64_t)(_x))
+#endif
+
+xmlDocPtr send_xml_file_to_ldm(xmlDoc *xml_output);
+xmlDocPtr handle_resp(char *resp_buf);
+
+void close_ldm_connection(int sock);
+int get_free_memory(unsigned long *);
+int get_ldom_names(int *, ldominfo_t ***);
+int get_ldom_cpu_bindings(char *, cpuBindings_t **);
+int get_ldom_total_cpu(int *);
+int get_ldom_total_memory(unsigned long *);
+int ldm_create_pkt_buf(char **pkt_buf, char *xml_buf, int xml_buf_len);
+int open_ldm_connection(void);
+int send_ldom_active_mgmt(char *snmp_user, char *ldom_name, int ldom_state);
+char * send_ldom_create_domain(char *, xmlChar *);
+int send_ldom_lifecycle_action(char *, int);
+int send_ldom_set_memory(char *, unsigned long);
+int send_ldom_set_vcpu(char *, int);
+
+int get_all_ldominfo(char *snmp_user, int *all_ldom_cnt, ldominfo_t ***all_ldominfo_list);
+int get_crypto(char *snmp_user, char *ldom_name, int *crypto_cnt, crypto_t ***crypto_list);
+int get_envvars(char *snmp_user, char *ldom_name, int *envvars_cnt, envvars_t ***envvars_list);
+int get_iobus(char *snmp_user, char *ldom_name, int *iobus_cnt, iobus_t ***iobus_list);
+int get_ldominfo(char *ldom_name, int *num_cpu, int *mem_size, int *mem_unit, int *num_crypto, int *num_iobus, int * console, int state);
+int get_response(int sock, char **resp_buf);
+int get_rp(char *snmp_user, int resource, int rp_type, ulong_t *rp_qty, int *unit);
+int get_vcc(char *snmp_user, char *ldom_name, int *vcc_cnt, vcc_t ***vcc_list);
+int get_vcons(char *snmp_user, char *ldom_name, int *vcons_cnt, vcons_t ***vcons_list);
+int get_vconsvccrel(char *snmp_user, char *ldom_name, int *vconsvccrel_cnt, vconsvccrel_t ***vconsvccrel_list);
+int get_vcpu(char *snmp_user, char *ldom_name, int *vcpu_cnt, vcpu_t ***vcpu_list);
+int get_vdisk(char *snmp_user, char *ldom_name, int *vdisk_cnt, vdisk_t ***vdisk_list);
+int get_vds(char *snmp_user, char *ldom_name, int *vds_cnt, vds_t ***vds_list);
+int get_vdsdev(char *snmp_user, char *ldom_name, int *vdsdev_cnt, vdsdev_t ***vdsdev_list);
+int get_vmem(char *snmp_user, char *ldom_name, int *vmem_cnt, vmem_data_t ***vmem_list);
+int get_vmem_physbind(char *snmp_user, char *ldom_name, int *vmem_physbind_cnt, vmem_physbind_t ***vmem_physbind_list);
+int get_vnet(char *snmp_user, char *ldom_name, int *vnet_cnt, vnet_t ***vnet_list);
+int get_vsw(char *snmp_user, char *ldom_name, int *vsw_cnt, vsw_t ***vsw_list);
+
+xmlNodePtr xml_get_next_ele_node(xmlNodePtr node);
+xmlNodePtr xml_find_subnode(xmlNodePtr node, const xmlChar *name);
+int create_pkt_buf(char **pkt_buf, char *xml_buf, int xml_buf_len,
+ int msg_type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WITH_LDOMS */
+#endif /* __VIR_LDOMS_INTFC_H__ */
diff --git a/src/ldoms_intfc.c b/src/ldoms_intfc.c
new file mode 100644
--- /dev/null
+++ b/src/ldoms_intfc.c
@@ -0,0 +1,1825 @@
+/*
+ * ldoms_intfc.c: Interface code to the LDoms Manager (LDM)
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ */
+
+#ifdef WITH_LDOMS
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <netdb.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <libintl.h>
+#include <time.h>
+
+
+#include "libvirt/libvirt.h"
+#include "internal.h"
+#include "ldoms_internal.h"
+#include "ldoms_common.h"
+#include "ldoms_xml_parse.h"
+#include "ldoms_intfc.h"
+#include "xml.h"
+
+
+/* Domain state info
+ * LDom State enumerations
+ * 1 = active LDOM_STATE_ACTIVE
+ * 2 = stopping LDOM_STATE_STOPPING
+ * 3 = inactive LDOM_STATE_INACTIVE
+ * 4 = binding LDOM_STATE_BINDING
+ * 5 = unbinding LDOM_STATE_UNBINDING
+ * 6 = bound LDOM_STATE_BOUND
+ * 7 = starting LDOM_STATE_STARTING
+ *
+ * libvirt LDom State enums
+ * typedef enum {
+ * VIR_DOMAIN_NOSTATE = 0, no state
+ * VIR_DOMAIN_RUNNING = 1, the domain is running
+ * VIR_DOMAIN_BLOCKED = 2, the domain is blocked on resource
+ * VIR_DOMAIN_PAUSED = 3, the domain is paused by user
+ * VIR_DOMAIN_SHUTDOWN= 4, the domain is being shut down
+ * VIR_DOMAIN_SHUTOFF = 5, the domain is shut off
+ * VIR_DOMAIN_CRASHED = 6 the domain is crashed
+ * } virDomainState;
+ */
+
+/* Global vars for debug statement */
+extern int ldoms_debug;
+extern int ldoms_detailed_debug;
+
+/*
+ * open_ldm_connection
+ *
+ * This is the function that opens a client socket connection to the LDOM Manager and
+ * performs the initial handshake protocol with the LDOM Manager.
+ *
+ * Returns:
+ * socket descriptor if the operation is successful
+ * -1 if it fails
+ *
+ * NOTE: This routine was copied from the example code provided by the LDOM Manager developer.
+ * The LDOM Manager handshake protocol is defined in the ldm_protocol.h file
+ * in the LDOM Manager source code. Also see the create_connection() routine in ldm.c
+ * from the LDOM Manager source code.
+ */
+int
+open_ldm_connection(void)
+{
+ struct sockaddr_in myaddr;
+ struct stat statbuf;
+ ldm_hdr_t *hdr, hdr_buf;
+ ldm_init_req_t *init_req;
+ ldm_handshake_msg *buf;
+ int error, sock;
+ uint16_t port;
+
+ int client_class = LDM_CLASS_CONTROL;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection(ENTER)\n");
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..can not create socket\n");
+ return (-1);
+ }
+
+ port = DEFAULT_PORT;
+
+ myaddr.sin_family = AF_INET;
+ myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ myaddr.sin_port = htons(port);
+ error = connect(sock, (struct sockaddr *)(&myaddr), sizeof (struct sockaddr_in));
+
+ if (error == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..socket connect failed: port=%d\n",port);
+ return (-1);
+ }
+
+ if ((buf = malloc(sizeof(ldm_handshake_msg))) == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..malloc ldm_handshake_msg failed\n");
+ return(-1);
+ }
+
+ /* Header msg is always required to LDM */
+ hdr = (ldm_hdr_t *)buf;
+ hdr->msg_type = hton32(LDM_INIT_REQ);
+ hdr->payload_len = sizeof (ldm_init_req_t);
+
+ /* Specific request to LDM */
+ init_req = &buf->msg;
+ init_req->client_class = hton32(client_class);
+ init_req->major_vers = hton16(LDM_CONTROL_MAJOR_VER);
+ init_req->minor_vers = hton16(LDM_CONTROL_MINOR_VER);
+
+ /* Send the request to the LDM */
+ error = send(sock, buf, sizeof(ldm_handshake_msg), 0);
+ if (error == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..socket send with LDM_INIT_REQ failed\n");
+ return(-1);
+ }
+
+ free(buf);
+
+ /*
+ * Get the header part of the response from the LDM. This
+ * will let us know how big the message part is.
+ */
+ error = recv(sock, &hdr_buf, sizeof (ldm_hdr_t), MSG_WAITALL);
+ if (error == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..socket recv failed\n");
+ return(-1);
+ }
+
+ hdr_buf.msg_type = ntoh32(hdr_buf.msg_type);
+ hdr_buf.payload_len = ntoh32(hdr_buf.payload_len);
+
+ /* See what the LDM responded with for the handshake request */
+ switch (hdr_buf.msg_type) {
+ case LDM_INIT_ACK: {
+ ldm_init_ack_t ack;
+
+ /* Get the rest of the response */
+ error = recv(sock, &ack, sizeof (ack), MSG_WAITALL);
+ if (error == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..LDM_INIT_ACK recv failed\n");
+ return(-1);
+ }
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: open_ldm_connection..LDM_INIT_ACK received, Minor sent=%d, Minor rcvd=%d\n",LDM_CONTROL_MINOR_VER,ack.minor_vers);
+ break;
+ }
+
+ case LDM_INIT_NACK: {
+ ldm_init_nack_t nack;
+
+ error = recv(sock, &nack, sizeof (nack), MSG_WAITALL);
+ if (error == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..LDM_INIT_NACK recv failed\n");
+ return(-1);
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..LDM_INIT_NACK received, Major Version mismatch. Mjr sent=%d, Mjr rcvd=%d\n",LDM_CONTROL_MAJOR_VER,nack.major_vers);
+ return(-1);
+ }
+
+ case LDM_ERROR: {
+ ldm_error_t err;
+
+ error = recv(sock, &err, sizeof (err), MSG_WAITALL);
+ if (error == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..LDM_ERROR recv failed\n");
+ return(-1);
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..LDM_ERROR: Protocol error=%d\n",err.error_code);
+
+ return(-1);
+ break;
+ }
+
+ default:
+ if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection: Unknown response type=%d\n",hdr_buf.msg_type);
+ return(-1);
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection(ENTER)\n");
+
+ return (sock);
+}
+
+/*
+ * close_ldm_connection
+ *
+ * This function will close the socket connection to the LDM
+ *
+ * Input:
+ * sock - a socket descriptor to close
+ */
+void
+close_ldm_connection(int sock)
+{
+ if (ldoms_debug) dprt("LDOMS_DEBUG: close_ldm_connection(ENTER)..trying to close LDM socket=%d\n", sock);
+ (void)close(sock);
+ if (ldoms_debug) dprt("LDOMS_DEBUG: close_ldm_connection(EXIT)\n");
+}
+
+
+/*
+ * get_response
+ *
+ * This function receives messages from the LDM socket connection and puts them
+ * into the message buffer.
+ *
+ * Input:
+ * sock - socket descriptor to receive messages
+ *
+ * Output:
+ * resp_buf - pointer to the response buffer that contains the messages
+ * from the socket connection. This memory must be freed by the caller.
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ * NOTE: This routine was copied from the example code provided by the LDOM Manager developer.
+ */
+int
+get_response(int sock, char **resp_buf)
+{
+ ldm_hdr_t hdr;
+ char *buf;
+ int status, resp_len, text_len, cc;
+ int i;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_response(ENTER)\n");
+
+ /* Receive the Header of the response */
+ status = recv(sock, &hdr, sizeof (ldm_hdr_t), MSG_WAITALL);
+ if (status <= 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_response..recv failed for rsp header\n");
+ /* error or LDom manager exited */
+ return(-1);
+ }
+
+ hdr.msg_type = ntoh32(hdr.msg_type);
+
+ if (hdr.msg_type != LDM_CNTRL_XML_RESP) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_response..Unexpected response message type=%d\n",hdr.msg_type);
+ return(-1);
+ }
+
+ hdr.payload_len = ntoh32(hdr.payload_len);
+
+ *resp_buf = malloc(hdr.payload_len);
+
+ if (*resp_buf == NULL)
+ return(-1);
+
+ /* receive the actual response body from LDM */
+ status = recv(sock, *resp_buf, hdr.payload_len, MSG_WAITALL);
+ if (status == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_response..recv failed for rsp body\n");
+ free(resp_buf);
+ return(-1);
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_response(EXIT)..received %d bytes for rsp body\n", status);
+
+ return (0);
+} /* get_response() */
+
+/*
+ * handle_resp
+ *
+ * This function converts the message buffer (received from the socket connection)
+ * into an xml document.
+ *
+ * Input:
+ * resp_buf - pointer to the message buffer received from the socket connection
+ *
+ * Returns:
+ * xml doc pointer if the operation is successful
+ * NULL if the operation fails
+ *
+ * NOTE: This routine was copied from the example code provided by the LDOM Manager developer.
+ */
+xmlDocPtr
+handle_resp(char *resp_buf)
+{
+ xmlDocPtr xml_output;
+ ldm_op_req_t *req;
+ xml_msg_t *xml_msg;
+ char * dptr;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: handle_resp(ENTER)\n");
+
+ req = (ldm_op_req_t *)resp_buf;
+ xml_msg = (xml_msg_t *)req->rq_data;
+
+
+ xml_output = xmlParseMemory((const char *)req->rq_data, req->rq_len);
+
+ if (xml_output == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: handle_resp.. xml output is NULL\n");
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: handle_resp(EXIT)\n");
+
+ return (xml_output);
+}
+
+/*
+ * send_xml_file_to_ldm
+ *
+ * This function sends an XML request to LDM and then receives the XML
+ * response. It packages the XML response into an XML document so other
+ * code can search through it.
+ *
+ * Input:
+ * doc - xml doc to send to the LDOM Manager
+ *
+ * Returns:
+ * xml doc pointer of the response xml file received from the LDOM Manager
+ * if the operation is successful.
+ * NULL if the operation fails
+ *
+ */
+xmlDocPtr
+send_xml_file_to_ldm(xmlDoc *doc)
+{
+ char *pkt_buf;
+ char *resp_buf;
+ char *xml_buf;
+ int status;
+ int pkt_buf_len;
+ int xml_buf_len;
+ int ret;
+ int sock;
+ xmlDoc *doc_from_ldm;
+
+ /* connect to the ldom manager */
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_xml_file_to_ldm(ENTER)\n");
+ sock = open_ldm_connection();
+
+ if (sock == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_xml_file_to_ldm.. error in opening socket connection\n");
+ return(NULL);
+ }
+
+ (void) xmlDocDumpMemory(doc, (xmlChar **)&xml_buf, &xml_buf_len);
+
+ pkt_buf_len = ldm_create_pkt_buf(&pkt_buf, xml_buf, xml_buf_len);
+
+ status = send(sock, pkt_buf, pkt_buf_len, 0);
+ if (status == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_xml_file_to_ldm.. error in send\n");
+ close_ldm_connection(sock);
+ return(NULL);
+ }
+
+ free(xml_buf);
+ free(pkt_buf);
+
+ if (get_response(sock, &resp_buf) == 0)
+ doc_from_ldm = handle_resp(resp_buf);
+ else {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_xml_file_to_ldm.. error in get_response\n");
+ close_ldm_connection(sock);
+ return(NULL);
+ }
+
+ free(resp_buf);
+
+ /* close the socket connection */
+ close_ldm_connection(sock);
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_xml_file_to_ldm(EXIT)\n");
+
+ return (doc_from_ldm);
+} /* send_xml_file_to_ldm() */
+
+/*
+ * ldm_create_pkt_buf
+ *
+ * This function creates a ldom operation request message buffer with an XML
+ * character buffer array. This functions sets the appropriate protocol headers
+ * for the protocol handshake with the LDOM Manager.
+ *
+ * Input:
+ * xml_buf - pointer to the xml character buffer
+ * xml_buf_len - length of the xml character buffer
+ *
+ * Output:
+ * pkt_buf - pointer to the message buffer to send to the socket connection
+ *
+ * Returns:
+ * buffer length for the message buffer
+ *
+ * NOTE: This routine was copied from the example code provided by the LDOM Manager developer.
+ * Also see the create_pkt_buf() routine in xml_common.c from the LDOM Manager source code.
+ */
+int
+ldm_create_pkt_buf(char **pkt_buf, char *xml_buf, int xml_buf_len)
+{
+ char *temp_buf;
+ int i;
+ int pkt_buf_len;
+ ldm_hdr_t *hdr;
+ ldm_op_req_t *req;
+ xml_msg_t *xml_msg;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: create_pkt_buf(ENTER)\n");
+
+ pkt_buf_len = sizeof (ldm_hdr_t) + sizeof (ldm_op_req_t) + xml_buf_len;
+
+ *pkt_buf = malloc(pkt_buf_len);
+
+ /* set LDM protocol headers */
+ hdr = (ldm_hdr_t *)*pkt_buf;
+ hdr->msg_type = hton32(LDM_CNTRL_XML_REQ);
+ hdr->payload_len = hton32(sizeof (ldm_op_req_t) + xml_buf_len);
+
+ req = (ldm_op_req_t *)(*pkt_buf + sizeof (ldm_hdr_t));
+ req->rq_len = hton32(xml_buf_len);
+ req->rq_id = 1;
+
+ memcpy(req->rq_data, xml_buf, xml_buf_len);
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: create_pkt_buf(EXIT)\n");
+
+ return (pkt_buf_len);
+
+} /* ldm_create_pkt_buf() */
+
+
+/*
+ * get_ldominfo
+ *
+ * This function gets the ldom info such as the number of virtial cpu, memory and
+ * its unit, crypto, iobus and console port for the given ldom by invoking routines
+ * to create and send the "list-constraints" and "list-bindings" XML request to the
+ * LDOM Manager and parse the response.
+ *
+ * XML output from the LDOM Manager.
+ *
+ * Input:
+ * ldom_name - name of the ldom to retrieve the ldom info
+ * state - State of the ldom
+ *
+ * Output (pointers are used to pass information from this function to the caller):
+ * num_cpu - pointer to the number of virtual cpu
+ * mem_size - pointer to the virtual memory size
+ * mem_unit - pointer to the virtual memory unit
+ * num_crypto - pointer to the number of crypto unit
+ * num_iobus - pointer to the number of io bus
+ * console - pointer to the console port
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ */
+int
+get_ldominfo(char *ldom_name, int *num_cpu, int *mem_size, int *mem_unit,
+ int *num_crypto, int *num_iobus, int *console, int state)
+{
+ xmlDocPtr xml_output;
+ xmlDocPtr xml_received;
+ xmlChar *action = XML_LIST_CONST;
+ xmlChar *bindAction = XML_LIST_BIND;
+ int ret;
+
+ int num_cpu_from_xml = 0;
+ int mem_size_from_xml = 0;
+ int mem_unit_from_xml = 0;
+ int num_crypto_from_xml = 0;
+ int num_iobus_from_xml = 0;
+ int console_from_xml = 0;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo(ENTER) ldom_name=%s\n", ldom_name);
+
+ *num_cpu = 0;
+ *mem_size = 0;
+ *mem_unit = 0;
+ *num_crypto = 0;
+ *num_iobus = 0;
+ *console = 0;
+
+ /*
+ * The following "list-constraints" XML request will be created and sent to the LDOM Manager
+ * NOTE: list-constraints will not get the Console port. We have to
+ * use list-bindings for that.
+ *
+ * if the input ldom name is 'primary':
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>list-constraints</action>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>primary</ldom_name>
+ * </ldom_info>
+ * </ldom>
+ * </data>
+ * </cmd>
+ * </LDM_interface>
+ */
+ xml_output = create_xml_file_4_ldom_action(ldom_name, action);
+ if (xml_output == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo.. failed to create xml file for ldom_name=%s action=%s\n",
+ ldom_name, action);
+ return (-1);
+ }
+
+ /* send XML file to the ldom manager */
+ xml_received = send_xml_file_to_ldm(xml_output);
+ if (xml_received == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo.. failed to send xml file to ldm and receive xml back\n");
+ xmlFreeDoc(xml_output);
+ return (-1);
+ }
+
+ /*
+ * Example of the xml file received from the LDOM Manager:
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>list-constraints</action>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>primary</ldom_name>
+ * </ldom_info>
+ * <cpu>
+ * <number>4</number>
+ * </cpu>
+ * <mau>
+ * <number>1</number>
+ * </mau>
+ * <memory>
+ * <size>1G</size>
+ * </memory>
+ * .....
+ */
+ /* parse the received XML file to get the ldom info */
+
+ /*
+ * <response><status> will be failure if the ldom is not active or bound.
+ * then, use zero for num of cpu and mem size
+ */
+ ret = parse_xml_get_ldominfo(xml_received, &num_cpu_from_xml, &mem_size_from_xml,
+ &mem_unit_from_xml, &num_crypto_from_xml, &num_iobus_from_xml);
+ if (ret == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo.. failed to parse xml file\n");
+ return (-1);
+ }
+
+ /* Update the return parms */
+ *num_cpu = num_cpu_from_xml;
+ *mem_size = mem_size_from_xml;
+ *mem_unit = mem_unit_from_xml;
+ *num_crypto = num_crypto_from_xml;
+ *num_iobus = num_iobus_from_xml;
+
+ /*
+ * Now we have to get the console port for each LDom. This is done by
+ * sending a 'list-bindings' XML command. So this means we can only
+ * send this request for domains that are bound or active. You cannot
+ * do a list-bindings on an inactive domain. If the domain is inactive,
+ * then the console port is set to 0.
+ *
+ * Example:
+ * If the input ldom name is 'primary', the XML request is:
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>list-bindings</action>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>primary</ldom_name>
+ * </ldom_info>
+ * </ldom>
+ * </data>
+ * </cmd>
+ * </LDM_interface>
+ */
+
+ /* Domain state is inactive (3), so list-bindings is invalid */
+ if (state == LDOM_STATE_INACTIVE)
+ return (0);
+
+ xml_output = create_xml_file_4_ldom_action(ldom_name, bindAction);
+ if (xml_output == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo.. failed to create xml file for ldom_name=%s action=%s\n",
+ ldom_name, action);
+ return (-1);
+ }
+
+ /* send XML file to the ldom manager */
+ xml_received = send_xml_file_to_ldm(xml_output);
+ if (xml_received == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo.. failed to send xml file to ldm and receive xml back for Ldom %s, action %s\n", ldom_name, action);
+ xmlFreeDoc(xml_output);
+ return (-1);
+ }
+
+ /*
+ * Example of the xml file received from the LDOM Manager:
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>list-constraints</action>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>ldom-126</ldom_name>
+ * <mac_address>00:14:4f:f9:1a:7d</mac_address>
+ * </ldom_info>
+ * .....
+ * <console>
+ * <service_name>primary-vcc0</service_name>
+ * <port>5005</port>
+ * </console>
+ * .....
+ * </ldom>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </data>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </cmd>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </LDM_interface>
+ */
+
+ /* parse the received XML file to get the ldom info */
+
+ ret = parse_xml_get_console(xml_received, &console_from_xml);
+ if (ret == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo() failed to parse xml file for action %s\n", bindAction);
+ return (-1);
+ }
+ /* Update the return parms */
+ *console = console_from_xml;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo(EXIT)\n");
+
+ return(0);
+}
+
+/*
+* get_ldom_names
+*
+* This function creates a list of all ldoms with the ldom name and state data
+* by invoking routines to create and send the "list-domain" XML request
+* to the LDOM Manager and parse the response XML output from the LDOM Manager.
+*
+* For each LDom returned from the list-domain action, get_ldominfo() is called
+* to get the specific LDom info.
+*
+* Input:
+*
+* Output (pointers are used to pass information from this function to the caller):
+* ldom_cnt - pointer to the number of ldoms in the ldom info list
+* ldominfo_list - pointer to the list of pointers to the ldom info array
+*
+* Returns:
+* 0 if the operation is successful
+* -1 if the operation fails
+*
+* NOTE: The following pictorial description explains the data structure used in
+* this function to pass the ldom count and the list of pointers to the ldom info array.
+* The definition of the data structures is implemented in the ldm_xml_parse.h file.
+* Most get_<data> routines in this file is using the similar data structures
+* to pass the data.
+*
+* +-------------+
+* | num_ldoms | <--- *ldom_cnt = pointer to the integer that has the value of
+* +-------------+ the number of ldoms
+*
+* +-------------+
+* | ldom_list + <--- ***ldominfo_list = pointer to the list of pointers to
+* +-------------+ the ldom info array of type ldominfo_t
+* of which is defined in ldm_xml_parse.h file
+* ldom_list[0]
+* |
+* | type ldominfo_t
+* | +-------------+---------------+------------+
+* |---> | ldom name | ldom state | ...... |
+* +------------------------------------------+
+*
+* ldom_list[1]
+* |
+* | type ldominfo_t
+* | +-------------+---------------+------------+
+* |---> | ldom name | ldom state | ...... |
+* +------------------------------------------+
+*
+*/
+int
+get_ldom_names(int *ldom_cnt, ldominfo_t ***ldominfolist)
+{
+ ldominfo_t **ldom_list = NULL;
+ xmlDocPtr xml_to_send;
+ xmlDocPtr xml_received;
+ xmlNodePtr root_node = NULL;
+ xmlNodePtr cmd_node = NULL;
+ xmlNodePtr data_node = NULL;
+ xmlNodePtr ldom_node = NULL;
+ xmlNodePtr name_node = NULL;
+ xmlNodePtr subnode = NULL;
+ xmlChar *ldom_name = NULL;
+ xmlChar *action = XML_LIST;
+
+ int num_ldoms = 0;
+ int i = 0, idx = 0;
+ int nameLen;
+ int ldomCpus, ldomMem, memUnit, ldomCrypto, ldomIO, ldomConsole;
+ char ldomName[NAME_SIZE];
+ char multChr;
+
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names(ENTER) i=%d\n",i);
+
+ /*
+ * This function can be called many times for a single Virt Mgr
+ * operation. In order to not have to devise a grand scheme to
+ * determine when certain LDom info is valid or not, we will
+ * always free the existing structure and then generate new
+ * ones with current data from LDM. This also allows us to
+ * have the latest data from LDM.
+ */
+ if (*ldominfolist != NULL ) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names.. freeing ldominfolist\n");
+ for (i=0; i < *ldom_cnt; i++) {
+ free((*ldominfolist)[i]);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names.. freed *ldominfolist[%d]\n",i);
+ }
+ free(*ldominfolist);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names.. freed *ldominfolist\n");
+ }
+
+ /* Initialize return parameters */
+ *ldom_cnt = 0;
+ *ldominfolist = NULL;
+
+ /*
+ * The following "list-domain" XML request will be created and sent to the LDOM Manager:
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>list-domain</action>
+ * <data version="2.0">
+ * </data>
+ * </cmd>
+ * </LDM_interface>
+ */
+ xml_to_send = create_xml_file_4_ldom_action(NULL, action);
+ if (xml_to_send == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. can not create list xml file\n");
+ return (-1);
+ }
+
+ xml_received = send_xml_file_to_ldm(xml_to_send);
+ if (xml_received == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. failed to send xml file to ldm and receive xml response\n");
+ xmlFreeDoc(xml_to_send);
+ return (-1);
+ }
+
+ /*
+ * Example of the xml file received from the LDOM Manager:
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>list-domain</action>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>primary</ldom_name>
+ * <state>active</state>
+ * </ldom_info>
+ * </ldom>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </data>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </cmd>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </LDM_interface>
+ */
+
+ /* Get the total # of LDoms first */
+ if (parse_xml_get_ldom_cnt(xml_received, &num_ldoms) == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. failed to parse xml file for ldom cnt=%s\n", xml_received);
+ xmlFreeDoc(xml_to_send);
+ xmlFreeDoc(xml_received);
+ return (-1);
+ }
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names.. number of ldoms=%d \n", num_ldoms);
+
+ /* Allocate the memory to hold the info for each LDom */
+ if (num_ldoms > 0)
+ ldom_list = calloc(num_ldoms, sizeof(ldominfo_t *));
+
+ if (ldom_list == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. can't alloc memory for ldom_list\n");
+ xmlFreeDoc(xml_to_send);
+ xmlFreeDoc(xml_received);
+ return (-1);
+ }
+
+ /* Make sure mandantory XML tags are present before getting LDom data */
+ root_node = xmlDocGetRootElement(xml_received);
+ if (root_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. XML file does not have root node\n");
+ free(ldom_list);
+ xmlFreeDoc(xml_to_send);
+ xmlFreeDoc(xml_received);
+ return (-1);
+ }
+ cmd_node = xml_find_subnode(root_node, XML_CMD);
+ if (cmd_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. XML file does not have <cmd> tag\n");
+ free(ldom_list);
+ xmlFreeDoc(xml_to_send);
+ xmlFreeDoc(xml_received);
+ return (-1);
+ }
+
+ data_node = xml_find_subnode(cmd_node, XML_DATA);
+ if (data_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. XML file does not have <data> tag\n");
+ free(ldom_list);
+ xmlFreeDoc(xml_to_send);
+ xmlFreeDoc(xml_received);
+ return (-1);
+ }
+
+ /*
+ * The response XML has data for all LDoms and their state. As we step thru
+ * the response for each LDom, we have to get more detailed info for the LDom,
+ * thus will send other XML requests for this data.
+ */
+ while (1) {
+
+ /* get the ldom node within the <data> tag */
+ ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+
+
+ /* Need a <ldom> tag */
+ if (ldom_node != NULL) {
+ subnode = ldom_node->xmlChildrenNode;
+
+ while (subnode != NULL) {
+ /* Skip tags that are not element tags (tags with no data) */
+ if (subnode->type != XML_ELEMENT_NODE) {
+ subnode = subnode->next;
+ continue;
+ }
+
+ /* Look for <ldom_info> tag */
+ if (xmlStrcmp(subnode->name, (const xmlChar *)XML_LDM_INFO) == 0) {
+ /* Need a <ldom_name> tag */
+ name_node = xml_find_subnode(subnode, XML_LDM_NAME);
+
+ /* We did not find a <ldom_name> tag. No work can be done without this */
+ if (name_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. XML file does not have <ldom_name> tag\n");
+ xmlFreeDoc(xml_to_send);
+ xmlFreeDoc(xml_received);
+ /* Should free the ldominto_t and ldominfo_list memory also, but this should NEVER happen */
+ return (-1);
+ }
+
+ /* Error checking needed here on ldom_name and ldom_list[idx] */
+ if ((ldom_name = xmlNodeGetContent(name_node)) == NULL) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names..xmlNodeGetContent() is NULL\n");
+ subnode = subnode->next;
+ continue;
+ }
+
+ if ((ldom_list[idx] = malloc(sizeof(ldominfo_t))) == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names..malloc() failed for ldom_list[idx]\n");
+ subnode = subnode->next;
+ xmlFree(ldom_name);
+ continue;
+ }
+
+ /* Save the LDom name and state */
+ strlcpy(ldom_list[idx]->ldomName, (char *)ldom_name, sizeof (ldom_list[idx]->ldomName));
+ ldom_list[idx]->ldomState = parse_xml_get_ldom_state(subnode);
+ xmlFree(ldom_name);
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names..ldom name:state=%s:%d; ldom_list[%d]=%u\n",
+ ldom_list[idx]->ldomName, ldom_list[idx]->ldomState,idx,ldom_list[idx]);
+
+ /* Now we need to get some specific data about the domain */
+ if (get_ldominfo(ldom_list[idx]->ldomName, &ldomCpus,
+ &ldomMem, &memUnit, &ldomCrypto, &ldomIO,
+ &ldomConsole, ldom_list[idx]->ldomState) >= 0)
+ {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names..get_ldominfo() cpus=%d, mem=%d, unit=%d, mau=%d, io=%d, console=%d\n",
+ ldomCpus, ldomMem, memUnit, ldomCrypto, ldomIO, ldomConsole);
+
+ /* The VMM GUI displays the memory in KB, so we need to convert to KB */
+ switch (memUnit) {
+ case LDOMMEMUNIT_KILOBYTES: break; /* KB already */
+ case LDOMMEMUNIT_MEGABYTES: ldomMem *= 1024; break; /* MB */
+ case LDOMMEMUNIT_GIGABYTES: ldomMem *= (1024 * 1024); break;/* GB */
+ case LDOMMEMUNIT_BYTES: ldomMem /= 1024; break; /* Bytes */
+ }
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names..get_ldominfo() mem=%d\n",ldomMem);
+
+ /* Now put the LDom into into the current list */
+ ldom_list[idx]->ldomNumVCpu = ldomCpus;
+ ldom_list[idx]->ldomMemSize = ldomMem;
+ ldom_list[idx]->ldomMemUnit = memUnit;
+ ldom_list[idx]->ldomNumCrypto = ldomCrypto;
+ ldom_list[idx]->ldomNumIOBus = ldomIO;
+ ldom_list[idx]->ldomConsole = ldomConsole;
+
+ /* Create the UUID for this domain/index. We want to keep the
+ * UUID constant, no matter how many domains are addeded or
+ * or deleted, so we will use the integer values for each
+ * char in the domain name in the calculation.
+ */
+ strcpy(ldomName, ldom_list[idx]->ldomName);
+ nameLen = strlen(ldom_list[idx]->ldomName);
+ for (i = 0 ; i < VIR_UUID_BUFLEN ; i++) {
+ if (i < nameLen)
+ multChr = ldomName[i];
+
+ ldom_list[idx]->uuid[i] = ((i+1) * (76 + multChr))%255;
+ }
+ }
+ else {
+ /* Now put the LDom into into the current list */
+ ldom_list[idx]->ldomNumVCpu = 0;;
+ ldom_list[idx]->ldomMemSize = 0;
+ ldom_list[idx]->ldomMemUnit = 4;
+ ldom_list[idx]->ldomNumCrypto = 0;
+ ldom_list[idx]->ldomNumIOBus = 0;
+ ldom_list[idx]->ldomConsole = 0;
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names() get_ldominfo() failed\n");
+ strcpy(ldomName, ldom_list[idx]->ldomName);
+ nameLen = strlen(ldom_list[idx]->ldomName);
+ for (i = 0 ; i < VIR_UUID_BUFLEN ; i++) {
+ if (i < nameLen)
+ multChr = ldomName[i];
+
+ ldom_list[idx]->uuid[i] = ((i+1) * (76 + multChr))%255;
+ }
+ }
+
+ idx++;
+ subnode = subnode->next;
+ continue;
+ }
+ subnode = subnode->next;
+ }
+ }
+
+ /*
+ * xml response for list-domain has <data> tags for each ldom info
+ * so, get the next data section
+ */
+ data_node = xml_get_next_ele_node(data_node);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names..looking for next <data> node\n");
+
+ if (data_node == NULL)
+ break;
+ }
+
+ *ldom_cnt = num_ldoms;
+ *ldominfolist = ldom_list;
+ for (i=0; i<*ldom_cnt; i++)
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names: ldom_list[%d]=%d\n",i,ldom_list[i]);
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names: ldominfolist=%u\n",ldominfolist);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names: *ldominfolist=%u\n",*ldominfolist);
+ for (i=0; i<*ldom_cnt; i++)
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names: (*ldominfolist)[%d]=%u\n",i,(*ldominfolist)[i]);
+
+ xmlFreeDoc(xml_to_send);
+ xmlFreeDoc(xml_received);
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names(EXIT) ldom_cnt=%d\n",*ldom_cnt);
+
+ return (0);
+} /* get_ldom_names() */
+
+/*
+ * send_ldom_set_vcpu
+ *
+ * This function sends an LDom XML xxxxxx request to the LDM to change the
+ * number of virtual cpus for the input domain.
+ *
+ * Input:
+ * ldom_name - name of the ldom to start or stop
+ * nvcpus - The new number of virtual cpus for the domain
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ */
+int
+send_ldom_set_vcpu(char *ldom_name, int nvcpus)
+{
+ xmlDocPtr xml_output;
+ xmlDocPtr xml_received;
+ xmlChar *action;
+ int ret;
+ xmlNodePtr root_node = NULL;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_vcpu(ENTER): ldom_name=%s, nvcpus=%d\n", ldom_name, nvcpus);
+
+ /* create XML file to send request to the ldom manager */
+ xml_output = create_xml_file_4_set_vcpu(ldom_name, nvcpus);
+ if (xml_output == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_vcpu.. failed to create xml file for set vcpus\n");
+ return (-1);
+ }
+
+ /* send XML file to the LDM */
+ xml_received = send_xml_file_to_ldm(xml_output);
+ if (xml_received == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_vcpu.. failed to send xml file to ldm and receive xml back\n");
+ xmlFreeDoc(xml_output);
+ return (-1);
+ }
+
+ /* check the response status */
+ root_node = xmlDocGetRootElement(xml_received);
+ if (root_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_vcpu.. XML file does not have root node\n");
+ xmlFreeDoc(xml_output);
+ xmlFreeDoc(xml_received);
+ return(-1);
+ }
+
+ if (parse_xml_get_response_status(root_node) == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_vcpu.. failure response from received xml\n");
+ xmlFreeDoc(xml_output);
+ xmlFreeDoc(xml_received);
+ return(-1);
+ }
+
+ /* cleanup */
+ xmlFreeDoc(xml_output);
+ xmlFreeDoc(xml_received);
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_vcpu(EXIT)\n");
+ return(0);
+}
+
+/*
+ * send_ldom_set_memory
+ *
+ * This function sends an LDom XML set-memory request to the LDM to change the
+ * virtual memory for the input domain. The value of memory is in KB.
+ *
+ * Input:
+ * ldom_name - name of the ldom to change the memory
+ * memory - The new memory for the domain
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ */
+int
+send_ldom_set_memory(char *ldom_name, unsigned long memory)
+{
+ xmlDocPtr xml_output;
+ xmlDocPtr xml_received;
+ xmlChar *action;
+ int ret;
+ xmlNodePtr root_node = NULL;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_memory(ENTER): ldom_name=%s, memory=%lu\n", ldom_name, memory);
+
+ /* create XML file to send request to the ldom manager */
+ xml_output = create_xml_file_4_set_memory(ldom_name, memory);
+ if (xml_output == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_memory.. failed to create xml file for set memory\n");
+ return (-1);
+ }
+
+ /* send XML file to the LDM */
+ xml_received = send_xml_file_to_ldm(xml_output);
+ if (xml_received == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_memory.. failed to send xml file to ldm and receive xml back\n");
+ xmlFreeDoc(xml_output);
+ return (-1);
+ }
+
+ /* check the response status */
+ root_node = xmlDocGetRootElement(xml_received);
+ if (root_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_memory.. XML file does not have root node\n");
+ xmlFreeDoc(xml_output);
+ xmlFreeDoc(xml_received);
+ return(-1);
+ }
+
+ if (parse_xml_get_response_status(root_node) == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_memory.. failure response from received xml\n");
+ xmlFreeDoc(xml_output);
+ xmlFreeDoc(xml_received);
+ return(-1);
+ }
+
+ /* cleanup */
+ xmlFreeDoc(xml_output);
+ xmlFreeDoc(xml_received);
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_memory(EXIT)\n");
+ return(0);
+}
+
+/*
+ * send_ldom_create_domain
+ *
+ * This function sends an LDom lifecycle action to the LDM to create a
+ * domain. The new domain will be left in either the inactive or bound
+ * state. The domain is created from the definition of an input XML file.
+ * The structure of the XML file is that of 'ldm list-constraints -x <ldom>'
+ *
+ * Input:
+ * xml - A char buffer of the input xml file (This is not an xmlDocPtr yet)
+ * action - The Lifecycle action to perform after domain creation
+ *
+ * Returns:
+ * Ptr to the Domain name if the operation is successful
+ * NULL - if the operation fails
+ *
+ */
+char *
+send_ldom_create_domain(char *xml, xmlChar *action)
+{
+ xmlDocPtr xml_request;
+ xmlDocPtr xml_response;
+ xmlNodePtr root_node = NULL;
+ int ret;
+ char *ldomName;
+ char *filerc;
+ char fname[64];
+ char xmlBuf[256];
+ char tags[64];
+ char *newXml,*modXml;
+ time_t timesecs;
+ FILE *fptr;
+ size_t fwrc;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain(ENTER)\n");
+
+ /*
+ * The input XML char buffer should be the output of list-constrtains -x
+ * It can be modified for the constraints, but will not have the
+ * <cmd> or <action> tags. These tags have to be added to that XML
+ * file before sending it to LDM.
+ *
+ * The input XML char buffer is written to a file, then that file is read
+ * one line at a time so we can determine when to insert the new tags.
+ * The lines read in are accumulated in memory in a char buffer, that
+ * will get converted into an XmlDoc.
+ */
+
+ /* Create a unique file name for the temp file */
+ timesecs = time(NULL);
+ sprintf(fname,"/tmp/xmlfile-%d",timesecs);
+
+ /* Write the XML char buffer to the file */
+ fptr = fopen(fname, "w");
+ if (fptr == NULL) {
+ ldomsError(NULL, NULL, VIR_ERR_OPEN_FAILED, fname, VIR_ERR_ERROR);
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain() fopen(%s) for write failed\n", fname);
+ return(NULL);
+ }
+ fwrc = fwrite(xml, strlen(xml), 1, fptr);
+ fclose(fptr);
+
+ /* Read in the XML file and insert the <cmd> and <action> tags */
+ fptr = fopen(fname, "r");
+ if (fptr == NULL) {
+ ldomsError(NULL, NULL, VIR_ERR_READ_FAILED, fname, VIR_ERR_ERROR);
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain() fopen(%s) for read failed\n", fname);
+ return(NULL);
+ }
+
+ /* Can't malloc the space for the XML doc + new tags */
+ if (!(modXml = malloc(strlen(xml) + 128))) {
+ ldomsError(NULL, NULL, VIR_ERR_NO_MEMORY, (char*)action, VIR_ERR_ERROR);
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain() malloc failed\n", fname);
+ fclose(fptr);
+ remove(fname);
+ return(NULL);
+ }
+ /* Save the poiner to the beginning of the in memory XML doc */
+ bzero(modXml, strlen(xml) + 128);
+ newXml = modXml;
+
+ /* Get the 1st line of the XML file */
+ filerc = fgets(xmlBuf, sizeof(xmlBuf), fptr);
+
+ /* Read in the XML file, appending to the in memory XML */
+ while (filerc != NULL) {
+ memcpy(modXml, xmlBuf, strlen(xmlBuf));
+ modXml = modXml + strlen(xmlBuf);
+
+ /* The 1st set of tags, <cmd><action>, go after <LDM_interface> */
+ if (strstr(xmlBuf, (char*)XML_LDM_INTERFACE) != NULL) {
+ sprintf(tags, "<%s><%s>%s</%s>",
+ XML_CMD, XML_ACTION, action, XML_ACTION);
+ memcpy(modXml, tags, strlen(tags));
+ modXml = modXml + strlen(tags);
+
+ filerc = fgets(xmlBuf, sizeof(xmlBuf), fptr);
+ /* Go to another while loop to find the end tags */
+ break;
+ }
+ filerc = fgets(xmlBuf, sizeof(xmlBuf), fptr);
+ }
+
+ /* Finish reading and appending until the end tag is found so we can add </cmd> */
+ while (filerc != NULL) {
+ /* </cmd> goes before </LDM_interface> */
+ if (strstr(xmlBuf, (char*)XML_LDM_INTERFACE) != NULL) {
+ sprintf(tags, "</%s>", XML_CMD);
+ memcpy(modXml, tags, strlen(tags));
+ modXml = modXml + strlen(tags);
+ }
+ memcpy(modXml, xmlBuf, strlen(xmlBuf));
+ modXml = modXml + strlen(xmlBuf);
+ filerc = fgets(xmlBuf, sizeof(xmlBuf), fptr);
+ }
+ fclose(fptr);
+ modXml++; *modXml = '\0';
+
+ /* create XML file to send request to the ldom manager */
+ xml_request = xmlReadDoc((const xmlChar *) newXml, NULL, NULL, 0);
+
+ if (xml_request == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain(EXIT) Failed to create xml file \n");
+ remove(fname);
+ return (NULL);
+ }
+
+ /* send XML file to the LDM */
+ xml_response = send_xml_file_to_ldm(xml_request);
+ if (xml_response == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain(EXIT) Failed to send xml file to ldm and receive xml back\n");
+ xmlFreeDoc(xml_request);
+ remove(fname);
+ return (NULL);
+ }
+
+ /* Check the response status to make the the request was successful.
+ * An invalid request can return an XML document.
+ */
+ root_node = xmlDocGetRootElement(xml_response);
+ if (root_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain.. XML file does not have root node\n");
+ xmlFreeDoc(xml_request);
+ xmlFreeDoc(xml_response);
+ remove(fname);
+ return(NULL);
+ }
+
+ if (parse_xml_get_response_status(root_node) == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain(EXIT) Failure response from received xml\n");
+ xmlFreeDoc(xml_request);
+ xmlFreeDoc(xml_response);
+ remove(fname);
+ return(NULL);
+ }
+
+ /* Get the Domain name from the request */
+ ldomName = parse_xml_get_ldom_name(xmlDocGetRootElement(xml_request));
+
+ /* cleanup */
+ xmlFreeDoc(xml_request);
+ xmlFreeDoc(xml_response);
+ remove(fname);
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain(EXIT)\n");
+
+ return(ldomName);
+}
+
+/*
+ * send_ldom_lifecycle_action
+ *
+ * This function sends an LDom lifecycle action to the LDM to change the state
+ * of an LDom. Valid actions are: start-domain, stop-domain, bind-domain,
+ * unbind-domain, destroy-domain.
+ *
+ * Input:
+ * ldom_name - name of the ldom to start or stop
+ * ldom_action - Life cycle action. See ldoms_common.h
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ */
+int
+send_ldom_lifecycle_action(char *ldom_name, int ldom_action)
+{
+ xmlDocPtr xml_output;
+ xmlDocPtr xml_received;
+ xmlChar *action;
+ int ret;
+ xmlNodePtr root_node = NULL;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_lifecycle_action(ENTER): ldom_name=%s, action=%d\n", ldom_name, ldom_action);
+
+ if (ldom_action == LDOM_START)
+ action = XML_START_DOMAIN;
+ else if (ldom_action == LDOM_STOP)
+ action = XML_STOP;
+ else if (ldom_action == LDOM_BIND)
+ action = XML_BIND_DOMAIN;
+ else if (ldom_action == LDOM_UNBIND)
+ action = XML_UNBIND;
+ else if (ldom_action == LDOM_DELETE)
+ action = XML_DELETE;
+ else {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_lifecycle_action(EXIT): unsupported lifecycle action %d\n",ldom_action);
+ return(-1);
+ }
+
+ /* create XML file to send request to the ldom manager */
+ xml_output = create_xml_file_4_ldom_action(ldom_name, action);
+ if (xml_output == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_active_mgmt.. failed to create xml file for ldom_name=%s action=%s\n",
+ ldom_name, action);
+ return (-1);
+ }
+
+ /* send XML file to the LDM */
+ xml_received = send_xml_file_to_ldm(xml_output);
+ if (xml_received == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_active_mgmt.. failed to send xml file to ldm and receive xml back\n");
+ xmlFreeDoc(xml_output);
+ return (-1);
+ }
+
+ /* check the response status */
+ root_node = xmlDocGetRootElement(xml_received);
+ if (root_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_active_mgmt.. XML file does not have root node\n");
+ xmlFreeDoc(xml_output);
+ xmlFreeDoc(xml_received);
+ return(-1);
+ }
+
+ if (parse_xml_get_response_status(root_node) == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_active_mgmt.. failure response from received xml\n");
+ xmlFreeDoc(xml_output);
+ xmlFreeDoc(xml_received);
+ return(-1);
+ }
+
+ /* cleanup */
+ xmlFreeDoc(xml_output);
+ xmlFreeDoc(xml_received);
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_lifecycle_action(EXIT)\n");
+
+ return(0);
+}
+
+
+/*
+ * get_ldom_rsc_pool
+ *
+ * This function gets the resource pool info such as the CPU and memory
+ * capacity or reserved data by invoking routines to create and send
+ * the "list-devices" (for capacity data) or "list-bindings" (for reserved data)
+ * XML requests to the LDOM Manager and parse the response XML output from the LDOM Manager.
+ *
+ * Input:
+ * resource - indicates which resource to retrieve the resource pool data
+ * CPU_RP=CPU resource pool
+ * MEM_RP = memory resource pool
+ * rp_type - indicates either capacity or reserved
+ * RP_CAPACITY = capacity resource
+ * RP_RESERVED = reserved resource
+ *
+ * Output (pointers are used to pass information from this function to the caller):
+ * rp_qty - pointer to the integer for the resource pool quantity
+ * unit - pointer to the allocation unit for CPU or memory resources
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ */
+int
+get_ldom_rsc_pool(int resource, int rp_type, ulong_t *rp_qty, int *unit)
+{
+ xmlDocPtr xml_output;
+ xmlDocPtr xml_received;
+ xmlChar *action;
+ int ret;
+
+ ulong_t rp_qty_from_xml = 0;
+ int unit_from_xml = 1;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_rsc_pool (ENTER)\n");
+
+ *rp_qty = 0;
+ *unit = 0;
+
+ /* use list-devices for capacity and list-bindings for reserved resources */
+ if (rp_type == RP_CAPACITY)
+ action = XML_LIST_DEVICES;
+ else
+ action = XML_LIST_BIND;
+
+ /* create XML file to send request to the ldom manager */
+ xml_output = create_xml_file_4_ldom_action(NULL, action);
+ if (xml_output == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_rsc_pool.. failed to create xml file for action=%s\n",
+ action);
+ return (-1);
+ }
+
+ /* send XML file to the ldom manager */
+ xml_received = send_xml_file_to_ldm(xml_output);
+ if (xml_received == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_rsc_pool.. failed to send xml file to ldm and receive xml back\n");
+ xmlFreeDoc(xml_output);
+ return (-1);
+ }
+
+ switch (resource) {
+ case CPU_RP:
+ /* parse the received XML file to get the cpu resource rp_qty info */
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_rsc_pool.. trying to parse for cpu resource\n");
+ if (rp_type == RP_CAPACITY) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_rsc_pool.. trying to parse for capacity value\n");
+ ret = parse_xml_get_cpu_rp(xml_received, rp_type, &rp_qty_from_xml, &unit_from_xml);
+ }
+ else {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_rsc_pool.. trying to parse for reserved value\n");
+ ret = parse_xml_get_cpu_rp(xml_received, rp_type, &rp_qty_from_xml, &unit_from_xml);
+ }
+ break;
+ case MEM_RP:
+ /* parse the received XML file to get the memory resource rp_qty info */
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_rsc_pool.. trying to parse for memory resource\n");
+ if (rp_type == RP_CAPACITY) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_rsc_pool.. trying to parse for capacity value\n");
+ ret = parse_xml_get_mem_rp(xml_received, rp_type, &rp_qty_from_xml, &unit_from_xml);
+ }
+ else {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_rsc_pool.. trying to parse for reserved value\n");
+ ret = parse_xml_get_mem_rp(xml_received, rp_type, &rp_qty_from_xml, &unit_from_xml);
+ }
+ break;
+ default:
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_rsc_pool.. unsupported resource\n");
+ }
+
+ if (ret == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_rsc_pool.. failed to parse xml file\n");
+ return (-1);
+ }
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_rsc_pool. rp_qty=%d unit=%d\n", rp_qty_from_xml, unit_from_xml);
+
+ *rp_qty = rp_qty_from_xml;
+ *unit = unit_from_xml;
+
+ /* cleanup */
+ xmlFreeDoc(xml_output);
+ xmlFreeDoc(xml_received);
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_rsc_pool (EXIT)\n");
+
+ return(0);
+} /* get_ldom_rsc_pool */
+
+/*
+ * get_ldom_cpu_bindings
+ *
+ * This function gets the cpu bindings for the input domain.
+ * The CPU binding info is put into the input cpuBinding structure.
+ * The processing of this data is handeled by the calling routine.
+
+ * Input:
+ * domain - The domain name
+ * cpuBindings - Pointer to a structure to place CPU binding info
+ *
+ * Output:
+ * cpuBindings - Updated structure content with CPU binding info
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ */
+int
+get_ldom_cpu_bindings(char *domain, cpuBindings_t **cpuBindings)
+{
+ xmlDocPtr xml_output;
+ xmlDocPtr xml_received;
+ xmlChar *action;
+ int ret;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_cpu_bindings (ENTER)\n");
+
+ action = XML_LIST_BIND;
+
+ /* create XML file to send request to the ldom manager */
+ xml_output = create_xml_file_4_ldom_action(domain, action);
+ if (xml_output == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_cpu_bindings.. failed to create xml file for action=%s\n",action);
+ return (-1);
+ }
+
+ /* send XML file to the ldom manager */
+ xml_received = send_xml_file_to_ldm(xml_output);
+ if (xml_received == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_cpu_bindings.... failed to send xml file to ldm and receive xml back\n");
+ xmlFreeDoc(xml_output);
+ return (-1);
+ }
+
+ ret = parse_xml_get_cpu_bindings(xml_received, cpuBindings);
+
+ if (ret < 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_cpu_bindings...... failed to parse xml file\n");
+ return (ret);
+ }
+
+ /* cleanup */
+ xmlFreeDoc(xml_output);
+ xmlFreeDoc(xml_received);
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_cpu_bindings(EXIT)\n");
+
+ return(ret);
+} /* get_ldom_cpu_bindings */
+
+/*
+ * get_free_memory
+ *
+ * This function gets the amount of unused (free) memory in the LDoms system, by
+ * invoking get_ldom_rsc_pool() routine that sends the "list-devices" XML request
+ * to the ldom manager.
+ * The memory amount is converted to KBytes.
+ *
+ * Input:
+ *
+ * Output (pointer is used to pass information from this function to the caller):
+ * maxmem - pointer to the maximum amount of memory allowed (in KB)
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ */
+int
+get_free_memory(unsigned long *maxmem)
+{
+ int ret;
+ ulong_t capacity = 0;
+ int memunit = LDOMMEMUNIT_KILOBYTES;
+
+ unsigned long mem;
+
+ int resource = MEM_RP;
+ int rp_type = RP_CAPACITY;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_free_memory(ENTER) \n");
+
+ *maxmem = 0;
+
+ ret = get_ldom_rsc_pool(resource, rp_type, &capacity, &memunit);
+
+ if (ret == -1)
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_free_memory... get_ldom_rsc_pool failed\n");
+ else
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_free_memory.. capacity=%d memunit=%d\n", capacity, memunit);
+
+ /* convert the memory value to KBytes */
+ switch (memunit) {
+ case LDOMMEMUNIT_KILOBYTES: break; /* KB already */
+ case LDOMMEMUNIT_MEGABYTES: capacity *= 1024; break; /* MB */
+ case LDOMMEMUNIT_GIGABYTES: capacity *= (1024 * 1024); break; /* GB */
+ case LDOMMEMUNIT_BYTES: capacity /= 1024; break; /* Bytes */
+ }
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_free_memory.. Free memory = %dKB\n", capacity);
+
+ mem = capacity;
+
+ *maxmem = mem;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_free_memory(EXIT).. Maximum Free memory = %dKB\n", mem);
+
+ return(ret);
+
+} /* get_free_memory */
+
+
+/*
+ * get_ldom_total_memory
+ *
+ * This function retrieves the total amount of memory on the system from LDM by
+ * invoking get_ldom_rsc_pool() calls to send the "list-devices" (for free
+ * resource) and "list-bindings" (for bound resource) to the ldom manager
+ * and adds up the free and bound memory amount for all domains.
+ * This function converts the memory to KBytes.
+ *
+ * Input:
+ *
+ * Output (pointer is used to pass information from this function to the caller):
+ * total_mem - pointer to the total amount of memory (in KB)
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ */
+int
+get_ldom_total_memory(unsigned long *total_mem)
+{
+ int ret;
+ ulong_t capacity = 0;
+ ulong_t reserved = 0;
+ int memunit = LDOMMEMUNIT_KILOBYTES;
+
+ unsigned long mem;
+
+ int resource = MEM_RP;
+ int rp_type = RP_CAPACITY;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_memory(ENTER) \n");
+
+ *total_mem = 0;
+
+ /* first, get the amount of free memory by using the RP_CAPACITY type
+ * that sends the list-devices request */
+ ret = get_ldom_rsc_pool(resource, rp_type, &capacity, &memunit);
+
+ if (ret == -1)
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_memory... get_ldom_rsc_pool failed with RP_CAPACITY\n");
+ else
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_total_memory.. capacity=%d memunit=%d\n", capacity, memunit);
+
+ /* convert the memory value to KBytes */
+ switch (memunit) {
+ case LDOMMEMUNIT_KILOBYTES: break; /* KB already */
+ case LDOMMEMUNIT_MEGABYTES: capacity *= 1024; break; /* MB */
+ case LDOMMEMUNIT_GIGABYTES: capacity *= (1024 * 1024); break; /* GB */
+ case LDOMMEMUNIT_BYTES: capacity /= 1024; break; /* Bytes */
+ }
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_total_memory.. Free memory = %dKB\n", capacity);
+
+ mem = capacity;
+
+ /* Set the global var for the Free memory in KB */
+ ldomsFreeMem = mem;
+
+ /* now, get the amount of bound memory by using the RP_RESERVED type
+ * that send the list-bindings request */
+ rp_type = RP_RESERVED;
+ ret = get_ldom_rsc_pool(resource, rp_type, &reserved, &memunit);
+
+ if (ret == -1)
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_memory... get_ldom_rsc_pool failed with RP_RESERVED\n");
+ else
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_total_memory.. reserved=%d memunit=%d\n", reserved, memunit);
+
+ /* convert the memory value to KBytes */
+ switch (memunit) {
+ case LDOMMEMUNIT_KILOBYTES: break; /* KB already */
+ case LDOMMEMUNIT_MEGABYTES: reserved *= 1024; break; /* MB */
+ case LDOMMEMUNIT_GIGABYTES: reserved *= (1024 * 1024); break; /* GB */
+ case LDOMMEMUNIT_BYTES: reserved /= 1024; break; /* Bytes */
+ }
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_total_memory.. Used memory = %dKB\n", reserved);
+
+ /* add up the amount of bound memory to the free memory */
+ mem += reserved;
+
+ /* Set the global var for the Used memory in KB */
+ ldomsUsedMem = reserved;
+
+ *total_mem = mem;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_memory(EXIT): total memory in KB=%d\n", mem);
+
+ return(ret);
+
+} /* get_ldom_total_memory */
+
+
+/*
+ * get_ldom_total_cpu
+ *
+ * This function retrieves the total number of CPUs on the system from LDM by
+ * invoking get_ldom_rsc_pool() calls to send the "list-devices" (for free
+ * resource) and "list-bindings" (for bound resource) to the ldom manager
+ * and adds up the free and bound CPUs for all domains.
+ *
+ * Input:
+ *
+ * Output (pointer is used to pass information from this function to the caller):
+ * total_cpu - pointer to the total number of CPUs
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ */
+int
+get_ldom_total_cpu(int *total_cpu)
+{
+ int ret;
+ ulong_t capacity = 0;
+ ulong_t reserved = 0;
+ int unit = 1;
+
+ int tcpu;
+
+ int resource = CPU_RP;
+ int rp_type = RP_CAPACITY;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_cpu(ENTER) \n");
+
+ *total_cpu = 0;
+
+ /* first, get the number of free CPUs by using the RP_CAPACITY type
+ * that sends the list-devices request */
+ ret = get_ldom_rsc_pool(resource, rp_type, &capacity, &unit);
+
+ if (ret == -1)
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_cpu... get_ldom_rsc_pool failed with RP_CAPACITY\n");
+ else
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_total_cpu.. capacity(free CPUs)=%d \n", capacity);
+
+ tcpu = capacity;
+
+ /* Set the global var for the Free CPUs */
+ ldomsFreeCpu = capacity;
+
+ /* now, get the number of bound CPUs by using the RP_RESERVED type
+ * that send the list-bindings request */
+ rp_type = RP_RESERVED;
+ ret = get_ldom_rsc_pool(resource, rp_type, &reserved, &unit);
+
+ if (ret == -1)
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_cpu... get_ldom_rsc_pool failed with RP_RESERVED\n");
+ else
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_total_cpu.. reserved(bound CPUs)=%d\n", reserved);
+
+ /* add up the amount of bound memory to the free memory */
+ tcpu += reserved;
+
+ /* Set the global var for the Used CPUs */
+ ldomsUsedCpu = reserved;
+
+ *total_cpu = tcpu;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_cpu(EXIT): total_cpu=%d\n", tcpu);
+
+ return(ret);
+
+} /* get_ldom_total_cpu */
+
+#endif /* WITH_LDOMS */
+
+/*
+ * vim: set tabstop=4:
+ * vim: set shiftwidth=4:
+ * vim: set expandtab:
+ */
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
+
diff --git a/src/ldoms_xml_parse.h b/src/ldoms_xml_parse.h
new file mode 100644
--- /dev/null
+++ b/src/ldoms_xml_parse.h
@@ -0,0 +1,212 @@
+/*
+ * ldoms_xml_parse.h: data structure to be used in the LDoms XML parsing.
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ */
+
+#ifndef __VIR_LDOMS_XML_PARSE_H__
+#define __VIR_LDOMS_XML_PARSE_H__
+
+#ifdef WITH_LDOMS
+
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include "libvirt/libvirt.h"
+#include "ldoms_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* data structures that parsing code will populate */
+typedef struct ldominfo {
+ ulong_t index;
+ char ldomName[NAME_SIZE]; /* ldom name */
+ uint_t ldomState; /* admin state */
+ ulong_t ldomNumVCpu; /* number of VCpu */
+ ulong_t ldomMemSize; /* virtual memory size */
+ uint_t ldomMemUnit; /* unit of memory */
+ ulong_t ldomNumCrypto; /* number of crypto */
+ ulong_t ldomNumIOBus; /* number of IO bus */
+ int ldomConsole; /* console port */
+ unsigned char uuid[VIR_UUID_BUFLEN];
+} ldominfo_t;
+
+typedef struct vcpu_s {
+ ulong_t index;
+ ulong_t vcpuLdomIndex; /* index to ldom table */
+ char vcpuDeviceID[NAME_SIZE]; /* virtual CPU Device ID */
+ uint_t vcpuOperationalStatus; /* vcpu status */
+ char vcpuPhysBind[NAME_SIZE]; /* physical binding */
+ ulong_t vcpuPhysBindUsage; /* physical bind usage */
+} vcpu_t;
+
+typedef struct vmem_data_s {
+ ulong_t index;
+ ulong_t vmemLdomIndex; /* index to ldom table */
+ ulong_t vmemNumberOfBlocks; /* number of vmem blocks */
+} vmem_data_t;
+
+typedef struct vmem_physbind_s {
+ ulong_t index;
+ ulong_t vmemLdomIndex; /* index to ldom table */
+ char vmemPhysBind[NAME_SIZE]; /* memory block binding */
+} vmem_physbind_t;
+
+typedef struct vsw_s {
+ ulong_t index;
+ ulong_t vswLdomIndex; /* index to ldom table */
+ char vswServiceName[NAME_SIZE]; /* vsw service name */
+ char vswMacAddress[NAME_SIZE]; /* vsw mac address */
+ char vswPhysDevPath[NAME_SIZE]; /* vsw physical dev path */
+ uint_t vswMode; /* vsw mode */
+ char vswLdomName[NAME_SIZE]; /* ldom name - used to index to ldom table */
+} vsw_t;
+
+typedef struct vsw_name_s {
+ char ServiceName[NAME_SIZE]; /* vsw service name */
+} vsw_name_t;
+
+typedef struct vnet_s {
+ ulong_t index;
+ ulong_t vnetLdomIndex; /* index to ldom table */
+ ulong_t vnetVswIndex; /* index to vsw table */
+ char vnetDevName[NAME_SIZE]; /* vnet dev name */
+ char vnetDevMacAddress[NAME_SIZE]; /* vnet dev mac address */
+ char vnetServiceName[NAME_SIZE]; /* vsw service name - used to index to vsw table */
+ char vnetLdomName[NAME_SIZE]; /* ldom name - used to index to ldom table */
+} vnet_t;
+
+typedef struct vds_s {
+ ulong_t index;
+ ulong_t vdsLdomIndex; /* index to ldom table */
+ char vdsServiceName[NAME_SIZE]; /* vds service name */
+ ulong_t vdsNumofAvailVolume; /* number of available logical volume */
+ ulong_t vdsNumofUsedVolume; /* number of used logical volume */
+ char vdsLdomName[NAME_SIZE]; /* ldom name - used to index to ldom table */
+} vds_t;
+
+typedef struct vds_name_s {
+ char ServiceName[NAME_SIZE]; /* vds service name */
+} vds_name_t;
+
+typedef struct vdsdev_s {
+ ulong_t index;
+ ulong_t vdsdevVdsIndex; /* index to vds table */
+ char vdsdevVolumeName[NAME_SIZE]; /* volume name */
+ char vdsdevDevPath[NAME_SIZE]; /* block dev */
+ char vdsdevServiceName[NAME_SIZE]; /* vds service name - used to index to vds table */
+} vdsdev_t;
+
+typedef struct vdsdev_name_s {
+ char VolumeName[NAME_SIZE]; /* vdsdev name */
+ char ServiceName[NAME_SIZE]; /* vds name */
+} vdsdev_name_t;
+
+typedef struct vdisk_s {
+ ulong_t index;
+ ulong_t vdiskLdomIndex; /* index to ldom table */
+ ulong_t vdiskVdsdevIndex; /* index to vdsdev table */
+ char vdiskName[NAME_SIZE]; /* vdisk name */
+ char vdiskServiceName[NAME_SIZE]; /* vds name - used to index to vdsdev table */
+ char vdiskVolumeName[NAME_SIZE]; /* vdsdev name - used to index to vdsdev table */
+ char vdiskLdomName[NAME_SIZE]; /* ldom name - used to index to ldom table */
+} vdisk_t;
+
+typedef struct vcc_s {
+ ulong_t index;
+ ulong_t vccLdomIndex; /* index to ldom table */
+ char vccName[NAME_SIZE]; /* vcc service name */
+ uint_t vccPortRangeLow; /* vcc min port */
+ uint_t vccPortRangeHigh; /* vcc max port */
+ char vccLdomName[NAME_SIZE]; /* ldom name - used to index to ldom table */
+} vcc_t;
+
+typedef struct vcc_name_s {
+ char ServiceName[NAME_SIZE]; /* vcc name */
+} vcc_name_t;
+
+typedef struct vcons_s {
+ ulong_t index;
+ char vconsGroupName[NAME_SIZE]; /* vcons group name */
+ uint_t vconsPortNumber; /* vcons port */
+ char vconsLdomName[NAME_SIZE]; /* ldom name - used to index to ldom table */
+} vcons_t;
+
+typedef struct vconsvccrel_s {
+ ulong_t index;
+ uint_t vconsvccrelVconsIndex; /* index to vcons table */
+ uint_t vconsvccrelLdomIndex; /* index to ldom table */
+ uint_t vconsvccrelVccIndex; /* index to vcc table */
+ char vconsvccrelServiceName[NAME_SIZE]; /* vcc service name - used to index to vcc table */
+ char vconsvccrelLdomName[NAME_SIZE]; /* ldom name - used to index to ldom table */
+} vconsvccrel_t;
+
+typedef struct envvars_s {
+ ulong_t index;
+ ulong_t envvarsLdomIndex; /* index to ldom table */
+ char envvarsName[NAME_SIZE]; /* env var name */
+ char envvarsValue[NAME_SIZE]; /* env var value */
+} envvars_t;
+
+typedef struct crypto_s {
+ ulong_t index;
+ ulong_t cryptoLdomIndex; /* index to ldom table */
+ char cryptoCpuSet[NAME_SIZE]; /* crypto cpuset */
+} crypto_t;
+
+typedef struct iobus_s {
+ ulong_t index;
+ ulong_t iobusLdomIndex; /* index to ldom table */
+ char iobusDevName[NAME_SIZE]; /* iobus device name */
+ char iobusDevPath[NAME_SIZE]; /* iobus device path */
+} iobus_t;
+
+xmlDocPtr create_xml_file(char *snmp_user, char *ldom_name, const xmlChar *action);
+xmlDocPtr create_xml_file_4_ldom_action(char *, const xmlChar *);
+xmlDocPtr create_xml_file_4_set_vcpu(char *, int );
+xmlDocPtr create_xml_file_4_set_memory(char *, unsigned long );
+
+int parse_xml_get_response_status(xmlNodePtr node);
+int parse_xml_get_ldom_state(xmlNodePtr node);
+
+int parse_xml_get_ldom_cnt(xmlDoc *doc, int *ldom_cnt);
+int parse_xml_get_ldominfo(xmlDoc *doc, int *num_cpu, int *mem_size, int *mem_unit, int *num_crypto, int *num_iobus);
+char* parse_xml_get_ldom_name(xmlNodePtr node);
+
+int parse_xml_get_subnode_cnt(xmlNodePtr node, xmlChar *subnode);
+int parse_xml_get_vds_volume(xmlNodePtr node, char *service_name);
+int parse_xml_get_vds_volume_bind(xmlDoc *doc, char *service_name);
+char* parse_xml_get_mac_addr(xmlNodePtr node);
+
+int parse_xml_get_cpu_bindings(xmlDocPtr, cpuBindings_t **);
+int parse_xml_get_console(xmlDoc *, int *);
+int parse_xml_get_vcpu(xmlDoc *doc, int *vcpu_cnt, vcpu_t ***vcpu);
+int parse_xml_get_vmem(xmlDoc *doc, int *vmem_cnt, vmem_data_t ***vmem);
+int parse_xml_get_vmem_physbind(xmlDoc *doc, int *vmem_cnt, vmem_physbind_t ***vmem);
+int parse_xml_get_vsw(xmlDoc *doc, int *vsw_cnt, vsw_t ***vsw);
+int parse_xml_get_vnet(xmlDoc *doc, int *vnet_cnt, vnet_t ***vnet);
+int parse_xml_get_vds(xmlDoc *doc, int *vds_cnt, vds_t ***vds);
+int parse_xml_get_vdsdev(xmlDoc *doc, int *vdsdev_cnt, vdsdev_t ***vdsdev);
+int parse_xml_get_vdisk(xmlDoc *doc, int *vdisk_cnt, vdisk_t ***vdisk);
+int parse_xml_get_vcc(xmlDoc *doc, int *vcc_cnt, vcc_t ***vcc);
+int parse_xml_get_vcons(xmlDoc *doc, int *vcons_cnt, vcons_t ***vcons);
+int parse_xml_get_vconsvccrel(xmlDoc *doc, int *vconsvccrel_cnt, vconsvccrel_t ***vconsvccrel);
+int parse_xml_get_envvars(xmlDoc *doc, int *envvars_cnt, envvars_t ***envvars);
+int parse_xml_get_crypto(xmlDoc *doc, int *crypto_cnt, crypto_t ***crypto);
+int parse_xml_get_iobus(xmlDoc *doc, int *iobus_cnt, iobus_t ***iobus);
+
+int parse_xml_get_cpu_rp(xmlDoc *doc, int rp_type, ulong_t *reserved, int *unit);
+int parse_xml_get_mem_rp(xmlDoc *doc, int rp_type, ulong_t *reserved, int *unit);
+int parse_xml_get_crypto_rp(xmlDoc *doc, int rp_type, ulong_t *reserved, int *unit);
+int parse_xml_get_iobus_rp(xmlDoc *doc, int rp_type, ulong_t *reserved, int *unit);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WITH_LDOMS*/
+#endif /* __VIR_LDOMS_XML_PARSE_H__ */
diff --git a/src/ldoms_xml_parse.c b/src/ldoms_xml_parse.c
new file mode 100644
--- /dev/null
+++ b/src/ldoms_xml_parse.c
@@ -0,0 +1,1832 @@
+/*
+ * ldoms_xml_parse.c: LDoms XML parsing routines using the LDoms XML Schema V2
+ * to interface with the LDoms Manager (LDM)
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ */
+
+#ifdef WITH_LDOMS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/processor.h>
+#include <fcntl.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+
+
+#include "internal.h"
+#include "xml.h"
+#include "ldoms_internal.h"
+#include "ldoms_intfc.h"
+
+/* Domain state info
+ * LDom State enumerations
+ * 1 = active
+ * 2 = stopping
+ * 3 = inactive
+ * 4 = binding
+ * 5 = unbinding
+ * 6 = bound
+ * 7 = starting
+ *
+ * libvirt LDom State enums
+ * typedef enum {
+ * VIR_DOMAIN_NOSTATE = 0, no state
+ * VIR_DOMAIN_RUNNING = 1, the domain is running
+ * VIR_DOMAIN_BLOCKED = 2, the domain is blocked on resource
+ * VIR_DOMAIN_PAUSED = 3, the domain is paused by user
+ * VIR_DOMAIN_SHUTDOWN= 4, the domain is being shut down
+ * VIR_DOMAIN_SHUTOFF = 5, the domain is shut off
+ * VIR_DOMAIN_CRASHED = 6 the domain is crashed
+ * } virDomainState;
+ */
+
+/*
+ * when adding up the memory (capacity/reserved) for the memory resource pool,
+ * the memory unit will be converted to take the smallest unit in use.
+ */
+#define MEM_GB_BYTES (1024*1024*1024) /* 1 GB in bytes */
+#define MEM_MB_BYTES (1024*1024) /* 1 MB in bytes */
+#define MEM_KB_BYTES (1024) /* 1 KB in bytes */
+
+/* Global vars for debug statement */
+extern int ldoms_debug;
+extern int ldoms_detailed_debug;
+
+/*
+ * Returns the next elemental sibling node of the node you pass in. If there
+ * are no more nodes it returns NULL.
+ */
+xmlNodePtr
+xml_get_next_ele_node(xmlNodePtr node)
+{
+ xmlNodePtr sib_node;
+
+ sib_node = node->next;
+
+ while (sib_node != NULL) {
+ if (sib_node->type != XML_ELEMENT_NODE)
+ sib_node = sib_node->next;
+ else
+ break;
+ }
+
+ return (sib_node);
+} /* xml_get_next_ele_node() */
+
+/*
+ * Find and return the first-level subnode (if any) of 'node' which has name
+ * 'name'.
+ */
+xmlNodePtr
+xml_find_subnode(xmlNodePtr node, const xmlChar *name)
+{
+ xmlNodePtr subnode;
+
+ subnode = node->xmlChildrenNode;
+ while (subnode != NULL) {
+ if (xmlStrcmp(subnode->name, name) == 0)
+ break;
+ subnode = subnode->next;
+ }
+
+ return (subnode);
+} /* xml_find_subnode */
+
+
+/*
+ * create_xml_file_4_set_vcpu
+ *
+ * This function creates the XML request file for changing the number
+ * or virtual cpus for an LDom
+ *
+ * Input:
+ * ldom_name - name of the ldom to be included in the XML file with
+ * the <ldom_name> tag.
+ * nvcpus - The new number of vcpus for this LDom
+ *
+ * Returns:
+ * pointer to the created xml doc if the operation is successful
+ * NULL if the operation fails
+ *
+ * Example: The following XML file will be created for LDom ldom1
+ * and a new vcpu value of 4
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>set-vcpu</action>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>ldom1</ldom_name>
+ * </ldom_info>
+ * <cpu>
+ * <number>4</number>
+ * </cpu>
+ * </ldom>
+ * </data>
+ * </cmd>
+ * </LDM_interface>
+ */
+
+xmlDocPtr
+create_xml_file_4_set_vcpu(char *ldom_name, int nvcpus)
+{
+ xmlDocPtr xml_output;
+ xmlNodePtr root, cmd, data, ldom, info_node, cpu;
+ char vcpu[10]; /* ascii version of input int nvcpus */
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: create_xml_file_4_set_vcpu(ENTER): ldom=%s, vcpus=%d\n",
+ (ldom_name==NULL? "NULL" : ldom_name), nvcpus);
+
+ xml_output = xmlNewDoc(XML_VERSION);
+
+ /* <LDM_interface> tag with version attribute */
+ root = xmlNewDocNode(xml_output, NULL, XML_LDM_INTERFACE, NULL);
+ xmlDocSetRootElement(xml_output, root);
+ xmlNewProp(root, VERSION_ATTR, LDOM_INTERFACE_VERSION);
+
+ /* <cmd> tag */
+ cmd = xmlNewChild(root, NULL, XML_CMD, NULL);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_vcpu() cmd tag\n");
+
+ /* <action> tag */
+ xmlNewChild(cmd, NULL, XML_ACTION, XML_SET_VCPU);
+
+ /* <data> tag with version attribute */
+ data = xmlNewChild(cmd, NULL, XML_DATA, NULL);
+ xmlNewProp(data, VERSION_ATTR, LDOM_DATA_VERSION);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_vcpu() data tag\n");
+
+ /* <ldom> tag */
+ ldom = xmlNewChild(data, NULL, LDOM_NODE, NULL);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_vcpu() ldom tag\n");
+
+ /* <ldom_info> tag with child <ldom_name> tag */
+ info_node = xmlNewChild(ldom, NULL, XML_LDM_INFO, NULL);
+ xmlNewChild(info_node, NULL, XML_LDM_NAME, (xmlChar *)ldom_name);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_vcpu() ldom_info tag\n");
+
+ /* <cpu> tag with child <number> tag */
+ cpu = xmlNewChild(ldom, NULL, CPU_NODE, NULL);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_vcpu() cpu tag\n");
+ sprintf(vcpu, "%d", nvcpus);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_vcpu() vcpu=%s\n",vcpu);
+ xmlNewChild(cpu, NULL, NUMBER_NODE, (xmlChar *)vcpu);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_vcpu() number tag\n");
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: create_xml_file_4_set_vcpu(EXIT)\n");
+
+ return(xml_output);
+} /* create_xml_file_4_set_vpcu() */
+
+/*
+ * create_xml_file_4_set_memory
+ *
+ * This function creates the XML request file for changing the memory
+ * for an LDom
+ *
+ * Input:
+ * ldom_name - name of the ldom to be included in the XML file with
+ * the <ldom_name> tag.
+ * memory - The new memory size for this LDom.
+ * The memory size is in Kilobytes.
+ * NOTE: The VMM and virsh displays the memory in KB.
+ *
+ * Returns:
+ * pointer to the created xml doc if the operation is successful
+ * NULL if the operation fails
+ *
+ * Example: The following XML file will be created for LDom ldom1
+ * and a new memory value of 256 Kilobytes.
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>set-memory</action>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>ldom1</ldom_name>
+ * </ldom_info>
+ * <memory>
+ * <size>256K</size>
+ * </memory>
+ * </ldom>
+ * </data>
+ * </cmd>
+ * </LDM_interface>
+ */
+
+xmlDocPtr
+create_xml_file_4_set_memory(char *ldom_name, unsigned long memory)
+{
+ xmlDocPtr xml_output;
+ xmlNodePtr root, cmd, data, ldom, info_node, mem;
+ char mem_str[10]; /* ascii version of input int memory */
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: create_xml_file_4_set_memory(ENTER): ldom=%s, memory=%lu\n",
+ (ldom_name==NULL? "NULL" : ldom_name), memory);
+
+ xml_output = xmlNewDoc(XML_VERSION);
+
+ /* <LDM_interface> tag with version sttribute */
+ root = xmlNewDocNode(xml_output, NULL, XML_LDM_INTERFACE, NULL);
+ xmlDocSetRootElement(xml_output, root);
+ xmlNewProp(root, VERSION_ATTR, LDOM_INTERFACE_VERSION);
+
+ /* <cmd> tag */
+ cmd = xmlNewChild(root, NULL, XML_CMD, NULL);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_memory() cmd tag\n");
+
+ /* <action> tag */
+ xmlNewChild(cmd, NULL, XML_ACTION, XML_SET_MEM);
+
+ /* <data> tag with version attribute */
+ data = xmlNewChild(cmd, NULL, XML_DATA, NULL);
+ xmlNewProp(data, VERSION_ATTR, LDOM_DATA_VERSION);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_memory() data tag\n");
+
+ /* <ldom> tag */
+ ldom = xmlNewChild(data, NULL, LDOM_NODE, NULL);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_memory() ldom tag\n");
+
+ /* <ldom_info> tag with child <ldom_name> tag */
+ info_node = xmlNewChild(ldom, NULL, XML_LDM_INFO, NULL);
+ xmlNewChild(info_node, NULL, XML_LDM_NAME, (xmlChar *)ldom_name);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_memory() ldom_info tag\n");
+
+ /* add memory unit K (for Kilobytes) to the memory size string */
+ sprintf(mem_str, "%d", memory);
+ strlcat(mem_str, "K", sizeof (mem_str));
+
+ /* <memory> tag with child <size> tag */
+ mem = xmlNewChild(ldom, NULL, MEMORY_NODE, NULL);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_memory() memory tag\n");
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_memory() memory=%s\n", mem_str);
+ xmlNewChild(mem, NULL, SIZE_NODE, (xmlChar *)mem_str);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_memory() size tag\n");
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: create_xml_file_4_set_memory(EXIT)\n");
+
+ return(xml_output);
+} /* create_xml_file_4_set_memory() */
+
+/*
+ * create_xml_file_4_ldom_action
+ *
+ * This function creates the XML request file for the given ldom and action.
+ *
+ * Input:
+ * ldom_name - name of the ldom to be included in the XML file with
+ * the <ldom_name> tag. if ldom_name is NULL, the XML request for
+ * all ldoms will be created
+ * action - action (such as list-bindings or list-constraints..etc) to be
+ * included in the XML file with the <action> tag
+ *
+ * Returns:
+ * pointer to the created xml doc if the operation is successful
+ * NULL if the operation fails
+ *
+ * Example: The following XML file will be created if the
+ * name of the ldom is 'ldg3', and the action is 'list-bindings'.
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>list-bindings</action>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>ldg3</ldom_name>
+ * </ldom_info>
+ * </ldom>
+ * </data>
+ * </cmd>
+ * </LDM_interface>
+ */
+xmlDocPtr
+create_xml_file_4_ldom_action(char *ldom_name, const xmlChar *action)
+{
+ xmlDocPtr xml_output;
+ xmlNodePtr root, cmd, data, ldom, info_node;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: create_xml_file_4_ldom_action(ENTER): ldom=%s, action=%s\n",
+ (ldom_name==NULL? "NULL" : ldom_name), action);
+
+ xml_output = xmlNewDoc(XML_VERSION);
+ root = xmlNewDocNode(xml_output, NULL, XML_LDM_INTERFACE, NULL);
+ xmlDocSetRootElement(xml_output, root);
+ xmlNewProp(root, VERSION_ATTR, LDOM_INTERFACE_VERSION);
+
+ cmd = xmlNewChild(root, NULL, XML_CMD, NULL);
+
+ xmlNewChild(cmd, NULL, XML_ACTION, action);
+
+ data = xmlNewChild(cmd, NULL, XML_DATA, NULL);
+ xmlNewProp(data, VERSION_ATTR, LDOM_DATA_VERSION);
+
+ /*
+ * If the ldom_name is NULL, the LDM will return info for
+ * all existing LDoms, independent of their state. Otherwise,
+ * we get the info for only the LDom specified.
+ */
+ if (ldom_name != NULL) {
+ ldom = xmlNewChild(data, NULL, LDOM_NODE, NULL);
+ info_node = xmlNewChild(ldom, NULL, XML_LDM_INFO, NULL);
+ xmlNewChild(info_node, NULL, XML_LDM_NAME, (xmlChar *)ldom_name);
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: create_xml_file_4_ldom_action(EXIT)\n");
+
+ return(xml_output);
+} /* create_xml_file_4_ldom_action() */
+
+
+/*
+ * parse_xml_get_subnode_cnt
+ *
+ * This function counts the specific subnodes starting from the given xml node.
+ *
+ * Input:
+ * node - pointer to the xml node to start looking for the subnode
+ * subnode_to_find - subnode to look for and count the numbers
+ *
+ * Returns:
+ * number of subnodes if the operation is successful
+ * 0 if no subnode is found
+ */
+int
+parse_xml_get_subnode_cnt(xmlNodePtr node, xmlChar *subnode_to_find)
+{
+ xmlNodePtr subnode;
+ int i = 0;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_subnode_cnt(ENTER)\n");
+
+ subnode = node->xmlChildrenNode;
+ while (subnode != NULL) {
+ if (subnode->type != XML_ELEMENT_NODE) {
+ subnode = subnode->next;
+ continue;
+ }
+
+
+ if (xmlStrcmp(subnode->name, (const xmlChar *)subnode_to_find) == 0) {
+ i++;
+ subnode = subnode->next;
+ continue;
+ }
+
+ subnode = subnode->next;
+ }
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_subnode_cnt(EXIT) cnt=%d\n",i);
+
+
+ return(i);
+}
+
+/*
+ * parse_xml_get_console
+ *
+ * This function gets the console port number for an LDom.
+ *
+ * Input:
+ * xml doc - XML document to read (this will be an XML document for one ldom)
+ *
+ * Output (pointers are used to pass information from this function to the caller):
+ * console - pointer to the console port number
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ * NOTE: Example XML document that this function will parse to get the ldom info:
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>list-bindings</action>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>primary</ldom_name>
+ * </ldom_info>
+ * <console>
+ * <service_name>primary-vcc0</service_name>
+ * <port>5004</port>
+ * </console>
+ *...
+ * </ldom>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </data>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </cmd>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </LDM_interface>
+ */
+int
+parse_xml_get_console(xmlDoc *doc, int *console)
+{
+ int ret = 0;
+ int console_xml;
+ xmlNodePtr root_node = NULL;
+ xmlNodePtr cmd_node = NULL;
+ xmlNodePtr data_node = NULL;
+ xmlNodePtr ldom_node = NULL;
+ xmlNodePtr console_node = NULL;
+ char *ldm_name = NULL;
+ xmlChar *content = NULL;
+
+ xmlNodePtr subnode;
+
+ uint64_t size = 0;
+
+ *console = 0;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console(ENTER) \n");
+
+ root_node = xmlDocGetRootElement(doc);
+
+ /* Check for an XML failure */
+ if (parse_xml_get_response_status(root_node) == -1)
+ return(-1);
+
+ /* Get the <cmd> tag */
+ cmd_node = xml_find_subnode(root_node, XML_CMD);
+ if (cmd_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console.. XML file does not have <cmd> tag\n");
+ return (-1);
+ }
+
+ /* Get the <data> tag */
+ data_node = xml_find_subnode(cmd_node, XML_DATA);
+ if (data_node != NULL)
+ /* Get the <ldom> tag */
+ ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+ else {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console.. XML file does not have <data> tag\n");
+ return (-1);
+ }
+
+ if (ldom_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console.. XML file does not have <ldom> tag\n");
+ return (-1);
+ }
+
+ /* Get the <console> tag */
+ console_node = xml_find_subnode(ldom_node, CONSOLE_NODE);
+ if (console_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console.. XML file does not have <console> tag\n");
+ console_xml = 0;
+ } else {
+ /* Get the <port> tag */
+ subnode = xml_find_subnode(console_node, XML_PORT);
+ if (subnode == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console.. XML file does not have <port> tag within <console> tag\n");
+ console_xml = 0;
+ } else {
+ /* Contents of the <port> tag */
+ content = xmlNodeGetContent(subnode);
+
+ console_xml = atoi((const char *)content);
+ if (console_xml <= 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console.. Invalid <port> num: %s\n", content);
+ }
+ xmlFree(content);
+ }
+ }
+
+ *console = console_xml;
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console(EXIT) console=%d\n", console_xml);
+
+ return (ret);
+}
+
+/*
+ * parse_xml_get_ldominfo
+ *
+ * This function gets the ldom info such as the number of virtial cpu, memory and
+ * its unit, crypto, and iobus by parsing the XML output from the LDOM Manager.
+ *
+ * Input:
+ * xml doc - XML document to read (this will be an XML document for one ldom)
+ *
+ * Output (pointers are used to pass information from this function to the caller):
+ * num_cpu - pointer to the number of virtual cpu
+ * mem_size - pointer to the virtual memory size
+ * mem_unit - pointer to the virtual memory unit
+ * num_crypto - pointer to the number of crypto unit
+ * num_iobus - pointer to the number of io bus
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ * NOTE: Example XML document that this function will parse to get the ldom info:
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>list-constraints</action>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>primary</ldom_name>
+ * </ldom_info>
+ * <cpu>
+ * <number>4</number>
+ * </cpu>
+ * <mau>
+ * <number>1</number>
+ * </mau>
+ * <memory>
+ * <size>1G</size>
+ * </memory>
+ * <physio_device>
+ * <name>pci@780</name>
+ * </physio_device>
+ * </ldom>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </data>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </cmd>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </LDM_interface>
+ */
+int
+parse_xml_get_ldominfo(xmlDoc *doc, int *num_cpu, int *mem_size, int *mem_unit, int *num_crypto, int *num_iobus)
+{
+ int ret = 0;
+ xmlNodePtr root_node = NULL;
+ xmlNodePtr cmd_node = NULL;
+ xmlNodePtr data_node = NULL;
+ xmlNodePtr ldom_node = NULL;
+ xmlNodePtr cpu_node = NULL;
+ xmlNodePtr memory_node = NULL;
+ xmlNodePtr mau_node = NULL;
+ char *ldm_name = NULL;
+ xmlChar *content = NULL;
+
+ xmlNodePtr subnode;
+
+ long long num_cpu_xml = 0;
+ long long num_crypto_xml = 0;
+ long long num_iobus_xml = 0;
+
+ char *endp;
+ uint64_t size = 0;
+
+ *num_cpu = 0;
+ *mem_size = 0;
+ *num_crypto = 0;
+ *num_iobus = 0;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo(ENTER) \n");
+
+ root_node = xmlDocGetRootElement(doc);
+
+ if (parse_xml_get_response_status(root_node) == -1)
+ return(-1);
+
+ cmd_node = xml_find_subnode(root_node, XML_CMD);
+ if (cmd_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. XML file does not have <cmd> tag\n");
+ return (-1);
+ }
+
+ data_node = xml_find_subnode(cmd_node, XML_DATA);
+ if (data_node != NULL)
+ ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+ else {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. XML file does not have <data> tag\n");
+ return (ret);
+ }
+
+ if (ldom_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. XML file does not have <ldom> tag\n");
+ return (ret);
+ }
+
+ /* get number of cpu */
+ cpu_node = xml_find_subnode(ldom_node, CPU_NODE);
+ if (cpu_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. XML file does not have <cpu> tag\n");
+ num_cpu_xml = 0;
+ } else {
+ subnode = xml_find_subnode(cpu_node, NUMBER_NODE);
+ if (subnode == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. XML file does not have <number> tag within <cpu> tag\n");
+ num_cpu_xml = 0;
+ } else {
+
+ content = xmlNodeGetContent(subnode);
+
+ num_cpu_xml = strtoll((char *)content, NULL, 0);
+ if (num_cpu_xml <= 0) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. Invalid cpu num specified: %s\n", content);
+ }
+ xmlFree(content);
+ }
+ }
+
+
+ /* get memory size */
+ memory_node = xml_find_subnode(ldom_node, MEMORY_NODE);
+ if (memory_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. XML file does not have <memory> tag\n");
+ size = 0;
+ } else {
+ subnode = xml_find_subnode(memory_node, SIZE_NODE);
+ if (subnode == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. XML file does not have <size> tag within <memory> tag\n");
+ size = 0;
+ } else {
+
+ content = xmlNodeGetContent(subnode);
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldominfo.. mem_size = %s\n", content);
+
+ /* extract the number and unit from the content */
+ size = strtoull((char *)content, &endp, 0);
+ if (size > 0) {
+
+ /* get the memory unit */
+ /* Ldoms Manager CLI is using "bytes" as the default memory unit. */
+ *mem_unit = LDOMMEMUNIT_BYTES; /* use bytes as default */
+ switch (strlen(endp)) {
+ case 0: break;
+ default:
+ switch (endp[strlen(endp)-1]) {
+ case 'G':
+ case 'g':
+ *mem_unit = LDOMMEMUNIT_GIGABYTES;
+ break;
+ case 'M':
+ case 'm':
+ *mem_unit = LDOMMEMUNIT_MEGABYTES;
+ break;
+ case 'K':
+ case 'k':
+ *mem_unit = LDOMMEMUNIT_KILOBYTES;
+ break;
+ default:
+ *mem_unit = LDOMMEMUNIT_BYTES;
+ }
+ break;
+ }
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldominfo.. mem size unit = %s\n", endp);
+ } else {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. Invalid mem size specified: %s\n", content);
+ }
+ xmlFree(content);
+ }
+
+ }
+
+ /* get number of crypto */
+ mau_node = xml_find_subnode(ldom_node, MAU_NODE);
+ if (mau_node == NULL) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldominfo.. XML file does not have <mau> tag\n");
+ num_crypto_xml = 0;
+ } else {
+ subnode = xml_find_subnode(mau_node, NUMBER_NODE);
+ if (subnode == NULL) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldominfo.. XML file does not have <number> tag within <mau> tag\n");
+ num_crypto_xml = 0;
+ } else {
+
+ content = xmlNodeGetContent(subnode);
+ num_crypto_xml = strtoll((char *)content, NULL, 0);
+ if (num_crypto_xml <= 0) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldominfo.. Invalid crypto num specified: %s\n", content);
+ }
+ xmlFree(content);
+ }
+ }
+
+ /* get number of io bus */
+ num_iobus_xml = parse_xml_get_subnode_cnt(ldom_node, XML_PHYSIO_DEVICE);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldominfo.. number of <physio_device> tags =%d\n", num_iobus_xml);
+
+ *num_cpu = (int)num_cpu_xml;
+ *mem_size = (int)size;
+ *num_crypto = (int)num_crypto_xml;
+ *num_iobus = (int)num_iobus_xml;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo(EXIT)\n");
+
+ return (ret);
+}
+
+xmlNodePtr
+xmlFindSubnode(xmlNodePtr node, const xmlChar *name)
+{
+ xmlNodePtr subnode;
+
+ subnode = node->xmlChildrenNode;
+ while (subnode != NULL) {
+ if (xmlStrcmp(subnode->name, name) == 0)
+ break;
+ subnode = subnode->next;
+ }
+
+ return (subnode);
+}
+
+/*
+ * parse_xml_get_ldom_name
+ *
+ * This function find the <ldom_name> tag within the input xml document
+ * and return the LDom name in that tag, or NULL if the tag does not exist.
+ *
+ * Input:
+ * node - An xmlNodePtr to the xml data root node
+ *
+ * Output:
+ * A ptr to the LDom name (caller must free memory when done)
+ * NULL if no <ldom_name> tag or content is found
+ */
+char *
+parse_xml_get_ldom_name(xmlNodePtr node)
+{
+ char *ldomName = NULL;
+ xmlChar *content = NULL;
+ xmlNodePtr subnode;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_name(ENTER) \n");
+ if (ldoms_debug) dprt(" DBG: ENTER: nodeName=%s, nodeType=%d\n",node->name,node->type);
+
+ /* Find the <ldom_name> tag and get its content, which is the LDom name */
+ subnode = xmlFindSubnode(node, XML_CMD);
+ if (subnode != NULL) {
+ subnode = xmlFindSubnode(subnode, XML_DATA);
+ if (subnode != NULL) {
+ subnode = xmlFindSubnode(subnode, LDOM_NODE);
+ if (subnode != NULL) {
+ subnode = xmlFindSubnode(subnode, XML_LDM_INFO);
+ if (subnode != NULL) {
+ subnode = xmlFindSubnode(subnode, XML_LDM_NAME);
+ if (subnode != NULL) {
+ content = xmlNodeGetContent(subnode);
+ ldomName = strdup((const char *)content);
+ }
+ }
+ }
+ }
+ }
+
+
+ if (ldomName == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_name() XML file does not have <ldom_name> tag\n");
+ return(NULL);
+ }
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_name(EXIT) LDom Name = %s\n",ldomName);
+
+ return (ldomName);
+} /* parse_xml_get_ldom_name */
+
+/*
+ * parse_xml_get_ldom_state
+ *
+ * This function converts the ldom state to the enum value.
+ *
+ * Input:
+ * node - pointer to the xml node that contains the ldom state data
+ *
+ * Returns:
+ * following ldom state enum value if the operation is successful
+ * 1 = active LDOM_STATE_ACTIVE
+ * 2 = stopping LDOM_STATE_STOPPING
+ * 3 = inactive LDOM_STATE_INACTIVE
+ * 4 = binding LDOM_STATE_BINDING
+ * 5 = unbinding LDOM_STATE_UNBINDING
+ * 6 = bound LDOM_STATE_BOUND
+ * 7 = starting LDOM_STATE_STARTING
+ *
+ * -1 if the operation fails
+ *
+ */
+int
+parse_xml_get_ldom_state(xmlNodePtr node)
+{
+ xmlNodePtr state_node = NULL;
+ xmlChar *content = NULL;
+ int ldom_state = 0;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_state(ENTER)\n");
+ state_node = xml_find_subnode(node, STATE_NODE);
+ if (state_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_state.. XML file does not have <state> tag\n");
+ return (-1);
+ }
+
+ content = xmlNodeGetContent(state_node);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldom_state.. state=%s\n", content);
+
+ if (strcmp((char *)content, "active") == 0)
+ ldom_state = LDOM_STATE_ACTIVE;
+ else if (strcmp((char *)content, "stopping") == 0)
+ ldom_state = LDOM_STATE_STOPPING;
+ else if (strcmp((char *)content, "inactive") == 0)
+ ldom_state = LDOM_STATE_INACTIVE;
+ else if (strcmp((char *)content, "binding") == 0)
+ ldom_state = LDOM_STATE_BINDING;
+ else if (strcmp((char *)content, "unbinding") == 0)
+ ldom_state = LDOM_STATE_UNBINDING;
+ else if (strcmp((char *)content, "bound") == 0)
+ ldom_state = LDOM_STATE_BOUND;
+ else if (strcmp((char *)content, "starting") == 0)
+ ldom_state = LDOM_STATE_STARTING;
+
+ xmlFree(content);
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_state(EXIT): state=%d\n",ldom_state);
+ return(ldom_state);
+} /* parse_xml_get_ldom_state */
+
+
+/*
+ * parse_xml_get_response_status
+ *
+ * This function checks for the <response> <status> tags in the XML response.
+ * There are <response><status> tags associated with the document, <cmd> and
+ * <data> tags. This function is general to be able to check for
+ * <response><status> for any of these. If the <status> of the document is
+ * 'success', then the other <response><status> tags do not need to be checked.
+ *
+ * Input:
+ * node - pointer to the xml node to check the response status
+ *
+ * Returns:
+ * 0 if the response status is success
+ * -1 if the response status is failure or the operation fails
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>bind-domain</action>
+ * <data version="2.0">
+ * <response>
+ * <status>failure</status>
+ * <resp_msg>ldom does not have ldom_name tag</resp_msg>
+ * </response>
+ * </data>
+ * <response>
+ * <status>failure</status>
+ * </response>
+ * </cmd>
+ * <response>
+ * <status>failure</status>
+ * </response>
+ * </LDM_interface>
+ */
+int
+parse_xml_get_response_status(xmlNodePtr node)
+{
+ xmlNodePtr response_node = NULL;
+ xmlNodePtr status_node = NULL;
+ xmlNodePtr resp_msg_node = NULL;
+ xmlNodePtr cmd_node = NULL;
+ xmlNodePtr cmd_child_node = NULL;
+ xmlNodePtr data_child_node = NULL;
+ xmlNodePtr respmsg_node = NULL;
+ xmlChar *content = NULL;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_response_status(ENTER)\n");
+
+ response_node = xml_find_subnode(node, XML_RESPONSE);
+ if (response_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_response_status.. XML file does not have <response> tag\n");
+ return (-1);
+ }
+
+
+ status_node = xml_find_subnode(response_node, XML_STATUS);
+ if (status_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_response_status.. XML file does not have <status> tag within <response>\n");
+ return (-1);
+ }
+
+ content = xmlNodeGetContent(status_node);
+
+ /*
+ * The <status> tag must indicate 'success', otherwise we cannot process
+ * anymore or the XML response because there has been some type of error.
+ */
+ if (strcmp((char *)content, XML_SUCCESS) == 0) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_response_status() <response><status> is success\n");
+ xmlFree(content);
+ }
+
+ /* XML request failed, get the reason why, <resp_msg> */
+ else {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_response_status() <response><status>=%s\n", content);
+ xmlFree(content);
+ content = NULL;
+
+ /* response status is not success, get the response msg.
+ * The <resp_msg> tag is within the <data> tag, not the <cmd>
+ * or <LDM_interface> tags, so drill down to the first <data>
+ * tag and get the <response><resp_msg> tag contents to display
+ * in an error message
+ */
+
+ /*
+ * Get the <cmd> node first, then get a list of the child nodes.
+ * There can be multiple <data></data> nodes, which are peers,
+ * but usually there is only 1 <data> node, but code for multiple
+ */
+ cmd_node = xml_find_subnode(node, XML_CMD);
+ cmd_child_node = cmd_node->xmlChildrenNode;
+ while (cmd_child_node != NULL) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_response_status() <cmd> child=%s\n",cmd_child_node->name);
+ /* Is current child node a <data> */
+ if (strcmp((const char*)cmd_child_node->name,(const char*)XML_DATA) != 0) {
+ cmd_child_node = cmd_child_node->next;
+ continue;
+ }
+
+ /* Found a <data> node, so get the list of child nodes */
+ data_child_node = cmd_child_node->xmlChildrenNode;
+ while (data_child_node != NULL) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_response_status() <data> child=%s\n",data_child_node->name);
+ /* Is current child node a <response> */
+ if (strcmp((const char*)data_child_node->name,(const char*)XML_RESPONSE) != 0) {
+ data_child_node = data_child_node->next;
+ continue;
+ }
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_response_status() Found <response>\n");
+
+ /* Found a <response> node, so get the <resp_msg> node */
+ respmsg_node = xml_find_subnode(data_child_node, XML_RESP_MSG);
+ if (respmsg_node != NULL) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_response_status() Found <resp_msg>\n");
+ content = xmlNodeGetContent(respmsg_node);
+ if (content != NULL) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_response_status() <resp_msg>=%s\n", content);
+ cmd_child_node = NULL;
+ }
+ }
+ /* No more <response> nodes in the <data> node */
+ break;
+ }
+ }
+
+ if (content != NULL) {
+ ldomsError(NULL, NULL, VIR_ERR_OPERATION_FAILED, (const char*)content, VIR_ERR_ERROR);
+ xmlFree(content);
+ }
+ return (-1);
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_response_status(EXIT)\n");
+
+ return(0);
+} /* parse_xml_get_response_status */
+
+/*
+ * parse_xml_get_ldom_cnt
+ *
+ * This functions gets the number of ldoms from the input xml file
+ * by counting the <ldom> tags.
+ *
+ * Input:
+ * xml doc - XML document to read
+ *
+ * Output:
+ * ldom_cnt - number of ldoms
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ * NOTE:
+ * Each <ldom> tag comes within the <data> tag.
+ *
+ * Example XML output from the LDOM Manager for the "list-domain" request:
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>list-domain</action>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>primary</ldom_name>
+ * <state>active</state>
+ * </ldom_info>
+ * </ldom>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </data>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>ldg1</ldom_name>
+ * <state>bound</state>
+ * </ldom_info>
+ * </ldom>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </data>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>ldg3</ldom_name>
+ * <state>bound</state>
+ * </ldom_info>
+ * </ldom>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </data>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </cmd>
+ * <response>
+ * <status>success</status>
+ * </response>
+ * </LDM_interface>
+ *
+ * for the following LDOM Manager CLI output:
+ *
+ * # ldm list
+ * Name State Flags Cons VCPU Memory Util Uptime
+ * primary active -t-cv 4 1G 0.0% 0s
+ * ldg1 bound ----v 5000 4 1G
+ * ldg3 bound ----v 5001 4 1G
+ */
+int
+parse_xml_get_ldom_cnt(xmlDoc *doc, int *ldom_cnt)
+{
+ char *ldm_name = NULL;
+ int ret = 0;
+ int num_ldoms = 0;
+ xmlNodePtr root_node = NULL;
+ xmlNodePtr cmd_node = NULL;
+ xmlNodePtr data_node = NULL;
+ xmlNodePtr ldom_node = NULL;
+ xmlNodePtr response_node = NULL;
+ xmlNodePtr status_node = NULL;
+ xmlNodePtr subnode;
+ xmlChar *content = NULL;
+
+ *ldom_cnt = 0;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_cnt(ENTER)\n");
+
+ root_node = xmlDocGetRootElement(doc);
+
+ if (parse_xml_get_response_status(root_node) == -1)
+ return(-1);
+
+ cmd_node = xml_find_subnode(root_node, XML_CMD);
+ if (cmd_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_cnt.. XML file does not have <cmd> tag\n");
+ return (-1);
+ }
+
+ data_node = xml_find_subnode(cmd_node, XML_DATA);
+
+ /* We did not find a data section. No work can be done without this */
+ if (data_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_cnt.. XML file does not have <data> tag\n");
+ return (-1);
+ }
+
+ /*
+ * There will be a <data></data> tag pair for each <ldom><ldom_info> pair.
+ * We don't care about the <status> tags with the <data> tags becuase we
+ * already checked the outermost <status>
+ */
+ while (1) {
+
+ ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+
+ if (ldom_node != NULL) {
+ subnode = ldom_node->xmlChildrenNode;
+
+ while (subnode != NULL) {
+ if (subnode->type != XML_ELEMENT_NODE) {
+ subnode = subnode->next;
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldom_cnt.. found non-element node under <ldom_info> continue\n");
+ continue;
+ }
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldom_cnt.. found element node %s\n",subnode->name);
+
+ if (xmlStrcmp(subnode->name, (const xmlChar *)XML_LDM_INFO) == 0) {
+ subnode = subnode->next;
+ ++num_ldoms;
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldom_cnt.. found <ldom_info> ldom_cnt=%d\n", num_ldoms);
+
+ /* I think we can break at this point instead of continue. View the debug
+ to verify this. */
+ continue;
+ }
+ subnode = subnode->next;
+ }
+ }
+
+
+ /*
+ * xml response for list-domain has <data> tags for each ldom info,
+ * so get the next data section
+ */
+ data_node = xml_get_next_ele_node(data_node);
+
+ if (data_node == NULL)
+ break;
+ }
+
+ *ldom_cnt = num_ldoms;
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_cnt(EXIT): ldom_cnt=%d\n", num_ldoms);
+
+ return (ret);
+} /* parse_xml_get_ldom_cnt() */
+
+
+/*
+ * parse_xml_get_mem_rp
+ *
+ * This function gets the memory resource pool data (quantity and unit) by parsing the
+ * XML output from the LDOM Manager.
+ *
+ * Input:
+ * xml doc - XML document to read
+ * "list-devices" xml output for capacity data and
+ * "list-bindings" xml output for reserved data
+ * rp_type - indicates either capacity or reserved
+ * RP_CAPACITY = capacity resource
+ * RP_RESERVED = reserved resource
+ *
+ * Output (pointers are used to pass information from this function to the caller):
+ * rp_qty - pointer to the integer for the resource pool quantity
+ * unit - pointer to the allocation unit
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ * NOTE:
+ * This function will tally up the available (with <free> tags in the "list-devices"
+ * xml output) and reserved (with <binding> tags in the "list-bindings" xml output)
+ * for the memory resource pool.
+ *
+ * Example - portion of the XML document that this function will parse to get the
+ * memory resource pool info:
+ *
+ * for capacity resource:
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>list-devices</action>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>primary</ldom_name>
+ * </ldom_info>
+ * <memory>
+ * <free>
+ * <phys_addr>0xc4800000</phys_addr>
+ * <size>29624M</size>
+ * </free>
+ * </memory>
+ *..
+ * for reserved resource:
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>list-bindings</action>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>primary</ldom_name>
+ * </ldom_info>
+ * <memory>
+ * <size>1G</size>
+ * <binding>
+ * <real_addr>0x4000000</real_addr>
+ * <phys_addr>0x4000000</phys_addr>
+ * <size>1G</size>
+ * </binding>
+ * </memory>
+ * ...
+ *
+ */
+int
+parse_xml_get_mem_rp(xmlDoc *doc, int rp_type, ulong_t *rp_qty, int *unit)
+{
+ int ret = 0;
+ xmlNodePtr root_node = NULL;
+ xmlNodePtr cmd_node = NULL;
+ xmlNodePtr data_node = NULL;
+ xmlNodePtr ldom_node = NULL;
+ xmlNodePtr memory_node = NULL;
+ xmlNodePtr phys_addr_node = NULL;
+ xmlNodePtr size_node = NULL;
+ xmlChar *content = NULL;
+ xmlChar *search_tag;
+
+ xmlNodePtr subnode;
+
+ unsigned long long size = 0;
+ unsigned long long total_size = 0;
+
+ /* use GB as default, but change it to smaller unit if found */
+ int mem_unit = LDOMMEMUNIT_GIGABYTES ;
+ char *endp;
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp (ENTER) \n");
+
+ root_node = xmlDocGetRootElement(doc);
+
+ if (parse_xml_get_response_status(root_node) == -1)
+ return(-1);
+
+ /* for capacity, look for <free> tag and
+ * for reserved, look for <binding> tag */
+ if (rp_type == RP_CAPACITY)
+ search_tag = XML_FREE;
+ else
+ search_tag = XML_BINDING;
+
+ cmd_node = xml_find_subnode(root_node, XML_CMD);
+ if (cmd_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_mem_rp.. XML file does not have <cmd> tag\n");
+ return (-1);
+ }
+
+ data_node = xml_find_subnode(cmd_node, XML_DATA);
+ if (data_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_mem_rp.. XML file does not have <data> tag\n");
+ return (-1);
+ }
+
+ /* get capacity data from list-devices which does not have <ldom> tag
+ * and get reserved data from list-bindings which has <ldom> tag
+ */
+ if (rp_type == RP_RESERVED) {
+ ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+ if (ldom_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_mem_rp.. XML file does not have <ldom> tag\n");
+ return (-1);
+ }
+ }
+
+ while (1) {
+
+ if (rp_type == RP_CAPACITY)
+ memory_node = xml_find_subnode(data_node, MEMORY_NODE);
+ else
+ memory_node = xml_find_subnode(ldom_node, MEMORY_NODE);
+
+ if (memory_node == NULL) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. XML file does not have <mem> tag\n");
+ }
+
+ if (memory_node != NULL) {
+ subnode = memory_node->xmlChildrenNode;
+ while (subnode != NULL) {
+ if (subnode->type != XML_ELEMENT_NODE) {
+ subnode = subnode->next;
+ continue;
+ }
+
+ if (xmlStrcmp(subnode->name, search_tag) == 0) {
+
+ if (rp_type == 1)
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. <free>tag found\n");
+ else
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. <binding>tag found\n");
+
+
+ /* get phys addr data */
+ phys_addr_node = xml_find_subnode(subnode, XML_PHYS_ADDR);
+ if (phys_addr_node != NULL) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. <phys_addr>tag found\n");
+ content = xmlNodeGetContent(phys_addr_node);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. phys_addr=%s\n", content);
+ xmlFree(content);
+
+ }
+
+ /* get mem size data */
+ size_node = xml_find_subnode(subnode, SIZE_NODE);
+ if (size_node != NULL) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. <size>tag found\n");
+ content = xmlNodeGetContent(size_node);
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. size=%s\n", content);
+
+ /* extract the number and unit from the content */
+ /* and calculate memory size in the smallest unit - "bytes" */
+ size = strtoull((char *)content, &endp, 0);
+ if (size <= 0) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. Invalid mem size specified: %s\n", content);
+ }
+ xmlFree(content);
+
+ /* get the memory unit */
+ /* and calculate the size in "bytes" which is the possible smallest memory unit */
+ switch (strlen(endp)) {
+ case 0: break;
+ default:
+ switch (endp[strlen(endp)-1]) {
+ case 'G':
+ case 'g':
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. unit in GB\n");
+ size = size * MEM_GB_BYTES;
+ break;
+ case 'M':
+ case 'm':
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. unit in MB\n");
+ size = size * MEM_MB_BYTES;
+ /* if megabyates is the smallest unit used so far,
+ * change the mem_unit to "megabyates" */
+ if (mem_unit == LDOMMEMUNIT_GIGABYTES)
+ mem_unit = LDOMMEMUNIT_MEGABYTES;
+ break;
+ case 'K':
+ case 'k':
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. unit in KB\n");
+ size = size * MEM_KB_BYTES;
+ /* if kilobytes is the smallest unit used so far,
+ * change the mem_unit to "kilobytes" */
+ if ((mem_unit == LDOMMEMUNIT_GIGABYTES) ||
+ (mem_unit == LDOMMEMUNIT_MEGABYTES))
+ mem_unit = LDOMMEMUNIT_KILOBYTES;
+ break;
+ default:
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp..unit in bytes\n");
+ /* if no memory unit is specified, use the default unit "bytes",
+ * and set the smallest unit used to "bytes" */
+ mem_unit = LDOMMEMUNIT_BYTES;
+ break;
+ }
+ break;
+ }
+
+ /* add up each strand rp_qty to calculate the total rp_qty */
+ total_size = total_size + size;
+
+ if (ldoms_detailed_debug) dprt(
+ "LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. size=%llu total_size=%llu in bytes\n",
+ size, total_size);
+ }
+
+
+ subnode = subnode->next;
+ continue;
+ }
+
+ subnode = subnode->next;
+ }
+
+ }
+
+ /* xml response for list has <data> tags for each <ldom_info>
+ * so, get the next data section
+ */
+ data_node = xml_get_next_ele_node(data_node);
+
+ if (data_node == NULL)
+ break;
+
+ if (rp_type == RP_RESERVED) {
+ ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+ if (ldom_node == NULL) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. XML file does not have <ldom> tag\n");
+ break;
+ }
+ }
+
+ }
+
+
+
+ /* recalculate mem size using the selected unit which is smallest unit in use */
+ if (mem_unit == LDOMMEMUNIT_BYTES)
+ *rp_qty = total_size;
+ else if (mem_unit == LDOMMEMUNIT_KILOBYTES)
+ *rp_qty = total_size / MEM_KB_BYTES;
+ else if (mem_unit == LDOMMEMUNIT_MEGABYTES)
+ *rp_qty = total_size / MEM_MB_BYTES;
+ else if (mem_unit == LDOMMEMUNIT_GIGABYTES)
+ *rp_qty = total_size / MEM_GB_BYTES;
+
+ *unit = mem_unit;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_mem_rp(EXIT): size=%llu in unit=%d\n",
+ total_size, mem_unit);
+
+ return(0);
+
+} /* parse_xml_get_mem_rp */
+
+
+/*
+ * parse_xml_get_cpu_rp
+ *
+ * This function gets the total number of CPUs (either free or bound depending on
+ * the rp_type) by parsing the XML output from the LDOM Manager.
+ *
+ * XX - copied from the MIB code, but changed to retrieve the number of
+ * CPUs instead of the CPU resource pool quantity.
+ *
+ * Input:
+ * xml doc - XML document to read
+ * "list-devices" xml output for capacity data and
+ * "list-bindings" xml output for reserved data
+ * rp_type - indicates either capacity or reserved
+ * RP_CAPACITY = capacity resource
+ * RP_RESERVED = reserved resource
+ *
+ * Output (pointers are used to pass information from this function to the caller):
+ * rp_qty - pointer to the integer for the number of CPUs
+ * unit - pointer to the allocation unit (always using 1 for Mhz)
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ * NOTE:
+ * This function will tally up the number of free (with <free> tags in the "list-devices"
+ * xml output) and reserved (with <binding> tags in the "list-bindings" xml output) CPUs.
+ *
+ * Example - portion of the XML document that this function will parse to get the
+ * CPU resource pool info:
+ *
+ * for capacity resource:
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>list-devices</action>
+ * <data version="2.0">
+ * <cpu>
+ * <free>
+ * <pid>12</pid>
+ * <strand_percent>100</strand_percent>
+ * </free>
+ * <free>
+ * <pid>13</pid>
+ * <strand_percent>100</strand_percent>
+ * </free>
+ *..
+ *..
+ * for reserved resource:
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>list-bindings</action>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>primary</ldom_name>
+ * </ldom_info>
+ * <cpu>
+ * <number>4</number>
+ * <binding>
+ * <vid>0</vid>
+ * <pid>0</pid>
+ * <strand_percent>100</strand_percent>
+ * </binding>
+ * ...
+ *
+ */
+int
+parse_xml_get_cpu_rp(xmlDoc *doc, int rp_type, ulong_t *rp_qty, int *unit)
+{
+ int ret = 0;
+ xmlNodePtr root_node = NULL;
+ xmlNodePtr cmd_node = NULL;
+ xmlNodePtr data_node = NULL;
+ xmlNodePtr ldom_node = NULL;
+ xmlNodePtr cpu_node = NULL;
+ xmlNodePtr pid_node = NULL;
+ xmlNodePtr strand_percent_node = NULL;
+ xmlChar *content = NULL;
+ xmlChar *search_tag;
+
+ xmlNodePtr subnode;
+
+ ulong_t strand_rp_qty = 0;
+ ulong_t total_rp_qty = 0;
+
+ int cpu_unit = 1; /* default MHz */
+
+ int ncpu = 0;
+
+ /*
+ * Get the processor clock speed using processor_info()
+ * which takes processor id as input and returns the status of
+ * the processor in the processor_info_t structure.
+ *
+ * The pi_clock member is the processor clock frequency rounded
+ * to the nearest MHz. It may be 0 if not known.
+ *
+ * Since processor_info doesn't provide the guest domain's
+ * processor info, we just need to find a CPU on the control
+ * domain, but we don't know which physical CPUs the control
+ * domain has. So just loop on the 1st 64, which should contain
+ * at least 1 CPU in the control domain.
+ */
+ processor_info_t cpu_info;
+ int pid = 0; /* use primary domain's processor id */
+ int p_clock = 1600; /* processor clock speed in MHz */
+ /* use 1600 MHz as default */
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_rp(ENTER)\n");
+
+
+ /* get the processor clock speed in MHz */
+ while ((pid < 64) && (processor_info(pid++, &cpu_info) != 0) );
+
+ /* get the processor clock speed in MHz */
+ if (pid <= 64) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsNodeGetInfo(). processor_info with pid=%d clock=%d\n",
+ pid, cpu_info.pi_clock);
+ p_clock = cpu_info.pi_clock;
+ }
+
+ root_node = xmlDocGetRootElement(doc);
+
+ if (parse_xml_get_response_status(root_node) == -1)
+ return(-1);
+
+ /* for capacity, look for <free> tag and
+ * for reserved, look for <binding> tag */
+ if (rp_type == 1)
+ search_tag = XML_FREE;
+ else
+ search_tag = XML_BINDING;
+
+ cmd_node = xml_find_subnode(root_node, XML_CMD);
+ if (cmd_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_rp.. XML file does not have <cmd> tag\n");
+ return (-1);
+ }
+
+ data_node = xml_find_subnode(cmd_node, XML_DATA);
+ if (data_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_rp.. XML file does not have <data> tag\n");
+ return (-1);
+ }
+
+ /* get capacity data from list-devices which does not have <ldom> tag
+ * and get reserved data from list-bindings which has <ldom> tag
+ */
+ if (rp_type == RP_RESERVED) {
+ ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+ if (ldom_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_rp.. XML file does not have <ldom> tag\n");
+ return (-1);
+ }
+ }
+
+ while (1) {
+
+ if (rp_type == RP_CAPACITY)
+ cpu_node = xml_find_subnode(data_node, CPU_NODE);
+ else
+ cpu_node = xml_find_subnode(ldom_node, CPU_NODE);
+
+ if (cpu_node == NULL) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_cpu_rp.. XML file does not have <cpu> tag\n");
+ }
+
+ if (cpu_node != NULL) {
+
+ subnode = cpu_node->xmlChildrenNode;
+ while (subnode != NULL) {
+ if (subnode->type != XML_ELEMENT_NODE) {
+ subnode = subnode->next;
+ continue;
+ }
+
+
+ if (xmlStrcmp(subnode->name, search_tag) == 0) {
+
+ if (rp_type == RP_CAPACITY)
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_cpu_rp.. <free>tag found\n");
+ else
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_cpu_rp.. <binding>tag found\n");
+
+ /* add up the number of CPUs */
+ ncpu++;
+
+
+ subnode = subnode->next;
+ continue;
+ }
+
+ subnode = subnode->next;
+ }
+
+ }
+
+
+ /* xml response for list has <data> tags for each <ldom_info>
+ * so, get the next data section
+ */
+ data_node = xml_get_next_ele_node(data_node);
+
+ if (data_node == NULL)
+ break;
+
+ if (rp_type == RP_RESERVED) {
+ ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+ if (ldom_node == NULL) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_cpu_rp.. XML file does not have <ldom> tag\n");
+ break;
+ }
+ }
+
+ }
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_rp(EXIT): total number of CPUs=%d frequency (in Mhz)=%d\n", ncpu, p_clock);
+
+ *rp_qty = ncpu;
+ *unit = cpu_unit;
+
+ return(0);
+} /* parse_xml_get_cpu_rp */
+
+/*
+ * parse_xml_get_cpu_bindings
+ *
+ * This function gets the CPU binding info for a domain.
+ * Specifically, the real and virtual CPU ids, the State for the CPU,
+ * and the CPU uptime, which is pretty much the same as the uptime of
+ * the Domain.
+ *
+ * Input:
+ * xml_received - XML document to read
+ * cpuBindings - Pointer to a structure to hold the binding info
+ *
+ * Output
+ * cpuBindings - Pointer to a structure with the binding info
+ *
+ * Returns:
+ * 0 if the operation is successful
+ * -1 if the operation fails
+ *
+ * Example XML response from a list-bindings request for a domain
+ * <LDM_interface version="1.0">
+ * <cmd>
+ * <action>list-bindings</action>
+ * <data version="2.0">
+ * <ldom>
+ * <ldom_info>
+ * <ldom_name>primary</ldom_name>
+ * </ldom_info>
+ * <cpu>
+ * <number>4</number>
+ * <binding>
+ * <vid>0</vid>
+ * <pid>0</pid>
+ * <strand_percent>100</strand_percent>
+ * </binding>
+ * ...
+ *
+ */
+int
+parse_xml_get_cpu_bindings(xmlDoc *doc, cpuBindings_t **cpuBindings)
+{
+ cpuBindings_t *headcpuBindings = NULL;
+ cpuBindings_t *newBinding = NULL;
+ cpuBindings_t *prevBinding = NULL;
+
+ xmlNodePtr root_node = NULL;
+ xmlNodePtr cmd_node = NULL;
+ xmlNodePtr data_node = NULL;
+ xmlNodePtr ldom_node = NULL;
+ xmlNodePtr cpu_node = NULL;
+ xmlNodePtr id_node = NULL;
+ xmlChar *virtID = NULL;
+ xmlChar *realID = NULL;
+ xmlNodePtr subnode;
+
+ int ret = 0;
+ int numCpus = 0;
+ int ncpu = 0;
+
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_bindings(ENTER)\n");
+ root_node = xmlDocGetRootElement(doc);
+
+ if (parse_xml_get_response_status(root_node) == -1) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_bindings() no response/status tags in the XML rsp\n");
+ return(-1);
+ }
+
+ cmd_node = xml_find_subnode(root_node, XML_CMD);
+ if (cmd_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_bindings() XML file does not have <cmd> tag\n");
+ return (-1);
+ }
+
+ data_node = xml_find_subnode(cmd_node, XML_DATA);
+ if (data_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_bindings() XML file does not have <data> tag\n");
+ return (-1);
+ }
+
+ ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+ if (ldom_node == NULL) {
+ if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_bindings() XML file does not have <ldom> tag\n");
+ return (-1);
+ }
+
+ cpu_node = xml_find_subnode(ldom_node, CPU_NODE);
+
+ if (cpu_node == NULL) {
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_cpu_bindings() XML file does not have <cpu> tag\n");
+ return(-1);
+ }
+
+ subnode = cpu_node->xmlChildrenNode;
+ while (subnode != NULL) {
+
+ if (xmlStrcmp(subnode->name, XML_BINDING) == 0) {
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_cpu_bindings() <binding>tag found\n");
+
+
+ /* Allocate a new cpuBindings struct to hold the info for the binding.
+ * This is regular single linked list stuff.
+ */
+ if (headcpuBindings == NULL) {
+ newBinding = malloc(sizeof(cpuBindings_t));
+ headcpuBindings = newBinding;
+ prevBinding = newBinding;
+ newBinding->next = NULL;
+ }
+ else {
+ newBinding = malloc(sizeof(cpuBindings_t));
+ prevBinding->next = newBinding;
+ newBinding->next = NULL;
+ prevBinding = newBinding;
+ }
+
+ /* Get the <vid> node and its value. subnode points to <binding> */
+ id_node = subnode->xmlChildrenNode;
+ virtID = xmlNodeGetContent(id_node);
+ newBinding->virt = (unsigned int)atoi((const char *)virtID);
+ xmlFree(virtID);
+
+ /* Get the <pid> node and its value */
+ id_node = id_node->next;
+ realID = xmlNodeGetContent(id_node);
+ newBinding->real = (int)atoi((const char *)realID);
+ xmlFree(realID);
+
+ if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_cpu_bindings() virt/real = %d/%d \n",newBinding->virt, newBinding->real);
+
+ numCpus++;
+
+ }
+
+ subnode = subnode->next;
+ } /* while */
+
+ *cpuBindings = headcpuBindings;
+ return(numCpus);
+} /* parse_xml_get_cpu_bindings */
+
+
+#endif /* WITH_LDOMS */
+
+/*
+ * vim: set tabstop=4:
+ * vim: set shiftwidth=4:
+ * vim: set expandtab:
+ */
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
+
7
37
This patch allows the lxc driver to handle SIGCHLD signals from exiting
containers. The handling will perform some cleanup such as waiting for
the container process and killing/waiting the tty process. This is also
required as a first step towards providing some kind of client container exit
notification. Additional support is needed for that but this SIGCHLD handling
is what would trigger the notification.
libvirtd was already catching SIGCHLD although it was just ignoring it. I
implemented a mechanism to distribute the signal to any other drivers in the
daemon that registered a function to handle them. This required some changes to
the way libvirtd was catching signals (to get the pid of the sending process) as
well as an addition to the state driver structure. The intent was to provide
future drivers access to signals as well.
--
Best Regards,
Dave Leskovec
IBM Linux Technology Center
Open Virtualization
3
10
07 May '08
The attached patch fills in two of the vcpu functions for the qemu driver:
virDomainSetVcpus : set the number of vcpus the domain can use
virDomainGetMaxVcpus : max number of vcpus that can be assigned to the domain.
Code change is only in qemu_driver, as the backend stuff was already in place.
I also edited qemudGetMaxVcpus to ignore case when checking the passed OS
type, since it wasn't matching the returned results of qemudDomainGetOSType.
Thanks,
Cole
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index b65ae66..8bedf5a 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -113,6 +113,8 @@ static int qemudShutdownNetworkDaemon(virConnectPtr conn,
struct qemud_driver *driver,
struct qemud_network *network);
+static int qemudDomainGetMaxVcpus(virDomainPtr dom);
+
static struct qemud_driver *qemu_driver = NULL;
@@ -1524,21 +1526,23 @@ static const char *qemudGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
return "QEMU";
}
-static int qemudGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED,
- const char *type) {
+static int qemudGetMaxVCPUs(virConnectPtr conn, const char *type) {
if (!type)
return 16;
- if (!strcmp(type, "qemu"))
+ if (!strcasecmp(type, "qemu"))
return 16;
/* XXX future KVM will support SMP. Need to probe
kernel to figure out KVM module version i guess */
- if (!strcmp(type, "kvm"))
+ if (!strcasecmp(type, "kvm"))
return 1;
- if (!strcmp(type, "kqemu"))
+ if (!strcasecmp(type, "kqemu"))
return 1;
+
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_ARG,
+ _("unknown type '%s'"), type);
return -1;
}
@@ -2122,6 +2126,66 @@ static int qemudDomainSave(virDomainPtr dom,
}
+static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
+ struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
+ struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ int max;
+
+ if (!vm) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+ _("no domain with matching uuid '%s'"), dom->uuid);
+ return -1;
+ }
+
+ if (qemudIsActiveVM(vm)) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot change vcpu count of an active domain"));
+ return -1;
+ }
+
+ if ((max = qemudDomainGetMaxVcpus(dom)) < 0) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("could not determine max vcpus for the domain"));
+ return -1;
+ }
+
+ if (nvcpus > max) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
+ _("requested vcpus is greater than max allowable"
+ " vcpus for the domain: %d > %d"), nvcpus, max);
+ return -1;
+ }
+
+ vm->def->vcpus = nvcpus;
+ return 0;
+}
+
+static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
+ struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
+ struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ char *type;
+ int ret;
+
+ if (!vm) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+ _("no domain with matching uuid '%s'"), dom->uuid);
+ return -1;
+ }
+
+ if (!(type = qemudDomainGetOSType(dom))) {
+ return -1;
+ }
+
+ if ((ret = qemudGetMaxVCPUs(dom->conn, vm->def->virtType)) < 0) {
+ free(type);
+ return -1;
+ }
+
+ free(type);
+ return ret;
+}
+
+
static int qemudDomainRestore(virConnectPtr conn,
const char *path) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
@@ -3042,10 +3106,10 @@ static virDriver qemuDriver = {
qemudDomainSave, /* domainSave */
qemudDomainRestore, /* domainRestore */
NULL, /* domainCoreDump */
- NULL, /* domainSetVcpus */
+ qemudDomainSetVcpus, /* domainSetVcpus */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
- NULL, /* domainGetMaxVcpus */
+ qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */
qemudDomainDumpXML, /* domainDumpXML */
qemudListDefinedDomains, /* listDomains */
qemudNumDefinedDomains, /* numOfDomains */
6
8
I seem to be completely unable to get make syntax-checks to function
properly with my bzr checkout of libvirt[1]. I've attached the output as
as-is.txt. I tried adding hacking bzr support into vc-list-files (see
vc-list-files-bzr.patch), but that didn't quite seem to do the trick, as
you can see in in vc-list-files-maybe-fixed.log, which is the output
after I patched vc-list-files.
I tried CVS, too, and that also fails (see cvs-syntax-check.log).
Is it only meant to work with git?
[1]: http://bazaar.launchpad.net/~vcs-imports/libvirt/trunk
--
Soren Hansen |
Virtualisation specialist | Ubuntu Server Team
Canonical Ltd. | http://www.ubuntu.com/
5
11
I have just changed the mailing list subject line prefix from '[libvir] '
to '[libvirt] ', so if anyone is using that for filtering you'll need to
update...
Dan.
--
|: Red Hat, Engineering, Boston -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 :|
1
0
Currently in Xen it is very easy to prototype a certain function related
to binding host hardware to virtual hardware. The script gets an argument,
can do anything it wants and returns another argument, or better: writes
it to the xen-store.
I was reviewing the current iSCSI code, because I cannot switch to libvirt
with the current implementation. (From OpenSolaris, I migrated to NetApp.)
So I pose a simple request: would anyone be able to create a xen-like
storage backend that in principle passes the URI to a script (that runs as
a fork) this script sets for example an envirionment variable or text
output, the code uses this envirionment variable as path to the storage
area. And a great prototypable system has been created.
It could be a question by some: 'why doesn't he write a simple
implementation in C?' basically: I'll will do this, no worries about that
one, but I would like to be able to prototype my programs first.
Is there anyone who wants to spend a few hours on this simple request, or
could someone tell me what he/she doesn't like about setting the
environment? Other solutions are ofcourse possible.
Waiting for your comments,
Stefan de Konink
2
13
05 May '08
iptables resides in /usr/sbin on SuSE distros. Add it to path when
searching for iptables.
Regards,
Jim
2
1
02 May '08
On Sun, Apr 27, 2008 at 02:57:54PM +0200, Geert Jansen wrote:
> I think it would be nice if it were possible to create a virtual network
> with virt-manager without DHCP and DNS services. This is useful when you
> want to use a host-only network for testing a setup that includes a DHCP
> server.
>
> I am not sure whether this is a limitation in virt-manager or in libvirt.
It's a libvirt thing. Replies redirected to libvir-list.
My understanding is that if the network doesn't contain a <ip...>
element in the network XML then no DHCP server will be created.
http://libvirt.org/formatnetwork.html
Rich.
--
Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones
virt-p2v converts physical machines to virtual machines. Boot with a
live CD or over the network (PXE) and turn machines into Xen guests.
http://et.redhat.com/~rjones/virt-p2v
2
1
Hi Dan,
I updated today to the latest CVS and can no longer connect to the lxc driver.
I've tracked it down to this check in doRemoteOpen() in remote_internal.c:
if ((
#ifdef HAVE_XMLURI_QUERY_RAW
uri->query_raw =
#else
uri->query =
#endif
qparam_get_query (vars)) == NULL) goto failed;
Looking at the recent VirBuffer changes, it looks like they changed the behavior
of qparam_get_query. With the old VirBuffer, qparam_get_query returned a
non-NULL result because virBufferNew allocated space. The new VirBuffer doesn't
allocate space until something is added and hence this function returns NULL if
nothing is ever put in the buffer. I'm not familiar enough with the intended
behavior to know what the fix should be here.
Thanks!
--
Best Regards,
Dave Leskovec
IBM Linux Technology Center
Open Virtualization
2
3
Daniel Berrange noticed some build problems on RHEL5.
Some were due to my not adding two .m4 files in yesterday's
gnulib update. [excuse time ;-) Normally (in other projects),
the gnulib-update process is automatic, since the imported files
are not version-controlled, but for libvirt I have to identify
new files pulled in by a gnulib update, and obviously didn't
complete that step.
Identifying and adding added files is not hard. Just have to remember
to do it before committing anything. Actually, the trick is (as usual)
to *automate* the process, so we don't have to depend on my memory.
This is now on my list.
Anyhow, I've committed the change.
3
4
[Libvir] PATCH: Support network interface model in Xen and QEMU driver
by Daniel P. Berrange 01 May '08
by Daniel P. Berrange 01 May '08
01 May '08
This patch finishes off the work from Rich / Soren to support network
interface model in both Xen and QEMU drivers, and adds test cases for
the new syntax
src/qemu_conf.c | 57 ++++++++++++++++++--
src/qemu_conf.h | 2
src/xend_internal.c | 7 ++
src/xm_internal.c | 22 +++++++
src/xml.c | 8 ++
tests/qemuxml2argvdata/qemuxml2argv-net-virtio.args | 1
tests/qemuxml2argvdata/qemuxml2argv-net-virtio.xml | 26 +++++++++
tests/qemuxml2argvtest.c | 1
tests/qemuxml2xmltest.c | 1
tests/sexpr2xmldata/sexpr2xml-net-e1000.sexpr | 2
tests/sexpr2xmldata/sexpr2xml-net-e1000.xml | 32 +++++++++++
tests/sexpr2xmltest.c | 1
tests/testutils.c | 31 ++++++----
tests/xmconfigdata/test-paravirt-net-e1000.cfg | 12 ++++
tests/xmconfigdata/test-paravirt-net-e1000.xml | 28 +++++++++
tests/xmconfigtest.c | 1
tests/xml2sexprdata/xml2sexpr-net-e1000.sexpr | 1
tests/xml2sexprdata/xml2sexpr-net-e1000.xml | 30 ++++++++++
tests/xml2sexprtest.c | 1
19 files changed, 247 insertions(+), 17 deletions(-)
Dan.
Index: src/qemu_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_conf.c,v
retrieving revision 1.50
diff -u -p -r1.50 qemu_conf.c
--- src/qemu_conf.c 28 Apr 2008 15:14:59 -0000 1.50
+++ src/qemu_conf.c 29 Apr 2008 17:15:31 -0000
@@ -718,6 +718,7 @@ static int qemudParseInterfaceXML(virCon
xmlChar *script = NULL;
xmlChar *address = NULL;
xmlChar *port = NULL;
+ xmlChar *model = NULL;
net->type = QEMUD_NET_USER;
@@ -779,6 +780,8 @@ static int qemudParseInterfaceXML(virCon
(net->type == QEMUD_NET_ETHERNET) &&
xmlStrEqual(cur->name, BAD_CAST "script")) {
script = xmlGetProp(cur, BAD_CAST "path");
+ } else if (xmlStrEqual (cur->name, BAD_CAST "model")) {
+ model = xmlGetProp (cur, BAD_CAST "type");
}
}
cur = cur->next;
@@ -938,6 +941,39 @@ static int qemudParseInterfaceXML(virCon
xmlFree(address);
}
+ /* NIC model (see -net nic,model=?). We only check that it looks
+ * reasonable, not that it is a supported NIC type. FWIW kvm
+ * supports these types as of April 2008:
+ * i82551 i82557b i82559er ne2k_pci pcnet rtl8139 e1000 virtio
+ */
+ if (model != NULL) {
+ int i, len, char_ok;
+
+ len = xmlStrlen (model);
+ if (len >= QEMUD_MODEL_MAX_LEN) {
+ qemudReportError (conn, NULL, NULL, VIR_ERR_INVALID_ARG,
+ _("Model name '%s' is too long"), model);
+ goto error;
+ }
+ for (i = 0; i < len; ++i) {
+ char_ok =
+ (model[i] >= '0' && model[i] <= '9') ||
+ (model[i] >= 'a' && model[i] <= 'z') ||
+ (model[i] >= 'A' && model[i] <= 'Z') || model[i] == '_';
+ if (!char_ok) {
+ qemudReportError (conn, NULL, NULL, VIR_ERR_INVALID_ARG,
+ _("Model name contains invalid characters"));
+ goto error;
+ }
+ }
+ strncpy (net->model, (const char*) model, len);
+ net->model[len] = '\0';
+
+ xmlFree (model);
+ model = NULL;
+ } else
+ net->model[0] = '\0';
+
return 0;
error:
@@ -953,6 +989,8 @@ static int qemudParseInterfaceXML(virCon
xmlFree(script);
if (bridge)
xmlFree(bridge);
+ if (model)
+ xmlFree(model);
return -1;
}
@@ -2283,13 +2321,22 @@ int qemudBuildCommandLine(virConnectPtr
} else {
int vlan = 0;
while (net) {
+ char model[100];
char nic[100];
- if (snprintf(nic, sizeof(nic), "nic,macaddr=%02x:%02x:%02x:%02x:%02x:%02x,vlan=%d",
+ if (net->model[0] != '\0') {
+ if (snprintf (model, sizeof (model), ",model=%s", net->model)
+ >= sizeof (model))
+ goto error;
+ } else
+ model[0] = '\0';
+
+ if (snprintf(nic, sizeof(nic),
+ "nic,macaddr=%02x:%02x:%02x:%02x:%02x:%02x,vlan=%d%s",
net->mac[0], net->mac[1],
net->mac[2], net->mac[3],
net->mac[4], net->mac[5],
- vlan) >= sizeof(nic))
+ vlan, model) >= sizeof(nic))
goto error;
if (!((*argv)[++n] = strdup("-net")))
@@ -3411,7 +3458,6 @@ static int qemudGenerateXMLChar(virBuffe
virBufferVSprintf(buf, " <source mode='connect' service='%s'/>\n",
dev->srcData.udp.connectService);
}
-
break;
case QEMUD_CHR_SRC_TYPE_TCP:
@@ -3625,6 +3671,11 @@ char *qemudGenerateXML(virConnectPtr con
net->dst.socket.port);
}
+ if (net->model && net->model[0] != '\0') {
+ virBufferVSprintf(&buf, " <model type='%s'/>\n",
+ net->model);
+ }
+
virBufferAddLit(&buf, " </interface>\n");
net = net->next;
Index: src/qemu_conf.h
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_conf.h,v
retrieving revision 1.23
diff -u -p -r1.23 qemu_conf.h
--- src/qemu_conf.h 25 Apr 2008 20:46:13 -0000 1.23
+++ src/qemu_conf.h 29 Apr 2008 17:15:32 -0000
@@ -68,6 +68,7 @@ struct qemud_vm_disk_def {
};
#define QEMUD_MAC_ADDRESS_LEN 6
+#define QEMUD_MODEL_MAX_LEN 10
#define QEMUD_OS_TYPE_MAX_LEN 10
#define QEMUD_OS_ARCH_MAX_LEN 10
#define QEMUD_OS_MACHINE_MAX_LEN 10
@@ -97,6 +98,7 @@ enum qemud_vm_net_forward_type {
struct qemud_vm_net_def {
int type;
unsigned char mac[QEMUD_MAC_ADDRESS_LEN];
+ char model[QEMUD_MODEL_MAX_LEN];
union {
struct {
char ifname[BR_IFNAME_MAXLEN];
Index: src/xend_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xend_internal.c,v
retrieving revision 1.182
diff -u -p -r1.182 xend_internal.c
--- src/xend_internal.c 28 Apr 2008 15:14:59 -0000 1.182
+++ src/xend_internal.c 29 Apr 2008 17:15:34 -0000
@@ -1893,9 +1893,10 @@ xend_parse_sexp_desc(virConnectPtr conn,
free(drvName);
free(drvType);
} else if (sexpr_lookup(node, "device/vif")) {
- const char *tmp2;
+ const char *tmp2, *model;
tmp2 = sexpr_node(node, "device/vif/script");
tmp = sexpr_node(node, "device/vif/bridge");
+ model = sexpr_node(node, "device/vif/model");
if ((tmp2 && strstr(tmp2, "bridge")) || tmp) {
virBufferAddLit(&buf, " <interface type='bridge'>\n");
if (tmp != NULL)
@@ -1924,6 +1925,10 @@ xend_parse_sexp_desc(virConnectPtr conn,
virBufferVSprintf(&buf, " <script path='%s'/>\n",
tmp2);
+ if (model)
+ virBufferVSprintf(&buf, " <model type='%s'/>\n",
+ model);
+
virBufferAddLit(&buf, " </interface>\n");
vif_index++;
} else if (sexpr_lookup(node, "device/vfb")) {
Index: src/xm_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xm_internal.c,v
retrieving revision 1.72
diff -u -p -r1.72 xm_internal.c
--- src/xm_internal.c 28 Apr 2008 15:14:59 -0000 1.72
+++ src/xm_internal.c 29 Apr 2008 17:15:37 -0000
@@ -845,6 +845,7 @@ char *xenXMDomainFormatXML(virConnectPtr
while (list) {
int type = -1;
char script[PATH_MAX];
+ char model[10];
char ip[16];
char mac[18];
char bridge[50];
@@ -854,6 +855,7 @@ char *xenXMDomainFormatXML(virConnectPtr
mac[0] = '\0';
script[0] = '\0';
ip[0] = '\0';
+ model[0] = '\0';
if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
goto skipnic;
@@ -886,6 +888,12 @@ char *xenXMDomainFormatXML(virConnectPtr
len = PATH_MAX-1;
strncpy(script, data, len);
script[len] = '\0';
+ } else if (!strncmp(key, "model=", 6)) {
+ int len = nextkey ? (nextkey - data) : sizeof(model)-1;
+ if (len > (sizeof(model)-1))
+ len = sizeof(model)-1;
+ strncpy(model, data, len);
+ model[len] = '\0';
} else if (!strncmp(key, "ip=", 3)) {
int len = nextkey ? (nextkey - data) : 15;
if (len > 15)
@@ -915,6 +923,8 @@ char *xenXMDomainFormatXML(virConnectPtr
virBufferVSprintf(&buf, " <script path='%s'/>\n", script);
if (ip[0])
virBufferVSprintf(&buf, " <ip address='%s'/>\n", ip);
+ if (model[0])
+ virBufferVSprintf(&buf, " <model type='%s'/>\n", model);
virBufferAddLit(&buf, " </interface>\n");
skipnic:
@@ -1777,6 +1787,7 @@ static char *xenXMParseXMLVif(virConnect
xmlChar *source = NULL;
xmlChar *mac = NULL;
xmlChar *script = NULL;
+ xmlChar *model = NULL;
xmlChar *ip = NULL;
int typ = 0;
char *buf = NULL;
@@ -1808,6 +1819,9 @@ static char *xenXMParseXMLVif(virConnect
} else if ((mac == NULL) &&
(xmlStrEqual(cur->name, BAD_CAST "mac"))) {
mac = xmlGetProp(cur, BAD_CAST "address");
+ } else if ((model == NULL) &&
+ (xmlStrEqual(cur->name, BAD_CAST "model"))) {
+ model = xmlGetProp(cur, BAD_CAST "type");
} else if ((ip == NULL) &&
(xmlStrEqual(cur->name, BAD_CAST "ip"))) {
ip = xmlGetProp(cur, BAD_CAST "address");
@@ -1843,6 +1857,8 @@ static char *xenXMParseXMLVif(virConnect
buflen += 11;
if (script)
buflen += 8 + strlen((const char*)script);
+ if (model)
+ buflen += 7 + strlen((const char*)model);
if (ip)
buflen += 4 + strlen((const char*)ip);
@@ -1870,6 +1886,10 @@ static char *xenXMParseXMLVif(virConnect
strcat(buf, ",script=");
strcat(buf, (const char*)script);
}
+ if (model) {
+ strcat(buf, ",model=");
+ strcat(buf, (const char*)model);
+ }
if (ip) {
strcat(buf, ",ip=");
strcat(buf, (const char*)ip);
@@ -1883,6 +1903,8 @@ static char *xenXMParseXMLVif(virConnect
xmlFree(source);
if (script != NULL)
xmlFree(script);
+ if (model != NULL)
+ xmlFree(model);
if (ip != NULL)
xmlFree(ip);
Index: src/xml.c
===================================================================
RCS file: /data/cvs/libvirt/src/xml.c,v
retrieving revision 1.119
diff -u -p -r1.119 xml.c
--- src/xml.c 28 Apr 2008 15:14:59 -0000 1.119
+++ src/xml.c 29 Apr 2008 17:15:38 -0000
@@ -1378,6 +1378,7 @@ virDomainParseXMLIfDesc(virConnectPtr co
xmlChar *source = NULL;
xmlChar *mac = NULL;
xmlChar *script = NULL;
+ xmlChar *model = NULL;
xmlChar *ip = NULL;
int typ = 0;
int ret = -1;
@@ -1409,6 +1410,9 @@ virDomainParseXMLIfDesc(virConnectPtr co
} else if ((script == NULL) &&
(xmlStrEqual(cur->name, BAD_CAST "script"))) {
script = xmlGetProp(cur, BAD_CAST "path");
+ } else if ((model == NULL) &&
+ (xmlStrEqual(cur->name, BAD_CAST "model"))) {
+ model = xmlGetProp(cur, BAD_CAST "type");
} else if ((ip == NULL) &&
(xmlStrEqual(cur->name, BAD_CAST "ip"))) {
/* XXX in future expect to need to have > 1 ip
@@ -1454,6 +1458,8 @@ virDomainParseXMLIfDesc(virConnectPtr co
}
if (script != NULL)
virBufferVSprintf(buf, "(script '%s')", script);
+ if (model != NULL)
+ virBufferVSprintf(buf, "(model '%s')", model);
if (ip != NULL)
virBufferVSprintf(buf, "(ip '%s')", ip);
/*
@@ -1474,6 +1480,8 @@ virDomainParseXMLIfDesc(virConnectPtr co
xmlFree(script);
if (ip != NULL)
xmlFree(ip);
+ if (model != NULL)
+ xmlFree(model);
return (ret);
}
Index: tests/qemuxml2argvtest.c
===================================================================
RCS file: /data/cvs/libvirt/tests/qemuxml2argvtest.c,v
retrieving revision 1.15
diff -u -p -r1.15 qemuxml2argvtest.c
--- tests/qemuxml2argvtest.c 25 Apr 2008 20:46:13 -0000 1.15
+++ tests/qemuxml2argvtest.c 29 Apr 2008 17:15:38 -0000
@@ -146,6 +146,7 @@ main(int argc, char **argv)
DO_TEST("misc-acpi");
DO_TEST("misc-no-reboot");
DO_TEST("net-user");
+ DO_TEST("net-virtio");
DO_TEST("serial-vc");
DO_TEST("serial-pty");
Index: tests/qemuxml2xmltest.c
===================================================================
RCS file: /data/cvs/libvirt/tests/qemuxml2xmltest.c,v
retrieving revision 1.13
diff -u -p -r1.13 qemuxml2xmltest.c
--- tests/qemuxml2xmltest.c 25 Apr 2008 20:46:13 -0000 1.13
+++ tests/qemuxml2xmltest.c 29 Apr 2008 17:15:38 -0000
@@ -109,6 +109,7 @@ main(int argc, char **argv)
DO_TEST("misc-acpi");
DO_TEST("misc-no-reboot");
DO_TEST("net-user");
+ DO_TEST("net-virtio");
DO_TEST("serial-vc");
DO_TEST("serial-pty");
Index: tests/sexpr2xmltest.c
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmltest.c,v
retrieving revision 1.26
diff -u -p -r1.26 sexpr2xmltest.c
--- tests/sexpr2xmltest.c 26 Apr 2008 14:22:02 -0000 1.26
+++ tests/sexpr2xmltest.c 29 Apr 2008 17:15:38 -0000
@@ -116,6 +116,7 @@ main(int argc, char **argv)
DO_TEST("curmem", "curmem", 1);
DO_TEST("net-routed", "net-routed", 2);
DO_TEST("net-bridged", "net-bridged", 2);
+ DO_TEST("net-e1000", "net-e1000", 2);
DO_TEST("no-source-cdrom", "no-source-cdrom", 1);
DO_TEST("fv-utc", "fv-utc", 1);
Index: tests/testutils.c
===================================================================
RCS file: /data/cvs/libvirt/tests/testutils.c,v
retrieving revision 1.12
diff -u -p -r1.12 testutils.c
--- tests/testutils.c 18 Apr 2008 15:05:29 -0000 1.12
+++ tests/testutils.c 29 Apr 2008 17:15:38 -0000
@@ -23,6 +23,7 @@
#include <fcntl.h>
#include <limits.h>
#include "testutils.h"
+#include "internal.h"
#ifdef HAVE_PATHS_H
#include <paths.h>
@@ -231,23 +232,27 @@ int virtTestDifference(FILE *stream,
const char *expectEnd = expect + (strlen(expect)-1);
const char *actualStart = actual;
const char *actualEnd = actual + (strlen(actual)-1);
+ const char *debug;
- if (getenv("DEBUG_TESTS") == NULL)
+ if ((debug = getenv("DEBUG_TESTS")) == NULL)
return 0;
- /* Skip to first character where they differ */
- while (*expectStart && *actualStart &&
- *actualStart == *expectStart) {
- actualStart++;
- expectStart++;
- }
+ if (STREQ(debug, "") ||
+ STREQ(debug, "1")) {
+ /* Skip to first character where they differ */
+ while (*expectStart && *actualStart &&
+ *actualStart == *expectStart) {
+ actualStart++;
+ expectStart++;
+ }
- /* Work backwards to last character where they differ */
- while (actualEnd > actualStart &&
- expectEnd > expectStart &&
- *actualEnd == *expectEnd) {
- actualEnd--;
- expectEnd--;
+ /* Work backwards to last character where they differ */
+ while (actualEnd > actualStart &&
+ expectEnd > expectStart &&
+ *actualEnd == *expectEnd) {
+ actualEnd--;
+ expectEnd--;
+ }
}
/* Show the trimmed differences */
Index: tests/xmconfigtest.c
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigtest.c,v
retrieving revision 1.15
diff -u -p -r1.15 xmconfigtest.c
--- tests/xmconfigtest.c 26 Apr 2008 14:22:02 -0000 1.15
+++ tests/xmconfigtest.c 29 Apr 2008 17:15:39 -0000
@@ -202,6 +202,7 @@ main(int argc, char **argv)
DO_TEST("paravirt-old-pvfb", 2);
DO_TEST("paravirt-new-pvfb", 3);
+ DO_TEST("paravirt-net-e1000", 3);
DO_TEST("fullvirt-old-cdrom", 1);
DO_TEST("fullvirt-new-cdrom", 2);
DO_TEST("fullvirt-utc", 2);
Index: tests/xml2sexprtest.c
===================================================================
RCS file: /data/cvs/libvirt/tests/xml2sexprtest.c,v
retrieving revision 1.25
diff -u -p -r1.25 xml2sexprtest.c
--- tests/xml2sexprtest.c 26 Apr 2008 14:22:02 -0000 1.25
+++ tests/xml2sexprtest.c 29 Apr 2008 17:15:39 -0000
@@ -123,6 +123,7 @@ main(int argc, char **argv)
DO_TEST("curmem", "curmem", "rhel5", 2);
DO_TEST("net-routed", "net-routed", "pvtest", 2);
DO_TEST("net-bridged", "net-bridged", "pvtest", 2);
+ DO_TEST("net-e1000", "net-e1000", "pvtest", 2);
DO_TEST("no-source-cdrom", "no-source-cdrom", "test", 2);
DO_TEST("fv-utc", "fv-utc", "fvtest", 1);
Index: tests/qemuxml2argvdata/qemuxml2argv-net-virtio.args
===================================================================
RCS file: tests/qemuxml2argvdata/qemuxml2argv-net-virtio.args
diff -N tests/qemuxml2argvdata/qemuxml2argv-net-virtio.args
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/qemuxml2argvdata/qemuxml2argv-net-virtio.args 29 Apr 2008 17:15:39 -0000
@@ -0,0 +1 @@
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net nic,macaddr=00:11:22:33:44:55,vlan=0,model=virtio -net user,vlan=0 -serial none -parallel none -usb
\ No newline at end of file
Index: tests/qemuxml2argvdata/qemuxml2argv-net-virtio.xml
===================================================================
RCS file: tests/qemuxml2argvdata/qemuxml2argv-net-virtio.xml
diff -N tests/qemuxml2argvdata/qemuxml2argv-net-virtio.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/qemuxml2argvdata/qemuxml2argv-net-virtio.xml 29 Apr 2008 17:15:39 -0000
@@ -0,0 +1,26 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda'/>
+ </disk>
+ <interface type='user'>
+ <mac address='00:11:22:33:44:55'/>
+ <model type='virtio'/>
+ </interface>
+ </devices>
+</domain>
Index: tests/sexpr2xmldata/sexpr2xml-net-e1000.sexpr
===================================================================
RCS file: tests/sexpr2xmldata/sexpr2xml-net-e1000.sexpr
diff -N tests/sexpr2xmldata/sexpr2xml-net-e1000.sexpr
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/sexpr2xmldata/sexpr2xml-net-e1000.sexpr 29 Apr 2008 17:15:39 -0000
@@ -0,0 +1,2 @@
+(domain (domid 6)(name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5… ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vif (mac '00:11:22:33:44:55')(bridge 'xenbr2')(script 'vif-bridge')(model 'e1000'))))
+
Index: tests/sexpr2xmldata/sexpr2xml-net-e1000.xml
===================================================================
RCS file: tests/sexpr2xmldata/sexpr2xml-net-e1000.xml
diff -N tests/sexpr2xmldata/sexpr2xml-net-e1000.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/sexpr2xmldata/sexpr2xml-net-e1000.xml 29 Apr 2008 17:15:39 -0000
@@ -0,0 +1,32 @@
+<domain type='xen' id='6'>
+ <name>pvtest</name>
+ <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid>
+ <os>
+ <type>linux</type>
+ <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel>
+ <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd>
+ <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5… </cmdline>
+ </os>
+ <memory>430080</memory>
+ <vcpu>2</vcpu>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>destroy</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <disk type='file' device='disk'>
+ <driver name='file'/>
+ <source file='/root/some.img'/>
+ <target dev='xvda'/>
+ </disk>
+ <interface type='bridge'>
+ <source bridge='xenbr2'/>
+ <target dev='vif6.0'/>
+ <mac address='00:11:22:33:44:55'/>
+ <script path='vif-bridge'/>
+ <model type='e1000'/>
+ </interface>
+ <console type='pty'>
+ <target port='0'/>
+ </console>
+ </devices>
+</domain>
Index: tests/xmconfigdata/test-paravirt-net-e1000.cfg
===================================================================
RCS file: tests/xmconfigdata/test-paravirt-net-e1000.cfg
diff -N tests/xmconfigdata/test-paravirt-net-e1000.cfg
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/xmconfigdata/test-paravirt-net-e1000.cfg 29 Apr 2008 17:15:39 -0000
@@ -0,0 +1,12 @@
+name = "XenGuest1"
+uuid = "c7a5fdb0-cdaf-9455-926a-d65c16db1809"
+maxmem = 579
+memory = 394
+vcpus = 1
+bootloader = "/usr/bin/pygrub"
+on_poweroff = "destroy"
+on_reboot = "restart"
+on_crash = "restart"
+vfb = [ "type=vnc,vncunused=1,vnclisten=127.0.0.1,vncpasswd=123poi" ]
+disk = [ "phy:/dev/HostVG/XenGuest1,xvda,w" ]
+vif = [ "mac=00:16:3E:66:94:9C,model=e1000,ip=192.168.0.9" ]
Index: tests/xmconfigdata/test-paravirt-net-e1000.xml
===================================================================
RCS file: tests/xmconfigdata/test-paravirt-net-e1000.xml
diff -N tests/xmconfigdata/test-paravirt-net-e1000.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/xmconfigdata/test-paravirt-net-e1000.xml 29 Apr 2008 17:15:39 -0000
@@ -0,0 +1,28 @@
+<domain type='xen'>
+ <name>XenGuest1</name>
+ <uuid>c7a5fdb0-cdaf-9455-926a-d65c16db1809</uuid>
+ <bootloader>/usr/bin/pygrub</bootloader>
+ <currentMemory>403456</currentMemory>
+ <memory>592896</memory>
+ <vcpu>1</vcpu>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <disk type='block' device='disk'>
+ <driver name='phy'/>
+ <source dev='/dev/HostVG/XenGuest1'/>
+ <target dev='xvda'/>
+ </disk>
+ <interface type='bridge'>
+ <mac address='00:16:3E:66:94:9C'/>
+ <ip address='192.168.0.9'/>
+ <model type='e1000'/>
+ </interface>
+ <input type='mouse' bus='xen'/>
+ <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/>
+ <console type='pty'>
+ <target port='0'/>
+ </console>
+ </devices>
+</domain>
Index: tests/xml2sexprdata/xml2sexpr-net-e1000.sexpr
===================================================================
RCS file: tests/xml2sexprdata/xml2sexpr-net-e1000.sexpr
diff -N tests/xml2sexprdata/xml2sexpr-net-e1000.sexpr
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/xml2sexprdata/xml2sexpr-net-e1000.sexpr 29 Apr 2008 17:15:39 -0000
@@ -0,0 +1 @@
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5… ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vif (mac '00:11:22:33:44:55')(bridge 'xenbr2')(script 'vif-bridge')(model 'e1000'))))
\ No newline at end of file
Index: tests/xml2sexprdata/xml2sexpr-net-e1000.xml
===================================================================
RCS file: tests/xml2sexprdata/xml2sexpr-net-e1000.xml
diff -N tests/xml2sexprdata/xml2sexpr-net-e1000.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/xml2sexprdata/xml2sexpr-net-e1000.xml 29 Apr 2008 17:15:39 -0000
@@ -0,0 +1,30 @@
+<domain type='xen' id='15'>
+ <name>pvtest</name>
+ <uuid>596a5d2171f48fb2e068e2386a5c413e</uuid>
+ <os>
+ <type>linux</type>
+ <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel>
+ <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd>
+ <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5… </cmdline>
+ </os>
+ <memory>430080</memory>
+ <vcpu>2</vcpu>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>destroy</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <disk type='file' device='disk'>
+ <source file='/root/some.img'/>
+ <target dev='xvda'/>
+ </disk>
+ <interface type="bridge">
+ <mac address="00:11:22:33:44:55"/>
+ <source bridge="xenbr2"/>
+ <script path="vif-bridge"/>
+ <model type='e1000'/>
+ <target dev="vif4.0"/>
+ </interface>
+ <console tty='/dev/pts/4'/>
+ </devices>
+</domain>
+
--
|: Red Hat, Engineering, Boston -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 :|
5
10
Alot of the docs pages have manually written table of contents linking to
headings with the page. I figured this is a good candidate for being
auto-generated.
The basic idea is that given a document with a series of headings
<h2><a name="xxx">Foo</a></h2>
..
<h3><a name="xxx">Bar</a></h3>
..
<h3><a name="xxx">Wizz</a></h3>
..
<h2><a name="xxx">Oooh</a></h2>
..
<h3><a name="xxx">Ahhh</a></h3>
Then, generate a table of contents with a nested set of lists <ul>. THe
XSL below attempts todo this for heading levels h2 -> h6, and splices the
TOC into the page where it sees an <ul id='toc'></ul> element (typically
just after <h1>).
I'm kind of out of practice with XSL, so there's probably a nicer way
to write the 'toc' template below...
Dan.
Index: docs/page.xsl
===================================================================
RCS file: /data/cvs/libvirt/docs/page.xsl,v
retrieving revision 1.7
diff -u -r1.7 page.xsl
--- docs/page.xsl 28 Apr 2008 08:29:35 -0000 1.7
+++ docs/page.xsl 30 Apr 2008 12:55:20 -0000
@@ -59,6 +59,54 @@
</ul>
</xsl:template>
+ <xsl:template name="toc">
+ <ul>
+ <xsl:for-each select="/html/body/h2[count(a) = 1]">
+ <xsl:variable name="thishead" select="."/>
+ <li>
+ <a href="#{a/@name}"><xsl:value-of select="a/text()"/></a>
+ <xsl:if test="count(./following-sibling::h3[preceding-sibling::h2[1] = $thishead and count(a) = 1]) > 0">
+ <ul>
+ <xsl:for-each select="./following-sibling::h3[preceding-sibling::h2[1] = $thishead and count(a) = 1]">
+ <xsl:variable name="thissubhead" select="."/>
+ <li>
+ <a href="#{a/@name}"><xsl:value-of select="a/text()"/></a>
+ <xsl:if test="count(./following-sibling::h4[preceding-sibling::h3[1] = $thissubhead and count(a) = 1]) > 0">
+ <ul>
+ <xsl:for-each select="./following-sibling::h4[preceding-sibling::h3[1] = $thissubhead and count(a) = 1]">
+ <li>
+ <a href="#{a/@name}"><xsl:value-of select="a/text()"/></a>
+ <xsl:if test="count(./following-sibling::h5[preceding-sibling::h4[1] = $thissubhead and count(a) = 1]) > 0">
+ <ul>
+ <xsl:for-each select="./following-sibling::h5[preceding-sibling::h4[1] = $thissubhead and count(a) = 1]">
+ <li>
+ <a href="#{a/@name}"><xsl:value-of select="a/text()"/></a>
+ <xsl:if test="count(./following-sibling::h6[preceding-sibling::h5[1] = $thissubhead and count(a) = 1]) > 0">
+ <ul>
+ <xsl:for-each select="./following-sibling::h6[preceding-sibling::h5[1] = $thissubhead and count(a) = 1]">
+ <li>
+ <a href="#{a/@name}"><xsl:value-of select="a/text()"/></a>
+ </li>
+ </xsl:for-each>
+ </ul>
+ </xsl:if>
+ </li>
+ </xsl:for-each>
+ </ul>
+ </xsl:if>
+ </li>
+ </xsl:for-each>
+ </ul>
+ </xsl:if>
+ </li>
+ </xsl:for-each>
+ </ul>
+ </xsl:if>
+ </li>
+ </xsl:for-each>
+ </ul>
+ </xsl:template>
+
<!-- This is the master page structure -->
<xsl:template match="/" mode="page">
<xsl:param name="pagename"/>
@@ -93,7 +141,16 @@
</xsl:apply-templates>
</div>
<div id="content">
- <xsl:copy-of select="html/body/*"/>
+ <xsl:for-each select="html/body/*">
+ <xsl:choose>
+ <xsl:when test="name() = 'ul' and @id = 'toc'">
+ <xsl:call-template name="toc"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
</div>
</div>
<div id="footer">
--
|: Red Hat, Engineering, Boston -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 :|
2
1
Forwarding, on request:
Date: Wed, 30 Apr 2008 04:53:43 -0400
From: Daniel Veillard <veillard(a)redhat.com>
To: Jim Meyering <meyering(a)redhat.com>
Cc: undisclosed-recipients: ;
Subject: Re: [Libvir] [PATCH] update from gnulib
Message-ID: <20080430085343.GF25119(a)redhat.com>
Reply-To: veillard(a)redhat.com
References: <20080430072336.4A4D18E0038(a)hormel.redhat.com>
In-Reply-To: <20080430072336.4A4D18E0038(a)hormel.redhat.com>
User-Agent: Mutt/1.5.13 (2006-09-08)
On Tue, Apr 29, 2008 at 05:57:36PM +0200, Jim Meyering wrote:
>
> Signed-off-by: Jim Meyering <meyering(a)redhat.com>
Hum, to me the gnulib update side is under your control, I don't
feel it's necessary for you to post the patch, unless you know there
may be an associated change for the other developpers. Others may disagree
but I don't think I can really review those :-)
Daniel
--
Red Hat Virtualization group http://redhat.com/virtualization/
Daniel Veillard | virtualization library http://libvirt.org/
veillard(a)redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/
http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/
2
2
I've just fixed a bug in my useless-if-detecting script,
committed in gnulib. Using that new script with today's
change adding xmlFree to the list exposed a bunch of useless tests.
This first change set removes those tests.
Below it is a separate patch that updates gnulib-related
files, including that script and vc-list-files.
I verified that with these changes "make distcheck" passes.
If no one objects, I'll push these in about 12 hours.
remove useless tests before xmlFree
* src/qemu_conf.c (qemudParseDiskXML, qemudParseInterfaceXML):
(qemudParseInputXML, qemudParseDhcpRangesXML):
* src/remote_internal.c (doRemoteOpen):
* src/storage_conf.c (virStoragePoolDefParseDoc):
* src/xm_internal.c (xenXMParseXMLDisk, xenXMParseXMLVif):
(xenXMParseXMLToConfig, xenXMAttachInterface):
* src/xml.c (virDomainParseXMLDiskDesc, virDomainParseXMLIfDesc):
(virDomainXMLDevID):
Signed-off-by: Jim Meyering <meyering(a)redhat.com>
---
src/qemu_conf.c | 48 ++++++++++++++++--------------------------------
src/remote_internal.c | 8 ++++----
src/storage_conf.c | 3 +--
src/xm_internal.c | 42 ++++++++++++++----------------------------
src/xml.c | 30 ++++++++++--------------------
5 files changed, 45 insertions(+), 86 deletions(-)
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index 07dfe47..a0c4a8f 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -680,14 +680,10 @@ static int qemudParseDiskXML(virConnectPtr conn,
return 0;
error:
- if (type)
- xmlFree(type);
- if (target)
- xmlFree(target);
- if (source)
- xmlFree(source);
- if (device)
- xmlFree(device);
+ xmlFree(type);
+ xmlFree(target);
+ xmlFree(source);
+ xmlFree(device);
return -1;
}
@@ -941,18 +937,12 @@ static int qemudParseInterfaceXML(virConnectPtr conn,
return 0;
error:
- if (network)
- xmlFree(network);
- if (address)
- xmlFree(address);
- if (port)
- xmlFree(port);
- if (ifname)
- xmlFree(ifname);
- if (script)
- xmlFree(script);
- if (bridge)
- xmlFree(bridge);
+ xmlFree(network);
+ xmlFree(address);
+ xmlFree(port);
+ xmlFree(ifname);
+ xmlFree(script);
+ xmlFree(bridge);
return -1;
}
@@ -1334,18 +1324,14 @@ static int qemudParseInputXML(virConnectPtr conn,
input->bus = QEMU_INPUT_BUS_USB;
}
- if (type)
- xmlFree(type);
- if (bus)
- xmlFree(bus);
+ xmlFree(type);
+ xmlFree(bus);
return 0;
error:
- if (type)
- xmlFree(type);
- if (bus)
- xmlFree(bus);
+ xmlFree(type);
+ xmlFree(bus);
return -1;
}
@@ -2860,10 +2846,8 @@ static int qemudParseDhcpRangesXML(virConnectPtr conn,
free(range);
}
- if (start)
- xmlFree(start);
- if (end)
- xmlFree(end);
+ xmlFree(start);
+ xmlFree(end);
cur = cur->next;
}
diff --git a/src/remote_internal.c b/src/remote_internal.c
index ef34a3a..70aa5e9 100644
--- a/src/remote_internal.c
+++ b/src/remote_internal.c
@@ -434,9 +434,9 @@ doRemoteOpen (virConnectPtr conn,
}
#ifdef HAVE_XMLURI_QUERY_RAW
- if (uri->query_raw) xmlFree (uri->query_raw);
+ xmlFree (uri->query_raw);
#else
- if (uri->query) xmlFree (uri->query);
+ xmlFree (uri->query);
#endif
if ((
@@ -464,10 +464,10 @@ doRemoteOpen (virConnectPtr conn,
transport_str[-1] = '\0';
}
/* Remove the username, server name and port number. */
- if (uri->user) xmlFree (uri->user);
+ xmlFree (uri->user);
uri->user = 0;
- if (uri->server) xmlFree (uri->server);
+ xmlFree (uri->server);
uri->server = 0;
uri->port = 0;
diff --git a/src/storage_conf.c b/src/storage_conf.c
index 4499ae2..be21d3b 100644
--- a/src/storage_conf.c
+++ b/src/storage_conf.c
@@ -357,8 +357,7 @@ virStoragePoolDefParseDoc(virConnectPtr conn,
cleanup:
free(uuid);
- if (type)
- xmlFree(type);
+ xmlFree(type);
virStoragePoolDefFree(ret);
return NULL;
}
diff --git a/src/xm_internal.c b/src/xm_internal.c
index a70436d..08e3e8e 100644
--- a/src/xm_internal.c
+++ b/src/xm_internal.c
@@ -1657,10 +1657,8 @@ static int xenXMParseXMLDisk(xmlNodePtr node, int hvm, int xendConfigVersion, ch
}
if (target == NULL) {
- if (source != NULL)
- xmlFree(source);
- if (device != NULL)
- xmlFree(device);
+ xmlFree(source);
+ xmlFree(device);
return (-1);
}
@@ -1687,10 +1685,8 @@ static int xenXMParseXMLDisk(xmlNodePtr node, int hvm, int xendConfigVersion, ch
}
if (source == NULL && !cdrom) {
- if (target != NULL)
- xmlFree(target);
- if (device != NULL)
- xmlFree(device);
+ xmlFree(target);
+ xmlFree(device);
return (-1);
}
@@ -1765,8 +1761,7 @@ static int xenXMParseXMLDisk(xmlNodePtr node, int hvm, int xendConfigVersion, ch
xmlFree(drvName);
xmlFree(device);
xmlFree(target);
- if(source)
- xmlFree(source);
+ xmlFree(source);
*disk = buf;
return (ret);
@@ -1877,14 +1872,10 @@ static char *xenXMParseXMLVif(virConnectPtr conn, xmlNodePtr node, int hvm) {
cleanup:
free(bridge);
- if (mac != NULL)
- xmlFree(mac);
- if (source != NULL)
- xmlFree(source);
- if (script != NULL)
- xmlFree(script);
- if (ip != NULL)
- xmlFree(ip);
+ xmlFree(mac);
+ xmlFree(source);
+ xmlFree(script);
+ xmlFree(ip);
return buf;
}
@@ -2164,8 +2155,7 @@ virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml) {
strcat(val, ",vncdisplay=");
strcat(val, portstr);
}
- if (vncport)
- xmlFree(vncport);
+ xmlFree(vncport);
if (vnclisten) {
strcat(val, ",vnclisten=");
strcat(val, (const char*)vnclisten);
@@ -2310,8 +2300,7 @@ virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml) {
error:
if (conf)
virConfFree(conf);
- if (prop != NULL)
- xmlFree(prop);
+ xmlFree(prop);
xmlXPathFreeObject(obj);
xmlXPathFreeContext(ctxt);
if (doc != NULL)
@@ -2960,12 +2949,9 @@ xenXMAttachInterface(virDomainPtr domain, xmlXPathContextPtr ctxt, int hvm,
goto cleanup;
node_cleanup:
- if (node_tmp)
- xmlFree(node_tmp);
- if (attr_node)
- xmlFree(attr_node);
- if (text_node)
- xmlFree(text_node);
+ xmlFree(node_tmp);
+ xmlFree(attr_node);
+ xmlFree(text_node);
cleanup:
free(type);
free(source);
diff --git a/src/xml.c b/src/xml.c
index e889cdd..25eba3d 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -1341,16 +1341,11 @@ virDomainParseXMLDiskDesc(virConnectPtr conn, xmlNodePtr node,
virBufferAddLit(buf, ")");
cleanup:
- if (drvType)
- xmlFree(drvType);
- if (drvName)
- xmlFree(drvName);
- if (device)
- xmlFree(device);
- if (target)
- xmlFree(target);
- if (source)
- xmlFree(source);
+ xmlFree(drvType);
+ xmlFree(drvName);
+ xmlFree(device);
+ xmlFree(target);
+ xmlFree(source);
return (ret);
}
@@ -1466,14 +1461,10 @@ virDomainParseXMLIfDesc(virConnectPtr conn ATTRIBUTE_UNUSED,
virBufferAddLit(buf, ")");
ret = 0;
error:
- if (mac != NULL)
- xmlFree(mac);
- if (source != NULL)
- xmlFree(source);
- if (script != NULL)
- xmlFree(script);
- if (ip != NULL)
- xmlFree(ip);
+ xmlFree(mac);
+ xmlFree(source);
+ xmlFree(script);
+ xmlFree(ip);
return (ret);
}
@@ -1953,8 +1944,7 @@ virDomainXMLDevID(virDomainPtr domain, const char *xmldesc, char *class,
cleanup:
if (xml != NULL)
xmlFreeDoc(xml);
- if (attr != NULL)
- xmlFree(attr);
+ xmlFree(attr);
return ret;
}
#endif /* WITH_XEN */
--
1.5.5.1.68.gbdcd8
2
4
Hi,
I know that there is no support for VMWare ESX yet but I would like to
know if someone is working on it. I need just three basic operations:
status/power on/power off but I never saw the source code of libvirt :)
Do you think it is possible to write this support (using VMWare API) in
acceptable time? week? month?
Thanks, for any suggestions
m,
--
Marek Grac
Red Hat Czech s.r.o.
3
2
Hi,
I know that there is no support for VMWare ESX yet but I would like to
know if someone is working on it. I need just three basic operations:
status/power on/power off but I never saw the source code of libvirt :)
Do you think it is possible to write this support (using VMWare API) in
acceptable time? week? month?
Thanks, for any suggestions
m,
--
Marek Grac
Red Hat Czech s.r.o.
2
1
Some time ago, Daniel Veillard assured me that xmlFree(NULL) is
valid in regular use, and with upstream code since January it's
ok even in a debug mode that's not normally available because
it's ifdef'd out:
http://mail.gnome.org/archives/svn-commits-list/2008-January/msg02233.html
Since the potential NULL-deref in debug mode is now gone,
we can now use this to prevent any new useless tests:
also check for useless test-before-xmlFree
* Makefile.cfg (useless_free_options): Add --name=xmlFree.
diff --git a/Makefile.cfg b/Makefile.cfg
index e0d5528..cbf97c2 100644
--- a/Makefile.cfg
+++ b/Makefile.cfg
@@ -53,5 +53,6 @@ local-checks-to-skip = \
useless_free_options = \
--name=sexpr_free \
+ --name=xmlFree \
--name=xmlXPathFreeContext \
--name=xmlXPathFreeObject
--
1.5.5.1.68.gbdcd8
2
1
[Libvir] PATCH: Avoid buffer out of bounds access in Xen capabilities
by Daniel P. Berrange 29 Apr '08
by Daniel P. Berrange 29 Apr '08
29 Apr '08
The Xen driver uses a regex to process the hypervisor capabilities data
"(xen|hvm)-[[:digit:]]+\\.[[:digit:]]+-(x86_32|x86_64|ia64|powerpc64)(p|be)?";
notice how the last match group, however, is optional due to the '?'. The
code processing matches does not check to see if the match is present or
not, and just indexes the string on match 3
if (strncmp (&token[subs[3].rm_so], "p", 1) == 0)
Unfortunately, subs[3].rm_so is -1 if the match was not present, so we're
doing an out of bounds array access here. This is fairly harmless, but it
is still good to fix it. So this patch adds a check for -1 before accessing
the match. I also replace the strncmp() calls with a call to the brand new
STRPREFIX() convenience macro
Dan.
Index: src/xen_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xen_internal.c,v
retrieving revision 1.119
diff -u -r1.119 xen_internal.c
--- src/xen_internal.c 10 Apr 2008 16:54:54 -0000 1.119
+++ src/xen_internal.c 28 Apr 2008 22:07:12 -0000
@@ -2349,28 +2349,31 @@
if (regexec (&xen_cap_rec, token, sizeof subs / sizeof subs[0],
subs, 0) == 0) {
- int hvm = strncmp (&token[subs[1].rm_so], "hvm", 3) == 0;
+ int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm");
const char *model;
int bits, pae = 0, nonpae = 0, ia64_be = 0;
- if (strncmp (&token[subs[2].rm_so], "x86_32", 6) == 0) {
+
+ if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) {
model = "i686";
bits = 32;
- if (strncmp (&token[subs[3].rm_so], "p", 1) == 0)
+ if (subs[3].rm_so != -1 &&
+ STRPREFIX(&token[subs[3].rm_so], "p"))
pae = 1;
else
nonpae = 1;
}
- else if (strncmp (&token[subs[2].rm_so], "x86_64", 6) == 0) {
+ else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) {
model = "x86_64";
bits = 64;
}
- else if (strncmp (&token[subs[2].rm_so], "ia64", 4) == 0) {
+ else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) {
model = "ia64";
bits = 64;
- if (strncmp (&token[subs[3].rm_so], "be", 2) == 0)
+ if (subs[3].rm_so != -1 &&
+ STRPREFIX(&token[subs[3].rm_so], "be"))
ia64_be = 1;
}
- else if (strncmp (&token[subs[2].rm_so], "powerpc64", 4) == 0) {
+ else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) {
model = "ppc64";
bits = 64;
} else {
@@ -2380,7 +2383,7 @@
/* Search for existing matching (model,hvm) tuple */
for (i = 0 ; i < nr_guest_archs ; i++) {
- if (!strcmp(guest_archs[i].model, model) &&
+ if (STREQ(guest_archs[i].model, model) &&
guest_archs[i].hvm == hvm) {
break;
}
--
|: Red Hat, Engineering, Boston -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 :|
2
2
Including config.h from memory.c is probably required only on
um, ... unusual systems, but technically, it is required for the
definition of a possibly missing "size_t" or "ptrdiff_t" type.
Avoid "make syntax-check" failures.
* src/memory.c: Include "config.h".
Remove trailing blanks.
diff --git a/src/memory.c b/src/memory.c
index fe41e38..1ca67fb 100644
--- a/src/memory.c
+++ b/src/memory.c
@@ -19,6 +19,7 @@
*
*/
+#include <config.h>
#include <stdlib.h>
#include "memory.h"
@@ -72,7 +73,7 @@ int virAlloc(void *ptrptr, size_t size)
* @size: number of bytes to allocate
* @count: number of elements to allocate
*
- * Allocate an array of memory 'count' elements long,
+ * Allocate an array of memory 'count' elements long,
* each with 'size' bytes. Return the address of the
* allocated memory in 'ptrptr'. The newly allocated
* memory is filled with zeros.
@@ -101,7 +102,7 @@ int virAllocN(void *ptrptr, size_t size, size_t count)
* Resize the block of memory in 'ptrptr' to be an array of
* 'count' elements, each 'size' bytes in length. Update 'ptrptr'
* with the address of the newly allocated memory. On failure,
- * 'ptrptr' is not changed and still points to the original memory
+ * 'ptrptr' is not changed and still points to the original memory
* block. The newly allocated memory is filled with zeros.
*
* Returns -1 on failure to allocate, zero on success
--
1.5.5.1.68.gbdcd8
2
1
Some of us are stuck with an ancient libparted, which doesn't know about
PED_PARTITION_PROTECTED. This patch allows us to compile libvirt.
=== modified file 'src/parthelper.c'
--- src/parthelper.c 2008-04-10 16:53:29 +0000
+++ src/parthelper.c 2008-04-29 07:47:08 +0000
@@ -67,8 +67,10 @@
content = "free";
else if (part->type & PED_PARTITION_METADATA)
content = "metadata";
+#ifdef PED_PARTITION_PROTECTED
else if (part->type & PED_PARTITION_PROTECTED)
content = "protected";
+#endif
else
content = "data";
} else if (part->type == PED_PARTITION_EXTENDED) {
@@ -80,8 +82,10 @@
content = "free";
else if (part->type & PED_PARTITION_METADATA)
content = "metadata";
+#ifdef PED_PARTITION_PROTECTED
else if (part->type & PED_PARTITION_PROTECTED)
content = "protected";
+#endif
else
content = "data";
}
--
Soren Hansen |
Virtualisation specialist | Ubuntu Server Team
Canonical Ltd. | http://www.ubuntu.com/
4
3
29 Apr '08
This patch allows selection of the NIC model for QEMU/KVM domains.
The selection is done by adding a <model/> element to the XML, as in
this example:
<interface type='user'>
<mac address='00:16:3e:33:b8:d3'/>
<model type='ne2k_pci'/>
</interface>
The model type string is only checked to make sure it's a short
alpha-numeric + underscore, since it seems impractical to extract the
actual list of supported models.
If you choose a supported model then QEMU starts up with this extra
-nic parameter:
/usr/bin/qemu-kvm -M pc -m 500 -smp 1 -monitor pty \
-boot c -hda /var/lib/xen/images/rhel51x32kvm.img \
-net nic,macaddr=00:16:3e:33:b8:d3,vlan=0,model=ne2k_pci -net user,vlan=0 \
-usb -vnc 127.0.0.1:0
If you choose a non-existant model then you get the error:
libvir: QEMU error : internal error QEMU quit during monitor startup
Rich.
--
Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones
virt-top is 'top' for virtual machines. Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://et.redhat.com/~rjones/virt-top
6
8
This patch fills in the network driver XML format page on
the website which has been requested many times...
Dan.
Index: formatnetwork.html.in
===================================================================
RCS file: /data/cvs/libvirt/docs/formatnetwork.html.in,v
retrieving revision 1.1
diff -r1.1 formatnetwork.html.in
4a5,122
> <p>
> This page provides an introduction to the network XML format. For background
> information on the concepts referred to here, consult the <a href="archnetwork.html">network driver architecture</a>
> page.
> </p>
>
> <h2>Element and attribute overview</h2>
>
> <p>
> The root element required for all virtual networks is
> named <code>network</code> and has no attributes.
> </p>
>
> <h3>General metadata</h3>
>
> <p>
> The first elements provide basic metadata about the virtual
> network.
> </p>
>
> <pre>
> <network>
> <name>default</name>
> <uuid>3e3fce45-4f53-4fa7-bb32-11f34168b82b</uuid>
> ...</pre>
>
> <dl>
> <dt><code>name</code></dt>
> <dd>The content of the <code>name</code> element provides
> a short name for the virtual network. This name should
> consist only of alpha-numeric characters and is required
> to be unique within the scope of a single host. It is
> used to form the filename for storing the persistent
> configuration file.</dd>
> <dt><code>uuid</code></dt>
> <dd>The content of the <code>uuid</code> element provides
> a globally unique identifier for the virtual network.
> The format must be RFC 4122 compliant, eg <code>3e3fce45-4f53-4fa7-bb32-11f34168b82b</code>.
> If omitted when defining/creating a new network, a random
> UUID is generated.</dd>
> </dl>
>
> <h3>Connectivity</h3>
>
> <p>
> The next set of elements control how a virtual network is
> provided connectivity to the physical LAN (if at all).
> </p>
>
> <pre>
> ...
> <bridge name="virbr0" />
> <forward type="nat"/>
> ...</pre>
>
> <dl>
> <dt><code>bridge</code></dt>
> <dd>The <code>name</code> attribute on the <code>bridge</code> element
> defines the name of a bridge device which will be used to construct
> the virtual network. The virtual machines will be connected to this
> bridge device allowing them to talk to each other. The bridge device
> may also be connected to the LAN. It is recommended that bridge
> device names started with the prefix <code>vir</code>, but the name
> <code>virbr0</code> is reserved for the "default" virtual network.
> This element should always be provided when defining a new network
> </dd>
> <dt><code>forward</code></dt>
> <dd>Inclusion of the <code>forward</code> element indicates that
> the virtual network is to be connected to the physical LAN. If
> no attributes are set, NAT forwarding will be used for connectivity.
> Firewall rules will allow forwarding to any other network device whether
> ethernet, wireless, dialup, or VPN. If the <code>dev</code> attribute
> is set, the firewall rules will restrict forwarding to the named
> device only. If the <code>type</code> attribute is set to <code>route</code>
> then the traffic will not have NAT applied. This presumes that the
> local LAN router has suitable routing table entries to return traffic
> to this host.</dd>
> </dl>
>
> <h3>Addressing</h3>
>
> <p>
> The final set of elements define the IPv4 address range available,
> and optionally enable DHCP sevices.
> </p>
>
> <pre>
> ...
> <ip address="192.168.122.1" netmask="255.255.255.0">
> <dhcp>
> <range start="192.168.122.2" end="192.168.122.254" />
> </dhcp>
> </ip>
> </network></pre>
>
> <dl>
> <dt><code>ip</code></dt>
> <dd>The <code>address</code> attribute defines an IPv4 address in
> dotted-decimal format, that will be configured on the bridge
> device associated with the virtual network. To the guests this
> address will be their default route. The <code>netmask</code>
> attribute defines the significant bits of the network address,
> again specified in dotted-decimal format.
> </dd>
> <dt><code>dhcp</code></dt>
> <dd>Immediately within the <code>ip</code> element there is an
> optional <code>dhcp</code> element. The presence of this element
> enables DHCP services on the virtual network. It will further
> contain one or more <code>range</code> elements.
> </dd>
> <dt><code>range</code></dt>
> <dd>The <code>start</code> and <code>end</code> attributes on the
> <code>range</code> element specify the boundaries of a pool of
> IPv4 addresses to be provided to DHCP clients. These two addresses
> must lie within the scope of the network defined on the parent
> <code>ip</code> element.
> </dd>
> </dl>
9a128,137
> <p>
> This example is the so called "default" virtual network. It is
> provided and enabled out-of-the-box for all libvirt installations.
> This is a configuration that allows guest OS to get outbound
> connectivity regardless of whether the host uses ethernet, wireless,
> dialup, or VPN networking without requiring any specific admin
> configuration. In the absence of host networking, it at least allows
> guests to talk directly to each other.
> </p>
>
23a152,160
> <p>
> This is a variant on the default network which routes traffic
> from the virtual network to the LAN without applying any NAT.
> It requires that the IP address range be pre-configured in the
> routing tables of the router on the host network. This example
> further specifies that guest traffic may only go out via the
> <code>eth1</code> host network device.
> </p>
>
37a175,182
> <p>
> This variant provides a completely isolated private network
> for guests. The guests can talk to each other, and the host
> OS, but cannot reach any other machines on the LAN, due to
> the omission of the <code>forward</code> element in the XML
> description.
> </p>
>
--
|: Red Hat, Engineering, Boston -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 :|
2
1
[Libvir] RFC: safer memory allocation APIs with compile time checking
by Daniel P. Berrange 29 Apr '08
by Daniel P. Berrange 29 Apr '08
29 Apr '08
After updating the virBuffer APIs to protect against improper usage I have
been thinking about how we might provider safer memory allocation APIs
with protection against common usage errors and compile time validation of
checks for failure.
The standard C library malloc/realloc/calloc/free APIs have just about the
worst possible design, positively encouraging serious application coding
errors. There are at least 7 common problems I can think of at the moment,
perhaps more....
1. malloc() - pass incorrect number of bytes
2. malloc() - fail to check the return value
3. malloc() - use uninitialized memory
4. free() - double free by not setting pointer to NULL
5. realloc() - fail to check the return value
6. realloc() - fail to re-assign the pointer with new address
7. realloc() - accidental overwrite of original pointer with NULL on
failure, leaking memory
Many applications / libraries wrap these in their own functions, but typically
fail to address one or more these problems.
eg glib re-definitions try to address point 2 by having g_malloc() call
abort() on failure, but then re-introduce the problem by adding g_try_malloc()
gpointer g_malloc (gulong n_bytes) G_GNUC_MALLOC;
gpointer g_try_malloc (gulong n_bytes) G_GNUC_MALLOC;
Simiarly it tries address point 6, with the annotation, but this still leaves
open the failure to check for NULL in point 1.
gpointer g_realloc (gpointer mem,
gulong n_bytes) G_GNUC_WARN_UNUSED_RESULT;
gpointer g_try_realloc (gpointer mem,
gulong n_bytes) G_GNUC_WARN_UNUSED_RESULT;
And the g_free wrapper doesn't help with the double free issue at all:
void g_free (gpointer mem);
All 7 of the errors listed early could be avoided and/or checked at compile
time if the APIs used a different calling convention.
1. For any given pointer the compiler knows how many bytes need to be
allocated for a single instance of it. ie sizeof(*(ptr)). Since C
has no data type representing a data type, this cannot be done with
a simple function - it needs a (trivial) macro.
2. The __attribute__((__warn_unused_result__)) annotation causes the
compiler to warn if an application doesn't do something with a return
value. With the standard malloc() API this doesn't help because you
always assign the return value to a pointer. The core problem here
is that the API encodes the error condition as a special case of
the actual data returned. This can be addressed by separating the
two. The return value should simply be bi-state success or fail code
and the return data passed back via an pointer to a pointer parameter.
3. The memory allocated by malloc() is not initialized to zero. For
that a separate calloc() function is provided. This leaves open the
possiblity of an app mistakenly using the wrong variant. Or consider
an app using malloc() and explicitly initializing all struct members.
Some time later a new member is added and now the developer needs to
find all malloc() calls wrt to that struct and explicitly initilize
the new member. It would be safer to always have malloc zero all
memory, even though it has a small performance impact, the net win
in safety is probably worth it.
4. Since free() takes the pointer to be freed directly it cannot reset
the caller's original pointer back to NULL. This can be addressed if
a pointer to the pointer is passed instead. The computational cost
of the often redundant assignment to NULL is negligable given the
safety benefit
5, 6 & 7. As with problem 2, these problems are all caused by the fact
that the error condition is special case of the return data value.
The impact of these is typically far worse because it often results
in a buffer overflow and the complex rules for calling realloc() are
hard to remember.
So the core requirements of a safer API for allocation are:
- Use return values *only* for the success/fail error condition
- Annotate all the return values with __warn_unused_result__
- Pass a pointer to the pointer into all functions
- Define macros around all functions to automatically do the sizeof(*(ptr))
Passing a pointer to a pointer gets a little tedious because of the need
to write '&(foo)' instead of just 'foo', and is actually introduces a
new problem of the caller accidentally passing merely a pointer, instead
of a pointer to a pointer. This is a minor problem though because it will
be identified on the very first run of the code. In addition, since we're
defining macros around every function we can have the macro also convert
from ptr to &(ptr) for us, avoiding this potential error:
So the primary application usage would be via a set of macros:
VIR_ALLOC(ptr)
VIR_ALLOC_N(ptr, count)
VIR_REALLOC(ptr)
VIR_REALLOC_N(ptr, count)
VIR_FREE(ptr)
These call through to the underlying APIs:
int virAlloc(void *, size_t bytes)
int virAllocN(void *, size_t bytes, size_t count)
int virRealloc(void *, size_t bytes)
int virReallocN(void *, size_t bytes, size_t count)
int virFree(void *)
Note that although we're passing a pointer to a pointer into all these, the
first param is still just 'void *' and not 'void **'. This is because 'void *'
is defined to hold any type of pointer, and using 'void **' causes gcc to
complain bitterly about strict aliasing violations. Internally the impls of
these methods will safely cast to 'void **' when deferencing the pointer.
All 4 of Alloc/Realloc functions will have __warn_unused_result__ annotation
so the caller is forced to check the return value for failure, validated at
compile time generating a warning (or fatal compile error with -Werror).
So to wire up the macros to the APIs:
#define VIR_ALLOC(ptr) virAlloc(&(ptr), sizeof(*(ptr)))
#define VIR_ALLOC_N(ptr, count) virAllocN(&(ptr), sizeof(*(ptr)), (count))
#define VIR_REALLOC(ptr) virRealloc(&(ptr), sizeof(*(ptr)))
#define VIR_REALLOC_N(ptr, count) virReallocN(&(ptr), sizeof(*(ptr)), (count))
#define VIR_FREE(ptr) virFree(&(ptr))
In particular notice how we're using the compiler to decide how many bytes
to allocate for each variable here, thus guarenteeing the correct size.
Finally here's an illustration of how these APis would be used in practice.
- Allocating a new variable:
virDomainPtr domain;
if (VIR_ALLOC(domain) < 0) {
__virRaiseError(VIR_ERROR_NO_MEMORY)
return NULL;
}
Looking at the macro, this pass '&domain' into virAlloc() which initalizes
it with address of memory sizeof(*domain) bytes long.
- Allocating an array of domains
virDomainPtr domains;
int ndomains = 10;
if (VIR_ALLOC_N(domains, ndomains) < 0) {
__virRaiseError(VIR_ERROR_NO_MEMORY)
return NULL;
}
- Allocating an array of domain pointers
virDomainPtr *domains;
int ndomains = 10;
if (VIR_ALLOC_N(domains, ndomains) < 0) {
__virRaiseError(VIR_ERROR_NO_MEMORY)
return NULL;
}
- Re-allocate the array of domains to be longer
ndomains = 20
if (VIR_REALLOC_N(domains, ndomains) < 0) {
__virRaiseError(VIR_ERROR_NO_MEMORY)
return NULL;
}
- Free the domain
VIR_FREE(domain);
The attached patch implements these ideas in a memory.h and memory.c file
and updates 'hash.c' to illustrate their usage. If we were to replace
every single instance of malloc/calloc/free/realloc with these calls the
automated builds which run with -Werror would quickly tell us of any places
where we forget to check memory allocations for failure, and we'd make
code like from capabilities.c:
if ((guest->arch.defaultInfo.machines =
calloc(nmachines,
sizeof(*guest->arch.defaultInfo.machines))) == NULL)
return -1;
char **migrateTrans;
if ((migrateTrans = realloc(caps->host.migrateTrans,
sizeof(*migrateTrans) *
(caps->host.nmigrateTrans+1))) == NULL)
return -1;
caps->host.migrateTrans = migrateTrans;
Much less ugly:
if (VIR_ALLOC_N(guest->arch.defaultInfo.machines, nmachines) < 0)
return -1;
if (VIR_REALLOC(migrateTrans, caps->host.nmigrateTrans+1) < 0)
return -1;
So we've addressed all 7 common error scenarios with malloc/free/realloc/caller
and produced easier to read code too. The cleaner realloc() API is particularly
appealing.
This does all seem a little bit too good to be true - I'm wondering why other
apps/libraries don't use this style of allocation functions already ? Perhaps
someone can find nasty flaws in this approach, but hopefuly not...
hash.c | 113 ++++++++++++++++++++++--------------------------
memory.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
memory.h | 95 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 294 insertions(+), 60 deletions(-)
Regards,
Daniel.
Index: memory.h
===================================================================
RCS file: memory.h
diff -N memory.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ memory.h 27 Apr 2008 19:04:28 -0000
@@ -0,0 +1,95 @@
+/*
+ * memory.c: safer memory allocation
+ *
+ * Copyright (C) 2008 Daniel P. 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
+ *
+ */
+
+
+#ifndef __VIR_MEMORY_H_
+#define __VIR_MEMORY_H_
+
+#include "internal.h"
+
+/* Don't call these directly - use the macros below */
+int virAlloc(void *ptrptr, size_t size) ATTRIBUTE_RETURN_CHECK;
+int virAllocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK;
+int virRealloc(void *ptrptr, size_t size) ATTRIBUTE_RETURN_CHECK;
+int virReallocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK;
+void virFree(void *ptrptr);
+
+
+/**
+ * VIR_ALLOC:
+ * @ptr: pointer to hold address of allocated memory
+ *
+ * Allocate sizeof(*ptr) bytes of memory and store
+ * the address of allocated memory in 'ptr'. Fill the
+ * newly allocated memory with zeros.
+ *
+ * Returns -1 on failure, 0 on success
+ */
+#define VIR_ALLOC(ptr) virAlloc(&(ptr), sizeof(*(ptr)))
+
+/**
+ * VIR_ALLOC_N:
+ * @ptr: pointer to hold address of allocated memory
+ * @count: number of elements to allocate
+ *
+ * Allocate an array of 'count' elements, each sizeof(*ptr)
+ * bytes long and store the address of allocated memory in
+ * 'ptr'. Fill the newly allocated memory with zeros.
+ *
+ * Returns -1 on failure, 0 on success
+ */
+#define VIR_ALLOC_N(ptr, count) virAllocN(&(ptr), sizeof(*(ptr)), (count))
+
+/**
+ * VIR_REALLOC:
+ * @ptr: pointer to hold address of allocated memory
+ *
+ * Re-allocate to sizeof(*ptr) bytes of memory and store
+ * the address of allocated memory in 'ptr'. Fill the
+ * newly allocated memory with zeros
+ *
+ * Returns -1 on failure, 0 on success
+ */
+#define VIR_REALLOC(ptr) virRealloc(&(ptr), sizeof(*(ptr)))
+
+/**
+ * VIR_REALLOC_N:
+ * @ptr: pointer to hold address of allocated memory
+ * @count: number of elements to allocate
+ *
+ * Re-allocate an array of 'count' elements, each sizeof(*ptr)
+ * bytes long and store the address of allocated memory in
+ * 'ptr'. Fill the newly allocated memory with zeros
+ *
+ * Returns -1 on failure, 0 on success
+ */
+#define VIR_REALLOC_N(ptr, count) virReallocN(&(ptr), sizeof(*(ptr)), (count))
+
+/**
+ * VIR_FREE:
+ * @ptr: pointer holding address to be freed
+ *
+ * Free the memory stored in 'ptr' and update to point
+ * to NULL.
+ */
+#define VIR_FREE(ptr) virFree(&(ptr))
+
+#endif /* __VIR_MEMORY_H_ */
Index: memory.c
===================================================================
RCS file: memory.c
diff -N memory.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ memory.c 27 Apr 2008 19:04:28 -0000
@@ -0,0 +1,146 @@
+/*
+ * memory.c: safer memory allocation
+ *
+ * Copyright (C) 2008 Daniel P. 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
+ *
+ */
+
+#include <stdlib.h>
+
+#include "memory.h"
+
+/**
+ * virAlloc:
+ * @ptrptr: pointer to pointer for address of allocated memory
+ * @size: number of bytes to allocate
+ *
+ * Allocate 'size' bytes of memory. Return the address of the
+ * allocated memory in 'ptrptr'. The newly allocated memory is
+ * filled with zeros.
+ *
+ * Returns -1 on failure to allocate, zero on success
+ */
+int virAlloc(void *ptrptr, size_t size)
+{
+ if (size == 0) {
+ *(void **)ptrptr = NULL;
+ return 0;
+ }
+
+ *(void **)ptrptr = calloc(1, size);
+ if (*(void **)ptrptr == NULL)
+ return -1;
+ return 0;
+}
+
+/**
+ * virAllocN:
+ * @ptrptr: pointer to pointer for address of allocated memory
+ * @size: number of bytes to allocate
+ * @count: number of elements to allocate
+ *
+ * Allocate an array of memory 'count' elements long,
+ * each with 'size' bytes. Return the address of the
+ * allocated memory in 'ptrptr'. The newly allocated
+ * memory is filled with zeros.
+ *
+ * Returns -1 on failure to allocate, zero on success
+ */
+int virAllocN(void *ptrptr, size_t size, size_t count)
+{
+ if (size == 0 || count == 0) {
+ *(void **)ptrptr = NULL;
+ return 0;
+ }
+
+ *(void**)ptrptr = calloc(count, size);
+ if (*(void**)ptrptr == NULL)
+ return -1;
+ return 0;
+}
+
+/**
+ * virRealloc:
+ * @ptrptr: pointer to pointer for address of allocated memory
+ * @size: number of bytes to allocate
+ *
+ * Resize the block of memory in 'ptrptr' to be 'size' bytes
+ * in length. Update 'ptrptr' with the address of the newly
+ * allocated memory. On failure, 'ptrptr' is not changed and
+ * still points to the original memory block. The newly
+ * allocated memory is filled with zeros.
+ *
+ * Returns -1 on failure to allocate, zero on success
+ */
+int virRealloc(void *ptrptr, size_t size)
+{
+ void *tmp;
+ if (size == 0) {
+ free(*(void **)ptrptr);
+ *(void **)ptrptr = NULL;
+ return 0;
+ }
+
+ tmp = realloc(*(void**)ptrptr, size);
+ if (!tmp)
+ return -1;
+ *(void**)ptrptr = tmp;
+ return 0;
+}
+
+/**
+ * virReallocN:
+ * @ptrptr: pointer to pointer for address of allocated memory
+ * @size: number of bytes to allocate
+ * @count: number of elements in array
+ *
+ * Resize the block of memory in 'ptrptr' to be an array of
+ * 'count' elements, each 'size' bytes in length. Update 'ptrptr'
+ * with the address of the newly allocated memory. On failure,
+ * 'ptrptr' is not changed and still points to the original memory
+ * block. The newly allocated memory is filled with zeros.
+ *
+ * Returns -1 on failure to allocate, zero on success
+ */
+int virReallocN(void *ptrptr, size_t size, size_t count)
+{
+ void *tmp;
+ if (size == 0 || count == 0) {
+ free(*(void **)ptrptr);
+ *(void **)ptrptr = NULL;
+ return 0;
+ }
+ tmp = realloc(*(void**)ptrptr, size * count);
+ if (!tmp)
+ return -1;
+ *(void**)ptrptr = tmp;
+ return 0;
+}
+
+/**
+ * virFree:
+ * @ptrptr: pointer to pointer for address of memory to be freed
+ *
+ * Release the chunk of memory in the pointer pointed to by
+ * the 'ptrptr' variable. After release, 'ptrptr' will be
+ * updated to point to NULL.
+ */
+void virFree(void *ptrptr)
+{
+ free(*(void**)ptrptr);
+ *(void**)ptrptr = NULL;
+}
Index: hash.c
===================================================================
RCS file: /data/cvs/libvirt/src/hash.c,v
retrieving revision 1.37
diff -u -p -r1.37 hash.c
--- hash.c 18 Apr 2008 08:33:23 -0000 1.37
+++ hash.c 27 Apr 2008 19:04:28 -0000
@@ -25,6 +25,7 @@
#include <libxml/threads.h>
#include "internal.h"
#include "hash.h"
+#include "memory.h"
#define MAX_HASH_LEN 8
@@ -85,22 +86,22 @@ virHashComputeKey(virHashTablePtr table,
virHashTablePtr
virHashCreate(int size)
{
- virHashTablePtr table;
+ virHashTablePtr table = NULL;
if (size <= 0)
size = 256;
- table = malloc(sizeof(*table));
- if (table) {
- table->size = size;
- table->nbElems = 0;
- table->table = calloc(1, size * sizeof(*(table->table)));
- if (table->table) {
- return (table);
- }
- free(table);
+ if (VIR_ALLOC(table) < 0)
+ return NULL;
+
+ table->size = size;
+ table->nbElems = 0;
+ if (VIR_ALLOC_N(table->table, size) < 0) {
+ VIR_FREE(table);
+ return NULL;
}
- return (NULL);
+
+ return table;
}
/**
@@ -136,8 +137,7 @@ virHashGrow(virHashTablePtr table, int s
if (oldtable == NULL)
return (-1);
- table->table = calloc(1, size * sizeof(*(table->table)));
- if (table->table == NULL) {
+ if (VIR_ALLOC_N(table->table, size) < 0) {
table->table = oldtable;
return (-1);
}
@@ -170,7 +170,7 @@ virHashGrow(virHashTablePtr table, int s
if (table->table[key].valid == 0) {
memcpy(&(table->table[key]), iter, sizeof(virHashEntry));
table->table[key].next = NULL;
- free(iter);
+ VIR_FREE(iter);
} else {
iter->next = table->table[key].next;
table->table[key].next = iter;
@@ -184,7 +184,7 @@ virHashGrow(virHashTablePtr table, int s
}
}
- free(oldtable);
+ VIR_FREE(oldtable);
#ifdef DEBUG_GROW
xmlGenericError(xmlGenericErrorContext,
@@ -225,19 +225,19 @@ virHashFree(virHashTablePtr table, virHa
next = iter->next;
if ((f != NULL) && (iter->payload != NULL))
f(iter->payload, iter->name);
- free(iter->name);
+ VIR_FREE(iter->name);
iter->payload = NULL;
if (!inside_table)
- free(iter);
+ VIR_FREE(iter);
nbElems--;
inside_table = 0;
iter = next;
}
inside_table = 0;
}
- free(table->table);
+ VIR_FREE(table->table);
}
- free(table);
+ VIR_FREE(table);
}
/**
@@ -281,8 +281,7 @@ virHashAddEntry(virHashTablePtr table, c
if (insert == NULL) {
entry = &(table->table[key]);
} else {
- entry = malloc(sizeof(*entry));
- if (entry == NULL)
+ if (VIR_ALLOC(entry) < 0)
return (-1);
}
@@ -354,8 +353,7 @@ virHashUpdateEntry(virHashTablePtr table
if (insert == NULL) {
entry = &(table->table[key]);
} else {
- entry = malloc(sizeof(*entry));
- if (entry == NULL)
+ if (VIR_ALLOC(entry) < 0)
return (-1);
}
@@ -451,10 +449,10 @@ virHashRemoveEntry(virHashTablePtr table
if ((f != NULL) && (entry->payload != NULL))
f(entry->payload, entry->name);
entry->payload = NULL;
- free(entry->name);
+ VIR_FREE(entry->name);
if (prev) {
prev->next = entry->next;
- free(entry);
+ VIR_FREE(entry);
} else {
if (entry->next == NULL) {
entry->valid = 0;
@@ -462,7 +460,7 @@ virHashRemoveEntry(virHashTablePtr table
entry = entry->next;
memcpy(&(table->table[key]), entry,
sizeof(virHashEntry));
- free(entry);
+ VIR_FREE(entry);
}
}
table->nbElems--;
@@ -535,11 +533,11 @@ int virHashRemoveSet(virHashTablePtr tab
if (iter(entry->payload, entry->name, data)) {
count++;
f(entry->payload, entry->name);
- free(entry->name);
+ VIR_FREE(entry->name);
table->nbElems--;
if (prev) {
prev->next = entry->next;
- free(entry);
+ VIR_FREE(entry);
entry = prev;
} else {
if (entry->next == NULL) {
@@ -549,7 +547,7 @@ int virHashRemoveSet(virHashTablePtr tab
entry = entry->next;
memcpy(&(table->table[i]), entry,
sizeof(virHashEntry));
- free(entry);
+ VIR_FREE(entry);
entry = &(table->table[i]);
continue;
}
@@ -689,8 +687,7 @@ virConnectPtr
virGetConnect(void) {
virConnectPtr ret;
- ret = calloc(1, sizeof(*ret));
- if (ret == NULL) {
+ if (VIR_ALLOC(ret) < 0) {
virHashError(NULL, VIR_ERR_NO_MEMORY, _("allocating connection"));
goto failed;
}
@@ -729,7 +726,7 @@ failed:
virHashFree(ret->storageVols, (virHashDeallocator) virStorageVolFreeName);
pthread_mutex_destroy(&ret->lock);
- free(ret);
+ VIR_FREE(ret);
}
return(NULL);
}
@@ -759,11 +756,11 @@ virReleaseConnect(virConnectPtr conn) {
if (__lastErr.conn == conn)
__lastErr.conn = NULL;
- free(conn->name);
+ VIR_FREE(conn->name);
pthread_mutex_unlock(&conn->lock);
pthread_mutex_destroy(&conn->lock);
- free(conn);
+ VIR_FREE(conn);
}
/**
@@ -824,8 +821,7 @@ __virGetDomain(virConnectPtr conn, const
ret = (virDomainPtr) virHashLookup(conn->domains, name);
/* TODO check the UUID */
if (ret == NULL) {
- ret = (virDomainPtr) calloc(1, sizeof(*ret));
- if (ret == NULL) {
+ if (VIR_ALLOC(ret) < 0) {
virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating domain"));
goto error;
}
@@ -854,8 +850,8 @@ __virGetDomain(virConnectPtr conn, const
error:
pthread_mutex_unlock(&conn->lock);
if (ret != NULL) {
- free(ret->name );
- free(ret);
+ VIR_FREE(ret->name);
+ VIR_FREE(ret);
}
return(NULL);
}
@@ -888,8 +884,8 @@ virReleaseDomain(virDomainPtr domain) {
__lastErr.dom = NULL;
domain->magic = -1;
domain->id = -1;
- free(domain->name);
- free(domain);
+ VIR_FREE(domain->name);
+ VIR_FREE(domain);
DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs);
conn->refs--;
@@ -962,8 +958,7 @@ __virGetNetwork(virConnectPtr conn, cons
ret = (virNetworkPtr) virHashLookup(conn->networks, name);
/* TODO check the UUID */
if (ret == NULL) {
- ret = (virNetworkPtr) calloc(1, sizeof(*ret));
- if (ret == NULL) {
+ if (VIR_ALLOC(ret) < 0) {
virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating network"));
goto error;
}
@@ -991,8 +986,8 @@ __virGetNetwork(virConnectPtr conn, cons
error:
pthread_mutex_unlock(&conn->lock);
if (ret != NULL) {
- free(ret->name );
- free(ret);
+ VIR_FREE(ret->name);
+ VIR_FREE(ret);
}
return(NULL);
}
@@ -1025,8 +1020,8 @@ virReleaseNetwork(virNetworkPtr network)
__lastErr.net = NULL;
network->magic = -1;
- free(network->name);
- free(network);
+ VIR_FREE(network->name);
+ VIR_FREE(network);
DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs);
conn->refs--;
@@ -1100,8 +1095,7 @@ __virGetStoragePool(virConnectPtr conn,
ret = (virStoragePoolPtr) virHashLookup(conn->storagePools, name);
/* TODO check the UUID */
if (ret == NULL) {
- ret = (virStoragePoolPtr) calloc(1, sizeof(*ret));
- if (ret == NULL) {
+ if (VIR_ALLOC(ret) < 0) {
virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating storage pool"));
goto error;
}
@@ -1129,8 +1123,8 @@ __virGetStoragePool(virConnectPtr conn,
error:
pthread_mutex_unlock(&conn->lock);
if (ret != NULL) {
- free(ret->name);
- free(ret);
+ VIR_FREE(ret->name);
+ VIR_FREE(ret);
}
return(NULL);
}
@@ -1159,8 +1153,8 @@ virReleaseStoragePool(virStoragePoolPtr
_("pool missing from connection hash table"));
pool->magic = -1;
- free(pool->name);
- free(pool);
+ VIR_FREE(pool->name);
+ VIR_FREE(pool);
DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs);
conn->refs--;
@@ -1232,8 +1226,7 @@ __virGetStorageVol(virConnectPtr conn, c
ret = (virStorageVolPtr) virHashLookup(conn->storageVols, key);
if (ret == NULL) {
- ret = (virStorageVolPtr) calloc(1, sizeof(*ret));
- if (ret == NULL) {
+ if (VIR_ALLOC(ret) < 0) {
virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating storage vol"));
goto error;
}
@@ -1266,9 +1259,9 @@ __virGetStorageVol(virConnectPtr conn, c
error:
pthread_mutex_unlock(&conn->lock);
if (ret != NULL) {
- free(ret->name);
- free(ret->pool);
- free(ret);
+ VIR_FREE(ret->name);
+ VIR_FREE(ret->pool);
+ VIR_FREE(ret);
}
return(NULL);
}
@@ -1297,9 +1290,9 @@ virReleaseStorageVol(virStorageVolPtr vo
_("vol missing from connection hash table"));
vol->magic = -1;
- free(vol->name);
- free(vol->pool);
- free(vol);
+ VIR_FREE(vol->name);
+ VIR_FREE(vol->pool);
+ VIR_FREE(vol);
DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs);
conn->refs--;
--
|: Red Hat, Engineering, Boston -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 :|
6
18
The following set of changes adjust the way errors are handled in the
virBuffer routines. The key idea is to make it hard (impossible) to
misuse the API, with each change addressing one of the errors scenarios
I've found in existing code using the routines.
- The contents of the struct are no longer public.
Rationale: This stops people accessing the buffer directly,
thus preventing use of data which may be in an error state.
- All virBuffer objects must now be declared on the stack and
initialized with the static VIR_BUFFER_INITIALIZER, instead
of the virBufferNew() allocator
Rationale: avoids the need to check virBufferNew for allocation
failure, and avoids a potential memory leak of the virBuffer
object itself.
- The buffer content can only be accessed via the public API
virBufferContentAndReset(). This returns the internal char *
content, and resets the state of the buffer.
Rationale: the caller can only obtain the internal content if
the buffer is in a known good state. On error they'll be given
back a NULL, rather than potentially incomplete / malformed
data.
- The virBufferAdd/VSprintf/etc routines for appending to the
buffer are all void and set the internal error flag upon
failure and immediately free the internal content.
Rationale: the caller will never see a potentially incomplete
buffer, and avoids the potential of leaking the memory for the
internal buffer in cleanup paths.
So in using the APIs, there are now only a handful of very low
impact errors the caller can make:
- Forget to initialize the buffer with VIR_BUFFER_INITIALIZER.
The compiler will warn about this, so it is harmless.
- Forget to free() the content from virBufferContentAndReset.
This data is typically propagated to the caller's caller
for free()ing anyway, so not an issue.
- Forget to check the error flag before asking for the internal
content. If the error flag is set the internal content will
have been free'd and they'll be given back NULL. So the caller
will not see incomplete data.
So the worst case behaviour is a leak of the buffer content, or
failing to raise a libvirt error when the buffer has an error.
The general style of usage now looks like
char *
somefunction(...) {
virBuffer buf = VIR_BUFFER_INITIALIZER;
...
virBufferAdd(&buf, "<domain>\n");
virBufferVSprint(&buf, " <memory>%d</memory>\n", memory);
...
virBufferAdd(&buf, "</domain>\n");
....
if (virBufferError(&buf)) {
__virRaiseError(...);
return NULL;
}
return virBufferContentAndReset(&buf);
}
In fixing up all the uses of virBuffer routines in existing driver
code I encountered every error condition mentioned here. Most of
these would have resulted in either memory leaks, or passing a
malformed XML document to another routine, so with the additional
code clarity gained by removing the gotos this is very useful
cleanup.
src/buf.c | 241 ++++++++++++++++-------------
src/buf.h | 50 ++++--
src/capabilities.c | 187 ++++++++--------------
src/conf.c | 77 ++++-----
src/libvirt_sym.version | 2
src/lxc_conf.c | 104 +++---------
src/qemu_conf.c | 391 ++++++++++++++++++------------------------------
src/qparams.c | 15 +
src/storage_conf.c | 227 ++++++++++-----------------
src/test.c | 74 ++++-----
src/virsh.c | 158 ++++++++-----------
src/xend_internal.c | 126 ++++++---------
src/xm_internal.c | 184 ++++++++++------------
src/xml.c | 101 +++++-------
src/xmlrpc.c | 22 +-
src/xmlrpc.h | 5
tests/xmlrpctest.c | 81 ++++-----
17 files changed, 898 insertions(+), 1147 deletions(-)
Regards,
Daniel.
Index: src/buf.c
===================================================================
RCS file: /data/cvs/libvirt/src/buf.c,v
retrieving revision 1.15
diff -u -p -r1.15 buf.c
--- src/buf.c 10 Apr 2008 16:54:54 -0000 1.15
+++ src/buf.c 26 Apr 2008 16:24:38 -0000
@@ -18,8 +18,37 @@
#include <stdarg.h>
#include <ctype.h>
+#define __VIR_BUFFER_C__
+
#include "buf.h"
+
+/* If adding more fields, ensure to edit buf.h to increase
+ the public __SIZEOF_VIR_BUFFER constant */
+struct _virBuffer {
+ unsigned int size;
+ unsigned int use;
+ unsigned int error;
+ char *content;
+};
+
+/**
+ * virBufferFail
+ * @buf: the buffer
+ *
+ * Mark the buffer has having failed a memory allocation,
+ * freeing the content and setting the error flag.
+ */
+static void
+virBufferNoMemory(const virBufferPtr buf)
+{
+ free(buf->content);
+ buf->content = NULL;
+ buf->size = 0;
+ buf->use = 0;
+ buf->error = 1;
+}
+
/**
* virBufferGrow:
* @buf: the buffer
@@ -27,7 +56,7 @@
*
* Grow the available space of a buffer to at least @len bytes.
*
- * Returns the new available space or -1 in case of error
+ * Returns zero on success or -1 on error
*/
static int
virBufferGrow(virBufferPtr buf, unsigned int len)
@@ -35,18 +64,22 @@ virBufferGrow(virBufferPtr buf, unsigned
int size;
char *newbuf;
- if (buf == NULL)
- return (-1);
- if (len + buf->use < buf->size)
- return (0);
+ if (buf->error)
+ return -1;
+
+ if ((len + buf->use) < buf->size)
+ return 0;
size = buf->use + len + 1000;
newbuf = realloc(buf->content, size);
- if (newbuf == NULL) return -1;
+ if (newbuf == NULL) {
+ virBufferNoMemory(buf);
+ return -1;
+ }
buf->content = newbuf;
buf->size = size;
- return (buf->size - buf->use);
+ return 0;
}
/**
@@ -58,33 +91,29 @@ virBufferGrow(virBufferPtr buf, unsigned
* Add a string range to an XML buffer. if len == -1, the length of
* str is recomputed to the full string.
*
- * Returns 0 successful, -1 in case of internal or API error.
*/
-int
-__virBufferAdd(virBufferPtr buf, const char *str, int len)
+void
+__virBufferAdd(const virBufferPtr buf, const char *str, int len)
{
unsigned int needSize;
- if ((str == NULL) || (buf == NULL)) {
- return -1;
- }
- if (len == 0)
- return 0;
+ if ((str == NULL) || (buf == NULL) || (len == 0))
+ return;
+
+ if (buf->error)
+ return;
if (len < 0)
len = strlen(str);
needSize = buf->use + len + 2;
- if (needSize > buf->size) {
- if (!virBufferGrow(buf, needSize - buf->use)) {
- return (-1);
- }
- }
+ if (needSize > buf->size &&
+ virBufferGrow(buf, needSize - buf->use) < 0)
+ return;
memcpy (&buf->content[buf->use], str, len);
buf->use += len;
- buf->content[buf->use] = 0;
- return (0);
+ buf->content[buf->use] = '\0';
}
/**
@@ -94,89 +123,85 @@ __virBufferAdd(virBufferPtr buf, const c
*
* Add a single character 'c' to a buffer.
*
- * Returns 0 if successful, -1 in the case of error.
*/
-int
+void
__virBufferAddChar (virBufferPtr buf, char c)
{
unsigned int needSize;
if (buf == NULL)
- return -1;
+ return;
+
+ if (buf->error)
+ return;
needSize = buf->use + 2;
- if (needSize > buf->size)
- if (!virBufferGrow (buf, needSize - buf->use))
- return -1;
+ if (needSize > buf->size &&
+ virBufferGrow (buf, needSize - buf->use) < 0)
+ return;
buf->content[buf->use++] = c;
- buf->content[buf->use] = 0;
-
- return 0;
+ buf->content[buf->use] = '\0';
}
/**
- * virBufferNew:
- * @size: creation size in bytes
+ * virBufferContentAndReset:
+ * @buf: Buffer
*
- * Creates a new buffer
+ * Get the content from the buffer and free (only) the buffer structure.
+ * The caller owns the returned string & should free it when no longer
+ * required. The buffer object is reset to its initial state.
*
- * Returns a pointer to the buffer or NULL in case of error
+ * Returns the buffer content or NULL in case of error.
*/
-virBufferPtr
-virBufferNew(unsigned int size)
+char *
+__virBufferContentAndReset(const virBufferPtr buf)
{
- virBufferPtr buf;
+ char *str;
+ if (buf == NULL)
+ return NULL;
- if (!(buf = malloc(sizeof(*buf)))) return NULL;
- if (size && (buf->content = malloc(size))==NULL) {
- free(buf);
+ if (buf->error) {
+ memset(buf, 0, sizeof(*buf));
return NULL;
}
- buf->size = size;
- buf->use = 0;
- return buf;
+ str = buf->content;
+ memset(buf, 0, sizeof(*buf));
+ return str;
}
/**
- * virBufferFree:
- * @buf: the buffer to deallocate
+ * virBufferError:
+ * @buf: the buffer
*
- * Free the set of resources used by a buffer.
+ * Check to see if the buffer is in an error state due
+ * to failed memory allocation
+ *
+ * Return true if in error, 0 if normal
*/
-
-void
-virBufferFree(virBufferPtr buf)
+int
+__virBufferError(const virBufferPtr buf)
{
- if (buf) {
- free(buf->content);
- free(buf);
- }
+ if (buf == NULL)
+ return 1;
+
+ return buf->error;
}
/**
- * virBufferContentAndFree:
- * @buf: Buffer
+ * virBufferUse:
+ * @buf: the usage of the string in the buffer
*
- * Get the content from the buffer and free (only) the buffer structure.
- *
- * Returns the buffer content or NULL in case of error.
+ * Return the string usage in bytes
*/
-char *
-virBufferContentAndFree (virBufferPtr buf)
+unsigned int
+virBufferUse(const virBufferPtr buf)
{
- char *content;
-
if (buf == NULL)
- return(NULL);
-
- content = buf->content;
- if (content != NULL)
- content[buf->use] = 0;
+ return 0;
- free (buf);
- return(content);
+ return buf->use;
}
/**
@@ -186,22 +211,22 @@ virBufferContentAndFree (virBufferPtr bu
* @...: the variable list of arguments
*
* Do a formatted print to an XML buffer.
- *
- * Returns 0 successful, -1 in case of internal or API error.
*/
-int
-__virBufferVSprintf(virBufferPtr buf, const char *format, ...)
+void
+__virBufferVSprintf(const virBufferPtr buf, const char *format, ...)
{
int size, count, grow_size;
va_list locarg, argptr;
- if ((format == NULL) || (buf == NULL)) {
- return (-1);
- }
+ if ((format == NULL) || (buf == NULL))
+ return;
+
+ if (buf->error)
+ return;
if (buf->size == 0 &&
virBufferGrow(buf, 100) < 0)
- return -1;
+ return;
size = buf->size - buf->use - 1;
va_start(argptr, format);
@@ -210,17 +235,17 @@ __virBufferVSprintf(virBufferPtr buf, co
locarg)) < 0) || (count >= size - 1)) {
buf->content[buf->use] = 0;
va_end(locarg);
+
grow_size = (count > 1000) ? count : 1000;
- if (virBufferGrow(buf, grow_size) < 0) {
- return (-1);
- }
+ if (virBufferGrow(buf, grow_size) < 0)
+ return;
+
size = buf->size - buf->use - 1;
va_copy(locarg, argptr);
}
va_end(locarg);
buf->use += count;
- buf->content[buf->use] = 0;
- return (0);
+ buf->content[buf->use] = '\0';
}
/**
@@ -231,25 +256,27 @@ __virBufferVSprintf(virBufferPtr buf, co
*
* Do a formatted print with a single string to an XML buffer. The string
* is escaped to avoid generating a not well-formed XML instance.
- *
- * Returns 0 successful, -1 in case of internal or API error.
*/
-int
-virBufferEscapeString(virBufferPtr buf, const char *format, const char *str)
+void
+virBufferEscapeString(const virBufferPtr buf, const char *format, const char *str)
{
int size, count, len, grow_size;
char *escaped, *out;
const char *cur;
- if ((format == NULL) || (buf == NULL) || (str == NULL)) {
- return (-1);
- }
+ if ((format == NULL) || (buf == NULL) || (str == NULL))
+ return;
+
+ if (buf->error)
+ return;
len = strlen(str);
escaped = malloc(5 * len + 1);
if (escaped == NULL) {
- return (-1);
+ virBufferNoMemory(buf);
+ return;
}
+
cur = str;
out = escaped;
while (*cur != 0) {
@@ -290,14 +317,13 @@ virBufferEscapeString(virBufferPtr buf,
grow_size = (count > 1000) ? count : 1000;
if (virBufferGrow(buf, grow_size) < 0) {
free(escaped);
- return (-1);
+ return;
}
size = buf->size - buf->use - 1;
}
buf->use += count;
- buf->content[buf->use] = 0;
+ buf->content[buf->use] = '\0';
free(escaped);
- return (0);
}
/**
@@ -308,10 +334,8 @@ virBufferEscapeString(virBufferPtr buf,
* Append the string to the buffer. The string will be URI-encoded
* during the append (ie any non alpha-numeric characters are replaced
* with '%xx' hex sequences).
- *
- * Returns 0 successful, -1 in case of internal or API error.
*/
-int
+void
virBufferURIEncodeString (virBufferPtr buf, const char *str)
{
int grow_size = 0;
@@ -319,6 +343,12 @@ virBufferURIEncodeString (virBufferPtr b
unsigned char uc;
const char *hex = "0123456789abcdef";
+ if ((buf == NULL) || (str == NULL))
+ return;
+
+ if (buf->error)
+ return;
+
for (p = str; *p; ++p) {
/* This may not work on EBCDIC. */
if ((*p >= 'a' && *p <= 'z') ||
@@ -329,8 +359,8 @@ virBufferURIEncodeString (virBufferPtr b
grow_size += 3; /* %ab */
}
- if (virBufferGrow (buf, grow_size) == -1)
- return -1;
+ if (virBufferGrow (buf, grow_size) < 0)
+ return;
for (p = str; *p; ++p) {
/* This may not work on EBCDIC. */
@@ -347,7 +377,6 @@ virBufferURIEncodeString (virBufferPtr b
}
buf->content[buf->use] = '\0';
- return 0;
}
/**
@@ -356,15 +385,16 @@ virBufferURIEncodeString (virBufferPtr b
* @...: the variable list of strings, the last argument must be NULL
*
* Concatenate strings to an XML buffer.
- *
- * Returns 0 successful, -1 in case of internal or API error.
*/
-int
+void
virBufferStrcat(virBufferPtr buf, ...)
{
va_list ap;
char *str;
+ if (buf->error)
+ return;
+
va_start(ap, buf);
while ((str = va_arg(ap, char *)) != NULL) {
@@ -372,13 +402,12 @@ virBufferStrcat(virBufferPtr buf, ...)
unsigned int needSize = buf->use + len + 2;
if (needSize > buf->size) {
- if (!virBufferGrow(buf, needSize - buf->use))
- return -1;
+ if (virBufferGrow(buf, needSize - buf->use) < 0)
+ return;
}
memcpy(&buf->content[buf->use], str, len);
buf->use += len;
buf->content[buf->use] = 0;
}
va_end(ap);
- return 0;
}
Index: src/buf.h
===================================================================
RCS file: /data/cvs/libvirt/src/buf.h,v
retrieving revision 1.5
diff -u -p -r1.5 buf.h
--- src/buf.h 20 Feb 2008 15:29:13 -0000 1.5
+++ src/buf.h 26 Apr 2008 16:24:38 -0000
@@ -20,22 +20,45 @@
*/
typedef struct _virBuffer virBuffer;
typedef virBuffer *virBufferPtr;
+
+#ifndef __VIR_BUFFER_C__
+/* This constant must match size of the actual struct
+ in the buf.c file */
+#if __WORDSIZE == 64
+#define __SIZEOF_VIR_BUFFER 32
+#define VIR_BUFFER_INITIALIZER { { 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, 0 \
+ } }
+#else
+#define __SIZEOF_VIR_BUFFER 16
+#define VIR_BUFFER_INITIALIZER { { 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, 0 \
+ } }
+#endif
struct _virBuffer {
- char *content; /* The buffer content UTF8 */
- unsigned int use; /* The buffer size used */
- unsigned int size; /* The buffer size */
+ char *padding[__SIZEOF_VIR_BUFFER]; /* This struct contents is private */
};
-virBufferPtr virBufferNew(unsigned int size);
-void virBufferFree(virBufferPtr buf);
-char *virBufferContentAndFree(virBufferPtr buf);
-int __virBufferAdd(virBufferPtr buf, const char *str, int len);
-int __virBufferAddChar(virBufferPtr buf, char c);
-int __virBufferVSprintf(virBufferPtr buf, const char *format, ...)
+#endif
+
+char *__virBufferContentAndReset(const virBufferPtr buf);
+int __virBufferError(const virBufferPtr buf);
+unsigned int virBufferUse(const virBufferPtr buf);
+void __virBufferAdd(const virBufferPtr buf, const char *str, int len);
+void __virBufferAddChar(const virBufferPtr buf, char c);
+void __virBufferVSprintf(const virBufferPtr buf, const char *format, ...)
ATTRIBUTE_FORMAT(printf, 2, 3);
-int virBufferStrcat(virBufferPtr buf, ...);
-int virBufferEscapeString(virBufferPtr buf, const char *format, const char *str);
-int virBufferURIEncodeString (virBufferPtr buf, const char *str);
+void virBufferStrcat(const virBufferPtr buf, ...);
+void virBufferEscapeString(const virBufferPtr buf, const char *format, const char *str);
+void virBufferURIEncodeString (const virBufferPtr buf, const char *str);
#define virBufferAddLit(buf_, literal_string_) \
__virBufferAdd (buf_, "" literal_string_ "", sizeof literal_string_ - 1)
@@ -44,4 +67,7 @@ int virBufferURIEncodeString (virBufferP
#define virBufferAddChar(b,c) __virBufferAddChar((b),(c))
#define virBufferVSprintf(b,f,...) __virBufferVSprintf((b),(f), __VA_ARGS__)
+#define virBufferContentAndReset(b) __virBufferContentAndReset((b))
+#define virBufferError(b) __virBufferError((b))
+
#endif /* __VIR_BUFFER_H__ */
Index: src/capabilities.c
===================================================================
RCS file: /data/cvs/libvirt/src/capabilities.c,v
retrieving revision 1.6
diff -u -p -r1.6 capabilities.c
--- src/capabilities.c 10 Apr 2008 16:53:29 -0000 1.6
+++ src/capabilities.c 26 Apr 2008 16:24:39 -0000
@@ -521,172 +521,127 @@ virCapabilitiesDefaultGuestEmulator(virC
char *
virCapabilitiesFormatXML(virCapsPtr caps)
{
- virBuffer xml = { NULL, 0, 0 };
+ virBuffer xml = VIR_BUFFER_INITIALIZER;
int i, j, k;
- if (virBufferAddLit(&xml, "<capabilities>\n\n") < 0)
- goto no_memory;
- if (virBufferAddLit(&xml, " <host>\n") < 0)
- goto no_memory;
- if (virBufferAddLit(&xml, " <cpu>\n") < 0)
- goto no_memory;
- if (virBufferVSprintf(&xml, " <arch>%s</arch>\n",
- caps->host.arch) < 0)
- goto no_memory;
+ virBufferAddLit(&xml, "<capabilities>\n\n");
+ virBufferAddLit(&xml, " <host>\n");
+ virBufferAddLit(&xml, " <cpu>\n");
+ virBufferVSprintf(&xml, " <arch>%s</arch>\n",
+ caps->host.arch);
if (caps->host.nfeatures) {
- if (virBufferAddLit(&xml, " <features>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&xml, " <features>\n");
for (i = 0 ; i < caps->host.nfeatures ; i++) {
- if (virBufferVSprintf(&xml, " <%s/>\n",
- caps->host.features[i]) <0)
- goto no_memory;
+ virBufferVSprintf(&xml, " <%s/>\n",
+ caps->host.features[i]);
}
- if (virBufferAddLit(&xml, " </features>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&xml, " </features>\n");
}
- if (virBufferAddLit(&xml, " </cpu>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&xml, " </cpu>\n");
if (caps->host.offlineMigrate) {
- if (virBufferAddLit(&xml, " <migration_features>\n") < 0)
- goto no_memory;
- if (caps->host.liveMigrate &&
- virBufferAddLit(&xml, " <live/>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&xml, " <migration_features>\n");
+ if (caps->host.liveMigrate)
+ virBufferAddLit(&xml, " <live/>\n");
if (caps->host.nmigrateTrans) {
- if (virBufferAddLit(&xml, " <uri_transports>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&xml, " <uri_transports>\n");
for (i = 0 ; i < caps->host.nmigrateTrans ; i++) {
- if (virBufferVSprintf(&xml, " <uri_transport>%s</uri_transport>\n",
- caps->host.migrateTrans[i]) < 0)
- goto no_memory;
+ virBufferVSprintf(&xml, " <uri_transport>%s</uri_transport>\n",
+ caps->host.migrateTrans[i]);
}
- if (virBufferAddLit(&xml, " </uri_transports>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&xml, " </uri_transports>\n");
}
- if (virBufferAddLit(&xml, " </migration_features>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&xml, " </migration_features>\n");
}
if (caps->host.nnumaCell) {
- if (virBufferAddLit(&xml, " <topology>\n") < 0)
- goto no_memory;
- if (virBufferVSprintf(&xml, " <cells num='%d'>\n",
- caps->host.nnumaCell) < 0)
- goto no_memory;
+ virBufferAddLit(&xml, " <topology>\n");
+ virBufferVSprintf(&xml, " <cells num='%d'>\n",
+ caps->host.nnumaCell);
for (i = 0 ; i < caps->host.nnumaCell ; i++) {
- if (virBufferVSprintf(&xml, " <cell id='%d'>\n",
- caps->host.numaCell[i]->num) < 0)
- goto no_memory;
- if (virBufferVSprintf(&xml, " <cpus num='%d'>\n",
- caps->host.numaCell[i]->ncpus) < 0)
- goto no_memory;
+ virBufferVSprintf(&xml, " <cell id='%d'>\n",
+ caps->host.numaCell[i]->num);
+ virBufferVSprintf(&xml, " <cpus num='%d'>\n",
+ caps->host.numaCell[i]->ncpus);
for (j = 0 ; j < caps->host.numaCell[i]->ncpus ; j++)
- if (virBufferVSprintf(&xml, " <cpu id='%d'/>\n",
- caps->host.numaCell[i]->cpus[j]) < 0)
- goto no_memory;
- if (virBufferAddLit(&xml, " </cpus>\n") < 0)
- goto no_memory;
- if (virBufferAddLit(&xml, " </cell>\n") < 0)
- goto no_memory;
- }
- if (virBufferAddLit(&xml, " </cells>\n") < 0)
- goto no_memory;
- if (virBufferAddLit(&xml, " </topology>\n") < 0)
- goto no_memory;
+ virBufferVSprintf(&xml, " <cpu id='%d'/>\n",
+ caps->host.numaCell[i]->cpus[j]);
+ virBufferAddLit(&xml, " </cpus>\n");
+ virBufferAddLit(&xml, " </cell>\n");
+ }
+ virBufferAddLit(&xml, " </cells>\n");
+ virBufferAddLit(&xml, " </topology>\n");
}
- if (virBufferAddLit(&xml, " </host>\n\n") < 0)
- goto no_memory;
+ virBufferAddLit(&xml, " </host>\n\n");
for (i = 0 ; i < caps->nguests ; i++) {
- if (virBufferAddLit(&xml, " <guest>\n") < 0)
- goto no_memory;
- if (virBufferVSprintf(&xml, " <os_type>%s</os_type>\n",
- caps->guests[i]->ostype) < 0)
- goto no_memory;
- if (virBufferVSprintf(&xml, " <arch name='%s'>\n",
- caps->guests[i]->arch.name) < 0)
- goto no_memory;
- if (virBufferVSprintf(&xml, " <wordsize>%d</wordsize>\n",
- caps->guests[i]->arch.wordsize) < 0)
- goto no_memory;
- if (caps->guests[i]->arch.defaultInfo.emulator &&
+ virBufferAddLit(&xml, " <guest>\n");
+ virBufferVSprintf(&xml, " <os_type>%s</os_type>\n",
+ caps->guests[i]->ostype);
+ virBufferVSprintf(&xml, " <arch name='%s'>\n",
+ caps->guests[i]->arch.name);
+ virBufferVSprintf(&xml, " <wordsize>%d</wordsize>\n",
+ caps->guests[i]->arch.wordsize);
+ if (caps->guests[i]->arch.defaultInfo.emulator)
virBufferVSprintf(&xml, " <emulator>%s</emulator>\n",
- caps->guests[i]->arch.defaultInfo.emulator) < 0)
- goto no_memory;
- if (caps->guests[i]->arch.defaultInfo.loader &&
- virBufferVSprintf(&xml, " <loader>%s</loader>\n",
- caps->guests[i]->arch.defaultInfo.loader) < 0)
- goto no_memory;
+ caps->guests[i]->arch.defaultInfo.emulator);
+ if (caps->guests[i]->arch.defaultInfo.loader)
+ virBufferVSprintf(&xml, " <loader>%s</loader>\n",
+ caps->guests[i]->arch.defaultInfo.loader);
for (j = 0 ; j < caps->guests[i]->arch.defaultInfo.nmachines ; j++) {
- if (virBufferVSprintf(&xml, " <machine>%s</machine>\n",
- caps->guests[i]->arch.defaultInfo.machines[j]) < 0)
- goto no_memory;
+ virBufferVSprintf(&xml, " <machine>%s</machine>\n",
+ caps->guests[i]->arch.defaultInfo.machines[j]);
}
for (j = 0 ; j < caps->guests[i]->arch.ndomains ; j++) {
- if (virBufferVSprintf(&xml, " <domain type='%s'>\n",
- caps->guests[i]->arch.domains[j]->type) < 0)
- goto no_memory;
- if (caps->guests[i]->arch.domains[j]->info.emulator &&
+ virBufferVSprintf(&xml, " <domain type='%s'>\n",
+ caps->guests[i]->arch.domains[j]->type);
+ if (caps->guests[i]->arch.domains[j]->info.emulator)
virBufferVSprintf(&xml, " <emulator>%s</emulator>\n",
- caps->guests[i]->arch.domains[j]->info.emulator) < 0)
- goto no_memory;
- if (caps->guests[i]->arch.domains[j]->info.loader &&
+ caps->guests[i]->arch.domains[j]->info.emulator);
+ if (caps->guests[i]->arch.domains[j]->info.loader)
virBufferVSprintf(&xml, " <loader>%s</loader>\n",
- caps->guests[i]->arch.domains[j]->info.loader) < 0)
- goto no_memory;
+ caps->guests[i]->arch.domains[j]->info.loader);
for (k = 0 ; k < caps->guests[i]->arch.domains[j]->info.nmachines ; k++) {
- if (virBufferVSprintf(&xml, " <machine>%s</machine>\n",
- caps->guests[i]->arch.domains[j]->info.machines[k]) < 0)
- goto no_memory;
+ virBufferVSprintf(&xml, " <machine>%s</machine>\n",
+ caps->guests[i]->arch.domains[j]->info.machines[k]);
}
- if (virBufferAddLit(&xml, " </domain>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&xml, " </domain>\n");
}
- if (virBufferAddLit(&xml, " </arch>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&xml, " </arch>\n");
if (caps->guests[i]->nfeatures) {
- if (virBufferAddLit(&xml, " <features>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&xml, " <features>\n");
for (j = 0 ; j < caps->guests[i]->nfeatures ; j++) {
if (STREQ(caps->guests[i]->features[j]->name, "pae") ||
STREQ(caps->guests[i]->features[j]->name, "nonpae") ||
STREQ(caps->guests[i]->features[j]->name, "ia64_be")) {
- if (virBufferVSprintf(&xml, " <%s/>\n",
- caps->guests[i]->features[j]->name) < 0)
- goto no_memory;
+ virBufferVSprintf(&xml, " <%s/>\n",
+ caps->guests[i]->features[j]->name);
} else {
- if (virBufferVSprintf(&xml, " <%s default='%s' toggle='%s'/>\n",
- caps->guests[i]->features[j]->name,
- caps->guests[i]->features[j]->defaultOn ? "on" : "off",
- caps->guests[i]->features[j]->toggle ? "yes" : "no") < 0)
- goto no_memory;
+ virBufferVSprintf(&xml, " <%s default='%s' toggle='%s'/>\n",
+ caps->guests[i]->features[j]->name,
+ caps->guests[i]->features[j]->defaultOn ? "on" : "off",
+ caps->guests[i]->features[j]->toggle ? "yes" : "no");
}
}
- if (virBufferAddLit(&xml, " </features>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&xml, " </features>\n");
}
-
- if (virBufferAddLit(&xml, " </guest>\n\n") < 0)
- goto no_memory;
+ virBufferAddLit(&xml, " </guest>\n\n");
}
- if (virBufferAddLit(&xml, "</capabilities>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&xml, "</capabilities>\n");
- return xml.content;
+ if (virBufferError(&xml))
+ return NULL;
- no_memory:
- free(xml.content);
- return NULL;
+ return virBufferContentAndReset(&xml);
}
Index: src/conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/conf.c,v
retrieving revision 1.25
diff -u -p -r1.25 conf.c
--- src/conf.c 10 Apr 2008 16:54:54 -0000 1.25
+++ src/conf.c 26 Apr 2008 16:24:39 -0000
@@ -877,43 +877,45 @@ __virConfSetValue (virConfPtr conf,
int
__virConfWriteFile(const char *filename, virConfPtr conf)
{
- virBufferPtr buf;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
virConfEntryPtr cur;
int ret;
int fd;
+ char *content;
+ unsigned int use;
if (conf == NULL)
return(-1);
- buf = virBufferNew(500);
- if (buf == NULL) {
- virConfError(NULL, VIR_ERR_NO_MEMORY, _("failed to allocate buffer"), 0);
- return(-1);
- }
-
cur = conf->entries;
while (cur != NULL) {
- virConfSaveEntry(buf, cur);
+ virConfSaveEntry(&buf, cur);
cur = cur->next;
}
+ if (virBufferError(&buf)) {
+ virConfError(NULL, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0);
+ return -1;
+ }
+
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR );
if (fd < 0) {
virConfError(NULL, VIR_ERR_WRITE_FAILED, _("failed to open file"), 0);
- ret = -1;
- goto error;
+ free(virBufferContentAndReset(&buf));
+ return -1;
}
- ret = safewrite(fd, buf->content, buf->use);
+ use = virBufferUse(&buf);
+ content = virBufferContentAndReset(&buf);
+ ret = safewrite(fd, content, use);
+ free(content);
close(fd);
- if (ret != (int) buf->use) {
+ if (ret != (int)use) {
virConfError(NULL, VIR_ERR_WRITE_FAILED, _("failed to save content"), 0);
- ret = -1;
- goto error;
+ return -1;
}
-error:
- virBufferFree(buf);
- return(ret);
+
+ return ret;
}
/**
@@ -932,34 +934,35 @@ error:
int
__virConfWriteMem(char *memory, int *len, virConfPtr conf)
{
- virBufferPtr buf;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
virConfEntryPtr cur;
- int ret;
+ char *content;
+ unsigned int use;
if ((memory == NULL) || (len == NULL) || (*len <= 0) || (conf == NULL))
return(-1);
- buf = virBufferNew(500);
- if (buf == NULL) {
- virConfError(NULL, VIR_ERR_NO_MEMORY, _("failed to allocate buffer"), 0);
- return(-1);
- }
-
cur = conf->entries;
while (cur != NULL) {
- virConfSaveEntry(buf, cur);
+ virConfSaveEntry(&buf, cur);
cur = cur->next;
}
- if ((int) buf->use >= *len) {
- *len = buf->use;
- ret = -1;
- goto error;
- }
- memcpy(memory, buf->content, buf->use);
- ret = buf->use;
- *len = buf->use;
-error:
- virBufferFree(buf);
- return(ret);
+ if (virBufferError(&buf)) {
+ virConfError(NULL, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0);
+ return -1;
+ }
+
+ use = virBufferUse(&buf);
+ content = virBufferContentAndReset(&buf);
+
+ if ((int)use >= *len) {
+ *len = (int)use;
+ free(content);
+ return -1;
+ }
+ memcpy(memory, content, use);
+ free(content);
+ *len = use;
+ return use;
}
Index: src/libvirt_sym.version
===================================================================
RCS file: /data/cvs/libvirt/src/libvirt_sym.version,v
retrieving revision 1.38
diff -u -p -r1.38 libvirt_sym.version
--- src/libvirt_sym.version 28 Feb 2008 17:06:32 -0000 1.38
+++ src/libvirt_sym.version 26 Apr 2008 16:24:39 -0000
@@ -184,6 +184,8 @@
__virBufferVSprintf;
__virBufferAdd;
__virBufferAddChar;
+ __virBufferContentAndReset;
+ __virBufferError;
__virMacAddrCompare;
Index: src/lxc_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/lxc_conf.c,v
retrieving revision 1.8
diff -u -p -r1.8 lxc_conf.c
--- src/lxc_conf.c 10 Apr 2008 16:54:54 -0000 1.8
+++ src/lxc_conf.c 26 Apr 2008 16:24:40 -0000
@@ -688,99 +688,49 @@ char *lxcGenerateXML(virConnectPtr conn,
lxc_vm_t *vm,
lxc_vm_def_t *def)
{
- virBufferPtr buf = 0;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
unsigned char *uuid;
char uuidstr[VIR_UUID_STRING_BUFLEN];
lxc_mount_t *mount;
- buf = virBufferNew(LXC_MAX_XML_LENGTH);
- if (!buf) {
- goto no_memory;
- }
-
- if (lxcIsActiveVM(vm)) {
- if (virBufferVSprintf(buf, "<domain type='%s' id='%d'>\n",
- LXC_DOMAIN_TYPE, vm->def->id) < 0) {
- goto no_memory;
- }
- } else {
- if (virBufferVSprintf(buf, "<domain type='%s'>\n",
- LXC_DOMAIN_TYPE) < 0) {
- goto no_memory;
- }
- }
+ if (lxcIsActiveVM(vm))
+ virBufferVSprintf(&buf, "<domain type='%s' id='%d'>\n",
+ LXC_DOMAIN_TYPE, vm->def->id);
+ else
+ virBufferVSprintf(&buf, "<domain type='%s'>\n",
+ LXC_DOMAIN_TYPE);
- if (virBufferVSprintf(buf, " <name>%s</name>\n", def->name) < 0) {
- goto no_memory;
- }
+ virBufferVSprintf(&buf, " <name>%s</name>\n", def->name);
uuid = def->uuid;
virUUIDFormat(uuid, uuidstr);
- if (virBufferVSprintf(buf, " <uuid>%s</uuid>\n", uuidstr) < 0) {
- goto no_memory;
- }
-
- if (virBufferAddLit(buf, " <os>\n") < 0) {
- goto no_memory;
- }
-
- if (virBufferVSprintf(buf, " <init>%s</init>\n", def->init) < 0) {
- goto no_memory;
- }
-
- if (virBufferAddLit(buf, " </os>\n") < 0) {
- goto no_memory;
- }
-
- if (virBufferVSprintf(buf, " <memory>%d</memory>\n", def->maxMemory) < 0) {
- goto no_memory;
- }
-
- if (virBufferAddLit(buf, " <devices>\n") < 0) {
- goto no_memory;
- }
+ virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr);
+ virBufferAddLit(&buf, " <os>\n");
+ virBufferVSprintf(&buf, " <init>%s</init>\n", def->init);
+ virBufferAddLit(&buf, " </os>\n");
+ virBufferVSprintf(&buf, " <memory>%d</memory>\n", def->maxMemory);
+ virBufferAddLit(&buf, " <devices>\n");
/* loop adding mounts */
for (mount = def->mounts; mount; mount = mount->next) {
- if (virBufferAddLit(buf, " <filesystem type='mount'>\n") < 0) {
- goto no_memory;
- }
-
- if (virBufferVSprintf(buf, " <source dir='%s'/>\n",
- mount->source) < 0) {
- goto no_memory;
- }
-
- if (virBufferVSprintf(buf, " <target dir='%s'/>\n",
- mount->target) < 0) {
- goto no_memory;
- }
-
- if (virBufferAddLit(buf, " </filesystem>\n") < 0) {
- goto no_memory;
- }
-
- }
-
- if (virBufferVSprintf(buf, " <console tty='%s'/>\n", def->tty) < 0) {
- goto no_memory;
+ virBufferAddLit(&buf, " <filesystem type='mount'>\n");
+ virBufferVSprintf(&buf, " <source dir='%s'/>\n",
+ mount->source);
+ virBufferVSprintf(&buf, " <target dir='%s'/>\n",
+ mount->target);
+ virBufferAddLit(&buf, " </filesystem>\n");
}
- if (virBufferAddLit(buf, " </devices>\n") < 0) {
- goto no_memory;
- }
+ virBufferVSprintf(&buf, " <console tty='%s'/>\n", def->tty);
+ virBufferAddLit(&buf, " </devices>\n");
+ virBufferAddLit(&buf, "</domain>\n");
- if (virBufferAddLit(buf, "</domain>\n") < 0) {
- goto no_memory;
+ if (virBufferError(&buf)) {
+ lxcError(conn, NULL, VIR_ERR_NO_MEMORY,_("allocate buffer"));
+ return NULL;
}
- return virBufferContentAndFree(buf);
-
-no_memory:
- lxcError(conn, NULL, VIR_ERR_NO_MEMORY, "generateXml");
- virBufferFree(buf);
-
- return NULL;
+ return virBufferContentAndReset(&buf);
}
void lxcFreeVMDef(lxc_vm_def_t *vmdef)
Index: src/qemu_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_conf.c,v
retrieving revision 1.49
diff -u -p -r1.49 qemu_conf.c
--- src/qemu_conf.c 25 Apr 2008 20:46:13 -0000 1.49
+++ src/qemu_conf.c 26 Apr 2008 16:24:42 -0000
@@ -3359,14 +3359,12 @@ static int qemudGenerateXMLChar(virBuffe
if (STREQ(type, "console") &&
dev->srcType == QEMUD_CHR_SRC_TYPE_PTY &&
dev->srcData.file.path[0] != '\0') {
- if (virBufferVSprintf(buf, " <%s type='%s' tty='%s'>\n",
- type, types[dev->srcType],
- dev->srcData.file.path) < 0)
- return -1;
+ virBufferVSprintf(buf, " <%s type='%s' tty='%s'>\n",
+ type, types[dev->srcType],
+ dev->srcData.file.path);
} else {
- if (virBufferVSprintf(buf, " <%s type='%s'>\n",
- type, types[dev->srcType]) < 0)
- return -1;
+ virBufferVSprintf(buf, " <%s type='%s'>\n",
+ type, types[dev->srcType]);
}
switch (dev->srcType) {
@@ -3382,74 +3380,62 @@ static int qemudGenerateXMLChar(virBuffe
case QEMUD_CHR_SRC_TYPE_PIPE:
if (dev->srcType != QEMUD_CHR_SRC_TYPE_PTY ||
dev->srcData.file.path[0]) {
- if (virBufferVSprintf(buf, " <source path='%s'/>\n",
- dev->srcData.file.path) < 0)
- return -1;
+ virBufferVSprintf(buf, " <source path='%s'/>\n",
+ dev->srcData.file.path);
}
break;
case QEMUD_CHR_SRC_TYPE_UDP:
if (dev->srcData.udp.bindService[0] != '\0' &&
dev->srcData.udp.bindHost[0] != '\0') {
- if (virBufferVSprintf(buf, " <source mode='bind' host='%s' service='%s'/>\n",
- dev->srcData.udp.bindHost,
- dev->srcData.udp.bindService) < 0)
- return -1;
+ virBufferVSprintf(buf, " <source mode='bind' host='%s' service='%s'/>\n",
+ dev->srcData.udp.bindHost,
+ dev->srcData.udp.bindService);
} else if (dev->srcData.udp.bindHost[0] !='\0') {
- if (virBufferVSprintf(buf, " <source mode='bind' host='%s'/>\n",
- dev->srcData.udp.bindHost) < 0)
- return -1;
+ virBufferVSprintf(buf, " <source mode='bind' host='%s'/>\n",
+ dev->srcData.udp.bindHost);
} else if (dev->srcData.udp.bindService[0] != '\0') {
- if (virBufferVSprintf(buf, " <source mode='bind' service='%s'/>\n",
- dev->srcData.udp.bindService) < 0)
- return -1;
+ virBufferVSprintf(buf, " <source mode='bind' service='%s'/>\n",
+ dev->srcData.udp.bindService);
}
if (dev->srcData.udp.connectService[0] != '\0' &&
dev->srcData.udp.connectHost[0] != '\0') {
- if (virBufferVSprintf(buf, " <source mode='connect' host='%s' service='%s'/>\n",
- dev->srcData.udp.connectHost,
- dev->srcData.udp.connectService) < 0)
- return -1;
+ virBufferVSprintf(buf, " <source mode='connect' host='%s' service='%s'/>\n",
+ dev->srcData.udp.connectHost,
+ dev->srcData.udp.connectService);
} else if (dev->srcData.udp.connectHost[0] != '\0') {
- if (virBufferVSprintf(buf, " <source mode='connect' host='%s'/>\n",
- dev->srcData.udp.connectHost) < 0)
- return -1;
+ virBufferVSprintf(buf, " <source mode='connect' host='%s'/>\n",
+ dev->srcData.udp.connectHost);
} else if (dev->srcData.udp.connectService[0] != '\0') {
- if (virBufferVSprintf(buf, " <source mode='connect' service='%s'/>\n",
- dev->srcData.udp.connectService) < 0)
- return -1;
+ virBufferVSprintf(buf, " <source mode='connect' service='%s'/>\n",
+ dev->srcData.udp.connectService);
}
break;
case QEMUD_CHR_SRC_TYPE_TCP:
- if (virBufferVSprintf(buf, " <source mode='%s' host='%s' service='%s'/>\n",
- dev->srcData.tcp.listen ? "bind" : "connect",
- dev->srcData.tcp.host,
- dev->srcData.tcp.service) < 0)
- return -1;
- if (virBufferVSprintf(buf, " <protocol type='%s'/>\n",
- dev->srcData.tcp.protocol == QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET
- ? "telnet" : "raw") < 0)
- return -1;
+ virBufferVSprintf(buf, " <source mode='%s' host='%s' service='%s'/>\n",
+ dev->srcData.tcp.listen ? "bind" : "connect",
+ dev->srcData.tcp.host,
+ dev->srcData.tcp.service);
+ virBufferVSprintf(buf, " <protocol type='%s'/>\n",
+ dev->srcData.tcp.protocol == QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET
+ ? "telnet" : "raw");
break;
case QEMUD_CHR_SRC_TYPE_UNIX:
- if (virBufferVSprintf(buf, " <source mode='%s' path='%s'/>\n",
- dev->srcData.nix.listen ? "bind" : "connect",
- dev->srcData.nix.path) < 0)
- return -1;
+ virBufferVSprintf(buf, " <source mode='%s' path='%s'/>\n",
+ dev->srcData.nix.listen ? "bind" : "connect",
+ dev->srcData.nix.path);
break;
}
- if (virBufferVSprintf(buf, " <target port='%d'/>\n",
- dev->dstPort) < 0)
- return -1;
+ virBufferVSprintf(buf, " <target port='%d'/>\n",
+ dev->dstPort);
- if (virBufferVSprintf(buf, " </%s>\n",
- type) < 0)
- return -1;
+ virBufferVSprintf(buf, " </%s>\n",
+ type);
return 0;
}
@@ -3461,7 +3447,7 @@ char *qemudGenerateXML(virConnectPtr con
struct qemud_vm *vm,
struct qemud_vm_def *def,
int live) {
- virBufferPtr buf = 0;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
unsigned char *uuid;
char uuidstr[VIR_UUID_STRING_BUFLEN];
const struct qemud_vm_disk_def *disk;
@@ -3471,10 +3457,6 @@ char *qemudGenerateXML(virConnectPtr con
const char *type = NULL;
int n;
- buf = virBufferNew (QEMUD_MAX_XML_LEN);
- if (!buf)
- goto no_memory;
-
switch (def->virtType) {
case QEMUD_VIRT_QEMU:
type = "qemu";
@@ -3492,49 +3474,34 @@ char *qemudGenerateXML(virConnectPtr con
goto cleanup;
}
- if (qemudIsActiveVM(vm) && live) {
- if (virBufferVSprintf(buf, "<domain type='%s' id='%d'>\n", type, vm->id) < 0)
- goto no_memory;
- } else {
- if (virBufferVSprintf(buf, "<domain type='%s'>\n", type) < 0)
- goto no_memory;
- }
+ if (qemudIsActiveVM(vm) && live)
+ virBufferVSprintf(&buf, "<domain type='%s' id='%d'>\n", type, vm->id);
+ else
+ virBufferVSprintf(&buf, "<domain type='%s'>\n", type);
- if (virBufferVSprintf(buf, " <name>%s</name>\n", def->name) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <name>%s</name>\n", def->name);
uuid = def->uuid;
virUUIDFormat(uuid, uuidstr);
- if (virBufferVSprintf(buf, " <uuid>%s</uuid>\n", uuidstr) < 0)
- goto no_memory;
- if (virBufferVSprintf(buf, " <memory>%lu</memory>\n", def->maxmem) < 0)
- goto no_memory;
- if (virBufferVSprintf(buf, " <currentMemory>%lu</currentMemory>\n", def->memory) < 0)
- goto no_memory;
- if (virBufferVSprintf(buf, " <vcpu>%d</vcpu>\n", def->vcpus) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr);
- if (virBufferAddLit(buf, " <os>\n") < 0)
- goto no_memory;
-
- if (def->virtType == QEMUD_VIRT_QEMU) {
- if (virBufferVSprintf(buf, " <type arch='%s' machine='%s'>%s</type>\n",
- def->os.arch, def->os.machine, def->os.type) < 0)
- goto no_memory;
- } else {
- if (virBufferVSprintf(buf, " <type>%s</type>\n", def->os.type) < 0)
- goto no_memory;
- }
+ virBufferVSprintf(&buf, " <memory>%lu</memory>\n", def->maxmem);
+ virBufferVSprintf(&buf, " <currentMemory>%lu</currentMemory>\n", def->memory);
+ virBufferVSprintf(&buf, " <vcpu>%d</vcpu>\n", def->vcpus);
+ virBufferAddLit(&buf, " <os>\n");
+
+ if (def->virtType == QEMUD_VIRT_QEMU)
+ virBufferVSprintf(&buf, " <type arch='%s' machine='%s'>%s</type>\n",
+ def->os.arch, def->os.machine, def->os.type);
+ else
+ virBufferVSprintf(&buf, " <type>%s</type>\n", def->os.type);
if (def->os.kernel[0])
- if (virBufferVSprintf(buf, " <kernel>%s</kernel>\n", def->os.kernel) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <kernel>%s</kernel>\n", def->os.kernel);
if (def->os.initrd[0])
- if (virBufferVSprintf(buf, " <initrd>%s</initrd>\n", def->os.initrd) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <initrd>%s</initrd>\n", def->os.initrd);
if (def->os.cmdline[0])
- if (virBufferVSprintf(buf, " <cmdline>%s</cmdline>\n", def->os.cmdline) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <cmdline>%s</cmdline>\n", def->os.cmdline);
for (n = 0 ; n < def->os.nBootDevs ; n++) {
const char *boottype = "hd";
@@ -3552,41 +3519,29 @@ char *qemudGenerateXML(virConnectPtr con
boottype = "network";
break;
}
- if (virBufferVSprintf(buf, " <boot dev='%s'/>\n", boottype) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <boot dev='%s'/>\n", boottype);
}
- if (virBufferAddLit(buf, " </os>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " </os>\n");
if (def->features & QEMUD_FEATURE_ACPI) {
- if (virBufferAddLit(buf, " <features>\n") < 0)
- goto no_memory;
- if (virBufferAddLit(buf, " <acpi/>\n") < 0)
- goto no_memory;
- if (virBufferAddLit(buf, " </features>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " <features>\n");
+ virBufferAddLit(&buf, " <acpi/>\n");
+ virBufferAddLit(&buf, " </features>\n");
}
- virBufferVSprintf(buf, " <clock offset='%s'/>\n", def->localtime ? "localtime" : "utc");
+ virBufferVSprintf(&buf, " <clock offset='%s'/>\n", def->localtime ? "localtime" : "utc");
- if (virBufferAddLit(buf, " <on_poweroff>destroy</on_poweroff>\n") < 0)
- goto no_memory;
- if (def->noReboot) {
- if (virBufferAddLit(buf, " <on_reboot>destroy</on_reboot>\n") < 0)
- goto no_memory;
- } else {
- if (virBufferAddLit(buf, " <on_reboot>restart</on_reboot>\n") < 0)
- goto no_memory;
- }
- if (virBufferAddLit(buf, " <on_crash>destroy</on_crash>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " <on_poweroff>destroy</on_poweroff>\n");
+ if (def->noReboot)
+ virBufferAddLit(&buf, " <on_reboot>destroy</on_reboot>\n");
+ else
+ virBufferAddLit(&buf, " <on_reboot>restart</on_reboot>\n");
- if (virBufferAddLit(buf, " <devices>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " <on_crash>destroy</on_crash>\n");
+ virBufferAddLit(&buf, " <devices>\n");
- if (virBufferVSprintf(buf, " <emulator>%s</emulator>\n", def->os.binary) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <emulator>%s</emulator>\n", def->os.binary);
disk = def->disks;
while (disk) {
@@ -3603,24 +3558,19 @@ char *qemudGenerateXML(virConnectPtr con
"cdrom",
"floppy",
};
- if (virBufferVSprintf(buf, " <disk type='%s' device='%s'>\n",
- types[disk->type], devices[disk->device]) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <disk type='%s' device='%s'>\n",
+ types[disk->type], devices[disk->device]);
if (disk->src[0])
- if (virBufferVSprintf(buf, " <source %s='%s'/>\n",
- typeAttrs[disk->type], disk->src) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <source %s='%s'/>\n",
+ typeAttrs[disk->type], disk->src);
- if (virBufferVSprintf(buf, " <target dev='%s'/>\n", disk->dst) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <target dev='%s'/>\n", disk->dst);
if (disk->readonly)
- if (virBufferAddLit(buf, " <readonly/>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " <readonly/>\n");
- if (virBufferAddLit(buf, " </disk>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " </disk>\n");
disk = disk->next;
}
@@ -3636,69 +3586,53 @@ char *qemudGenerateXML(virConnectPtr con
"network",
"bridge",
};
- if (virBufferVSprintf(buf, " <interface type='%s'>\n",
- types[net->type]) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <interface type='%s'>\n",
+ types[net->type]);
- if (virBufferVSprintf(buf, " <mac address='%02x:%02x:%02x:%02x:%02x:%02x'/>\n",
- net->mac[0], net->mac[1], net->mac[2],
- net->mac[3], net->mac[4], net->mac[5]) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <mac address='%02x:%02x:%02x:%02x:%02x:%02x'/>\n",
+ net->mac[0], net->mac[1], net->mac[2],
+ net->mac[3], net->mac[4], net->mac[5]);
switch (net->type) {
case QEMUD_NET_NETWORK:
- if (virBufferVSprintf(buf, " <source network='%s'/>\n", net->dst.network.name) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <source network='%s'/>\n", net->dst.network.name);
- if (net->dst.network.ifname[0] != '\0') {
- if (virBufferVSprintf(buf, " <target dev='%s'/>\n", net->dst.network.ifname) < 0)
- goto no_memory;
- }
+ if (net->dst.network.ifname[0] != '\0')
+ virBufferVSprintf(&buf, " <target dev='%s'/>\n", net->dst.network.ifname);
break;
case QEMUD_NET_ETHERNET:
- if (net->dst.ethernet.ifname[0] != '\0') {
- if (virBufferVSprintf(buf, " <target dev='%s'/>\n", net->dst.ethernet.ifname) < 0)
- goto no_memory;
- }
- if (net->dst.ethernet.script[0] != '\0') {
- if (virBufferVSprintf(buf, " <script path='%s'/>\n", net->dst.ethernet.script) < 0)
- goto no_memory;
- }
+ if (net->dst.ethernet.ifname[0] != '\0')
+ virBufferVSprintf(&buf, " <target dev='%s'/>\n", net->dst.ethernet.ifname);
+ if (net->dst.ethernet.script[0] != '\0')
+ virBufferVSprintf(&buf, " <script path='%s'/>\n", net->dst.ethernet.script);
break;
case QEMUD_NET_BRIDGE:
- if (virBufferVSprintf(buf, " <source bridge='%s'/>\n", net->dst.bridge.brname) < 0)
- goto no_memory;
- if (net->dst.bridge.ifname[0] != '\0') {
- if (virBufferVSprintf(buf, " <target dev='%s'/>\n", net->dst.bridge.ifname) < 0)
- goto no_memory;
- }
+ virBufferVSprintf(&buf, " <source bridge='%s'/>\n", net->dst.bridge.brname);
+ if (net->dst.bridge.ifname[0] != '\0')
+ virBufferVSprintf(&buf, " <target dev='%s'/>\n", net->dst.bridge.ifname);
break;
case QEMUD_NET_SERVER:
case QEMUD_NET_CLIENT:
case QEMUD_NET_MCAST:
- if (net->dst.socket.address[0] != '\0') {
- if (virBufferVSprintf(buf, " <source address='%s' port='%d'/>\n",
- net->dst.socket.address, net->dst.socket.port) < 0)
- goto no_memory;
- } else {
- if (virBufferVSprintf(buf, " <source port='%d'/>\n",
- net->dst.socket.port) < 0)
- goto no_memory;
- }
+ if (net->dst.socket.address[0] != '\0')
+ virBufferVSprintf(&buf, " <source address='%s' port='%d'/>\n",
+ net->dst.socket.address, net->dst.socket.port);
+ else
+ virBufferVSprintf(&buf, " <source port='%d'/>\n",
+ net->dst.socket.port);
}
- if (virBufferAddLit(buf, " </interface>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " </interface>\n");
net = net->next;
}
chr = def->serials;
while (chr) {
- if (qemudGenerateXMLChar(buf, chr, "serial") < 0)
+ if (qemudGenerateXMLChar(&buf, chr, "serial") < 0)
goto no_memory;
chr = chr->next;
@@ -3706,7 +3640,7 @@ char *qemudGenerateXML(virConnectPtr con
chr = def->parallels;
while (chr) {
- if (qemudGenerateXMLChar(buf, chr, "parallel") < 0)
+ if (qemudGenerateXMLChar(&buf, chr, "parallel") < 0)
goto no_memory;
chr = chr->next;
@@ -3714,49 +3648,41 @@ char *qemudGenerateXML(virConnectPtr con
/* First serial device is the primary console */
if (def->nserials > 0 &&
- qemudGenerateXMLChar(buf, def->serials, "console") < 0)
+ qemudGenerateXMLChar(&buf, def->serials, "console") < 0)
goto no_memory;
input = def->inputs;
while (input) {
- if (input->bus != QEMU_INPUT_BUS_PS2 &&
- virBufferVSprintf(buf, " <input type='%s' bus='usb'/>\n",
- input->type == QEMU_INPUT_TYPE_MOUSE ? "mouse" : "tablet") < 0)
- goto no_memory;
+ if (input->bus != QEMU_INPUT_BUS_PS2)
+ virBufferVSprintf(&buf, " <input type='%s' bus='usb'/>\n",
+ input->type == QEMU_INPUT_TYPE_MOUSE ? "mouse" : "tablet");
input = input->next;
}
/* If graphics is enable, add implicit mouse */
if (def->graphicsType != QEMUD_GRAPHICS_NONE)
- if (virBufferAddLit(buf, " <input type='mouse' bus='ps2'/>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " <input type='mouse' bus='ps2'/>\n");
switch (def->graphicsType) {
case QEMUD_GRAPHICS_VNC:
- if (virBufferAddLit(buf, " <graphics type='vnc'") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " <graphics type='vnc'");
- if (def->vncPort &&
- virBufferVSprintf(buf, " port='%d'",
- qemudIsActiveVM(vm) && live ? def->vncActivePort : def->vncPort) < 0)
- goto no_memory;
+ if (def->vncPort)
+ virBufferVSprintf(&buf, " port='%d'",
+ qemudIsActiveVM(vm) && live ? def->vncActivePort : def->vncPort);
- if (def->vncListen[0] &&
- virBufferVSprintf(buf, " listen='%s'",
- def->vncListen) < 0)
- goto no_memory;
+ if (def->vncListen[0])
+ virBufferVSprintf(&buf, " listen='%s'",
+ def->vncListen);
- if (def->keymap &&
- virBufferVSprintf(buf, " keymap='%s'",
- def->keymap) < 0)
- goto no_memory;
+ if (def->keymap)
+ virBufferVSprintf(&buf, " keymap='%s'",
+ def->keymap);
- if (virBufferAddLit(buf, "/>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, "/>\n");
break;
case QEMUD_GRAPHICS_SDL:
- if (virBufferAddLit(buf, " <graphics type='sdl'/>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " <graphics type='sdl'/>\n");
break;
case QEMUD_GRAPHICS_NONE:
@@ -3764,20 +3690,19 @@ char *qemudGenerateXML(virConnectPtr con
break;
}
- if (virBufferAddLit(buf, " </devices>\n") < 0)
- goto no_memory;
-
+ virBufferAddLit(&buf, " </devices>\n");
+ virBufferAddLit(&buf, "</domain>\n");
- if (virBufferAddLit(buf, "</domain>\n") < 0)
+ if (virBufferError(&buf))
goto no_memory;
- return virBufferContentAndFree (buf);
+ return virBufferContentAndReset(&buf);
no_memory:
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to generate XML: out of memory"));
cleanup:
- if (buf) virBufferFree (buf);
+ free(virBufferContentAndReset(&buf));
return NULL;
}
@@ -3786,89 +3711,73 @@ char *qemudGenerateNetworkXML(virConnect
struct qemud_driver *driver ATTRIBUTE_UNUSED,
struct qemud_network *network,
struct qemud_network_def *def) {
- virBufferPtr buf = 0;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
unsigned char *uuid;
char uuidstr[VIR_UUID_STRING_BUFLEN];
- buf = virBufferNew (QEMUD_MAX_XML_LEN);
- if (!buf)
- goto no_memory;
+ virBufferAddLit(&buf, "<network>\n");
- if (virBufferAddLit(buf, "<network>\n") < 0)
- goto no_memory;
-
- if (virBufferVSprintf(buf, " <name>%s</name>\n", def->name) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <name>%s</name>\n", def->name);
uuid = def->uuid;
virUUIDFormat(uuid, uuidstr);
- if (virBufferVSprintf(buf, " <uuid>%s</uuid>\n", uuidstr) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr);
if (def->forward) {
if (def->forwardDev[0]) {
- virBufferVSprintf(buf, " <forward dev='%s' mode='%s'/>\n",
+ virBufferVSprintf(&buf, " <forward dev='%s' mode='%s'/>\n",
def->forwardDev, (def->forwardMode == QEMUD_NET_FORWARD_ROUTE ? "route" : "nat"));
} else {
- virBufferVSprintf(buf, " <forward mode='%s'/>\n", (def->forwardMode == QEMUD_NET_FORWARD_ROUTE ? "route" : "nat"));
+ virBufferVSprintf(&buf, " <forward mode='%s'/>\n", (def->forwardMode == QEMUD_NET_FORWARD_ROUTE ? "route" : "nat"));
}
}
- virBufferAddLit(buf, " <bridge");
+ virBufferAddLit(&buf, " <bridge");
if (qemudIsActiveNetwork(network)) {
- if (virBufferVSprintf(buf, " name='%s'", network->bridge) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " name='%s'", network->bridge);
} else if (def->bridge[0]) {
- if (virBufferVSprintf(buf, " name='%s'", def->bridge) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " name='%s'", def->bridge);
}
- if (virBufferVSprintf(buf, " stp='%s' forwardDelay='%d' />\n",
- def->disableSTP ? "off" : "on",
- def->forwardDelay) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " stp='%s' forwardDelay='%d' />\n",
+ def->disableSTP ? "off" : "on",
+ def->forwardDelay);
if (def->ipAddress[0] || def->netmask[0]) {
- if (virBufferAddLit(buf, " <ip") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " <ip");
- if (def->ipAddress[0] &&
- virBufferVSprintf(buf, " address='%s'", def->ipAddress) < 0)
- goto no_memory;
+ if (def->ipAddress[0])
+ virBufferVSprintf(&buf, " address='%s'", def->ipAddress);
- if (def->netmask[0] &&
- virBufferVSprintf(buf, " netmask='%s'", def->netmask) < 0)
- goto no_memory;
+ if (def->netmask[0])
+ virBufferVSprintf(&buf, " netmask='%s'", def->netmask);
- if (virBufferAddLit(buf, ">\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, ">\n");
if (def->ranges) {
struct qemud_dhcp_range_def *range = def->ranges;
- if (virBufferAddLit(buf, " <dhcp>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " <dhcp>\n");
while (range) {
- if (virBufferVSprintf(buf, " <range start='%s' end='%s' />\n",
- range->start, range->end) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <range start='%s' end='%s' />\n",
+ range->start, range->end);
range = range->next;
}
- if (virBufferAddLit(buf, " </dhcp>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " </dhcp>\n");
}
- if (virBufferAddLit(buf, " </ip>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " </ip>\n");
}
- if (virBufferAddLit(buf, "</network>\n") < 0)
+ virBufferAddLit(&buf, "</network>\n");
+
+ if (virBufferError(&buf))
goto no_memory;
- return virBufferContentAndFree (buf);
+ return virBufferContentAndReset(&buf);
no_memory:
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to generate XML: out of memory"));
- if (buf) virBufferFree (buf);
+ free(virBufferContentAndReset(&buf));
return NULL;
}
Index: src/qparams.c
===================================================================
RCS file: /data/cvs/libvirt/src/qparams.c,v
retrieving revision 1.3
diff -u -p -r1.3 qparams.c
--- src/qparams.c 10 Apr 2008 16:53:29 -0000 1.3
+++ src/qparams.c 26 Apr 2008 16:24:43 -0000
@@ -136,20 +136,23 @@ append_qparam (struct qparam_set *ps,
char *
qparam_get_query (const struct qparam_set *ps)
{
- virBufferPtr buf;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
int i, amp = 0;
- buf = virBufferNew (100);
for (i = 0; i < ps->n; ++i) {
if (!ps->p[i].ignore) {
- if (amp) virBufferAddChar (buf, '&');
- virBufferStrcat (buf, ps->p[i].name, "=", NULL);
- virBufferURIEncodeString (buf, ps->p[i].value);
+ if (amp) virBufferAddChar (&buf, '&');
+ virBufferStrcat (&buf, ps->p[i].name, "=", NULL);
+ virBufferURIEncodeString (&buf, ps->p[i].value);
amp = 1;
}
}
- return virBufferContentAndFree (buf);
+ if (virBufferError(&buf)) {
+ return NULL;
+ }
+
+ return virBufferContentAndReset(&buf);
}
void
Index: src/storage_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/storage_conf.c,v
retrieving revision 1.5
diff -u -p -r1.5 storage_conf.c
--- src/storage_conf.c 10 Apr 2008 16:53:29 -0000 1.5
+++ src/storage_conf.c 26 Apr 2008 16:24:43 -0000
@@ -414,7 +414,7 @@ char *
virStoragePoolDefFormat(virConnectPtr conn,
virStoragePoolDefPtr def) {
virStorageBackendPoolOptionsPtr options;
- virBufferPtr buf;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
const char *type;
char uuid[VIR_UUID_STRING_BUFLEN];
int i;
@@ -423,126 +423,96 @@ virStoragePoolDefFormat(virConnectPtr co
if (options == NULL)
return NULL;
- if ((buf = virBufferNew(8192)) == NULL)
- goto no_memory;
-
type = virStorageBackendToString(def->type);
if (!type) {
virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("unexpected pool type"));
goto cleanup;
}
- if (virBufferVSprintf(buf, "<pool type='%s'>\n", type) < 0)
- goto no_memory;
-
- if (virBufferVSprintf(buf," <name>%s</name>\n", def->name) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, "<pool type='%s'>\n", type);
+ virBufferVSprintf(&buf," <name>%s</name>\n", def->name);
virUUIDFormat(def->uuid, uuid);
- if (virBufferVSprintf(buf," <uuid>%s</uuid>\n", uuid) < 0)
- goto no_memory;
-
- if (virBufferVSprintf(buf," <capacity>%llu</capacity>\n",
- def->capacity) < 0)
- goto no_memory;
- if (virBufferVSprintf(buf," <allocation>%llu</allocation>\n",
- def->allocation) < 0)
- goto no_memory;
- if (virBufferVSprintf(buf," <available>%llu</available>\n",
- def->available) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf," <uuid>%s</uuid>\n", uuid);
+ virBufferVSprintf(&buf," <capacity>%llu</capacity>\n",
+ def->capacity);
+ virBufferVSprintf(&buf," <allocation>%llu</allocation>\n",
+ def->allocation);
+ virBufferVSprintf(&buf," <available>%llu</available>\n",
+ def->available);
- if (virBufferAddLit(buf," <source>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf," <source>\n");
if ((options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_HOST) &&
- def->source.host.name &&
- virBufferVSprintf(buf," <host name='%s'/>\n", def->source.host.name) < 0)
- goto no_memory;
+ def->source.host.name)
+ virBufferVSprintf(&buf," <host name='%s'/>\n", def->source.host.name);
+
if ((options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_DEVICE) &&
def->source.ndevice) {
for (i = 0 ; i < def->source.ndevice ; i++) {
- if (virBufferVSprintf(buf," <device path='%s'>\n", def->source.devices[i].path) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf," <device path='%s'>\n", def->source.devices[i].path);
if (def->source.devices[i].nfreeExtent) {
int j;
for (j = 0 ; j < def->source.devices[i].nfreeExtent ; j++) {
- if (virBufferVSprintf(buf, " <freeExtent start='%llu' end='%llu'/>\n",
- def->source.devices[i].freeExtents[j].start,
- def->source.devices[i].freeExtents[j].end) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf, " <freeExtent start='%llu' end='%llu'/>\n",
+ def->source.devices[i].freeExtents[j].start,
+ def->source.devices[i].freeExtents[j].end);
}
}
- if (virBufferAddLit(buf," </device>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf," </device>\n");
}
}
if ((options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_DIR) &&
- def->source.dir &&
- virBufferVSprintf(buf," <dir path='%s'/>\n", def->source.dir) < 0)
- goto no_memory;
+ def->source.dir)
+ virBufferVSprintf(&buf," <dir path='%s'/>\n", def->source.dir);
if ((options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_ADAPTER) &&
- def->source.adapter &&
- virBufferVSprintf(buf," <adapter name='%s'/>\n", def->source.adapter) < 0)
- goto no_memory;
+ def->source.adapter)
+ virBufferVSprintf(&buf," <adapter name='%s'/>\n", def->source.adapter);
if (options->formatToString) {
const char *format = (options->formatToString)(conn, def->source.format);
if (!format)
goto cleanup;
- if (virBufferVSprintf(buf," <format type='%s'/>\n", format) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf," <format type='%s'/>\n", format);
}
- if (def->source.authType == VIR_STORAGE_POOL_AUTH_CHAP &&
- virBufferVSprintf(buf," <auth type='chap' login='%s' passwd='%s'>\n",
+ if (def->source.authType == VIR_STORAGE_POOL_AUTH_CHAP)
+ virBufferVSprintf(&buf," <auth type='chap' login='%s' passwd='%s'>\n",
def->source.auth.chap.login,
- def->source.auth.chap.passwd) < 0)
- goto no_memory;
- if (virBufferAddLit(buf," </source>\n") < 0)
- goto no_memory;
+ def->source.auth.chap.passwd);
+ virBufferAddLit(&buf," </source>\n");
+ virBufferAddLit(&buf," <target>\n");
+ if (def->target.path)
+ virBufferVSprintf(&buf," <path>%s</path>\n", def->target.path);
- if (virBufferAddLit(buf," <target>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf," <permissions>\n");
+ virBufferVSprintf(&buf," <mode>0%o</mode>\n",
+ def->target.perms.mode);
+ virBufferVSprintf(&buf," <owner>%d</owner>\n",
+ def->target.perms.uid);
+ virBufferVSprintf(&buf," <group>%d</group>\n",
+ def->target.perms.gid);
- if (def->target.path &&
- virBufferVSprintf(buf," <path>%s</path>\n", def->target.path) < 0)
- goto no_memory;
+ if (def->target.perms.label)
+ virBufferVSprintf(&buf," <label>%s</label>\n",
+ def->target.perms.label);
- if (virBufferAddLit(buf," <permissions>\n") < 0)
- goto no_memory;
- if (virBufferVSprintf(buf," <mode>0%o</mode>\n",
- def->target.perms.mode) < 0)
- goto no_memory;
- if (virBufferVSprintf(buf," <owner>%d</owner>\n",
- def->target.perms.uid) < 0)
- goto no_memory;
- if (virBufferVSprintf(buf," <group>%d</group>\n",
- def->target.perms.gid) < 0)
- goto no_memory;
+ virBufferAddLit(&buf," </permissions>\n");
+ virBufferAddLit(&buf," </target>\n");
+ virBufferAddLit(&buf,"</pool>\n");
- if (def->target.perms.label) {
- if (virBufferVSprintf(buf," <label>%s</label>\n",
- def->target.perms.label) < 0)
- goto no_memory;
- }
- if (virBufferAddLit(buf," </permissions>\n") < 0)
- goto no_memory;
- if (virBufferAddLit(buf," </target>\n") < 0)
+ if (virBufferError(&buf))
goto no_memory;
- if (virBufferAddLit(buf,"</pool>\n") < 0)
- goto no_memory;
-
- return virBufferContentAndFree(buf);
+ return virBufferContentAndReset(&buf);
no_memory:
virStorageReportError(conn, VIR_ERR_NO_MEMORY, "%s", _("xml"));
cleanup:
- virBufferFree(buf);
+ free(virBufferContentAndReset(&buf));
return NULL;
}
@@ -804,26 +774,17 @@ virStorageVolDefFormat(virConnectPtr con
virStoragePoolDefPtr pool,
virStorageVolDefPtr def) {
virStorageBackendVolOptionsPtr options;
- virBufferPtr buf = virBufferNew(8192);
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
options = virStorageBackendVolOptionsForType(pool->type);
if (options == NULL)
return NULL;
- if (!buf)
- goto no_memory;
-
- if (virBufferAddLit(buf, "<volume>\n") < 0)
- goto no_memory;
-
- if (virBufferVSprintf(buf," <name>%s</name>\n", def->name) < 0)
- goto no_memory;
-
- if (virBufferVSprintf(buf," <key>%s</key>\n", def->key) < 0)
- goto no_memory;
+ virBufferAddLit(&buf, "<volume>\n");
+ virBufferVSprintf(&buf," <name>%s</name>\n", def->name);
+ virBufferVSprintf(&buf," <key>%s</key>\n", def->key);
+ virBufferAddLit(&buf, " <source>\n");
- if (virBufferAddLit(buf, " <source>\n") < 0)
- goto no_memory;
if (def->source.nextent) {
int i;
const char *thispath = NULL;
@@ -831,81 +792,67 @@ virStorageVolDefFormat(virConnectPtr con
if (thispath == NULL ||
STRNEQ(thispath, def->source.extents[i].path)) {
if (thispath != NULL)
- if (virBufferAddLit(buf, " </device>\n") < 0)
- goto no_memory;
- if (virBufferVSprintf(buf, " <device path='%s'>\n",
- def->source.extents[i].path) < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " </device>\n");
+
+ virBufferVSprintf(&buf, " <device path='%s'>\n",
+ def->source.extents[i].path);
}
- if (virBufferVSprintf(buf,
- " <extent start='%llu' end='%llu'/>\n",
- def->source.extents[i].start,
- def->source.extents[i].end) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf,
+ " <extent start='%llu' end='%llu'/>\n",
+ def->source.extents[i].start,
+ def->source.extents[i].end);
thispath = def->source.extents[i].path;
}
if (thispath != NULL)
- if (virBufferAddLit(buf, " </device>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " </device>\n");
}
- if (virBufferAddLit(buf, " </source>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " </source>\n");
- if (virBufferVSprintf(buf," <capacity>%llu</capacity>\n",
- def->capacity) < 0)
- goto no_memory;
- if (virBufferVSprintf(buf," <allocation>%llu</allocation>\n",
- def->allocation) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf," <capacity>%llu</capacity>\n",
+ def->capacity);
+ virBufferVSprintf(&buf," <allocation>%llu</allocation>\n",
+ def->allocation);
- if (virBufferAddLit(buf, " <target>\n") < 0)
- goto no_memory;
+ virBufferAddLit(&buf, " <target>\n");
- if (def->target.path &&
- virBufferVSprintf(buf," <path>%s</path>\n", def->target.path) < 0)
- goto no_memory;
+ if (def->target.path)
+ virBufferVSprintf(&buf," <path>%s</path>\n", def->target.path);
if (options->formatToString) {
const char *format = (options->formatToString)(conn,
def->target.format);
if (!format)
goto cleanup;
- if (virBufferVSprintf(buf," <format type='%s'/>\n", format) < 0)
- goto no_memory;
+ virBufferVSprintf(&buf," <format type='%s'/>\n", format);
}
- if (virBufferAddLit(buf," <permissions>\n") < 0)
- goto no_memory;
- if (virBufferVSprintf(buf," <mode>0%o</mode>\n",
- def->target.perms.mode) < 0)
- goto no_memory;
- if (virBufferVSprintf(buf," <owner>%d</owner>\n",
- def->target.perms.uid) < 0)
- goto no_memory;
- if (virBufferVSprintf(buf," <group>%d</group>\n",
- def->target.perms.gid) < 0)
- goto no_memory;
+ virBufferAddLit(&buf," <permissions>\n");
+ virBufferVSprintf(&buf," <mode>0%o</mode>\n",
+ def->target.perms.mode);
+ virBufferVSprintf(&buf," <owner>%d</owner>\n",
+ def->target.perms.uid);
+ virBufferVSprintf(&buf," <group>%d</group>\n",
+ def->target.perms.gid);
- if (def->target.perms.label &&
- virBufferVSprintf(buf," <label>%s</label>\n",
- def->target.perms.label) < 0)
- goto no_memory;
- if (virBufferAddLit(buf," </permissions>\n") < 0)
- goto no_memory;
- if (virBufferAddLit(buf, " </target>\n") < 0)
- goto no_memory;
+ if (def->target.perms.label)
+ virBufferVSprintf(&buf," <label>%s</label>\n",
+ def->target.perms.label);
+
+ virBufferAddLit(&buf," </permissions>\n");
+ virBufferAddLit(&buf, " </target>\n");
+ virBufferAddLit(&buf,"</volume>\n");
- if (virBufferAddLit(buf,"</volume>\n") < 0)
+ if (virBufferError(&buf))
goto no_memory;
- return virBufferContentAndFree(buf);
+ return virBufferContentAndReset(&buf);
no_memory:
virStorageReportError(conn, VIR_ERR_NO_MEMORY, "%s", _("xml"));
cleanup:
- virBufferFree(buf);
+ free(virBufferContentAndReset(&buf));
return NULL;
}
Index: src/test.c
===================================================================
RCS file: /data/cvs/libvirt/src/test.c,v
retrieving revision 1.72
diff -u -p -r1.72 test.c
--- src/test.c 10 Apr 2008 16:53:29 -0000 1.72
+++ src/test.c 26 Apr 2008 16:24:45 -0000
@@ -1523,34 +1523,30 @@ static int testSetVcpus(virDomainPtr dom
static char *testDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED)
{
- virBufferPtr buf;
- char *xml;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
unsigned char *uuid;
char uuidstr[VIR_UUID_STRING_BUFLEN];
GET_DOMAIN(domain, NULL);
- if (!(buf = virBufferNew(4000))) {
- testError(domain->conn, domain, NULL, VIR_ERR_NO_MEMORY, __FUNCTION__);
- return (NULL);
- }
-
- virBufferVSprintf(buf, "<domain type='test' id='%d'>\n", domain->id);
- virBufferVSprintf(buf, " <name>%s</name>\n", domain->name);
+ virBufferVSprintf(&buf, "<domain type='test' id='%d'>\n", domain->id);
+ virBufferVSprintf(&buf, " <name>%s</name>\n", domain->name);
uuid = domain->uuid;
virUUIDFormat(uuid, uuidstr);
- virBufferVSprintf(buf, " <uuid>%s</uuid>\n", uuidstr);
- virBufferVSprintf(buf, " <memory>%lu</memory>\n", privdom->info.maxMem);
- virBufferVSprintf(buf, " <vcpu>%d</vcpu>\n", privdom->info.nrVirtCpu);
- virBufferVSprintf(buf, " <on_reboot>%s</on_reboot>\n", testRestartFlagToString(privdom->onReboot));
- virBufferVSprintf(buf, " <on_poweroff>%s</on_poweroff>\n", testRestartFlagToString(privdom->onPoweroff));
- virBufferVSprintf(buf, " <on_crash>%s</on_crash>\n", testRestartFlagToString(privdom->onCrash));
+ virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr);
+ virBufferVSprintf(&buf, " <memory>%lu</memory>\n", privdom->info.maxMem);
+ virBufferVSprintf(&buf, " <vcpu>%d</vcpu>\n", privdom->info.nrVirtCpu);
+ virBufferVSprintf(&buf, " <on_reboot>%s</on_reboot>\n", testRestartFlagToString(privdom->onReboot));
+ virBufferVSprintf(&buf, " <on_poweroff>%s</on_poweroff>\n", testRestartFlagToString(privdom->onPoweroff));
+ virBufferVSprintf(&buf, " <on_crash>%s</on_crash>\n", testRestartFlagToString(privdom->onCrash));
- virBufferAddLit(buf, "</domain>\n");
+ virBufferAddLit(&buf, "</domain>\n");
- xml = buf->content;
- free(buf);
+ if (virBufferError(&buf)) {
+ testError(domain->conn, domain, NULL, VIR_ERR_NO_MEMORY, __FUNCTION__);
+ return NULL;
+ }
- return (xml);
+ return virBufferContentAndReset(&buf);
}
static int testNumOfDefinedDomains(virConnectPtr conn) {
@@ -1928,44 +1924,40 @@ static int testNetworkDestroy(virNetwork
}
static char *testNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) {
- virBufferPtr buf;
- char *xml;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
unsigned char *uuid;
char uuidstr[VIR_UUID_STRING_BUFLEN];
GET_NETWORK(network, NULL);
- if (!(buf = virBufferNew(4000))) {
- testError(network->conn, NULL, network, VIR_ERR_NO_MEMORY, __FUNCTION__);
- return (NULL);
- }
-
- virBufferAddLit(buf, "<network>\n");
- virBufferVSprintf(buf, " <name>%s</name>\n", network->name);
+ virBufferAddLit(&buf, "<network>\n");
+ virBufferVSprintf(&buf, " <name>%s</name>\n", network->name);
uuid = network->uuid;
virUUIDFormat(uuid, uuidstr);
- virBufferVSprintf(buf, " <uuid>%s</uuid>\n", uuidstr);
- virBufferVSprintf(buf, " <bridge name='%s'/>\n", privnet->bridge);
+ virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr);
+ virBufferVSprintf(&buf, " <bridge name='%s'/>\n", privnet->bridge);
if (privnet->forward) {
if (privnet->forwardDev[0])
- virBufferVSprintf(buf, " <forward dev='%s'/>\n", privnet->forwardDev);
+ virBufferVSprintf(&buf, " <forward dev='%s'/>\n", privnet->forwardDev);
else
- virBufferAddLit(buf, " <forward/>\n");
+ virBufferAddLit(&buf, " <forward/>\n");
}
- virBufferVSprintf(buf, " <ip address='%s' netmask='%s'>\n",
+ virBufferVSprintf(&buf, " <ip address='%s' netmask='%s'>\n",
privnet->ipAddress, privnet->ipNetmask);
- virBufferAddLit(buf, " <dhcp>\n");
- virBufferVSprintf(buf, " <range start='%s' end='%s'/>\n",
+ virBufferAddLit(&buf, " <dhcp>\n");
+ virBufferVSprintf(&buf, " <range start='%s' end='%s'/>\n",
privnet->dhcpStart, privnet->dhcpEnd);
- virBufferAddLit(buf, " </dhcp>\n");
- virBufferAddLit(buf, " </ip>\n");
+ virBufferAddLit(&buf, " </dhcp>\n");
+ virBufferAddLit(&buf, " </ip>\n");
- virBufferAddLit(buf, "</network>\n");
+ virBufferAddLit(&buf, "</network>\n");
- xml = buf->content;
- free(buf);
+ if (virBufferError(&buf)) {
+ testError(network->conn, NULL, network, VIR_ERR_NO_MEMORY, __FUNCTION__);
+ return NULL;
+ }
- return (xml);
+ return virBufferContentAndReset(&buf);
}
static char *testNetworkGetBridgeName(virNetworkPtr network) {
Index: src/virsh.c
===================================================================
RCS file: /data/cvs/libvirt/src/virsh.c,v
retrieving revision 1.146
diff -u -p -r1.146 virsh.c
--- src/virsh.c 25 Apr 2008 14:53:05 -0000 1.146
+++ src/virsh.c 26 Apr 2008 16:24:49 -0000
@@ -2885,10 +2885,9 @@ cmdPoolCreateAs(vshControl * ctl, vshCmd
{
virStoragePoolPtr pool;
int found;
+ char *xml;
char *name, *type, *srcHost, *srcPath, *srcDev, *target;
- virBuffer buf;
-
- memset(&buf, 0, sizeof(buf));
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
@@ -2905,39 +2904,36 @@ cmdPoolCreateAs(vshControl * ctl, vshCmd
srcDev = vshCommandOptString(cmd, "source-dev", &found);
target = vshCommandOptString(cmd, "target", &found);
- if (virBufferVSprintf(&buf, "<pool type='%s'>\n", type) < 0)
- goto cleanup;
- if (virBufferVSprintf(&buf, " <name>%s</name>\n", name) < 0)
- goto cleanup;
+ virBufferVSprintf(&buf, "<pool type='%s'>\n", type);
+ virBufferVSprintf(&buf, " <name>%s</name>\n", name);
if (srcHost || srcPath || srcDev) {
- if (virBufferAddLit(&buf, " <source>\n") < 0)
- goto cleanup;
- if (srcHost &&
- virBufferVSprintf(&buf, " <host name='%s'>\n", srcHost) < 0)
- goto cleanup;
- if (srcPath &&
- virBufferVSprintf(&buf, " <dir path='%s'/>\n", srcPath) < 0)
- goto cleanup;
- if (srcDev &&
- virBufferVSprintf(&buf, " <device path='%s'/>\n", srcDev) < 0)
- goto cleanup;
+ virBufferAddLit(&buf, " <source>\n");
+ if (srcHost)
+ virBufferVSprintf(&buf, " <host name='%s'>\n", srcHost);
- if (virBufferAddLit(&buf, " </source>\n") < 0)
- goto cleanup;
+ if (srcPath)
+ virBufferVSprintf(&buf, " <dir path='%s'/>\n", srcPath);
+
+ if (srcDev)
+ virBufferVSprintf(&buf, " <device path='%s'/>\n", srcDev);
+
+ virBufferAddLit(&buf, " </source>\n");
}
if (target) {
- if (virBufferAddLit(&buf, " <target>\n") < 0)
- goto cleanup;
- if (virBufferVSprintf(&buf, " <path>%s</path>\n", target) < 0)
- goto cleanup;
- if (virBufferAddLit(&buf, " </target>\n") < 0)
- goto cleanup;
+ virBufferAddLit(&buf, " <target>\n");
+ virBufferVSprintf(&buf, " <path>%s</path>\n", target);
+ virBufferAddLit(&buf, " </target>\n");
}
- if (virBufferAddLit(&buf, "</pool>\n") < 0)
- goto cleanup;
+ virBufferAddLit(&buf, "</pool>\n");
+
+ if (virBufferError(&buf)) {
+ vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
+ return FALSE;
+ }
+ xml = virBufferContentAndReset(&buf);
- pool = virStoragePoolCreateXML(ctl->conn, buf.content, 0);
- free (buf.content);
+ pool = virStoragePoolCreateXML(ctl->conn, xml, 0);
+ free (xml);
if (pool != NULL) {
vshPrint(ctl, _("Pool %s created\n"), name);
@@ -2949,7 +2945,7 @@ cmdPoolCreateAs(vshControl * ctl, vshCmd
}
cleanup:
- free(buf.content);
+ free(virBufferContentAndReset(&buf));
return FALSE;
}
@@ -3028,10 +3024,9 @@ cmdPoolDefineAs(vshControl * ctl, vshCmd
{
virStoragePoolPtr pool;
int found;
+ char *xml;
char *name, *type, *srcHost, *srcPath, *srcDev, *target;
- virBuffer buf;
-
- memset(&buf, 0, sizeof(buf));
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
@@ -3048,39 +3043,35 @@ cmdPoolDefineAs(vshControl * ctl, vshCmd
srcDev = vshCommandOptString(cmd, "source-dev", &found);
target = vshCommandOptString(cmd, "target", &found);
- if (virBufferVSprintf(&buf, "<pool type='%s'>\n", type) < 0)
- goto cleanup;
- if (virBufferVSprintf(&buf, " <name>%s</name>\n", name) < 0)
- goto cleanup;
+ virBufferVSprintf(&buf, "<pool type='%s'>\n", type);
+ virBufferVSprintf(&buf, " <name>%s</name>\n", name);
if (srcHost || srcPath || srcDev) {
- if (virBufferAddLit(&buf, " <source>\n") < 0)
- goto cleanup;
- if (srcHost &&
- virBufferVSprintf(&buf, " <host>%s</host>\n", srcHost) < 0)
- goto cleanup;
- if (srcPath &&
- virBufferVSprintf(&buf, " <path>%s</path>\n", srcPath) < 0)
- goto cleanup;
- if (srcDev &&
- virBufferVSprintf(&buf, " <device>%s</device>\n", srcDev) < 0)
- goto cleanup;
+ virBufferAddLit(&buf, " <source>\n");
+ if (srcHost)
+ virBufferVSprintf(&buf, " <host>%s</host>\n", srcHost);
+ if (srcPath)
+ virBufferVSprintf(&buf, " <path>%s</path>\n", srcPath);
+ if (srcDev)
+ virBufferVSprintf(&buf, " <device>%s</device>\n", srcDev);
- if (virBufferAddLit(&buf, " </source>\n") < 0)
- goto cleanup;
+ virBufferAddLit(&buf, " </source>\n");
}
if (target) {
- if (virBufferAddLit(&buf, " <target>\n") < 0)
- goto cleanup;
- if (virBufferVSprintf(&buf, " <path>%s</path>\n", target) < 0)
- goto cleanup;
- if (virBufferAddLit(&buf, " </target>\n") < 0)
- goto cleanup;
+ virBufferAddLit(&buf, " <target>\n");
+ virBufferVSprintf(&buf, " <path>%s</path>\n", target);
+ virBufferAddLit(&buf, " </target>\n");
}
- if (virBufferAddLit(&buf, "</pool>\n") < 0)
- goto cleanup;
+ virBufferAddLit(&buf, "</pool>\n");
- pool = virStoragePoolDefineXML(ctl->conn, buf.content, 0);
- free (buf.content);
+
+ if (virBufferError(&buf)) {
+ vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
+ return FALSE;
+ }
+ xml = virBufferContentAndReset(&buf);
+
+ pool = virStoragePoolDefineXML(ctl->conn, xml, 0);
+ free (xml);
if (pool != NULL) {
vshPrint(ctl, _("Pool %s defined\n"), name);
@@ -3092,7 +3083,7 @@ cmdPoolDefineAs(vshControl * ctl, vshCmd
}
cleanup:
- free(buf.content);
+ free(virBufferContentAndReset(&buf));
return FALSE;
}
@@ -3641,11 +3632,10 @@ cmdVolCreateAs(vshControl * ctl, vshCmd
virStoragePoolPtr pool;
virStorageVolPtr vol;
int found;
+ char *xml;
char *name, *capacityStr, *allocationStr, *format;
unsigned long long capacity, allocation = 0;
- virBuffer buf;
-
- memset(&buf, 0, sizeof(buf));
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
@@ -3671,30 +3661,28 @@ cmdVolCreateAs(vshControl * ctl, vshCmd
format = vshCommandOptString(cmd, "format", &found);
- if (virBufferAddLit(&buf, "<volume>\n") < 0)
- goto cleanup;
- if (virBufferVSprintf(&buf, " <name>%s</name>\n", name) < 0)
- goto cleanup;
- if (virBufferVSprintf(&buf, " <capacity>%llu</capacity>\n", capacity) < 0)
- goto cleanup;
- if (allocationStr &&
- virBufferVSprintf(&buf, " <allocation>%llu</allocation>\n", allocation) < 0)
- goto cleanup;
+ virBufferAddLit(&buf, "<volume>\n");
+ virBufferVSprintf(&buf, " <name>%s</name>\n", name);
+ virBufferVSprintf(&buf, " <capacity>%llu</capacity>\n", capacity);
+ if (allocationStr)
+ virBufferVSprintf(&buf, " <allocation>%llu</allocation>\n", allocation);
if (format) {
- if (virBufferAddLit(&buf, " <target>\n") < 0)
- goto cleanup;
+ virBufferAddLit(&buf, " <target>\n");
if (format)
- if (virBufferVSprintf(&buf, " <format type='%s'/>\n",format) < 0)
- goto cleanup;
- if (virBufferAddLit(&buf, " </target>\n") < 0)
- goto cleanup;
+ virBufferVSprintf(&buf, " <format type='%s'/>\n",format);
+ virBufferAddLit(&buf, " </target>\n");
}
- if (virBufferAddLit(&buf, "</volume>\n") < 0)
- goto cleanup;
+ virBufferAddLit(&buf, "</volume>\n");
+
- vol = virStorageVolCreateXML(pool, buf.content, 0);
- free (buf.content);
+ if (virBufferError(&buf)) {
+ vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
+ return FALSE;
+ }
+ xml = virBufferContentAndReset(&buf);
+ vol = virStorageVolCreateXML(pool, xml, 0);
+ free (xml);
virStoragePoolFree(pool);
if (vol != NULL) {
@@ -3707,7 +3695,7 @@ cmdVolCreateAs(vshControl * ctl, vshCmd
}
cleanup:
- free(buf.content);
+ free(virBufferContentAndReset(&buf));
virStoragePoolFree(pool);
return FALSE;
}
Index: src/xend_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xend_internal.c,v
retrieving revision 1.181
diff -u -p -r1.181 xend_internal.c
--- src/xend_internal.c 26 Apr 2008 14:22:02 -0000 1.181
+++ src/xend_internal.c 26 Apr 2008 16:24:51 -0000
@@ -608,16 +608,9 @@ xend_op_ext2(virConnectPtr xend, const c
size_t n_error, const char *key, va_list ap)
{
const char *k = key, *v;
- virBuffer buf;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
int ret;
-
- buf.content = malloc(1000);
- if (buf.content == NULL) {
- virXendError(xend, VIR_ERR_NO_MEMORY, _("allocate new buffer"));
- return -1;
- }
- buf.size = 1000;
- buf.use = 0;
+ char *content;
while (k) {
v = va_arg(ap, const char *);
@@ -631,8 +624,14 @@ xend_op_ext2(virConnectPtr xend, const c
virBufferVSprintf(&buf, "%s", "&");
}
- ret = http2unix(xend, xend_post(xend, path, buf.content, error, n_error));
- free(buf.content);
+ if (virBufferError(&buf)) {
+ virXendError(NULL, VIR_ERR_NO_MEMORY, _("allocate buffer"));
+ return -1;
+ }
+
+ content = virBufferContentAndReset(&buf);
+ ret = http2unix(xend, xend_post(xend, path, content, error, n_error));
+ free(content);
return ret;
}
@@ -1437,13 +1436,11 @@ xend_parse_sexp_desc_char(virConnectPtr
if (STREQ(devtype, "console") &&
STREQ(type, "pty") &&
tty != NULL) {
- if (virBufferVSprintf(buf, " <%s type='%s' tty='%s'>\n",
- devtype, type, tty) < 0)
- goto no_memory;
+ virBufferVSprintf(buf, " <%s type='%s' tty='%s'>\n",
+ devtype, type, tty);
} else {
- if (virBufferVSprintf(buf, " <%s type='%s'>\n",
- devtype, type) < 0)
- goto no_memory;
+ virBufferVSprintf(buf, " <%s type='%s'>\n",
+ devtype, type);
}
if (STREQ(type, "null") ||
@@ -1451,15 +1448,13 @@ xend_parse_sexp_desc_char(virConnectPtr
STREQ(type, "stdio")) {
/* no source needed */
} else if (STREQ(type, "pty")) {
- if (tty &&
+ if (tty)
virBufferVSprintf(buf, " <source path='%s'/>\n",
- tty) < 0)
- goto no_memory;
+ tty);
} else if (STREQ(type, "file") ||
STREQ(type, "pipe")) {
- if (virBufferVSprintf(buf, " <source path='%s'/>\n",
- value) < 0)
- goto no_memory;
+ virBufferVSprintf(buf, " <source path='%s'/>\n",
+ value);
} else if (STREQ(type, "tcp")) {
const char *offset = strchr(value, ':');
const char *offset2;
@@ -1490,20 +1485,17 @@ xend_parse_sexp_desc_char(virConnectPtr
protocol = telnet ? "telnet":"raw";
if (bindHost) {
- if (virBufferVSprintf(buf,
- " <source mode='%s' host='%s' service='%s'/>\n",
- mode, bindHost, bindPort) < 0)
- goto no_memory;
+ virBufferVSprintf(buf,
+ " <source mode='%s' host='%s' service='%s'/>\n",
+ mode, bindHost, bindPort);
} else {
- if (virBufferVSprintf(buf,
- " <source mode='%s' service='%s'/>\n",
- mode, bindPort) < 0)
- goto no_memory;
- }
- if (virBufferVSprintf(buf,
- " <protocol type='%s'/>\n",
- protocol) < 0)
- goto no_memory;
+ virBufferVSprintf(buf,
+ " <source mode='%s' service='%s'/>\n",
+ mode, bindPort);
+ }
+ virBufferVSprintf(buf,
+ " <protocol type='%s'/>\n",
+ protocol);
} else if (STREQ(type, "udp")) {
const char *offset = strchr(value, ':');
const char *offset2, *offset3;
@@ -1543,28 +1535,24 @@ xend_parse_sexp_desc_char(virConnectPtr
if (connectPort) {
if (connectHost) {
- if (virBufferVSprintf(buf,
- " <source mode='connect' host='%s' service='%s'/>\n",
- connectHost, connectPort) < 0)
- goto no_memory;
+ virBufferVSprintf(buf,
+ " <source mode='connect' host='%s' service='%s'/>\n",
+ connectHost, connectPort);
} else {
- if (virBufferVSprintf(buf,
- " <source mode='connect' service='%s'/>\n",
- connectPort) < 0)
- goto no_memory;
+ virBufferVSprintf(buf,
+ " <source mode='connect' service='%s'/>\n",
+ connectPort);
}
}
if (bindPort) {
if (bindHost) {
- if (virBufferVSprintf(buf,
- " <source mode='bind' host='%s' service='%s'/>\n",
- bindHost, bindPort) < 0)
- goto no_memory;
+ virBufferVSprintf(buf,
+ " <source mode='bind' host='%s' service='%s'/>\n",
+ bindHost, bindPort);
} else {
- if (virBufferVSprintf(buf,
- " <source mode='bind' service='%s'/>\n",
- bindPort) < 0)
- goto no_memory;
+ virBufferVSprintf(buf,
+ " <source mode='bind' service='%s'/>\n",
+ bindPort);
}
}
@@ -1582,18 +1570,15 @@ xend_parse_sexp_desc_char(virConnectPtr
strstr(offset, ",listen") != NULL)
dolisten = 1;
- if (virBufferVSprintf(buf, " <source mode='%s' path='%s'/>\n",
- dolisten ? "bind" : "connect", path) < 0)
- goto no_memory;
+ virBufferVSprintf(buf, " <source mode='%s' path='%s'/>\n",
+ dolisten ? "bind" : "connect", path);
}
- if (virBufferVSprintf(buf, " <target port='%d'/>\n",
- portNum) < 0)
- goto no_memory;
-
- if (virBufferVSprintf(buf, " </%s>\n",
- devtype) < 0)
- goto no_memory;
+ virBufferVSprintf(buf, " <target port='%d'/>\n",
+ portNum);
+
+ virBufferVSprintf(buf, " </%s>\n",
+ devtype);
ret = 0;
@@ -1635,7 +1620,7 @@ xend_parse_sexp_desc(virConnectPtr conn,
struct sexpr *cur, *node;
const char *tmp;
char *tty;
- virBuffer buf;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
int hvm = 0, bootloader = 0, vfb = 0;
int domid = -1;
int max_mem, cur_mem;
@@ -1647,11 +1632,6 @@ xend_parse_sexp_desc(virConnectPtr conn,
/* ERROR */
return (NULL);
}
- buf.content = malloc(4000);
- if (buf.content == NULL)
- return (NULL);
- buf.size = 4000;
- buf.use = 0;
tmp = sexpr_node(root, "domain/domid");
if (tmp == NULL && xendConfigVersion < 3) { /* Old XenD, domid was mandatory */
@@ -2097,11 +2077,15 @@ xend_parse_sexp_desc(virConnectPtr conn,
virBufferAddLit(&buf, " </devices>\n");
virBufferAddLit(&buf, "</domain>\n");
- buf.content[buf.use] = 0;
- return (buf.content);
+ if (virBufferError(&buf)) {
+ virXendError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"));
+ return NULL;
+ }
+
+ return virBufferContentAndReset(&buf);
error:
- free(buf.content);
+ free(virBufferContentAndReset(&buf));
return (NULL);
}
Index: src/xm_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xm_internal.c,v
retrieving revision 1.71
diff -u -p -r1.71 xm_internal.c
--- src/xm_internal.c 26 Apr 2008 14:22:02 -0000 1.71
+++ src/xm_internal.c 26 Apr 2008 16:24:54 -0000
@@ -579,8 +579,7 @@ int xenXMDomainGetInfo(virDomainPtr doma
* domain, suitable for later feeding for virDomainCreateLinux
*/
char *xenXMDomainFormatXML(virConnectPtr conn, virConfPtr conf) {
- virBufferPtr buf;
- char *xml;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
const char *name;
unsigned char uuid[VIR_UUID_BUFLEN];
char uuidstr[VIR_UUID_STRING_BUFLEN];
@@ -602,12 +601,10 @@ char *xenXMDomainFormatXML(virConnectPtr
if (xenXMConfigGetUUID(conf, "uuid", uuid) < 0)
return (NULL);
- buf = virBufferNew(4096);
-
- virBufferAddLit(buf, "<domain type='xen'>\n");
- virBufferVSprintf(buf, " <name>%s</name>\n", name);
+ virBufferAddLit(&buf, "<domain type='xen'>\n");
+ virBufferVSprintf(&buf, " <name>%s</name>\n", name);
virUUIDFormat(uuid, uuidstr);
- virBufferVSprintf(buf, " <uuid>%s</uuid>\n", uuidstr);
+ virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr);
if ((xenXMConfigGetString(conf, "builder", &str) == 0) &&
!strcmp(str, "hvm"))
@@ -615,10 +612,10 @@ char *xenXMDomainFormatXML(virConnectPtr
if (hvm) {
const char *boot;
- virBufferAddLit(buf, " <os>\n");
- virBufferAddLit(buf, " <type>hvm</type>\n");
+ virBufferAddLit(&buf, " <os>\n");
+ virBufferAddLit(&buf, " <type>hvm</type>\n");
if (xenXMConfigGetString(conf, "kernel", &str) == 0)
- virBufferVSprintf(buf, " <loader>%s</loader>\n", str);
+ virBufferVSprintf(&buf, " <loader>%s</loader>\n", str);
if (xenXMConfigGetString(conf, "boot", &boot) < 0)
boot = "c";
@@ -637,90 +634,90 @@ char *xenXMDomainFormatXML(virConnectPtr
dev = "hd";
break;
}
- virBufferVSprintf(buf, " <boot dev='%s'/>\n", dev);
+ virBufferVSprintf(&buf, " <boot dev='%s'/>\n", dev);
boot++;
}
- virBufferAddLit(buf, " </os>\n");
+ virBufferAddLit(&buf, " </os>\n");
} else {
if (xenXMConfigGetString(conf, "bootloader", &str) == 0)
- virBufferVSprintf(buf, " <bootloader>%s</bootloader>\n", str);
+ virBufferVSprintf(&buf, " <bootloader>%s</bootloader>\n", str);
if (xenXMConfigGetString(conf, "bootargs", &str) == 0)
- virBufferEscapeString(buf, " <bootloader_args>%s</bootloader_args>\n", str);
+ virBufferEscapeString(&buf, " <bootloader_args>%s</bootloader_args>\n", str);
if (xenXMConfigGetString(conf, "kernel", &str) == 0) {
- virBufferAddLit(buf, " <os>\n");
- virBufferAddLit(buf, " <type>linux</type>\n");
- virBufferVSprintf(buf, " <kernel>%s</kernel>\n", str);
+ virBufferAddLit(&buf, " <os>\n");
+ virBufferAddLit(&buf, " <type>linux</type>\n");
+ virBufferVSprintf(&buf, " <kernel>%s</kernel>\n", str);
if (xenXMConfigGetString(conf, "ramdisk", &str) == 0)
- virBufferVSprintf(buf, " <initrd>%s</initrd>\n", str);
+ virBufferVSprintf(&buf, " <initrd>%s</initrd>\n", str);
if (xenXMConfigGetString(conf, "extra", &str) == 0)
- virBufferEscapeString(buf, " <cmdline>%s</cmdline>\n", str);
- virBufferAddLit(buf, " </os>\n");
+ virBufferEscapeString(&buf, " <cmdline>%s</cmdline>\n", str);
+ virBufferAddLit(&buf, " </os>\n");
}
}
if (xenXMConfigGetInt(conf, "memory", &val) < 0)
val = MIN_XEN_GUEST_SIZE * 2;
- virBufferVSprintf(buf, " <currentMemory>%ld</currentMemory>\n",
+ virBufferVSprintf(&buf, " <currentMemory>%ld</currentMemory>\n",
val * 1024);
if (xenXMConfigGetInt(conf, "maxmem", &val) < 0)
if (xenXMConfigGetInt(conf, "memory", &val) < 0)
val = MIN_XEN_GUEST_SIZE * 2;
- virBufferVSprintf(buf, " <memory>%ld</memory>\n", val * 1024);
+ virBufferVSprintf(&buf, " <memory>%ld</memory>\n", val * 1024);
- virBufferAddLit(buf, " <vcpu");
+ virBufferAddLit(&buf, " <vcpu");
if (xenXMConfigGetString(conf, "cpus", &str) == 0) {
char *ranges;
ranges = virConvertCpuSet(conn, str, 0);
if (ranges != NULL) {
- virBufferVSprintf(buf, " cpuset='%s'", ranges);
+ virBufferVSprintf(&buf, " cpuset='%s'", ranges);
free(ranges);
} else
- virBufferVSprintf(buf, " cpuset='%s'", str);
+ virBufferVSprintf(&buf, " cpuset='%s'", str);
}
if (xenXMConfigGetInt(conf, "vcpus", &val) < 0)
val = 1;
- virBufferVSprintf(buf, ">%ld</vcpu>\n", val);
+ virBufferVSprintf(&buf, ">%ld</vcpu>\n", val);
if (xenXMConfigGetString(conf, "on_poweroff", &str) < 0)
str = "destroy";
- virBufferVSprintf(buf, " <on_poweroff>%s</on_poweroff>\n", str);
+ virBufferVSprintf(&buf, " <on_poweroff>%s</on_poweroff>\n", str);
if (xenXMConfigGetString(conf, "on_reboot", &str) < 0)
str = "restart";
- virBufferVSprintf(buf, " <on_reboot>%s</on_reboot>\n", str);
+ virBufferVSprintf(&buf, " <on_reboot>%s</on_reboot>\n", str);
if (xenXMConfigGetString(conf, "on_crash", &str) < 0)
str = "restart";
- virBufferVSprintf(buf, " <on_crash>%s</on_crash>\n", str);
+ virBufferVSprintf(&buf, " <on_crash>%s</on_crash>\n", str);
if (hvm) {
- virBufferAddLit(buf, " <features>\n");
+ virBufferAddLit(&buf, " <features>\n");
if (xenXMConfigGetInt(conf, "pae", &val) == 0 &&
val)
- virBufferAddLit(buf, " <pae/>\n");
+ virBufferAddLit(&buf, " <pae/>\n");
if (xenXMConfigGetInt(conf, "acpi", &val) == 0 &&
val)
- virBufferAddLit(buf, " <acpi/>\n");
+ virBufferAddLit(&buf, " <acpi/>\n");
if (xenXMConfigGetInt(conf, "apic", &val) == 0 &&
val)
- virBufferAddLit(buf, " <apic/>\n");
- virBufferAddLit(buf, " </features>\n");
+ virBufferAddLit(&buf, " <apic/>\n");
+ virBufferAddLit(&buf, " </features>\n");
if (xenXMConfigGetInt(conf, "localtime", &val) < 0)
val = 0;
- virBufferVSprintf(buf, " <clock offset='%s'/>\n", val ? "localtime" : "utc");
+ virBufferVSprintf(&buf, " <clock offset='%s'/>\n", val ? "localtime" : "utc");
}
- virBufferAddLit(buf, " <devices>\n");
+ virBufferAddLit(&buf, " <devices>\n");
if (hvm) {
if (xenXMConfigGetString(conf, "device_model", &str) == 0)
- virBufferVSprintf(buf, " <emulator>%s</emulator>\n", str);
+ virBufferVSprintf(&buf, " <emulator>%s</emulator>\n", str);
}
list = virConfGetValue(conf, "disk");
@@ -808,23 +805,23 @@ char *xenXMDomainFormatXML(virConnectPtr
tmp[0] = '\0';
}
- virBufferVSprintf(buf, " <disk type='%s' device='%s'>\n",
+ virBufferVSprintf(&buf, " <disk type='%s' device='%s'>\n",
block ? "block" : "file",
cdrom ? "cdrom" : "disk");
if (drvType[0])
- virBufferVSprintf(buf, " <driver name='%s' type='%s'/>\n", drvName, drvType);
+ virBufferVSprintf(&buf, " <driver name='%s' type='%s'/>\n", drvName, drvType);
else
- virBufferVSprintf(buf, " <driver name='%s'/>\n", drvName);
+ virBufferVSprintf(&buf, " <driver name='%s'/>\n", drvName);
if (src[0])
- virBufferVSprintf(buf, " <source %s='%s'/>\n", block ? "dev" : "file", src);
- virBufferVSprintf(buf, " <target dev='%s'/>\n", dev);
+ virBufferVSprintf(&buf, " <source %s='%s'/>\n", block ? "dev" : "file", src);
+ virBufferVSprintf(&buf, " <target dev='%s'/>\n", dev);
if (!strcmp(head, "r") ||
!strcmp(head, "ro"))
- virBufferAddLit(buf, " <readonly/>\n");
+ virBufferAddLit(&buf, " <readonly/>\n");
else if ((!strcmp(head, "w!")) ||
(!strcmp(head, "!")))
- virBufferAddLit(buf, " <shareable/>\n");
- virBufferAddLit(buf, " </disk>\n");
+ virBufferAddLit(&buf, " <shareable/>\n");
+ virBufferAddLit(&buf, " </disk>\n");
skipdisk:
list = list->next;
@@ -833,12 +830,12 @@ char *xenXMDomainFormatXML(virConnectPtr
if (hvm && priv->xendConfigVersion == 1) {
if (xenXMConfigGetString(conf, "cdrom", &str) == 0) {
- virBufferAddLit(buf, " <disk type='file' device='cdrom'>\n");
- virBufferAddLit(buf, " <driver name='file'/>\n");
- virBufferVSprintf(buf, " <source file='%s'/>\n", str);
- virBufferAddLit(buf, " <target dev='hdc'/>\n");
- virBufferAddLit(buf, " <readonly/>\n");
- virBufferAddLit(buf, " </disk>\n");
+ virBufferAddLit(&buf, " <disk type='file' device='cdrom'>\n");
+ virBufferAddLit(&buf, " <driver name='file'/>\n");
+ virBufferVSprintf(&buf, " <source file='%s'/>\n", str);
+ virBufferAddLit(&buf, " <target dev='hdc'/>\n");
+ virBufferAddLit(&buf, " <readonly/>\n");
+ virBufferAddLit(&buf, " </disk>\n");
}
}
@@ -909,16 +906,16 @@ char *xenXMDomainFormatXML(virConnectPtr
type = 1;
}
- virBufferAddLit(buf, " <interface type='bridge'>\n");
+ virBufferAddLit(&buf, " <interface type='bridge'>\n");
if (mac[0])
- virBufferVSprintf(buf, " <mac address='%s'/>\n", mac);
+ virBufferVSprintf(&buf, " <mac address='%s'/>\n", mac);
if (type == 1 && bridge[0])
- virBufferVSprintf(buf, " <source bridge='%s'/>\n", bridge);
+ virBufferVSprintf(&buf, " <source bridge='%s'/>\n", bridge);
if (script[0])
- virBufferVSprintf(buf, " <script path='%s'/>\n", script);
+ virBufferVSprintf(&buf, " <script path='%s'/>\n", script);
if (ip[0])
- virBufferVSprintf(buf, " <ip address='%s'/>\n", ip);
- virBufferAddLit(buf, " </interface>\n");
+ virBufferVSprintf(&buf, " <ip address='%s'/>\n", ip);
+ virBufferAddLit(&buf, " </interface>\n");
skipnic:
list = list->next;
@@ -928,9 +925,9 @@ char *xenXMDomainFormatXML(virConnectPtr
if (hvm) {
if (xenXMConfigGetString(conf, "usbdevice", &str) == 0 && str) {
if (!strcmp(str, "tablet"))
- virBufferAddLit(buf, " <input type='tablet' bus='usb'/>\n");
+ virBufferAddLit(&buf, " <input type='tablet' bus='usb'/>\n");
else if (!strcmp(str, "mouse"))
- virBufferAddLit(buf, " <input type='mouse' bus='usb'/>\n");
+ virBufferAddLit(&buf, " <input type='mouse' bus='usb'/>\n");
/* Ignore else branch - probably some other non-input device we don't
support in libvirt yet */
}
@@ -1003,54 +1000,56 @@ char *xenXMDomainFormatXML(virConnectPtr
}
if (vnc || sdl) {
- virBufferVSprintf(buf, " <input type='mouse' bus='%s'/>\n", hvm ? "ps2":"xen");
+ virBufferVSprintf(&buf, " <input type='mouse' bus='%s'/>\n", hvm ? "ps2":"xen");
}
if (vnc) {
- virBufferVSprintf(buf,
+ virBufferVSprintf(&buf,
" <graphics type='vnc' port='%ld'",
(vncunused ? -1 : 5900+vncdisplay));
if (vnclisten) {
- virBufferVSprintf(buf, " listen='%s'", vnclisten);
+ virBufferVSprintf(&buf, " listen='%s'", vnclisten);
}
if (vncpasswd) {
- virBufferVSprintf(buf, " passwd='%s'", vncpasswd);
+ virBufferVSprintf(&buf, " passwd='%s'", vncpasswd);
}
if (keymap) {
- virBufferVSprintf(buf, " keymap='%s'", keymap);
+ virBufferVSprintf(&buf, " keymap='%s'", keymap);
}
- virBufferAddLit(buf, "/>\n");
+ virBufferAddLit(&buf, "/>\n");
}
if (sdl) {
- virBufferAddLit(buf, " <graphics type='sdl'/>\n");
+ virBufferAddLit(&buf, " <graphics type='sdl'/>\n");
}
if (hvm) {
if (xenXMConfigGetString(conf, "parallel", &str) == 0) {
if (STRNEQ(str, "none"))
- xend_parse_sexp_desc_char(conn, buf, "parallel", 0, str, NULL);
+ xend_parse_sexp_desc_char(conn, &buf, "parallel", 0, str, NULL);
}
if (xenXMConfigGetString(conf, "serial", &str) == 0) {
if (STRNEQ(str, "none")) {
- xend_parse_sexp_desc_char(conn, buf, "serial", 0, str, NULL);
+ xend_parse_sexp_desc_char(conn, &buf, "serial", 0, str, NULL);
/* Add back-compat console tag for primary console */
- xend_parse_sexp_desc_char(conn, buf, "console", 0, str, NULL);
+ xend_parse_sexp_desc_char(conn, &buf, "console", 0, str, NULL);
}
}
} else {
/* Paravirt implicitly always has a single console */
- virBufferAddLit(buf, " <console type='pty'>\n");
- virBufferAddLit(buf, " <target port='0'/>\n");
- virBufferAddLit(buf, " </console>\n");
+ virBufferAddLit(&buf, " <console type='pty'>\n");
+ virBufferAddLit(&buf, " <target port='0'/>\n");
+ virBufferAddLit(&buf, " </console>\n");
}
- virBufferAddLit(buf, " </devices>\n");
+ virBufferAddLit(&buf, " </devices>\n");
+
+ virBufferAddLit(&buf, "</domain>\n");
- virBufferAddLit(buf, "</domain>\n");
+ if (virBufferError(&buf)) {
+ xenXMError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"));
+ return NULL;
+ }
- xml = buf->content;
- buf->content = NULL;
- virBufferFree(buf);
- return (xml);
+ return virBufferContentAndReset(&buf);
}
@@ -1254,7 +1253,7 @@ int xenXMDomainPinVcpu(virDomainPtr doma
{
const char *filename;
xenXMConfCachePtr entry;
- virBufferPtr mapbuf;
+ virBuffer mapbuf = VIR_BUFFER_INITIALIZER;
char *mapstr = NULL;
char *ranges = NULL;
int i, j, n, comma = 0;
@@ -1288,33 +1287,24 @@ int xenXMDomainPinVcpu(virDomainPtr doma
}
/* from bit map, build character string of mapped CPU numbers */
- mapbuf = virBufferNew (16);
- if (mapbuf == NULL) {
- xenXMError (domain->conn, VIR_ERR_NO_MEMORY, __FUNCTION__);
- return -1;
- }
for (i = 0; i < maplen; i++)
for (j = 0; j < 8; j++)
if ((cpumap[i] & (1 << j))) {
n = i*8 + j;
- if (comma) {
- if (virBufferAddLit (mapbuf, ",") == -1) {
- xenXMError (domain->conn, VIR_ERR_NO_MEMORY, __FUNCTION__);
- virBufferFree (mapbuf);
- return -1;
- }
- }
+ if (comma)
+ virBufferAddLit (&mapbuf, ",");
comma = 1;
- if (virBufferVSprintf (mapbuf, "%d", n) == -1) {
- xenXMError (domain->conn, VIR_ERR_NO_MEMORY, __FUNCTION__);
- virBufferFree (mapbuf);
- return -1;
- }
+ virBufferVSprintf (&mapbuf, "%d", n);
}
- mapstr = virBufferContentAndFree (mapbuf);
+ if (virBufferError(&mapbuf)) {
+ xenXMError(domain->conn, VIR_ERR_NO_MEMORY, _("allocate buffer"));
+ return -1;
+ }
+
+ mapstr = virBufferContentAndReset(&mapbuf);
/* convert the mapstr to a range based string */
ranges = virConvertCpuSet(domain->conn, mapstr, 0);
Index: src/xml.c
===================================================================
RCS file: /data/cvs/libvirt/src/xml.c,v
retrieving revision 1.118
diff -u -p -r1.118 xml.c
--- src/xml.c 26 Apr 2008 14:22:02 -0000 1.118
+++ src/xml.c 26 Apr 2008 16:24:55 -0000
@@ -102,19 +102,13 @@ parseCpuNumber(const char **str, int max
char *
virSaveCpuSet(virConnectPtr conn, char *cpuset, int maxcpu)
{
- virBufferPtr buf;
- char *ret;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
int start, cur;
int first = 1;
if ((cpuset == NULL) || (maxcpu <= 0) || (maxcpu > 100000))
return (NULL);
- buf = virBufferNew(1000);
- if (buf == NULL) {
- virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 1000);
- return (NULL);
- }
cur = 0;
start = -1;
while (cur < maxcpu) {
@@ -123,27 +117,32 @@ virSaveCpuSet(virConnectPtr conn, char *
start = cur;
} else if (start != -1) {
if (!first)
- virBufferAddLit(buf, ",");
+ virBufferAddLit(&buf, ",");
else
first = 0;
if (cur == start + 1)
- virBufferVSprintf(buf, "%d", start);
+ virBufferVSprintf(&buf, "%d", start);
else
- virBufferVSprintf(buf, "%d-%d", start, cur - 1);
+ virBufferVSprintf(&buf, "%d-%d", start, cur - 1);
start = -1;
}
cur++;
}
if (start != -1) {
if (!first)
- virBufferAddLit(buf, ",");
+ virBufferAddLit(&buf, ",");
if (maxcpu == start + 1)
- virBufferVSprintf(buf, "%d", start);
+ virBufferVSprintf(&buf, "%d", start);
else
- virBufferVSprintf(buf, "%d-%d", start, maxcpu - 1);
+ virBufferVSprintf(&buf, "%d-%d", start, maxcpu - 1);
}
- ret = virBufferContentAndFree(buf);
- return (ret);
+
+ if (virBufferError(&buf)) {
+ virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 1000);
+ return NULL;
+ }
+
+ return virBufferContentAndReset(&buf);
}
/**
@@ -1054,11 +1053,9 @@ virDomainParseXMLOSDescHVM(virConnectPtr
char scratch[PATH_MAX];
if (virDomainParseXMLOSDescHVMChar(conn, scratch, sizeof(scratch), cur) < 0)
goto error;
- if (virBufferVSprintf(buf, "(parallel %s)", scratch) < 0)
- goto no_memory;
+ virBufferVSprintf(buf, "(parallel %s)", scratch);
} else {
- if (virBufferAddLit(buf, "(parallel none)") < 0)
- goto no_memory;
+ virBufferAddLit(buf, "(parallel none)");
}
cur = virXPathNode("/domain/devices/serial[1]", ctxt);
@@ -1066,8 +1063,7 @@ virDomainParseXMLOSDescHVM(virConnectPtr
char scratch[PATH_MAX];
if (virDomainParseXMLOSDescHVMChar(conn, scratch, sizeof(scratch), cur) < 0)
goto error;
- if (virBufferVSprintf(buf, "(serial %s)", scratch) < 0)
- goto no_memory;
+ virBufferVSprintf(buf, "(serial %s)", scratch);
} else {
res = virXPathBoolean("count(domain/devices/console) > 0", ctxt);
if (res < 0) {
@@ -1075,27 +1071,20 @@ virDomainParseXMLOSDescHVM(virConnectPtr
goto error;
}
if (res) {
- if (virBufferAddLit(buf, "(serial pty)") < 0)
- goto no_memory;
+ virBufferAddLit(buf, "(serial pty)");
} else {
- if (virBufferAddLit(buf, "(serial none)") < 0)
- goto no_memory;
+ virBufferAddLit(buf, "(serial none)");
}
}
str = virXPathString("string(/domain/clock/@offset)", ctxt);
- if (str != NULL && !strcmp(str, "localtime")) {
- if (virBufferAddLit(buf, "(localtime 1)") < 0)
- goto no_memory;
+ if (str != NULL && STREQ(str, "localtime")) {
+ virBufferAddLit(buf, "(localtime 1)");
}
free(str);
return (0);
-no_memory:
- virXMLError(conn, VIR_ERR_XML_ERROR,
- _("cannot allocate memory for buffer"), 0);
-
error:
free(nodes);
return (-1);
@@ -1509,7 +1498,7 @@ virDomainParseXMLDesc(virConnectPtr conn
xmlDocPtr xml = NULL;
xmlNodePtr node;
char *nam = NULL;
- virBuffer buf;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
xmlChar *prop;
xmlParserCtxtPtr pctxt;
xmlXPathContextPtr ctxt = NULL;
@@ -1525,11 +1514,6 @@ virDomainParseXMLDesc(virConnectPtr conn
if (name != NULL)
*name = NULL;
- buf.content = malloc(1000);
- if (buf.content == NULL)
- return (NULL);
- buf.size = 1000;
- buf.use = 0;
pctxt = xmlNewParserCtxt();
if ((pctxt == NULL) || (pctxt->sax == NULL)) {
@@ -1787,7 +1771,6 @@ virDomainParseXMLDesc(virConnectPtr conn
virBufferAddLit(&buf, ")"); /* closes (vm */
- buf.content[buf.use] = 0;
xmlXPathFreeContext(ctxt);
xmlFreeDoc(xml);
@@ -1798,7 +1781,12 @@ virDomainParseXMLDesc(virConnectPtr conn
else
free(nam);
- return (buf.content);
+ if (virBufferError(&buf)) {
+ virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0);
+ return NULL;
+ }
+
+ return virBufferContentAndReset(&buf);
error:
free(nam);
@@ -1809,7 +1797,7 @@ virDomainParseXMLDesc(virConnectPtr conn
xmlFreeDoc(xml);
if (pctxt != NULL)
xmlFreeParserCtxt(pctxt);
- free(buf.content);
+ free(virBufferContentAndReset(&buf));
return (NULL);
}
@@ -1834,14 +1822,8 @@ virParseXMLDevice(virConnectPtr conn, co
{
xmlDocPtr xml = NULL;
xmlNodePtr node;
- virBuffer buf;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
- buf.content = malloc(1000);
- if (buf.content == NULL)
- return (NULL);
- buf.size = 1000;
- buf.use = 0;
- buf.content[0] = 0;
xml = xmlReadDoc((const xmlChar *) xmldesc, "device.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
@@ -1856,9 +1838,6 @@ virParseXMLDevice(virConnectPtr conn, co
if (virDomainParseXMLDiskDesc(conn, node, &buf, hvm,
xendConfigVersion) != 0)
goto error;
- /* SXP is not created when device is "floppy". */
- else if (buf.use == 0)
- goto error;
} else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
if (virDomainParseXMLIfDesc(conn, node, &buf, hvm,
xendConfigVersion) != 0)
@@ -1867,14 +1846,20 @@ virParseXMLDevice(virConnectPtr conn, co
virXMLError(conn, VIR_ERR_XML_ERROR, (const char *) node->name, 0);
goto error;
}
- cleanup:
- if (xml != NULL)
- xmlFreeDoc(xml);
- return buf.content;
+
+ xmlFreeDoc(xml);
+
+ if (virBufferError(&buf)) {
+ virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0);
+ return NULL;
+ }
+
+ return virBufferContentAndReset(&buf);
+
error:
- free(buf.content);
- buf.content = NULL;
- goto cleanup;
+ free(virBufferContentAndReset(&buf));
+ xmlFreeDoc(xml);
+ return NULL;
}
Index: src/xmlrpc.c
===================================================================
RCS file: /data/cvs/libvirt/src/xmlrpc.c,v
retrieving revision 1.13
diff -u -p -r1.13 xmlrpc.c
--- src/xmlrpc.c 10 Apr 2008 16:54:54 -0000 1.13
+++ src/xmlrpc.c 26 Apr 2008 16:24:56 -0000
@@ -363,14 +363,12 @@ void xmlRpcValueMarshal(xmlRpcValuePtr v
virBufferStrcat(buf, "</value>\n", NULL);
}
-virBufferPtr xmlRpcMarshalRequest(const char *request,
- int argc, xmlRpcValuePtr *argv)
+void xmlRpcMarshalRequest(const char *request,
+ virBufferPtr buf,
+ int argc, xmlRpcValuePtr *argv)
{
- virBufferPtr buf;
int i;
- buf = virBufferNew(1024);
-
virBufferStrcat(buf,
"<?xml version=\"1.0\"?>\n"
"<methodCall>\n"
@@ -386,7 +384,6 @@ virBufferPtr xmlRpcMarshalRequest(const
virBufferStrcat(buf,
" </params>\n"
"</methodCall>\n", NULL);
- return buf;
}
xmlRpcValuePtr xmlRpcUnmarshalResponse(xmlNodePtr node, bool *is_fault)
@@ -564,13 +561,14 @@ int xmlRpcCall(xmlRpcContextPtr context,
va_list ap;
int argc;
xmlRpcValuePtr *argv;
- virBufferPtr buf;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
char *ret;
xmlDocPtr xml;
xmlNodePtr node;
bool fault;
xmlRpcValuePtr value;
void *retval = NULL;
+ char *content;
va_start(ap, fmt);
@@ -582,16 +580,16 @@ int xmlRpcCall(xmlRpcContextPtr context,
va_end(ap);
- buf = xmlRpcMarshalRequest(method, argc, argv);
+ xmlRpcMarshalRequest(method, &buf, argc, argv);
xmlRpcArgvFree(argc, argv);
- if (!buf)
+ if (virBufferError(&buf))
return -1;
- ret = xmlRpcCallRaw(context->uri, buf->content);
-
- virBufferFree(buf);
+ content = virBufferContentAndReset(&buf);
+ ret = xmlRpcCallRaw(context->uri, content);
+ free(content);
if (!ret)
return -1;
Index: src/xmlrpc.h
===================================================================
RCS file: /data/cvs/libvirt/src/xmlrpc.h,v
retrieving revision 1.4
diff -u -p -r1.4 xmlrpc.h
--- src/xmlrpc.h 10 Apr 2008 16:54:54 -0000 1.4
+++ src/xmlrpc.h 26 Apr 2008 16:24:56 -0000
@@ -89,8 +89,9 @@ struct _xmlRpcContext;
xmlRpcValuePtr *xmlRpcArgvNew(const char *fmt, va_list ap, int *argc);
void xmlRpcArgvFree(int argc, xmlRpcValuePtr *argv);
-virBufferPtr xmlRpcMarshalRequest(const char *request,
- int argc, xmlRpcValuePtr *argv);
+void xmlRpcMarshalRequest(const char *request,
+ virBufferPtr buf,
+ int argc, xmlRpcValuePtr *argv);
xmlRpcValuePtr xmlRpcUnmarshalResponse(xmlNodePtr node, bool *is_fault);
Index: tests/xmlrpctest.c
===================================================================
RCS file: /data/cvs/libvirt/tests/xmlrpctest.c,v
retrieving revision 1.11
diff -u -p -r1.11 xmlrpctest.c
--- tests/xmlrpctest.c 10 Apr 2008 16:54:54 -0000 1.11
+++ tests/xmlrpctest.c 26 Apr 2008 16:24:56 -0000
@@ -59,22 +59,20 @@ testMethodPlusDOUBLE(const void *data)
return retval==(10.1234+10.1234) ? 0 : -1;
}
-static virBufferPtr
-marshalRequest(const char *fmt, ...)
+static void
+marshalRequest(virBufferPtr buf, const char *fmt, ...)
{
int argc;
xmlRpcValuePtr *argv;
- virBufferPtr buf;
va_list ap;
va_start(ap, fmt);
argv = xmlRpcArgvNew(fmt, ap, &argc);
va_end(ap);
- buf = xmlRpcMarshalRequest("test", argc, argv);
+ xmlRpcMarshalRequest("test", buf, argc, argv);
xmlRpcArgvFree(argc, argv);
- return buf;
}
static int
@@ -132,14 +130,21 @@ testMarshalRequestINT(const void *data)
int num = INT_MAX;
int ret = 0;
int check = data ? *((int *)data) : 0;
- virBufferPtr buf = marshalRequest("i", num);
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ marshalRequest(&buf, "i", num);
+ char *content;
+
+ if (virBufferError(&buf))
+ return -1;
+
+ content = virBufferContentAndReset(&buf);
if (check)
- ret = checkRequestValue(buf->content,
+ ret = checkRequestValue(content,
"number(/methodCall/params/param[1]/value/int)",
XML_RPC_INTEGER, (void *) &num);
- virBufferFree(buf);
+ free(content);
return ret;
}
@@ -149,13 +154,21 @@ testMarshalRequestSTRING(const void *dat
const char *str = "This library will be really sexy.";
int ret = 0;
int check = data ? *((int *)data) : 0;
- virBufferPtr buf = marshalRequest("s", str);
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ char *content;
+
+ marshalRequest(&buf, "s", str);
+ if (virBufferError(&buf))
+ return -1;
+
+ content = virBufferContentAndReset(&buf);
if (check)
- ret = checkRequestValue(buf->content,
+ ret = checkRequestValue(content,
"string(/methodCall/params/param[1]/value/string)",
XML_RPC_STRING, (void *) str);
- virBufferFree(buf);
+
+ free(content);
return ret;
}
@@ -165,42 +178,24 @@ testMarshalRequestDOUBLE(const void *dat
double num = 123456789.123;
int ret = 0;
int check = data ? *((int *)data) : 0;
- virBufferPtr buf = marshalRequest("f", num);
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ char *content;
+
+ marshalRequest(&buf, "f", num);
+ if (virBufferError(&buf))
+ return -1;
+
+ content = virBufferContentAndReset(&buf);
if (check)
- ret = checkRequestValue(buf->content,
+ ret = checkRequestValue(content,
"number(/methodCall/params/param[1]/value/double)",
XML_RPC_DOUBLE, (void *) &num);
- virBufferFree(buf);
+ free(content);
return ret;
}
-static int
-testBufferStrcat(const void *data ATTRIBUTE_UNUSED)
-{
- virBufferPtr buf = virBufferNew(1000*32); /* don't waste time with realloc */
- int i;
-
- for (i=0; i < 1000; i++)
- virBufferStrcat(buf, "My name is ", "libvirt", ".\n", NULL);
-
- virBufferFree(buf);
- return 0;
-}
-
-static int
-testBufferVSprintf(const void *data ATTRIBUTE_UNUSED)
-{
- virBufferPtr buf = virBufferNew(1000*32); /* don't waste time with realloc */
- int i;
-
- for (i=0; i < 1000; i++)
- virBufferVSprintf(buf, "My name is %s.\n", "libvirt");
-
- virBufferFree(buf);
- return 0;
-}
int
main(int argc, char **argv)
@@ -263,13 +258,7 @@ main(int argc, char **argv)
NLOOPS, testMarshalRequestSTRING, NULL) != 0)
ret = -1;
- if (virtTestRun("Buffer: strcat", NLOOPS, testBufferStrcat, NULL) != 0)
- ret = -1;
- if (virtTestRun("Buffer: sprintf", NLOOPS, testBufferVSprintf, NULL) != 0)
- ret = -1;
-
-
- exit(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
+ exit(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
--
|: Red Hat, Engineering, Boston -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 :|
2
6
28 Apr '08
Hi All,
I have just finished some scripts that allows 'native Xen' to use some
facilities of NetApp. Basically using a vfiler, and a q-tree Xen can be
provisioned. Allowing: netapp://customer/disk
Some scripts can be found here:
http://kinkrsoftware.nl/contrib/xen/
I wonder if people are already working on the libvirt storage side to
support 'remote' highlevel filesystems. For example ZFS or NetApp storage
machines could benefit from an easy interface.
Currently I'm building these 'block' scripts because they give
straightforward facities to my setup. But if anyone wants to team up to
get this all inside some more abstract libvirt setup I would happy to
join.
Stefan
2
2
Hey,
First thing - libvirt.spec has previously matched the spec file we've
used in Fedora for building packages, but now it's quite a bit out of
sync.
My question is whether libvirt.spec should be upstream at all:
1) Having the two copies is confusing - which is canonical?
2) Keeping the two copies in sync is time consuming, especially if
they're not going to be exactly identical.
3) It's not clear that it's useful to have it upstream at all - i.e.
is it useful anywhere but Fedora? Are iscsi-initiator-utils or
selinux-devel valid RPM names on any other distro?
4) If we're to keep libvirt.spec in CVS purely as a convenience for
Fedora users wanting to build the latest tarball, then we should
be ensuring that libvirt.spec is usable for the tarball *before*
releasing it, which is a pain.
Personally, I think we should remove it from upstream libvirt.
Finally, here's some changes to how arch conditionals are handed in the
spec file - what prompted this was the way we were enabling with_proxy
even when with_xen was disabled, causing the proxy to be in the files
section even when it wasn't built. Please give it a look over before I
built in dist-f10.
Cheers,
Mark.
6
10
This patch series adds support for serial & parallel devices to the QEMU
driver, and updates the Xen driver to support new syntax for HVM guests too.
The following syntax is used. Anywhere you see 'serial', you can equally
use 'console' or 'parallel'.
The 'serial' is for real serial devices only, likewise 'parallel' is for
parallel port devices only. 'console' tag is for paravirtualized
consoles. IF there is no paravirt console, then the first serial device
(if any) is also duplicated as a 'console' tag. This provides backwards
compatability with existing syntax.
- To attach device to STDIO - in essence this makes input /dev/null
and output goto the VM's logfile
<serial type='stdio'>
<target port="1"/>
</serial>
- To attach to a virtual console - accessed via Ctrl+Alt+'n' in the
SDL / VNC graphical console
<serial type='vc'>
<target port="1"/>
</serial>
- To send input & output to /dev/null
<serial type='null'>
<target port="1"/>
</serial>
- To auto-allocate a Pseudo TTY device
<serial type="pty">
<source path="/dev/pts/3"/>
<target port="1"/>
</serial>
NB special case if <console type='pty'>, then the TTY
path is also duplicated as an attribute tty='/dv/pts/3'
on the top level <console> tag. This provides compat
with existing syntax for <console> tags.
- To attach to a host device
<serial type="dev">
<source path="/dev/ttyS0"/>
<target port="1"/>
</serial>
- To operate as a TCP client
<serial type="tcp">
<source mode="connect" host="0.0.0.0" service="2445"/>
<target port="1"/>
</serial>
- To operate as a TCP client
<serial type="tcp">
<source mode="bind" host="0.0.0.0" service="2445"/>
<target port="1"/>
</serial>
- To operate as a UDP network console
<serial type="udp">
<source mode="bind" host="0.0.0.0" service="2445"/>
<source mode="connect" host="0.0.0.0" service="2445"/>
<target port="1"/>
</serial>
- To operate as a UNIX domain socket server
<serial type="unix">
<source mode="bind" path="/tmp/foo"/>
<target port="1"/>
</serial>
This is sufficient flexibility to represent all QEMU character device modes,
Xen paravirt console, LXC container fake console and the Solaris LDoms
console, and VMWare serial devices.
This series of patches updates the Xen and QEMU drivers, and their test
suites. A later patch will also update the LXC driver to this new syntax.
I was going to document this all in the format.html page, but looking at
the content there it needs a complete re-write. The split between Xen and
QEMU formats is pointless because they share 95% of the their config. Both
the Xen and QEMU descriptions are outdated, and the Xen PV vs HVM split is
also less than useful since they have much more commmonaility now. I intend
to re-write it to describe each element / attribute in turn, and then at
the end provide some example configs for each driver.
Dan.
--
|: Red Hat, Engineering, Boston -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 :|
3
17
"make distcheck" was failing. This fixes it:
avoid "make distcheck" failure
* docs/Makefile.am (EXTRA_DIST): Replace wildcards html/*.html
and html/*.png the corresponding lists of file names.
Signed-off-by: Jim Meyering <meyering(a)redhat.com>
---
docs/Makefile.am | 11 +++++++++--
1 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/docs/Makefile.am b/docs/Makefile.am
index feb72c1..c6f6032 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -63,8 +63,15 @@ fig = \
EXTRA_DIST= \
libvirt-api.xml libvirt-refs.xml apibuild.py \
site.xsl newapi.xsl news.xsl page.xsl ChangeLog.xsl \
- $(dot_html) $(dot_html_in) $(gif) html/*.html html/*.png \
- $(xml) $(rng) $(fig) $(png) \
+ $(dot_html) $(dot_html_in) $(gif) \
+ html/index.html \
+ html/libvirt-libvirt.html \
+ html/libvirt-virterror.html \
+ html/home.png \
+ html/left.png \
+ html/right.png \
+ html/up.png \
+ $(xml) $(rng) $(fig) $(png) \
virsh.pod ChangeLog.awk
all: web $(top_builddir)/NEWS $(man_MANS)
--
1.5.5.1.69.g2ffd
2
5
The test cases which have a shell wrapper script generate a pile of memory
leak warnings from valgrind due to various issues in bash itself. This
disguises the real errors valgrind finds in libvirt. So this patch adds
a surpressions file to hide the bash problems
Regards,
Daniel.
Index: .valgrind.supp
===================================================================
RCS file: .valgrind.supp
diff -N .valgrind.supp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ .valgrind.supp 27 Apr 2008 19:41:14 -0000
@@ -0,0 +1,44 @@
+{
+ bashMemoryLeak1
+ Memcheck:Leak
+ fun:malloc
+ fun:xmalloc
+ fun:set_signal
+ fun:trap_builtin
+ obj:/bin/bash
+ obj:/bin/bash
+ fun:execute_command_internal
+ fun:parse_and_execute
+ obj:/bin/bash
+ fun:source_file
+ fun:source_builtin
+ obj:/bin/bash
+}
+{
+ bashMemoryLeak2
+ Memcheck:Leak
+ fun:malloc
+ fun:xmalloc
+ fun:make_command
+ fun:yyparse
+ fun:parse_command
+ fun:read_command
+ fun:reader_loop
+ fun:main
+}
+{
+ bashMemoryLeak3
+ Memcheck:Leak
+ fun:malloc
+ fun:xmalloc
+ obj:/bin/bash
+ fun:execute_command_internal
+ obj:/bin/bash
+ fun:execute_command_internal
+ fun:execute_command_internal
+ obj:/bin/bash
+ obj:/bin/bash
+ fun:execute_command_internal
+ fun:parse_and_execute
+ fun:command_substitute
+}
Index: Makefile.am
===================================================================
RCS file: /data/cvs/libvirt/tests/Makefile.am,v
retrieving revision 1.41
diff -u -p -r1.41 Makefile.am
--- Makefile.am 18 Apr 2008 15:28:33 -0000 1.41
+++ Makefile.am 27 Apr 2008 19:41:14 -0000
@@ -73,7 +73,7 @@ TESTS_ENVIRONMENT = \
$(VG)
valgrind:
- $(MAKE) check VG="valgrind --quiet --leak-check=full"
+ $(MAKE) check VG="valgrind --quiet --leak-check=full --suppressions=$(srcdir)/.valgrind.supp"
# Note: xmlrpc.[c|h] is not in libvirt yet
xmlrpctest_SOURCES = \
--
|: Red Hat, Engineering, Boston -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 :|
2
1
This avoids two warnings:
avoid format-related warnings
* qemud/qemud.c (main): Fix a bogus format string reported as umarked.
* src/virsh.c (cmdVcpupin): Non-literal with no args.
Signed-off-by: Jim Meyering <meyering(a)redhat.com>
---
qemud/qemud.c | 4 ++--
src/virsh.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/qemud/qemud.c b/qemud/qemud.c
index a7b27ee..a9d825d 100644
--- a/qemud/qemud.c
+++ b/qemud/qemud.c
@@ -2164,8 +2164,8 @@ int main(int argc, char **argv) {
const char *sockdirname = LOCAL_STATE_DIR "/run/libvirt";
if (chown(sockdirname, -1, unix_sock_gid) < 0)
- qemudLog(QEMUD_ERR, "%s %s",
- _("Failed to change group ownership of "), sockdirname);
+ qemudLog(QEMUD_ERR, _("Failed to change group ownership of %s"),
+ sockdirname);
}
if (godaemon) {
diff --git a/src/virsh.c b/src/virsh.c
index ef6165b..5e098a7 100644
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -1745,7 +1745,7 @@ cmdVcpupin(vshControl * ctl, vshCmd * cmd)
}
if (vcpu >= info.nrVirtCpu) {
- vshError(ctl, FALSE, _("vcpupin: Invalid vCPU number."));
+ vshError(ctl, FALSE, "%s", _("vcpupin: Invalid vCPU number."));
virDomainFree(dom);
return FALSE;
}
--
1.5.5.1.69.g2ffd
2
1