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

[Libvir] [PATCH][RFC] libvirt ldoms support




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 Sun COM on any response.

Thanks,
Ryan


LDoms Support

This patch adds the Logical Domains (LDoms) support for the SPARC platforms. LDoms software is Sun Microsystem's virtualization technology to subdivide a supported system's resources (CPUs, memory, I/O, and storage) creating partitions called logical domains. The Logical Domains Manager is used to create and manage logical domains and maps logical domains to physical resources. The LDoms Manager provides a command-line interface and also exports an XML-based control interface. The Libvirt for LDoms uses this XML interface to communicate with the LDoms Manager to retrieve the LDoms data for:
  - Listing domains
  - Requesting CPU and memory resource updates
  - Performing life-cycle actions for logical domains

This libvirt patch supports LDoms 1.0.1 and 1.0.2.

This patch will modify the following existing files:
  src/libvirt.c
  src/virsh.c
  src/virterror.c
  src/driver.h
  src/Makefile.am
  include/libvirt/libvirt.h.in
  include/libvirt/virterror.h
  configure.in

and add the following new files:
  src/ldoms_common.h
  src/ldoms_internal.h
  src/ldoms_internal.c
  src/ldoms_intfc.h
  src/ldoms_intfc.c
  src/ldoms_xml_parse.h
  src/ldoms_xml_parse.c

Signed-off-by: Eunice Moon <eunice moon sun com>

diff --git a/src/libvirt.c b/src/libvirt.c
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -48,6 +48,9 @@
 #ifdef WITH_LXC
 #include "lxc_driver.h"
 #endif
+#ifdef WITH_LDOMS
+extern int ldomsRegister(void);
+#endif
 
 /*
  * TODO:
@@ -267,6 +270,11 @@ virInitialize(void)
      * Note that the order is important: the first ones have a higher
      * priority when calling virConnectOpen.
      */
+#ifdef WITH_LDOMS
+    if (ldomsRegister() == -1) return -1;
+    /* Don't want to run any other HV with LDoms */
+        return (0);
+#endif
 #ifdef WITH_TEST
     if (testRegister() == -1) return -1;
 #endif
@@ -1794,11 +1802,17 @@ virDomainGetUUID(virDomainPtr domain, un
         return (-1);
     }
 
+#ifndef WITH_LDOMS
     if (domain->id == 0) {
         memset(uuid, 0, VIR_UUID_BUFLEN);
     } else {
         memcpy(uuid, &domain->uuid[0], VIR_UUID_BUFLEN);
     }
+#endif
+
+#ifdef WITH_LDOMS
+    memcpy(uuid, &domain->uuid[0], VIR_UUID_BUFLEN);
+#endif
     return (0);
 }
 
@@ -5025,6 +5039,42 @@ virStorageVolGetPath(virStorageVolPtr vo
     return NULL;
 }
 
+#ifdef WITH_LDOMS
+/** 
+ * virLDomConsole:
+ * @domain: the domain if available
+ *  
+ * Opens a terminal window to the console for a domain
+ *
+ * Returns -1 in case of error, LDom console port number in case of success
+ */
+int
+virLDomConsole(virDomainPtr domain)
+{
+    virConnectPtr conn; 
+    DEBUG("Starting domain %p", domain);
+
+    if (domain == NULL) {
+        TODO
+        return (-1);
+    }
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    conn = domain->conn;
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        return (-1);
+    }
+
+    if (conn->driver->ldomConsole)
+        return conn->driver->ldomConsole (domain);
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+#endif
 
 /*
  * vim: set tabstop=4:
diff --git a/src/virsh.c b/src/virsh.c
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -494,6 +494,11 @@ cmdConsole(vshControl * ctl, vshCmd * cm
     virDomainPtr dom;
     int ret = FALSE;
     char *doc;
+#ifdef WITH_LDOMS
+    int port;
+    char command[80];
+#endif
+
 
     if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
         return FALSE;
@@ -501,6 +506,19 @@ cmdConsole(vshControl * ctl, vshCmd * cm
     if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
         return FALSE;
 
+#ifdef WITH_LDOMS
+    port = virLDomConsole(dom);
+    if (port > 0) {
+        sprintf(command, "%s %d &",
+            "/usr/X/bin/xterm -sb -sl 1000 -e telnet localhost ", port);
+        system(command);
+        return TRUE;
+    }
+
+    vshError(ctl, FALSE, _("Failed to start console"));
+    return FALSE;
+#endif
+
     doc = virDomainGetXMLDesc(dom, 0);
     if (!doc)
         goto cleanup;
@@ -1003,13 +1021,21 @@ cmdUndefine(vshControl * ctl, vshCmd * c
  */
 static vshCmdInfo info_start[] = {
     {"syntax", "start <domain>"},
+#ifdef WITH_LDOMS
+        {"help", gettext_noop("start an inactive or bound domain")},
+#else
     {"help", gettext_noop("start a (previously defined) inactive domain")},
+#endif
     {"desc", gettext_noop("Start a domain.")},
     {NULL, NULL}
 };
 
 static vshCmdOptDef opts_start[] = {
+#ifdef WITH_LDOMS
+        {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("name of the inactive or bound domain")},
+#else
     {"name", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("name of the inactive domain")},
+#endif
     {NULL, 0, 0, NULL}
 };
 
@@ -1019,17 +1045,26 @@ cmdStart(vshControl * ctl, vshCmd * cmd)
     virDomainPtr dom;
     int ret = TRUE;
 
+#ifdef WITH_LDOMS
+    /* Need to send in the 'domain' option name instead of 'name' */
+    if (!(dom = vshCommandOptDomainBy(ctl, cmd, "domain", NULL, VSH_BYNAME)))
+        return FALSE;
+#else
     if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
         return FALSE;
+#endif
 
     if (!(dom = vshCommandOptDomainBy(ctl, cmd, "name", NULL, VSH_BYNAME)))
         return FALSE;
 
+    /* Allow LDoms domain state to be inactive or bound */
+#ifndef WITH_LDOMS
     if (virDomainGetID(dom) != (unsigned int)-1) {
         vshError(ctl, FALSE, "%s", _("Domain is already active"));
 	virDomainFree(dom);
         return FALSE;
     }
+#endif
 
     if (virDomainCreate(dom) == 0) {
         vshPrint(ctl, _("Domain %s started\n"),
@@ -1660,11 +1695,13 @@ cmdVcpuinfo(vshControl * ctl, vshCmd * c
 
                 vshPrint(ctl, "%-15s %.1lfs\n", _("CPU time:"), cpuUsed);
             }
+#ifndef WITH_LDOMS
             vshPrint(ctl, "%-15s ", _("CPU Affinity:"));
             for (m = 0 ; m < VIR_NODEINFO_MAXCPUS(nodeinfo) ; m++) {
                 vshPrint(ctl, "%c", VIR_CPU_USABLE(cpumap, cpumaplen, n, m) ? 'y' : '-');
             }
             vshPrint(ctl, "\n");
+#endif
             if (n < (ncpus - 1)) {
                 vshPrint(ctl, "\n");
             }
@@ -5087,19 +5124,23 @@ cmdQuit(vshControl * ctl, vshCmd * cmd A
  */
 static vshCmdDef commands[] = {
     {"help", cmdHelp, opts_help, info_help},
+#ifndef WITH_LDOMS
     {"attach-device", cmdAttachDevice, opts_attach_device, info_attach_device},
     {"attach-disk", cmdAttachDisk, opts_attach_disk, info_attach_disk},
     {"attach-interface", cmdAttachInterface, opts_attach_interface, info_attach_interface},
     {"autostart", cmdAutostart, opts_autostart, info_autostart},
     {"capabilities", cmdCapabilities, NULL, info_capabilities},
     {"connect", cmdConnect, opts_connect, info_connect},
+#endif /* WITH_LDOMS */
     {"console", cmdConsole, opts_console, info_console},
     {"create", cmdCreate, opts_create, info_create},
     {"start", cmdStart, opts_start, info_start},
     {"destroy", cmdDestroy, opts_destroy, info_destroy},
+#ifndef WITH_LDOMS
     {"detach-device", cmdDetachDevice, opts_detach_device, info_detach_device},
     {"detach-disk", cmdDetachDisk, opts_detach_disk, info_detach_disk},
     {"detach-interface", cmdDetachInterface, opts_detach_interface, info_detach_interface},
+#endif /* WITH_LDOMS */
     {"define", cmdDefine, opts_define, info_define},
     {"domid", cmdDomid, opts_domid, info_domid},
     {"domuuid", cmdDomuuid, opts_domuuid, info_domuuid},
@@ -5112,7 +5153,9 @@ static vshCmdDef commands[] = {
     {"freecell", cmdFreecell, opts_freecell, info_freecell},
     {"hostname", cmdHostname, NULL, info_hostname},
     {"list", cmdList, opts_list, info_list},
+#ifndef WITH_LDOMS
     {"migrate", cmdMigrate, opts_migrate, info_migrate},
+#endif /* WITH_LDOMS */
 
     {"net-autostart", cmdNetworkAutostart, opts_network_autostart, info_network_autostart},
     {"net-create", cmdNetworkCreate, opts_network_create, info_network_create},
@@ -5144,20 +5187,28 @@ static vshCmdDef commands[] = {
     {"pool-uuid", cmdPoolUuid, opts_pool_uuid, info_pool_uuid},
 
     {"quit", cmdQuit, NULL, info_quit},
+#ifndef WITH_LDOMS
     {"reboot", cmdReboot, opts_reboot, info_reboot},
     {"restore", cmdRestore, opts_restore, info_restore},
     {"resume", cmdResume, opts_resume, info_resume},
     {"save", cmdSave, opts_save, info_save},
     {"schedinfo", cmdSchedinfo, opts_schedinfo, info_schedinfo},
     {"dump", cmdDump, opts_dump, info_dump},
+#endif /* WITH_LDOMS */
     {"shutdown", cmdShutdown, opts_shutdown, info_shutdown},
     {"setmem", cmdSetmem, opts_setmem, info_setmem},
+#ifndef WITH_LDOMS
     {"setmaxmem", cmdSetmaxmem, opts_setmaxmem, info_setmaxmem},
+#endif /* WITH_LDOMS */
     {"setvcpus", cmdSetvcpus, opts_setvcpus, info_setvcpus},
+#ifndef WITH_LDOMS
     {"suspend", cmdSuspend, opts_suspend, info_suspend},
     {"ttyconsole", cmdTTYConsole, opts_ttyconsole, info_ttyconsole},
+#endif /* WITH_LDOMS */
     {"undefine", cmdUndefine, opts_undefine, info_undefine},
+#ifndef WITH_LDOMS
     {"uri", cmdURI, NULL, info_uri},
+#endif /* WITH_LDOMS */
 
     {"vol-create", cmdVolCreate, opts_vol_create, info_vol_create},
     {"vol-create-as", cmdVolCreateAs, opts_vol_create_as, info_vol_create_as},
@@ -5170,9 +5221,13 @@ static vshCmdDef commands[] = {
     {"vol-key", cmdVolKey, opts_vol_key, info_vol_key},
 
     {"vcpuinfo", cmdVcpuinfo, opts_vcpuinfo, info_vcpuinfo},
+#ifndef WITH_LDOMS
     {"vcpupin", cmdVcpupin, opts_vcpupin, info_vcpupin},
+#endif /* WITH_LDOMS */
     {"version", cmdVersion, NULL, info_version},
+#ifndef WITH_LDOMS
     {"vncdisplay", cmdVNCDisplay, opts_vncdisplay, info_vncdisplay},
+#endif /* WITH_LDOMS */
     {NULL, NULL, NULL, NULL}
 };
 
@@ -5905,6 +5960,10 @@ vshDomainVcpuStateToString(int state)
         return gettext_noop("blocked");
     case VIR_VCPU_RUNNING:
         return gettext_noop("running");
+#ifdef WITH_LDOMS
+        case VIR_VCPU_UNKNOWN:
+                return gettext_noop("unknown");
+#endif
     default:
         ;/*FALLTHROUGH*/
     }
diff --git a/src/virterror.c b/src/virterror.c
--- a/src/virterror.c
+++ b/src/virterror.c
@@ -304,7 +304,11 @@ virDefaultErrorFunc(virErrorPtr err)
         case VIR_FROM_STORAGE:
             dom = "Storage ";
             break;
-
+#ifdef WITH_LDOMS
+        case VIR_FROM_LDOMS:
+            dom = "LDoms ";
+            break;
+#endif
     }
     if ((err->dom != NULL) && (err->code != VIR_ERR_INVALID_DOMAIN)) {
         domain = err->dom->name;
@@ -713,6 +717,14 @@ __virErrorMsg(virErrorNumber error, cons
 		else
 			errmsg = _("Failed to find a storage driver: %s");
 		break;
+#ifdef WITH_LDOMS
+    case VIR_ERR_INVALID_OPTION:
+            if (info == NULL)
+                errmsg = _("invalid option");
+            else
+                errmsg = _("invalid option: %s");
+            break;
+#endif
     }
     return (errmsg);
 }
diff --git a/src/driver.h b/src/driver.h
--- a/src/driver.h
+++ b/src/driver.h
@@ -24,7 +24,10 @@ typedef enum {
     VIR_DRV_QEMU = 3,
     VIR_DRV_REMOTE = 4,
     VIR_DRV_OPENVZ = 5,
-    VIR_DRV_LXC = 6
+    VIR_DRV_LXC = 6,
+#ifdef WITH_LDOMS
+    VIR_DRV_LDOMS = 7
+#endif
 } virDrvNo;
 
 
@@ -253,6 +256,11 @@ typedef virDomainPtr
                      const char *uri,
                      unsigned long flags);
 
+#ifdef WITH_LDOMS
+typedef int
+        (*virDrvLDomConsole)            (virDomainPtr domain);
+#endif
+
 typedef struct _virDriver virDriver;
 typedef virDriver *virDriverPtr;
 
@@ -337,6 +345,9 @@ struct _virDriver {
     virDrvDomainInterfaceStats  domainInterfaceStats;
     virDrvNodeGetCellsFreeMemory	nodeGetCellsFreeMemory;
     virDrvNodeGetFreeMemory		getFreeMemory;
+#ifdef WITH_LDOMS
+    virDrvLDomConsole			ldomConsole;
+#endif
 };
 
 typedef int
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -549,6 +549,9 @@ typedef enum {
     VIR_VCPU_OFFLINE	= 0,	/* the virtual CPU is offline */
     VIR_VCPU_RUNNING	= 1,	/* the virtual CPU is running */
     VIR_VCPU_BLOCKED	= 2,	/* the virtual CPU is blocked on resource */
+#ifdef WITH_LDOMS
+    VIR_VCPU_UNKNOWN    = 3,    /* the virtual CPU state is unknown */
+#endif
 } virVcpuState;
 
 typedef struct _virVcpuInfo virVcpuInfo;
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -56,6 +56,9 @@ typedef enum {
     VIR_FROM_STATS_LINUX, /* Error in the Linux Stats code */
     VIR_FROM_LXC,   /* Error from Linux Container driver */
     VIR_FROM_STORAGE,   /* Error from storage driver */
+#ifdef WITH_LDOMS
+    VIR_FROM_LDOMS,     /* Error from LDoms driver */
+#endif
 } virErrorDomain;
 
 
@@ -139,6 +142,9 @@ typedef enum {
     VIR_WAR_NO_STORAGE, /* failed to start storage */
     VIR_ERR_NO_STORAGE_POOL, /* storage pool not found */
     VIR_ERR_NO_STORAGE_VOL, /* storage pool not found */
+#ifdef WITH_LDOMS
+    VIR_ERR_INVALID_OPTION, /* invalid command line option */
+#endif
 } virErrorNumber;
 
 /**
diff --git a/src/Makefile.am b/src/Makefile.am
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -89,7 +89,17 @@ else
 EXTRA_DIST += storage_backend_disk.h storage_backend_disk.c
 endif
 
-
+if WITH_LDOMS
+CLIENT_SOURCES += ldoms_common.h			\
+		ldoms_internal.h ldoms_internal.c	\
+		ldoms_intfc.h ldoms_intfc.h		\
+		ldoms_xml_parse.h ldoms_xml_parse.c	\
+else
+EXTRA_DIST += ldoms_common.h				\
+		ldoms_internal.h ldoms_internal.c	\
+		ldoms_intfc.h ldoms_intfc.h		\
+		ldoms_xml_parse.h ldoms_xml_parse.c	\
+endif
 
 
 libvirt_la_SOURCES = $(CLIENT_SOURCES) $(SERVER_SOURCES)
diff --git a/configure.in b/configure.in
--- a/configure.in
+++ b/configure.in
@@ -246,6 +246,10 @@ if test "$with_remote" = "yes" ; then
     LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_REMOTE"
 fi
 
+if test "$with_ldoms" = "yes" ; then
+    LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_LDOMS"
+fi
+
 if test "$with_xen" = "yes" ; then
     dnl search for the Xen store library
     AC_SEARCH_LIBS(xs_read, [xenstore],
diff --git a/src/ldoms_common.h b/src/ldoms_common.h
new file mode 100644
--- /dev/null
+++ b/src/ldoms_common.h
@@ -0,0 +1,80 @@
+/*
+ * ldoms_common.h: LDoms common definitions
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ * 
+ */
+
+#ifndef __VIR_LDOMS_COMMON_H__
+#define __VIR_LDOMS_COMMON_H__
+
+#ifdef WITH_LDOMS
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#define LDOMS_VERSION_NUMBER         1000001  /* 1.0.1 */
+#define NAME_SIZE 256
+
+/* LDOM memory unit */
+#define LDOMMEMUNIT_BYTES            1 
+#define LDOMMEMUNIT_KILOBYTES        2 
+#define LDOMMEMUNIT_MEGABYTES        3 
+#define LDOMMEMUNIT_GIGABYTES        4 
+
+/* LDOM lifecycle actions */
+#define LDOM_START 1
+#define LDOM_STOP  2
+#define LDOM_BIND  3
+#define LDOM_UNBIND 4
+#define LDOM_DELETE 5
+
+/* LDOM States */
+/* binding is to bind (attach) configured resource to a logical domain
+ * unbinding is to release resources bound to configured logical domains
+ */
+#define  LDOM_STATE_ACTIVE 1
+#define  LDOM_STATE_STOPPING 2
+#define  LDOM_STATE_INACTIVE 3
+#define  LDOM_STATE_BINDING 4
+#define  LDOM_STATE_UNBINDING 5
+#define  LDOM_STATE_BOUND 6
+#define  LDOM_STATE_STARTING 7
+
+/* resource pool supported */
+#define CPU_RP          1
+#define MEM_RP          2
+#define CRYPTO_RP       3
+#define IOBUS_RP        4
+
+/* capacity or reserved resource */
+#define RP_CAPACITY     1
+#define RP_RESERVED     2
+
+/* Global vars */
+extern unsigned long ldomsFreeMem;
+extern unsigned long ldomsUsedMem;
+extern int           ldomsFreeCpu;
+extern int           ldomsUsedCpu;
+
+/* Structures */
+
+struct cpuBindings_s {
+	unsigned int virt;
+	int real;
+	struct cpuBindings_s *next;
+};
+typedef struct cpuBindings_s cpuBindings_t;
+
+/* Debug print */
+extern void dprt(const char *template, ...);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif  /* WITH_LDOMS */
+#endif  /* __VIR_LDOMS_COMMON_H__ */
diff --git a/src/ldoms_internal.h b/src/ldoms_internal.h
new file mode 100644
--- /dev/null
+++ b/src/ldoms_internal.h
@@ -0,0 +1,29 @@
+/*
+ * ldoms_internal.h: internal definitions just used by LDoms driver
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ */
+
+#ifndef __VIR_LDOMS_INTERNAL_H__
+#define __VIR_LDOMS_INTERNAL_H__
+
+#ifdef WITH_LDOMS
+
+#include <libvirt/virterror.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int ldomsRegister(void);
+void ldomsError(virConnectPtr, virDomainPtr, virErrorNumber, const char*, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WITH_LDOMS */
+#endif /* __VIR_LDOMS_INTERNAL_H__ */
diff --git a/src/ldoms_internal.c b/src/ldoms_internal.c
new file mode 100644
--- /dev/null
+++ b/src/ldoms_internal.c
@@ -0,0 +1,2254 @@
+/*
+ * ldoms_internal.c: access to LDoms hypervisor via LDoms Manager (LDM) 
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ */
+
+#ifdef WITH_LDOMS
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <sys/processor.h>
+#include <pwd.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/uri.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <values.h>
+#include <limits.h>
+#include <pthread.h>
+
+#include "buf.h"
+#include "internal.h"
+#include "xml.h"
+#include "ldoms_common.h"
+#include "ldoms_internal.h"
+#include "ldoms_intfc.h"
+#include "ldoms_xml_parse.h"
+
+/* Local function prototypes */
+static void refresh_ldom_data();
+static int ldomsNodeGetInfo(virConnectPtr , virNodeInfoPtr );
+static long long getCpuUpTime();
+static long getHypervisorVersion();
+static unsigned long getLDMVersion();
+
+/* Domain state info
+ * LDom State enumerations
+ *       1 = active        LDOM_STATE_ACTIVE
+ *       2 = stopping        LDOM_STATE_STOPPING
+ *       3 = inactive        LDOM_STATE_INACTIVE
+ *       4 = binding        LDOM_STATE_BINDING
+ *       5 = unbinding    LDOM_STATE_UNBINDING
+ *       6 = bound        LDOM_STATE_BOUND
+ *       7 = starting        LDOM_STATE_STARTING
+ *
+ * libvirt LDom State enums
+ * typedef enum {
+ *   VIR_DOMAIN_NOSTATE = 0,  no state 
+ *   VIR_DOMAIN_RUNNING = 1,  the domain is running 
+ *   VIR_DOMAIN_BLOCKED = 2,  the domain is blocked on resource
+ *   VIR_DOMAIN_PAUSED  = 3,  the domain is paused by user
+ *   VIR_DOMAIN_SHUTDOWN= 4,  the domain is being shut down 
+ *   VIR_DOMAIN_SHUTOFF = 5,  the domain is shut off 
+ *   VIR_DOMAIN_CRASHED = 6   the domain is crashed 
+ * } virDomainState;
+ */
+
+ldominfo_t **ldominfo_list = NULL;
+int ldom_cnt = 0;
+const unsigned char Uuid[] =  "" ;
+static long last_ldom_refresh = 0;
+static pthread_rwlock_t  update_lock;
+static unsigned long LDMVersion = 1000001; 
+
+/* Mem and CPU Free/Used */
+unsigned long ldomsFreeMem;
+unsigned long ldomsUsedMem;
+int       ldomsFreeCpu;
+int       ldomsUsedCpu;
+
+/* Global vars for debug statement */
+int ldoms_debug = 0;
+int ldoms_detailed_debug = 0;
+
+/* Prototype Structures */
+struct domains {
+    short valid;        /* Flag to indicate this Domain is valid */
+    short active;       /* Flag to indicate this Domain is valid */
+    char name[30];      /* Domain Name; primary, ldg1, etc */
+    int  id;            /* ID for the Domain; Used alot by other code to find a Domain */
+    virDomainInfo info;    /* Domain name, state */
+    unsigned char uuid[VIR_UUID_BUFLEN];    /* 32 char unique ID */
+};
+
+/* This is global.  Need to fill on first call from virsh or VMM */
+virNodeInfo nodeInfo;
+short nodeInfoFilled = 0;
+
+int maxDomID = 0;
+
+/*
+ * General error logging function.  This is the exact same
+ * as used by Qemu and Test.  
+ */
+void
+ldomsError(virConnectPtr con,
+           virDomainPtr dom,
+           virErrorNumber error,
+           const char *info,
+           int level)
+{
+    const char *errmsg;
+
+    if (error == VIR_ERR_OK) {
+        errmsg = info;
+        /* return; */
+    } else
+        errmsg = __virErrorMsg(error, info);
+
+    __virRaiseError(con, dom, NULL, VIR_FROM_LDOMS, error, level,
+                    errmsg, info, NULL, 0, 0, errmsg, info, 0);
+}
+
+/*
+ * getDomainIndex
+ *
+ * What: Get the index for the input Domain for a given connection.
+ *       Note: libivrt does not associated an Index with an inactive
+ *       Domain.  For LDoms, we assign an Index to all Domains.
+ *
+ * Input: domain - A ptr to a virDomain
+ * Output: The Domain ID.  -1 if for no ID.
+ */
+static int 
+getDomainIndex(virDomainPtr domain) 
+{
+    int i, domID;
+
+    /* get the current ldom data from LDM (LDoms Manager) */
+    (void) pthread_rwlock_wrlock(&update_lock);
+    refresh_ldom_data();
+    (void) pthread_rwlock_unlock(&update_lock);
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: getDomainIndex(ENTER) domName=%s, domID=%d, ldom_cnt=%d\n",domain->name,domain->id,ldom_cnt);
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        ldomsError((domain ? domain->conn : NULL), domain, VIR_ERR_INVALID_ARG,
+                  __FUNCTION__, VIR_ERR_ERROR);
+        if (ldoms_debug) dprt("LDOMS_DEBUG: getDomainIndex(EXIT ERROR) domain input not valid\n");
+        return (-1);
+    }
+
+    domID = domain->id;
+    for (i = 0 ; i < ldom_cnt ; i++) {
+        if (domID >= 0) {
+            if (domID == i) {
+                if (ldoms_debug) dprt("LDOMS_DEBUG: getDomainIndex(EXIT) From ID: domidx=%d\n",i);
+                return (i);
+            }
+        } else {
+            if (!strcmp(domain->name, ldominfo_list[i]->ldomName)) {
+                if (ldoms_debug) dprt("LDOMS_DEBUG: getDomainIndex(EXIT) From Name:domidx=%d\n",i);
+                return (i);
+            }
+        }
+    }
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: getDomainIndex(EXIT ERROR) domID=-1\n");
+    return (-1);
+} /* getDomainIndex() */
+
+/*
+ * ldomsOpen
+ *
+ * Open a connection to the LDoms Manager and handshake to
+ * verify the a connection can be made for future XML requests.
+ *
+ * Input: All inputs are ignored at this time.
+ * Output: 0 -> Success, <0 -> Failure
+ */
+static virDrvOpenStatus
+ldomsOpen(virConnectPtr conn, xmlURIPtr uri, virConnectAuthPtr auth ATTRIBUTE_UNUSED, int flags) 
+{
+    struct timeval tv;
+    int u, ret, connid;
+    int socketFD;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsOpen(ENTER) \n");
+
+        if (!uri)
+               return VIR_DRV_OPEN_DECLINED;
+
+        if (!uri->scheme || strcmp(uri->scheme, "ldoms") != 0)
+               return VIR_DRV_OPEN_DECLINED;
+
+    if (!uri->scheme || strcmp(uri->scheme, "ldoms")) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsOpen(FAIL): uri scheme NOT correct\n");
+        ldomsError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("URI is not valid for LDoms"), VIR_ERR_ERROR);
+        return (-1);
+    }
+
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsOpen(): scheme=%s, path=%s\n",
+        (uri->scheme==0) ? "NULL" : uri->scheme,
+        (uri->path==0) ? "NULL" : uri->path);
+
+    /* Verify the LDM (LDoms Manager) can be talked to.  Open an socket
+       connection, Handshake, then close the socket. */
+    if ((socketFD = open_ldm_connection()) < 0) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsOpen(): Cannot talk with LDoms Manager\n");
+        ldomsError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("Cannot open socket to LDMD"), VIR_ERR_ERROR);
+        return(-1);
+    }
+    close_ldm_connection(socketFD);
+
+
+    return(0);
+} /* ldomsOpen() */
+
+static int
+ldomsClose(virConnectPtr conn) 
+{
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsClose(ENTER/EXIT)\n");
+    /* Nothing to do */
+    return(0);
+}
+
+/*
+ * ldomsGetMaxVcpus
+ *
+ * What: Just get the total number of free CPUs in the system.
+ *       Call get_ldom_total_cpu(), so it will set, as a side effect,
+ *       the number of free CPUs and free Memory in the system.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ *        memory - Size in KiloBytes
+ * Output: function return - Number of Max CPUs supported, or -1 for error
+ */
+int
+ldomsGetMaxVcpus(virConnectPtr conn, const char *type)
+{
+    virNodeInfo nodeInfo;
+    int rc;
+    int totalVcpus;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsGetMaxVcpus(ENTER) \n");
+
+    if (get_ldom_total_cpu(&totalVcpus) < 0) { 
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsGetMaxVcpus() get_ldom_total_cpu() failed\n");
+        return (0);
+    }
+
+    /* Success */
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsGetMaxVcpus() Free Vcpus = %d\n",ldomsFreeCpu);
+    return (ldomsFreeCpu);
+} /* ldomsGetMaxVcpus() */
+
+/*
+ * ldomsNodeGetInfo
+ *
+ * What: Get the info for a Node, which is the physical
+ *       hardware system.  
+ *
+ * Input: conn - Pointer to a virConnect struct (Not used)
+ *        info - Poiner to a virNodeInfo struct to update
+ * Output: Indirect virNodeInfo struct updated with Node info
+ */
+static int
+ldomsNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
+{
+    int total_cpu;
+    unsigned long total_memory;
+
+    /* to get the CPU frequency and fill the nodeInfo.mhz field
+     *
+     * NOTE:
+     * Since processor_info provides info for the domain on which it
+     * is being called (control domain), the virtual processor id 0 is used
+     * to retrieve the processor speed assuming that the cpu speed
+     * is the same for all Cpus on the system. That is a safe
+     * assumption for single-chip platforms like Ontario and Huron,
+     * but it might not work for multi-chip platforms based on VF or ROCK
+     * chips.
+     */
+    processor_info_t cpu_info;
+    int pid = 0;         /* physical processor ID */
+    int p_clock = 1600; /* default processor clock speed in MHz */
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNodeGetInfo(ENTER)\n");
+
+        /*
+     * NOTE: We get the Node info values (number of CPUs and memory)
+     * from the LDM (LDoms Manager) by adding up the total number of CPUs and Memory for all domains.
+     */
+     
+    /* if the nodeInfo variable hasn't been filled yet, try to get the
+     * total number of CPUs and memory from the LDM (LDoms Manager).
+     */ 
+
+    
+    if (nodeInfoFilled == 0) {
+
+        strcpy(nodeInfo.model, "SPARC");
+
+        /* 
+         * Fill the total amount of memory by sending the LDM list-devices
+         * and list-bindings XML requests and adding up free and bound
+         * memory amounts for all domains. If it fails to retrieve the total
+         * amount of memory from LDM, 64GB (expressed in KB) will be
+         * used as default value. 
+         */ 
+
+        if (get_ldom_total_memory(&total_memory) < 0) { 
+            if (ldoms_debug) 
+                dprt("LDOMS_DEBUG: ldomsNodeGetInfo() get_ldom_total_memory() failed\n");
+            nodeInfo.memory = 0;
+        } else {
+            if (ldoms_detailed_debug) 
+                dprt("LDOMS_DETAILED_DEBUG: ldomsNodeGetInfo() Total Node Memory=%lu\n", total_memory);
+            nodeInfo.memory  = total_memory;
+        }
+
+        /* 
+         * Fill the total number of CPUs by sending the LDM list-devices
+         * and list-bindings XML requests and adding up free and bound
+         * CPUs for all domains. If it fails to retrieve the total
+         * number of CPUs from LDM, 0 will be used as default value. 
+         */ 
+
+        if (get_ldom_total_cpu(&total_cpu) < 0) { 
+            if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNodeGetInfo() get_ldom_total_cpu() failed\n");
+            nodeInfo.cpus = 0;
+        } else {
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsNodeGetInfo() Total Node CPUs=%d\n", total_cpu);
+            nodeInfo.cpus = total_cpu;          
+        }
+
+        /* get the processor clock speed in MHz */
+        while ((pid < 64) && (processor_info(pid++, &cpu_info) != 0) );
+
+        /* Found a pid on the primary domain */
+        if (pid <= 64) {
+            if (ldoms_detailed_debug) 
+                dprt("LDOMS_DETAILED_DEBUG: ldomsNodeGetInfo(). processor_info with pid=%d clock=%d\n",
+                       pid, cpu_info.pi_clock);
+            p_clock = cpu_info.pi_clock;
+        }
+
+        nodeInfo.mhz = p_clock; 
+        nodeInfo.nodes   = 1;        /* Only 1 node in LDoms */
+        nodeInfo.sockets = 1;
+        nodeInfo.cores   = 8;    /* 8 cores on N1 and N2. 4 threads on N1 core, 8 on N2 */
+
+        /* If there are more than 32 CPUs, then 8 Threads/Core, else 4 Threads/Core */
+        if (nodeInfo.cpus > 32)
+            nodeInfo.threads = 8;  /* This is Threads per Core, not total Threads */
+        else
+            nodeInfo.threads = 4;  /* This is Threads per Core, not total Threads */
+    
+        /* nodeInfo has been filled */
+        nodeInfoFilled = 1;
+    }
+
+    memcpy(info, &nodeInfo, sizeof(virNodeInfo));
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNodeGetInfo(EXIT)\n");
+    return (0);
+} /* ldomsNodeGetInfo() */
+
+/* Don't really know what to return for this */
+static const char *
+ldomsGetType(virConnectPtr conn) 
+{
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsGetType(ENTER)\n");
+    return(strdup("LDoms"));
+}
+
+/* This returns the HV version.  Make it the same as the LDoms version */
+static int
+ldomsGetVersion(virConnectPtr conn, unsigned long *hvVer) 
+{
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsGetVersion(ENTER/EXIT)\n");
+    *hvVer = getHypervisorVersion();
+    return(0);
+}
+
+static char *
+ldomsGetHostname(virConnectPtr conn) 
+{
+
+    int rc;
+    char hostname [MAXHOSTNAMELEN+1];
+    char *host;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsGetHostname(ENTER)\n");
+
+    rc = gethostname (hostname, MAXHOSTNAMELEN);
+    if (rc == -1) {
+        ldomsError (conn, NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno), VIR_ERR_ERROR);
+        return NULL;
+    }
+
+    host = strdup (hostname);
+    if (host == NULL) {
+        ldomsError (conn, NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno), VIR_ERR_ERROR);
+        return NULL;
+    }
+    return host;
+}
+
+/*
+ * ldomsListDomains
+ *
+ * What: Return the array of Domain ID's for all the active Domains.
+ *       Send an XML request to LDM (LDoms Manager) for a list of all Domains.
+ *
+ * Yes, this functions does pretty much the same as ldomsNumOfDomains() with
+ * the addition of returning the ID numbers for the valid Domains.
+ *
+ * Input:  conn - The Connection structure
+ *         maxids - The total number of Domains to look at to
+ *                  determine what Domain IDs to return.
+ * Output: ids - An array of integers to hold the IDs of the
+ *               Domains whose state is other than 'inactive' -
+ *               VIR_DOMAIN_SHUTOFF
+ */
+static int
+ldomsListDomains(virConnectPtr conn, int *ids, int maxids) 
+{
+    int i,n;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsListDomains(ENTER), Max # of non inactive domains=%d\n",maxids);
+
+    /* Send an LDM request 'list-domains' */
+    if (get_ldom_names(&ldom_cnt, &ldominfo_list) < 0) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsListDomains() get_ldom_names() failed\n");
+        return (-1);
+    };
+
+    /* The Domain ID will be the index into the ldominfo_list array */
+    for (i=0, n=0; i<ldom_cnt && n<maxids; i++) {
+        if (ldominfo_list[i]->ldomState != LDOM_STATE_INACTIVE) {
+            ids[n++] = i;
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsListDomains(), Active Domain ID=%d\n",i);
+        }
+    }
+    
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsListDomains(EXIT), # of non inactive domains=%d\n",n);
+    return(n);
+} /* ldomsListDomains() */
+
+/*
+ * ldomsNumOfDomains
+ *
+ * What: Return the total number of active Domains (not VIR_SHUT_OFF)
+ *
+ * Input: conn - Pointer to a connection structure
+ * Output: function return - # of active Domains
+ */
+static int
+ldomsNumOfDomains(virConnectPtr conn) 
+{
+    int rc, i, numActive=0;
+    /* int ldom_cnt; */
+    /* ldominfo_t **ldominfo_list = NULL; */
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNumOfDomains(ENTER) \n");
+    /* 
+     * Call LDM with a list-domains cmd to get the total
+     * # of Domains and the basic information of each one.
+     */
+
+    if (get_ldom_names(&ldom_cnt, &ldominfo_list) < 0) {
+        /* Any ldominfo_t memory was freed in get_ldom_names() */
+        free(ldominfo_list);
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNumOfDomains() get_ldom_names() failed\n");
+        return (0);
+    };
+
+    /* Get the number of non inactive domains */
+    for (i=0; i<ldom_cnt; i++) {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsNumOfDomains() name=%s\n",ldominfo_list[i]->ldomName);
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsNumOfDomains() state=%d\n",ldominfo_list[i]->ldomState);
+        if (ldominfo_list[i]->ldomState != LDOM_STATE_INACTIVE) numActive++;
+    }
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNumOfDomains(EXIT) non inactive ldom_cnt=%d\n",numActive);
+    return (numActive);
+
+} /* ldomsNumOfDomains() */
+
+/*
+ * ldomsDomainCreateXML
+ *
+ * What: Create a domain from an XML file so that it is left in the    
+ *       inactive state.  Just call the DefineXML function.  The XML input    
+ *       has to be a complete and valid XML requeset for the LDM.  No
+ *       modification is done to this file.
+ *
+ * Input: xml - The xml file
+ * Output: function return - A ptr to a virDomain or NULL
+ */
+virDomainPtr
+ldomsDomainCreateXML(virConnectPtr conn,  const char *xml, unsigned int flags)
+{
+    virDomainPtr domPtr = NULL;
+    char *domainName = NULL;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainCreateXML(ENTER) \n");
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainCreateXML(ENTER) xmldoc=\n%s\n",xml);
+
+    /* Send the XML file along with the lifecycle action */
+    domainName = send_ldom_create_domain((char *)xml, XML_ADD_DOMAIN);
+
+    /* 
+     * If the create/bind domain was successful, then we have to create a DomainInfo
+     * structure to pass back to the caller.  We need the Domain name that was
+     * created, and the only way to get that is from parsing the input xml
+     * document. This is done in send_ldom_create_domain() and passed back as the return.  
+     * Also we create the uuid for the domain name.
+     */
+    if (domainName != NULL) {
+
+        /*
+         * The UUID is not important, cuz only the Domain name is printed
+         * out in the virsh.  So just use the default UUID.
+         */
+        domPtr = virGetDomain(conn, domainName, Uuid);
+        free(domainName);
+    }
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainCreateXML(EXIT) \n");
+
+    return (domPtr);
+} /* ldomsDomainCreateXML() */
+
+
+/*
+ * ldomsDomainLookupByID
+ *
+ * What: Given a Domain ID, either malloc or return the existing
+ *       virDomain structure for the Domain associated with the ID.
+ *
+ * Input: conn - A connection structure
+ *        id - ID of the Domain you want to find
+ * Output: Pointer to a virDomain of the Domain identified by the ID
+ */
+static virDomainPtr
+ldomsDomainLookupByID(virConnectPtr conn, int id) 
+{
+
+    virDomainPtr domPtr;
+    int i, idx=-1;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainLookupByID(ENTER) id=%d\n",id);
+
+    /* get the current ldom data from LDM */
+    (void) pthread_rwlock_wrlock(&update_lock);
+    refresh_ldom_data();
+    (void) pthread_rwlock_unlock(&update_lock);
+
+    /* Find the Domain that matches the ID.  The index of the ldominfo_list
+     * array is the Domain ID */
+    for (i=0; i<ldom_cnt; i++) {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainLookupByID() id=%d, Dom id=%d\n",id,i);
+        if (i == id) {
+            idx = i;
+            break;
+        }
+    }
+
+    /*
+     * If Domain is inactive, then libvirt does not assocaite an ID with an
+     * inactive domain.  So check the LDoms domain state and if inactive, log
+     * and return an error.
+     */
+    if ((idx < 0) || (ldominfo_list[idx]->ldomState == LDOM_STATE_INACTIVE)) {
+        ldomsError(conn, NULL, VIR_ERR_NO_DOMAIN, _("no ID match"), VIR_ERR_ERROR);
+        return(NULL);
+    }
+
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainLookupByID() found id=%d, Dom id=%d\n",id,idx);
+
+    domPtr = virGetDomain(conn, ldominfo_list[id]->ldomName, ldominfo_list[id]->uuid);
+    if (domPtr == NULL) {
+        ldomsError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating domain"), VIR_ERR_ERROR);
+        return(NULL);
+    }
+    
+    domPtr->id = id;
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainLookupByID(EXIT) \n");
+    return (domPtr);
+} /* ldomsDomainLookupByID() */
+
+/*
+ * ldomsDomainLookupByUUID
+ *
+ * What: Given a Domain UUID, either malloc or return the existing
+ *       virDomain structure for the Domain associated with the UUID.
+ *
+ * Input: conn - A connection structure
+ *        id - ID of the Domain you want to find
+ * Output: Pointer to a virDomain of the Domain identified by the UUID
+ */
+static virDomainPtr
+ldomsDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) 
+{
+
+    virDomainPtr domPtr;
+    int i, idx=-1;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainLookupByUUID(ENTER) \n");
+
+    /* get the current ldom data from LDM */
+    (void) pthread_rwlock_wrlock(&update_lock);
+    refresh_ldom_data();
+    (void) pthread_rwlock_unlock(&update_lock);
+
+
+    /* Find the Domain that matches the UUID.  */
+    for (i=0; i<ldom_cnt; i++) {
+        if (memcmp(uuid, ldominfo_list[i]->uuid, VIR_UUID_BUFLEN) == 0) {
+            idx = i;
+            break;
+        }
+    }
+
+    if (idx < 0) {
+        ldomsError(conn, NULL, VIR_ERR_NO_DOMAIN, _("no UUID match"), VIR_ERR_ERROR);
+        return(NULL);
+    }
+
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainLookupByUUID() found id=%d\n",idx);
+
+    domPtr = virGetDomain(conn, ldominfo_list[idx]->ldomName, ldominfo_list[idx]->uuid);
+    if (domPtr == NULL) {
+        ldomsError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating domain"), VIR_ERR_ERROR);
+        return(NULL);
+    }
+    
+    /* If the Domain state is inactive, then the ID must be set to -1 */
+    if (ldominfo_list[idx]->ldomState == LDOM_STATE_INACTIVE) {
+        idx = -1;
+    }
+    domPtr->id = idx;
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainLookupByUUID(EXIT) \n");
+    return (domPtr);
+} /* ldomsDomainLookupByID() */
+
+/*
+ * ldomsDomainLookupByName
+ *
+ * What: Given a Domain Name, either malloc or return the existing
+ *       virDomain structure for the Domain associated with the name.
+ *       The virDomain will contain the ID and UUID for the domain.
+ *       If a Domain is in the inactive state, then we don't set a
+ *       ID for it.  libvirt considers inactive Domains to have an
+ *       ID of -1 until they are moved out of the inactive state.
+ *
+ *
+ * Input: conn - A connection structure
+ *        name - Pointer to the Domain name
+ * Output: Pointer to a virDomain of the Domain identified by the name
+ */
+virDomainPtr 
+ldomsDomainLookupByName(virConnectPtr conn, const char *name)
+{
+    virDomainPtr domPtr = NULL;
+    int i, uuidIdx, idx = -99;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainLookupByName(ENTER) name=%s\n",name);
+
+    /* get the current ldom data from LDM */
+    (void) pthread_rwlock_wrlock(&update_lock);
+    refresh_ldom_data();
+    (void) pthread_rwlock_unlock(&update_lock);
+
+
+    /* Find the index of our internal ldominfo_list[] that has the Domain data */
+    for (i=0; i<ldom_cnt; i++) {
+        if (strcmp(ldominfo_list[i]->ldomName,name) == 0) {
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainLookupByName(), Found Domain: ID=%d\n",i);
+
+            /* If the Domain is inactive, then set the index to -1 */
+            if (ldominfo_list[i]->ldomState == LDOM_STATE_INACTIVE) {
+                idx = -1;
+                uuidIdx = i;
+            }
+            else
+                idx = i;
+            break;
+        }
+    }
+
+
+    /* A non-inactive domain was found */
+    if (idx >= 0) {
+        domPtr = virGetDomain(conn, name, ldominfo_list[idx]->uuid);
+        if (domPtr == NULL) {
+            ldomsError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating domain"), VIR_ERR_ERROR);
+            return(NULL);
+        }
+        domPtr->id = idx;
+    }
+
+    /* An inactive domain was found, or worst case, LDM does not know
+     * about the input domain name!!  This latter case should not happen
+     */
+    else if (idx == -1) {
+        domPtr = virGetDomain(conn, name, ldominfo_list[uuidIdx]->uuid);
+        if (domPtr == NULL) {
+            ldomsError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating inactive domain"), VIR_ERR_ERROR);
+            return(NULL);
+        }
+        domPtr->id = idx;
+    }
+
+    /* No domain name match was made */
+    else {
+        ldomsError(conn, NULL, VIR_ERR_NO_DOMAIN, _("no domain name match"), VIR_ERR_ERROR);
+    }
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainLookupByName(EXIT) ID=%d\n",idx);
+    return (domPtr);
+} /* ldomsDomainLookupByName() */
+
+/*
+ * ldomsDomainSuspend
+ *
+ * What: Given a Domain pointer, suspend/stop/pause the domain.
+ *       These 3 actions are equivalent: suspend/stop/pause.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainSuspend(virDomainPtr domain)
+{
+    int rc;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSuspend(ENTER) name=%s\n",domain->name);
+
+    /* get the current ldom data from LDM */
+    (void) pthread_rwlock_wrlock(&update_lock);
+    refresh_ldom_data();
+    (void) pthread_rwlock_unlock(&update_lock);
+
+
+    /*
+     * If the domain state is not active (1), then we can't perform
+     * this action.  
+     */
+
+    if (ldominfo_list[domain->id]->ldomState != LDOM_STATE_ACTIVE) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSuspend() Domain state not 'active', aborting request. domain=%s, state=%d\n",domain->name, ldominfo_list[domain->id]->ldomState);
+        return (-1);
+    }
+
+    /* Request LDM to change the state of the LDom */
+    rc = send_ldom_lifecycle_action(domain->name, LDOM_STOP);
+
+    /* 
+     * If successful, the domain state changed from active to bound,
+     * so update the status.
+     */
+    if (rc == 0) {
+        ldominfo_list[domain->id]->ldomState = LDOM_STATE_BOUND;
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainSuspend() Domain state changed to 'bound'. domain=%s\n",
+            domain->name);
+        return (0);
+    }
+    
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSuspend(EXIT) Domain state change failed. domain=%s\n",domain->name);
+    return (-1);
+} /* ldomsDomainSuspend() */
+
+/*
+ * ldomsDomainResume
+ *
+ * What: Given a Domain pointer, resume/start the domain.
+ *       These 2 states are equivalent: resume/start.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainResume(virDomainPtr domain)
+{
+    int rc;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainResume(ENTER) name=%s\n",domain->name);
+
+    /* get the current ldom data from LDM */
+    (void) pthread_rwlock_wrlock(&update_lock);
+    refresh_ldom_data();
+    (void) pthread_rwlock_unlock(&update_lock);
+
+
+    /*
+     * If the domain state is not bound (6), then we can't perform
+     * this action.  
+     */
+
+    if (ldominfo_list[domain->id]->ldomState != LDOM_STATE_BOUND) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainResume() Domain state not 'bound', aborting request. domain=%s, state=%d\n",domain->name, ldominfo_list[domain->id]->ldomState);
+        return (0);
+    }
+
+    /* Request LDM to change the state of the LDom */
+    rc = send_ldom_lifecycle_action(domain->name, LDOM_START);
+
+    /* 
+     * If successful, the domain state changed from bound to active,
+     * so update the status.
+     */
+    if (rc == 0) {
+        ldominfo_list[domain->id]->ldomState = LDOM_STATE_ACTIVE;
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainResume() Domain state changed to 'active'. domain=%s\n",
+            domain->name);
+        return (0);
+    }
+    
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainResume(EXIT) Domain state change failed. domain=%s\n",domain->name);
+    return (-1);
+} /* ldomsDomainResume() */
+
+/*
+ * ldomsDomainShutdown
+ *
+ * What: Given a Domain pointer, shutdown/bind the domain.
+ *       The domain can only be in the active state to begin,
+ *       and will be put into the bound state.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainShutdown(virDomainPtr domain)
+{
+    int rc = -1;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainShutdown(ENTER) domName=%s, domID=%d\n",
+        domain->name,domain->id);
+
+    /* get the current ldom data from LDM */
+    (void) pthread_rwlock_wrlock(&update_lock);
+    refresh_ldom_data();
+    (void) pthread_rwlock_unlock(&update_lock);
+
+
+    /* If the domain is inactive, then log an error and return */
+    if (domain->id == -1) {
+        ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, _("Domain is inactive"), VIR_ERR_WARNING );
+        return (-1);
+    }
+
+    /* If the domain is already bound, then log an error and return */
+    if (ldominfo_list[domain->id]->ldomState == LDOM_STATE_BOUND) {
+        ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, _("Domain is already bound"), VIR_ERR_WARNING );
+        return (-1);
+    }
+
+
+    /* If the domain state is active, then stop the domain */
+    if (ldominfo_list[domain->id]->ldomState == LDOM_STATE_ACTIVE) {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainShutdown() Domain state is 'active', stopping...\n");
+        rc = send_ldom_lifecycle_action(domain->name, LDOM_STOP);
+    }
+
+    /*
+     * If successful, the domain state changed from active to bound,
+     * so update the status.
+     */
+    if (rc == 0) {
+        ldominfo_list[domain->id]->ldomState = LDOM_STATE_BOUND;
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainShutdown() Domain state changed to 'bound'. domain=%s\n",
+            domain->name);
+        return (0);
+    }
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainShutdown(EXIT) Domain state change failed. domain=%s\n",domain->name);
+
+    return (-1);
+} /* ldomsDomainShutdown() */
+
+
+/*
+ * ldomsDomainDestroy
+ *
+ * What: Given a Domain pointer, destroy/unbind the domain.
+ *       The domain can be in the active or bound state to begin
+ *       and will be put into the inactive state.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainDestroy(virDomainPtr domain)
+{
+    int rc = -1;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDestroy(ENTER) domName=%s, domID=%d\n",
+        domain->name,domain->id);
+
+    /* If the domain is already inactive, then log an error and return */
+    if (domain->id == -1) {
+        ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, _("Domain is already inactive"), VIR_ERR_WARNING );
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainDestroy() Domain is already inactive.\n");
+        return (-1);
+    }
+
+    /* get the current ldom data from LDM */
+    (void) pthread_rwlock_wrlock(&update_lock);
+    refresh_ldom_data();
+    (void) pthread_rwlock_unlock(&update_lock);
+
+
+    /* If the domain state is active, then stop the domain */
+    if (ldominfo_list[domain->id]->ldomState == LDOM_STATE_ACTIVE) {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainDestroy() Domain state is 'active', stopping...\n");
+        rc = send_ldom_lifecycle_action(domain->name, LDOM_STOP);
+
+        /* Need to tell the next piece of code that a 'stop' was done and
+         * was successful, because the ldom info has not been updated. 
+         */
+        if (rc == 0) rc = 1;
+    }
+
+    /* If the domain state is bound (6), then unbind the domain */
+    if ((rc == 1) ||  (ldominfo_list[domain->id]->ldomState == LDOM_STATE_BOUND)) {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainDestroy() Domain state is 'bound' rc=%d, unbinding...\n",rc);
+        rc = send_ldom_lifecycle_action(domain->name, LDOM_UNBIND);
+    }
+
+    /* 
+     * If successful, the domain state changed to inactive,
+     * so update the status.
+     */
+    if (rc == 0) {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainDestroy() Domain state changed to 'inactive'. domain=%s\n",
+            domain->name);
+        return (0);
+    }
+    
+    /*
+     * In case the input domain info is not correct and the domain is really
+     * inactive, log a warning.
+     */
+    if (rc == -1) {
+        ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, _("Domain is already inactive"), VIR_ERR_WARNING );
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainDestroy() Domain state/ID not indicating inactive, ID=%d\n", domain->id);
+    }
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDestroy(EXIT) Domain state change failed. domain=%s\n",domain->name);
+
+    return (-1);
+} /* ldomsDomainDestroy() */
+
+/*
+ * ldomsDomainGetOSType
+ *
+ * What: The the OS type for an LDoms domain
+ *
+ * Input: domain - A pointer to the virDomain structure * NOT USED *
+ * Output: String representing the OS type
+ */
+char *
+ldomsDomainGetOSType(virDomainPtr domain)
+{
+    return strdup("Solaris");
+} /* ldomsDomainGetOSType() */
+
+
+/*
+ * ldomsDomainGetMaxMemory
+ *
+ * What:
+ * For LDoms, GetMaxMemory will just get the current memory
+ * allocated to the Domain.  There is no concept of Max memory
+ * for a Domain in LDoms.  
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - The amount of memory in Kilobytes
+ *
+ */
+unsigned long
+ldomsDomainGetMaxMemory(virDomainPtr domain)
+{
+    int domidx;
+    unsigned long memory;
+
+    if ((domidx = getDomainIndex(domain)) < 0) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetMaxMemory(EXIT) getDomainIndex() failed\n");
+        return (-1);
+    }
+    memory = ldominfo_list[domidx]->ldomMemSize;
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetMaxMemory() MaxMemory=%dKB\n",memory);
+    return (memory);
+} /* ldomsDomainGetMaxMemory() */
+
+/*
+ * ldomsDomainSetMemory
+ *
+ * What: Given a Domain pointer, send an XML request to change
+ *       the amount of memory for the domain.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ *        memory - Size in KiloBytes
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainSetMemory(virDomainPtr domain, unsigned long memory)
+{
+    int rc;
+    int domidx;
+    virDomainInfo domInfo;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSetMemory(ENTER) memory=%d\n",memory);
+
+    if ((domidx = getDomainIndex(domain)) < 0) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSetMemory(EXIT) getDomainIndex() failed\n");
+        return (-1);
+    }
+
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainSetMemory: domain=%s, domidx=%d\n",domain->name,domidx);
+
+    /* Send request to LDM to set the memory */
+    rc = send_ldom_set_memory(domain->name, memory);
+
+    if (rc == 0) {
+        ldominfo_list[domidx]->ldomMemSize = memory;
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainSetMemory() memory changed to %dKB\n",memory);
+    }
+    else {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSetMemory(EXIT) memory change failed\n");
+        return (-1);
+    }
+
+    /* Success */
+    return (0);
+} /* ldomsDomainSetMemory() */
+
+/*
+ * ldomsDomainSetMaxMemory
+ *
+ * What:
+ * For LDoms, you cannot set the Maximum memory that a domain can use.
+ * If a domain asks for X memory and it is available, then the domain
+ * will get it when it is bound.  Max memory is already calculated for
+ * all domains, just to be able to work with virsh, so this function will 
+ * merely return Success to appease virsh.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ *        memory - Size in KiloBytes
+ * Output: function return - 0 - success
+ *
+ */
+int
+ldomsDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
+{
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSetMaxMemory(ENTER/EXIT) memory=%d\n",memory);
+    return (0);
+} /* ldomsDomainSetMaxMemory() */
+
+/*
+ * ldomsDomainGetInfo
+ *
+ * What: Given a virDomain, get the info for that Domain and return it.
+ *       Note: The info.maxMem variable is set to the maximum memory allowed.
+ *         We try to get the maximum memory allowed by LDM, by calling
+ *         list-devices to get the free memory and by
+ *         adding up the total used memory from all domains.
+ *         If this fails,
+ *         the info.maxMem variable will be set to the maximum value for
+ *         a signed long.  This is because LDoms does not have a
+ *         concept for Max memory for a Domain.  However the VMM and
+ *         virsh shell do have a Max mem concept and won't let you
+ *         change the memory for a Domain if the new amount is
+ *         greater than the Maximum.  So this is why we set the Max
+ *         to the value for a signed long, even though the info.maxMem
+ *         data type is an unsigned long.
+ *
+ * Input: domain - Pointer to a virDomain struct
+ *        info - Poiner to a virDomainInfo struct to update
+ * Output: Indirect virDomainInfo struct updated with input domain info
+ */
+int 
+ldomsDomainGetInfo (virDomainPtr domain, virDomainInfoPtr info) 
+{
+    char state;
+    int domidx;
+    struct timeval tv;
+    virDomainInfo domInfo;
+
+    unsigned long maxmem;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetInfo(ENTER) \n");
+
+    if (gettimeofday(&tv, NULL) < 0) {
+        ldomsError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day"), VIR_ERR_WARNING);
+        return (-1);
+    }
+
+    if ((domidx = getDomainIndex(domain)) < 0) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetInfo(EXIT) getDomainIndex() failed\n");
+        return (-1);
+    }
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetInfo() domain=%s, domidx=%d\n",domain->name,domidx);
+
+/* Convert between LDom Domain state and libvirt Domain state
+ * LDoms
+ *       1 = active
+ *       2 = stopping
+ *       3 = inactive
+ *       4 = binding
+ *       5 = unbinding
+ *       6 = bound
+ *       7 = starting
+ *
+ * libvirt
+ *
+ *   VIR_DOMAIN_NOSTATE = 0,  no state 
+ *   VIR_DOMAIN_RUNNING = 1, /* the domain is running 
+ *   VIR_DOMAIN_BLOCKED = 2, /* the domain is blocked on resource 
+ *   VIR_DOMAIN_PAUSED  = 3, /* the domain is paused by user 
+ *   VIR_DOMAIN_SHUTDOWN= 4, /* the domain is being shut down 
+ *   VIR_DOMAIN_SHUTOFF = 5, /* the domain is shut off 
+ *   VIR_DOMAIN_CRASHED = 6  /* the domain is crashed 
+ */
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetInfo() ldomName=%s\n",ldominfo_list[domidx]->ldomName);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetInfo() ldomState=%d\n",ldominfo_list[domidx]->ldomState);
+
+    switch (ldominfo_list[domidx]->ldomState) {
+        case LDOM_STATE_ACTIVE: state = VIR_DOMAIN_RUNNING; break;
+        case LDOM_STATE_STOPPING: state = VIR_DOMAIN_SHUTDOWN; break;
+        case LDOM_STATE_INACTIVE: state = VIR_DOMAIN_SHUTOFF; break;
+        case LDOM_STATE_BINDING: state = VIR_DOMAIN_SHUTDOWN; break;
+        case LDOM_STATE_UNBINDING: state = VIR_DOMAIN_SHUTOFF; break;
+        case LDOM_STATE_BOUND: state = VIR_DOMAIN_SHUTDOWN; break;
+        case LDOM_STATE_STARTING: state = VIR_DOMAIN_RUNNING; break;
+        default: state= VIR_DOMAIN_NOSTATE; break;
+    }
+
+    /* Only name and state are obtained from a list-domain */
+    domInfo.state = state;
+
+    /* 
+     * Get the maximum memory that can be allocated for this domain.
+     * For a domain that is bound or active, then it already has that
+     * memory allocated to it.  The amount the it can add is only the
+     * amount free in the system, so just add Free + Bound memory.
+     *
+     * For a domain that is inactive, it can request any amount of
+     * memory, even more than what is physically present.  Thus we
+     * have to put an upper limit on the Maximum, so again, we just
+     * add the amount of Free system memory to the requested memory.
+     *
+     * Set the dominfo.maxMem to the maximum value for a signed long
+     * if it fails to get the maximum memory allowed from LDM 
+     */ 
+    if (get_free_memory(&maxmem) < 0) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetInfo() get_free_memory() failed\n");
+        domInfo.maxMem = MAXLONG;
+    } else
+        domInfo.maxMem = maxmem + ldominfo_list[domidx]->ldomMemSize;
+
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetInfo() MaxMemory=%d\n", maxmem);
+
+    domInfo.memory = ldominfo_list[domidx]->ldomMemSize; 
+    domInfo.nrVirtCpu = (unsigned short)ldominfo_list[domidx]->ldomNumVCpu;
+    /* LDM XML does not give the uptime for a Domain, so just set this to 0 */
+    domInfo.cpuTime = 0;  /* ((tv.tv_sec * 1000ll * 1000ll  * 1000ll * (domidx+1)) + (tv.tv_usec + 100011));  */
+    memcpy(info, &domInfo, sizeof(virDomainInfo));
+
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetInfo() ldomMemory=%d\n",ldominfo_list[domidx]->ldomMemSize);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetInfo() ldomVcpu=%d\n",ldominfo_list[domidx]->ldomNumVCpu);
+
+
+    return (0);
+} /* ldomsDomainGetInfo() */
+
+/*
+ * ldomsDomainSetVcpus
+ *
+ * What: Given a Domain pointer, send an XML request to change
+ *       the number of cpus for the domain.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus)
+{
+    int rc;
+    int domidx;
+    virDomainInfo domInfo;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSetVcpus(ENTER) vcpus=%d\n",nvcpus);
+
+    if ((domidx = getDomainIndex(domain) < 0)) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSetVcpus(EXIT) getDomainIndex() failed\n");
+        return (-1);
+    }
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainSetVcpus: domain=%s, domidx=%d\n",domain->name,domidx);
+    rc = send_ldom_set_vcpu(domain->name, nvcpus);
+
+    if (rc == 0) {
+        ldominfo_list[domidx]->ldomNumVCpu = nvcpus;
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainSetVcpus() vcpus changed to %d\n",nvcpus);
+    }
+    else {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainSetVcpus() vcpu change failed\n");
+        return (-1);
+    }
+    return(0);
+
+} /* ldomsDomainSetVcpus() */
+
+/*
+ * ldomsDomainGetVcpus
+ *
+ * What: Given a Domain pointer, send an XML request to get
+ *       the CPU bindings for the domain.  Then fill in the
+ *       input cpuInfo structure with detailed info for each
+ *       CPU: virt->phys mapping, State, Uptime.  The Affinity
+ *       is only Xen specific at this time.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo,
+                    unsigned char *cpumaps, int maplen)
+{
+    int i,rc;
+    int domidx;
+    int numCpu;
+    long long upTime;
+    char cpuBits;
+    cpuBindings_t *cpuBindings;
+    processor_info_t pinfo;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetVcpus(ENTER) domName=%s, maxinfo=%d, maplen=%d\n",domain->name, maxinfo, maplen);
+
+    /* Get the Domain index */
+    if ((domidx = getDomainIndex(domain) < 0)) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetVcpus(EXIT) getDomainIndex() failed\n");
+        return (-1);
+    }
+
+    /* The domain must be in the Bound or Active state */
+    if ( (ldominfo_list[domidx]->ldomState == LDOM_STATE_BOUND) ||
+         (ldominfo_list[domidx]->ldomState == LDOM_STATE_ACTIVE) )
+    {
+        if ((numCpu = get_ldom_cpu_bindings(domain->name, &cpuBindings)) < 0) {
+            if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetVcpus(EXIT) numCpu=%d failed\n",numCpu);
+            return (-1);
+        }
+    }
+    else {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetVcpus(EXIT) Domain in wrong state %s\n",ldominfo_list[domidx]->ldomState);
+        return (-1);
+    }
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainGetVcpus() numCpu=%d, cpuBindings=%d \n",numCpu,cpuBindings);
+
+    /* Walk the linked list of CPU bindings and fill in the cpuInfoPtr return structure */
+        
+    upTime = getCpuUpTime();
+    while (cpuBindings != NULL) {
+        
+        /* Get the CPU state from processor_info().  This will only work for
+         * CPUs in the Control Domain.  All other CPUs are in the Guest Domains,
+         * so we set their state to Unknown and Uptime to 0.
+         * TODO unless we can get the State and Uptime from the PRI??
+         */
+
+        if (processor_info(cpuBindings->real, &pinfo) == 0) {
+            switch (pinfo.pi_state) {
+                case 1: info->state = VIR_VCPU_OFFLINE; break;
+                case 2: info->state = VIR_VCPU_RUNNING; break;
+                case 3: info->state = VIR_VCPU_BLOCKED; break;
+                case 4: info->state = VIR_VCPU_OFFLINE; break;
+                case 5: info->state = VIR_VCPU_OFFLINE; break;
+                case 6: info->state = VIR_VCPU_RUNNING; break;
+                case 7: info->state = VIR_VCPU_OFFLINE; break;
+                default: info->state = VIR_VCPU_OFFLINE; break;
+            }
+            info->cpuTime = upTime;
+        } else {
+            info->state = VIR_VCPU_UNKNOWN;
+            info->cpuTime = 0;
+        }
+
+        info->number = cpuBindings->virt;
+        info->cpu    = cpuBindings->real;
+        
+        /* Got this from libvirt/libvirt.h  VIR_CPU_USABLE */
+        /* cpumaps[(info->number) + (info->cpu)/8] = (1<<((info->cpu)%8)); */
+        info++;
+
+        cpuBindings = cpuBindings->next;
+    }
+    
+    return (numCpu);
+
+} /* ldomsDomainSetVcpus() */
+
+/*
+ * ldomsDomainGetMaxVcpus
+ *
+ * What: If the domain is inactive, then you can set the cpu constraint
+ *       to any number you want, because the CPUs are not reserved until
+ *       the domain is bound.  Return MAXINT for inactive domains.
+ *
+ *       For non-inactive domains, call existing fuctions to get the amount 
+ *       of Free and Used CPUs in the system.  Now since a request is being
+ *       made for a domain that already has Vcpus allocated to it, we have       
+ *       to add that amount of the Free amount, and then return that value.
+ *
+ *       Example.  Total Vcpus=32; Free Vcpus=10; Domains X has 15.
+ *       Now, we want to increase Domain X Vcpus to 17.
+ *       Now, if we return the # for Free Vcpus, virsh will not call the
+ *       SetVcpu routine, and will report an error instead, because the
+ *       request of 17 is greater than the Free amount.
+ *       So we add the Free (10) and the current allocated (15) and return
+ *       that as the Max # of Vcpus.
+ *             
+ *
+ * Input: domain - A pointer to the virDomain structure UNUSED
+ * Output: function return - >=0 # of Free CPUs.  <0 error.
+ */
+int
+ldomsDomainGetMaxVcpus(virDomainPtr domain) 
+{
+    int freeVcpus;
+    int domainVcpus;
+
+    /* inactive domains can request any amount of vcpus */
+    if (domain->id < 0) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetMaxVcpus(ENTER) inactive domain=%s, MaxVcpus=%d\n",domain->name,MAXINT);
+        return (MAXINT);
+    }
+
+    /*
+     * For bound and active domains, sum the # of Free Vcpus and the # currently
+     * currently used by the Domain.  This is the Max # that can be requested.
+     */
+    freeVcpus = ldomsGetMaxVcpus(NULL, NULL);
+    domainVcpus = ldominfo_list[domain->id]->ldomNumVCpu;
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainGetMaxVcpus() Domain Vcpus=%d, Free Vcpus=%d\n",ldominfo_list[domain->id]->ldomNumVCpu,freeVcpus);
+
+    return (freeVcpus + domainVcpus);
+
+
+} /* ldomsDomainSetVcpus() */
+
+/*
+ * ldomsDomainDumpXML
+ *
+ * What: Send a list-constraints request to LDM for the domain specified
+ *       by the input virDomain.
+ *
+ * Input: domain - Pointer to a virDomain structure
+ * Output: function return - char ptr to the XML data
+ */
+char *
+ldomsDomainDumpXML(virDomainPtr domain, int flags)
+{
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDumpXML(ENTER) domain=%s\n",domain->name);
+
+    xmlDocPtr xml_to_send;
+    xmlDocPtr xml_received;
+    unsigned char *xml;
+    int xmlSize;
+    int domidx;
+
+    if ((domidx = getDomainIndex(domain)) < 0) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDumpXML(EXIT) getDomainIndex() failed\n");
+        return (NULL);
+    }
+
+    /* Create XML list-constraints request */
+    xml_to_send = create_xml_file_4_ldom_action(domain->name, XML_LIST_CONST);
+    if (xml_to_send == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDumpXML() can not create list-constraints xml file\n");        
+        ldomsError(NULL, domain, VIR_ERR_INTERNAL_ERROR, "Could not create XML file", VIR_ERR_ERROR);
+        return (NULL);
+    }
+
+    /* Send request to LDM  and receive response */
+    xml_received  = send_xml_file_to_ldm(xml_to_send);
+    if (xml_received  == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDumpXML() failed to send xml file to ldm and receive xml response\n");
+        ldomsError(NULL, domain, VIR_ERR_OPERATION_FAILED, "Could not create XML file", VIR_ERR_ERROR);
+        xmlFreeDoc(xml_to_send);
+        return (NULL);
+    }
+
+    /* Dump the response to memory */
+    xml = malloc(sizeof(char) * 10000);
+    xmlKeepBlanksDefault(0);
+    xmlDocDumpFormatMemory(xml_received, &xml, &xmlSize, 1);
+    if ( xmlSize > 0 ) {
+        xmlFree(xml_received);
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainDumpXML() xml doc size is %d:\n%s\n",xmlSize,xml);
+        return ((char *)xml);
+    } 
+
+    return (NULL);
+
+} /* ldomsDomainDumpXML() */
+
+/*
+ * ldomsListDefinedDomains
+ *
+ * What: Return the names of all inactive Domains
+ *
+ * Input: conn - Pointer to a connection structure
+ *      names - An array of pointers to chars (Domain names)
+ *      maxnames - Total number of inactive Domains
+ * Output: function return - # of inactive Domains found
+ *       names - Updated pointers to strdup'd inactive Domain names
+ */
+int ldomsListDefinedDomains(virConnectPtr conn,
+                            char **const names,
+                            int maxnames) 
+{
+
+/* virsh command 'define' creates a domain but leaves it in the bound state.
+ * This routine is finding all inactive domains, but the name of the routine is
+ * ListDefinedDomains.   We are just following what test.c does, which is count
+ * the number of Domains in libvirt state SHUTOFF, which is LDoms state inactive.
+ */
+    int n = 0, i;
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsListDefinedDomains(ENTER) maxnames=%d\n",maxnames);
+
+    /* get the current ldom data from LDM */
+    (void) pthread_rwlock_wrlock(&update_lock);
+    refresh_ldom_data();
+    (void) pthread_rwlock_unlock(&update_lock);
+
+
+    /* TODO NOTE: We did not call get_ldom_names() here since the thought
+     * is that ldomsNumOfDefinedDomains() will always be called right
+     * before this is.  This may not be the case, but for now we will
+     * leave until we find out otherwise.
+     */
+    for (i = 0, n = 0 ; i < ldom_cnt && n < maxnames ; i++) {
+        if (ldominfo_list[i]->ldomState == LDOM_STATE_INACTIVE) {
+            names[n++] = strdup(ldominfo_list[i]->ldomName);
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsListDefinedDomains() inactive domain=%s\n",
+                ldominfo_list[i]->ldomName);
+        }
+    }
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsListDefinedDomains(EXIT) # of inactive domains=%d\n",n);
+    return (n);
+} /* ldomsListDefinedDomains() */
+
+/*
+ * ldomsNumOfDefinedDomains
+ *
+ * What: Return the total number of inactive Domains (VIR_SHUT_OFF)
+ *
+ * Input: conn - Pointer to a connection structure
+ * Output: function return - # of inactive Domains
+ */
+int 
+ldomsNumOfDefinedDomains (virConnectPtr conn)
+{
+    int numInactive = 0, i;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNumOfDefinedDomains(ENTER) \n");
+
+    /* Send an LDM request 'list-domains' */
+    if (get_ldom_names(&ldom_cnt, &ldominfo_list) < 0) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNumOfDefinedDomains() get_ldom_names() failed\n");
+        return (-1);
+    };
+
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsNumOfDefinedDomains() get_ldom_names(return) ldom_cnt=%d\n",ldom_cnt);
+
+
+    /* The Domain ID will be the index into the ldominfo_list array */
+    for (i=0; i<ldom_cnt; i++) {
+        if (ldominfo_list[i] == NULL) {
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsNumOfDefinedDomains() ldominfo_list[%d] is NULL\n",i);
+        }
+        else if (ldominfo_list[i]->ldomState == LDOM_STATE_INACTIVE) {
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsNumOfDefinedDomains() inactive Domain ID=%d \n",i);
+            numInactive++;
+        }
+    }
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsNumOfDefinedDomains(EXIT) # of inactive domains=%d \n",numInactive);
+    return (numInactive);
+} /* ldomsNumOfDefinedDomains() */
+
+/*
+ * ldomsDomainStart
+ *
+ * What: Start a previously defined inactive domain.  
+ *       The domain can be in the inactive or bound state to begin
+ *       and will be put into the active state.
+ *
+ * Input: domain - A pointer to a virDomain structure (unused)
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainStart(virDomainPtr domain)
+{
+    int rc = 0;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainStart(ENTER) domName=%s, domID=%d\n",
+        domain->name,domain->id);
+
+    /* get the current ldom data from LDM */
+    (void) pthread_rwlock_wrlock(&update_lock);
+    refresh_ldom_data();
+    (void) pthread_rwlock_unlock(&update_lock);
+
+
+    /* If the domain ID is -1, this means the domain state is 'inactive.
+     * If the domain state is inactive (3), then bind the domain */
+    if ((domain->id == -1) ||
+        (ldominfo_list[domain->id]->ldomState == LDOM_STATE_INACTIVE)) {
+
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainStart() Domain state is 'inactive', binding...\n");
+        rc = send_ldom_lifecycle_action(domain->name, LDOM_BIND);
+
+        /* Need to tell the next piece of code that a 'bind' was done and
+         * was successful, because the ldom info has not been updated. 
+         */
+        if (rc == 0) rc = 1;
+    }
+
+    /* If the domain was inactive and failed to bind, or if the domain was already
+     * active, then we fall into this case.
+     */
+    if (rc < 0) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainStart(EXIT) Domain state change failed. domain=%s\n",domain->name);
+        return (-1);
+    } 
+
+    /* If the domain state is bound (6), then start the domain */
+    if ((rc == 1) ||  (ldominfo_list[domain->id]->ldomState == LDOM_STATE_BOUND)) {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainStart() Domain state is 'bound' rc=%d, starting...\n",rc);
+        rc = send_ldom_lifecycle_action(domain->name, LDOM_START);
+        if (rc == 0) rc = 2;
+    }
+
+    /* If successful, the domain state changed to active */
+    if (rc == 2) {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainStart() Domain state changed to 'active'. domain=%s\n",
+            domain->name);
+        return (0);
+    } 
+
+    ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, _("Domain is active"), VIR_ERR_WARNING );
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainStart(EXIT) Domain state change failed. domain=%s\n",domain->name);
+    return (-1);
+    
+
+} /* ldomsDomainStart() */
+
+/*
+ * ldomsDomainDefineXML
+ *
+ * What: Create a domain from an XML file so that it is left in the    
+ *       bound state. The XML input must be of the form from the
+ *       output of 'ldm list-constraints -x <ldom>'.  Any of the
+ *       XML can be changed, but the <action> tag will be added by
+ *       this code.
+ *
+ * Input: xml - The xml file in a char buffer
+ * Output: function return - A ptr to a virDomain or NULL
+ */
+virDomainPtr
+ldomsDomainDefineXML(virConnectPtr conn,  const char *xml)
+{
+    virDomainPtr domPtr = NULL;
+    char *domainName = NULL;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDefineXML(ENTER) \n");
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainDefineXML(ENTER) xmldoc=\n%s\n",xml);
+
+    /* Send the XML file along with the lifecycle action */
+    domainName = send_ldom_create_domain((char *)xml, XML_BIND_DOMAIN);
+
+    /* 
+     * If the create domain was successful, then we have to create a DomainInfo
+     * structure to pass back to the caller.  We need the Domain name that was
+     * created, and the only way to get that is from parsing the input xml
+     * document. This is done in send_ldom_create_domain() and passed back as the return.  
+     * Also we create the uuid for the domain name.
+     */
+    if (domainName != NULL) {
+
+        /*
+         * The UUID is not important, cuz only the Domain name is printed
+         * out in the virsh.  So just use the default UUID.
+         */
+        domPtr = virGetDomain(conn, domainName, Uuid);
+        free(domainName);
+    }
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainDefine(EXIT) \n");
+
+    return (domPtr);
+} /* ldomsDomainDefineXML() */
+
+/*
+ * ldomsDomainUndefine
+ *
+ * What: Given a Domain pointer, undefine/delete the domain.
+ *       The domain can only be in the inactive state to begin,
+ *       and will be deleted to not exist.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - >=0 is success
+ */
+int
+ldomsDomainUndefine(virDomainPtr domain)
+{
+    int rc = -1;
+    int domidx;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainUndefine(ENTER) domName=%s, domID=%d\n",
+        domain->name,domain->id);
+
+    /* If the Domain is inactive, the ID in the input domain will be a -1.
+     * Get the domain index from our ldominfo_list to verify it is indeed inactive
+     * before we try to delete it.
+     */
+    if ((domidx = getDomainIndex(domain)) < 0) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainUndefine(EXIT) getDomainIndex() failed\n");
+        return (-1);
+    }
+
+    /* If the domain state is inactive, then delete the domain */
+    if ( (ldominfo_list[domidx]->ldomState == LDOM_STATE_INACTIVE) &&
+         (domain->id == -1) )
+    {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainUndefine() Domain state is 'inactive', deleting...\n");
+        rc = send_ldom_lifecycle_action(domain->name, LDOM_DELETE);
+    } else {
+        ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, _("Domain is not inactive"), VIR_ERR_WARNING );
+        return (-1);
+    }
+
+    /* If successful, the domain has been deleted */
+    if (rc == 0) {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsDomainUndefine() Domain deleted\n");
+        return (0);
+    }
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainUndefine(EXIT) Domain undefine failed\n");
+
+    return (-1);
+} /* ldomsDomainUndefine() */
+
+/*
+ * ldomsDomainConsole
+ *
+ * What: Given a Domain pointer, get the console port number
+ *       for the domain.
+ *
+ * Input: domain - A pointer to the virDomain structure
+ * Output: function return - <0 is failure, >0 is the domain console port number
+ */
+int
+ldomsDomainConsole(virDomainPtr domain)
+{
+    int rc = 0;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainConsole(ENTER) domName=%s, domID=%d\n",
+        domain->name,domain->id);
+
+    /* get the current ldom data from LDM */
+    (void) pthread_rwlock_wrlock(&update_lock);
+    refresh_ldom_data();
+    (void) pthread_rwlock_unlock(&update_lock);
+
+    /*
+     * If the domain ID is -1, this means the domain state is 'inactive.
+     * If the domain state is inactive (3), then we don't return a port #
+     * Log an error because an inactive domain has no active console port.
+     */
+    if ((domain->id == -1) ||
+        (ldominfo_list[domain->id]->ldomState == LDOM_STATE_INACTIVE)) {
+
+        if (ldoms_detailed_debug) dprt("LDOMS_DEBUG: ldomsDomainConsole(EXIT) Domain state is 'inactive'\n");
+        ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, "Domain is inactive", VIR_ERR_WARNING );
+        return (-1);
+    }
+
+    /*
+     * If the domain is the primary domain, then its console has to be accessed
+     * via the SC and not thru this utility.  There is no port number associated
+     * with the primary domain console.
+     */
+    if (strcmp(domain->name, "primary") == 0) {
+        ldomsError(NULL, domain, VIR_ERR_INVALID_OPTION, "Must connect to primary console via the SC", VIR_ERR_WARNING );
+        return (-1);
+    }
+
+    /* Else, the console port # is in the ldominfo_list[] for that domain */
+    if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsDomainConsole(EXIT) console=%d\n",
+        ldominfo_list[domain->id]->ldomConsole);
+    return (ldominfo_list[domain->id]->ldomConsole);
+}
+
+void dprt(const char *template, ...)
+{
+    va_list ap;
+    char buf[10240];
+    static int do_open = 1;
+    static FILE * fp;
+
+    va_start(ap, template);
+    (void) vsprintf(buf, template, ap);
+    va_end(ap);
+
+    if (do_open) {
+        do_open = 0;
+
+        fp = fopen("/var/log/libvirt_ldoms.dbg", "w");
+    }
+    fputs(buf, fp);
+    fflush(fp);
+} /* dprt */
+
+/*
+ * refresh_ldom_data
+ *
+ * Send an XML request to LDM for a list of all Domains
+ * and get the basic information of each Domain.
+ *
+ * This function will be called for each commands to
+ * guarantee that we have the current LDom info for any
+ * virsh CLI command.
+ *
+ * Input:
+ * Output: 
+ */
+static void 
+refresh_ldom_data()
+{
+    struct timeval tv;
+    long delta;
+
+    /* Try and throttle calling the LDM to update the list of
+     * LDoms.  If the calls are 2 secs or less apart, then we just
+     * use the current LDoms info.  This is because each
+     * command from virsh can turn into several calls into
+     * function in this file, which all call this function
+     * to refresh the LDom data.
+     */
+    if (gettimeofday(&tv, NULL) >= 0) {
+        /* See if the time since the last call to this functions
+         * is less than 3 seconds.  If so, just return.
+         */
+        if ((delta=tv.tv_sec - last_ldom_refresh) < 3) {
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: refresh_ldom_data(NO Refresh) delta=%d\n",
+                delta);
+            return;
+        }
+        last_ldom_refresh = tv.tv_sec;
+    }
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: refresh_ldom_data(Refresh) delta=%d\n",delta);
+
+    /*
+     * Call LDM with a list-domains cmd to get the total
+     * # of Domains and the basic information of each one.
+     */
+
+    if (get_ldom_names(&ldom_cnt, &ldominfo_list) < 0) {
+        /* Any ldominfo_t memory was freed in get_ldom_names() */
+        free(ldominfo_list);
+        if (ldoms_debug) dprt("LDOMS_DEBUG: refresh_ldom_data() get_ldom_names() failed\n");
+    }
+
+} /* refresh_ldom_data() */
+
+/*
+ * getHypervisorVersion()
+ *
+ * Gets the LDoms hypervisor version by parsing the output of
+ * the command 'ldm -V'.
+ *
+ * The output is:
+ * Logical Domain Manager (v 1.0.1)
+ *      Hypervisor control protocol v 1.0
+
+ * System PROM:
+ *      Hypervisor      v. 1.5.1        @(#)Hypervisor 1.5.1 2007/09/14 16:11\015
+ *
+ *      OpenBoot        v. 4.27.1       @(#)OBP 4.27.1 2007/09/14 15:17
+ *
+ * Output: long representing the value of the hypervisor version in the format
+ *         needed by virsh.
+ */
+
+static long
+getHypervisorVersion()
+{
+    FILE *fp = popen("/opt/SUNWldm/bin/ldm -V", "r");
+    char buf[256];
+    char major[8], minor[8], rel[8];
+    char *chp,*chp1;
+    long long hyperVersion;
+    int done = 0;
+    int PROM_line_found = 0;
+    long maj,min,release;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: getHypervisorVersion(ENTER)\n");
+
+    /* check the popen for failure */
+    if (fp == NULL)
+        return(0);
+
+    /* Read the input until we find and process the Hypervisor version */
+    while (! done) {
+        chp = fgets(buf,sizeof(buf),fp);
+        if (chp == NULL)
+            return(0);
+
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getHypervisorVersion() line=%s\n",buf);
+
+        if ( (chp1=strstr(buf,"PROM")) != NULL ) {
+            PROM_line_found = 1;
+            continue;
+        }
+
+        if (((chp1=strstr(buf,"Hypervisor")) != NULL ) && (PROM_line_found)) {
+
+            /*
+             * There are more than 1 lines with 'Hypervisor' in them.  Wait until
+             * we find the line with 'System PROM'.  The next line with 'Hypervisor'
+             * will be the one we want.
+             */
+
+            /* Step thru to the '.' */
+            while (*chp1 != '.') chp1++;
+            chp1++;
+
+            /* Step to the 1st digit of the version */
+            while ((*chp1 == ' ') || (*chp1 == '\t')) chp1++;
+
+            /* Pointing to 1st digit of version. */
+            if (isdigit(*chp1)) {
+                major[0] = *chp1++;
+            } else {
+                if (ldoms_debug) dprt("LDOMS_DEBUG: getHypervisorVersion() Major '%c' is not a digit\n",*chp1);
+                return(0);
+            }
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getHypervisorVersion() major=%c:%d \n",major[0],major[0]);
+
+            /* *chp1 should be a '.' */
+            if (*chp1++ != '.' ) {
+                if (ldoms_debug) dprt("LDOMS_DEBUG: getHypervisorVersion() No . after major? ch=%c\n",*(--chp1));
+                return(0);
+            } 
+            /* Should be pointing to minor version digit */
+            if (isdigit(*chp1)) {
+                minor[0] = *chp1++;
+            } else {
+                if (ldoms_debug) dprt("LDOMS_DEBUG: getHypervisorVersion() Minor '%c' is not a digit\n",*chp1);
+                return(0);
+            }
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getHypervisorVersion() minor=%c:%d \n",minor[0],minor[0]);
+
+            /* If we are not pointing to a '.', then there is no rel */
+            if (*chp1++ != '.' ) {
+                rel[0] = '0';
+                if (ldoms_debug) dprt("LDOMS_DEBUG: getHypervisorVersion()  Not pointing to a '.' before the release digit. ch=%c\n",*(--chp1));
+            } else {
+                if (isdigit(*chp1)) {
+                    rel[0] = *chp1++;
+                 } else {
+                    if (ldoms_debug) dprt("LDOMS_DEBUG: getHypervisorVersion() Release '%c' is not a digit\n",*chp1);
+                    rel[0] = '0';
+                 }
+            } 
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getHypervisorVersion() rel=%c:%d \n",rel[0],rel[0]);
+
+            break; /* out of while */
+        }
+    } /* while */
+
+    /* Now construct the long long that virsh needs to convert to a version number */
+    major[1] = '\0';
+    minor[1] = '\0';
+    rel[1] = '\0';
+
+    maj = atol(major) * 1000000;
+    min = atol(minor) * 1000;
+    release = atol(rel);
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: getHypervisorVersion(EXIT) maj=%d, min=%d, rel=%d, version=%d\n",
+        maj,min,release,maj+min+release);
+
+    return (maj + min + release);
+
+} /* getHypervisorVersion() */
+
+
+/*
+ * getLDMVersion()
+ *
+ * Gets the LDoms Manager version by parsing the output of
+ * the command 'ldm -V'.
+ *
+ * The output is:
+ * Logical Domain Manager (v 1.0.1)
+ * ..
+ * Output: long representing the value of the LDoms Manager version in the format
+ *         needed by virsh.
+ */
+
+static unsigned long
+getLDMVersion()
+{
+    FILE *fp = popen("/opt/SUNWldm/bin/ldm -V", "r");
+    char buf[256];
+    char major[8], minor[8], rel[8];
+    char *chp,*chp1;
+    int done = 0;
+    int LDM_line_found = 0;
+    unsigned long maj,min,release;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: getLDMVersion(ENTER)\n");
+
+    /* check the popen for failure */
+    if (fp == NULL)
+        return(0);
+
+    /* Read the input until we find and process the LDoms Manager version */
+    while (! done) {
+        chp = fgets(buf,sizeof(buf),fp);
+        if (chp == NULL)
+            return(0);
+
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getLDMVersion() line=%s\n",buf);
+
+
+        if ( (chp1=strstr(buf,"Logical Domain Manager")) != NULL ) {
+            LDM_line_found = 1;
+        }
+
+        if (LDM_line_found) {
+
+            /* Step thru to the 'v' */
+            while (*chp1 != 'v') chp1++;
+            chp1++;
+
+            /* Step to the 1st digit of the version */
+            while ((*chp1 == ' ') || (*chp1 == '\t')) chp1++;
+
+            /* Pointing to 1st digit of version. */
+            if (isdigit(*chp1)) {
+                major[0] = *chp1++;
+            } else {
+                if (ldoms_debug) dprt("LDOMS_DEBUG: getLDMVersion() Major '%c' is not a digit\n",*chp1);
+                return(0);
+            }
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getLDMVersion() major=%c:%d \n",major[0],major[0]);
+
+            /* *chp1 should be a '.' */
+            if (*chp1++ != '.' ) {
+                if (ldoms_debug) dprt("LDOMS_DEBUG: getLDMVersion() No . after major? ch=%c\n",*(--chp1));
+                return(0);
+            } 
+            /* Should be pointing to minor version digit */
+            if (isdigit(*chp1)) {
+                minor[0] = *chp1++;
+            } else {
+                if (ldoms_debug) dprt("LDOMS_DEBUG: getLDMVersion() Minor '%c' is not a digit\n",*chp1);
+                return(0);
+            }
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getLDMVersion() minor=%c:%d \n",minor[0],minor[0]);
+
+            /* If we are not pointing to a '.', then there is no rel */
+            if (*chp1++ != '.' ) {
+                rel[0] = '0';
+                if (ldoms_debug) dprt("LDOMS_DEBUG: getLDMVersion()  Not pointing to a '.' before the release digit. ch=%c\n",*(--chp1));
+            } else {
+                if (isdigit(*chp1)) {
+                    rel[0] = *chp1++;
+                 } else {
+                    if (ldoms_debug) dprt("LDOMS_DEBUG: getLDMVersion() Release '%c' is not a digit\n",*chp1);
+                    rel[0] = '0';
+                 }
+            } 
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getLDMVersion() rel=%c:%d \n",rel[0],rel[0]);
+
+            break; /* out of while */
+        }
+    } /* while */
+
+    /* Now construct the long long that virsh needs to convert to a version number */
+    major[1] = '\0';
+    minor[1] = '\0';
+    rel[1] = '\0';
+
+    maj = atol(major) * 1000000;
+    min = atol(minor) * 1000;
+    release = atol(rel);
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: getLDMVersion(EXIT) maj=%d, min=%d, rel=%d, version=%d\n",
+        maj,min,release,maj+min+release);
+
+    return (maj + min + release);
+
+} /* getLDMVersion() */
+
+/*
+ * getCpuUpTime()
+ *
+ * Gets the CPU uptime by parsing the output of the command 'uptime'.
+ *
+ * Output: long representing the value of the cpu up time in nanosecs 
+ */
+long long
+getCpuUpTime()
+{
+        FILE *fp = popen("/bin/uptime", "r");
+        char buf[256];
+        char output[256];
+        char day[5];
+        char hour[5];
+        char min[5];
+        char *chp1,*chp2;
+        int d=0,h=0,m=0;
+        long long uptime;
+        long long duptime;
+        long long huptime;
+        long long muptime;
+
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getCpuUpTime(ENTER) \n");
+
+        /* check the popen for failure */
+        if (fp == NULL)
+            return(0);
+
+        fgets(buf,sizeof(buf),fp);
+        pclose(fp);
+
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getCpuUpTime() buf=%s \n",buf);
+        /* Find 'up', then advance to the day */
+        /* 6:56am  up 6 day(s), 14:46,  10 users,  load average: 0.06, 0.14, 0.12 */
+        chp1 = strstr(buf, "up");
+        if (chp1 == NULL)
+            return(0);
+
+        while (*chp1 != ' ') chp1++;
+        chp1++;
+
+        /* Get the day number */
+        /* chp2 is point at the 6 */
+        chp2=chp1;
+        while (*chp2 != ' ') {
+            day[d++] = *chp2; 
+            chp2++;
+        }
+        day[d] = '\0';
+        chp2++;
+
+        /* Advance to the 1st digit of the hour */
+        /* chp2 is pointing at the 'd' */
+        while (*chp2 != ' ') chp2++;
+        chp2++;
+
+        /* Get the hour number */
+        /* chp2 is pointing at the '1' */
+        while (*chp2 != ':') { hour[h++] = *chp2; chp2++; }
+        hour[h] = '\0';
+        chp2++;
+
+        /* Get the minute number */
+        /* chp2 is pointing at the '4' after : */
+        while (*chp2 != ',') { min[m++] = *chp2; chp2++; }
+        min[m] = '\0';
+        chp2++;
+
+        strncpy(output, chp1, (chp2 - chp1));
+        output[chp2-chp1] = '\0';
+
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getCpuUpTime(): Uptime = %s\n",output);
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getCpuUpTime(): day=%s, hour=%s, min=%s\n",day,hour,min);
+
+        duptime = atoll(day);
+        duptime = duptime * 60 * 60 * 24;
+        huptime = atoll(hour);
+        huptime = huptime * 60 * 60;
+        muptime = atoll(min);
+        muptime = muptime * 60;
+        uptime = duptime + huptime + muptime;
+        uptime *= 1000000000;
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: getCpuUpTime(): Uptime = %lld nanosecs\n",uptime);
+
+        return (uptime);
+
+} /* getCpuUpTime() */
+
+/* 
+ * Callback functions for Network actions. These are defined at the end
+ * so we don't have to declare function prototypes at the beginning of
+ * this file.
+ */
+static virNetworkDriver ldomsNtwkDriver = {
+    "LDoms",
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+/* 
+ * Callback functions for Domain actions.  These are defined at the end
+ * so we don't have to declare function prototypes at the beginning of
+ * this file.
+ */
+static virDriver ldomsDriver = {
+    VIR_DRV_LDOMS,             /* Driver number */
+    "LDoms",                   /* Name of the driver */
+    LDOMS_VERSION_NUMBER,      /* Version of LDoms API */
+    ldomsOpen,                 /* open */
+    ldomsClose,                /* close */
+    NULL,                      /* virDrvSupportsFeature supports_feature; NOT LDOMS SUPPORTED */
+    ldomsGetType,              /* type */
+    ldomsGetVersion,           /* getVersion */
+    ldomsGetHostname,          /* getHostname */
+    NULL,                      /* virDrvGetURI  getURI; NOT LDOMS SUPPORTED */
+    ldomsGetMaxVcpus,          /* virDrvGetMaxVcpus TODO need support */
+    ldomsNodeGetInfo,          /* nodeGetInfo */
+    NULL,                      /* virDrvGetCapabilities  getCapabilities; NOT LDOMS SUPPORTED */
+    ldomsListDomains,          /* listDomains */
+    ldomsNumOfDomains,         /* numOfDomains */
+    ldomsDomainCreateXML,      /* domainCreateLinux; Create an inactive domain from XML */
+    ldomsDomainLookupByID,     /* domainLookupByID */
+    ldomsDomainLookupByUUID,   /* domainLookupByUUID */
+    ldomsDomainLookupByName,   /* domainLookupByName */
+    ldomsDomainSuspend,        /* virDrvDomainSuspend  domainSuspend; TODO NOT LDOMS SUPPORTED */
+    ldomsDomainResume,         /* virDrvDomainResume   domainResume; TODO NOT LDOMS SUPPORTED */
+    ldomsDomainShutdown,       /* domainShutdown */
+    NULL,                      /* virDrvDomainReboot   domainReboot; NOT LDOMS SUPPORTED */
+    ldomsDomainDestroy,        /* domainDestroy */
+    ldomsDomainGetOSType,      /* domainGetOSType */
+    ldomsDomainGetMaxMemory,   /* domainGetMaxMemory */
+    ldomsDomainSetMaxMemory,   /* domainSetMaxMemory */
+    ldomsDomainSetMemory,      /* domainSetMemory */
+    ldomsDomainGetInfo,        /* domainGetInfo */
+    NULL,                      /* virDrvDomainSave  domainSave; NOT LDOMS SUPPORTED */
+    NULL,                      /* virDrvDomainRestore  domainRestore; NOT LDOMS SUPPORTED */
+    NULL,                      /* virDrvDomainCoreDump  domainCoreDump; NOT LDOMS SUPPORTED */
+    ldomsDomainSetVcpus,       /* domainSetVcpus */
+    NULL,                      /* virDrvDomainPinVcpu  domainPinVcpu; NOT LDOMS SUPPORTED */
+    ldomsDomainGetVcpus,       /* domainGetVcpus */
+    ldomsDomainGetMaxVcpus,    /* domainGetMaxVcpus; */
+    ldomsDomainDumpXML,        /* domainDumpXML */
+    ldomsListDefinedDomains,   /* listDefinedDomains */
+    ldomsNumOfDefinedDomains,  /* numOfDefinedDomains */
+    ldomsDomainStart,          /* domainCreate - Really start an inactive domain */
+    ldomsDomainDefineXML,      /* domainDefineXML */
+    ldomsDomainUndefine,       /* domainUndefine */
+    NULL,        /* virDrvDomainAttachDevice  domainAttachDevice; NOT LDOMS SUPPORTED */
+    NULL,        /* virDrvDomainDetachDevice  domainDetachDevice; NOT LDOMS SUPPORTED */
+    NULL,        /* virDrvDomainGetAutostart  domainGetAutostart; NOT LDOMS SUPPORTED */
+    NULL,        /* virDrvDomainSetAutostart  domainSetAutostart; NOT LDOMS SUPPORTED */
+    NULL,        /* virDrvDomainGetSchedulerType  domainGetSchedulerType; NOT LDOMS SUPPORTED */
+    NULL,        /* virDrvDomainGetSchedulerParameters domainGetSchedulerParameters; NOT LDOMS SUPPORTED */
+    NULL,        /* virDrvDomainSetSchedulerParameters domainSetSchedulerParameters; NOT LDOMS SUPPORTED */
+    NULL,        /* virDrvDomainMigratePrepare  domainMigratePrepare; NOT LDOMS SUPPORTED */
+    NULL,        /* virDrvDomainMigratePerform  domainMigratePerform; NOT LDOMS SUPPORTED */
+    NULL,        /* virDrvDomainMigrateFinish   domainMigrateFinish; NOT LDOMS SUPPORTED */
+    NULL,        /* virDrvDomainBlockStats      domainBlockStats; NOT LDOMS SUPPORTED */
+    NULL,        /* virDrvDomainInterfaceStats  domainInterfaceStats; NOT LDOMS SUPPORTED */
+    NULL,        /* virDrvNodeGetCellsFreeMemory    nodeGetCellsFreeMemory; NOT LDOMS SUPPORTED */
+    NULL,        /* virDrvNodeGetFreeMemory         getFreeMemory; NOT LDOMS SUPPORTED */
+    ldomsDomainConsole,   /* ldomConsole */
+};
+
+/*
+ * ldomsRegister:
+ *
+ * Registers LDoms in libvirt driver system.  This functions goes at the
+ * end so we don't have to declare ldomsDriver or ldomsNtwkDriver ahead of time.
+ */
+int ldomsRegister(void) {
+
+    /* for debug statements */
+#ifdef LDOMS_DEBUG
+   ldoms_debug = 1;
+   dprt("LDOMS_DEBUG on\n");
+#endif
+#ifdef LDOMS_DETAILED_DEBUG
+   ldoms_detailed_debug = 1;
+   dprt("LDOMS_DETAILED_DEBUG on\n");
+#endif
+   if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsRegister(ENTER)\n");
+
+   /* Only root can execute libvirt LDoms */
+   if (geteuid() != 0) return -1; 
+
+   /* initialize for a rw-lock to make the code more multithread-safe */
+   (void) pthread_rwlock_init(&update_lock, NULL);
+
+   /* Get the LDoms Manager version number */
+   LDMVersion = getLDMVersion(); 
+
+   if (ldoms_debug) dprt("LDOMS_DEBUG: ldomsRegister.. LDoms version used = %u\n", LDMVersion);
+
+   return (virRegisterDriver(&ldomsDriver));
+    
+
+}
+
+
+#endif /* WITH_LDOMS */
+
+/*
+ * vim: set tabstop=4:
+ * vim: set shiftwidth=4:
+ * vim: set expandtab:
+ */
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
+
diff --git a/src/ldoms_intfc.h b/src/ldoms_intfc.h
new file mode 100644
--- /dev/null
+++ b/src/ldoms_intfc.h
@@ -0,0 +1,336 @@
+/*
+ * ldoms_intfc.h: LDoms definitions used for interfaces with the LDoms Manager (LDM)
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ */
+
+#ifndef __VIR_LDOMS_INTFC_H__
+#define __VIR_LDOMS_INTFC_H__
+
+#ifdef WITH_LDOMS
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/byteorder.h>
+#include <inttypes.h>    
+#include <libxml/tree.h>
+
+#include "ldoms_xml_parse.h"
+#include "ldoms_common.h"
+
+#define DEFAULT_PORT    5311
+#define LDOM_INTERFACE_VERSION  ((xmlChar *)"1.0")
+#define LDOM_DATA_VERSION       ((xmlChar *)"2.0")
+#define VERSION_ATTR            ((xmlChar *)"version")
+
+#define XML_VERSION     ((xmlChar *)"1.0") /* version of XML used */
+
+#define XML_ADD_DOMAIN          ((xmlChar *)"add-domain")
+#define XML_DELETE              ((xmlChar *)"remove-domain")
+#define XML_STOP                ((xmlChar *)"stop-domain")
+#define XML_START_DOMAIN        ((xmlChar *)"start-domain")
+#define XML_BIND_DOMAIN         ((xmlChar *)"bind-domain")
+#define XML_UNBIND              ((xmlChar *)"unbind-domain")
+#define XML_LIST_CONST          ((xmlChar *)"list-constraints")
+#define XML_LIST_BIND           ((xmlChar *)"list-bindings")
+#define XML_LIST                ((xmlChar *)"list-domain")
+#define XML_LIST_DEVICES        ((xmlChar *)"list-devices")
+#define XML_LIST_SERVICES       ((xmlChar *)"list-services")
+#define XML_LIST_SETS           ((xmlChar *)"list-spconfig")
+#define XML_LIST_VARS           ((xmlChar *)"list-variable")
+#define XML_ADD_VCPU            ((xmlChar *)"add-vcpu")
+#define XML_ADD_MAU             ((xmlChar *)"add-mau")
+#define XML_ADD_MEM             ((xmlChar *)"add-memory")
+#define XML_ADD_IO              ((xmlChar *)"add-io")
+#define XML_ADD_VAR             ((xmlChar *)"add-variable")
+#define XML_ADD_VCONSCON        ((xmlChar *)"add-vconscon")
+#define XML_ADD_VDISK           ((xmlChar *)"add-vdisk")
+#define XML_ADD_VDS             ((xmlChar *)"add-vdiskserver")
+#define XML_ADD_VDSDEV          ((xmlChar *)"add-vdiskserverdevice")
+#define XML_ADD_VNET            ((xmlChar *)"add-vnet")
+#define XML_ADD_VSW             ((xmlChar *)"add-vswitch")
+#define XML_ADD_SPCONFIG        ((xmlChar *)"add-spconfig")
+#define XML_ADD_VDPCS           ((xmlChar *)"add-vdpcs")
+#define XML_ADD_VDPCC           ((xmlChar *)"add-vdpcc")
+#define XML_SET_VCPU            ((xmlChar *)"set-vcpu")
+#define XML_SET_MAU             ((xmlChar *)"set-mau")
+#define XML_SET_MEM             ((xmlChar *)"set-memory")
+#define XML_SET_VAR             ((xmlChar *)"set-variable")
+#define XML_SET_VCONSCON        ((xmlChar *)"set-vconscon")
+#define XML_SET_VNET            ((xmlChar *)"set-vnet")
+#define XML_SET_VSW             ((xmlChar *)"set-vswitch")
+#define XML_SET_SPCONFIG        ((xmlChar *)"set-spconfig")
+#define XML_SET_VCONSOLE        ((xmlChar *)"set-vconsole")
+#define XML_REMOVE_VCPU         ((xmlChar *)"remove-vcpu")
+#define XML_REMOVE_MAU          ((xmlChar *)"remove-mau")
+#define XML_REMOVE_MEM          ((xmlChar *)"remove-memory")
+#define XML_REMOVE_IO           ((xmlChar *)"remove-io")
+#define XML_REMOVE_VAR          ((xmlChar *)"remove-variable")
+#define XML_REMOVE_VCONSCON     ((xmlChar *)"remove-vconscon")
+#define XML_REMOVE_VDISK        ((xmlChar *)"remove-vdisk")
+#define XML_REMOVE_VDS          ((xmlChar *)"remove-vdiskserver")
+#define XML_REMOVE_VDSDEV       ((xmlChar *)"remove-vdiskserverdevice")
+#define XML_REMOVE_VNET         ((xmlChar *)"remove-vnet")
+#define XML_REMOVE_VSW          ((xmlChar *)"remove-vswitch")
+#define XML_REMOVE_SPCONFIG     ((xmlChar *)"remove-spconfig")
+#define XML_REMOVE_RECONF       ((xmlChar *)"remove-reconf")
+#define XML_REMOVE_VDPCS        ((xmlChar *)"remove-vdpcs")
+#define XML_REMOVE_VDPCC        ((xmlChar *)"remove-vdpcc")
+
+#define XML_LDM_INTERFACE       ((xmlChar *)"LDM_interface")
+#define XML_ACTION              ((xmlChar *)"action")
+#define XML_DATA                ((xmlChar *)"data")
+#define XML_SNMP_USER           ((xmlChar *)"snmp_user")
+#define XML_CMD                 ((xmlChar *)"cmd")
+#define XML_LDM_INFO            ((xmlChar *)"ldom_info")
+#define XML_LDM_NAME            ((xmlChar *)"ldom_name")
+#define XML_RESPONSE            ((xmlChar *)"response")
+#define XML_STATUS              ((xmlChar *)"status")
+#define XML_RESP_MSG            ((xmlChar *)"resp_msg")
+#define XML_BINDING             ((xmlChar *)"binding")
+#define XML_FREE                ((xmlChar *)"free")
+#define XML_PID                 ((xmlChar *)"pid")
+#define XML_VID                 ((xmlChar *)"vid")
+#define XML_STRAND_PERCENT      ((xmlChar *)"strand_percent")
+#define XML_REAL_ADDR           ((xmlChar *)"real_addr")
+#define XML_PHYS_ADDR           ((xmlChar *)"phys_addr")
+#define XML_MODE                ((xmlChar *)"mode")
+#define XML_CPUSET              ((xmlChar *)"cpuset")
+#define XML_DEV_TYPE            ((xmlChar *)"device_type")
+#define XML_PORT                ((xmlChar *)"port")
+#define XML_SPCONFIG            ((xmlChar *)"spconfig")
+#define XML_SPCONFIG_NAME       ((xmlChar *)"spconfig_name")
+#define XML_SPCONFIG_STATUS     ((xmlChar *)"spconfig_status")
+#define XML_SERVICE_DOMAIN      ((xmlChar *)"service_domain")
+#define XML_PHYSIO_DEVICE       ((xmlChar *)"physio_device")
+
+#define XML_CURRENT_STATUS      ((xmlChar *)"current")
+#define XML_NEXT_STATUS         ((xmlChar *)"next")
+
+#define XML_SUCCESS             "success"
+#define XML_FAILURE             "failure"
+
+/*
+ * XML node and attribute names
+ */
+#define CONSOLE_INSTANCE_NODE   ((xmlChar *)"console_instance")
+#define CONSOLE_NODE            ((xmlChar *)"console")
+#define CPU_NODE                ((xmlChar *)"cpu")
+#define MAU_NODE                ((xmlChar *)"mau")
+#define DEV_PATH_NODE           ((xmlChar *)"dev_path")
+#define GROUP_NODE              ((xmlChar *)"group")
+#define VCONS_PORT_NODE         ((xmlChar *)"port")
+#define INSTANCE_NODE           ((xmlChar *)"instance")
+#define LDOM_DATABASE_NODE      ((xmlChar *)"ldom_database")
+#define LDOM_NAME_NODE          ((xmlChar *)"ldom_name")
+#define LDOM_NODE               ((xmlChar *)"ldom")
+#define MAC_ADDRESS_NODE        ((xmlChar *)"mac_address")
+#define MAX_PORT_NODE           ((xmlChar *)"max_port")
+#define MEMORY_NODE             ((xmlChar *)"memory")
+#define MIN_PORT_NODE           ((xmlChar *)"min_port")
+#define MTU_NODE                ((xmlChar *)"mtu")
+#define NAME_NODE               ((xmlChar *)"name")
+#define NUMBER_NODE             ((xmlChar *)"number")
+#define PHYSIO_MINOR_NODE       ((xmlChar *)"minor")
+#define VOLUME_NAME_NODE        ((xmlChar *)"vol_name")
+#define VOLUME_OPTS_NODE        ((xmlChar *)"vol_opts")
+#define BLOCKDEV_NODE           ((xmlChar *)"block_dev")
+#define PHYSIO_NODE             ((xmlChar *)"physio")
+#define SERVICE_NAME_NODE       ((xmlChar *)"service_name")
+#define SERVER_INSTANCE_NODE    ((xmlChar *)"server_instance")
+#define SERVER_NODE             ((xmlChar *)"server")
+#define SHARING_NODE            ((xmlChar *)"sharing")
+#define SIZE_NODE               ((xmlChar *)"size")
+#define STATE_NODE              ((xmlChar *)"state")
+#define VALUE_NODE              ((xmlChar *)"value")
+#define VARIABLES_NODE          ((xmlChar *)"variables")
+#define VAR_NODE                ((xmlChar *)"var")
+#define VCC_INSTANCE_NODE       ((xmlChar *)"vcc_instance")
+#define VCC_NODE                ((xmlChar *)"vcc")
+#define DISK_INSTANCE_NODE      ((xmlChar *)"disk_instance")
+#define DISK_NODE               ((xmlChar *)"disk")
+#define VDISK_NAME_NODE         ((xmlChar *)"vdisk_name")
+#define VDS_VOLUME_NODE         ((xmlChar *)"vds_volume")
+#define VDS_VOLUMES_NODE        ((xmlChar *)"vds_volumes")
+#define VDS_INSTANCE_NODE       ((xmlChar *)"vds_instance")
+#define VDS_NODE                ((xmlChar *)"vds")
+#define VNET_INSTANCE_NODE      ((xmlChar *)"network_instance")
+#define VNET_NODE               ((xmlChar *)"network")
+#define VNET_NAME_NODE          ((xmlChar *)"vnet_name")
+#define VSW_INSTANCE_NODE       ((xmlChar *)"vsw_instance")
+#define VSW_POLICIES_NODE       ((xmlChar *)"policies")
+#define VSW_NODE                ((xmlChar *)"vsw")
+#define IO_INSTANCE_NODE        ((xmlChar *)"io_instance")
+#define IO_NODE                 ((xmlChar *)"io")
+#define IO_NAME_NODE            ((xmlChar *)"iodevice")
+#define IO_BYPASS_NODE          ((xmlChar *)"bypass_mode")
+#define VLDCC_NODE              ((xmlChar *)"vldcc")
+#define TIMEOUT_NODE            ((xmlChar *)"timeout")
+
+/*
+ * Protocol version supported.
+ */
+#define LDM_MAJOR_VER   1
+#define LDM_MINOR_VER   0
+
+/* per class version numbers */
+#define LDM_CLI_MAJOR_VER       2
+#define LDM_CLI_MINOR_VER       0
+
+#define LDM_CONTROL_MAJOR_VER   1
+#define LDM_CONTROL_MINOR_VER   0
+
+#define LDM_SUNMC_MAJOR_VER     1
+#define LDM_SUNMC_MINOR_VER     0
+
+enum {
+        LDM_INIT_REQ    = 0x0,
+        LDM_INIT_ACK    = 0x1,
+        LDM_INIT_NACK   = 0x2,
+        LDM_ERROR       = 0x3,
+        LDM_OP_REQ      = 0x4,
+        LDM_OP_REPLY    = 0x5
+};
+
+typedef struct {
+        uint32_t        msg_type;
+        uint32_t        payload_len;
+} ldm_hdr_t;
+
+enum {
+        LDM_CLASS_CLI           = 0x1,
+        LDM_CLASS_CONTROL       = 0x2,
+        LDM_CLASS_SUNMC         = 0x3
+};
+
+typedef struct {
+        uint32_t        client_class;
+        uint16_t        major_vers;
+        uint16_t        minor_vers;
+} ldm_init_req_t;
+
+typedef struct {
+        uint16_t        minor_vers;
+} ldm_init_ack_t;
+
+typedef struct {
+        uint16_t        major_vers;
+} ldm_init_nack_t;
+
+enum {
+        LDM_ERROR_UNKNOWN       = 0x1,
+        LDM_ERROR_UNEXPECTED    = 0x2,
+        LDM_ERROR_INVALID       = 0x3
+};
+
+typedef struct {
+        uint32_t        error_code;
+} ldm_error_t;
+
+typedef struct {
+        uint32_t        rq_len;
+        uint32_t        rq_id;
+        uint8_t         rq_data[];
+} ldm_op_req_t;
+
+typedef struct {
+        uint32_t        rp_len;
+        uint32_t        rp_reqid;
+        uint8_t         rp_data[];
+} ldm_op_reply_t;
+
+/*
+ * 0-3 are used by the ldm_protocol's initialization calls. 
+ */
+enum {
+        LDM_CNTRL_PRI_REQ       = 0x4,
+        LDM_CNTRL_PRI_REPLY     = 0x5,
+        LDM_CNTRL_XML_REQ       = 0x6,
+        LDM_CNTRL_XML_RESP      = 0x7
+};
+
+/* used by malloc to allocate memory for an entire msg  */
+typedef struct ldm_handshake_msg_s {
+        ldm_hdr_t       hdr_msg;
+        ldm_init_req_t  msg;
+} ldm_handshake_msg;
+
+typedef struct {
+        int     len;
+        char    data[];
+} xml_msg_t;
+
+#if defined(_BIG_ENDIAN)
+#define hton8(_x)       ((uint8_t)(_x))
+#define hton16(_x)      ((uint16_t)(_x))
+#define hton32(_x)      ((uint32_t)(_x))
+#define hton64(_x)      ((uint64_t)(_x))
+#define ntoh8(_x)       ((uint8_t)(_x))
+#define ntoh16(_x)      ((uint16_t)(_x))
+#define ntoh32(_x)      ((uint32_t)(_x))
+#define ntoh64(_x)      ((uint64_t)(_x))
+#else
+#define hton8(_x)       ((uint8_t)(_x))
+#define hton16(_x)      BSWAP_16((uint16_t)(_x))
+#define hton32(_x)      BSWAP_32((uint32_t)(_x))
+#define hton64(_x)      BSWAP_64((uint64_t)(_x))
+#define ntoh8(_x)       ((uint8_t)(_x))
+#define ntoh16(_x)      BSWAP_16((uint16_t)(_x))
+#define ntoh32(_x)      BSWAP_32((uint32_t)(_x))
+#define ntoh64(_x)      BSWAP_64((uint64_t)(_x))
+#endif
+
+xmlDocPtr send_xml_file_to_ldm(xmlDoc *xml_output);
+xmlDocPtr  handle_resp(char *resp_buf); 
+
+void close_ldm_connection(int sock);
+int get_free_memory(unsigned long *);
+int get_ldom_names(int *, ldominfo_t ***);
+int get_ldom_cpu_bindings(char *, cpuBindings_t **);
+int get_ldom_total_cpu(int *);
+int get_ldom_total_memory(unsigned long *);
+int ldm_create_pkt_buf(char **pkt_buf, char *xml_buf, int xml_buf_len);
+int open_ldm_connection(void);
+int send_ldom_active_mgmt(char *snmp_user, char *ldom_name, int ldom_state);
+char * send_ldom_create_domain(char *, xmlChar *);
+int send_ldom_lifecycle_action(char *, int);
+int send_ldom_set_memory(char *, unsigned long);
+int send_ldom_set_vcpu(char *, int);
+
+int get_all_ldominfo(char *snmp_user, int *all_ldom_cnt, ldominfo_t ***all_ldominfo_list);
+int get_crypto(char *snmp_user, char *ldom_name, int *crypto_cnt, crypto_t ***crypto_list);
+int get_envvars(char *snmp_user, char *ldom_name, int *envvars_cnt, envvars_t ***envvars_list);
+int get_iobus(char *snmp_user, char *ldom_name, int *iobus_cnt, iobus_t ***iobus_list);
+int get_ldominfo(char *ldom_name, int *num_cpu, int *mem_size, int *mem_unit, int *num_crypto, int *num_iobus, int * console, int state);
+int get_response(int sock, char **resp_buf);
+int get_rp(char *snmp_user, int resource, int rp_type, ulong_t *rp_qty, int *unit);
+int get_vcc(char *snmp_user, char *ldom_name, int *vcc_cnt, vcc_t ***vcc_list);
+int get_vcons(char *snmp_user, char *ldom_name, int *vcons_cnt, vcons_t ***vcons_list);
+int get_vconsvccrel(char *snmp_user, char *ldom_name, int *vconsvccrel_cnt, vconsvccrel_t ***vconsvccrel_list);
+int get_vcpu(char *snmp_user, char *ldom_name, int *vcpu_cnt, vcpu_t ***vcpu_list);
+int get_vdisk(char *snmp_user, char *ldom_name, int *vdisk_cnt, vdisk_t ***vdisk_list);
+int get_vds(char *snmp_user, char *ldom_name, int *vds_cnt, vds_t ***vds_list);
+int get_vdsdev(char *snmp_user, char *ldom_name, int *vdsdev_cnt, vdsdev_t ***vdsdev_list);
+int get_vmem(char *snmp_user, char *ldom_name, int *vmem_cnt, vmem_data_t ***vmem_list);
+int get_vmem_physbind(char *snmp_user, char *ldom_name, int *vmem_physbind_cnt, vmem_physbind_t ***vmem_physbind_list);
+int get_vnet(char *snmp_user, char *ldom_name, int *vnet_cnt, vnet_t ***vnet_list);
+int get_vsw(char *snmp_user, char *ldom_name, int *vsw_cnt, vsw_t ***vsw_list);
+
+xmlNodePtr xml_get_next_ele_node(xmlNodePtr node);
+xmlNodePtr xml_find_subnode(xmlNodePtr node, const xmlChar *name);
+int create_pkt_buf(char **pkt_buf, char *xml_buf, int xml_buf_len,
+    int msg_type);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif  /* WITH_LDOMS */
+#endif  /* __VIR_LDOMS_INTFC_H__ */
diff --git a/src/ldoms_intfc.c b/src/ldoms_intfc.c
new file mode 100644
--- /dev/null
+++ b/src/ldoms_intfc.c
@@ -0,0 +1,1825 @@
+/*
+ * ldoms_intfc.c: Interface code to the LDoms Manager (LDM)
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ */
+
+#ifdef WITH_LDOMS
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <netdb.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <libintl.h>
+#include <time.h>
+
+
+#include "libvirt/libvirt.h"
+#include "internal.h"
+#include "ldoms_internal.h"
+#include "ldoms_common.h"
+#include "ldoms_xml_parse.h"
+#include "ldoms_intfc.h"
+#include "xml.h"
+
+
+/* Domain state info
+ * LDom State enumerations
+ *       1 = active       LDOM_STATE_ACTIVE
+ *       2 = stopping     LDOM_STATE_STOPPING
+ *       3 = inactive     LDOM_STATE_INACTIVE
+ *       4 = binding      LDOM_STATE_BINDING
+ *       5 = unbinding    LDOM_STATE_UNBINDING
+ *       6 = bound        LDOM_STATE_BOUND
+ *       7 = starting     LDOM_STATE_STARTING
+ *
+ * libvirt LDom State enums
+ * typedef enum {
+ *   VIR_DOMAIN_NOSTATE = 0,  no state 
+ *   VIR_DOMAIN_RUNNING = 1,  the domain is running 
+ *   VIR_DOMAIN_BLOCKED = 2,  the domain is blocked on resource
+ *   VIR_DOMAIN_PAUSED  = 3,  the domain is paused by user
+ *   VIR_DOMAIN_SHUTDOWN= 4,  the domain is being shut down 
+ *   VIR_DOMAIN_SHUTOFF = 5,  the domain is shut off 
+ *   VIR_DOMAIN_CRASHED = 6   the domain is crashed 
+ * } virDomainState;
+ */
+
+/* Global vars for debug statement */
+extern int ldoms_debug;
+extern int ldoms_detailed_debug;
+
+/* 
+ * open_ldm_connection
+ *
+ * This is the function that opens a client socket connection to the LDOM Manager and
+ * performs the initial handshake protocol with the LDOM Manager.
+ *
+ * Returns:
+ *  socket descriptor if the operation is successful
+ *  -1 if it fails
+ *
+ * NOTE: This routine was copied from the example code provided by the LDOM Manager developer.
+ *  The LDOM Manager handshake protocol is defined in the ldm_protocol.h file  
+ *  in the LDOM Manager source code.  Also see the create_connection() routine in ldm.c 
+ *  from the LDOM Manager source code. 
+ */
+int
+open_ldm_connection(void)
+{
+    struct sockaddr_in myaddr;
+    struct stat statbuf;
+    ldm_hdr_t *hdr, hdr_buf;
+    ldm_init_req_t *init_req;
+    ldm_handshake_msg *buf;
+    int error, sock;
+    uint16_t port;
+
+     int client_class = LDM_CLASS_CONTROL; 
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection(ENTER)\n");
+
+    sock = socket(AF_INET, SOCK_STREAM, 0);
+    if (sock == -1) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..can not create socket\n");
+        return (-1);
+    }
+
+    port = DEFAULT_PORT;
+
+    myaddr.sin_family = AF_INET;
+    myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+    myaddr.sin_port = htons(port);
+    error = connect(sock, (struct sockaddr *)(&myaddr), sizeof (struct sockaddr_in));
+
+    if (error == -1) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..socket connect failed: port=%d\n",port);
+        return (-1);
+    }
+
+    if ((buf = malloc(sizeof(ldm_handshake_msg))) == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..malloc ldm_handshake_msg failed\n");
+        return(-1);
+    }
+
+    /* Header msg is always required to LDM */
+    hdr = (ldm_hdr_t *)buf;
+    hdr->msg_type = hton32(LDM_INIT_REQ);
+    hdr->payload_len = sizeof (ldm_init_req_t);
+
+    /* Specific request to LDM */
+    init_req = &buf->msg;
+    init_req->client_class = hton32(client_class);
+    init_req->major_vers = hton16(LDM_CONTROL_MAJOR_VER); 
+    init_req->minor_vers = hton16(LDM_CONTROL_MINOR_VER);
+
+    /* Send the request to the LDM */
+    error = send(sock, buf, sizeof(ldm_handshake_msg), 0);
+    if (error == -1) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..socket send with LDM_INIT_REQ failed\n");
+        return(-1);
+    }
+
+    free(buf);
+
+    /* 
+     * Get the header part of the response from the LDM.  This
+     * will let us know how big the message part is.
+     */
+    error = recv(sock, &hdr_buf, sizeof (ldm_hdr_t), MSG_WAITALL);
+    if (error == -1) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..socket recv failed\n");
+        return(-1);
+    }
+
+    hdr_buf.msg_type = ntoh32(hdr_buf.msg_type);
+    hdr_buf.payload_len = ntoh32(hdr_buf.payload_len);
+
+    /* See what the LDM responded with for the handshake request */
+    switch (hdr_buf.msg_type) {
+    case LDM_INIT_ACK: {
+        ldm_init_ack_t ack;
+
+        /* Get the rest of the response */
+        error = recv(sock, &ack, sizeof (ack), MSG_WAITALL);
+        if (error == -1) {
+            if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..LDM_INIT_ACK recv failed\n");
+            return(-1);
+        }
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: open_ldm_connection..LDM_INIT_ACK received, Minor sent=%d, Minor rcvd=%d\n",LDM_CONTROL_MINOR_VER,ack.minor_vers);
+        break;
+    }
+
+    case LDM_INIT_NACK: {
+        ldm_init_nack_t nack;
+
+        error = recv(sock, &nack, sizeof (nack), MSG_WAITALL);
+        if (error == -1) {
+            if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..LDM_INIT_NACK recv failed\n");
+            return(-1);
+        }
+
+        if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..LDM_INIT_NACK received, Major Version mismatch. Mjr sent=%d, Mjr rcvd=%d\n",LDM_CONTROL_MAJOR_VER,nack.major_vers);
+        return(-1);
+    }
+
+    case LDM_ERROR: {
+        ldm_error_t err;
+
+        error = recv(sock, &err, sizeof (err), MSG_WAITALL);
+        if (error == -1) {
+            if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..LDM_ERROR recv failed\n");
+            return(-1);
+        }
+
+        if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection..LDM_ERROR:  Protocol error=%d\n",err.error_code);
+
+        return(-1);
+        break;
+    }
+
+    default:
+        if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection: Unknown response type=%d\n",hdr_buf.msg_type);
+        return(-1);
+    }
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: open_ldm_connection(ENTER)\n");
+
+    return (sock);
+}
+
+/*
+ * close_ldm_connection
+ *
+ * This function will close the socket connection to the LDM
+ *
+ * Input:
+ *  sock - a socket descriptor to close
+ */
+void
+close_ldm_connection(int sock)
+{
+    if (ldoms_debug) dprt("LDOMS_DEBUG: close_ldm_connection(ENTER)..trying to close LDM socket=%d\n", sock);
+    (void)close(sock);
+    if (ldoms_debug) dprt("LDOMS_DEBUG: close_ldm_connection(EXIT)\n");
+}
+
+
+/*
+ * get_response
+ *
+ * This function receives messages from the LDM socket connection and puts them
+ * into the message buffer.
+ *
+ * Input:
+ *  sock - socket descriptor to receive messages
+ *
+ * Output:
+ *  resp_buf - pointer to the response buffer that contains the messages
+ *             from the socket connection.  This memory must be freed by the caller.
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *    
+ * NOTE: This routine was copied from the example code provided by the LDOM Manager developer.
+ */
+int
+get_response(int sock, char **resp_buf)
+{
+    ldm_hdr_t hdr;
+    char *buf;
+    int status, resp_len, text_len, cc;
+    int i;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_response(ENTER)\n");
+
+    /* Receive the Header of the response */
+    status = recv(sock, &hdr, sizeof (ldm_hdr_t), MSG_WAITALL);
+    if (status <= 0) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_response..recv failed for rsp header\n");
+        /* error or LDom manager exited */
+        return(-1);
+    }
+
+    hdr.msg_type = ntoh32(hdr.msg_type);
+
+    if (hdr.msg_type != LDM_CNTRL_XML_RESP) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_response..Unexpected response message type=%d\n",hdr.msg_type);
+        return(-1);
+    }
+
+    hdr.payload_len = ntoh32(hdr.payload_len);
+
+    *resp_buf = malloc(hdr.payload_len);
+
+    if (*resp_buf == NULL)
+        return(-1);
+
+    /* receive the actual response body from LDM */
+    status = recv(sock, *resp_buf, hdr.payload_len, MSG_WAITALL);
+    if (status == -1) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_response..recv failed for rsp body\n");
+        free(resp_buf);
+        return(-1);
+    }
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_response(EXIT)..received %d bytes for rsp body\n", status);
+
+    return (0);
+} /* get_response() */
+
+/*
+ * handle_resp
+ *
+ * This function converts the message buffer (received from the socket connection)
+ * into an xml document.
+ *
+ * Input:
+ *  resp_buf - pointer to the message buffer received from the socket connection
+ *
+ * Returns:
+ *  xml doc pointer if the operation is successful
+ *  NULL if the operation fails
+ *
+ * NOTE: This routine was copied from the example code provided by the LDOM Manager developer.
+ */
+xmlDocPtr
+handle_resp(char *resp_buf)
+{
+    xmlDocPtr       xml_output;
+    ldm_op_req_t    *req;
+    xml_msg_t       *xml_msg;
+    char * dptr;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: handle_resp(ENTER)\n");
+
+    req = (ldm_op_req_t *)resp_buf;
+    xml_msg = (xml_msg_t *)req->rq_data;
+
+
+    xml_output = xmlParseMemory((const char *)req->rq_data, req->rq_len);
+
+    if (xml_output == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: handle_resp.. xml output is NULL\n");
+    }
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: handle_resp(EXIT)\n");
+
+    return (xml_output);
+}
+
+/*
+ * send_xml_file_to_ldm
+ *
+ * This function sends an XML request to LDM and then receives the XML
+ * response.  It packages the XML response into an XML document so other
+ * code can search through it. 
+ *
+ * Input:
+ *  doc - xml doc to send to the LDOM Manager
+ * 
+ * Returns:
+ *  xml doc pointer of the response xml file received from the LDOM Manager 
+ *    if the operation is successful.
+ *  NULL if the operation fails
+ *
+ */
+xmlDocPtr
+send_xml_file_to_ldm(xmlDoc *doc)
+{
+    char      *pkt_buf;
+    char      *resp_buf;
+    char      *xml_buf;
+    int       status;
+    int       pkt_buf_len;
+    int       xml_buf_len;
+    int       ret;
+    int       sock;
+    xmlDoc    *doc_from_ldm;
+
+    /* connect to the ldom manager */
+    if (ldoms_debug) dprt("LDOMS_DEBUG: send_xml_file_to_ldm(ENTER)\n");
+    sock = open_ldm_connection();
+
+    if (sock == -1) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_xml_file_to_ldm.. error in opening socket connection\n");
+        return(NULL); 
+    }
+
+    (void) xmlDocDumpMemory(doc, (xmlChar **)&xml_buf, &xml_buf_len);
+
+    pkt_buf_len = ldm_create_pkt_buf(&pkt_buf, xml_buf, xml_buf_len);
+
+    status = send(sock, pkt_buf, pkt_buf_len, 0);
+    if (status == -1) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_xml_file_to_ldm.. error in send\n");
+        close_ldm_connection(sock);
+        return(NULL);
+    }
+
+    free(xml_buf);
+    free(pkt_buf);
+
+    if (get_response(sock, &resp_buf) == 0)
+        doc_from_ldm = handle_resp(resp_buf);
+    else {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_xml_file_to_ldm.. error in get_response\n");
+    close_ldm_connection(sock);
+        return(NULL);
+    }
+
+    free(resp_buf);
+
+    /* close the socket connection */
+    close_ldm_connection(sock);
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: send_xml_file_to_ldm(EXIT)\n");
+
+    return (doc_from_ldm);
+} /* send_xml_file_to_ldm() */
+
+/*
+ * ldm_create_pkt_buf
+ *
+ * This function creates a ldom operation request message buffer  with an XML
+ * character buffer array. This functions sets the appropriate protocol headers 
+ * for the protocol handshake with the LDOM Manager.
+ *
+ * Input:
+ *  xml_buf - pointer to the xml character buffer
+ *  xml_buf_len - length of the xml character buffer 
+ *
+ * Output:
+ *  pkt_buf - pointer to the message buffer to send to the socket connection 
+ *
+ * Returns:
+ *  buffer length for the message buffer 
+ *  
+ * NOTE: This routine was copied from the example code provided by the LDOM Manager developer.
+ *  Also see the create_pkt_buf() routine in xml_common.c from the LDOM Manager source code. 
+ */
+int
+ldm_create_pkt_buf(char **pkt_buf, char *xml_buf, int xml_buf_len)
+{
+    char            *temp_buf;
+    int i;
+    int             pkt_buf_len;
+    ldm_hdr_t       *hdr;
+    ldm_op_req_t    *req;
+    xml_msg_t       *xml_msg;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: create_pkt_buf(ENTER)\n");
+
+    pkt_buf_len = sizeof (ldm_hdr_t) + sizeof (ldm_op_req_t) + xml_buf_len;
+
+    *pkt_buf = malloc(pkt_buf_len);
+
+    /* set LDM protocol headers */
+    hdr = (ldm_hdr_t *)*pkt_buf;
+    hdr->msg_type = hton32(LDM_CNTRL_XML_REQ);
+    hdr->payload_len = hton32(sizeof (ldm_op_req_t) + xml_buf_len);
+
+    req = (ldm_op_req_t *)(*pkt_buf + sizeof (ldm_hdr_t));
+    req->rq_len = hton32(xml_buf_len);
+    req->rq_id = 1;
+
+    memcpy(req->rq_data, xml_buf, xml_buf_len);
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: create_pkt_buf(EXIT)\n");
+
+    return (pkt_buf_len);
+
+} /* ldm_create_pkt_buf() */
+
+
+/*
+ * get_ldominfo
+ *
+ * This function gets the ldom info such as the number of virtial cpu, memory and
+ * its unit, crypto, iobus and console port  for the given ldom by invoking routines 
+ * to create and send the "list-constraints" and "list-bindings" XML request to the 
+ * LDOM Manager and parse the response.
+ * 
+ * XML output from the LDOM Manager.
+ *
+ * Input:
+ *  ldom_name - name of the ldom to retrieve the ldom info
+ *  state     - State of the ldom
+ *   
+ * Output (pointers are used to pass information from this function to the caller):
+ *  num_cpu - pointer to the number of virtual cpu
+ *  mem_size - pointer to the virtual memory size
+ *  mem_unit - pointer to the virtual memory unit
+ *  num_crypto - pointer to the number of crypto unit
+ *  num_iobus - pointer to the number of io bus
+ *  console - pointer to the console port
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *  
+ */
+int
+get_ldominfo(char *ldom_name, int *num_cpu, int *mem_size, int *mem_unit, 
+        int *num_crypto, int *num_iobus, int *console, int state)
+{
+    xmlDocPtr    xml_output;
+    xmlDocPtr    xml_received;
+    xmlChar        *action = XML_LIST_CONST; 
+    xmlChar        *bindAction = XML_LIST_BIND; 
+    int        ret;
+
+    int        num_cpu_from_xml = 0;
+    int        mem_size_from_xml = 0;
+    int        mem_unit_from_xml = 0;
+    int        num_crypto_from_xml = 0;
+    int        num_iobus_from_xml = 0;
+    int        console_from_xml = 0;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo(ENTER) ldom_name=%s\n", ldom_name);
+
+    *num_cpu = 0;
+    *mem_size = 0;
+    *mem_unit = 0;
+    *num_crypto = 0;
+    *num_iobus = 0;
+    *console = 0;
+
+    /*
+     * The following "list-constraints" XML request will be created and sent to the LDOM Manager
+     *   NOTE: list-constraints will not get the Console port.  We have to
+     *            use list-bindings for that.
+     *
+     * if the input ldom name is 'primary':
+     *
+     * <?xml version="1.0"?>
+     * <LDM_interface version="1.0">
+     *  <cmd>
+     *  <action>list-constraints</action>
+     *  <data version="2.0">
+     *    <ldom>
+     *      <ldom_info>
+     *         <ldom_name>primary</ldom_name>
+     *      </ldom_info>
+     *    </ldom>
+     *  </data>
+     *  </cmd>
+     * </LDM_interface>
+     */
+    xml_output = create_xml_file_4_ldom_action(ldom_name, action);
+    if (xml_output == NULL) {
+            if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo.. failed to create xml file for ldom_name=%s action=%s\n",
+            ldom_name, action);
+        return (-1);
+    }    
+    
+    /* send XML file to the ldom manager */
+    xml_received = send_xml_file_to_ldm(xml_output);
+    if (xml_received == NULL) {
+            if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo.. failed to send xml file to ldm and receive xml back\n");
+            xmlFreeDoc(xml_output);
+        return (-1);
+    }
+
+    /*
+     * Example of the xml file received from the LDOM Manager:
+     *
+     * <?xml version="1.0"?>
+     * <LDM_interface version="1.0">
+     *  <cmd>
+     *    <action>list-constraints</action>
+     *    <data version="2.0">
+     *      <ldom>
+     *        <ldom_info>
+     *          <ldom_name>primary</ldom_name>
+     *        </ldom_info>
+     *        <cpu>
+     *          <number>4</number>
+     *        </cpu>
+     *        <mau>
+     *          <number>1</number>
+     *        </mau>
+     *        <memory>
+     *          <size>1G</size>
+     *        </memory>
+     * .....
+     */
+    /* parse the received XML file to get the ldom info */
+
+    /* 
+     * <response><status> will be failure if the ldom is not active or bound.
+     * then, use zero for num of cpu and mem size 
+     */
+    ret = parse_xml_get_ldominfo(xml_received, &num_cpu_from_xml, &mem_size_from_xml, 
+                    &mem_unit_from_xml, &num_crypto_from_xml, &num_iobus_from_xml);
+    if (ret == -1) {
+            if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo.. failed to parse xml file\n");
+        return (-1);
+    }
+
+    /* Update the return parms */
+    *num_cpu = num_cpu_from_xml;
+    *mem_size = mem_size_from_xml;
+    *mem_unit = mem_unit_from_xml;
+    *num_crypto = num_crypto_from_xml;
+    *num_iobus = num_iobus_from_xml;
+
+    /*
+     * Now we have to get the console port for each LDom.  This is done by
+     * sending a 'list-bindings' XML command.  So this means we can only
+     * send this request for domains that are bound or active.  You cannot
+     * do a list-bindings on an inactive domain.  If the domain is inactive,
+     * then the console port is set to 0.
+     *
+     * Example:
+     * If the input ldom name is 'primary', the XML request is:
+     *
+     * <?xml version="1.0"?>
+     * <LDM_interface version="1.0">
+     *  <cmd>
+     *  <action>list-bindings</action>
+     *  <data version="2.0">
+     *    <ldom>
+     *      <ldom_info>
+     *         <ldom_name>primary</ldom_name>
+     *      </ldom_info>
+     *    </ldom>
+     *  </data>
+     *  </cmd>
+     * </LDM_interface>
+     */
+
+    /* Domain state is inactive (3), so list-bindings is invalid */
+    if (state == LDOM_STATE_INACTIVE)
+        return (0);
+
+    xml_output = create_xml_file_4_ldom_action(ldom_name, bindAction);
+    if (xml_output == NULL) {
+            if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo.. failed to create xml file for ldom_name=%s action=%s\n",
+            ldom_name, action);
+        return (-1);
+    }    
+    
+    /* send XML file to the ldom manager */
+    xml_received = send_xml_file_to_ldm(xml_output);
+    if (xml_received == NULL) {
+            if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo.. failed to send xml file to ldm and receive xml back for Ldom %s, action %s\n", ldom_name, action);
+            xmlFreeDoc(xml_output);
+        return (-1);
+    }
+
+    /*
+     * Example of the xml file received from the LDOM Manager:
+     *
+     * <?xml version="1.0"?>
+     * <LDM_interface version="1.0">
+     *  <cmd>
+     *    <action>list-constraints</action>
+     *    <data version="2.0">
+     *    <ldom>
+     *      <ldom_info>
+     *        <ldom_name>ldom-126</ldom_name>
+     *        <mac_address>00:14:4f:f9:1a:7d</mac_address>
+     *      </ldom_info>
+     * .....
+     *      <console>
+     *        <service_name>primary-vcc0</service_name>
+     *        <port>5005</port>
+     *      </console>
+     * .....
+     *     </ldom>
+     *       <response>
+     *         <status>success</status>
+     *       </response>
+     *     </data>
+     *     <response>
+     *       <status>success</status>
+     *     </response>
+     *   </cmd>
+     *   <response>
+     *     <status>success</status>
+       *   </response>
+     * </LDM_interface>
+     */
+
+    /* parse the received XML file to get the ldom info */
+
+    ret = parse_xml_get_console(xml_received, &console_from_xml);
+    if (ret == -1) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo() failed to parse xml file for action %s\n", bindAction);
+        return (-1);
+    }
+    /* Update the return parms */
+    *console = console_from_xml;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldominfo(EXIT)\n");
+
+    return(0);
+}
+
+/*
+* get_ldom_names
+*
+* This function creates a list of all ldoms with the ldom name and state data
+* by invoking routines to create and send the "list-domain" XML request  
+* to the LDOM Manager and parse the response XML output from the LDOM Manager.
+*
+* For each LDom returned from the list-domain action, get_ldominfo() is called
+* to get the specific LDom info.
+*
+* Input:
+*   
+* Output (pointers are used to pass information from this function to the caller):
+*  ldom_cnt -  pointer to the number of ldoms in the ldom info list
+*  ldominfo_list - pointer to the list of pointers to the ldom info array 
+*
+* Returns:
+*  0 if the operation is successful
+*  -1 if the operation fails
+*  
+* NOTE: The following pictorial description explains the data structure used in
+*  this function to pass the ldom count and the list of pointers to the ldom info array. 
+*  The definition of the data structures is implemented in the ldm_xml_parse.h file.
+*  Most get_<data> routines in this file is using the similar data structures
+*  to pass the data.
+*
+*  +-------------+
+*  | num_ldoms   |   <--- *ldom_cnt = pointer to the integer that has the value of 
+*  +-------------+                    the number of ldoms 
+*
+*  +-------------+
+*  | ldom_list   + <--- ***ldominfo_list = pointer to the list of pointers to 
+*  +-------------+                         the ldom info array of type ldominfo_t
+*  of                                      which is defined in ldm_xml_parse.h file 
+*  ldom_list[0]
+*      |
+*      |     type ldominfo_t 
+*      |     +-------------+---------------+------------+
+*      |---> | ldom name   |   ldom state  |  ......    |
+*            +------------------------------------------+
+*
+*  ldom_list[1]
+*      |
+*      |     type ldominfo_t 
+*      |     +-------------+---------------+------------+
+*      |---> | ldom name   |   ldom state  |  ......    |
+*            +------------------------------------------+
+*
+*/
+int
+get_ldom_names(int *ldom_cnt, ldominfo_t  ***ldominfolist)
+{
+    ldominfo_t **ldom_list = NULL;
+    xmlDocPtr xml_to_send;
+    xmlDocPtr xml_received;
+    xmlNodePtr      root_node = NULL;
+    xmlNodePtr      cmd_node = NULL;
+    xmlNodePtr      data_node = NULL;
+    xmlNodePtr      ldom_node = NULL;
+    xmlNodePtr      name_node = NULL;
+    xmlNodePtr      subnode = NULL;
+    xmlChar         *ldom_name = NULL;
+    xmlChar         *action = XML_LIST; 
+
+    int num_ldoms = 0;
+    int i = 0, idx = 0;
+    int nameLen;
+    int ldomCpus, ldomMem, memUnit, ldomCrypto, ldomIO, ldomConsole;
+    char ldomName[NAME_SIZE];
+    char multChr;
+
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names(ENTER) i=%d\n",i);
+
+    /*
+     * This function can be called many times for a single Virt Mgr
+     * operation.  In order to not have to devise a grand scheme to
+     * determine when certain LDom info is valid or not, we will
+     * always free the existing structure and then generate new
+     * ones with current data from LDM.  This also allows us to
+     * have the latest data from LDM.
+     */
+    if (*ldominfolist != NULL ) {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names.. freeing ldominfolist\n");
+        for (i=0; i < *ldom_cnt; i++) {
+            free((*ldominfolist)[i]);
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names.. freed *ldominfolist[%d]\n",i);
+        }
+        free(*ldominfolist);
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names.. freed *ldominfolist\n");
+    }
+
+    /* Initialize return parameters */
+    *ldom_cnt = 0;
+    *ldominfolist = NULL;
+
+    /*
+     * The following "list-domain" XML request will be created and sent to the LDOM Manager:
+     *
+     * <?xml version="1.0"?>
+     * <LDM_interface version="1.0">
+     *  <cmd>
+     *  <action>list-domain</action>
+     *  <data version="2.0">
+     *  </data>
+     *  </cmd>
+     * </LDM_interface>
+     */
+    xml_to_send = create_xml_file_4_ldom_action(NULL, action);
+    if (xml_to_send == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. can not create list xml file\n");
+        return (-1);
+    }
+
+    xml_received  = send_xml_file_to_ldm(xml_to_send);
+    if (xml_received  == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. failed to send xml file to ldm and receive xml response\n");
+        xmlFreeDoc(xml_to_send);
+        return (-1);
+    }
+
+    /*
+     * Example of the xml file received from the LDOM Manager:
+     *
+     * <?xml version="1.0"?>
+     * <LDM_interface version="1.0">
+     *  <cmd>
+     *    <action>list-domain</action>
+     *    <data version="2.0">
+     *      <ldom>
+     *        <ldom_info>
+     *          <ldom_name>primary</ldom_name>
+     *          <state>active</state>
+     *        </ldom_info>
+     *      </ldom>
+     *      <response>
+     *        <status>success</status>
+     *      </response>
+     *    </data>
+     *    <response>
+     *      <status>success</status>
+     *    </response>
+     *  </cmd>
+     *  <response>
+     *    <status>success</status>
+     *  </response>
+     * </LDM_interface>
+     */
+
+    /* Get the total # of LDoms first */
+    if (parse_xml_get_ldom_cnt(xml_received, &num_ldoms)  == -1) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. failed to parse xml file for ldom cnt=%s\n", xml_received);
+        xmlFreeDoc(xml_to_send);
+        xmlFreeDoc(xml_received);
+        return (-1);
+    }
+
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names.. number of ldoms=%d \n", num_ldoms);
+
+    /* Allocate the memory to hold the info for each LDom */
+    if (num_ldoms > 0)
+        ldom_list = calloc(num_ldoms, sizeof(ldominfo_t *));
+
+    if (ldom_list == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. can't alloc memory for ldom_list\n");
+        xmlFreeDoc(xml_to_send);
+        xmlFreeDoc(xml_received);
+        return (-1);
+    }
+
+    /* Make sure mandantory XML tags are present before getting LDom data */
+    root_node = xmlDocGetRootElement(xml_received);
+    if (root_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. XML file does not have root node\n");
+        free(ldom_list);
+        xmlFreeDoc(xml_to_send);
+        xmlFreeDoc(xml_received);
+        return (-1);
+    }
+    cmd_node = xml_find_subnode(root_node, XML_CMD);
+    if (cmd_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. XML file does not have <cmd> tag\n");
+        free(ldom_list);
+        xmlFreeDoc(xml_to_send);
+        xmlFreeDoc(xml_received);
+        return (-1);
+    }
+
+    data_node = xml_find_subnode(cmd_node, XML_DATA);
+    if (data_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. XML file does not have <data> tag\n");
+        free(ldom_list);
+        xmlFreeDoc(xml_to_send);
+        xmlFreeDoc(xml_received);
+        return (-1);
+    }
+
+    /*
+     * The response XML has data for all LDoms and their state.  As we step thru
+     * the response for each LDom, we have to get more detailed info for the LDom,
+     * thus will send other XML requests for this data.
+     */
+    while (1) {
+
+        /* get the ldom node within the <data> tag */
+        ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+
+        
+        /* Need a <ldom> tag */
+        if (ldom_node != NULL) {
+            subnode = ldom_node->xmlChildrenNode;
+
+            while (subnode != NULL) {
+                /* Skip tags that are not element tags (tags with no data) */
+                if (subnode->type != XML_ELEMENT_NODE) {
+                    subnode = subnode->next;
+                    continue;
+                }
+
+                /* Look for <ldom_info> tag */
+                if (xmlStrcmp(subnode->name, (const xmlChar *)XML_LDM_INFO) == 0) {
+                    /* Need a <ldom_name> tag */
+                    name_node = xml_find_subnode(subnode, XML_LDM_NAME);
+
+                    /* We did not find a <ldom_name> tag. No work can be done without this */
+                    if (name_node == NULL) {
+                        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names.. XML file does not have <ldom_name> tag\n");
+                        xmlFreeDoc(xml_to_send);
+                        xmlFreeDoc(xml_received);
+                        /* Should free the ldominto_t and ldominfo_list memory also, but this should NEVER happen */
+                        return (-1);
+                    }
+
+                    /* Error checking needed here on ldom_name and ldom_list[idx] */
+                    if ((ldom_name = xmlNodeGetContent(name_node)) == NULL) {
+                        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names..xmlNodeGetContent() is NULL\n");
+                        subnode = subnode->next;
+                        continue;
+                    }
+
+                    if ((ldom_list[idx] = malloc(sizeof(ldominfo_t))) == NULL) {
+                        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names..malloc() failed for ldom_list[idx]\n");
+                        subnode = subnode->next;
+                        xmlFree(ldom_name);
+                        continue;
+                    }
+
+                    /* Save the LDom name and state */
+                    strlcpy(ldom_list[idx]->ldomName,  (char *)ldom_name, sizeof (ldom_list[idx]->ldomName));
+                    ldom_list[idx]->ldomState = parse_xml_get_ldom_state(subnode);
+                    xmlFree(ldom_name);
+
+                    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names..ldom name:state=%s:%d; ldom_list[%d]=%u\n",
+                        ldom_list[idx]->ldomName, ldom_list[idx]->ldomState,idx,ldom_list[idx]);
+
+                    /* Now we need to get some specific data about the domain */
+                    if (get_ldominfo(ldom_list[idx]->ldomName, &ldomCpus, 
+                                &ldomMem, &memUnit, &ldomCrypto, &ldomIO,
+                                &ldomConsole, ldom_list[idx]->ldomState) >= 0)
+                    {
+                        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names..get_ldominfo() cpus=%d, mem=%d, unit=%d, mau=%d, io=%d, console=%d\n",
+                            ldomCpus, ldomMem, memUnit, ldomCrypto, ldomIO, ldomConsole);
+
+                        /* The VMM GUI displays the memory in KB, so we need to convert to KB */
+                        switch (memUnit) {
+                        case LDOMMEMUNIT_KILOBYTES: break;                            /* KB already */
+                        case LDOMMEMUNIT_MEGABYTES: ldomMem *= 1024; break;            /* MB */
+                        case LDOMMEMUNIT_GIGABYTES: ldomMem *= (1024 * 1024); break;/* GB */
+                        case LDOMMEMUNIT_BYTES: ldomMem /= 1024; break;            /* Bytes */
+                        }
+                        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names..get_ldominfo() mem=%d\n",ldomMem);
+
+                        /* Now put the LDom into into the current list */
+                        ldom_list[idx]->ldomNumVCpu = ldomCpus;
+                        ldom_list[idx]->ldomMemSize = ldomMem;
+                        ldom_list[idx]->ldomMemUnit = memUnit;
+                        ldom_list[idx]->ldomNumCrypto  = ldomCrypto;
+                        ldom_list[idx]->ldomNumIOBus = ldomIO;
+                        ldom_list[idx]->ldomConsole = ldomConsole;
+
+                        /* Create the UUID for this domain/index.  We want to keep the
+                         * UUID constant, no matter how many domains are addeded or
+                         * or deleted, so we will use the integer values for each
+                         * char in the domain name in the calculation.
+                         */
+                        strcpy(ldomName, ldom_list[idx]->ldomName);
+                        nameLen = strlen(ldom_list[idx]->ldomName);
+                        for (i = 0 ; i < VIR_UUID_BUFLEN ; i++) {
+                            if (i < nameLen)
+                                multChr = ldomName[i];
+
+                            ldom_list[idx]->uuid[i] = ((i+1) * (76 + multChr))%255;
+                        }
+                    }
+                    else {
+                        /* Now put the LDom into into the current list */
+                        ldom_list[idx]->ldomNumVCpu = 0;;
+                        ldom_list[idx]->ldomMemSize = 0;
+                        ldom_list[idx]->ldomMemUnit = 4;
+                        ldom_list[idx]->ldomNumCrypto  = 0;
+                        ldom_list[idx]->ldomNumIOBus = 0;
+                        ldom_list[idx]->ldomConsole = 0;
+                        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names() get_ldominfo() failed\n");
+                        strcpy(ldomName, ldom_list[idx]->ldomName);
+                        nameLen = strlen(ldom_list[idx]->ldomName);
+                        for (i = 0 ; i < VIR_UUID_BUFLEN ; i++) {
+                            if (i < nameLen)
+                                multChr = ldomName[i];
+
+                            ldom_list[idx]->uuid[i] = ((i+1) * (76 + multChr))%255;
+                        }
+                    }
+
+                    idx++;
+                    subnode = subnode->next;
+                    continue;
+                }
+                subnode = subnode->next;
+            }
+        }
+
+        /* 
+         * xml response for list-domain has <data> tags for each ldom info 
+         * so, get the next data section
+         */
+        data_node = xml_get_next_ele_node(data_node);
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names..looking for next <data> node\n");
+
+        if (data_node == NULL)
+            break;
+    }
+
+    *ldom_cnt = num_ldoms;
+    *ldominfolist = ldom_list;
+    for (i=0; i<*ldom_cnt; i++)
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names: ldom_list[%d]=%d\n",i,ldom_list[i]);
+    
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names: ldominfolist=%u\n",ldominfolist);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names: *ldominfolist=%u\n",*ldominfolist);
+    for (i=0; i<*ldom_cnt; i++)
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_names: (*ldominfolist)[%d]=%u\n",i,(*ldominfolist)[i]);
+
+    xmlFreeDoc(xml_to_send);
+    xmlFreeDoc(xml_received);
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_names(EXIT) ldom_cnt=%d\n",*ldom_cnt);
+
+    return (0);
+} /* get_ldom_names() */
+
+/*
+ * send_ldom_set_vcpu
+ *
+ * This function sends an LDom XML xxxxxx request to the LDM to change the
+ * number of virtual cpus for the input domain.
+ *
+ * Input:
+ *  ldom_name - name of the ldom to start or stop
+ *  nvcpus - The new number of virtual cpus for the domain
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *
+ */
+int
+send_ldom_set_vcpu(char *ldom_name, int nvcpus)
+{
+    xmlDocPtr       xml_output;
+    xmlDocPtr       xml_received;
+    xmlChar         *action;
+    int             ret;
+    xmlNodePtr      root_node = NULL;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_vcpu(ENTER): ldom_name=%s, nvcpus=%d\n", ldom_name, nvcpus);
+
+    /* create XML file to send request to the ldom manager */
+    xml_output = create_xml_file_4_set_vcpu(ldom_name, nvcpus);
+    if (xml_output == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_vcpu.. failed to create xml file for set vcpus\n");
+        return (-1);
+    }
+
+    /* send XML file to the LDM */
+    xml_received = send_xml_file_to_ldm(xml_output);
+    if (xml_received == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_vcpu.. failed to send xml file to ldm and receive xml back\n");
+        xmlFreeDoc(xml_output);
+        return (-1);
+    }
+
+    /* check the response status */
+    root_node = xmlDocGetRootElement(xml_received);
+    if (root_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_vcpu.. XML file does not have root node\n");
+        xmlFreeDoc(xml_output);
+        xmlFreeDoc(xml_received);
+        return(-1);
+    }
+
+    if (parse_xml_get_response_status(root_node) == -1) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_vcpu.. failure response from received xml\n");
+        xmlFreeDoc(xml_output);
+        xmlFreeDoc(xml_received);
+        return(-1);
+    }
+
+    /* cleanup */
+    xmlFreeDoc(xml_output);
+    xmlFreeDoc(xml_received);
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_vcpu(EXIT)\n");
+    return(0);
+}
+
+/*
+ * send_ldom_set_memory
+ *
+ * This function sends an LDom XML set-memory request to the LDM to change the
+ * virtual memory for the input domain. The value of memory is in KB.
+ *
+ * Input:
+ *  ldom_name - name of the ldom to change the memory 
+ *  memory - The new memory for the domain
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *
+ */
+int
+send_ldom_set_memory(char *ldom_name, unsigned long memory)
+{
+    xmlDocPtr       xml_output;
+    xmlDocPtr       xml_received;
+    xmlChar         *action;
+    int             ret;
+    xmlNodePtr      root_node = NULL;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_memory(ENTER): ldom_name=%s, memory=%lu\n", ldom_name, memory);
+
+    /* create XML file to send request to the ldom manager */
+    xml_output = create_xml_file_4_set_memory(ldom_name, memory);
+    if (xml_output == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_memory.. failed to create xml file for set memory\n");
+        return (-1);
+    }
+
+    /* send XML file to the LDM */
+    xml_received = send_xml_file_to_ldm(xml_output);
+    if (xml_received == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_memory.. failed to send xml file to ldm and receive xml back\n");
+        xmlFreeDoc(xml_output);
+        return (-1);
+    }
+
+    /* check the response status */
+    root_node = xmlDocGetRootElement(xml_received);
+    if (root_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_memory.. XML file does not have root node\n");
+        xmlFreeDoc(xml_output);
+        xmlFreeDoc(xml_received);
+        return(-1);
+    }
+
+    if (parse_xml_get_response_status(root_node) == -1) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_memory.. failure response from received xml\n");
+        xmlFreeDoc(xml_output);
+        xmlFreeDoc(xml_received);
+        return(-1);
+    }
+
+    /* cleanup */
+    xmlFreeDoc(xml_output);
+    xmlFreeDoc(xml_received);
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_set_memory(EXIT)\n");
+    return(0);
+}
+
+/*
+ * send_ldom_create_domain
+ *
+ * This function sends an LDom lifecycle action to the LDM to create a
+ * domain.  The new domain will be left in either the inactive or bound
+ * state.  The domain is created from the definition of an input XML file.
+ * The structure of the XML file is that of 'ldm list-constraints -x <ldom>'
+ *
+ * Input:
+ *  xml - A char buffer of the input xml file (This is not an xmlDocPtr yet)
+ *  action - The Lifecycle action to perform after domain creation
+ *
+ * Returns:
+ *  Ptr to the Domain name if the operation is successful
+ *  NULL - if the operation fails
+ *
+ */
+char *
+send_ldom_create_domain(char *xml, xmlChar *action)
+{
+    xmlDocPtr    xml_request;
+    xmlDocPtr    xml_response;
+    xmlNodePtr    root_node = NULL;
+    int        ret;
+    char        *ldomName;
+    char        *filerc;
+    char        fname[64];
+    char        xmlBuf[256];
+    char        tags[64];
+    char        *newXml,*modXml;
+    time_t        timesecs;
+    FILE        *fptr;
+    size_t        fwrc;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain(ENTER)\n");
+
+    /*
+     * The input XML char buffer should be the output of list-constrtains -x
+     * It can be modified for the constraints, but will not have the
+     * <cmd> or <action> tags.  These tags have to be added to that XML
+     * file before sending it to LDM.
+     *
+     * The input XML char buffer is written to a file, then that file is read
+     * one line at a time so we can determine when to insert the new tags.
+     * The lines read in are accumulated in memory in a char buffer, that
+     * will get converted into an XmlDoc.
+     */
+
+    /* Create a unique file name for the temp file */
+    timesecs = time(NULL);
+    sprintf(fname,"/tmp/xmlfile-%d",timesecs);
+
+    /* Write the XML char buffer to the file */
+    fptr = fopen(fname, "w");
+        if (fptr == NULL) {
+        ldomsError(NULL, NULL, VIR_ERR_OPEN_FAILED, fname, VIR_ERR_ERROR);
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain() fopen(%s) for write failed\n", fname);
+                return(NULL);
+        }
+        fwrc = fwrite(xml, strlen(xml), 1, fptr);
+        fclose(fptr);
+
+    /* Read in the XML file and insert the <cmd> and <action> tags */
+    fptr = fopen(fname, "r");
+        if (fptr == NULL) {
+        ldomsError(NULL, NULL, VIR_ERR_READ_FAILED, fname, VIR_ERR_ERROR);
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain() fopen(%s) for read failed\n", fname);
+                return(NULL);
+        }
+
+    /* Can't malloc the space for the XML doc + new tags */
+    if (!(modXml = malloc(strlen(xml) + 128))) {
+        ldomsError(NULL, NULL, VIR_ERR_NO_MEMORY, (char*)action, VIR_ERR_ERROR);
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain() malloc failed\n", fname);
+        fclose(fptr);
+        remove(fname);
+        return(NULL);
+    }
+    /* Save the poiner to the beginning of the in memory XML doc */
+    bzero(modXml, strlen(xml) + 128);
+    newXml = modXml;
+
+    /* Get the 1st line of the XML file */
+        filerc = fgets(xmlBuf, sizeof(xmlBuf), fptr);
+
+    /* Read in the XML file, appending to the in memory XML */
+        while (filerc != NULL) {
+                memcpy(modXml, xmlBuf, strlen(xmlBuf));
+        modXml = modXml + strlen(xmlBuf);
+
+        /* The 1st set of tags, <cmd><action>, go after <LDM_interface> */
+                if (strstr(xmlBuf, (char*)XML_LDM_INTERFACE) != NULL) {
+            sprintf(tags, "<%s><%s>%s</%s>", 
+                XML_CMD, XML_ACTION, action, XML_ACTION);
+                        memcpy(modXml, tags, strlen(tags));
+            modXml = modXml + strlen(tags);
+
+                        filerc = fgets(xmlBuf, sizeof(xmlBuf), fptr);
+            /* Go to another while loop to find the end tags */
+                        break;
+                }
+                filerc = fgets(xmlBuf, sizeof(xmlBuf), fptr);
+        }
+
+    /* Finish reading and appending until the end tag is found so we can add </cmd> */
+        while (filerc != NULL) {
+        /* </cmd> goes before </LDM_interface> */
+                if (strstr(xmlBuf, (char*)XML_LDM_INTERFACE) != NULL) {
+            sprintf(tags, "</%s>", XML_CMD);
+                        memcpy(modXml, tags, strlen(tags));
+            modXml = modXml + strlen(tags);
+                }
+        memcpy(modXml, xmlBuf, strlen(xmlBuf));
+        modXml = modXml + strlen(xmlBuf);
+                filerc = fgets(xmlBuf, sizeof(xmlBuf), fptr);
+        }
+        fclose(fptr);
+    modXml++; *modXml = '\0';
+
+    /* create XML file to send request to the ldom manager */
+    xml_request = xmlReadDoc((const xmlChar *) newXml, NULL, NULL, 0);
+
+    if (xml_request == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain(EXIT) Failed to create xml file \n");
+        remove(fname);
+        return (NULL);
+    }
+
+    /* send XML file to the LDM */
+    xml_response = send_xml_file_to_ldm(xml_request);
+    if (xml_response == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain(EXIT) Failed to send xml file to ldm and receive xml back\n");
+        xmlFreeDoc(xml_request);
+        remove(fname);
+        return (NULL);
+    }
+
+    /* Check the response status to make the the request was successful.
+     * An invalid request can return an XML document.
+     */
+    root_node = xmlDocGetRootElement(xml_response);
+    if (root_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain.. XML file does not have root node\n");
+        xmlFreeDoc(xml_request);
+        xmlFreeDoc(xml_response);
+        remove(fname);
+        return(NULL);
+    }
+
+    if (parse_xml_get_response_status(root_node) == -1) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain(EXIT) Failure response from received xml\n");
+        xmlFreeDoc(xml_request);
+        xmlFreeDoc(xml_response);
+        remove(fname);
+        return(NULL);
+    }
+
+    /* Get the Domain name from the request */
+    ldomName = parse_xml_get_ldom_name(xmlDocGetRootElement(xml_request));
+    
+    /* cleanup */
+    xmlFreeDoc(xml_request);
+    xmlFreeDoc(xml_response);
+    remove(fname);
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_create_domain(EXIT)\n");
+
+    return(ldomName);
+}
+
+/*
+ * send_ldom_lifecycle_action
+ *
+ * This function sends an LDom lifecycle action to the LDM to change the state
+ * of an LDom.  Valid actions are: start-domain,  stop-domain, bind-domain,
+ * unbind-domain, destroy-domain.
+ *
+ * Input:
+ *  ldom_name - name of the ldom to start or stop
+ *  ldom_action - Life cycle action.  See ldoms_common.h
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *
+ */
+int
+send_ldom_lifecycle_action(char *ldom_name, int ldom_action)
+{
+    xmlDocPtr       xml_output;
+    xmlDocPtr       xml_received;
+    xmlChar         *action;
+    int             ret;
+    xmlNodePtr      root_node = NULL;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_lifecycle_action(ENTER): ldom_name=%s, action=%d\n", ldom_name, ldom_action);
+
+    if (ldom_action == LDOM_START)
+        action = XML_START_DOMAIN;
+    else if (ldom_action == LDOM_STOP)
+        action = XML_STOP;
+    else if (ldom_action == LDOM_BIND)
+        action = XML_BIND_DOMAIN;
+    else if (ldom_action == LDOM_UNBIND)
+        action = XML_UNBIND;
+    else if (ldom_action == LDOM_DELETE)
+        action = XML_DELETE;
+    else {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_lifecycle_action(EXIT): unsupported lifecycle action %d\n",ldom_action);
+        return(-1);
+    }
+
+    /* create XML file to send request to the ldom manager */
+    xml_output = create_xml_file_4_ldom_action(ldom_name, action);
+    if (xml_output == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_active_mgmt.. failed to create xml file for ldom_name=%s action=%s\n",
+                    ldom_name, action);
+        return (-1);
+    }
+
+    /* send XML file to the LDM */
+    xml_received = send_xml_file_to_ldm(xml_output);
+    if (xml_received == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_active_mgmt.. failed to send xml file to ldm and receive xml back\n");
+        xmlFreeDoc(xml_output);
+        return (-1);
+    }
+
+    /* check the response status */
+    root_node = xmlDocGetRootElement(xml_received);
+    if (root_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_active_mgmt.. XML file does not have root node\n");
+        xmlFreeDoc(xml_output);
+        xmlFreeDoc(xml_received);
+        return(-1);
+    }
+
+    if (parse_xml_get_response_status(root_node) == -1) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_active_mgmt.. failure response from received xml\n");
+        xmlFreeDoc(xml_output);
+        xmlFreeDoc(xml_received);
+        return(-1);
+    }
+
+    /* cleanup */
+    xmlFreeDoc(xml_output);
+    xmlFreeDoc(xml_received);
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: send_ldom_lifecycle_action(EXIT)\n");
+
+    return(0);
+}
+
+
+/*
+ * get_ldom_rsc_pool
+ *
+ * This function gets the resource pool info such as the CPU and memory
+ * capacity or reserved data by invoking routines to create and send
+ * the "list-devices" (for capacity data) or "list-bindings" (for reserved data)
+ * XML requests to the LDOM Manager and parse the response XML output from the LDOM Manager.
+ *
+ * Input:
+ *  resource - indicates which resource to retrieve the resource pool data
+ *             CPU_RP=CPU resource pool
+ *             MEM_RP = memory resource pool
+ *  rp_type - indicates either capacity or reserved
+ *             RP_CAPACITY = capacity resource
+ *             RP_RESERVED = reserved resource
+ *
+ * Output (pointers are used to pass information from this function to the caller):
+ *  rp_qty - pointer to the integer for the resource pool quantity
+ *  unit - pointer to the allocation unit for CPU or memory resources
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *
+ */
+int
+get_ldom_rsc_pool(int resource, int rp_type, ulong_t *rp_qty, int *unit)
+{
+    xmlDocPtr       xml_output;
+    xmlDocPtr       xml_received;
+    xmlChar         *action;
+    int             ret;
+
+    ulong_t         rp_qty_from_xml = 0;
+    int             unit_from_xml = 1;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_rsc_pool (ENTER)\n");
+
+    *rp_qty = 0;
+    *unit = 0;
+
+    /* use list-devices for capacity and list-bindings for reserved resources */
+    if (rp_type == RP_CAPACITY)
+        action = XML_LIST_DEVICES;
+    else
+        action = XML_LIST_BIND;
+
+    /* create XML file to send request to the ldom manager */
+    xml_output = create_xml_file_4_ldom_action(NULL, action);
+    if (xml_output == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_rsc_pool.. failed to create xml file for action=%s\n",
+            action);
+        return (-1);
+    }
+
+    /* send XML file to the ldom manager */
+    xml_received = send_xml_file_to_ldm(xml_output);
+    if (xml_received == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_rsc_pool.. failed to send xml file to ldm and receive xml back\n");
+        xmlFreeDoc(xml_output);
+        return (-1);
+    }
+
+    switch (resource) {
+    case CPU_RP:
+        /* parse the received XML file to get the cpu resource rp_qty info */
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_rsc_pool.. trying to parse for cpu resource\n");
+        if (rp_type == RP_CAPACITY) {
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_rsc_pool.. trying to parse for capacity value\n");
+            ret = parse_xml_get_cpu_rp(xml_received, rp_type,  &rp_qty_from_xml, &unit_from_xml);
+        }
+        else {
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_rsc_pool.. trying to parse for reserved value\n");
+            ret = parse_xml_get_cpu_rp(xml_received, rp_type, &rp_qty_from_xml, &unit_from_xml);
+        }
+        break;
+    case MEM_RP:
+        /* parse the received XML file to get the memory resource rp_qty info */
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_rsc_pool.. trying to parse for memory resource\n");
+        if (rp_type == RP_CAPACITY) {
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_rsc_pool.. trying to parse for capacity value\n");
+            ret = parse_xml_get_mem_rp(xml_received, rp_type, &rp_qty_from_xml, &unit_from_xml);
+        }
+        else {
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_rsc_pool.. trying to parse for reserved value\n");
+            ret = parse_xml_get_mem_rp(xml_received, rp_type, &rp_qty_from_xml, &unit_from_xml);
+        }
+        break;
+        default:
+            if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_rsc_pool.. unsupported resource\n");
+    }
+
+    if (ret == -1) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_rsc_pool.. failed to parse xml file\n");
+        return (-1);
+    }
+
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_rsc_pool. rp_qty=%d unit=%d\n", rp_qty_from_xml, unit_from_xml);
+
+    *rp_qty = rp_qty_from_xml;
+    *unit = unit_from_xml;
+
+    /* cleanup */
+    xmlFreeDoc(xml_output);
+    xmlFreeDoc(xml_received);
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_rsc_pool (EXIT)\n");
+
+    return(0);
+} /* get_ldom_rsc_pool */
+
+/*
+ * get_ldom_cpu_bindings
+ *
+ * This function gets the cpu bindings for the input domain.
+ * The CPU binding info is put into the input cpuBinding structure.
+ * The processing of this data is handeled by the calling routine.
+
+ * Input:
+ *  domain - The domain name
+ *  cpuBindings - Pointer to a structure to place CPU binding info
+ *
+ * Output:
+ *  cpuBindings - Updated structure content with CPU binding info
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *
+ */
+int
+get_ldom_cpu_bindings(char *domain, cpuBindings_t **cpuBindings)
+{
+    xmlDocPtr       xml_output;
+    xmlDocPtr       xml_received;
+    xmlChar         *action;
+    int             ret;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_cpu_bindings (ENTER)\n");
+
+    action = XML_LIST_BIND;
+
+    /* create XML file to send request to the ldom manager */
+    xml_output = create_xml_file_4_ldom_action(domain, action);
+    if (xml_output == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_cpu_bindings.. failed to create xml file for action=%s\n",action);
+        return (-1);
+    }
+
+    /* send XML file to the ldom manager */
+    xml_received = send_xml_file_to_ldm(xml_output);
+    if (xml_received == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_cpu_bindings.... failed to send xml file to ldm and receive xml back\n");
+        xmlFreeDoc(xml_output);
+        return (-1);
+    }
+
+    ret = parse_xml_get_cpu_bindings(xml_received, cpuBindings);
+
+    if (ret < 0) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_cpu_bindings...... failed to parse xml file\n");
+        return (ret);
+    }
+
+    /* cleanup */
+    xmlFreeDoc(xml_output);
+    xmlFreeDoc(xml_received);
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_cpu_bindings(EXIT)\n");
+
+    return(ret);
+} /* get_ldom_cpu_bindings */
+
+/*
+ * get_free_memory
+ * 
+ * This function gets the amount of unused (free) memory in the LDoms system, by
+ * invoking get_ldom_rsc_pool() routine that sends the "list-devices" XML request
+ * to the ldom manager.
+ * The memory amount is converted to KBytes.
+ * 
+ * Input:
+ *
+ * Output (pointer is used to pass information from this function to the caller):
+ *  maxmem - pointer to the maximum amount of memory allowed  (in KB) 
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *
+ */
+int
+get_free_memory(unsigned long *maxmem)
+{
+    int ret;
+    ulong_t capacity = 0;
+    int memunit = LDOMMEMUNIT_KILOBYTES;
+
+    unsigned long mem;    
+
+    int resource = MEM_RP;
+    int rp_type = RP_CAPACITY;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_free_memory(ENTER) \n");
+
+    *maxmem = 0;
+
+    ret = get_ldom_rsc_pool(resource, rp_type, &capacity, &memunit);
+
+    if (ret == -1) 
+       if (ldoms_debug) dprt("LDOMS_DEBUG: get_free_memory... get_ldom_rsc_pool failed\n");
+    else
+       if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_free_memory.. capacity=%d memunit=%d\n", capacity, memunit);
+
+    /* convert the memory value to KBytes */ 
+    switch (memunit) {
+    case LDOMMEMUNIT_KILOBYTES: break;                     /* KB already */
+    case LDOMMEMUNIT_MEGABYTES: capacity *= 1024; break;        /* MB */
+    case LDOMMEMUNIT_GIGABYTES: capacity *= (1024 * 1024); break;    /* GB */
+    case LDOMMEMUNIT_BYTES: capacity /= 1024; break;        /* Bytes */
+    }
+
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_free_memory.. Free memory = %dKB\n", capacity);
+
+    mem = capacity;
+
+    *maxmem  = mem;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_free_memory(EXIT).. Maximum Free memory = %dKB\n", mem);
+ 
+    return(ret);
+
+} /* get_free_memory */
+
+ 
+/*
+ * get_ldom_total_memory
+ * 
+ * This function retrieves the total amount of memory on the system from LDM by
+ * invoking get_ldom_rsc_pool() calls to send the "list-devices" (for free 
+ * resource) and "list-bindings" (for bound resource) to the ldom manager
+ * and adds up the free and bound memory amount for all domains.
+ * This function converts the memory to KBytes.
+ * 
+ * Input:
+ *
+ * Output (pointer is used to pass information from this function to the caller):
+ *  total_mem - pointer to the total amount of memory (in KB) 
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *
+ */
+int
+get_ldom_total_memory(unsigned long *total_mem)
+{
+    int ret;
+    ulong_t capacity = 0;
+    ulong_t reserved = 0;
+    int memunit = LDOMMEMUNIT_KILOBYTES;
+
+    unsigned long mem;    
+
+    int resource = MEM_RP;
+    int rp_type = RP_CAPACITY;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_memory(ENTER) \n");
+
+    *total_mem = 0;
+
+    /* first, get the amount of free memory by using the RP_CAPACITY type
+     * that sends the list-devices request */
+    ret = get_ldom_rsc_pool(resource, rp_type, &capacity, &memunit);
+
+    if (ret == -1) 
+       if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_memory... get_ldom_rsc_pool failed with RP_CAPACITY\n");
+    else
+       if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_total_memory.. capacity=%d memunit=%d\n", capacity, memunit);
+
+    /* convert the memory value to KBytes */ 
+    switch (memunit) {
+    case LDOMMEMUNIT_KILOBYTES: break;                    /* KB already */
+    case LDOMMEMUNIT_MEGABYTES: capacity *= 1024; break;        /* MB */
+    case LDOMMEMUNIT_GIGABYTES: capacity *= (1024 * 1024); break;    /* GB */
+    case LDOMMEMUNIT_BYTES: capacity /= 1024; break;        /* Bytes */
+    }
+
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_total_memory.. Free memory = %dKB\n", capacity);
+
+    mem = capacity; 
+
+    /* Set the global var for the Free memory in KB */
+    ldomsFreeMem = mem;
+
+    /* now, get the amount of bound memory by using the RP_RESERVED type
+     * that send the list-bindings request */
+    rp_type = RP_RESERVED;
+    ret = get_ldom_rsc_pool(resource, rp_type, &reserved, &memunit);
+
+    if (ret == -1) 
+        if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_memory... get_ldom_rsc_pool failed with RP_RESERVED\n");
+    else
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_total_memory.. reserved=%d memunit=%d\n", reserved, memunit);
+
+    /* convert the memory value to KBytes */ 
+    switch (memunit) {
+    case LDOMMEMUNIT_KILOBYTES: break;                    /* KB already */
+    case LDOMMEMUNIT_MEGABYTES: reserved *= 1024; break;        /* MB */
+    case LDOMMEMUNIT_GIGABYTES: reserved *= (1024 * 1024); break;    /* GB */
+    case LDOMMEMUNIT_BYTES: reserved /= 1024; break;        /* Bytes */
+    }
+
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_total_memory.. Used memory = %dKB\n", reserved);
+
+    /* add up the amount of bound memory to the free memory */
+    mem += reserved; 
+
+    /* Set the global var for the Used memory in KB */
+    ldomsUsedMem = reserved;
+
+    *total_mem  = mem;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_memory(EXIT):  total memory in KB=%d\n", mem);
+ 
+    return(ret);
+
+} /* get_ldom_total_memory */
+
+ 
+/*
+ * get_ldom_total_cpu
+ * 
+ * This function retrieves the total number of CPUs on the system from LDM by
+ * invoking get_ldom_rsc_pool() calls to send the "list-devices" (for free 
+ * resource) and "list-bindings" (for bound resource) to the ldom manager
+ * and adds up the free and bound CPUs for all domains.
+ * 
+ * Input:
+ *
+ * Output (pointer is used to pass information from this function to the caller):
+ *  total_cpu - pointer to the total number of CPUs 
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *
+ */
+int
+get_ldom_total_cpu(int *total_cpu)
+{
+    int ret;
+    ulong_t capacity = 0;
+    ulong_t reserved = 0;
+    int unit = 1;
+
+    int tcpu;
+
+    int resource = CPU_RP;
+    int rp_type = RP_CAPACITY;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_cpu(ENTER) \n");
+
+    *total_cpu = 0;
+
+    /* first, get the number of free CPUs by using the RP_CAPACITY type
+     * that sends the list-devices request */
+    ret = get_ldom_rsc_pool(resource, rp_type, &capacity, &unit);
+
+    if (ret == -1) 
+       if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_cpu... get_ldom_rsc_pool failed with RP_CAPACITY\n");
+    else
+       if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_total_cpu.. capacity(free CPUs)=%d \n", capacity);
+
+    tcpu = capacity;
+
+    /* Set the global var for the Free CPUs */
+    ldomsFreeCpu = capacity;
+
+    /* now, get the number of bound CPUs by using the RP_RESERVED type
+     * that send the list-bindings request */
+    rp_type = RP_RESERVED;
+    ret = get_ldom_rsc_pool(resource, rp_type, &reserved, &unit);
+
+    if (ret == -1) 
+       if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_cpu... get_ldom_rsc_pool failed with RP_RESERVED\n");
+    else
+       if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: get_ldom_total_cpu.. reserved(bound CPUs)=%d\n", reserved);
+
+    /* add up the amount of bound memory to the free memory */
+    tcpu += reserved; 
+
+    /* Set the global var for the Used CPUs */
+    ldomsUsedCpu = reserved;
+
+    *total_cpu  = tcpu;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: get_ldom_total_cpu(EXIT): total_cpu=%d\n", tcpu);
+ 
+    return(ret);
+
+} /* get_ldom_total_cpu */
+ 
+#endif /* WITH_LDOMS */
+
+/*
+ * vim: set tabstop=4:
+ * vim: set shiftwidth=4:
+ * vim: set expandtab:
+ */
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
+
diff --git a/src/ldoms_xml_parse.h b/src/ldoms_xml_parse.h
new file mode 100644
--- /dev/null
+++ b/src/ldoms_xml_parse.h
@@ -0,0 +1,212 @@
+/*
+ * ldoms_xml_parse.h: data structure to be used in the LDoms XML parsing.
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ */
+
+#ifndef	__VIR_LDOMS_XML_PARSE_H__
+#define	__VIR_LDOMS_XML_PARSE_H__
+
+#ifdef WITH_LDOMS
+
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include "libvirt/libvirt.h"
+#include "ldoms_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* data structures that parsing code will populate */
+typedef struct ldominfo {
+	ulong_t		index;
+	char		ldomName[NAME_SIZE];  /* ldom name */
+	uint_t		ldomState;	  /* admin state */
+	ulong_t		ldomNumVCpu;	/* number of VCpu */
+	ulong_t		ldomMemSize;	/* virtual memory size */
+	uint_t		ldomMemUnit;	/* unit of memory */
+	ulong_t		ldomNumCrypto;  /* number of crypto */
+	ulong_t		ldomNumIOBus;   /* number of IO bus */
+	int		ldomConsole;	/* console port */
+	unsigned char   uuid[VIR_UUID_BUFLEN];
+} ldominfo_t;
+
+typedef struct vcpu_s {
+	ulong_t		 index;
+	ulong_t	         vcpuLdomIndex;		   /* index to ldom table */
+	char		 vcpuDeviceID[NAME_SIZE];  /* virtual CPU Device ID */
+	uint_t		 vcpuOperationalStatus;    /* vcpu status */
+	char		 vcpuPhysBind[NAME_SIZE];  /* physical binding */
+	ulong_t		 vcpuPhysBindUsage;	   /* physical bind usage */
+} vcpu_t;
+
+typedef struct vmem_data_s {
+	ulong_t		 index;
+	ulong_t		 vmemLdomIndex;	        /* index to ldom table */
+	ulong_t		 vmemNumberOfBlocks;	/* number of vmem blocks */ 
+} vmem_data_t;
+
+typedef struct vmem_physbind_s {
+	ulong_t		 index;
+	ulong_t		 vmemLdomIndex;		   /* index to ldom table */
+	char		 vmemPhysBind[NAME_SIZE];  /* memory block binding */ 
+} vmem_physbind_t;
+
+typedef struct vsw_s {
+	ulong_t		 index;
+	ulong_t		 vswLdomIndex;		    /* index to ldom table */
+	char		 vswServiceName[NAME_SIZE]; /* vsw service name */
+	char		 vswMacAddress[NAME_SIZE];  /* vsw mac address */
+	char		 vswPhysDevPath[NAME_SIZE]; /* vsw physical dev path */
+	uint_t		 vswMode;		    /* vsw mode */
+	char		 vswLdomName[NAME_SIZE];    /* ldom name - used to index to ldom table */
+} vsw_t;
+
+typedef struct vsw_name_s {
+	char	 	ServiceName[NAME_SIZE];	/* vsw service name */
+} vsw_name_t;
+
+typedef struct vnet_s {
+	ulong_t		 index;
+	ulong_t		 vnetLdomIndex;		 /* index to ldom table */
+	ulong_t		 vnetVswIndex;		 /* index to vsw table */
+	char        	 vnetDevName[NAME_SIZE];	/* vnet dev name */
+	char		 vnetDevMacAddress[NAME_SIZE];  /* vnet dev mac address */
+	char		 vnetServiceName[NAME_SIZE];    /* vsw service name - used to index to vsw table */
+	char		 vnetLdomName[NAME_SIZE];       /* ldom name - used to index to ldom table */
+} vnet_t;
+
+typedef struct vds_s {
+	ulong_t		 index;
+	ulong_t		 vdsLdomIndex;		    /* index to ldom table */
+	char		 vdsServiceName[NAME_SIZE]; /* vds service name */
+	ulong_t		 vdsNumofAvailVolume;       /* number of available logical volume */
+	ulong_t		 vdsNumofUsedVolume;        /* number of used logical volume */
+	char		 vdsLdomName[NAME_SIZE];    /* ldom name - used to index to ldom table */
+} vds_t;
+
+typedef struct vds_name_s {
+	char		 ServiceName[NAME_SIZE];    /* vds service name */
+} vds_name_t;
+
+typedef struct vdsdev_s {
+	ulong_t		 index;
+	ulong_t		 vdsdevVdsIndex;	      /* index to vds table */
+	char		 vdsdevVolumeName[NAME_SIZE]; /* volume name */ 
+	char		 vdsdevDevPath[NAME_SIZE];    /* block dev */ 
+	char		 vdsdevServiceName[NAME_SIZE];  /* vds service name - used to index to vds table */
+} vdsdev_t;
+
+typedef struct vdsdev_name_s {
+	char		VolumeName[NAME_SIZE];	/* vdsdev name */
+	char		ServiceName[NAME_SIZE];	/* vds name */
+} vdsdev_name_t;
+
+typedef struct vdisk_s {
+	ulong_t		 index;
+	ulong_t		 vdiskLdomIndex;	 /* index to ldom table */
+	ulong_t		 vdiskVdsdevIndex;	 /* index to vdsdev table */
+	char		 vdiskName[NAME_SIZE];	  /* vdisk name */ 
+	char		 vdiskServiceName[NAME_SIZE]; /* vds name - used to index to vdsdev table */ 
+	char		 vdiskVolumeName[NAME_SIZE];  /* vdsdev name - used to index to vdsdev table */ 
+	char		 vdiskLdomName[NAME_SIZE];    /* ldom name - used to index to ldom table */
+} vdisk_t;
+
+typedef struct vcc_s {
+	ulong_t		 index;
+	ulong_t		 vccLdomIndex;		 /* index to ldom table */
+	char		 vccName[NAME_SIZE];	 /* vcc service name */
+	uint_t		 vccPortRangeLow;	 /* vcc min port */
+	uint_t		 vccPortRangeHigh;	 /* vcc max port */
+	char		 vccLdomName[NAME_SIZE]; /* ldom name - used to index to ldom table */
+} vcc_t;
+
+typedef struct vcc_name_s {
+	char		 ServiceName[NAME_SIZE]; /* vcc name */
+} vcc_name_t;
+
+typedef struct vcons_s {
+	ulong_t		 index;
+	char		 vconsGroupName[NAME_SIZE];     /* vcons group name */
+	uint_t		 vconsPortNumber;       	/* vcons port */
+	char		 vconsLdomName[NAME_SIZE];      /* ldom name - used to index to ldom table */
+} vcons_t;
+
+typedef struct vconsvccrel_s {
+	ulong_t		 index;
+	uint_t		 vconsvccrelVconsIndex;	  /* index to vcons table */ 
+	uint_t		 vconsvccrelLdomIndex;	  /* index to ldom table */ 
+	uint_t		 vconsvccrelVccIndex;	  /* index to vcc table */ 
+	char		 vconsvccrelServiceName[NAME_SIZE]; /* vcc service name - used to index to vcc table */
+	char		 vconsvccrelLdomName[NAME_SIZE];    /* ldom name - used to index to ldom table */
+} vconsvccrel_t;
+
+typedef struct envvars_s {
+	ulong_t		 index;
+	ulong_t		 envvarsLdomIndex;	        /* index to ldom table */
+	char		 envvarsName[NAME_SIZE];	/* env var name */ 
+	char		 envvarsValue[NAME_SIZE];       /* env var value */ 
+} envvars_t;
+
+typedef struct crypto_s {
+	ulong_t		 index;
+	ulong_t		 cryptoLdomIndex;	   /* index to ldom table */
+	char		 cryptoCpuSet[NAME_SIZE];  /* crypto cpuset */
+} crypto_t;
+
+typedef struct iobus_s {
+	ulong_t		 index;
+	ulong_t		 iobusLdomIndex;	   /* index to ldom table */
+	char		 iobusDevName[NAME_SIZE];  /* iobus device name */
+	char		 iobusDevPath[NAME_SIZE];  /* iobus device path */
+} iobus_t;
+
+xmlDocPtr create_xml_file(char *snmp_user, char *ldom_name, const xmlChar *action);
+xmlDocPtr create_xml_file_4_ldom_action(char *, const xmlChar *);
+xmlDocPtr create_xml_file_4_set_vcpu(char *, int );
+xmlDocPtr create_xml_file_4_set_memory(char *, unsigned long );
+
+int parse_xml_get_response_status(xmlNodePtr node);
+int parse_xml_get_ldom_state(xmlNodePtr node);
+
+int parse_xml_get_ldom_cnt(xmlDoc *doc, int *ldom_cnt);
+int parse_xml_get_ldominfo(xmlDoc *doc, int *num_cpu, int *mem_size, int *mem_unit, int *num_crypto, int *num_iobus);
+char* parse_xml_get_ldom_name(xmlNodePtr node);
+
+int parse_xml_get_subnode_cnt(xmlNodePtr node, xmlChar *subnode);
+int parse_xml_get_vds_volume(xmlNodePtr node, char *service_name);
+int parse_xml_get_vds_volume_bind(xmlDoc *doc, char *service_name);
+char* parse_xml_get_mac_addr(xmlNodePtr node);
+
+int parse_xml_get_cpu_bindings(xmlDocPtr, cpuBindings_t **);
+int parse_xml_get_console(xmlDoc *, int *);
+int parse_xml_get_vcpu(xmlDoc *doc, int *vcpu_cnt, vcpu_t ***vcpu);
+int parse_xml_get_vmem(xmlDoc *doc, int *vmem_cnt, vmem_data_t ***vmem);
+int parse_xml_get_vmem_physbind(xmlDoc *doc, int *vmem_cnt, vmem_physbind_t ***vmem);
+int parse_xml_get_vsw(xmlDoc *doc, int *vsw_cnt, vsw_t ***vsw);
+int parse_xml_get_vnet(xmlDoc *doc, int *vnet_cnt, vnet_t ***vnet);
+int parse_xml_get_vds(xmlDoc *doc, int *vds_cnt, vds_t ***vds);
+int parse_xml_get_vdsdev(xmlDoc *doc, int *vdsdev_cnt, vdsdev_t ***vdsdev);
+int parse_xml_get_vdisk(xmlDoc *doc, int *vdisk_cnt, vdisk_t ***vdisk);
+int parse_xml_get_vcc(xmlDoc *doc, int *vcc_cnt, vcc_t ***vcc);
+int parse_xml_get_vcons(xmlDoc *doc, int *vcons_cnt, vcons_t ***vcons);
+int parse_xml_get_vconsvccrel(xmlDoc *doc, int *vconsvccrel_cnt, vconsvccrel_t ***vconsvccrel);
+int parse_xml_get_envvars(xmlDoc *doc, int *envvars_cnt, envvars_t ***envvars);
+int parse_xml_get_crypto(xmlDoc *doc, int *crypto_cnt, crypto_t ***crypto);
+int parse_xml_get_iobus(xmlDoc *doc, int *iobus_cnt, iobus_t ***iobus);
+
+int parse_xml_get_cpu_rp(xmlDoc *doc, int rp_type, ulong_t *reserved, int *unit);
+int parse_xml_get_mem_rp(xmlDoc *doc, int rp_type, ulong_t *reserved, int *unit);
+int parse_xml_get_crypto_rp(xmlDoc *doc, int rp_type, ulong_t *reserved, int *unit);
+int parse_xml_get_iobus_rp(xmlDoc *doc, int rp_type, ulong_t *reserved, int *unit);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WITH_LDOMS*/
+#endif /* __VIR_LDOMS_XML_PARSE_H__ */
diff --git a/src/ldoms_xml_parse.c b/src/ldoms_xml_parse.c
new file mode 100644
--- /dev/null
+++ b/src/ldoms_xml_parse.c
@@ -0,0 +1,1832 @@
+/*
+ * ldoms_xml_parse.c: LDoms XML parsing routines using the LDoms XML Schema V2 
+ *                    to interface with the LDoms Manager (LDM)
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ */
+
+#ifdef WITH_LDOMS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/processor.h>
+#include <fcntl.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+
+
+#include "internal.h"
+#include "xml.h"
+#include "ldoms_internal.h"
+#include "ldoms_intfc.h"
+
+/* Domain state info
+ * LDom State enumerations
+ *       1 = active
+ *       2 = stopping
+ *       3 = inactive
+ *       4 = binding
+ *       5 = unbinding
+ *       6 = bound
+ *       7 = starting
+ *
+ * libvirt LDom State enums
+ * typedef enum {
+ *   VIR_DOMAIN_NOSTATE = 0,  no state 
+ *   VIR_DOMAIN_RUNNING = 1,  the domain is running 
+ *   VIR_DOMAIN_BLOCKED = 2,  the domain is blocked on resource
+ *   VIR_DOMAIN_PAUSED  = 3,  the domain is paused by user
+ *   VIR_DOMAIN_SHUTDOWN= 4,  the domain is being shut down 
+ *   VIR_DOMAIN_SHUTOFF = 5,  the domain is shut off 
+ *   VIR_DOMAIN_CRASHED = 6   the domain is crashed 
+ * } virDomainState;
+ */
+
+/*
+ * when adding up the memory (capacity/reserved) for the memory resource pool,
+ * the memory unit will be converted to take the smallest unit in use.
+ */
+#define MEM_GB_BYTES    (1024*1024*1024)    /* 1 GB in bytes */
+#define MEM_MB_BYTES    (1024*1024)         /* 1 MB in bytes */
+#define MEM_KB_BYTES    (1024)              /* 1 KB in bytes */
+
+/* Global vars for debug statement */
+extern int ldoms_debug;
+extern int ldoms_detailed_debug;
+
+/*
+ * Returns the next elemental sibling node of the node you pass in. If there
+ * are no more nodes it returns NULL.
+ */
+xmlNodePtr
+xml_get_next_ele_node(xmlNodePtr node)
+{
+    xmlNodePtr sib_node;
+
+    sib_node = node->next;
+
+    while (sib_node != NULL) {
+        if (sib_node->type != XML_ELEMENT_NODE)
+            sib_node = sib_node->next;
+        else
+            break;
+    }
+
+    return (sib_node);
+} /* xml_get_next_ele_node() */
+
+/*
+ * Find and return the first-level subnode (if any) of 'node' which has name
+ * 'name'.
+ */
+xmlNodePtr
+xml_find_subnode(xmlNodePtr node, const xmlChar *name)
+{
+    xmlNodePtr subnode;
+
+    subnode = node->xmlChildrenNode;
+    while (subnode != NULL) {
+        if (xmlStrcmp(subnode->name, name) == 0)
+            break;
+        subnode = subnode->next;
+    }
+
+    return (subnode);
+} /* xml_find_subnode */
+
+
+/*
+ * create_xml_file_4_set_vcpu 
+ *
+ * This function creates the XML request file for changing the number
+ * or virtual cpus for an LDom
+ *
+ * Input:
+ *  ldom_name - name of the ldom to be included in the XML file with
+ *              the <ldom_name> tag. 
+ *  nvcpus - The new number of vcpus for this LDom
+ * 
+ * Returns:
+ *  pointer to the created xml doc if the operation is successful
+ *  NULL if the operation fails
+ *  
+ * Example: The following XML file will be created for LDom ldom1
+ * and a new vcpu value of 4
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ *   <cmd>
+ *     <action>set-vcpu</action>
+ *     <data version="2.0">
+ *       <ldom>
+ *         <ldom_info>
+ *           <ldom_name>ldom1</ldom_name>
+ *         </ldom_info>
+ *         <cpu>
+ *           <number>4</number>
+ *         </cpu>
+ *       </ldom>
+ *     </data>
+ *   </cmd>
+ * </LDM_interface>
+ */
+
+xmlDocPtr
+create_xml_file_4_set_vcpu(char *ldom_name, int nvcpus)
+{
+    xmlDocPtr       xml_output;
+    xmlNodePtr      root, cmd, data, ldom, info_node, cpu;
+    char vcpu[10];  /* ascii version of input int nvcpus */
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: create_xml_file_4_set_vcpu(ENTER): ldom=%s, vcpus=%d\n",
+        (ldom_name==NULL? "NULL" : ldom_name), nvcpus);
+
+    xml_output = xmlNewDoc(XML_VERSION);
+
+    /* <LDM_interface> tag with version attribute */
+    root =  xmlNewDocNode(xml_output, NULL, XML_LDM_INTERFACE, NULL);
+    xmlDocSetRootElement(xml_output, root);
+    xmlNewProp(root, VERSION_ATTR, LDOM_INTERFACE_VERSION);
+
+    /* <cmd> tag */
+    cmd = xmlNewChild(root, NULL, XML_CMD, NULL);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_vcpu() cmd tag\n");
+
+    /* <action> tag */
+    xmlNewChild(cmd, NULL, XML_ACTION, XML_SET_VCPU);
+
+    /* <data> tag with version attribute */
+    data = xmlNewChild(cmd, NULL, XML_DATA, NULL);
+    xmlNewProp(data, VERSION_ATTR, LDOM_DATA_VERSION);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_vcpu() data tag\n");
+
+    /* <ldom> tag */
+    ldom = xmlNewChild(data, NULL, LDOM_NODE, NULL);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_vcpu() ldom tag\n");
+
+    /* <ldom_info> tag with child <ldom_name> tag */
+    info_node = xmlNewChild(ldom, NULL, XML_LDM_INFO, NULL);
+    xmlNewChild(info_node, NULL, XML_LDM_NAME, (xmlChar *)ldom_name);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_vcpu() ldom_info tag\n");
+
+    /* <cpu> tag with child <number> tag */
+    cpu = xmlNewChild(ldom, NULL, CPU_NODE, NULL);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_vcpu() cpu tag\n");
+    sprintf(vcpu, "%d", nvcpus);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_vcpu() vcpu=%s\n",vcpu);
+    xmlNewChild(cpu, NULL, NUMBER_NODE, (xmlChar *)vcpu);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_vcpu() number tag\n");
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: create_xml_file_4_set_vcpu(EXIT)\n");
+
+    return(xml_output);
+} /* create_xml_file_4_set_vpcu() */
+
+/*
+ * create_xml_file_4_set_memory
+ *
+ * This function creates the XML request file for changing the memory
+ * for an LDom
+ *
+ * Input:
+ *  ldom_name - name of the ldom to be included in the XML file with
+ *              the <ldom_name> tag.
+ *  memory - The new memory size for this LDom.
+ *           The memory size is in Kilobytes.
+ *           NOTE: The VMM and virsh displays the memory in KB.
+ *
+ * Returns:
+ *  pointer to the created xml doc if the operation is successful
+ *  NULL if the operation fails
+ *
+ * Example: The following XML file will be created for LDom ldom1
+ * and a new memory value of 256 Kilobytes.
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ *   <cmd>
+ *     <action>set-memory</action>
+ *     <data version="2.0">
+ *       <ldom>
+ *         <ldom_info>
+ *           <ldom_name>ldom1</ldom_name>
+ *         </ldom_info>
+ *         <memory>
+ *           <size>256K</size>
+ *         </memory>
+ *       </ldom>
+ *     </data>
+ *   </cmd>
+ * </LDM_interface>
+ */
+
+xmlDocPtr
+create_xml_file_4_set_memory(char *ldom_name, unsigned long memory)
+{
+    xmlDocPtr       xml_output;
+    xmlNodePtr      root, cmd, data, ldom, info_node, mem;
+    char mem_str[10];  /* ascii version of input int memory */
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: create_xml_file_4_set_memory(ENTER): ldom=%s, memory=%lu\n",
+        (ldom_name==NULL? "NULL" : ldom_name), memory);
+
+    xml_output = xmlNewDoc(XML_VERSION);
+
+    /* <LDM_interface> tag with version sttribute */
+    root =  xmlNewDocNode(xml_output, NULL, XML_LDM_INTERFACE, NULL);
+    xmlDocSetRootElement(xml_output, root);
+    xmlNewProp(root, VERSION_ATTR, LDOM_INTERFACE_VERSION);
+
+    /* <cmd> tag */
+    cmd = xmlNewChild(root, NULL, XML_CMD, NULL);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_memory() cmd tag\n");
+
+    /* <action> tag */
+    xmlNewChild(cmd, NULL, XML_ACTION, XML_SET_MEM);
+
+    /* <data> tag with version attribute */
+    data = xmlNewChild(cmd, NULL, XML_DATA, NULL);
+    xmlNewProp(data, VERSION_ATTR, LDOM_DATA_VERSION);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_memory() data tag\n");
+
+    /* <ldom> tag */
+    ldom = xmlNewChild(data, NULL, LDOM_NODE, NULL);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_memory() ldom tag\n");
+
+    /* <ldom_info> tag with child <ldom_name> tag */
+    info_node = xmlNewChild(ldom, NULL, XML_LDM_INFO, NULL);
+    xmlNewChild(info_node, NULL, XML_LDM_NAME, (xmlChar *)ldom_name);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_memory() ldom_info tag\n");
+
+        /* add memory unit K (for Kilobytes) to the memory size string */
+    sprintf(mem_str, "%d", memory);
+    strlcat(mem_str, "K", sizeof (mem_str));
+
+    /* <memory> tag with child <size> tag */
+    mem = xmlNewChild(ldom, NULL, MEMORY_NODE, NULL);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_memory() memory tag\n");
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_memory() memory=%s\n", mem_str);
+    xmlNewChild(mem, NULL, SIZE_NODE, (xmlChar *)mem_str);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: create_xml_file_4_set_memory() size tag\n");
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: create_xml_file_4_set_memory(EXIT)\n");
+
+    return(xml_output);
+} /* create_xml_file_4_set_memory() */
+
+/*
+ * create_xml_file_4_ldom_action 
+ *
+ * This function creates the XML request file for the given ldom and action. 
+ *
+ * Input:
+ *  ldom_name - name of the ldom to be included in the XML file with
+ *              the <ldom_name> tag. if ldom_name is NULL, the XML request for
+ *              all ldoms will be created
+ *  action - action (such as list-bindings or list-constraints..etc) to be
+ *           included in the XML file with the <action> tag
+ * 
+ * Returns:
+ *  pointer to the created xml doc if the operation is successful
+ *  NULL if the operation fails
+ *  
+ * Example: The following XML file will be created if the 
+ * name of the ldom is 'ldg3', and the action is 'list-bindings'.
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ *  <cmd>
+ *    <action>list-bindings</action>
+ *    <data version="2.0">
+ *     <ldom>
+ *       <ldom_info>
+ *         <ldom_name>ldg3</ldom_name>
+ *       </ldom_info>
+ *     </ldom>
+ *   </data>
+ *  </cmd>
+ * </LDM_interface>
+ */
+xmlDocPtr
+create_xml_file_4_ldom_action(char *ldom_name, const xmlChar *action)
+{
+    xmlDocPtr       xml_output;
+    xmlNodePtr      root, cmd, data, ldom, info_node;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: create_xml_file_4_ldom_action(ENTER): ldom=%s, action=%s\n",
+        (ldom_name==NULL? "NULL" : ldom_name), action);
+
+    xml_output = xmlNewDoc(XML_VERSION);
+    root =  xmlNewDocNode(xml_output, NULL, XML_LDM_INTERFACE, NULL);
+    xmlDocSetRootElement(xml_output, root);
+    xmlNewProp(root, VERSION_ATTR, LDOM_INTERFACE_VERSION);
+
+    cmd = xmlNewChild(root, NULL, XML_CMD, NULL);
+
+    xmlNewChild(cmd, NULL, XML_ACTION, action);
+
+    data = xmlNewChild(cmd, NULL, XML_DATA, NULL);
+    xmlNewProp(data, VERSION_ATTR, LDOM_DATA_VERSION);
+
+    /* 
+     * If the ldom_name is NULL, the LDM will return info for
+     * all existing LDoms, independent of their state.  Otherwise,
+     * we get the info for only the LDom specified.
+     */
+    if (ldom_name != NULL) {
+        ldom = xmlNewChild(data, NULL, LDOM_NODE, NULL);
+        info_node = xmlNewChild(ldom, NULL, XML_LDM_INFO, NULL);
+        xmlNewChild(info_node, NULL, XML_LDM_NAME, (xmlChar *)ldom_name);
+    }
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: create_xml_file_4_ldom_action(EXIT)\n");
+
+    return(xml_output);
+} /* create_xml_file_4_ldom_action() */
+
+
+/*
+ * parse_xml_get_subnode_cnt
+ *
+ * This function counts the specific subnodes starting from the given xml node.   
+ *
+ * Input:
+ *  node - pointer to the xml node to start looking for the subnode
+ *  subnode_to_find - subnode to look for and count the numbers
+ *
+ * Returns:
+ *  number of subnodes if the operation is successful
+ *  0 if no subnode is found
+ */  
+int
+parse_xml_get_subnode_cnt(xmlNodePtr node, xmlChar *subnode_to_find)
+{
+    xmlNodePtr      subnode;
+    int     i = 0;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_subnode_cnt(ENTER)\n");
+
+    subnode = node->xmlChildrenNode;
+    while (subnode != NULL) {
+        if (subnode->type != XML_ELEMENT_NODE) {
+            subnode = subnode->next;
+            continue;
+        }
+
+
+        if (xmlStrcmp(subnode->name, (const xmlChar *)subnode_to_find) == 0) {
+            i++;
+            subnode = subnode->next;
+            continue;
+        }
+
+        subnode = subnode->next;
+    }
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_subnode_cnt(EXIT) cnt=%d\n",i);
+
+
+   return(i);
+}
+
+/*
+ * parse_xml_get_console
+ *
+ * This function gets the console port number for an LDom.
+ *
+ * Input:
+ *  xml doc - XML document to read (this will be an XML document for one ldom)
+ *
+ * Output (pointers are used to pass information from this function to the caller):
+ *  console - pointer to the console port number
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *
+ * NOTE: Example XML document that this function will parse to get the ldom info:
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ *   <cmd>
+ *     <action>list-bindings</action>
+ *     <data version="2.0">
+ *       <ldom>
+ *         <ldom_info>
+ *           <ldom_name>primary</ldom_name>
+ *        </ldom_info>
+ *        <console>
+ *          <service_name>primary-vcc0</service_name>
+ *          <port>5004</port>
+ *        </console>
+ *...
+ *      </ldom>
+ *      <response>
+ *        <status>success</status>
+ *      </response>
+ *     </data>
+ *     <response>
+ *       <status>success</status>
+ *     </response>
+ *  </cmd>
+ *  <response>
+ *    <status>success</status>
+ *  </response>
+ * </LDM_interface>
+ */
+int
+parse_xml_get_console(xmlDoc *doc, int *console)
+{
+    int        ret = 0;
+    int        console_xml;
+    xmlNodePtr    root_node = NULL;
+    xmlNodePtr    cmd_node = NULL;
+    xmlNodePtr    data_node = NULL;
+    xmlNodePtr    ldom_node = NULL;
+    xmlNodePtr    console_node = NULL;
+    char        *ldm_name = NULL;
+    xmlChar        *content = NULL;
+
+    xmlNodePtr    subnode;
+
+    uint64_t size = 0;
+
+    *console = 0;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console(ENTER) \n");
+
+    root_node = xmlDocGetRootElement(doc);
+
+    /* Check for an XML failure */
+    if (parse_xml_get_response_status(root_node) == -1)
+            return(-1);
+
+    /* Get the <cmd> tag */
+    cmd_node = xml_find_subnode(root_node, XML_CMD);
+    if (cmd_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console.. XML file does not have <cmd> tag\n");
+            return (-1);
+    }
+
+    /* Get the <data> tag */
+    data_node = xml_find_subnode(cmd_node, XML_DATA);
+    if (data_node != NULL)
+        /* Get the <ldom> tag */
+        ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+    else {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console.. XML file does not have <data> tag\n");
+            return (-1);
+    }
+        
+    if (ldom_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console.. XML file does not have <ldom> tag\n");
+            return (-1);
+    }
+
+    /* Get the <console> tag */
+    console_node = xml_find_subnode(ldom_node, CONSOLE_NODE);
+    if (console_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console.. XML file does not have <console> tag\n");
+        console_xml = 0;
+    } else {
+        /* Get the <port> tag */
+        subnode = xml_find_subnode(console_node, XML_PORT);
+        if (subnode == NULL) {
+            if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console.. XML file does not have <port> tag within <console> tag\n");
+            console_xml = 0;
+        } else {
+            /* Contents of the <port> tag */
+            content = xmlNodeGetContent(subnode);
+
+            console_xml = atoi((const char *)content);
+            if (console_xml <= 0) {
+                if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console.. Invalid <port> num: %s\n", content);
+            }
+            xmlFree(content);
+        }
+    }
+
+    *console = console_xml;
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_console(EXIT) console=%d\n", console_xml);
+
+    return (ret);
+}
+
+/*
+ * parse_xml_get_ldominfo
+ *
+ * This function gets the ldom info such as the number of virtial cpu, memory and
+ * its unit, crypto, and iobus by parsing the XML output from the LDOM Manager.
+ *
+ * Input:
+ *  xml doc - XML document to read (this will be an XML document for one ldom)
+ *
+ * Output (pointers are used to pass information from this function to the caller):
+ *  num_cpu - pointer to the number of virtual cpu
+ *  mem_size - pointer to the virtual memory size
+ *  mem_unit - pointer to the virtual memory unit
+ *  num_crypto - pointer to the number of crypto unit
+ *  num_iobus - pointer to the number of io bus
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *
+ * NOTE: Example XML document that this function will parse to get the ldom info:
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ *   <cmd>
+ *     <action>list-constraints</action>
+ *     <data version="2.0">
+ *       <ldom>
+ *         <ldom_info>
+ *           <ldom_name>primary</ldom_name>
+ *        </ldom_info>
+ *        <cpu>
+ *          <number>4</number>
+ *        </cpu>
+ *        <mau>
+ *          <number>1</number>
+ *        </mau>
+ *        <memory>
+ *          <size>1G</size>
+ *        </memory>
+ *        <physio_device>
+ *          <name>pci 780</name>
+ *        </physio_device>
+ *      </ldom>
+ *      <response>
+ *        <status>success</status>
+ *      </response>
+ *     </data>
+ *     <response>
+ *       <status>success</status>
+ *     </response>
+ *  </cmd>
+ *  <response>
+ *    <status>success</status>
+ *  </response>
+ * </LDM_interface>
+ */
+int
+parse_xml_get_ldominfo(xmlDoc *doc, int *num_cpu, int *mem_size, int *mem_unit, int *num_crypto, int *num_iobus)
+{
+    int             ret = 0;
+    xmlNodePtr      root_node = NULL;
+    xmlNodePtr      cmd_node = NULL;
+    xmlNodePtr      data_node = NULL;
+    xmlNodePtr      ldom_node = NULL;
+    xmlNodePtr      cpu_node = NULL;
+    xmlNodePtr      memory_node = NULL;
+    xmlNodePtr      mau_node = NULL;
+    char            *ldm_name = NULL;
+    xmlChar         *content = NULL;
+
+    xmlNodePtr      subnode;
+
+    long long    num_cpu_xml = 0;
+    long long    num_crypto_xml = 0;
+    long long    num_iobus_xml = 0;
+
+    char *endp;
+    uint64_t size = 0;
+
+    *num_cpu = 0;
+    *mem_size = 0; 
+    *num_crypto = 0; 
+    *num_iobus = 0; 
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo(ENTER) \n");
+
+    root_node = xmlDocGetRootElement(doc);
+
+    if (parse_xml_get_response_status(root_node) == -1)
+        return(-1);
+
+    cmd_node = xml_find_subnode(root_node, XML_CMD);
+    if (cmd_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. XML file does not have <cmd> tag\n");
+        return (-1);
+    }
+
+    data_node = xml_find_subnode(cmd_node, XML_DATA);
+    if (data_node != NULL)
+        ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+    else {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. XML file does not have <data> tag\n");
+        return (ret);
+    }
+    
+    if (ldom_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. XML file does not have <ldom> tag\n");
+        return (ret);
+    }
+
+    /* get number of cpu */  
+    cpu_node = xml_find_subnode(ldom_node, CPU_NODE);
+    if (cpu_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. XML file does not have <cpu> tag\n");
+        num_cpu_xml = 0;
+    } else {
+        subnode = xml_find_subnode(cpu_node, NUMBER_NODE);
+        if (subnode == NULL) {
+            if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. XML file does not have <number> tag within <cpu> tag\n");
+            num_cpu_xml = 0;
+        } else {
+
+            content = xmlNodeGetContent(subnode);
+
+            num_cpu_xml = strtoll((char *)content, NULL, 0);
+            if (num_cpu_xml <= 0) {
+                if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. Invalid cpu num specified: %s\n", content);
+            }
+            xmlFree(content);
+        }
+    }
+
+
+    /* get memory size */  
+    memory_node = xml_find_subnode(ldom_node, MEMORY_NODE);
+    if (memory_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. XML file does not have <memory> tag\n");
+        size = 0;
+    } else {
+        subnode = xml_find_subnode(memory_node, SIZE_NODE);
+        if (subnode == NULL) {
+            if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. XML file does not have <size> tag within <memory> tag\n");
+            size = 0;
+        } else {
+
+            content = xmlNodeGetContent(subnode);
+
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldominfo.. mem_size = %s\n", content);
+
+            /* extract the number and unit from the content */
+            size = strtoull((char *)content, &endp, 0);
+            if (size > 0) {
+
+                /* get the memory unit */
+                /* Ldoms Manager CLI is using "bytes" as the default memory unit. */
+                *mem_unit = LDOMMEMUNIT_BYTES; /* use bytes as default */
+                switch (strlen(endp)) {
+                case 0: break;
+                default:
+                    switch (endp[strlen(endp)-1]) {
+                    case 'G':
+                    case 'g':
+                        *mem_unit = LDOMMEMUNIT_GIGABYTES;
+                        break;
+                    case 'M':
+                    case 'm':
+                        *mem_unit = LDOMMEMUNIT_MEGABYTES;
+                        break;
+                    case 'K':
+                    case 'k':
+                        *mem_unit = LDOMMEMUNIT_KILOBYTES;
+                        break;
+                    default:
+                        *mem_unit = LDOMMEMUNIT_BYTES;
+                    }
+                    break;
+                }
+                if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldominfo.. mem size unit = %s\n", endp);
+            } else {
+                if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo.. Invalid mem size specified: %s\n", content);
+            }
+            xmlFree(content);
+        }
+
+    }
+
+    /* get number of crypto */  
+    mau_node = xml_find_subnode(ldom_node, MAU_NODE);
+    if (mau_node == NULL) {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldominfo.. XML file does not have <mau> tag\n");
+        num_crypto_xml = 0;
+    } else {
+        subnode = xml_find_subnode(mau_node, NUMBER_NODE);
+        if (subnode == NULL) {
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldominfo.. XML file does not have <number> tag within <mau> tag\n");
+            num_crypto_xml = 0;
+        } else {
+
+            content = xmlNodeGetContent(subnode);
+            num_crypto_xml = strtoll((char *)content, NULL, 0);
+            if (num_crypto_xml <= 0) {
+                if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldominfo.. Invalid crypto num specified: %s\n", content);
+            }
+            xmlFree(content);
+        }
+    }
+
+    /* get number of io bus */
+    num_iobus_xml = parse_xml_get_subnode_cnt(ldom_node, XML_PHYSIO_DEVICE);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldominfo.. number of <physio_device> tags =%d\n", num_iobus_xml);
+
+    *num_cpu = (int)num_cpu_xml;
+    *mem_size = (int)size;
+    *num_crypto = (int)num_crypto_xml;
+    *num_iobus = (int)num_iobus_xml;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldominfo(EXIT)\n");
+
+    return (ret);
+}
+
+xmlNodePtr
+xmlFindSubnode(xmlNodePtr node, const xmlChar *name) 
+{
+    xmlNodePtr subnode;
+
+    subnode = node->xmlChildrenNode;
+    while (subnode != NULL) {
+        if (xmlStrcmp(subnode->name, name) == 0)
+            break;
+        subnode = subnode->next;
+    }
+
+    return (subnode);
+}
+
+/*
+ * parse_xml_get_ldom_name
+ *
+ * This function find the <ldom_name> tag within the input xml document
+ * and return the LDom name in that tag, or NULL if the tag does not exist.
+ *
+ * Input:
+ *   node - An xmlNodePtr to the xml data root node
+ *
+ * Output:
+ *   A ptr to the LDom name (caller must free memory when done)
+ *   NULL if no <ldom_name> tag or content is found
+ */
+char *
+parse_xml_get_ldom_name(xmlNodePtr node)
+{
+    char            *ldomName = NULL;
+    xmlChar         *content = NULL;
+    xmlNodePtr      subnode;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_name(ENTER) \n");
+    if (ldoms_debug) dprt("   DBG: ENTER: nodeName=%s, nodeType=%d\n",node->name,node->type);
+
+    /* Find the <ldom_name> tag and get its content, which is the LDom name */
+    subnode = xmlFindSubnode(node, XML_CMD);
+    if (subnode != NULL) {
+        subnode = xmlFindSubnode(subnode, XML_DATA);
+            if (subnode != NULL) {
+                subnode = xmlFindSubnode(subnode, LDOM_NODE);
+                    if (subnode != NULL) {
+                        subnode = xmlFindSubnode(subnode, XML_LDM_INFO);
+                            if (subnode != NULL) {
+                                subnode = xmlFindSubnode(subnode, XML_LDM_NAME);
+                                    if (subnode != NULL) {
+                                        content = xmlNodeGetContent(subnode);
+                                        ldomName = strdup((const char *)content);
+                                    }
+                            }
+                    }
+            }
+    }
+
+
+    if (ldomName == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_name() XML file does not have <ldom_name> tag\n");
+        return(NULL);
+    }
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_name(EXIT) LDom Name = %s\n",ldomName);
+
+    return (ldomName);
+} /* parse_xml_get_ldom_name */
+
+/*
+ * parse_xml_get_ldom_state
+ *
+ * This function converts the ldom state to the enum value.
+ *
+ * Input:
+ *   node - pointer to the xml node that contains the ldom state data 
+ *
+ * Returns:
+ *   following ldom state enum value if the operation is successful
+ *       1 = active       LDOM_STATE_ACTIVE
+ *       2 = stopping     LDOM_STATE_STOPPING
+ *       3 = inactive     LDOM_STATE_INACTIVE
+ *       4 = binding      LDOM_STATE_BINDING
+ *       5 = unbinding    LDOM_STATE_UNBINDING
+ *       6 = bound        LDOM_STATE_BOUND
+ *       7 = starting     LDOM_STATE_STARTING
+ *
+ *   -1 if the operation fails
+ *
+ */
+int
+parse_xml_get_ldom_state(xmlNodePtr node)
+{
+    xmlNodePtr      state_node = NULL;
+    xmlChar         *content = NULL;
+    int        ldom_state = 0;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_state(ENTER)\n");
+    state_node = xml_find_subnode(node, STATE_NODE);
+    if (state_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_state.. XML file does not have <state> tag\n");
+        return (-1);
+    }
+
+    content = xmlNodeGetContent(state_node);
+    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldom_state.. state=%s\n", content);
+
+    if (strcmp((char *)content, "active") == 0) 
+        ldom_state = LDOM_STATE_ACTIVE;
+    else if (strcmp((char *)content, "stopping") == 0) 
+        ldom_state = LDOM_STATE_STOPPING;
+    else if (strcmp((char *)content, "inactive") == 0) 
+        ldom_state = LDOM_STATE_INACTIVE;
+    else if (strcmp((char *)content, "binding") == 0) 
+        ldom_state = LDOM_STATE_BINDING;
+    else if (strcmp((char *)content, "unbinding") == 0) 
+        ldom_state = LDOM_STATE_UNBINDING;
+    else if (strcmp((char *)content, "bound") == 0) 
+        ldom_state = LDOM_STATE_BOUND;
+    else if (strcmp((char *)content, "starting") == 0) 
+        ldom_state = LDOM_STATE_STARTING;
+
+    xmlFree(content);
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_state(EXIT): state=%d\n",ldom_state);
+    return(ldom_state);
+} /* parse_xml_get_ldom_state */
+
+
+/*
+ * parse_xml_get_response_status
+ *
+ * This function checks for the <response> <status> tags in the XML response.
+ * There are <response><status> tags associated with the document, <cmd> and
+ * <data> tags.  This function is general to be able to check for
+ * <response><status> for any of these.  If the <status> of the document is
+ * 'success', then the other <response><status> tags do not need to be checked.
+ *
+ * Input:
+ *  node - pointer to the xml node to check the response status
+ *
+ * Returns:
+ *  0 if the response status is success
+ * -1 if the response status is failure or the operation fails
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ *   <cmd>
+ *     <action>bind-domain</action>
+ *     <data version="2.0">
+ *       <response>
+ *         <status>failure</status>
+ *         <resp_msg>ldom does not have ldom_name tag</resp_msg>
+ *       </response>
+ *     </data>
+ *     <response>
+ *       <status>failure</status>
+ *     </response>
+ *   </cmd>
+ *   <response>
+ *     <status>failure</status>
+ *   </response>
+ * </LDM_interface>
+ */
+int
+parse_xml_get_response_status(xmlNodePtr node)
+{
+    xmlNodePtr    response_node = NULL;
+    xmlNodePtr    status_node = NULL;
+    xmlNodePtr    resp_msg_node = NULL;
+    xmlNodePtr    cmd_node = NULL;
+    xmlNodePtr    cmd_child_node = NULL;
+    xmlNodePtr    data_child_node = NULL;
+    xmlNodePtr    respmsg_node = NULL;
+    xmlChar       *content = NULL;
+    
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_response_status(ENTER)\n");
+
+    response_node = xml_find_subnode(node, XML_RESPONSE);
+    if (response_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_response_status.. XML file does not have <response> tag\n");
+        return (-1);
+    }
+
+
+    status_node = xml_find_subnode(response_node, XML_STATUS);
+    if (status_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_response_status.. XML file does not have <status> tag within <response>\n");
+        return (-1);
+    }
+
+    content = xmlNodeGetContent(status_node);
+
+    /* 
+     * The <status> tag must indicate 'success', otherwise we cannot process
+     * anymore or the XML response because there has been some type of error.
+     */
+    if (strcmp((char *)content, XML_SUCCESS) == 0) {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_response_status() <response><status> is success\n");
+        xmlFree(content);
+    } 
+
+    /* XML request failed, get the reason why, <resp_msg> */
+    else {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_response_status() <response><status>=%s\n", content);
+        xmlFree(content);
+        content = NULL;
+
+        /* response status is not success, get the response msg.
+         * The <resp_msg> tag is within the <data> tag, not the <cmd>
+         * or <LDM_interface> tags, so drill down to the first <data>
+         * tag and get the <response><resp_msg> tag contents to display
+         * in an error message
+         */
+        
+        /* 
+         * Get the <cmd> node first, then get a list of the child nodes.
+         * There can be multiple <data></data> nodes, which are peers,
+         * but usually there is only 1 <data> node, but code for multiple
+         */
+        cmd_node = xml_find_subnode(node, XML_CMD);
+        cmd_child_node = cmd_node->xmlChildrenNode;
+        while (cmd_child_node != NULL) {
+            if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_response_status() <cmd> child=%s\n",cmd_child_node->name);
+            /* Is current child node a <data> */
+            if (strcmp((const char*)cmd_child_node->name,(const char*)XML_DATA) != 0) {
+                cmd_child_node = cmd_child_node->next;
+                continue;
+            }
+
+            /* Found a <data> node, so get the list of child nodes */
+            data_child_node = cmd_child_node->xmlChildrenNode;
+            while (data_child_node != NULL) {
+                if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_response_status() <data> child=%s\n",data_child_node->name);
+                /* Is current child node a <response> */
+                if (strcmp((const char*)data_child_node->name,(const char*)XML_RESPONSE) != 0) {
+                    data_child_node = data_child_node->next;
+                    continue;
+                }
+                if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_response_status() Found <response>\n");
+
+                /* Found a <response> node, so get the <resp_msg> node */
+                respmsg_node = xml_find_subnode(data_child_node, XML_RESP_MSG);
+                if (respmsg_node != NULL) {
+                    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_response_status() Found <resp_msg>\n");
+                    content = xmlNodeGetContent(respmsg_node);
+                    if (content != NULL) {
+                        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_response_status() <resp_msg>=%s\n", content);
+                        cmd_child_node = NULL;
+                    }
+                }
+                /* No more <response> nodes in the <data> node */
+                break;
+            }
+        }
+
+        if (content != NULL) {
+            ldomsError(NULL, NULL, VIR_ERR_OPERATION_FAILED, (const char*)content, VIR_ERR_ERROR);
+            xmlFree(content);
+        }
+        return (-1);
+    }
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_response_status(EXIT)\n");
+
+    return(0);
+} /* parse_xml_get_response_status */
+
+/*
+ * parse_xml_get_ldom_cnt
+ *
+ * This functions gets the number of ldoms from the input xml file
+ * by counting the <ldom> tags.
+ *
+ * Input:
+ *  xml doc  - XML document to read
+ *
+ * Output:
+ *  ldom_cnt - number of ldoms   
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *
+ * NOTE: 
+ * Each <ldom> tag comes within the <data> tag. 
+ *
+ * Example XML output from the LDOM Manager for the "list-domain" request:
+ *
+ * <?xml version="1.0"?>
+ * <LDM_interface version="1.0">
+ *  <cmd>
+ *   <action>list-domain</action>
+ *   <data version="2.0">
+ *     <ldom>
+ *       <ldom_info>
+ *         <ldom_name>primary</ldom_name>
+ *         <state>active</state>
+ *       </ldom_info>
+ *     </ldom>
+ *     <response>
+ *       <status>success</status>
+ *     </response>
+ *   </data>
+ *   <data version="2.0">
+ *     <ldom>
+ *       <ldom_info>
+ *         <ldom_name>ldg1</ldom_name>
+ *         <state>bound</state>
+ *       </ldom_info>
+ *     </ldom>
+ *     <response>
+ *       <status>success</status>
+ *     </response>
+ *   </data>
+ *   <data version="2.0">
+ *     <ldom>
+ *       <ldom_info>
+ *         <ldom_name>ldg3</ldom_name>
+ *         <state>bound</state>
+ *       </ldom_info>
+ *     </ldom>
+ *     <response>
+ *       <status>success</status>
+ *     </response>
+ *   </data>
+ *   <response>
+ *     <status>success</status>
+ *   </response>
+ *  </cmd>
+ *  <response>
+ *   <status>success</status>
+ *  </response>
+ * </LDM_interface>
+ *
+ * for the following LDOM Manager CLI output:
+ *
+ * # ldm list
+ * Name             State    Flags   Cons    VCPU  Memory   Util  Uptime
+ * primary          active   -t-cv           4     1G       0.0%  0s
+ * ldg1             bound    ----v   5000    4     1G
+ * ldg3             bound    ----v   5001    4     1G
+ */
+int
+parse_xml_get_ldom_cnt(xmlDoc *doc, int *ldom_cnt)
+{
+    char        *ldm_name = NULL;
+    int        ret = 0;
+    int        num_ldoms = 0;
+    xmlNodePtr    root_node = NULL;
+    xmlNodePtr    cmd_node = NULL;
+    xmlNodePtr    data_node = NULL;
+    xmlNodePtr    ldom_node = NULL;
+    xmlNodePtr    response_node = NULL;
+    xmlNodePtr    status_node = NULL;
+    xmlNodePtr    subnode;
+    xmlChar        *content = NULL;
+
+    *ldom_cnt = 0;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_cnt(ENTER)\n");
+
+    root_node = xmlDocGetRootElement(doc);
+
+    if (parse_xml_get_response_status(root_node) == -1)
+        return(-1);
+
+    cmd_node = xml_find_subnode(root_node, XML_CMD);
+    if (cmd_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_cnt.. XML file does not have <cmd> tag\n");
+        return (-1);
+    }
+
+    data_node = xml_find_subnode(cmd_node, XML_DATA);
+
+    /* We did not find a data section. No work can be done without this */
+    if (data_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_cnt.. XML file does not have <data> tag\n");
+        return (-1);
+    }
+
+    /* 
+     * There will be a <data></data> tag pair for each <ldom><ldom_info> pair. 
+     * We don't care about the <status> tags with the <data> tags becuase we
+     * already checked the outermost <status>
+     */
+    while (1) {
+
+        ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+
+        if (ldom_node != NULL) {
+            subnode = ldom_node->xmlChildrenNode;
+
+            while (subnode != NULL) {
+                if (subnode->type != XML_ELEMENT_NODE) {
+                    subnode = subnode->next;
+                    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldom_cnt.. found non-element node under <ldom_info> continue\n");
+                    continue;
+                }
+                if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldom_cnt.. found element node %s\n",subnode->name);
+
+                if (xmlStrcmp(subnode->name, (const xmlChar *)XML_LDM_INFO) == 0) {
+                    subnode = subnode->next;
+                    ++num_ldoms;
+                    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_ldom_cnt.. found <ldom_info> ldom_cnt=%d\n", num_ldoms);
+                    
+                    /* I think we can break at this point instead of continue.  View the debug
+                       to verify this. */
+                    continue;
+                }
+                subnode = subnode->next;
+            }
+        }
+
+
+        /* 
+         * xml response for list-domain has <data> tags for each ldom info,
+         * so get the next data section
+         */
+        data_node = xml_get_next_ele_node(data_node);
+
+        if (data_node == NULL)
+            break;
+    }
+
+    *ldom_cnt = num_ldoms;
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_ldom_cnt(EXIT): ldom_cnt=%d\n", num_ldoms);
+
+    return (ret);
+} /* parse_xml_get_ldom_cnt() */
+
+
+/*
+ * parse_xml_get_mem_rp
+ *
+ * This function gets the memory resource pool data (quantity and unit) by parsing the
+ * XML output from the LDOM Manager.
+ *
+ * Input:
+ *  xml doc - XML document to read
+ *            "list-devices" xml output for capacity data and
+ *            "list-bindings" xml output for reserved data
+ *  rp_type - indicates either capacity or reserved
+ *             RP_CAPACITY = capacity resource
+ *             RP_RESERVED = reserved resource
+ *
+ * Output (pointers are used to pass information from this function to the caller):
+ *  rp_qty - pointer to the integer for the resource pool quantity
+ *  unit - pointer to the allocation unit
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *
+ * NOTE:
+ * This function will tally up the available (with <free> tags in the "list-devices"
+ * xml output) and reserved (with <binding> tags in the "list-bindings" xml output)
+ * for the memory resource pool.
+ *
+ * Example -  portion of the XML document that this function will parse to get the
+ *            memory resource pool info:
+ *
+ * for capacity resource:
+ * <LDM_interface version="1.0">
+ *   <cmd>
+ *    <action>list-devices</action>
+ *    <data version="2.0">
+ *     <ldom>
+ *       <ldom_info>
+ *         <ldom_name>primary</ldom_name>
+ *       </ldom_info>
+ *      <memory>
+ *       <free>
+ *         <phys_addr>0xc4800000</phys_addr>
+ *         <size>29624M</size>
+ *       </free>
+ *     </memory>
+ *..
+ * for reserved resource:
+ * <LDM_interface version="1.0">
+ *   <cmd>
+ *    <action>list-bindings</action>
+ *    <data version="2.0">
+ *     <ldom>
+ *       <ldom_info>
+ *         <ldom_name>primary</ldom_name>
+ *       </ldom_info>
+ *      <memory>
+ *         <size>1G</size>
+ *         <binding>
+ *           <real_addr>0x4000000</real_addr>
+ *           <phys_addr>0x4000000</phys_addr>
+ *           <size>1G</size>
+ *         </binding>
+ *       </memory>
+ * ...
+ *
+ */
+int
+parse_xml_get_mem_rp(xmlDoc *doc, int rp_type, ulong_t *rp_qty, int *unit)
+{
+        int             ret = 0;
+        xmlNodePtr      root_node = NULL;
+        xmlNodePtr      cmd_node = NULL;
+        xmlNodePtr      data_node = NULL;
+        xmlNodePtr      ldom_node = NULL;
+        xmlNodePtr      memory_node = NULL;
+        xmlNodePtr      phys_addr_node = NULL;
+        xmlNodePtr      size_node = NULL;
+        xmlChar         *content = NULL;
+        xmlChar        *search_tag;
+
+        xmlNodePtr      subnode;
+
+        unsigned long long         size = 0;
+        unsigned long long         total_size = 0;
+
+        /* use GB as default, but change it to smaller unit if found */
+        int        mem_unit = LDOMMEMUNIT_GIGABYTES ;
+        char *endp;
+
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp (ENTER) \n");
+
+        root_node = xmlDocGetRootElement(doc);
+
+        if (parse_xml_get_response_status(root_node) == -1)
+            return(-1);
+
+        /* for capacity, look for <free> tag and
+         * for reserved, look for <binding> tag */
+        if (rp_type == RP_CAPACITY)
+            search_tag = XML_FREE;
+        else
+            search_tag = XML_BINDING;
+
+        cmd_node = xml_find_subnode(root_node, XML_CMD);
+        if (cmd_node == NULL) {
+            if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_mem_rp.. XML file does not have <cmd> tag\n");
+            return (-1);
+        }
+
+        data_node = xml_find_subnode(cmd_node, XML_DATA);
+        if (data_node == NULL) {
+            if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_mem_rp.. XML file does not have <data> tag\n");
+            return (-1);
+        }
+
+        /* get capacity data from list-devices which does not have <ldom> tag
+         * and get reserved data from list-bindings which has <ldom> tag
+         */
+        if (rp_type == RP_RESERVED) {
+            ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+            if (ldom_node == NULL) {
+                if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_mem_rp.. XML file does not have <ldom> tag\n");
+                return (-1);
+            }
+        }
+
+        while (1) {
+
+           if (rp_type == RP_CAPACITY)
+               memory_node = xml_find_subnode(data_node, MEMORY_NODE);
+           else
+               memory_node = xml_find_subnode(ldom_node, MEMORY_NODE);
+
+           if (memory_node == NULL) {
+               if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. XML file does not have <mem> tag\n");
+           }
+
+           if (memory_node != NULL) {
+               subnode = memory_node->xmlChildrenNode;
+               while (subnode != NULL) {
+                   if (subnode->type != XML_ELEMENT_NODE) {
+                       subnode = subnode->next;
+                       continue;
+                   }
+
+                   if (xmlStrcmp(subnode->name, search_tag) == 0) {
+
+                       if (rp_type == 1)
+                           if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. <free>tag found\n");
+                       else
+                           if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. <binding>tag found\n");
+
+
+                       /* get phys addr data */
+                       phys_addr_node = xml_find_subnode(subnode, XML_PHYS_ADDR);
+                       if (phys_addr_node != NULL) {
+                           if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. <phys_addr>tag found\n");
+                           content = xmlNodeGetContent(phys_addr_node);
+                           if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. phys_addr=%s\n", content);
+                           xmlFree(content);
+
+                       }
+
+                       /* get mem size data */
+                       size_node = xml_find_subnode(subnode, SIZE_NODE);
+                       if (size_node != NULL) {
+                           if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. <size>tag found\n");
+                           content = xmlNodeGetContent(size_node);
+                           if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. size=%s\n", content);
+
+                           /* extract the number and unit from the content */
+                           /* and calculate memory size in the smallest unit - "bytes"  */
+                           size = strtoull((char *)content, &endp, 0);
+                           if (size <= 0) {
+                               if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. Invalid mem size specified: %s\n", content);
+                           }
+                           xmlFree(content);
+
+                           /* get the memory unit */
+                           /* and calculate the size in "bytes" which is the possible smallest memory unit */
+                           switch (strlen(endp)) {
+                            case 0: break;
+                            default:
+                                switch (endp[strlen(endp)-1]) {
+                                case 'G':
+                                case 'g':
+                                   if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. unit in GB\n");
+                                   size = size * MEM_GB_BYTES;
+                                   break;
+                                case 'M':
+                                case 'm':
+                                   if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. unit in MB\n");
+                                   size = size * MEM_MB_BYTES;
+                                   /* if megabyates is the smallest unit used so far,
+                                    * change the mem_unit to "megabyates" */
+                                   if (mem_unit == LDOMMEMUNIT_GIGABYTES)
+                                        mem_unit =  LDOMMEMUNIT_MEGABYTES;
+                                    break;
+                                case 'K':
+                                case 'k':
+                                    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. unit in KB\n");
+                                    size = size * MEM_KB_BYTES;
+                                    /* if kilobytes is the smallest unit used so far,
+                                     * change the mem_unit to "kilobytes" */
+                                    if ((mem_unit == LDOMMEMUNIT_GIGABYTES) ||
+                                        (mem_unit == LDOMMEMUNIT_MEGABYTES))
+                                        mem_unit = LDOMMEMUNIT_KILOBYTES;
+                                        break;
+                                default:
+                                    if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp..unit in bytes\n");
+                                    /* if no memory unit is specified, use the default unit "bytes",
+                                     * and set the smallest unit used to "bytes" */
+                                    mem_unit = LDOMMEMUNIT_BYTES;
+                                    break;
+                                }
+                                break;
+                            }
+
+                            /* add up each strand rp_qty to calculate the total rp_qty */
+                            total_size = total_size + size;
+
+                            if (ldoms_detailed_debug) dprt( 
+                               "LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. size=%llu total_size=%llu in bytes\n",
+                               size, total_size);
+                       }
+
+
+                       subnode = subnode->next;
+                       continue;
+                   }
+
+                   subnode = subnode->next;
+               }
+
+          }
+
+          /* xml response for list has <data> tags for each <ldom_info>
+           * so, get the next data section
+           */
+          data_node = xml_get_next_ele_node(data_node);
+
+          if (data_node == NULL)
+                break;
+
+          if (rp_type == RP_RESERVED) {
+                ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+                if (ldom_node == NULL) {
+                        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_mem_rp.. XML file does not have <ldom> tag\n");
+                        break;
+                }
+          }
+
+    }
+
+
+
+    /* recalculate mem size using the selected unit which is smallest unit in use */
+    if (mem_unit == LDOMMEMUNIT_BYTES)
+            *rp_qty = total_size;
+    else if (mem_unit == LDOMMEMUNIT_KILOBYTES)
+            *rp_qty = total_size / MEM_KB_BYTES;
+    else if (mem_unit ==  LDOMMEMUNIT_MEGABYTES)
+        *rp_qty = total_size / MEM_MB_BYTES;
+    else if (mem_unit == LDOMMEMUNIT_GIGABYTES)
+        *rp_qty = total_size / MEM_GB_BYTES;
+
+    *unit = mem_unit;
+
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_mem_rp(EXIT): size=%llu in unit=%d\n",
+        total_size, mem_unit);
+
+        return(0);
+
+} /* parse_xml_get_mem_rp */
+
+
+/*
+ * parse_xml_get_cpu_rp
+ *
+ * This function gets the total number of CPUs (either free or bound depending on
+ * the rp_type) by parsing the XML output from the LDOM Manager.
+ *
+ * XX - copied from the MIB code, but changed to retrieve the number of
+ *      CPUs instead of the CPU resource pool quantity.
+ * 
+ * Input:
+ *  xml doc - XML document to read
+ *            "list-devices" xml output for capacity data and
+ *            "list-bindings" xml output for reserved data
+ *  rp_type - indicates either capacity or reserved
+ *             RP_CAPACITY = capacity resource
+ *             RP_RESERVED = reserved resource
+ *
+ * Output (pointers are used to pass information from this function to the caller):
+ *  rp_qty - pointer to the integer for the number of CPUs 
+ *  unit -  pointer to the allocation unit (always using 1 for Mhz) 
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *
+ * NOTE:
+ * This function will tally up the number of free (with <free> tags in the "list-devices"
+ * xml output) and reserved (with <binding> tags in the "list-bindings" xml output) CPUs. 
+ *
+ * Example -  portion of the XML document that this function will parse to get the
+ *            CPU resource pool info:
+ *
+ * for capacity resource:
+ * <LDM_interface version="1.0">
+ *   <cmd>
+ *    <action>list-devices</action>
+ *    <data version="2.0">
+ *    <cpu>
+ *       <free>
+ *         <pid>12</pid>
+ *         <strand_percent>100</strand_percent>
+ *       </free>
+ *       <free>
+ *         <pid>13</pid>
+ *         <strand_percent>100</strand_percent>
+ *       </free>
+ *..
+ *..
+ * for reserved resource:
+ * <LDM_interface version="1.0">
+ *   <cmd>
+ *    <action>list-bindings</action>
+ *    <data version="2.0">
+ *     <ldom>
+ *       <ldom_info>
+ *         <ldom_name>primary</ldom_name>
+ *       </ldom_info>
+ *       <cpu>
+ *          <number>4</number>
+ *          <binding>
+ *            <vid>0</vid>
+ *            <pid>0</pid>
+ *            <strand_percent>100</strand_percent>
+ *         </binding>
+ * ...
+ *
+ */
+int
+parse_xml_get_cpu_rp(xmlDoc *doc, int rp_type, ulong_t *rp_qty, int *unit)
+{
+    int             ret = 0;
+    xmlNodePtr      root_node = NULL;
+    xmlNodePtr      cmd_node = NULL;
+    xmlNodePtr      data_node = NULL;
+    xmlNodePtr      ldom_node = NULL;
+    xmlNodePtr      cpu_node = NULL;
+    xmlNodePtr      pid_node = NULL;
+    xmlNodePtr      strand_percent_node = NULL;
+    xmlChar         *content = NULL;
+    xmlChar        *search_tag;
+
+    xmlNodePtr      subnode;
+
+    ulong_t         strand_rp_qty = 0;
+    ulong_t         total_rp_qty = 0;
+
+    int             cpu_unit = 1; /* default MHz */
+
+    int             ncpu = 0;
+
+    /*
+     * Get the processor clock speed using processor_info()
+     * which takes processor id as input and returns the status of
+     * the processor in the processor_info_t structure.
+     *
+     * The pi_clock member is the processor clock frequency rounded
+     * to the nearest MHz.  It may be 0 if not known.
+     *
+     * Since processor_info doesn't provide the guest domain's
+     * processor info, we just need to find a CPU on the control
+     * domain, but we don't know which physical CPUs the control
+     * domain has.  So just loop on the 1st 64, which should contain
+     * at least 1 CPU in the control domain.
+     */
+    processor_info_t cpu_info;
+    int             pid = 0; /* use primary domain's processor id */
+    int             p_clock = 1600; /* processor clock speed in MHz */
+                                    /* use 1600 MHz as default */
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_rp(ENTER)\n");
+
+
+    /* get the processor clock speed in MHz */
+    while ((pid < 64) && (processor_info(pid++, &cpu_info) != 0) );
+
+    /* get the processor clock speed in MHz */
+    if (pid <= 64) {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: ldomsNodeGetInfo(). processor_info with pid=%d clock=%d\n",
+                   pid, cpu_info.pi_clock);
+        p_clock = cpu_info.pi_clock;
+    }
+
+    root_node = xmlDocGetRootElement(doc);
+
+    if (parse_xml_get_response_status(root_node) == -1)
+            return(-1);
+
+    /* for capacity, look for <free> tag and
+     * for reserved, look for <binding> tag */
+    if (rp_type == 1)
+        search_tag = XML_FREE;
+    else
+        search_tag = XML_BINDING;
+
+    cmd_node = xml_find_subnode(root_node, XML_CMD);
+    if (cmd_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_rp.. XML file does not have <cmd> tag\n");
+        return (-1);
+    }
+
+    data_node = xml_find_subnode(cmd_node, XML_DATA);
+    if (data_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_rp.. XML file does not have <data> tag\n");
+        return (-1);
+    }
+
+    /* get capacity data from list-devices which does not have <ldom> tag
+     * and get reserved data from list-bindings which has <ldom> tag
+     */
+    if (rp_type == RP_RESERVED) {
+        ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+        if (ldom_node == NULL) {
+            if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_rp.. XML file does not have <ldom> tag\n");
+            return (-1);
+        }
+    }
+
+    while (1) {
+
+       if (rp_type == RP_CAPACITY)
+               cpu_node = xml_find_subnode(data_node, CPU_NODE);
+       else
+               cpu_node = xml_find_subnode(ldom_node, CPU_NODE);
+
+       if (cpu_node == NULL) {
+                if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_cpu_rp.. XML file does not have <cpu> tag\n");
+       }
+
+       if (cpu_node != NULL) {
+
+          subnode = cpu_node->xmlChildrenNode;
+          while (subnode != NULL) {
+             if (subnode->type != XML_ELEMENT_NODE) {
+                 subnode = subnode->next;
+                 continue;
+             }
+
+
+             if (xmlStrcmp(subnode->name, search_tag) == 0) {
+
+                 if (rp_type == RP_CAPACITY)
+                     if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_cpu_rp.. <free>tag found\n");
+                 else
+                     if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_cpu_rp.. <binding>tag found\n");
+
+                 /* add up the number of CPUs */
+                 ncpu++;
+
+
+                 subnode = subnode->next;
+                 continue;
+             }
+
+             subnode = subnode->next;
+            }
+
+         }
+
+
+        /* xml response for list has <data> tags for each <ldom_info>
+         * so, get the next data section
+         */
+        data_node = xml_get_next_ele_node(data_node);
+
+        if (data_node == NULL)
+            break;
+
+        if (rp_type == RP_RESERVED) {
+            ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+            if (ldom_node == NULL) {
+                if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_cpu_rp.. XML file does not have <ldom> tag\n");
+                break;
+            }
+        }
+
+    }
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_rp(EXIT): total number of CPUs=%d frequency (in Mhz)=%d\n", ncpu, p_clock);
+
+    *rp_qty = ncpu;
+    *unit = cpu_unit;
+
+    return(0);
+} /* parse_xml_get_cpu_rp */
+
+/*
+ * parse_xml_get_cpu_bindings
+ *
+ * This function gets the CPU binding info for a domain.
+ * Specifically, the real and virtual CPU ids, the State for the CPU,
+ * and the CPU uptime, which is pretty much the same as the uptime of
+ * the Domain.
+ * 
+ * Input:
+ *  xml_received - XML document to read
+ *  cpuBindings - Pointer to a structure to hold the binding info
+ *
+ * Output 
+ *  cpuBindings - Pointer to a structure with the binding info
+ *
+ * Returns:
+ *  0 if the operation is successful
+ *  -1 if the operation fails
+ *
+ * Example XML response from a list-bindings request for a domain
+ * <LDM_interface version="1.0">
+ *   <cmd>
+ *    <action>list-bindings</action>
+ *    <data version="2.0">
+ *     <ldom>
+ *       <ldom_info>
+ *         <ldom_name>primary</ldom_name>
+ *       </ldom_info>
+ *       <cpu>
+ *          <number>4</number>
+ *          <binding>
+ *            <vid>0</vid>
+ *            <pid>0</pid>
+ *            <strand_percent>100</strand_percent>
+ *         </binding>
+ * ...
+ *
+ */
+int
+parse_xml_get_cpu_bindings(xmlDoc *doc, cpuBindings_t **cpuBindings)
+{
+    cpuBindings_t *headcpuBindings = NULL;
+    cpuBindings_t *newBinding = NULL;
+    cpuBindings_t *prevBinding = NULL;
+
+    xmlNodePtr      root_node = NULL;
+    xmlNodePtr    cmd_node = NULL;
+    xmlNodePtr    data_node = NULL;
+    xmlNodePtr    ldom_node = NULL;
+    xmlNodePtr    cpu_node = NULL;
+    xmlNodePtr    id_node = NULL;
+    xmlChar        *virtID = NULL;
+    xmlChar        *realID = NULL;
+    xmlNodePtr    subnode;
+
+    int        ret = 0;
+    int        numCpus = 0;
+    int        ncpu = 0;
+
+    if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_bindings(ENTER)\n");
+    root_node = xmlDocGetRootElement(doc);
+
+    if (parse_xml_get_response_status(root_node) == -1) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_bindings() no response/status tags in the XML rsp\n");
+        return(-1);
+    }
+
+    cmd_node = xml_find_subnode(root_node, XML_CMD);
+    if (cmd_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_bindings() XML file does not have <cmd> tag\n");
+        return (-1);
+    }
+
+    data_node = xml_find_subnode(cmd_node, XML_DATA);
+    if (data_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_bindings() XML file does not have <data> tag\n");
+        return (-1);
+    }
+
+    ldom_node = xml_find_subnode(data_node, LDOM_NODE);
+    if (ldom_node == NULL) {
+        if (ldoms_debug) dprt("LDOMS_DEBUG: parse_xml_get_cpu_bindings() XML file does not have <ldom> tag\n");
+        return (-1);
+    }
+
+    cpu_node = xml_find_subnode(ldom_node, CPU_NODE);
+
+    if (cpu_node == NULL) {
+        if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_cpu_bindings() XML file does not have <cpu> tag\n");
+        return(-1);
+    }
+
+    subnode = cpu_node->xmlChildrenNode;
+    while (subnode != NULL) {
+
+        if (xmlStrcmp(subnode->name, XML_BINDING) == 0) {
+
+           if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_cpu_bindings() <binding>tag found\n");
+
+                    
+           /* Allocate a new cpuBindings struct to hold the info for the binding.
+            * This is regular single linked list stuff. 
+            */
+           if (headcpuBindings == NULL)  {
+               newBinding = malloc(sizeof(cpuBindings_t));
+               headcpuBindings = newBinding;
+               prevBinding = newBinding;
+               newBinding->next = NULL;
+           }
+           else {
+               newBinding = malloc(sizeof(cpuBindings_t));
+               prevBinding->next = newBinding;
+               newBinding->next = NULL;
+               prevBinding = newBinding;
+           }
+
+           /* Get the <vid> node and its value. subnode points to <binding> */
+           id_node = subnode->xmlChildrenNode;
+           virtID = xmlNodeGetContent(id_node);
+           newBinding->virt = (unsigned int)atoi((const char *)virtID);
+           xmlFree(virtID);
+                    
+           /* Get the <pid> node and its value */
+           id_node = id_node->next;
+           realID = xmlNodeGetContent(id_node);
+           newBinding->real = (int)atoi((const char *)realID);
+           xmlFree(realID);
+
+           if (ldoms_detailed_debug) dprt("LDOMS_DETAILED_DEBUG: parse_xml_get_cpu_bindings() virt/real = %d/%d \n",newBinding->virt, newBinding->real);
+    
+           numCpus++;
+                    
+       }
+
+       subnode = subnode->next;
+   } /* while */
+        
+   *cpuBindings = headcpuBindings;
+   return(numCpus);
+} /* parse_xml_get_cpu_bindings */
+
+
+#endif /* WITH_LDOMS */
+
+/*
+ * vim: set tabstop=4:
+ * vim: set shiftwidth=4:
+ * vim: set expandtab:
+ */
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
+

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