From a7a82f98890f6652461c133867bae08ddb2036a3 Mon Sep 17 00:00:00 2001 From: Eduardo Otubo Date: Fri, 24 Jul 2009 16:17:06 +0200 Subject: [PATCH] First version of the Power Hypervisor driver Features supported: - Connects to HMC/VIOS or IVM systems. - Life cycle commands (resume and shutdown). - dumpxml - 'list' and 'list --all' What is being implemented: - better and centralized control for UUID - definexml - CPU management commands * src/domain_conf.c src/domain_conf.h: first version of the driver * configure.in src/Makefile.am include/libvirt/virterror.h src/domain_conf.[ch] src/libvirt.c src/virterror.c: glue the driver in the general framework --- configure.in | 55 +- docs/downloads.html | 7 +- include/libvirt/virterror.h | 15 +- src/Makefile.am | 45 +- src/domain_conf.c | 3 +- src/domain_conf.h | 1 + src/driver.h | 1 + src/libvirt.c | 10 + src/phyp/phyp_driver.c | 1374 +++++++++++++++++++++++++++++++++++ src/phyp/phyp_driver.h | 66 ++ src/virterror.c | 3 + 11 files changed, 1554 insertions(+), 26 deletions(-) create mode 100644 src/phyp/phyp_driver.c create mode 100644 src/phyp/phyp_driver.h diff --git a/configure.in b/configure.in index 552587c001..a3d357aeb3 100644 --- a/configure.in +++ b/configure.in @@ -187,6 +187,10 @@ 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([libssh], +[ --with-libssh=[PFX] libssh location],[],[with_libssh=yes]) +AC_ARG_WITH([phyp], +[ --with-phyp=[PFX] add PHYP support (on)],[with_phyp=yes],[with_phyp=check]) AC_ARG_WITH([vbox], [ --with-vbox add VirtualBox support (on)],[],[with_vbox=yes]) AC_ARG_WITH([lxc], @@ -776,7 +780,50 @@ AM_CONDITIONAL([HAVE_NUMACTL], [test "$with_numactl" != "no"]) AC_SUBST([NUMACTL_CFLAGS]) AC_SUBST([NUMACTL_LIBS]) +if test "$with_libssh" != "yes" -a "$with_libssh" != "no"; then + libssh_path="$with_libssh" +elif test "$with_libssh" = "yes"; then + libssh_path="/usr/local/lib/" +elif test "$with_libssh" = "no"; then + with_phyp="no"; +fi +if test "$with_phyp" = "check"; then + AC_CHECK_LIB([ssh],[ssh_new],[ + LIBSSH_LIBS="$LIBSSH_LIBS -lssh -L$libssh_path" + AC_SUBST([LIBSSH_LIBS])],[ + with_phyp="no" + with_libssh="no"; + ],[]) + + if test "$with_phyp" != "no"; then + AC_CHECK_HEADERS([libssh/libssh.h],[ + with_phyp="yes" + LIBSSH_CFLAGS="-I/usr/local/include/libssh" + AC_SUBST([LIBSSH_CFLAGS]) + AC_DEFINE_UNQUOTED([WITH_PHYP], 1, + [whether IBM HMC / IVM driver is enabled]) + ],[ + with_phyp="no" + with_libssh="no"; + ],[]) + fi +elif test "$with_phyp" = "yes"; then + AC_CHECK_LIB([ssh],[ssh_new],[ + LIBSSH_LIBS="$LIBSSH_LIBS -lssh -L$libssh_path" + 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 libcap-ng AC_ARG_WITH([capng], @@ -1518,6 +1565,7 @@ AC_MSG_NOTICE([ UML: $with_uml]) AC_MSG_NOTICE([ OpenVZ: $with_openvz]) AC_MSG_NOTICE([ VBox: $with_vbox]) AC_MSG_NOTICE([ LXC: $with_lxc]) +AC_MSG_NOTICE([ PHYP: $with_phyp]) AC_MSG_NOTICE([ ONE: $with_one]) AC_MSG_NOTICE([ ESX: $with_esx]) AC_MSG_NOTICE([ Test: $with_test]) @@ -1556,6 +1604,11 @@ AC_MSG_NOTICE([]) AC_MSG_NOTICE([Libraries]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([ libxml: $LIBXML_CFLAGS $LIBXML_LIBS]) +if test "$with_libssh" != "no" ; then +AC_MSG_NOTICE([ libssh: $LIBSSH_CFLAGS $LIBSSH_LIBS]) +else +AC_MSG_NOTICE([ libssh: no]) +fi AC_MSG_NOTICE([ gnutls: $GNUTLS_CFLAGS $GNUTLS_LIBS]) if test "$with_sasl" != "no" ; then AC_MSG_NOTICE([ sasl: $SASL_CFLAGS $SASL_LIBS]) @@ -1627,4 +1680,4 @@ AC_MSG_NOTICE([]) AC_MSG_NOTICE([Privileges]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([ QEMU: $QEMU_USER:$QEMU_GROUP]) -AC_MSG_NOTICE([]) \ No newline at end of file +AC_MSG_NOTICE([]) diff --git a/docs/downloads.html b/docs/downloads.html index 448c06d9ab..603814e90a 100644 --- a/docs/downloads.html +++ b/docs/downloads.html @@ -123,9 +123,10 @@

Jim Mereying was maintaining a CVS to git mirror on git.et.redhat.com. - Existing users should migrate to the new git server, as the - old one will be deprecated and turned into a mirror of the - libvirt.org one. It's available as: + Existing users should migrate to the new libvirt.org git server, as the + old one is now deprecated. For the sake of old links including now- + rewritten SHA1s, we'll leave the old repository on-line for some time. + It is available as:

 
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index dc2592e932..e4d013f310 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -53,19 +53,20 @@ typedef enum {
     VIR_FROM_REMOTE,	/* Error from remote driver */
     VIR_FROM_OPENVZ,    /* Error from OpenVZ driver */
     VIR_FROM_XENXM,	/* Error at Xen XM layer */
-    VIR_FROM_STATS_LINUX, /* Error in the Linux Stats code */
-    VIR_FROM_LXC,   /* Error from Linux Container driver */
+    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 */
     VIR_FROM_NETWORK,   /* Error from network config */
     VIR_FROM_DOMAIN,    /* Error from domain config */
     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_NODEDEV,   /* Error from node device monitor */
+    VIR_FROM_XEN_INOTIFY,/* Error from xen inotify layer */
     VIR_FROM_SECURITY,  /* Error from security framework */
-    VIR_FROM_VBOX,    /* Error from VirtualBox driver */
+    VIR_FROM_VBOX,      /* Error from VirtualBox driver */
     VIR_FROM_INTERFACE, /* Error when operating on an interface */
-    VIR_FROM_ONE,     /* Error from OpenNebula driver */
-    VIR_FROM_ESX,      /* Error from ESX driver */
+    VIR_FROM_ONE,       /* Error from OpenNebula driver */
+    VIR_FROM_ESX,       /* Error from ESX driver */
+    VIR_FROM_PHYP,      /* Error from IBM power hypervisor */
 } virErrorDomain;
 
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 92091fd1f7..9a0e1f5d0c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -6,6 +6,7 @@ INCLUDES = \
 	   -I@top_srcdir@/include \
 	   -I@top_srcdir@/qemud \
 	   $(LIBXML_CFLAGS) \
+	   $(LIBSSH_CFLAGS) \
 	   $(XEN_CFLAGS) \
 	   $(SELINUX_CFLAGS) \
 	   $(DRIVER_MODULE_CFLAGS) \
@@ -129,13 +130,16 @@ LXC_CONTROLLER_SOURCES =					\
 		veth.c veth.h                                   \
 		cgroup.c cgroup.h
 
+PHYP_DRIVER_SOURCES =						\
+		phyp/phyp_driver.c phyp/phyp_driver.h
+
 OPENVZ_DRIVER_SOURCES =						\
 		openvz_conf.c openvz_conf.h			\
 		openvz_driver.c openvz_driver.h
 
-VBOX_DRIVER_SOURCES =                                 \
-        vbox/vbox_XPCOMCGlue.c vbox/vbox_XPCOMCGlue.h \
-        vbox/vbox_driver.c vbox/vbox_driver.h         \
+VBOX_DRIVER_SOURCES =						\
+        vbox/vbox_XPCOMCGlue.c vbox/vbox_XPCOMCGlue.h		\
+        vbox/vbox_driver.c vbox/vbox_driver.h			\
         vbox/vbox_V2_2.c vbox/vbox_CAPI_v2_2.h
 
 VBOX_DRIVER_EXTRA_DIST = vbox/vbox_tmpl.c vbox/README
@@ -149,18 +153,18 @@ UML_DRIVER_SOURCES =						\
 		uml_conf.c uml_conf.h				\
 		uml_driver.c uml_driver.h
 
-ONE_DRIVER_SOURCES =					\
-		./opennebula/one_conf.c			\
-		./opennebula/one_conf.h			\
-		./opennebula/one_driver.c		\
-		./opennebula/one_driver.h		\
-		./opennebula/one_client.c		\
+ONE_DRIVER_SOURCES =						\
+		./opennebula/one_conf.c				\
+		./opennebula/one_conf.h				\
+		./opennebula/one_driver.c			\
+		./opennebula/one_driver.h			\
+		./opennebula/one_client.c			\
 		./opennebula/one_client.h
 
-ESX_DRIVER_SOURCES =								\
-		esx/esx_driver.c esx/esx_driver.h			\
-		esx/esx_util.c esx/esx_util.h				\
-		esx/esx_vi.c esx/esx_vi.h					\
+ESX_DRIVER_SOURCES =						\
+		esx/esx_driver.c esx/esx_driver.h		\
+		esx/esx_util.c esx/esx_util.h			\
+		esx/esx_vi.c esx/esx_vi.h			\
 		esx/esx_vi_methods.c esx/esx_vi_methods.h	\
 		esx/esx_vi_types.c esx/esx_vi_types.h		\
 		esx/esx_vmx.c esx/esx_vmx.h
@@ -201,7 +205,7 @@ STORAGE_HELPER_DISK_SOURCES =					\
 
 
 # Security framework and drivers for various models
-SECURITY_DRIVER_SOURCES =                                      \
+SECURITY_DRIVER_SOURCES =					\
 		security.h security.c
 
 SECURITY_DRIVER_SELINUX_SOURCES =				\
@@ -295,6 +299,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
@@ -511,6 +527,7 @@ EXTRA_DIST +=							\
 		$(UML_DRIVER_SOURCES)				\
 		$(ONE_DRIVER_SOURCES)				\
 		$(OPENVZ_DRIVER_SOURCES)			\
+		$(PHYP_DRIVER_SOURCES)				\
 		$(VBOX_DRIVER_SOURCES)				\
 		$(ESX_DRIVER_SOURCES)				\
 		$(NETWORK_DRIVER_SOURCES)			\
diff --git a/src/domain_conf.c b/src/domain_conf.c
index d0e3282659..2301a969b9 100644
--- a/src/domain_conf.c
+++ b/src/domain_conf.c
@@ -57,7 +57,8 @@ VIR_ENUM_IMPL(virDomainVirt, VIR_DOMAIN_VIRT_LAST,
               "vmware",
               "hyperv",
               "vbox",
-              "one")
+              "one",
+              "phyp")
 
 VIR_ENUM_IMPL(virDomainBoot, VIR_DOMAIN_BOOT_LAST,
               "fd",
diff --git a/src/domain_conf.h b/src/domain_conf.h
index 8dda78d807..63fca76f97 100644
--- a/src/domain_conf.h
+++ b/src/domain_conf.h
@@ -55,6 +55,7 @@ enum virDomainVirtType {
     VIR_DOMAIN_VIRT_HYPERV,
     VIR_DOMAIN_VIRT_VBOX,
     VIR_DOMAIN_VIRT_ONE,
+    VIR_DOMAIN_VIRT_PHYP,
 
     VIR_DOMAIN_VIRT_LAST,
 };
diff --git a/src/driver.h b/src/driver.h
index 2d94444a2c..79d46ffbff 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -23,6 +23,7 @@ typedef enum {
     VIR_DRV_VBOX = 8,
     VIR_DRV_ONE = 9,
     VIR_DRV_ESX = 10,
+    VIR_DRV_PHYP = 11,
 } virDrvNo;
 
 
diff --git a/src/libvirt.c b/src/libvirt.c
index 8a0ad3866a..1752e9d939 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/phyp_driver.h"
+#endif
 #ifdef WITH_VBOX
 #include "vbox/vbox_driver.h"
 #endif
@@ -323,6 +326,9 @@ virInitialize(void)
 #ifdef WITH_OPENVZ
     if (openvzRegister() == -1) return -1;
 #endif
+#ifdef WITH_PHYP
+    if (phypRegister() == -1) return -1;
+#endif
 #ifdef WITH_VBOX
     if (vboxRegister() == -1) return -1;
 #endif
@@ -896,6 +902,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/phyp_driver.c b/src/phyp/phyp_driver.c
new file mode 100644
index 0000000000..cf3cd4b03f
--- /dev/null
+++ b/src/phyp/phyp_driver.c
@@ -0,0 +1,1374 @@
+
+/*
+ * Copyright IBM Corp. 2009
+ *
+ * phyp_driver.c: ssh layer to access Power Hypervisors
+ *
+ * Authors:
+ *  Eduardo Otubo 
+ *
+ * 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 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "internal.h"
+#include "util.h"
+#include "datatypes.h"
+#include "buf.h"
+#include "memory.h"
+#include "logging.h"
+#include "driver.h"
+#include "libvirt/libvirt.h"
+#include "virterror_internal.h"
+#include "uuid.h"
+#include "domain_conf.h"
+
+#include "phyp_driver.h"
+
+#define VIR_FROM_THIS VIR_FROM_PHYP
+
+/*
+ * URI: phyp://user@[hmc|ivm]/managed_system
+ * */
+
+static virDrvOpenStatus
+phypOpen(virConnectPtr conn,
+         virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
+{
+    SSH_SESSION *session;
+    ConnectionData *connection_data;
+    char string[strlen(conn->uri->path)];
+
+    uuid_dbPtr uuid_db = NULL;
+
+    if (VIR_ALLOC(uuid_db) < 0)
+        virReportOOMError(conn);
+
+    if (VIR_ALLOC(connection_data) < 0)
+        virReportOOMError(conn);
+
+    if (!conn || !conn->uri)
+        return VIR_DRV_OPEN_DECLINED;
+
+    if (conn->uri->scheme == NULL || STRNEQ(conn->uri->scheme, "phyp"))
+        return VIR_DRV_OPEN_DECLINED;
+
+
+    if (conn->uri->server == NULL) {
+        virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
+                      VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
+                      _("Missing server name in phyp:// URI"));
+        return VIR_DRV_OPEN_ERROR;
+    }
+
+    if (conn->uri->path == NULL) {
+        virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
+                      VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
+                      _("Missing path name in phyp:// URI"));
+        return VIR_DRV_OPEN_ERROR;
+    }
+
+    if (escape_specialcharacters(conn->uri->path, string) == -1) {
+        virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
+                      VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
+                      _("Error parsing 'path'. Invalid characters."));
+        return VIR_DRV_OPEN_ERROR;
+    }
+
+    if ((session = openSSHSession(conn, auth)) == NULL) {
+        virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
+                      VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
+                      _("Error while opening SSH session."));
+        return VIR_DRV_OPEN_ERROR;
+    }
+
+    conn->uri->path = string;
+    connection_data->session = session;
+    connection_data->auth = auth;
+
+    uuid_db->nlpars = 0;
+    uuid_db->lpars = NULL;
+
+    conn->privateData = uuid_db;
+    conn->networkPrivateData = connection_data;
+    init_uuid_db(conn);
+
+    return VIR_DRV_OPEN_SUCCESS;
+}
+
+static int
+phypClose(virConnectPtr conn)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    SSH_SESSION *ssh_session = connection_data->session;
+
+    ssh_disconnect(ssh_session);
+
+    VIR_FREE(connection_data);
+    return 0;
+}
+
+SSH_SESSION *
+openSSHSession(virConnectPtr conn, virConnectAuthPtr auth)
+{
+    SSH_SESSION *session;
+    SSH_OPTIONS *opt;
+    char *user = conn->uri->user;
+    char *host = conn->uri->server;
+    int ssh_auth = 0;
+    char *banner;
+    int port = 22;
+    char *password;
+
+    if (conn->uri->port)
+        port = conn->uri->port;
+
+    session = ssh_new();
+    opt = ssh_options_new();
+
+    /*setting some ssh options */
+    ssh_options_set_host(opt, host);
+    ssh_options_set_port(opt, port);
+    ssh_options_set_username(opt, user);
+    ssh_set_options(session, opt);
+
+    /*starting ssh connection */
+    if (ssh_connect(session)) {
+        virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP, VIR_ERR_ERROR,
+                      NULL, NULL, NULL, 0, 0, "%s",
+                      _("Connection failed."));
+        ssh_disconnect(session);
+        ssh_finalize();
+        goto err;
+    }
+
+    /*trying to use pub key */
+    if ((ssh_auth =
+         ssh_userauth_autopubkey(session, NULL)) == SSH_AUTH_ERROR) {
+        VIR_WARN("%s", "Authentication with public key failed.");
+    }
+
+    if ((banner = ssh_get_issue_banner(session))) {
+        VIR_INFO("%s", banner);
+        VIR_FREE(banner);
+    }
+
+    if (ssh_auth != SSH_AUTH_SUCCESS) {
+        int i;
+        int hasPassphrase = 0;
+        int auth_check = 0;
+
+        virConnectCredential creds[] = {
+            {VIR_CRED_PASSPHRASE, "password", "Password", NULL, NULL, 0},
+        };
+
+        if (!auth || !auth->cb) {
+            virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
+                          VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
+                          _("No authentication callback provided."));
+            goto err;
+        }
+
+        for (i = 0; i < auth->ncredtype; i++) {
+            if (auth->credtype[i] == VIR_CRED_PASSPHRASE)
+                hasPassphrase = 1;
+        }
+
+        if (!hasPassphrase) {
+            virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
+                          VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
+                          _("Required credentials are not supported."));
+            goto err;
+        }
+
+        int res =
+            (auth->cb) (creds, ARRAY_CARDINALITY(creds), auth->cbdata);
+
+        if (res < 0) {
+            virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
+                          VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
+                          _("Unable to fetch credentials."));
+            goto err;
+        }
+
+        if (creds[0].result)
+            password = creds[0].result;
+        else {
+            virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
+                          VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s : %s",
+                          "Unable to get password certificate.",
+                          ssh_get_error(session));
+            ssh_disconnect(session);
+            goto err;
+        }
+
+        char *username = user;
+
+        auth_check = ssh_userauth_password(session, username, password);
+        memset(password, 0, strlen(password));
+
+        if (auth_check != SSH_AUTH_SUCCESS) {
+            virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
+                          VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s : %s",
+                          "Authentication failed.",
+                          ssh_get_error(session));
+            ssh_disconnect(session);
+            goto err;
+        } else
+            goto exit;
+    } else
+        goto exit;
+
+  err:
+    return NULL;
+
+  exit:
+    return session;
+}
+
+/* this functions is the layer that manipulates the ssh channel itself
+ * and executes the commands on the remote machine */
+static char *
+phypExec(SSH_SESSION * session, char *cmd, int *exit_status,
+         virConnectPtr conn)
+{
+    CHANNEL *channel = channel_new(session);
+    virBuffer tex_ret = VIR_BUFFER_INITIALIZER;
+    char buf[4096] = { 0 };
+    int ret = 0;
+
+    if (channel_open_session(channel) == SSH_ERROR) {
+        virRaiseError(NULL, NULL, NULL, 0, VIR_FROM_PHYP,
+                      VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
+                      _("Unable to open a SSH channel."));
+        goto err;
+    }
+
+    if (channel_request_exec(channel, cmd) == SSH_ERROR) {
+        virRaiseError(NULL, NULL, NULL, 0, VIR_FROM_PHYP,
+                      VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
+                      _("Unable to execute remote command."));
+        goto err;
+    }
+
+    if (channel_send_eof(channel) == SSH_ERROR) {
+        virRaiseError(NULL, NULL, NULL, 0, VIR_FROM_PHYP,
+                      VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
+                      _("Unable to send EOF."));
+        goto err;
+    }
+
+    while (channel && channel_is_open(channel)) {
+        ret = channel_read(channel, buf, sizeof(buf), 0);
+        if (ret < 0)
+            goto err;
+
+        if (ret == 0) {
+            channel_send_eof(channel);
+            if (channel_get_exit_status(channel) == -1)
+                goto err;
+
+            if (channel_close(channel) == SSH_ERROR)
+                goto err;
+
+            channel_free(channel);
+            channel = NULL;
+            goto exit;
+        }
+
+        virBufferAdd(&tex_ret, (const char *) &buf, ret);
+    }
+
+  err:
+    (*exit_status) = SSH_CMD_ERR;
+    char *cleanup_buf = virBufferContentAndReset(&tex_ret);
+
+    VIR_FREE(cleanup_buf);
+    return NULL;
+
+  exit:
+    if (virBufferError(&tex_ret)) {
+        virReportOOMError(conn);
+        return NULL;
+    }
+    return virBufferContentAndReset(&tex_ret);
+}
+
+/* return the lpar_id given a name and a managed system name */
+static int
+phypGetLparID(SSH_SESSION * ssh_session, const char *managed_system,
+              const char *name, virConnectPtr conn)
+{
+    int exit_status = 0;
+    int lpar_id = 0;
+    char *char_ptr;
+    char *cmd;
+
+    if (virAsprintf(&cmd,
+                    "lssyscfg -r lpar -m %s --filter lpar_names=%s -F lpar_id",
+                    managed_system, name) < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+
+    const char *tex_ret = phypExec(ssh_session, cmd, &exit_status, conn);
+
+    if (exit_status < 0 || tex_ret == NULL)
+        goto err;
+
+    if (virStrToLong_i(tex_ret, &char_ptr, 10, &lpar_id) == -1)
+        goto err;
+
+    VIR_FREE(cmd);
+    return lpar_id;
+
+  err:
+    VIR_FREE(cmd);
+    return -1;
+}
+
+/* return the lpar name given a lpar_id and a managed system name */
+static char *
+phypGetLparNAME(SSH_SESSION * ssh_session, const char *managed_system,
+                unsigned int lpar_id, virConnectPtr conn)
+{
+    char *cmd;
+    int exit_status = 0;
+
+    if (virAsprintf(&cmd,
+                    "lssyscfg -r lpar -m %s --filter lpar_ids=%d -F name",
+                    managed_system, lpar_id) < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+
+    char *lpar_name = phypExec(ssh_session, cmd, &exit_status, conn);
+
+    if (lpar_name == NULL)
+        goto err;
+
+    char *char_ptr = strchr(lpar_name, '\n');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    if (exit_status < 0 || lpar_name == NULL)
+        goto err;
+
+    VIR_FREE(cmd);
+    return lpar_name;
+
+  err:
+    VIR_FREE(cmd);
+    return NULL;
+}
+
+
+/* Search into the uuid_db for a lpar_uuid given a lpar_id
+ * and a managed system name
+ *
+ * return:  0 - record found
+ *         -1 - not found
+ * */
+int
+phypGetLparUUID(unsigned char *uuid, int lpar_id, virConnectPtr conn)
+{
+    uuid_dbPtr uuid_db = conn->privateData;
+    lparPtr *lpars = uuid_db->lpars;
+    unsigned int i = 0;
+
+    for (i = 0; i < uuid_db->nlpars; i++) {
+        if (lpars[i]->id == lpar_id) {
+            memmove(uuid, lpars[i]->uuid, VIR_UUID_BUFLEN);
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
+/*
+ * type:
+ * 0 - maxmem
+ * 1 - memory
+ * */
+unsigned long
+phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id,
+               int type)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    SSH_SESSION *ssh_session = connection_data->session;
+    char *cmd;
+    char *char_ptr;
+    int memory = 0;
+    int exit_status = 0;
+
+    if (type != 1 && type != 0)
+        goto err;
+
+    if (type) {
+        if (virAsprintf(&cmd,
+                        "lshwres -m %s -r mem --level lpar -F curr_mem --filter lpar_ids=%d",
+                        managed_system, lpar_id) < 0) {
+            virReportOOMError(conn);
+            goto err;
+        }
+    } else {
+        if (virAsprintf(&cmd,
+                        "lshwres -m %s -r mem --level lpar -F curr_max_mem --filter lpar_ids=%d",
+                        managed_system, lpar_id) < 0) {
+            virReportOOMError(conn);
+            goto err;
+        }
+    }
+
+    char *tex_ret = phypExec(ssh_session, cmd, &exit_status, conn);
+
+    if (tex_ret == NULL)
+        goto err;
+
+    char *mem_char_ptr = strchr(tex_ret, '\n');
+
+    if (mem_char_ptr)
+        *mem_char_ptr = '\0';
+
+    if (exit_status < 0)
+        goto err;
+
+    if (virStrToLong_i(tex_ret, &char_ptr, 10, &memory) == -1)
+        goto err;
+
+    VIR_FREE(cmd);
+    return memory;
+
+  err:
+    VIR_FREE(cmd);
+    return 0;
+
+}
+
+unsigned long
+phypGetLparCPU(virConnectPtr conn, const char *managed_system, int lpar_id)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    SSH_SESSION *ssh_session = connection_data->session;
+    char *cmd;
+    int exit_status = 0;
+    int vcpus = 0;
+
+    if (virAsprintf(&cmd,
+                    "lshwres -m %s -r proc --level lpar -F curr_procs --filter lpar_ids=%d",
+                    managed_system, lpar_id) < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+    char *tex_ret = phypExec(ssh_session, cmd, &exit_status, conn);
+
+    if (tex_ret == NULL)
+        goto err;
+
+    char *char_ptr = strchr(tex_ret, '\n');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    if (virStrToLong_i(tex_ret, &char_ptr, 10, &vcpus) == -1)
+        goto err;
+
+    if (exit_status < 0)
+        goto err;
+
+    VIR_FREE(cmd);
+    return (unsigned long) vcpus;
+
+  err:
+    VIR_FREE(cmd);
+    return 0;
+}
+
+int
+phypGetRemoteSlot(virConnectPtr conn, const char *managed_system,
+                  const char *lpar_name)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    SSH_SESSION *ssh_session = connection_data->session;
+    char *cmd;
+    char *char_ptr;
+    int remote_slot = 0;
+    int exit_status = 0;
+
+    if (virAsprintf(&cmd,
+                    "lshwres -m %s -r virtualio --rsubtype scsi -F remote_slot_num --filter lpar_names=%s",
+                    managed_system, lpar_name) < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+    char *tex_ret = phypExec(ssh_session, cmd, &exit_status, conn);
+
+    if (tex_ret == NULL)
+        goto err;
+
+    char *char_ptr2 = strchr(tex_ret, '\n');
+
+    if (char_ptr2)
+        *char_ptr2 = '\0';
+
+    if (exit_status < 0)
+        goto err;
+
+    if (virStrToLong_i(tex_ret, &char_ptr, 10, &remote_slot) == -1)
+        goto err;
+
+    VIR_FREE(cmd);
+    return remote_slot;
+
+  err:
+    VIR_FREE(cmd);
+    return 0;
+}
+
+char *
+phypGetBackingDevice(virConnectPtr conn, const char *managed_system,
+                     char *lpar_name)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    SSH_SESSION *ssh_session = connection_data->session;
+    char *cmd;
+    int remote_slot = 0;
+    int exit_status = 0;
+
+    if ((remote_slot =
+         phypGetRemoteSlot(conn, managed_system, lpar_name)) == 0)
+        goto err;
+
+    if (virAsprintf(&cmd,
+                    "lshwres -m %s -r virtualio --rsubtype scsi -F backing_devices --filter slots=%d",
+                    managed_system, remote_slot) < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+
+    char *ret = phypExec(ssh_session, cmd, &exit_status, conn);
+
+    if (ret == NULL)
+        goto err;
+
+    /* here is a little trick to deal returns of this kind:
+     *
+     * 0x8100000000000000//lv01
+     *
+     * the information we really need is only lv01, so we
+     * need to skip a lot of things on the string.
+     * */
+    char *backing_device = strchr(ret, '/');
+
+    if (backing_device) {
+        backing_device++;
+        if (backing_device[0] == '/')
+            backing_device++;
+        else
+            goto err;
+    } else {
+        backing_device = ret;
+    }
+
+    char *char_ptr = strchr(backing_device, '\n');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    if (exit_status < 0 || backing_device == NULL)
+        goto err;
+
+    VIR_FREE(cmd);
+    return backing_device;
+
+  err:
+    VIR_FREE(cmd);
+    return NULL;
+
+}
+
+int
+phypGetLparState(virConnectPtr conn, unsigned int lpar_id)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    SSH_SESSION *ssh_session = connection_data->session;
+    char *cmd;
+    int exit_status = 0;
+    char *char_ptr = NULL;
+    char *managed_system = conn->uri->path;
+
+    /* need to shift one byte in order to remove the first "/" of URI component */
+    if (managed_system[0] == '/')
+        managed_system++;
+
+    /* here we are handling only the first component of the path,
+     * so skipping the second:
+     * */
+
+    char_ptr = strchr(managed_system, '/');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    if (virAsprintf(&cmd,
+                    "lssyscfg -r lpar -m %s -F state --filter lpar_ids=%d",
+                    managed_system, lpar_id) < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+
+    char *ret = phypExec(ssh_session, cmd, &exit_status, conn);
+
+    if (ret == NULL)
+        goto err;
+
+    char_ptr = strchr(ret, '\n');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    if (exit_status < 0 || ret == NULL)
+        goto err;
+
+    VIR_FREE(cmd);
+    if (STREQ(ret, "Running"))
+        return VIR_DOMAIN_RUNNING;
+    else if (STREQ(ret, "Not Activated"))
+        return VIR_DOMAIN_SHUTOFF;
+    else if (STREQ(ret, "Shutting Down"))
+        return VIR_DOMAIN_SHUTDOWN;
+    else
+        goto err;
+
+  err:
+    VIR_FREE(cmd);
+    return VIR_DOMAIN_NOSTATE;
+}
+
+int
+phypDiskType(virConnectPtr conn, char *backing_device)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    SSH_SESSION *ssh_session = connection_data->session;
+    char *cmd;
+    int exit_status = 0;
+
+    if (virAsprintf(&cmd,
+                    "ioscli lssp -field name type -fmt , -all|grep %s|sed -e 's/^.*,//g'",
+                    backing_device) < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+
+    char *ret = phypExec(ssh_session, cmd, &exit_status, conn);
+
+    if (ret == NULL)
+        goto err;
+
+    char *char_ptr = strchr(ret, '\n');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    if (exit_status < 0 || ret == NULL)
+        goto err;
+
+    VIR_FREE(cmd);
+    if (STREQ(ret, "LVPOOL"))
+        return VIR_DOMAIN_DISK_TYPE_BLOCK;
+    else if (STREQ(ret, "FBPOOL"))
+        return VIR_DOMAIN_DISK_TYPE_FILE;
+    else
+        goto err;
+
+  err:
+    VIR_FREE(cmd);
+    return -1;
+}
+
+/* This is a generic function that won't be used directly by
+ * libvirt api. The function returns the number of domains
+ * in different states: Running, Not Activated and all:
+ *
+ * type: 0 - Running
+ *       1 - Not Activated
+ *       * - All
+ * */
+static int
+phypNumDomainsGeneric(virConnectPtr conn, unsigned int type)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    SSH_SESSION *ssh_session = connection_data->session;
+    int exit_status = 0;
+    int ndom = 0;
+    char *char_ptr;
+    char *cmd;
+    char *managed_system = conn->uri->path;
+    const char *state;
+
+    if (type == 0)
+        state = "|grep Running";
+    else if (type == 1)
+        state = "|grep \"Not Activated\"";
+    else
+        state = " ";
+
+    /* need to shift one byte in order to remove the first "/" of URI component */
+    if (managed_system[0] == '/')
+        managed_system++;
+
+    /* here we are handling only the first component of the path,
+     * so skipping the second:
+     * */
+
+    char_ptr = strchr(managed_system, '/');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    if (virAsprintf(&cmd,
+                    "lssyscfg -r lpar -m %s -F lpar_id,state %s |grep -c ^[0-9]*",
+                    managed_system, state) < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+
+    char *ret = phypExec(ssh_session, cmd, &exit_status, conn);
+
+    if (exit_status < 0 || ret == NULL)
+        goto err;
+
+    if (virStrToLong_i(ret, &char_ptr, 10, &ndom) == -1)
+        goto err;
+
+    VIR_FREE(cmd);
+    return ndom;
+
+  err:
+    VIR_FREE(cmd);
+    return 0;
+}
+
+static int
+phypNumDefinedDomains(virConnectPtr conn)
+{
+    return phypNumDomainsGeneric(conn, 1);
+}
+
+static int
+phypNumDomains(virConnectPtr conn)
+{
+    return phypNumDomainsGeneric(conn, 0);
+}
+
+/* This is a generic function that won't be used directly by
+ * libvirt api. The function returns the ids of domains
+ * in different states: Running, and all:
+ *
+ * type: 0 - Running
+ *       * - all
+ * */
+static int
+phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids,
+                       unsigned int type)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    SSH_SESSION *ssh_session = connection_data->session;
+    char *managed_system = conn->uri->path;
+    int exit_status = 0;
+    int got = 0;
+    char *char_ptr;
+    unsigned int i = 0, j = 0;
+    char id_c[10];
+    char *cmd;
+    const char *state;
+
+    if (type == 0)
+        state = "|grep Running";
+    else
+        state = " ";
+
+    /* need to shift one byte in order to remove the first "/" of URI component */
+    if (managed_system[0] == '/')
+        managed_system++;
+
+    /* here we are handling only the first component of the path,
+     * so skipping the second:
+     * */
+    char_ptr = strchr(managed_system, '/');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    memset(id_c, 0, 10);
+
+    if (virAsprintf
+        (&cmd,
+         "lssyscfg -r lpar -m %s -F lpar_id,state %s | sed -e 's/,.*$//g'",
+         managed_system, state) < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+    char *domains = phypExec(ssh_session, cmd, &exit_status, conn);
+
+    /* I need to parse the textual return in order to get the domains */
+    if (exit_status < 0 || domains == NULL || got == 0)
+        goto err;
+    else {
+        while (got < nids) {
+            if (domains[i] == '\n') {
+                if (virStrToLong_i(id_c, &char_ptr, 10, &ids[got]) == -1)
+                    return 0;
+                memset(id_c, 0, 10);
+                j = 0;
+                got++;
+            } else {
+                id_c[j] = domains[i];
+                j++;
+            }
+            i++;
+        }
+    }
+
+    VIR_FREE(cmd);
+    return got;
+
+  err:
+    VIR_FREE(cmd);
+    return 0;
+}
+
+static int
+phypListDomains(virConnectPtr conn, int *ids, int nids)
+{
+    return phypListDomainsGeneric(conn, ids, nids, 0);
+}
+
+static int
+phypListDefinedDomains(virConnectPtr conn, char **const names, int nnames)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    SSH_SESSION *ssh_session = connection_data->session;
+    char *managed_system = conn->uri->path;
+    int exit_status = 0;
+    int got = 0;
+    char *char_ptr = NULL;
+    char *cmd;
+    char *domains;
+
+    /* need to shift one byte in order to remove the first "/" of URI component */
+    if (managed_system[0] == '/')
+        managed_system++;
+
+    /* here we are handling only the first component of the path,
+     * so skipping the second:
+     * */
+    char_ptr = strchr(managed_system, '/');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    if (virAsprintf
+        (&cmd,
+         "lssyscfg -r lpar -m %s -F name,state | grep \"Not Activated\" | sed -e 's/,.*$//g'",
+         managed_system) < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+
+    char *ret = phypExec(ssh_session, cmd, &exit_status, conn);
+
+    if (VIR_ALLOC(domains) < 0)
+        virReportOOMError(conn);
+
+    domains = strdup(ret);
+    if (!domains)
+        goto err;
+
+    char *char_ptr2 = NULL;
+    /* I need to parse the textual return in order to get the domains */
+    if (exit_status < 0 || domains == NULL)
+        goto err;
+    else {
+        while (got < nnames) {
+            char_ptr2 = strchr(domains, '\n');
+
+            if (char_ptr2) {
+                *char_ptr2 = '\0';
+                if (!strdup(domains))
+                    goto err;
+                names[got] = strdup(domains);
+                char_ptr2++;
+                domains = char_ptr2;
+                got++;
+            }
+        }
+    }
+
+    VIR_FREE(domains);
+    VIR_FREE(cmd);
+    VIR_FREE(ret);
+    return got;
+
+  err:
+    VIR_FREE(domains);
+    VIR_FREE(ret);
+    return 0;
+}
+
+static virDomainPtr
+phypDomainLookupByName(virConnectPtr conn, const char *lpar_name)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    SSH_SESSION *ssh_session = connection_data->session;
+    virDomainPtr dom = NULL;
+    int lpar_id = 0;
+    char *managed_system = conn->uri->path;
+    unsigned char *lpar_uuid = NULL;
+
+    if (VIR_ALLOC_N(lpar_uuid, VIR_UUID_BUFLEN) < 0)
+        virReportOOMError(dom->conn);
+
+    /* need to shift one byte in order to remove the first "/" of uri component */
+    if (managed_system[0] == '/')
+        managed_system++;
+
+    /* here we are handling only the first component of the path,
+     * so skipping the second:
+     * */
+    char *char_ptr = strchr(managed_system, '/');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    lpar_id = phypGetLparID(ssh_session, managed_system, lpar_name, conn);
+    if (lpar_id < 0)
+        goto err;
+
+    if (phypGetLparUUID(lpar_uuid, lpar_id, conn) == -1)
+        goto err;
+
+    dom = virGetDomain(conn, lpar_name, lpar_uuid);
+
+    if (dom)
+        dom->id = lpar_id;
+
+    VIR_FREE(lpar_uuid);
+    return dom;
+
+  err:
+    VIR_FREE(lpar_uuid);
+    return NULL;
+}
+
+static virDomainPtr
+phypDomainLookupByID(virConnectPtr conn, int lpar_id)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    SSH_SESSION *ssh_session = connection_data->session;
+    virDomainPtr dom = NULL;
+    char *managed_system = conn->uri->path;
+    int exit_status = 0;
+    unsigned char *lpar_uuid = NULL;
+
+    if (VIR_ALLOC_N(lpar_uuid, VIR_UUID_BUFLEN) < 0)
+        virReportOOMError(dom->conn);
+
+    /* need to shift one byte in order to remove the first "/" of uri component */
+    if (managed_system[0] == '/')
+        managed_system++;
+
+    /* here we are handling only the first component of the path,
+     * so skipping the second:
+     * */
+    char *char_ptr = strchr(managed_system, '/');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    char *lpar_name = phypGetLparNAME(ssh_session, managed_system, lpar_id,
+                                      conn);
+
+    if (phypGetLparUUID(lpar_uuid, lpar_id, conn) == -1)
+        goto err;
+
+    if (exit_status < 0)
+        goto err;
+
+    dom = virGetDomain(conn, lpar_name, lpar_uuid);
+
+    if (dom)
+        dom->id = lpar_id;
+
+    VIR_FREE(lpar_name);
+    VIR_FREE(lpar_uuid);
+    return dom;
+
+  err:
+    VIR_FREE(lpar_name);
+    VIR_FREE(lpar_uuid);
+    return NULL;
+}
+
+static char *
+phypDomainDumpXML(virDomainPtr dom, int flags)
+{
+    ConnectionData *connection_data = dom->conn->networkPrivateData;
+    SSH_SESSION *ssh_session = connection_data->session;
+    virDomainDefPtr def = NULL;
+    char *ret = NULL;
+    char *managed_system = dom->conn->uri->path;
+    unsigned char *lpar_uuid = NULL;
+
+    if (VIR_ALLOC_N(lpar_uuid, VIR_UUID_BUFLEN) < 0)
+        virReportOOMError(dom->conn);
+
+    if (VIR_ALLOC(def) < 0)
+        virReportOOMError(dom->conn);
+
+    /* need to shift one byte in order to remove the first "/" of uri component */
+    if (managed_system[0] == '/')
+        managed_system++;
+
+    /* here we are handling only the first component of the path,
+     * so skipping the second:
+     * */
+    char *char_ptr = strchr(managed_system, '/');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    def->virtType = VIR_DOMAIN_VIRT_PHYP;
+    def->id = dom->id;
+
+    char *lpar_name = phypGetLparNAME(ssh_session, managed_system, def->id,
+                                      dom->conn);
+
+    if (lpar_name == NULL) {
+        VIR_ERROR("%s", "Unable to determine domain's name.");
+        goto err;
+    }
+
+    if (phypGetLparUUID(lpar_uuid, dom->id, dom->conn) == -1) {
+        VIR_ERROR("%s", "Unable to generate random uuid.");
+        goto err;
+    }
+
+    if (!memcpy(def->uuid, lpar_uuid, VIR_UUID_BUFLEN)) {
+        VIR_ERROR("%s", "Unable to generate random uuid.");
+        goto err;
+    }
+
+    if ((def->maxmem =
+         phypGetLparMem(dom->conn, managed_system, dom->id, 0)) == 0) {
+        VIR_ERROR("%s", "Unable to determine domain's max memory.");
+        goto err;
+    }
+
+    if ((def->memory =
+         phypGetLparMem(dom->conn, managed_system, dom->id, 1)) == 0) {
+        VIR_ERROR("%s", "Unable to determine domain's memory.");
+        goto err;
+    }
+
+    if ((def->vcpus =
+         phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0) {
+        VIR_ERROR("%s", "Unable to determine domain's CPU.");
+        goto err;
+    }
+
+    ret = virDomainDefFormat(dom->conn, def, flags);
+
+  err:
+    VIR_FREE(def);
+    return ret;
+}
+
+static int
+phypDomainResume(virDomainPtr dom)
+{
+    ConnectionData *connection_data = dom->conn->networkPrivateData;
+    SSH_SESSION *ssh_session = connection_data->session;
+    char *managed_system = dom->conn->uri->path;
+    int exit_status = 0;
+    char *char_ptr = NULL;
+    char *cmd;
+
+    /* need to shift one byte in order to remove the first "/" of URI component */
+    if (managed_system[0] == '/')
+        managed_system++;
+
+    /* here we are handling only the first component of the path,
+     * so skipping the second:
+     * */
+    char_ptr = strchr(managed_system, '/');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    if (virAsprintf
+        (&cmd,
+         "chsysstate -m %s -r lpar -o on --id %d -f %s",
+         managed_system, dom->id, dom->name) < 0) {
+        virReportOOMError(dom->conn);
+        goto err;
+    }
+
+    char *ret = phypExec(ssh_session, cmd, &exit_status, dom->conn);
+
+  err:
+    VIR_FREE(cmd);
+    VIR_FREE(ret);
+    return 0;
+
+}
+
+static int
+phypDomainShutdown(virDomainPtr dom)
+{
+    ConnectionData *connection_data = dom->conn->networkPrivateData;
+    SSH_SESSION *ssh_session = connection_data->session;
+    char *managed_system = dom->conn->uri->path;
+    int exit_status = 0;
+    char *char_ptr = NULL;
+    char *cmd;
+
+    /* need to shift one byte in order to remove the first "/" of URI component */
+    if (managed_system[0] == '/')
+        managed_system++;
+
+    /* here we are handling only the first component of the path,
+     * so skipping the second:
+     * */
+    char_ptr = strchr(managed_system, '/');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    if (virAsprintf
+        (&cmd,
+         "chsysstate -m %s -r lpar -o shutdown --id %d",
+         managed_system, dom->id) < 0) {
+        virReportOOMError(dom->conn);
+        goto err;
+    }
+
+    char *ret = phypExec(ssh_session, cmd, &exit_status, dom->conn);
+
+  err:
+    VIR_FREE(cmd);
+    VIR_FREE(ret);
+    return 0;
+
+}
+
+static int
+phypDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
+{
+    char *managed_system = dom->conn->uri->path;
+
+    /* need to shift one byte in order to remove the first "/" of uri component */
+    if (managed_system[0] == '/')
+        managed_system++;
+
+    /* here we are handling only the first component of the path,
+     * so skipping the second:
+     * */
+    char *char_ptr = strchr(managed_system, '/');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    info->state = phypGetLparState(dom->conn, dom->id);
+
+    if ((info->maxMem =
+         phypGetLparMem(dom->conn, managed_system, dom->id, 0)) == 0)
+        VIR_WARN("%s", "Unable to determine domain's max memory.");
+
+    if ((info->memory =
+         phypGetLparMem(dom->conn, managed_system, dom->id, 1)) == 0)
+        VIR_WARN("%s", "Unable to determine domain's memory.");
+
+    if ((info->nrVirtCpu =
+         phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0)
+        VIR_WARN("%s", "Unable to determine domain's CPU.");
+
+    return 0;
+
+}
+
+virDriver phypDriver = {
+    VIR_DRV_PHYP,
+    "PHYP",
+    phypOpen,                   /* open */
+    phypClose,                  /* close */
+    NULL,                       /* supports_feature */
+    NULL,                       /* type */
+    NULL,                       /* version */
+    NULL,                       /* getHostname */
+    NULL,                       /* getMaxVcpus */
+    NULL,                       /* nodeGetInfo */
+    NULL,                       /* getCapabilities */
+    phypListDomains,            /* listDomains */
+    phypNumDomains,             /* numOfDomains */
+    NULL,                       /* domainCreateXML */
+    phypDomainLookupByID,       /* domainLookupByID */
+    NULL,                       /* domainLookupByUUID */
+    phypDomainLookupByName,     /* domainLookupByName */
+    NULL,                       /* domainSuspend */
+    phypDomainResume,           /* domainResume */
+    phypDomainShutdown,         /* domainShutdown */
+    NULL,                       /* domainReboot */
+    NULL,                       /* domainDestroy */
+    NULL,                       /* domainGetOSType */
+    NULL,                       /* domainGetMaxMemory */
+    NULL,                       /* domainSetMaxMemory */
+    NULL,                       /* domainSetMemory */
+    phypDomainGetInfo,          /* domainGetInfo */
+    NULL,                       /* domainSave */
+    NULL,                       /* domainRestore */
+    NULL,                       /* domainCoreDump */
+    NULL,                       /* domainSetVcpus */
+    NULL,                       /* domainPinVcpu */
+    NULL,                       /* domainGetVcpus */
+    NULL,                       /* domainGetMaxVcpus */
+    NULL,                       /* domainGetSecurityLabel */
+    NULL,                       /* nodeGetSecurityModel */
+    phypDomainDumpXML,          /* domainDumpXML */
+    NULL,                       /* domainXmlFromNative */
+    NULL,                       /* domainXmlToNative */
+    phypListDefinedDomains,     /* listDefinedDomains */
+    phypNumDefinedDomains,      /* numOfDefinedDomains */
+    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,                       /* getFreeMemory */
+    NULL,                       /* domainEventRegister */
+    NULL,                       /* domainEventDeregister */
+    NULL,                       /* domainMigratePrepare2 */
+    NULL,                       /* domainMigrateFinish2 */
+    NULL,                       /* nodeDeviceDettach */
+    NULL,                       /* nodeDeviceReAttach */
+    NULL,                       /* nodeDeviceReset */
+};
+
+int
+phypRegister(void)
+{
+    virRegisterDriver(&phypDriver);
+    return 0;
+}
+
+void
+init_uuid_db(virConnectPtr conn)
+{
+    uuid_dbPtr uuid_db;
+    int nids = 0;
+    int *ids = NULL;
+    unsigned int i = 0;
+
+    if ((nids = phypNumDomainsGeneric(conn, 2)) == 0)
+        goto exit;
+
+    if (VIR_ALLOC_N(ids, nids) < 0)
+        virReportOOMError(conn);
+
+    if (VIR_ALLOC(uuid_db) < 0)
+        virReportOOMError(conn);
+
+    if (phypListDomainsGeneric(conn, ids, nids, 1) == 0)
+        goto exit;
+
+    uuid_db = conn->privateData;
+    uuid_db->nlpars = nids;
+
+    if (VIR_ALLOC_N(uuid_db->lpars, uuid_db->nlpars) >= 0) {
+        for (i = 0; i < uuid_db->nlpars; i++) {
+            if (VIR_ALLOC(uuid_db->lpars[i]) < 0)
+                virReportOOMError(conn);
+            uuid_db->lpars[i]->id = ids[i];
+
+            if (virUUIDGenerate(uuid_db->lpars[i]->uuid) < 0)
+                VIR_WARN("%s %d", "Unable to generate UUID for domain",
+                         ids[i]);
+        }
+    }
+  exit:
+    VIR_FREE(ids);
+    return;
+}
+
+int
+escape_specialcharacters(char *src, char *dst)
+{
+    size_t len = strlen(src);
+    char temp_buffer[len];
+    unsigned int i = 0, j = 0;
+    if (len == 0)
+        return -1;
+
+    for (i = 0; i < len; i++) {
+        switch (src[i]) {
+            case '&': case ';': case '`': case '@':
+            case '"': case '|': case '*': case '?':
+            case '~': case '<': case '>': case '^':
+            case '(': case ')': case '[': case ']':
+            case '{': case '}': case '$': case '%':
+            case '#': case '\\': case '\n': case '\r':
+            case '\t':
+                continue;
+            default:
+                temp_buffer[j] = src[i];
+                j++;
+        }
+    }
+    temp_buffer[j] = '\0';
+
+    if (strncpy(dst, temp_buffer, j) == NULL)
+        return -1;
+
+    return 0;
+}
diff --git a/src/phyp/phyp_driver.h b/src/phyp/phyp_driver.h
new file mode 100644
index 0000000000..fd824b33bd
--- /dev/null
+++ b/src/phyp/phyp_driver.h
@@ -0,0 +1,66 @@
+#include 
+#include 
+
+#define LPAR_EXEC_ERR -1
+#define SSH_CONN_ERR -2         /* error while trying to connect to remote host */
+#define SSH_CMD_ERR -3          /* error while trying to execute the remote cmd */
+
+typedef struct _ConnectionData ConnectionData;
+typedef ConnectionData *ConnectionDataPtr;
+struct _ConnectionData {
+    SSH_SESSION *session;
+    virConnectAuthPtr auth;
+};
+
+/* This is the lpar (domain) struct that relates
+ * the ID with UUID generated by the API
+ * */
+typedef struct _lpar lpar_t;
+typedef lpar_t *lparPtr;
+struct _lpar {
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    int id;
+};
+
+/* Struct that holds how many lpars (domains) we're
+ * handling and a pointer to an array of lpar structs
+ * */
+typedef struct _uuid_db uuid_db_t;
+typedef uuid_db_t *uuid_dbPtr;
+struct _uuid_db {
+    int nlpars;
+    lparPtr *lpars;
+};
+
+int phypGetLparUUID(unsigned char *uuid, int lpar_id, virConnectPtr conn);
+
+void init_uuid_db(virConnectPtr conn);
+
+int phypRegister(void);
+
+void stripPath(char *striped_path, char *path);
+
+void stripNewline(char *striped_string, char *string);
+
+int buffer_add_u8(struct buffer_struct *buffer, u8 data);
+
+int phypGetLparState(virConnectPtr conn, unsigned int lpar_id);
+
+unsigned long phypGetLparMem(virConnectPtr conn,
+                             const char *managed_system, int lpar_id,
+                             int type);
+
+unsigned long phypGetLparCPU(virConnectPtr conn,
+                             const char *managed_system, int lpar_id);
+
+int phypGetRemoteSlot(virConnectPtr conn, const char *managed_system,
+                      const char *lpar_name);
+
+char *phypGetBackingDevice(virConnectPtr conn, const char *managed_system,
+                           char *lpar_name);
+
+int phypDiskType(virConnectPtr conn, char *backing_device);
+
+SSH_SESSION *openSSHSession(virConnectPtr conn, virConnectAuthPtr auth);
+
+int escape_specialcharacters(char *src, char *dst);
diff --git a/src/virterror.c b/src/virterror.c
index e9192632a5..362d8ef1f7 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;