2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright IBM Corp. 2009
|
|
|
|
*
|
|
|
|
* phyp_driver.c: ssh layer to access Power Hypervisors
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Eduardo Otubo <otubo at linux.vnet.ibm.com>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
2009-11-05 16:18:07 +00:00
|
|
|
#include <sys/stat.h>
|
2009-07-24 14:17:06 +00:00
|
|
|
#include <limits.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <strings.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdio.h>
|
2009-09-04 10:08:47 +00:00
|
|
|
#include <libssh2.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netdb.h>
|
2009-11-05 16:18:07 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
#include <domain_event.h>
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
#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"
|
2009-11-05 16:18:07 +00:00
|
|
|
#include "nodeinfo.h"
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
#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)
|
|
|
|
{
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = NULL;
|
2009-08-20 10:32:19 +00:00
|
|
|
ConnectionData *connection_data = NULL;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *string = NULL;
|
2009-08-20 11:59:07 +00:00
|
|
|
size_t len = 0;
|
2009-09-04 10:08:47 +00:00
|
|
|
int internal_socket;
|
2009-11-05 16:18:07 +00:00
|
|
|
uuid_tablePtr uuid_table = NULL;
|
|
|
|
phyp_driverPtr phyp_driver = NULL;
|
|
|
|
char *char_ptr;
|
|
|
|
char *managed_system;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
if (conn->uri->path == NULL) {
|
|
|
|
virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
|
|
|
|
VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
|
|
|
|
_("Missing managed system name in phyp:// URI"));
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-07-24 14:17:06 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
if (VIR_ALLOC(phyp_driver) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(uuid_table) < 0) {
|
2009-08-20 10:32:19 +00:00
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(connection_data) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
2009-08-20 11:59:07 +00:00
|
|
|
len = strlen(conn->uri->path) + 1;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(string, len) < 0) {
|
2009-08-20 10:32:19 +00:00
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
/* need to shift one byte in order to remove the first "/" of URI component */
|
|
|
|
if (conn->uri->path[0] == '/')
|
|
|
|
managed_system = strdup(conn->uri->path + 1);
|
|
|
|
else
|
|
|
|
managed_system = strdup(conn->uri->path);
|
|
|
|
|
|
|
|
if (!managed_system) {
|
2009-11-05 16:18:07 +00:00
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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';
|
|
|
|
|
2009-08-20 11:59:07 +00:00
|
|
|
if (escape_specialcharacters(conn->uri->path, string, len) == -1) {
|
2009-07-24 14:17:06 +00:00
|
|
|
virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
|
|
|
|
VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
|
|
|
|
_("Error parsing 'path'. Invalid characters."));
|
2009-08-20 10:32:19 +00:00
|
|
|
goto failure;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if ((session = openSSHSession(conn, auth, &internal_socket)) == NULL) {
|
2009-07-24 14:17:06 +00:00
|
|
|
virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
|
|
|
|
VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
|
|
|
|
_("Error while opening SSH session."));
|
2009-08-20 10:32:19 +00:00
|
|
|
goto failure;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
2009-09-04 10:08:47 +00:00
|
|
|
//conn->uri->path = string;
|
2009-07-24 14:17:06 +00:00
|
|
|
connection_data->session = session;
|
|
|
|
connection_data->auth = auth;
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
uuid_table->nlpars = 0;
|
|
|
|
uuid_table->lpars = NULL;
|
|
|
|
|
|
|
|
phyp_driver->managed_system = managed_system;
|
|
|
|
phyp_driver->uuid_table = uuid_table;
|
|
|
|
if ((phyp_driver->caps = phypCapsInit()) == NULL) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
conn->privateData = phyp_driver;
|
2009-07-24 14:17:06 +00:00
|
|
|
conn->networkPrivateData = connection_data;
|
2009-11-05 16:18:07 +00:00
|
|
|
if (phypUUIDTable_Init(conn) == -1)
|
|
|
|
goto failure;
|
|
|
|
|
|
|
|
if ((phyp_driver->vios_id = phypGetVIOSPartitionID(conn)) == -1)
|
|
|
|
goto failure;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
return VIR_DRV_OPEN_SUCCESS;
|
2009-08-20 10:32:19 +00:00
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
failure:
|
2009-11-05 23:19:16 +00:00
|
|
|
if (phyp_driver != NULL) {
|
|
|
|
virCapabilitiesFree(phyp_driver->caps);
|
|
|
|
VIR_FREE(phyp_driver->managed_system);
|
|
|
|
VIR_FREE(phyp_driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
phypUUIDTable_Free(uuid_table);
|
|
|
|
|
|
|
|
if (session != NULL) {
|
|
|
|
libssh2_session_disconnect(session, "Disconnecting...");
|
|
|
|
libssh2_session_free(session);
|
|
|
|
}
|
|
|
|
|
2009-08-20 10:32:19 +00:00
|
|
|
VIR_FREE(connection_data);
|
|
|
|
VIR_FREE(string);
|
|
|
|
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
phypClose(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
ConnectionData *connection_data = conn->networkPrivateData;
|
2009-11-05 16:18:07 +00:00
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
libssh2_session_disconnect(session, "Disconnecting...");
|
|
|
|
libssh2_session_free(session);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
virCapabilitiesFree(phyp_driver->caps);
|
2009-11-05 23:19:16 +00:00
|
|
|
phypUUIDTable_Free(phyp_driver->uuid_table);
|
2009-11-05 16:18:07 +00:00
|
|
|
VIR_FREE(phyp_driver->managed_system);
|
|
|
|
VIR_FREE(phyp_driver);
|
2009-07-24 14:17:06 +00:00
|
|
|
VIR_FREE(connection_data);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *
|
|
|
|
openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
|
|
|
|
int *internal_socket)
|
2009-07-24 14:17:06 +00:00
|
|
|
{
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session;
|
|
|
|
const char *hostname = conn->uri->server;
|
|
|
|
const char *username = conn->uri->user;
|
|
|
|
const char *password = NULL;
|
|
|
|
int sock;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
struct addrinfo *ai = NULL, *cur;
|
|
|
|
struct addrinfo hints;
|
|
|
|
int ret;
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
memset(&hints, '\0', sizeof(hints));
|
2009-09-04 10:08:47 +00:00
|
|
|
hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
|
|
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
|
|
hints.ai_protocol = 0;
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
ret = getaddrinfo(hostname, "22", &hints, &ai);
|
2009-09-04 10:08:47 +00:00
|
|
|
if (ret != 0) {
|
|
|
|
virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
|
|
|
|
VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
2009-11-05 16:18:07 +00:00
|
|
|
_("Error while getting %s address info"), hostname);
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
cur = ai;
|
|
|
|
while (cur != NULL) {
|
|
|
|
sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
|
|
|
|
if (sock >= 0) {
|
2009-11-05 16:18:07 +00:00
|
|
|
if (connect(sock, cur->ai_addr, cur->ai_addrlen) == 0) {
|
2009-09-04 10:08:47 +00:00
|
|
|
goto connected;
|
|
|
|
}
|
2009-11-05 16:18:07 +00:00
|
|
|
close(sock);
|
2009-09-04 10:08:47 +00:00
|
|
|
}
|
|
|
|
cur = cur->ai_next;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
|
|
|
|
VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
|
|
|
_("Failed to connect to %s"), hostname);
|
2009-11-05 16:18:07 +00:00
|
|
|
freeaddrinfo(ai);
|
2009-09-04 10:08:47 +00:00
|
|
|
goto err;
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
connected:
|
2009-09-04 10:08:47 +00:00
|
|
|
|
|
|
|
(*internal_socket) = sock;
|
|
|
|
|
|
|
|
/* Create a session instance */
|
|
|
|
session = libssh2_session_init();
|
|
|
|
if (!session)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* tell libssh2 we want it all done non-blocking */
|
|
|
|
libssh2_session_set_blocking(session, 0);
|
|
|
|
|
|
|
|
while ((rc = libssh2_session_startup(session, sock)) ==
|
|
|
|
LIBSSH2_ERROR_EAGAIN) ;
|
|
|
|
if (rc) {
|
|
|
|
virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
|
|
|
|
VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
|
|
|
|
_("Failure establishing SSH session."));
|
2009-11-05 23:19:16 +00:00
|
|
|
goto disconnect;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
/* Trying authentication by pubkey */
|
|
|
|
while ((rc =
|
|
|
|
libssh2_userauth_publickey_fromfile(session, username,
|
|
|
|
"/home/user/"
|
|
|
|
".ssh/id_rsa.pub",
|
|
|
|
"/home/user/"
|
|
|
|
".ssh/id_rsa",
|
|
|
|
password)) ==
|
|
|
|
LIBSSH2_ERROR_EAGAIN) ;
|
|
|
|
if (rc) {
|
2009-07-24 14:17:06 +00:00
|
|
|
int i;
|
|
|
|
int hasPassphrase = 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."));
|
2009-11-05 23:19:16 +00:00
|
|
|
goto disconnect;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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."));
|
2009-11-05 23:19:16 +00:00
|
|
|
goto disconnect;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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."));
|
2009-11-05 23:19:16 +00:00
|
|
|
goto disconnect;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if (creds[0].result) {
|
2009-07-24 14:17:06 +00:00
|
|
|
password = creds[0].result;
|
2009-09-04 10:08:47 +00:00
|
|
|
} else {
|
2009-07-24 14:17:06 +00:00
|
|
|
virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
|
2009-09-04 10:08:47 +00:00
|
|
|
VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
|
|
|
|
_("Unable to get password certificates"));
|
2009-11-05 23:19:16 +00:00
|
|
|
goto disconnect;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
while ((rc =
|
|
|
|
libssh2_userauth_password(session, username,
|
|
|
|
password)) ==
|
|
|
|
LIBSSH2_ERROR_EAGAIN) ;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if (rc) {
|
2009-07-24 14:17:06 +00:00
|
|
|
virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
|
2009-09-04 10:08:47 +00:00
|
|
|
VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s",
|
|
|
|
_("Authentication failed"));
|
2009-11-05 23:19:16 +00:00
|
|
|
goto disconnect;
|
2009-07-24 14:17:06 +00:00
|
|
|
} else
|
|
|
|
goto exit;
|
2009-09-04 10:08:47 +00:00
|
|
|
}
|
2009-11-05 23:19:16 +00:00
|
|
|
disconnect:
|
|
|
|
libssh2_session_disconnect(session, "Disconnecting...");
|
|
|
|
libssh2_session_free(session);
|
2009-07-24 14:17:06 +00:00
|
|
|
err:
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(password);
|
2009-07-24 14:17:06 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
exit:
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(password);
|
2009-07-24 14:17:06 +00:00
|
|
|
return session;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this functions is the layer that manipulates the ssh channel itself
|
|
|
|
* and executes the commands on the remote machine */
|
|
|
|
static char *
|
2009-09-04 10:08:47 +00:00
|
|
|
phypExec(LIBSSH2_SESSION * session, char *cmd, int *exit_status,
|
2009-07-24 14:17:06 +00:00
|
|
|
virConnectPtr conn)
|
|
|
|
{
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_CHANNEL *channel;
|
|
|
|
ConnectionData *connection_data = conn->networkPrivateData;
|
2009-07-24 14:17:06 +00:00
|
|
|
virBuffer tex_ret = VIR_BUFFER_INITIALIZER;
|
2009-09-04 10:08:47 +00:00
|
|
|
char buffer[0x4000] = { 0 };
|
|
|
|
int exitcode;
|
|
|
|
int bytecount = 0;
|
|
|
|
int sock = connection_data->sock;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
/* Exec non-blocking on the remove host */
|
|
|
|
while ((channel = libssh2_channel_open_session(session)) == NULL &&
|
|
|
|
libssh2_session_last_error(session, NULL, NULL, 0) ==
|
|
|
|
LIBSSH2_ERROR_EAGAIN) {
|
|
|
|
waitsocket(sock, session);
|
|
|
|
}
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if (channel == NULL) {
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
while ((rc = libssh2_channel_exec(channel, cmd)) ==
|
|
|
|
LIBSSH2_ERROR_EAGAIN) {
|
|
|
|
waitsocket(sock, session);
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if (rc != 0) {
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
for (;;) {
|
|
|
|
/* loop until we block */
|
|
|
|
do {
|
|
|
|
rc = libssh2_channel_read(channel, buffer, sizeof(buffer));
|
|
|
|
if (rc > 0) {
|
|
|
|
bytecount += rc;
|
|
|
|
virBufferVSprintf(&tex_ret, "%s", buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (rc > 0);
|
|
|
|
|
|
|
|
/* this is due to blocking that would occur otherwise so we loop on
|
|
|
|
* this condition */
|
|
|
|
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
|
|
|
waitsocket(sock, session);
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
exitcode = 127;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
while ((rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN) {
|
|
|
|
waitsocket(sock, session);
|
|
|
|
}
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if (rc == 0) {
|
|
|
|
exitcode = libssh2_channel_get_exit_status(channel);
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
(*exit_status) = exitcode;
|
|
|
|
libssh2_channel_free(channel);
|
|
|
|
channel = NULL;
|
|
|
|
goto exit;
|
|
|
|
|
2009-07-24 14:17:06 +00:00
|
|
|
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
|
2009-09-04 10:08:47 +00:00
|
|
|
phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system,
|
2009-07-24 14:17:06 +00:00
|
|
|
const char *name, virConnectPtr conn)
|
|
|
|
{
|
|
|
|
int exit_status = 0;
|
|
|
|
int lpar_id = 0;
|
|
|
|
char *char_ptr;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if (virAsprintf(&cmd,
|
|
|
|
"lssyscfg -r lpar -m %s --filter lpar_names=%s -F lpar_id",
|
|
|
|
managed_system, name) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, conn);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if (exit_status < 0 || ret == NULL)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-07-24 14:17:06 +00:00
|
|
|
return lpar_id;
|
|
|
|
|
|
|
|
err:
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-07-24 14:17:06 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* return the lpar name given a lpar_id and a managed system name */
|
|
|
|
static char *
|
2009-09-04 10:08:47 +00:00
|
|
|
phypGetLparNAME(LIBSSH2_SESSION * session, const char *managed_system,
|
2009-07-24 14:17:06 +00:00
|
|
|
unsigned int lpar_id, virConnectPtr conn)
|
|
|
|
{
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, conn);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if (ret == NULL)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
char *char_ptr = strchr(ret, '\n');
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if (char_ptr)
|
|
|
|
*char_ptr = '\0';
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if (exit_status < 0 || ret == NULL)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
VIR_FREE(cmd);
|
2009-09-04 10:08:47 +00:00
|
|
|
return ret;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
err:
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-07-24 14:17:06 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
/* Search into the uuid_table for a lpar_uuid given a lpar_id
|
2009-07-24 14:17:06 +00:00
|
|
|
* and a managed system name
|
|
|
|
*
|
|
|
|
* return: 0 - record found
|
|
|
|
* -1 - not found
|
|
|
|
* */
|
|
|
|
int
|
|
|
|
phypGetLparUUID(unsigned char *uuid, int lpar_id, virConnectPtr conn)
|
|
|
|
{
|
2009-11-05 16:18:07 +00:00
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
|
|
|
uuid_tablePtr uuid_table = phyp_driver->uuid_table;
|
|
|
|
lparPtr *lpars = uuid_table->lpars;
|
2009-07-24 14:17:06 +00:00
|
|
|
unsigned int i = 0;
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
for (i = 0; i < uuid_table->nlpars; i++) {
|
2009-07-24 14:17:06 +00:00
|
|
|
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;
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
char *char_ptr;
|
|
|
|
int memory = 0;
|
|
|
|
int exit_status = 0;
|
|
|
|
|
|
|
|
if (type != 1 && type != 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (type) {
|
|
|
|
if (virAsprintf(&cmd,
|
2009-11-05 16:18:07 +00:00
|
|
|
"lshwres -m %s -r mem --level lpar -F curr_mem "
|
|
|
|
"--filter lpar_ids=%d",
|
2009-07-24 14:17:06 +00:00
|
|
|
managed_system, lpar_id) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (virAsprintf(&cmd,
|
2009-11-05 16:18:07 +00:00
|
|
|
"lshwres -m %s -r mem --level lpar -F "
|
|
|
|
"curr_max_mem --filter lpar_ids=%d",
|
2009-07-24 14:17:06 +00:00
|
|
|
managed_system, lpar_id) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, conn);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if (ret == NULL)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
char *mem_char_ptr = strchr(ret, '\n');
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if (mem_char_ptr)
|
|
|
|
*mem_char_ptr = '\0';
|
|
|
|
|
|
|
|
if (exit_status < 0)
|
|
|
|
goto err;
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if (virStrToLong_i(ret, &char_ptr, 10, &memory) == -1)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-07-24 14:17:06 +00:00
|
|
|
return memory;
|
|
|
|
|
|
|
|
err:
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-07-24 14:17:06 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned long
|
|
|
|
phypGetLparCPU(virConnectPtr conn, const char *managed_system, int lpar_id)
|
2009-11-05 16:18:07 +00:00
|
|
|
{
|
|
|
|
return phypGetLparCPUGeneric(conn, managed_system, lpar_id, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
phypGetLparCPUMAX(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
phyp_driverPtr phyp_driver = dom->conn->privateData;
|
|
|
|
char *managed_system = phyp_driver->managed_system;
|
|
|
|
|
|
|
|
return phypGetLparCPUGeneric(dom->conn, managed_system, dom->id, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned long
|
|
|
|
phypGetLparCPUGeneric(virConnectPtr conn, const char *managed_system,
|
|
|
|
int lpar_id, int type)
|
2009-07-24 14:17:06 +00:00
|
|
|
{
|
|
|
|
ConnectionData *connection_data = conn->networkPrivateData;
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
int exit_status = 0;
|
|
|
|
int vcpus = 0;
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
if (type) {
|
|
|
|
if (virAsprintf(&cmd,
|
|
|
|
"lshwres -m %s -r proc --level lpar -F "
|
|
|
|
"curr_max_procs --filter lpar_ids=%d",
|
|
|
|
managed_system, lpar_id) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
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;
|
|
|
|
}
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, conn);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if (ret == NULL)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
char *char_ptr = strchr(ret, '\n');
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if (char_ptr)
|
|
|
|
*char_ptr = '\0';
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if (virStrToLong_i(ret, &char_ptr, 10, &vcpus) == -1)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (exit_status < 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-07-24 14:17:06 +00:00
|
|
|
return (unsigned long) vcpus;
|
|
|
|
|
|
|
|
err:
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-07-24 14:17:06 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
phypGetRemoteSlot(virConnectPtr conn, const char *managed_system,
|
|
|
|
const char *lpar_name)
|
|
|
|
{
|
|
|
|
ConnectionData *connection_data = conn->networkPrivateData;
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
char *char_ptr;
|
|
|
|
int remote_slot = 0;
|
|
|
|
int exit_status = 0;
|
|
|
|
|
|
|
|
if (virAsprintf(&cmd,
|
2009-11-05 16:18:07 +00:00
|
|
|
"lshwres -m %s -r virtualio --rsubtype scsi -F "
|
|
|
|
"remote_slot_num --filter lpar_names=%s",
|
2009-07-24 14:17:06 +00:00
|
|
|
managed_system, lpar_name) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto err;
|
|
|
|
}
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, conn);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if (ret == NULL)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
char *char_ptr2 = strchr(ret, '\n');
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if (char_ptr2)
|
|
|
|
*char_ptr2 = '\0';
|
|
|
|
|
|
|
|
if (exit_status < 0)
|
|
|
|
goto err;
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
if (virStrToLong_i(ret, &char_ptr, 10, &remote_slot) == -1)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-07-24 14:17:06 +00:00
|
|
|
return remote_slot;
|
|
|
|
|
|
|
|
err:
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-11-05 16:18:07 +00:00
|
|
|
return -1;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
phypGetBackingDevice(virConnectPtr conn, const char *managed_system,
|
|
|
|
char *lpar_name)
|
|
|
|
{
|
|
|
|
ConnectionData *connection_data = conn->networkPrivateData;
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
int remote_slot = 0;
|
|
|
|
int exit_status = 0;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *char_ptr;
|
|
|
|
char *backing_device = NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if ((remote_slot =
|
2009-11-05 16:18:07 +00:00
|
|
|
phypGetRemoteSlot(conn, managed_system, lpar_name)) == -1)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (virAsprintf(&cmd,
|
2009-11-05 16:18:07 +00:00
|
|
|
"lshwres -m %s -r virtualio --rsubtype scsi -F "
|
|
|
|
"backing_devices --filter slots=%d",
|
2009-07-24 14:17:06 +00:00
|
|
|
managed_system, remote_slot) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, conn);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
if (exit_status < 0 || ret == NULL)
|
2009-07-24 14:17:06 +00:00
|
|
|
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.
|
|
|
|
* */
|
2009-11-05 23:19:16 +00:00
|
|
|
char_ptr = strchr(ret, '/');
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
if (char_ptr) {
|
|
|
|
char_ptr++;
|
|
|
|
if (char_ptr[0] == '/')
|
|
|
|
char_ptr++;
|
2009-07-24 14:17:06 +00:00
|
|
|
else
|
|
|
|
goto err;
|
2009-11-05 23:19:16 +00:00
|
|
|
|
|
|
|
backing_device = strdup(char_ptr);
|
|
|
|
|
|
|
|
if (backing_device == NULL) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto err;
|
|
|
|
}
|
2009-07-24 14:17:06 +00:00
|
|
|
} else {
|
|
|
|
backing_device = ret;
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
char_ptr = strchr(backing_device, '\n');
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if (char_ptr)
|
|
|
|
*char_ptr = '\0';
|
|
|
|
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-07-24 14:17:06 +00:00
|
|
|
return backing_device;
|
|
|
|
|
|
|
|
err:
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-07-24 14:17:06 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
phypGetLparState(virConnectPtr conn, unsigned int lpar_id)
|
|
|
|
{
|
|
|
|
ConnectionData *connection_data = conn->networkPrivateData;
|
2009-11-05 16:18:07 +00:00
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
int exit_status = 0;
|
|
|
|
char *char_ptr = NULL;
|
2009-11-05 16:18:07 +00:00
|
|
|
char *managed_system = phyp_driver->managed_system;
|
2009-11-05 23:19:16 +00:00
|
|
|
int state = VIR_DOMAIN_NOSTATE;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if (virAsprintf(&cmd,
|
|
|
|
"lssyscfg -r lpar -m %s -F state --filter lpar_ids=%d",
|
|
|
|
managed_system, lpar_id) < 0) {
|
|
|
|
virReportOOMError(conn);
|
2009-11-05 23:19:16 +00:00
|
|
|
goto cleanup;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, conn);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
if (exit_status < 0 || ret == NULL)
|
|
|
|
goto cleanup;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
char_ptr = strchr(ret, '\n');
|
|
|
|
|
|
|
|
if (char_ptr)
|
|
|
|
*char_ptr = '\0';
|
|
|
|
|
|
|
|
if (STREQ(ret, "Running"))
|
2009-11-05 23:19:16 +00:00
|
|
|
state = VIR_DOMAIN_RUNNING;
|
2009-07-24 14:17:06 +00:00
|
|
|
else if (STREQ(ret, "Not Activated"))
|
2009-11-05 23:19:16 +00:00
|
|
|
state = VIR_DOMAIN_SHUTOFF;
|
2009-07-24 14:17:06 +00:00
|
|
|
else if (STREQ(ret, "Shutting Down"))
|
2009-11-05 23:19:16 +00:00
|
|
|
state = VIR_DOMAIN_SHUTDOWN;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
cleanup:
|
2009-07-24 14:17:06 +00:00
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
|
|
|
return state;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
int
|
|
|
|
phypGetVIOSPartitionID(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
ConnectionData *connection_data = conn->networkPrivateData;
|
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-11-05 16:18:07 +00:00
|
|
|
int exit_status = 0;
|
|
|
|
int id = -1;
|
|
|
|
char *char_ptr;
|
|
|
|
char *managed_system = phyp_driver->managed_system;
|
|
|
|
|
|
|
|
if (virAsprintf(&cmd,
|
|
|
|
"lssyscfg -m %s -r lpar -F lpar_id,lpar_env|grep "
|
|
|
|
"vioserver|sed -s 's/,.*$//g'", managed_system) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, conn);
|
2009-11-05 16:18:07 +00:00
|
|
|
|
|
|
|
if (exit_status < 0 || ret == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (virStrToLong_i(ret, &char_ptr, 10, &id) == -1)
|
|
|
|
goto err;
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(cmd);
|
|
|
|
VIR_FREE(ret);
|
2009-11-05 16:18:07 +00:00
|
|
|
return id;
|
|
|
|
|
|
|
|
err:
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-11-05 16:18:07 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-07-24 14:17:06 +00:00
|
|
|
int
|
|
|
|
phypDiskType(virConnectPtr conn, char *backing_device)
|
|
|
|
{
|
2009-11-05 16:18:07 +00:00
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
2009-07-24 14:17:06 +00:00
|
|
|
ConnectionData *connection_data = conn->networkPrivateData;
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
int exit_status = 0;
|
2009-11-05 16:18:07 +00:00
|
|
|
char *char_ptr;
|
|
|
|
char *managed_system = phyp_driver->managed_system;
|
|
|
|
int vios_id = phyp_driver->vios_id;
|
2009-11-05 23:19:16 +00:00
|
|
|
int disk_type = -1;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if (virAsprintf(&cmd,
|
2009-11-05 16:18:07 +00:00
|
|
|
"viosvrcmd -m %s -p %d -c \"lssp -field name type "
|
|
|
|
"-fmt , -all|grep %s|sed -e 's/^.*,//g'\"",
|
|
|
|
managed_system, vios_id, backing_device) < 0) {
|
2009-07-24 14:17:06 +00:00
|
|
|
virReportOOMError(conn);
|
2009-11-05 23:19:16 +00:00
|
|
|
goto cleanup;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, conn);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
if (exit_status < 0 || ret == NULL)
|
|
|
|
goto cleanup;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
char_ptr = strchr(ret, '\n');
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if (char_ptr)
|
|
|
|
*char_ptr = '\0';
|
|
|
|
|
|
|
|
if (STREQ(ret, "LVPOOL"))
|
2009-11-05 23:19:16 +00:00
|
|
|
disk_type = VIR_DOMAIN_DISK_TYPE_BLOCK;
|
2009-07-24 14:17:06 +00:00
|
|
|
else if (STREQ(ret, "FBPOOL"))
|
2009-11-05 23:19:16 +00:00
|
|
|
disk_type = VIR_DOMAIN_DISK_TYPE_FILE;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
cleanup:
|
2009-07-24 14:17:06 +00:00
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
|
|
|
return disk_type;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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;
|
2009-11-05 16:18:07 +00:00
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-07-24 14:17:06 +00:00
|
|
|
int exit_status = 0;
|
|
|
|
int ndom = 0;
|
|
|
|
char *char_ptr;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-11-05 16:18:07 +00:00
|
|
|
char *managed_system = phyp_driver->managed_system;
|
2009-07-24 14:17:06 +00:00
|
|
|
const char *state;
|
|
|
|
|
|
|
|
if (type == 0)
|
|
|
|
state = "|grep Running";
|
|
|
|
else if (type == 1)
|
|
|
|
state = "|grep \"Not Activated\"";
|
|
|
|
else
|
|
|
|
state = " ";
|
|
|
|
|
|
|
|
if (virAsprintf(&cmd,
|
2009-11-05 16:18:07 +00:00
|
|
|
"lssyscfg -r lpar -m %s -F lpar_id,state %s |grep -c "
|
|
|
|
"^[0-9]*", managed_system, state) < 0) {
|
2009-07-24 14:17:06 +00:00
|
|
|
virReportOOMError(conn);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, conn);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if (exit_status < 0 || ret == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (virStrToLong_i(ret, &char_ptr, 10, &ndom) == -1)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-07-24 14:17:06 +00:00
|
|
|
return ndom;
|
|
|
|
|
|
|
|
err:
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-07-24 14:17:06 +00:00
|
|
|
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
|
2009-11-05 16:18:07 +00:00
|
|
|
* 1 - all
|
2009-07-24 14:17:06 +00:00
|
|
|
* */
|
|
|
|
static int
|
|
|
|
phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids,
|
|
|
|
unsigned int type)
|
|
|
|
{
|
|
|
|
ConnectionData *connection_data = conn->networkPrivateData;
|
2009-11-05 16:18:07 +00:00
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-11-05 16:18:07 +00:00
|
|
|
char *managed_system = phyp_driver->managed_system;
|
2009-07-24 14:17:06 +00:00
|
|
|
int exit_status = 0;
|
|
|
|
int got = 0;
|
|
|
|
char *char_ptr;
|
|
|
|
unsigned int i = 0, j = 0;
|
|
|
|
char id_c[10];
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
const char *state;
|
|
|
|
|
|
|
|
if (type == 0)
|
|
|
|
state = "|grep Running";
|
|
|
|
else
|
|
|
|
state = " ";
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, conn);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
/* I need to parse the textual return in order to get the ret */
|
|
|
|
if (exit_status < 0 || ret == NULL)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
else {
|
|
|
|
while (got < nids) {
|
2009-09-04 10:08:47 +00:00
|
|
|
if (ret[i] == '\n') {
|
2009-07-24 14:17:06 +00:00
|
|
|
if (virStrToLong_i(id_c, &char_ptr, 10, &ids[got]) == -1)
|
|
|
|
return 0;
|
|
|
|
memset(id_c, 0, 10);
|
|
|
|
j = 0;
|
|
|
|
got++;
|
|
|
|
} else {
|
2009-09-04 10:08:47 +00:00
|
|
|
id_c[j] = ret[i];
|
2009-07-24 14:17:06 +00:00
|
|
|
j++;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-07-24 14:17:06 +00:00
|
|
|
return got;
|
|
|
|
|
|
|
|
err:
|
|
|
|
VIR_FREE(cmd);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(ret);
|
2009-07-24 14:17:06 +00:00
|
|
|
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;
|
2009-11-05 16:18:07 +00:00
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-11-05 16:18:07 +00:00
|
|
|
char *managed_system = phyp_driver->managed_system;
|
2009-07-24 14:17:06 +00:00
|
|
|
int exit_status = 0;
|
|
|
|
int got = 0;
|
2009-11-05 23:19:16 +00:00
|
|
|
int i;
|
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
|
|
|
char *domains = NULL;
|
|
|
|
char *char_ptr2 = NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if (virAsprintf
|
|
|
|
(&cmd,
|
2009-11-05 16:18:07 +00:00
|
|
|
"lssyscfg -r lpar -m %s -F name,state | grep \"Not Activated\" | "
|
|
|
|
"sed -e 's/,.*$//g'", managed_system) < 0) {
|
2009-07-24 14:17:06 +00:00
|
|
|
virReportOOMError(conn);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, conn);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
/* I need to parse the textual return in order to get the domains */
|
2009-11-05 23:19:16 +00:00
|
|
|
if (exit_status < 0 || ret == NULL)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
else {
|
2009-11-05 23:19:16 +00:00
|
|
|
domains = ret;
|
|
|
|
|
2009-07-24 14:17:06 +00:00
|
|
|
while (got < nnames) {
|
|
|
|
char_ptr2 = strchr(domains, '\n');
|
|
|
|
|
|
|
|
if (char_ptr2) {
|
|
|
|
*char_ptr2 = '\0';
|
2009-11-05 23:19:16 +00:00
|
|
|
if ((names[got++] = strdup(domains)) == NULL) {
|
|
|
|
virReportOOMError(conn);
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
2009-11-05 23:19:16 +00:00
|
|
|
}
|
2009-07-24 14:17:06 +00:00
|
|
|
char_ptr2++;
|
|
|
|
domains = char_ptr2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
VIR_FREE(ret);
|
|
|
|
return got;
|
|
|
|
|
|
|
|
err:
|
2009-11-05 23:19:16 +00:00
|
|
|
for (i = 0; i < got; i++)
|
|
|
|
VIR_FREE(names[i]);
|
|
|
|
VIR_FREE(cmd);
|
2009-07-24 14:17:06 +00:00
|
|
|
VIR_FREE(ret);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
phypDomainLookupByName(virConnectPtr conn, const char *lpar_name)
|
|
|
|
{
|
|
|
|
ConnectionData *connection_data = conn->networkPrivateData;
|
2009-11-05 16:18:07 +00:00
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-07-24 14:17:06 +00:00
|
|
|
virDomainPtr dom = NULL;
|
|
|
|
int lpar_id = 0;
|
2009-11-05 16:18:07 +00:00
|
|
|
char *managed_system = phyp_driver->managed_system;
|
2009-07-24 14:17:06 +00:00
|
|
|
unsigned char *lpar_uuid = NULL;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(lpar_uuid, VIR_UUID_BUFLEN) < 0)
|
|
|
|
virReportOOMError(dom->conn);
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
lpar_id = phypGetLparID(session, managed_system, lpar_name, conn);
|
2009-11-05 16:18:07 +00:00
|
|
|
if (lpar_id == -1)
|
2009-07-24 14:17:06 +00:00
|
|
|
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;
|
2009-11-05 16:18:07 +00:00
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-07-24 14:17:06 +00:00
|
|
|
virDomainPtr dom = NULL;
|
2009-11-05 16:18:07 +00:00
|
|
|
char *managed_system = phyp_driver->managed_system;
|
2009-07-24 14:17:06 +00:00
|
|
|
int exit_status = 0;
|
|
|
|
unsigned char *lpar_uuid = NULL;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(lpar_uuid, VIR_UUID_BUFLEN) < 0)
|
|
|
|
virReportOOMError(dom->conn);
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
char *lpar_name = phypGetLparNAME(session, managed_system, lpar_id,
|
2009-07-24 14:17:06 +00:00
|
|
|
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;
|
2009-11-05 16:18:07 +00:00
|
|
|
phyp_driverPtr phyp_driver = dom->conn->privateData;
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-07-24 14:17:06 +00:00
|
|
|
virDomainDefPtr def = NULL;
|
|
|
|
char *ret = NULL;
|
2009-11-05 16:18:07 +00:00
|
|
|
char *managed_system = phyp_driver->managed_system;
|
2009-07-24 14:17:06 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
def->virtType = VIR_DOMAIN_VIRT_PHYP;
|
|
|
|
def->id = dom->id;
|
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
char *lpar_name = phypGetLparNAME(session, managed_system, def->id,
|
2009-07-24 14:17:06 +00:00
|
|
|
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);
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
virDomainDefFree(def);
|
2009-07-24 14:17:06 +00:00
|
|
|
return ret;
|
2009-11-05 16:18:07 +00:00
|
|
|
|
|
|
|
err:
|
|
|
|
virDomainDefFree(def);
|
|
|
|
return NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
phypDomainResume(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
ConnectionData *connection_data = dom->conn->networkPrivateData;
|
2009-11-05 16:18:07 +00:00
|
|
|
phyp_driverPtr phyp_driver = dom->conn->privateData;
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-11-05 16:18:07 +00:00
|
|
|
char *managed_system = phyp_driver->managed_system;
|
2009-07-24 14:17:06 +00:00
|
|
|
int exit_status = 0;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, dom->conn);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
if (exit_status < 0)
|
|
|
|
goto err;
|
|
|
|
|
2009-07-24 14:17:06 +00:00
|
|
|
VIR_FREE(cmd);
|
|
|
|
VIR_FREE(ret);
|
|
|
|
return 0;
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
err:
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
VIR_FREE(ret);
|
|
|
|
return -1;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
phypDomainShutdown(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
ConnectionData *connection_data = dom->conn->networkPrivateData;
|
2009-11-05 16:18:07 +00:00
|
|
|
phyp_driverPtr phyp_driver = dom->conn->privateData;
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
2009-11-05 16:18:07 +00:00
|
|
|
char *managed_system = phyp_driver->managed_system;
|
2009-07-24 14:17:06 +00:00
|
|
|
int exit_status = 0;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if (virAsprintf
|
|
|
|
(&cmd,
|
|
|
|
"chsysstate -m %s -r lpar -o shutdown --id %d",
|
|
|
|
managed_system, dom->id) < 0) {
|
|
|
|
virReportOOMError(dom->conn);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, dom->conn);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
if (exit_status < 0)
|
|
|
|
goto err;
|
|
|
|
|
2009-07-24 14:17:06 +00:00
|
|
|
VIR_FREE(cmd);
|
|
|
|
VIR_FREE(ret);
|
|
|
|
return 0;
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
err:
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
VIR_FREE(ret);
|
|
|
|
return 0;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
phypDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
|
|
|
|
{
|
2009-11-05 16:18:07 +00:00
|
|
|
phyp_driverPtr phyp_driver = dom->conn->privateData;
|
|
|
|
char *managed_system = phyp_driver->managed_system;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
static int
|
|
|
|
phypDomainDestroy(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
ConnectionData *connection_data = dom->conn->networkPrivateData;
|
|
|
|
phyp_driverPtr phyp_driver = dom->conn->privateData;
|
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
|
|
|
char *managed_system = phyp_driver->managed_system;
|
|
|
|
int exit_status = 0;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-11-05 16:18:07 +00:00
|
|
|
|
|
|
|
if (virAsprintf
|
|
|
|
(&cmd,
|
|
|
|
"rmsyscfg -m %s -r lpar --id %d", managed_system, dom->id) < 0) {
|
|
|
|
virReportOOMError(dom->conn);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, dom->conn);
|
2009-11-05 16:18:07 +00:00
|
|
|
|
|
|
|
if (exit_status < 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (phypUUIDTable_RemLpar(dom->conn, dom->id) == -1)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
VIR_FREE(ret);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
VIR_FREE(ret);
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
phypDomainCreateAndStart(virConnectPtr conn,
|
|
|
|
const char *xml,
|
|
|
|
unsigned int flags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
|
|
|
|
ConnectionData *connection_data = conn->networkPrivateData;
|
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
|
|
|
virDomainDefPtr def = NULL;
|
|
|
|
virDomainPtr dom = NULL;
|
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
|
|
|
uuid_tablePtr uuid_table = phyp_driver->uuid_table;
|
|
|
|
lparPtr *lpars = uuid_table->lpars;
|
|
|
|
unsigned int i = 0;
|
|
|
|
char *managed_system = phyp_driver->managed_system;
|
|
|
|
|
|
|
|
if (!(def = virDomainDefParseString(conn, phyp_driver->caps, xml,
|
|
|
|
VIR_DOMAIN_XML_SECURE)))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* checking if this name already exists on this system */
|
|
|
|
if (phypGetLparID(session, managed_system, def->name, conn) == -1) {
|
|
|
|
VIR_WARN("%s", "LPAR name already exists.");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* checking if ID or UUID already exists on this system */
|
|
|
|
for (i = 0; i < uuid_table->nlpars; i++) {
|
|
|
|
if (lpars[i]->id == def->id || lpars[i]->uuid == def->uuid) {
|
|
|
|
VIR_WARN("%s", "LPAR ID or UUID already exists.");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((dom = virGetDomain(conn, def->name, def->uuid)) == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (phypBuildLpar(conn, def) == -1)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (phypDomainResume(dom) == -1)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
return dom;
|
|
|
|
|
|
|
|
err:
|
|
|
|
virDomainDefFree(def);
|
2009-11-05 23:19:16 +00:00
|
|
|
if (dom)
|
|
|
|
virUnrefDomain(dom);
|
2009-11-05 16:18:07 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
phypConnectGetCapabilities(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
|
|
|
char *xml;
|
|
|
|
|
|
|
|
if ((xml = virCapabilitiesFormatXML(phyp_driver->caps)) == NULL)
|
|
|
|
virReportOOMError(conn);
|
|
|
|
|
|
|
|
return xml;
|
|
|
|
}
|
|
|
|
|
|
|
|
virCapsPtr
|
|
|
|
phypCapsInit(void)
|
|
|
|
{
|
|
|
|
struct utsname utsname;
|
|
|
|
virCapsPtr caps;
|
|
|
|
virCapsGuestPtr guest;
|
|
|
|
|
|
|
|
uname(&utsname);
|
|
|
|
|
|
|
|
if ((caps = virCapabilitiesNew(utsname.machine, 0, 0)) == NULL)
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
/* Some machines have problematic NUMA toplogy causing
|
|
|
|
* unexpected failures. We don't want to break the QEMU
|
|
|
|
* driver in this scenario, so log errors & carry on
|
|
|
|
*/
|
|
|
|
if (nodeCapsInitNUMA(caps) < 0) {
|
|
|
|
virCapabilitiesFreeNUMAInfo(caps);
|
|
|
|
VIR_WARN0
|
|
|
|
("Failed to query host NUMA topology, disabling NUMA capabilities");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX shouldn't 'borrow' KVM's prefix */
|
|
|
|
virCapabilitiesSetMacPrefix(caps, (unsigned char[]) {
|
|
|
|
0x52, 0x54, 0x00});
|
|
|
|
|
|
|
|
if ((guest = virCapabilitiesAddGuest(caps,
|
|
|
|
"linux",
|
|
|
|
utsname.machine,
|
|
|
|
sizeof(int) == 4 ? 32 : 8,
|
|
|
|
NULL, NULL, 0, NULL)) == NULL)
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
if (virCapabilitiesAddGuestDomain(guest,
|
|
|
|
"phyp", NULL, NULL, 0, NULL) == NULL)
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
return caps;
|
|
|
|
|
|
|
|
no_memory:
|
|
|
|
virCapabilitiesFree(caps);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus)
|
|
|
|
{
|
|
|
|
ConnectionData *connection_data = dom->conn->networkPrivateData;
|
|
|
|
phyp_driverPtr phyp_driver = dom->conn->privateData;
|
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
|
|
|
char *managed_system = phyp_driver->managed_system;
|
|
|
|
int exit_status = 0;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-11-05 16:18:07 +00:00
|
|
|
char operation;
|
|
|
|
unsigned long ncpus = 0;
|
|
|
|
unsigned int amount = 0;
|
|
|
|
|
|
|
|
if ((ncpus = phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (nvcpus > phypGetLparCPUMAX(dom)) {
|
|
|
|
VIR_ERROR("%s",
|
|
|
|
"You are trying to set a number of CPUs bigger than "
|
|
|
|
"the max possible..");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ncpus > nvcpus) {
|
|
|
|
operation = 'r';
|
|
|
|
amount = nvcpus - ncpus;
|
|
|
|
} else if (ncpus < nvcpus) {
|
|
|
|
operation = 'a';
|
|
|
|
amount = nvcpus - ncpus;
|
|
|
|
} else
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
if (virAsprintf
|
|
|
|
(&cmd,
|
|
|
|
"chhwres -r proc -m %s --id %d -o %c --procunits %d 2>&1 |sed"
|
|
|
|
"-e 's/^.*\\([0-9]\\+.[0-9]\\+\\).*$/\\1/g'",
|
|
|
|
managed_system, dom->id, operation, amount) < 0) {
|
|
|
|
virReportOOMError(dom->conn);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, dom->conn);
|
2009-11-05 16:18:07 +00:00
|
|
|
|
|
|
|
if (exit_status < 0) {
|
|
|
|
VIR_ERROR("%s",
|
|
|
|
"Possibly you don't have IBM Tools installed in your LPAR."
|
|
|
|
"Contact your support to enable this feature.");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
exit:
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
VIR_FREE(ret);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
VIR_FREE(ret);
|
|
|
|
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 */
|
|
|
|
phypConnectGetCapabilities, /* getCapabilities */
|
|
|
|
phypListDomains, /* listDomains */
|
|
|
|
phypNumDomains, /* numOfDomains */
|
|
|
|
phypDomainCreateAndStart, /* domainCreateXML */
|
|
|
|
phypDomainLookupByID, /* domainLookupByID */
|
|
|
|
NULL, /* domainLookupByUUID */
|
|
|
|
phypDomainLookupByName, /* domainLookupByName */
|
|
|
|
NULL, /* domainSuspend */
|
|
|
|
phypDomainResume, /* domainResume */
|
|
|
|
phypDomainShutdown, /* domainShutdown */
|
|
|
|
NULL, /* domainReboot */
|
|
|
|
phypDomainDestroy, /* domainDestroy */
|
|
|
|
NULL, /* domainGetOSType */
|
|
|
|
NULL, /* domainGetMaxMemory */
|
|
|
|
NULL, /* domainSetMaxMemory */
|
|
|
|
NULL, /* domainSetMemory */
|
2009-07-24 14:17:06 +00:00
|
|
|
phypDomainGetInfo, /* domainGetInfo */
|
|
|
|
NULL, /* domainSave */
|
|
|
|
NULL, /* domainRestore */
|
|
|
|
NULL, /* domainCoreDump */
|
2009-11-05 16:18:07 +00:00
|
|
|
phypDomainSetCPU, /* domainSetVcpus */
|
2009-07-24 14:17:06 +00:00
|
|
|
NULL, /* domainPinVcpu */
|
|
|
|
NULL, /* domainGetVcpus */
|
2009-11-05 16:18:07 +00:00
|
|
|
phypGetLparCPUMAX, /* domainGetMaxVcpus */
|
2009-07-24 14:17:06 +00:00
|
|
|
NULL, /* domainGetSecurityLabel */
|
|
|
|
NULL, /* nodeGetSecurityModel */
|
|
|
|
phypDomainDumpXML, /* domainDumpXML */
|
2009-09-06 14:03:06 +00:00
|
|
|
NULL, /* domainXMLFromNative */
|
|
|
|
NULL, /* domainXMLToNative */
|
2009-07-24 14:17:06 +00:00
|
|
|
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 */
|
2009-09-30 10:51:54 +00:00
|
|
|
NULL, /* domainMigratePrepareTunnel */
|
2009-07-24 14:17:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
int
|
2009-11-05 16:18:07 +00:00
|
|
|
phypBuildLpar(virConnectPtr conn, virDomainDefPtr def)
|
2009-07-24 14:17:06 +00:00
|
|
|
{
|
2009-11-05 16:18:07 +00:00
|
|
|
ConnectionData *connection_data = conn->networkPrivateData;
|
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
|
|
|
char *managed_system = phyp_driver->managed_system;
|
2009-11-05 23:19:16 +00:00
|
|
|
char *cmd = NULL;
|
|
|
|
char *ret = NULL;
|
2009-11-05 16:18:07 +00:00
|
|
|
int exit_status = 0;
|
|
|
|
|
|
|
|
if (virAsprintf
|
|
|
|
(&cmd,
|
|
|
|
"mksyscfg -m %s -r lpar -p %s -i min_mem=%d,desired_mem=%d,"
|
|
|
|
"max_mem=%d,desired_procs=%d,virtual_scsi_adapters=%s",
|
|
|
|
managed_system, def->name, (int) def->memory,
|
|
|
|
(int) def->memory, (int) def->maxmem, (int) def->vcpus,
|
|
|
|
def->disks[0]->src) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
ret = phypExec(session, cmd, &exit_status, conn);
|
2009-11-05 16:18:07 +00:00
|
|
|
|
|
|
|
if (exit_status < 0) {
|
|
|
|
VIR_ERROR("%s\"%s\"", "Unable to create LPAR. Reason: ", ret);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (phypUUIDTable_AddLpar(conn, def->uuid, def->id) == -1) {
|
|
|
|
VIR_ERROR("%s", "Unable to add LPAR to the table");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
VIR_FREE(ret);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
VIR_FREE(ret);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
phypUUIDTable_RemLpar(virConnectPtr conn, int id)
|
|
|
|
{
|
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
|
|
|
uuid_tablePtr uuid_table = phyp_driver->uuid_table;
|
|
|
|
unsigned int i = 0;
|
|
|
|
|
|
|
|
for (i = 0; i <= uuid_table->nlpars; i++) {
|
|
|
|
if (uuid_table->lpars[i]->id == id) {
|
|
|
|
uuid_table->lpars[i]->id = -1;
|
|
|
|
if (!memset(uuid_table->lpars[i]->uuid, '0', VIR_UUID_BUFLEN))
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (phypUUIDTable_WriteFile(conn) == -1)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (phypUUIDTable_Push(conn) == -1)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
exit:
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id)
|
|
|
|
{
|
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
|
|
|
uuid_tablePtr uuid_table = phyp_driver->uuid_table;
|
|
|
|
|
|
|
|
uuid_table->nlpars++;
|
|
|
|
unsigned int i = uuid_table->nlpars;
|
|
|
|
i--;
|
|
|
|
|
|
|
|
if (VIR_REALLOC_N(uuid_table->lpars, uuid_table->nlpars) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(uuid_table->lpars[i]) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
uuid_table->lpars[i]->id = id;
|
|
|
|
if (memmove(uuid_table->lpars[i]->uuid, uuid, VIR_UUID_BUFLEN) == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (phypUUIDTable_WriteFile(conn) == -1)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (phypUUIDTable_Push(conn) == -1)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
phypUUIDTable_ReadFile(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
|
|
|
uuid_tablePtr uuid_table = phyp_driver->uuid_table;
|
|
|
|
unsigned int i = 0;
|
|
|
|
int fd = -1;
|
|
|
|
char local_file[] = "./uuid_table";
|
|
|
|
int rc = 0;
|
|
|
|
char buffer[1024];
|
|
|
|
|
|
|
|
if ((fd = open(local_file, O_RDONLY)) == -1) {
|
|
|
|
VIR_WARN("%s", "Unable to write information to local file.");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Creating a new data base and writing to local file */
|
|
|
|
if (VIR_ALLOC_N(uuid_table->lpars, uuid_table->nlpars) >= 0) {
|
|
|
|
for (i = 0; i < uuid_table->nlpars; i++) {
|
|
|
|
|
|
|
|
rc = read(fd, buffer, sizeof(int));
|
|
|
|
if (rc == sizeof(int)) {
|
2009-11-05 23:19:16 +00:00
|
|
|
if (VIR_ALLOC(uuid_table->lpars[i]) < 0) {
|
2009-11-05 16:18:07 +00:00
|
|
|
virReportOOMError(conn);
|
2009-11-05 23:19:16 +00:00
|
|
|
goto err;
|
|
|
|
}
|
2009-11-05 16:18:07 +00:00
|
|
|
uuid_table->lpars[i]->id = (*buffer);
|
|
|
|
} else {
|
|
|
|
VIR_WARN("%s",
|
|
|
|
"Unable to read from information to local file.");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = read(fd, uuid_table->lpars[i]->uuid, VIR_UUID_BUFLEN);
|
|
|
|
if (rc != VIR_UUID_BUFLEN) {
|
|
|
|
VIR_WARN("%s",
|
|
|
|
"Unable to read information to local file.");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
phypUUIDTable_WriteFile(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
phyp_driverPtr phyp_driver = conn->privateData;
|
|
|
|
uuid_tablePtr uuid_table = phyp_driver->uuid_table;
|
|
|
|
unsigned int i = 0;
|
|
|
|
int fd = -1;
|
|
|
|
char local_file[] = "./uuid_table";
|
|
|
|
|
|
|
|
if ((fd = creat(local_file, 0755)) == -1)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
for (i = 0; i < uuid_table->nlpars; i++) {
|
|
|
|
if (safewrite(fd, &uuid_table->lpars[i]->id,
|
|
|
|
sizeof(uuid_table->lpars[i]->id)) ==
|
|
|
|
sizeof(uuid_table->lpars[i]->id)) {
|
|
|
|
VIR_ERROR("%s", "Unable to write information to local file.");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (safewrite(fd, uuid_table->lpars[i]->uuid, VIR_UUID_BUFLEN) !=
|
|
|
|
VIR_UUID_BUFLEN) {
|
|
|
|
VIR_ERROR("%s", "Unable to write information to local file.");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
close(fd);
|
2009-07-24 14:17:06 +00:00
|
|
|
return 0;
|
2009-11-05 16:18:07 +00:00
|
|
|
|
|
|
|
err:
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
int
|
|
|
|
phypUUIDTable_Init(virConnectPtr conn)
|
2009-07-24 14:17:06 +00:00
|
|
|
{
|
2009-11-05 16:18:07 +00:00
|
|
|
uuid_tablePtr uuid_table;
|
|
|
|
phyp_driverPtr phyp_driver;
|
2009-07-24 14:17:06 +00:00
|
|
|
int nids = 0;
|
|
|
|
int *ids = NULL;
|
|
|
|
unsigned int i = 0;
|
|
|
|
|
|
|
|
if ((nids = phypNumDomainsGeneric(conn, 2)) == 0)
|
2009-11-05 16:18:07 +00:00
|
|
|
goto err;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
if (VIR_ALLOC_N(ids, nids) < 0) {
|
2009-07-24 14:17:06 +00:00
|
|
|
virReportOOMError(conn);
|
2009-11-05 16:18:07 +00:00
|
|
|
goto err;
|
|
|
|
}
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if (phypListDomainsGeneric(conn, ids, nids, 1) == 0)
|
2009-11-05 16:18:07 +00:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
phyp_driver = conn->privateData;
|
|
|
|
uuid_table = phyp_driver->uuid_table;
|
|
|
|
uuid_table->nlpars = nids;
|
|
|
|
|
|
|
|
/* try to get the table from server */
|
|
|
|
if (phypUUIDTable_Pull(conn) == -1) {
|
|
|
|
/* file not found in the server, creating a new one */
|
|
|
|
if (VIR_ALLOC_N(uuid_table->lpars, uuid_table->nlpars) >= 0) {
|
|
|
|
for (i = 0; i < uuid_table->nlpars; i++) {
|
|
|
|
if (VIR_ALLOC(uuid_table->lpars[i]) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
uuid_table->lpars[i]->id = ids[i];
|
|
|
|
|
|
|
|
if (virUUIDGenerate(uuid_table->lpars[i]->uuid) < 0)
|
|
|
|
VIR_WARN("%s %d", "Unable to generate UUID for domain",
|
|
|
|
ids[i]);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (phypUUIDTable_WriteFile(conn) == -1)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (phypUUIDTable_Push(conn) == -1)
|
|
|
|
goto err;
|
|
|
|
} else {
|
|
|
|
if (phypUUIDTable_ReadFile(conn) == -1)
|
|
|
|
goto err;
|
2009-07-24 14:17:06 +00:00
|
|
|
goto exit;
|
2009-11-05 16:18:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
exit:
|
|
|
|
VIR_FREE(ids);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
VIR_FREE(ids);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-11-05 23:19:16 +00:00
|
|
|
void
|
|
|
|
phypUUIDTable_Free(uuid_tablePtr uuid_table)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (uuid_table == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < uuid_table->nlpars; i++)
|
|
|
|
VIR_FREE(uuid_table->lpars[i]);
|
|
|
|
|
|
|
|
VIR_FREE(uuid_table->lpars);
|
|
|
|
VIR_FREE(uuid_table);
|
|
|
|
}
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
int
|
|
|
|
phypUUIDTable_Push(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
ConnectionData *connection_data = conn->networkPrivateData;
|
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
|
|
|
LIBSSH2_CHANNEL *channel = NULL;
|
|
|
|
struct stat local_fileinfo;
|
|
|
|
char buffer[1024];
|
|
|
|
int rc = 0;
|
|
|
|
FILE *fd;
|
|
|
|
size_t nread, sent;
|
|
|
|
char *ptr;
|
|
|
|
char remote_file[] = "/home/hscroot/libvirt_uuid_table";
|
|
|
|
char local_file[] = "./uuid_table";
|
|
|
|
|
|
|
|
if (stat(local_file, &local_fileinfo) == -1) {
|
|
|
|
VIR_WARN0("Unable to stat local file.");
|
|
|
|
goto err;
|
|
|
|
}
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
if (!(fd = fopen(local_file, "rb"))) {
|
|
|
|
VIR_WARN0("Unable to open local file.");
|
|
|
|
goto err;
|
|
|
|
}
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
do {
|
|
|
|
channel =
|
|
|
|
libssh2_scp_send(session, remote_file,
|
|
|
|
0x1FF & local_fileinfo.st_mode,
|
|
|
|
(unsigned long) local_fileinfo.st_size);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
if ((!channel) && (libssh2_session_last_errno(session) !=
|
|
|
|
LIBSSH2_ERROR_EAGAIN))
|
|
|
|
goto err;
|
|
|
|
} while (!channel);
|
|
|
|
|
|
|
|
do {
|
|
|
|
nread = fread(buffer, 1, sizeof(buffer), fd);
|
|
|
|
if (nread <= 0) {
|
|
|
|
/* end of file */
|
|
|
|
break;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
2009-11-05 16:18:07 +00:00
|
|
|
ptr = buffer;
|
|
|
|
sent = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
/* write the same data over and over, until error or completion */
|
|
|
|
rc = libssh2_channel_write(channel, ptr, nread);
|
|
|
|
if (LIBSSH2_ERROR_EAGAIN == rc) { /* must loop around */
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
/* rc indicates how many bytes were written this time */
|
|
|
|
sent += rc;
|
|
|
|
}
|
|
|
|
} while (rc > 0 && sent < nread);
|
|
|
|
ptr += sent;
|
|
|
|
nread -= sent;
|
|
|
|
} while (1);
|
|
|
|
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
exit:
|
|
|
|
if (channel) {
|
|
|
|
libssh2_channel_send_eof(channel);
|
|
|
|
libssh2_channel_wait_eof(channel);
|
|
|
|
libssh2_channel_wait_closed(channel);
|
|
|
|
libssh2_channel_free(channel);
|
|
|
|
channel = NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
2009-11-05 16:18:07 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
if (channel) {
|
|
|
|
libssh2_channel_send_eof(channel);
|
|
|
|
libssh2_channel_wait_eof(channel);
|
|
|
|
libssh2_channel_wait_closed(channel);
|
|
|
|
libssh2_channel_free(channel);
|
|
|
|
channel = NULL;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
phypUUIDTable_Pull(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
ConnectionData *connection_data = conn->networkPrivateData;
|
|
|
|
LIBSSH2_SESSION *session = connection_data->session;
|
|
|
|
LIBSSH2_CHANNEL *channel = NULL;
|
|
|
|
struct stat fileinfo;
|
|
|
|
char buffer[1024];
|
|
|
|
int rc = 0;
|
|
|
|
int fd;
|
|
|
|
int got = 0;
|
|
|
|
int amount = 0;
|
|
|
|
int total = 0;
|
|
|
|
int sock = 0;
|
|
|
|
char remote_file[] = "/home/hscroot/libvirt_uuid_table";
|
|
|
|
char local_file[] = "./uuid_table";
|
|
|
|
|
|
|
|
/* Trying to stat the remote file. */
|
|
|
|
do {
|
|
|
|
channel = libssh2_scp_recv(session, remote_file, &fileinfo);
|
|
|
|
|
|
|
|
if (!channel) {
|
|
|
|
if (libssh2_session_last_errno(session) !=
|
|
|
|
LIBSSH2_ERROR_EAGAIN) {
|
|
|
|
goto err;;
|
|
|
|
} else {
|
|
|
|
waitsocket(sock, session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (!channel);
|
|
|
|
|
|
|
|
/* Creating a new data base based on remote file */
|
|
|
|
if ((fd = creat(local_file, 0755)) == -1)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* Request a file via SCP */
|
|
|
|
while (got < fileinfo.st_size) {
|
|
|
|
do {
|
|
|
|
amount = sizeof(buffer);
|
|
|
|
|
|
|
|
if ((fileinfo.st_size - got) < amount) {
|
|
|
|
amount = fileinfo.st_size - got;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = libssh2_channel_read(channel, buffer, amount);
|
|
|
|
if (rc > 0) {
|
|
|
|
if (safewrite(fd, buffer, rc) != rc)
|
|
|
|
VIR_WARN("%s",
|
|
|
|
"Unable to write information to local file.");
|
|
|
|
|
|
|
|
got += rc;
|
|
|
|
total += rc;
|
|
|
|
}
|
|
|
|
} while (rc > 0);
|
|
|
|
|
|
|
|
if ((rc == LIBSSH2_ERROR_EAGAIN)
|
|
|
|
&& (got < fileinfo.st_size)) {
|
|
|
|
/* this is due to blocking that would occur otherwise
|
|
|
|
* so we loop on this condition */
|
|
|
|
|
|
|
|
waitsocket(sock, session); /* now we wait */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
close(fd);
|
|
|
|
goto exit;
|
|
|
|
|
2009-07-24 14:17:06 +00:00
|
|
|
exit:
|
2009-11-05 16:18:07 +00:00
|
|
|
if (channel) {
|
|
|
|
libssh2_channel_send_eof(channel);
|
|
|
|
libssh2_channel_wait_eof(channel);
|
|
|
|
libssh2_channel_wait_closed(channel);
|
|
|
|
libssh2_channel_free(channel);
|
|
|
|
channel = NULL;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
if (channel) {
|
|
|
|
libssh2_channel_send_eof(channel);
|
|
|
|
libssh2_channel_wait_eof(channel);
|
|
|
|
libssh2_channel_wait_closed(channel);
|
|
|
|
libssh2_channel_free(channel);
|
|
|
|
channel = NULL;
|
|
|
|
}
|
|
|
|
return -1;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
int
|
2009-08-03 11:53:26 +00:00
|
|
|
escape_specialcharacters(char *src, char *dst, size_t dstlen)
|
2009-07-24 14:17:06 +00:00
|
|
|
{
|
|
|
|
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]) {
|
2009-11-05 16:18:07 +00:00
|
|
|
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':
|
2009-07-24 14:17:06 +00:00
|
|
|
case '\t':
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
temp_buffer[j] = src[i];
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
temp_buffer[j] = '\0';
|
|
|
|
|
2009-08-03 12:37:44 +00:00
|
|
|
if (virStrcpy(dst, temp_buffer, dstlen) == NULL)
|
2009-07-24 14:17:06 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2009-09-04 10:08:47 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
waitsocket(int socket_fd, LIBSSH2_SESSION * session)
|
|
|
|
{
|
|
|
|
struct timeval timeout;
|
|
|
|
int rc;
|
|
|
|
fd_set fd;
|
|
|
|
fd_set *writefd = NULL;
|
|
|
|
fd_set *readfd = NULL;
|
|
|
|
int dir;
|
|
|
|
|
|
|
|
timeout.tv_sec = 10;
|
|
|
|
timeout.tv_usec = 0;
|
|
|
|
|
|
|
|
FD_ZERO(&fd);
|
|
|
|
|
|
|
|
FD_SET(socket_fd, &fd);
|
|
|
|
|
|
|
|
/* now make sure we wait in the correct direction */
|
|
|
|
dir = libssh2_session_block_directions(session);
|
|
|
|
|
|
|
|
if (dir & LIBSSH2_SESSION_BLOCK_INBOUND)
|
|
|
|
readfd = &fd;
|
|
|
|
|
|
|
|
if (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
|
|
|
|
writefd = &fd;
|
|
|
|
|
|
|
|
rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
2009-11-05 16:18:07 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
phypRegister(void)
|
|
|
|
{
|
|
|
|
virRegisterDriver(&phypDriver);
|
|
|
|
return 0;
|
|
|
|
}
|