Hello all,

I've been working on a libvirt extension to manage IBM's Power VMs
(LPARs). The Power systems are managed through management console
referred to as the HMC or using a management partition (IVM). Both HMC
and IVM runs an SSH, then you can reach it via command line, and an HTTP
server, then you can reach it via web browser.

The protocol between the console and the partition (LPAR) is not
disclosed, therefore I propose the driver to execute commands remoetly
over an SSH connection to the consoles to manage IBM LPARs.

The patch attached is the first scratch of the driver that will interact
with HMC over a SSH connection. The URI model that is
used in virsh command line is:

virsh --conect phyp://$u...@$server

Some known issues are:
 * Next step is to make the URI like this: phyp://$user@
$HMC/@managed_system. Almost finished. What it takes now is
$server = $HMC = $managed_system.
 * Next features in my TODO list are "resume", "stop" and "reboot" the
LPAR.

Any comments are welcome.

Thanks,


-- 
Eduardo Otubo
Software Engineer
Linux Technology Center
IBM Systems & Technology Group
Mobile: +55 19 8135 0885 
ot...@linux.vnet.ibm.com
diff --git a/configure.in b/configure.in
index 6b2bb5e..201a7dc 100644
--- a/configure.in
+++ b/configure.in
@@ -182,6 +182,8 @@ AC_ARG_WITH([uml],
 [  --with-uml              add UML support (on)],[],[with_uml=yes])
 AC_ARG_WITH([openvz],
 [  --with-openvz           add OpenVZ support (on)],[],[with_openvz=yes])
+AC_ARG_WITH([phyp],
+[  --with-phyp             add IBM HMC/IVM  support (on)],[],[with_phyp=yes])
 AC_ARG_WITH([lxc],
 [  --with-lxc              add Linux Container support (on)],[],[with_lxc=yes])
 AC_ARG_WITH([test],
@@ -714,6 +716,21 @@ AM_CONDITIONAL([HAVE_NUMACTL], [test "$with_numactl" != "no"])
 AC_SUBST([NUMACTL_CFLAGS])
 AC_SUBST([NUMACTL_LIBS])
 
+if test "$with_phyp" = "yes"; then
+  AC_CHECK_LIB([ssh],[ssh_new],[
+        LIBSSH_LIBS="$LIBSSH_LIBS -lssh -L/usr/local/lib/"
+        AC_SUBST([LIBSSH_LIBS])],[
+        AC_MSG_ERROR([You must install the libssh to compile Phype driver.])])
+
+  AC_CHECK_HEADERS([libssh/libssh.h],[
+        LIBSSH_CFLAGS="-I/usr/local/include/libssh"
+        AC_SUBST([LIBSSH_CFLAGS])],[
+        AC_MSG_ERROR([Cannot find libssh headers.Is libssh installed ?])],[])
+  AC_DEFINE_UNQUOTED([WITH_PHYP], 1,
+        [whether IBM HMC / IVM driver is enabled])
+fi
+AM_CONDITIONAL([WITH_PHYP],[test "$with_phyp" = "yes"])
+
 dnl virsh libraries
 AC_CHECK_HEADERS([readline/readline.h])
 
@@ -1345,6 +1362,7 @@ AC_MSG_NOTICE([    QEMU: $with_qemu])
 AC_MSG_NOTICE([     UML: $with_uml])
 AC_MSG_NOTICE([  OpenVZ: $with_openvz])
 AC_MSG_NOTICE([     LXC: $with_lxc])
+AC_MSG_NOTICE([ IBM HMC/IVM: $with_phyp])
 AC_MSG_NOTICE([    Test: $with_test])
 AC_MSG_NOTICE([  Remote: $with_remote])
 AC_MSG_NOTICE([ Network: $with_network])
@@ -1373,6 +1391,7 @@ fi
 AC_MSG_NOTICE([])
 AC_MSG_NOTICE([Libraries])
 AC_MSG_NOTICE([])
+AC_MSG_NOTICE([  libssh: $LIBSSH_CFLAGS $LIBSSH_LIBS])
 AC_MSG_NOTICE([  libxml: $LIBXML_CFLAGS $LIBXML_LIBS])
 AC_MSG_NOTICE([  gnutls: $GNUTLS_CFLAGS $GNUTLS_LIBS])
 if test "$with_sasl" != "no" ; then
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index 2c3777d..a61e2f3 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -61,6 +61,7 @@ typedef enum {
     VIR_FROM_UML,       /* Error at the UML driver */
     VIR_FROM_NODEDEV, /* Error from node device monitor */
     VIR_FROM_XEN_INOTIFY, /* Error from xen inotify layer */
+    VIR_FROM_PHYP, /* Error from IBM power hypervisor */
     VIR_FROM_SECURITY,  /* Error from security framework */
 } virErrorDomain;
 
diff --git a/src/Makefile.am b/src/Makefile.am
index d5aac11..787dc37 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,6 +5,7 @@ INCLUDES = \
 	   -I../include \
 	   -...@top_srcdir@/include \
 	   -...@top_srcdir@/qemud \
+	   $(LIBSSH_CFLAGS) \
 	   $(LIBXML_CFLAGS) \
 	   $(XEN_CFLAGS) \
 	   $(SELINUX_CFLAGS) \
@@ -125,6 +126,10 @@ LXC_CONTROLLER_SOURCES =					\
 		veth.c veth.h                                   \
 		cgroup.c cgroup.h
 
+PHYP_DRIVER_SOURCES =						\
+		phyp_conf.c phyp_conf.h \
+		phyp_driver.c phyp_driver.h
+
 OPENVZ_DRIVER_SOURCES =						\
 		openvz_conf.c openvz_conf.h			\
 		openvz_driver.c openvz_driver.h
@@ -255,6 +260,18 @@ endif
 libvirt_driver_xen_la_SOURCES = $(XEN_DRIVER_SOURCES)
 endif
 
+if WITH_PHYP
+if WITH_DRIVER_MODULES
+mod_LTLIBRARIES += libvirt_driver_phyp.la
+else
+noinst_LTLIBRARIES += libvirt_driver_phyp.la
+libvirt_la_LIBADD += libvirt_driver_phyp.la
+endif
+libvirt_driver_phyp_la_LDFLAGS = $(LIBSSH_LIBS)
+libvirt_driver_phyp_la_CFLAGS = $(LIBSSH_CFLAGS)
+libvirt_driver_phyp_la_SOURCES = $(PHYP_DRIVER_SOURCES)
+endif
+
 if WITH_OPENVZ
 if WITH_DRIVER_MODULES
 mod_LTLIBRARIES += libvirt_driver_openvz.la
@@ -403,6 +420,7 @@ EXTRA_DIST +=							\
 		$(LXC_DRIVER_SOURCES)				\
 		$(UML_DRIVER_SOURCES)				\
 		$(OPENVZ_DRIVER_SOURCES)			\
+		$(PHYP_DRIVER_SOURCES)			\
 		$(NETWORK_DRIVER_SOURCES)			\
 		$(STORAGE_DRIVER_SOURCES)			\
 		$(STORAGE_DRIVER_FS_SOURCES)			\
diff --git a/src/driver.h b/src/driver.h
index 62d6fbc..aa85bb9 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -20,6 +20,7 @@ typedef enum {
     VIR_DRV_OPENVZ = 5,
     VIR_DRV_LXC = 6,
     VIR_DRV_UML = 7,
+    VIR_DRV_PHYP = 8,
 } virDrvNo;
 
 
diff --git a/src/libvirt.c b/src/libvirt.c
index f29df6b..80b51c7 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -55,6 +55,9 @@
 #ifdef WITH_OPENVZ
 #include "openvz_driver.h"
 #endif
+#ifdef WITH_PHYP
+#include "phyp_driver.h"
+#endif
 #endif
 
 #define VIR_FROM_THIS VIR_FROM_NONE
@@ -317,6 +320,9 @@ virInitialize(void)
 #ifdef WITH_OPENVZ
     if (openvzRegister() == -1) return -1;
 #endif
+#ifdef WITH_PHYP
+    if (phypRegister() == -1) return -1;
+#endif
 #ifdef WITH_REMOTE
     if (remoteRegister () == -1) return -1;
 #endif
@@ -826,6 +832,10 @@ virGetVersion(unsigned long *libVer, const char *type,
         if (STRCASEEQ(type, "LXC"))
             *typeVer = LIBVIR_VERSION_NUMBER;
 #endif
+#if WITH_PHYP
+        if (STRCASEEQ(type, "Phyp"))
+            *typeVer = LIBVIR_VERSION_NUMBER;
+#endif
 #if WITH_OPENVZ
         if (STRCASEEQ(type, "OpenVZ"))
             *typeVer = LIBVIR_VERSION_NUMBER;
diff --git a/src/phyp_conf.c b/src/phyp_conf.c
new file mode 100644
index 0000000..4317936
--- /dev/null
+++ b/src/phyp_conf.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright IBM Corp. 2009
+ *
+ * phyp_driver.c: ssh layer to access Power Hypervisors
+ *
+ * Authors:
+ *  Eduardo Otubo <otubo at linux.vnet.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <config.h>
diff --git a/src/phyp_conf.h b/src/phyp_conf.h
new file mode 100644
index 0000000..51ca65e
--- /dev/null
+++ b/src/phyp_conf.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright IBM Corp. 2009
+ *
+ * phyp_driver.c: ssh layer to access Power Hypervisors
+ *
+ * Authors:
+ *  Eduardo Otubo <otubo at linux.vnet.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sys/types.h>
+#include <config.h>
+
+#include "internal.h"
+#include "capabilities.h"
+#include "domain_conf.h"
+/* Main driver state */
+typedef struct __phyp_driver phyp_driver_t;
+struct __phyp_driver {
+    virMutex lock;
+
+    virCapsPtr *caps;
+
+    virDomainObjList *domains;
+
+    char *configDir;
+    char *autostartDir;
+    char *stateDir;
+    char *logDir;
+    int have_netns;
+};
diff --git a/src/phyp_driver.c b/src/phyp_driver.c
new file mode 100644
index 0000000..89b3e8c
--- /dev/null
+++ b/src/phyp_driver.c
@@ -0,0 +1,501 @@
+
+/*
+ * Copyright IBM Corp. 2009
+ *
+ * phyp_driver.c: ssh layer to access Power Hypervisors
+ *
+ * Authors:
+ *  Eduardo Otubo <otubo at linux.vnet.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <limits.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include <libssh/libssh.h>
+
+#include "internal.h"
+#include "datatypes.h"
+#include "buf.h"
+#include "memory.h"
+
+#include "phyp_driver.h"
+#include "phyp_conf.h"
+
+/*
+ * XXX: Here I consider the managed system name as
+ * being the server name.
+ * */
+
+/*
+ * TODO: I still need to implement a way to distinguish
+ * an HMC from an IVM
+ * */
+
+static virDrvOpenStatus
+phypOpen(virConnectPtr conn,
+         virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+         int flags ATTRIBUTE_UNUSED)
+{
+    if (!conn || !conn->uri)
+        return VIR_DRV_OPEN_DECLINED;
+
+    if (conn->uri->scheme == NULL || conn->uri->server == NULL)
+        return VIR_DRV_OPEN_DECLINED;
+
+    int ssh_auth = 0, exit_status = 0;
+    char *banner;
+    char *password;
+
+    SSH_SESSION *session;
+    SSH_OPTIONS *opt;
+
+    session = ssh_new();
+    opt = ssh_options_new();
+
+    if (!conn->uri->port)
+        conn->uri->port = 22;
+
+    /*setting some ssh options */
+    ssh_options_set_host(opt, conn->uri->server);
+    ssh_options_set_port(opt, conn->uri->port);
+    ssh_options_set_username(opt, conn->uri->user);
+    ssh_set_options(session, opt);
+
+    /*starting ssh connection */
+    if (ssh_connect(session)) {
+        fprintf(stderr, "Connection failed : %s\n",
+                ssh_get_error(session));
+        ssh_disconnect(session);
+        ssh_finalize();
+        exit_status = SSH_CONN_ERR;
+        return VIR_DRV_OPEN_DECLINED;
+    }
+
+    /*trying to use pub key */
+    if ((ssh_auth =
+         ssh_userauth_autopubkey(session, NULL)) == SSH_AUTH_ERROR) {
+        fprintf(stderr, "Authenticating with pubkey: %s\n",
+                ssh_get_error(session));
+        exit_status = SSH_AUTH_PUBKEY_ERR;
+        return VIR_DRV_OPEN_DECLINED;
+    }
+
+    if ((banner = ssh_get_issue_banner(session))) {
+        printf("%s\n", banner);
+        VIR_FREE(banner);
+    }
+
+    if (ssh_auth != SSH_AUTH_SUCCESS) {
+        password = getpass("Password: ");
+        if (ssh_userauth_password(session, NULL, password) !=
+            SSH_AUTH_SUCCESS) {
+            fprintf(stderr, "Authentication failed: %s\n",
+                    ssh_get_error(session));
+            ssh_disconnect(session);
+            memset(password, 0, strlen(password));
+            exit_status = SSH_AUTH_ERR;
+            return VIR_DRV_OPEN_DECLINED;
+        } else
+            goto exec;
+    } else
+        goto exec;
+
+  exec:
+    conn->privateData = session;
+    return VIR_DRV_OPEN_SUCCESS;
+}
+
+static int
+phypClose(virConnectPtr conn)
+{
+    SSH_SESSION *ssh_session = conn->privateData;
+
+    ssh_disconnect(ssh_session);
+
+    return 0;
+}
+
+static int
+__inner_exec_command(SSH_SESSION * session, char *cmd,
+                     char *textual_return)
+{
+    CHANNEL *channel = channel_new(session);
+    BUFFER *readbuf = buffer_new();
+
+    int exit_status = 0, temp_return = 0, buffer_size = 0;
+
+    memset(textual_return, 0, sizeof(textual_return));
+
+    if (channel_open_session(channel) == SSH_ERROR)
+        return SSH_CHANNEL_OPEN_ERR;
+
+    if (channel_request_exec(channel, cmd) == SSH_ERROR)
+        return SSH_CHANNEL_EXEC_ERR;
+
+    while (channel && channel_is_open(channel)) {
+        temp_return = channel_read(channel, readbuf, 0, 0);
+
+        strncat(textual_return, buffer_get(readbuf),
+                buffer_get_len(readbuf));
+        buffer_size += buffer_size + buffer_get_len(readbuf);
+
+        if (temp_return == 0) {
+            textual_return[buffer_size + 1] = 0;
+            exit_status = channel_get_exit_status(channel);
+            break;
+        }
+    }
+
+    if (channel_send_eof(channel) == SSH_ERROR)
+        return SSH_CHANNEL_SEND_EOF_ERR;
+
+    if (channel_close(channel) == SSH_ERROR)
+        return SSH_CHANNEL_CLOSE_ERR;
+
+    return exit_status;
+}
+
+static int
+phypGetLparID(SSH_SESSION * ssh_session, const char *managed_system,
+              const char *name)
+{
+    char id_c[10];
+    unsigned int i = 0;
+    int ret = 0;
+    char *cmd;
+    char *textual_return;
+
+    if (VIR_ALLOC_N(cmd, MAXSIZE+sizeof(name)+sizeof(managed_system))) {
+        return PHYP_NO_MEM;
+    }
+
+    if (VIR_ALLOC_N(textual_return, MAXSIZE)) {
+        return PHYP_NO_MEM;
+    }
+
+    memset(id_c, 0, sizeof(id_c));
+
+    sprintf(cmd,
+            "lssyscfg -r lpar -m %s --filter lpar_names=%s -F lpar_id",
+            managed_system, name);
+    ret = __inner_exec_command(ssh_session, cmd, textual_return);
+
+    if (ret) {
+        CLEANUP;
+        return LPAR_EXEC_ERR;
+    }
+
+    for (i = 0; textual_return[i] != '\n'; i++)
+        id_c[i] = textual_return[i];
+    id_c[i] = '\0';
+
+    CLEANUP;
+    return atoi(id_c);
+}
+
+static int
+phypGetLparNAME(SSH_SESSION * ssh_session, const char *managed_system,
+                unsigned int lpar_id, char *lpar_name)
+{
+    unsigned int i = 0;
+    int ret = 0;
+    char *cmd;
+    char *textual_return;
+
+    if (VIR_ALLOC_N(cmd, MAXSIZE+sizeof(managed_system))) {
+        return PHYP_NO_MEM;
+    }
+
+    if (VIR_ALLOC_N(textual_return, MAXSIZE)) {
+        return PHYP_NO_MEM;
+    }
+
+    sprintf(cmd,
+            "lssyscfg -r lpar -m %s --filter lpar_ids=%d -F name",
+            managed_system, lpar_id);
+    ret = __inner_exec_command(ssh_session, cmd, textual_return);
+
+    if (ret) {
+        CLEANUP;
+        lpar_name = NULL;
+        return LPAR_EXEC_ERR;
+    }
+
+    for (i = 0; textual_return[i] != '\n'; i++)
+        lpar_name[i] = textual_return[i];
+    lpar_name[i] = '\0';
+
+    CLEANUP;
+    return ret;
+}
+
+static int
+phypGetLparUUID(SSH_SESSION * ssh_session, const char *managed_system,
+                unsigned int lpar_id, unsigned char *lpar_uuid)
+{
+    unsigned int i = 0;
+    int ret = 0;
+    char *cmd;
+    char *textual_return;
+
+    if (VIR_ALLOC_N(cmd, MAXSIZE+sizeof(managed_system))) {
+        return PHYP_NO_MEM;
+    }
+
+    if (VIR_ALLOC_N(textual_return, MAXSIZE)) {
+        return PHYP_NO_MEM;
+    }
+
+    sprintf(cmd,
+            "lssyscfg -r lpar -m %s --filter lpar_ids=%d -F logical_serial_num",
+            managed_system, lpar_id);
+    ret = __inner_exec_command(ssh_session, cmd, textual_return);
+
+    if (ret) {
+        CLEANUP;
+        lpar_uuid = NULL;
+        return LPAR_EXEC_ERR;
+    }
+
+    for (i = 0; textual_return[i] != '\n'; i++)
+        lpar_uuid[i] = textual_return[i];
+    lpar_uuid[i] = '\0';
+
+    CLEANUP;
+    return ret;
+}
+
+static int
+phypNumDomains(virConnectPtr conn)
+{
+    SSH_SESSION *ssh_session = conn->privateData;
+    const char *managed_system = conn->uri->server;
+    int ret = 0;
+    unsigned int i = 0, ndom = 1;
+    char *cmd;
+    char *textual_return;
+
+    if (VIR_ALLOC_N(cmd, MAXSIZE+sizeof(managed_system))) {
+        return PHYP_NO_MEM;
+    }
+
+    if (VIR_ALLOC_N(textual_return, MAXSIZE)) {
+        return PHYP_NO_MEM;
+    }
+
+    sprintf(cmd, "lssyscfg -r lpar -m %s -F lpar_id", managed_system);
+    ret = __inner_exec_command(ssh_session, cmd, textual_return);
+
+    if (ret) {
+        CLEANUP;
+        return 0;
+    }
+
+    for (i = 0; textual_return[i] != 0; i++)
+        if (textual_return[i] == '\n')
+            ndom++;
+
+    VIR_FREE(cmd);
+    VIR_FREE(textual_return);
+    return ndom;
+}
+
+static int
+phypListDomains(virConnectPtr conn, int *ids, int nids)
+{
+    SSH_SESSION *ssh_session = conn->privateData;
+    const char *managed_system = conn->uri->server;
+    int ret = 0;
+    char id_c[10];
+    unsigned int i = 0, j = 0;
+    char *cmd;
+    char *textual_return;
+
+    if (VIR_ALLOC_N(cmd, MAXSIZE+sizeof(managed_system))) {
+        return PHYP_NO_MEM;
+    }
+
+    if (VIR_ALLOC_N(textual_return, MAXSIZE)) {
+        return PHYP_NO_MEM;
+    }
+
+    nids = 0;
+
+    memset(id_c, 0, 10);
+    sprintf(cmd, "lssyscfg -r lpar -m %s -F lpar_id", managed_system);
+    ret = __inner_exec_command(ssh_session, cmd, textual_return);
+
+    for (i = 0; textual_return[i] != 0; i++) {
+        if (textual_return[i] == '\n') {
+            ids[nids] = atoi(id_c);
+            memset(id_c, 0, 10);
+            j = 0;
+            nids++;
+            continue;
+        }
+        id_c[j] = textual_return[i];
+        j++;
+    }
+
+    VIR_FREE(cmd);
+    VIR_FREE(textual_return);
+    return nids;
+}
+
+static virDomainPtr
+phypDomainLookupByName(virConnectPtr conn, const char *name)
+{
+    SSH_SESSION *ssh_session = conn->privateData;
+    virDomainPtr dom = NULL;
+    const char *managed_system = conn->uri->server;
+    unsigned char *lpar_uuid;
+
+    if (VIR_ALLOC_N(lpar_uuid, 100 * sizeof(char))) {
+        return NULL;
+    }
+    int lpar_id = 0;
+
+    lpar_id = phypGetLparID(ssh_session, managed_system, name);
+    if (lpar_id == PHYP_NO_MEM)
+        return NULL;
+
+    if (phypGetLparUUID(ssh_session, managed_system, lpar_id, lpar_uuid) ==
+        PHYP_NO_MEM)
+        return NULL;
+
+    dom = virGetDomain(conn, name, lpar_uuid);
+
+    if (dom)
+        dom->id = lpar_id;
+
+    VIR_FREE(lpar_uuid);
+    return dom;
+}
+
+static virDomainPtr
+phypDomainLookupByID(virConnectPtr conn, int lpar_id)
+{
+    SSH_SESSION *ssh_session = conn->privateData;
+    virDomainPtr dom = NULL;
+    const char *managed_system = conn->uri->server;
+    char *lpar_name;
+    unsigned char *lpar_uuid;
+
+    if (VIR_ALLOC_N(lpar_name, 100 * sizeof(char)))
+        return NULL;
+
+    if (VIR_ALLOC_N(lpar_uuid, 100 * sizeof(char)))
+        return NULL;
+
+    if (phypGetLparNAME(ssh_session, managed_system, lpar_id, lpar_name) ==
+        PHYP_NO_MEM)
+        return NULL;
+
+    if (phypGetLparUUID(ssh_session, managed_system, lpar_id, lpar_uuid) ==
+        PHYP_NO_MEM)
+        return NULL;
+
+    dom = virGetDomain(conn, lpar_name, lpar_uuid);
+
+    if (dom)
+        dom->id = lpar_id;
+
+    VIR_FREE(lpar_name);
+    VIR_FREE(lpar_uuid);
+    return dom;
+}
+
+static virDriver phypDriver = {
+    VIR_DRV_PHYP,
+    "PHYP",
+    phypOpen,                   /* open */
+    phypClose,                  /* close */
+    NULL,                       /* supports_feature */
+    NULL,                       /* type */
+    NULL,                       /* version */
+    NULL,                       /* hostname */
+    NULL,                       /* uri */
+    NULL,                       /* getMaxVcpus */
+    NULL,                       /* nodeGetInfo */
+    NULL,                       /* getCapabilities */
+    phypListDomains,            /* listDomains */
+    phypNumDomains,             /* numOfDomains */
+    NULL,                       /* domainCreateXML */
+    phypDomainLookupByID,       /* domainLookupByID */
+    NULL,                       /* domainLookupByUUID */
+    phypDomainLookupByName,     /* domainLookupByName */
+    NULL,                       /* domainSuspend */
+    NULL,                       /* domainResume */
+    NULL,                       /* domainShutdown */
+    NULL,                       /* domainReboot */
+    NULL,                       /* domainDestroy */
+    NULL,                       /* domainGetOSType */
+    NULL,                       /* domainGetMaxMemory */
+    NULL,                       /* domainSetMaxMemory */
+    NULL,                       /* domainSetMemory */
+    NULL,                       /* domainGetInfo */
+    NULL,                       /* domainSave */
+    NULL,                       /* domainRestore */
+    NULL,                       /* domainCoreDump */
+    NULL,                       /* domainSetVcpus */
+    NULL,                       /* domainPinVcpu */
+    NULL,                       /* domainGetVcpus */
+    NULL,                       /* domainGetMaxVcpus */
+    NULL,                       /* domainDumpXML */
+    NULL,                       /* listDomains */
+    NULL,                       /* numOfDomains */
+    NULL,                       /* domainCreate */
+    NULL,                       /* domainDefineXML */
+    NULL,                       /* domainUndefine */
+    NULL,                       /* domainAttachDevice */
+    NULL,                       /* domainDetachDevice */
+    NULL,                       /* domainGetAutostart */
+    NULL,                       /* domainSetAutostart */
+    NULL,                       /* domainGetSchedulerType */
+    NULL,                       /* domainGetSchedulerParameters */
+    NULL,                       /* domainSetSchedulerParameters */
+    NULL,                       /* domainMigratePrepare */
+    NULL,                       /* domainMigratePerform */
+    NULL,                       /* domainMigrateFinish */
+    NULL,                       /* domainBlockStats */
+    NULL,                       /* domainInterfaceStats */
+    NULL,                       /* domainBlockPeek */
+    NULL,                       /* domainMemoryPeek */
+    NULL,                       /* nodeGetCellsFreeMemory */
+    NULL,                       /* nodeGetFreeMemory */
+    NULL,                       /* domainEventRegister */
+    NULL,                       /* domainEventDeregister */
+    NULL,                       /* domainMigratePrepare2 */
+    NULL,                       /* domainMigrateFinish2 */
+};
+
+int
+phypRegister(void)
+{
+    virRegisterDriver(&phypDriver);
+    return 0;
+}
diff --git a/src/phyp_driver.h b/src/phyp_driver.h
new file mode 100644
index 0000000..1d935bd
--- /dev/null
+++ b/src/phyp_driver.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright IBM Corp. 2009
+ *
+ * phyp_driver.c: ssh layer to access Power Hypervisors
+ *
+ * Authors:
+ *  Eduardo Otubo <otubo at linux.vnet.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <config.h>
+#include <libssh/libssh.h>
+
+#define MAXSIZE 65536
+#define CLEANUP free(cmd); \
+                free(textual_return);
+#define LPAR_EXEC_ERR -1
+#define SSH_CONN_ERR -2
+#define SSH_AUTH_PUBKEY_ERR -3
+#define SSH_AUTH_ERR -4
+#define SSH_CHANNEL_OPEN_ERR -5
+#define SSH_CHANNEL_EXEC_ERR -6
+#define SSH_CHANNEL_SEND_EOF_ERR -7
+#define SSH_CHANNEL_CLOSE_ERR -8
+#define PHYP_NO_MEM -9
+
+int phypRegister(void);
+
+int
+ exec_command(SSH_SESSION * session, char *cmd, char *managed_system,
+              char *lpar);
+
diff --git a/src/virterror.c b/src/virterror.c
index d2514db..0756e84 100644
--- a/src/virterror.c
+++ b/src/virterror.c
@@ -124,6 +124,9 @@ static const char *virErrorDomainName(virErrorDomain domain) {
         case VIR_FROM_CONF:
             dom = "Config ";
             break;
+        case VIR_FROM_PHYP:
+            dom = "IBM power hypervisor ";
+            break;
         case VIR_FROM_OPENVZ:
             dom = "OpenVZ ";
             break;
--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to