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