diff --git a/configure.in b/configure.in index 552587c00161f6c06cfb401fc429fa228599f578..a3d357aeb31782128941c41b746b949ccd151c75 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 448c06d9abdc1512e5d84e3743d2857ffd029d5e..603814e90addb960681919f35e69bf6a40a83a06 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 dc2592e932daa1d3208a12d7daedb691459aafa5..e4d013f310f89b2803a25a2955d00e8d823e82b5 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 92091fd1f70833d7d14b6cdae157e67093b70465..9a0e1f5d0cdfe909fb8814ac5ad4508151ce33a2 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 d0e32826591257301325f20f391571a05ccc8871..2301a969b9857542fa2de27f716bd8bbcc180e96 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 8dda78d807035b3d199ed2e3ee7117cedf03811b..63fca76f979b9bd88ce2f29030bcc41fab4f5a9b 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 2d94444a2c075f30d73a6a443c0928f58a68c457..79d46ffbfff61eae75a8f860862c6c564f51e1ee 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 8a0ad3866a2e94156e76b5cbee36e506d2927ecb..1752e9d93946cb6d75edf92b891354f7e57c269c 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 0000000000000000000000000000000000000000..cf3cd4b03f4aec167b82f7fca18139a4baaee12f --- /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 0000000000000000000000000000000000000000..fd824b33bd4be8df0824568265c6bf86309bdf75 --- /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 e9192632a54dfe8c2ebe46f3f195554a1180b084..362d8ef1f791633444e084886dbf3e70bcc3021f 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;