[PATCH][RFC] libvirt ldoms support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




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@xxxxxxx 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@xxxxxxx>

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:
+ */
+
--
Libvir-list mailing list
Libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list

[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]