2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
/*
|
2010-03-01 23:38:28 +00:00
|
|
|
* Copyright (C) 2010 Red Hat, Inc.
|
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"
|
2010-03-14 20:46:32 +00:00
|
|
|
#include "authhelper.h"
|
2009-07-24 14:17:06 +00:00
|
|
|
#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
|
|
|
|
|
2010-04-03 00:49:39 +00:00
|
|
|
#define PHYP_ERROR(code, ...) \
|
|
|
|
virReportErrorHelper(NULL, VIR_FROM_PHYP, code, __FILE__, __FUNCTION__, \
|
2010-03-01 23:38:28 +00:00
|
|
|
__LINE__, __VA_ARGS__)
|
2009-11-06 02:19:22 +00:00
|
|
|
|
2009-07-24 14:17:06 +00:00
|
|
|
/*
|
|
|
|
* 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) {
|
2010-04-03 00:49:39 +00:00
|
|
|
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
|
2009-12-05 00:10:01 +00:00
|
|
|
"%s", _("Missing server name in phyp:// URI"));
|
2009-11-05 16:18:07 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-07-24 14:17:06 +00:00
|
|
|
if (conn->uri->path == NULL) {
|
2010-04-03 00:49:39 +00:00
|
|
|
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
|
2009-12-05 00:10:01 +00:00
|
|
|
"%s", _("Missing managed system name in phyp:// URI"));
|
2009-07-24 14:17:06 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
if (VIR_ALLOC(phyp_driver) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(uuid_table) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-08-20 10:32:19 +00:00
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(connection_data) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-08-20 10:32:19 +00:00
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
2009-08-20 11:59:07 +00:00
|
|
|
len = strlen(conn->uri->path) + 1;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(string, len) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-08-20 10:32:19 +00:00
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
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) {
|
2010-04-03 00:49:39 +00:00
|
|
|
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
|
2009-12-05 00:10:01 +00:00
|
|
|
"%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) {
|
2010-04-03 00:49:39 +00:00
|
|
|
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
|
2009-12-05 00:10:01 +00:00
|
|
|
"%s", _("Error while opening SSH session."));
|
2009-08-20 10:32:19 +00:00
|
|
|
goto failure;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
2010-03-14 20:46:32 +00:00
|
|
|
|
2009-07-24 14:17:06 +00:00
|
|
|
connection_data->session = session;
|
|
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
phypIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
/* Phyp uses an SSH tunnel, so is always encrypted */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
phypIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
/* Phyp uses an SSH tunnel, so is always secure */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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;
|
2010-03-14 20:46:32 +00:00
|
|
|
char *username = NULL;
|
|
|
|
char *password = NULL;
|
2009-09-04 10:08:47 +00:00
|
|
|
int sock;
|
|
|
|
int rc;
|
|
|
|
struct addrinfo *ai = NULL, *cur;
|
|
|
|
struct addrinfo hints;
|
|
|
|
int ret;
|
2009-11-10 12:15:34 +00:00
|
|
|
char *pubkey = NULL;
|
|
|
|
char *pvtkey = NULL;
|
2010-02-04 22:41:52 +00:00
|
|
|
char *userhome = virGetUserDirectory(geteuid());
|
2009-11-10 12:15:34 +00:00
|
|
|
struct stat pvt_stat, pub_stat;
|
|
|
|
|
|
|
|
if (userhome == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (virAsprintf(&pubkey, "%s/.ssh/id_rsa.pub", userhome) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-10 12:15:34 +00:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virAsprintf(&pvtkey, "%s/.ssh/id_rsa", userhome) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-10 12:15:34 +00:00
|
|
|
goto err;
|
|
|
|
}
|
2009-09-04 10:08:47 +00:00
|
|
|
|
2010-03-14 20:46:32 +00:00
|
|
|
if (conn->uri->user != NULL) {
|
|
|
|
username = strdup(conn->uri->user);
|
|
|
|
|
|
|
|
if (username == NULL) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (auth == NULL || auth->cb == NULL) {
|
2010-04-03 00:49:39 +00:00
|
|
|
PHYP_ERROR(VIR_ERR_AUTH_FAILED,
|
2010-03-14 20:46:32 +00:00
|
|
|
"%s", _("No authentication callback provided."));
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
username = virRequestUsername(auth, NULL, conn->uri->server);
|
|
|
|
|
|
|
|
if (username == NULL) {
|
2010-04-03 00:49:39 +00:00
|
|
|
PHYP_ERROR(VIR_ERR_AUTH_FAILED, "%s", _("Username request failed"));
|
2010-03-14 20:46:32 +00:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-06 01:28:05 +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) {
|
2010-04-03 00:49:39 +00:00
|
|
|
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
|
2009-11-06 02:19:22 +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
|
|
|
}
|
|
|
|
|
2010-04-03 00:49:39 +00:00
|
|
|
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
|
2009-11-06 02:19:22 +00:00
|
|
|
_("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) {
|
2010-04-03 00:49:39 +00:00
|
|
|
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
|
2009-12-05 00:10:01 +00:00
|
|
|
"%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 */
|
2009-11-11 01:45:51 +00:00
|
|
|
if (stat(pvtkey, &pvt_stat) || stat(pubkey, &pub_stat)) {
|
|
|
|
rc = LIBSSH2_ERROR_SOCKET_NONE;
|
2009-11-10 12:15:34 +00:00
|
|
|
goto keyboard_interactive;
|
2009-11-11 01:45:51 +00:00
|
|
|
}
|
2009-11-10 12:15:34 +00:00
|
|
|
|
2009-09-04 10:08:47 +00:00
|
|
|
while ((rc =
|
|
|
|
libssh2_userauth_publickey_fromfile(session, username,
|
2009-11-10 12:15:34 +00:00
|
|
|
pubkey,
|
|
|
|
pvtkey,
|
|
|
|
NULL)) ==
|
2009-09-04 10:08:47 +00:00
|
|
|
LIBSSH2_ERROR_EAGAIN) ;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-11 01:45:51 +00:00
|
|
|
keyboard_interactive:
|
2009-11-10 12:15:34 +00:00
|
|
|
if (rc == LIBSSH2_ERROR_SOCKET_NONE
|
|
|
|
|| rc == LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED
|
|
|
|
|| rc == LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED) {
|
2010-03-14 20:46:32 +00:00
|
|
|
if (auth == NULL || auth->cb == NULL) {
|
2010-04-03 00:49:39 +00:00
|
|
|
PHYP_ERROR(VIR_ERR_AUTH_FAILED,
|
2009-12-05 00:10:01 +00:00
|
|
|
"%s", _("No authentication callback provided."));
|
2009-11-05 23:19:16 +00:00
|
|
|
goto disconnect;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
2010-03-14 20:46:32 +00:00
|
|
|
password = virRequestPassword(auth, username, conn->uri->server);
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2010-03-14 20:46:32 +00:00
|
|
|
if (password == NULL) {
|
2010-04-03 00:49:39 +00:00
|
|
|
PHYP_ERROR(VIR_ERR_AUTH_FAILED, "%s", _("Password request failed"));
|
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) {
|
2010-04-03 00:49:39 +00:00
|
|
|
PHYP_ERROR(VIR_ERR_AUTH_FAILED,
|
2009-12-05 00:10:01 +00:00
|
|
|
"%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-11-10 12:15:34 +00:00
|
|
|
|
|
|
|
} else if (rc == LIBSSH2_ERROR_NONE) {
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
} else if (rc == LIBSSH2_ERROR_ALLOC || rc == LIBSSH2_ERROR_SOCKET_SEND
|
|
|
|
|| rc == LIBSSH2_ERROR_SOCKET_TIMEOUT) {
|
|
|
|
goto err;
|
2009-09-04 10:08:47 +00:00
|
|
|
}
|
2009-11-10 12:15:34 +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-10 12:15:34 +00:00
|
|
|
VIR_FREE(userhome);
|
|
|
|
VIR_FREE(pubkey);
|
|
|
|
VIR_FREE(pvtkey);
|
2010-03-14 20:46:32 +00:00
|
|
|
VIR_FREE(username);
|
2009-11-05 23:19:16 +00:00
|
|
|
VIR_FREE(password);
|
2009-07-24 14:17:06 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
exit:
|
2009-11-10 12:15:34 +00:00
|
|
|
VIR_FREE(userhome);
|
|
|
|
VIR_FREE(pubkey);
|
|
|
|
VIR_FREE(pvtkey);
|
2010-03-14 20:46:32 +00:00
|
|
|
VIR_FREE(username);
|
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;
|
2009-12-09 23:00:50 +00:00
|
|
|
virBufferFreeAndReset(&tex_ret);
|
2009-07-24 14:17:06 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
exit:
|
|
|
|
if (virBufferError(&tex_ret)) {
|
2009-12-09 23:00:50 +00:00
|
|
|
virBufferFreeAndReset(&tex_ret);
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-07-24 14:17:06 +00:00
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-07-24 14:17:06 +00:00
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-07-24 14:17:06 +00:00
|
|
|
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-06 01:33:20 +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
|
|
|
char *char_ptr = strchr(ret, '\n');
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if (char_ptr)
|
|
|
|
*char_ptr = '\0';
|
|
|
|
|
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-07-24 14:17:06 +00:00
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-07-24 14:17:06 +00:00
|
|
|
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-06 01:33:20 +00:00
|
|
|
if (exit_status < 0 || ret == NULL)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
|
2009-11-06 01:33:20 +00:00
|
|
|
char_ptr = strchr(ret, '\n');
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-06 01:33:20 +00:00
|
|
|
if (char_ptr)
|
|
|
|
*char_ptr = '\0';
|
2009-07-24 14:17:06 +00:00
|
|
|
|
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-11-06 01:33:20 +00:00
|
|
|
char *char_ptr;
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
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-11-06 01:33:20 +00:00
|
|
|
if (exit_status < 0 || ret == NULL)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
|
2009-11-06 01:33:20 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-07-24 14:17:06 +00:00
|
|
|
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-06 01:33:20 +00:00
|
|
|
if (exit_status < 0 || ret == NULL)
|
2009-07-24 14:17:06 +00:00
|
|
|
goto err;
|
|
|
|
|
2009-11-06 01:33:20 +00:00
|
|
|
char_ptr = strchr(ret, '\n');
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-06 01:33:20 +00:00
|
|
|
if (char_ptr)
|
|
|
|
*char_ptr = '\0';
|
2009-07-24 14:17:06 +00:00
|
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-07-24 14:17:06 +00:00
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 23:19:16 +00:00
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-07-24 14:17:06 +00:00
|
|
|
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-11-06 01:15:19 +00:00
|
|
|
return -1;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-07-24 14:17:06 +00:00
|
|
|
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-11-06 00:53:24 +00:00
|
|
|
if (ret[i] == '\0')
|
|
|
|
break;
|
|
|
|
else if (ret[i] == '\n') {
|
|
|
|
if (virStrToLong_i(id_c, &char_ptr, 10, &ids[got]) == -1) {
|
|
|
|
VIR_ERROR("Cannot parse number from '%s'", id_c);
|
|
|
|
goto err;
|
|
|
|
}
|
2009-07-24 14:17:06 +00:00
|
|
|
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-11-06 01:15:19 +00:00
|
|
|
return -1;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-07-24 14:17:06 +00:00
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
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;
|
2009-11-06 00:53:24 +00:00
|
|
|
} else
|
|
|
|
break;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2009-11-06 01:15:19 +00:00
|
|
|
return -1;
|
2009-07-24 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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-11-06 02:07:26 +00:00
|
|
|
unsigned char lpar_uuid[VIR_UUID_BUFLEN];
|
2009-07-24 14:17:06 +00:00
|
|
|
|
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-11-06 02:07:26 +00:00
|
|
|
return NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
if (phypGetLparUUID(lpar_uuid, lpar_id, conn) == -1)
|
2009-11-06 02:07:26 +00:00
|
|
|
return NULL;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
|
|
|
dom = virGetDomain(conn, lpar_name, lpar_uuid);
|
|
|
|
|
|
|
|
if (dom)
|
|
|
|
dom->id = lpar_id;
|
|
|
|
|
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2009-11-06 02:07:26 +00:00
|
|
|
unsigned char lpar_uuid[VIR_UUID_BUFLEN];
|
2009-07-24 14:17:06 +00:00
|
|
|
|
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);
|
|
|
|
return dom;
|
|
|
|
|
|
|
|
err:
|
|
|
|
VIR_FREE(lpar_name);
|
|
|
|
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-11-06 02:07:26 +00:00
|
|
|
virDomainDef def;
|
2009-11-05 16:18:07 +00:00
|
|
|
char *managed_system = phyp_driver->managed_system;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-06 02:07:26 +00:00
|
|
|
memset(&def, 0, sizeof(virDomainDef));
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-06 02:07:26 +00:00
|
|
|
def.virtType = VIR_DOMAIN_VIRT_PHYP;
|
|
|
|
def.id = dom->id;
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-06 02:07:26 +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;
|
|
|
|
}
|
|
|
|
|
2009-11-06 02:07:26 +00:00
|
|
|
if (phypGetLparUUID(def.uuid, dom->id, dom->conn) == -1) {
|
2009-07-24 14:17:06 +00:00
|
|
|
VIR_ERROR("%s", "Unable to generate random uuid.");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2009-11-06 02:07:26 +00:00
|
|
|
if ((def.maxmem =
|
2009-07-24 14:17:06 +00:00
|
|
|
phypGetLparMem(dom->conn, managed_system, dom->id, 0)) == 0) {
|
|
|
|
VIR_ERROR("%s", "Unable to determine domain's max memory.");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2009-11-06 02:07:26 +00:00
|
|
|
if ((def.memory =
|
2009-07-24 14:17:06 +00:00
|
|
|
phypGetLparMem(dom->conn, managed_system, dom->id, 1)) == 0) {
|
|
|
|
VIR_ERROR("%s", "Unable to determine domain's memory.");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2009-11-06 02:07:26 +00:00
|
|
|
if ((def.vcpus =
|
2009-07-24 14:17:06 +00:00
|
|
|
phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0) {
|
|
|
|
VIR_ERROR("%s", "Unable to determine domain's CPU.");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
return virDomainDefFormat(&def, flags);
|
2009-11-05 16:18:07 +00:00
|
|
|
|
|
|
|
err:
|
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-07-24 14:17:06 +00:00
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-07-24 14:17:06 +00:00
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
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;
|
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
if (!(def = virDomainDefParseString(phyp_driver->caps, xml,
|
2009-11-05 16:18:07 +00:00
|
|
|
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)
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
|
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
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 */
|
2009-11-12 15:53:26 +00:00
|
|
|
NULL, /* libvirtVersion (impl. in libvirt.c) */
|
2009-11-05 16:18:07 +00:00
|
|
|
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 */
|
2010-01-14 01:44:26 +00:00
|
|
|
NULL, /* domainAttachDeviceFlags */
|
2009-07-24 14:17:06 +00:00
|
|
|
NULL, /* domainDetachDevice */
|
2010-01-14 01:44:26 +00:00
|
|
|
NULL, /* domainDetachDeviceFlags */
|
Introduce a new virDomainUpdateDeviceFlags public API
The current virDomainAttachDevice API can be (ab)used to change
the media of an existing CDROM/Floppy device. Going forward there
will be more devices that can be configured on the fly and overloading
virDomainAttachDevice for this is not too pleasant. This patch adds
a new virDomainUpdateDeviceFlags() explicitly just for modifying
existing devices.
* include/libvirt/libvirt.h.in: Add virDomainUpdateDeviceFlags
* src/driver.h: Internal API for virDomainUpdateDeviceFlags
* src/libvirt.c, src/libvirt_public.syms: Glue public API to
driver API
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c, src/qemu/qemu_driver.c,
src/remote/remote_driver.c, src/test/test_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c, src/xenapi/xenapi_driver.c: Add
stubs for new driver entry point
2010-03-22 12:23:41 +00:00
|
|
|
NULL, /* domainUpdateDeviceFlags */
|
2009-07-24 14:17:06 +00:00
|
|
|
NULL, /* domainGetAutostart */
|
|
|
|
NULL, /* domainSetAutostart */
|
|
|
|
NULL, /* domainGetSchedulerType */
|
|
|
|
NULL, /* domainGetSchedulerParameters */
|
|
|
|
NULL, /* domainSetSchedulerParameters */
|
|
|
|
NULL, /* domainMigratePrepare */
|
|
|
|
NULL, /* domainMigratePerform */
|
|
|
|
NULL, /* domainMigrateFinish */
|
|
|
|
NULL, /* domainBlockStats */
|
|
|
|
NULL, /* domainInterfaceStats */
|
2009-12-20 12:28:42 +00:00
|
|
|
NULL, /* domainMemoryStats */
|
2009-07-24 14:17:06 +00:00
|
|
|
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 */
|
2010-03-23 18:00:38 +00:00
|
|
|
phypIsEncrypted, /* isEncrypted */
|
|
|
|
phypIsSecure, /* isSecure */
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
NULL, /* domainIsActive */
|
|
|
|
NULL, /* domainIsPersistent */
|
2009-12-18 13:59:39 +00:00
|
|
|
NULL, /* cpuCompare */
|
2010-02-02 11:34:01 +00:00
|
|
|
NULL, /* cpuBaseline */
|
Stub out internal driver entry points for job processing
The internal glue layer for the new pubic API
* src/driver.h: Define internal driver API contract
* src/libvirt.c, src/libvirt_public.syms: Wire up public
API to internal driver API
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c: Stub new entry point
2010-02-03 11:32:24 +00:00
|
|
|
NULL, /* domainGetJobInfo */
|
Wire up internal entry points for virDomainAbortJob API
This provides the internal glue for the driver API
* src/driver.h: Internal API contract
* src/libvirt.c, src/libvirt_public.syms: Connect public API
to driver API
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/test/test_driver.c src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c: Stub out entry points
2010-02-04 16:16:35 +00:00
|
|
|
NULL, /* domainAbortJob */
|
2010-03-12 13:55:08 +00:00
|
|
|
NULL, /* domainMigrateSetMaxDowntime */
|
Introduce a new public API for domain events
The current API for domain events has a number of problems
- Only allows for domain lifecycle change events
- Does not allow the same callback to be registered multiple times
- Does not allow filtering of events to a specific domain
This introduces a new more general purpose domain events API
typedef enum {
VIR_DOMAIN_EVENT_ID_LIFECYCLE = 0, /* virConnectDomainEventCallback */
...more events later..
}
int virConnectDomainEventRegisterAny(virConnectPtr conn,
virDomainPtr dom, /* Optional, to filter */
int eventID,
virConnectDomainEventGenericCallback cb,
void *opaque,
virFreeCallback freecb);
int virConnectDomainEventDeregisterAny(virConnectPtr conn,
int callbackID);
Since different event types can received different data in the callback,
the API is defined with a generic callback. Specific events will each
have a custom signature for their callback. Thus when registering an
event it is neccessary to cast the callback to the generic signature
eg
int myDomainEventCallback(virConnectPtr conn,
virDomainPtr dom,
int event,
int detail,
void *opaque)
{
...
}
virConnectDomainEventRegisterAny(conn, NULL,
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
VIR_DOMAIN_EVENT_CALLBACK(myDomainEventCallback)
NULL, NULL);
The VIR_DOMAIN_EVENT_CALLBACK() macro simply does a "bad" cast
to the generic signature
* include/libvirt/libvirt.h.in: Define new APIs for registering
domain events
* src/driver.h: Internal driver entry points for new events APIs
* src/libvirt.c: Wire up public API to driver API for events APIs
* src/libvirt_public.syms: Export new APIs
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c,
src/xenapi/xenapi_driver.c: Stub out new API entries
2010-03-18 13:01:48 +00:00
|
|
|
NULL, /* domainEventRegisterAny */
|
|
|
|
NULL, /* domainEventDeregisterAny */
|
2010-04-01 08:46:28 +00:00
|
|
|
NULL, /* domainManagedSave */
|
|
|
|
NULL, /* domainHasManagedSaveImage */
|
|
|
|
NULL, /* domainManagedSaveRemove */
|
2010-03-31 20:33:13 +00:00
|
|
|
NULL, /* domainSnapshotCreateXML */
|
|
|
|
NULL, /* domainSnapshotDumpXML */
|
|
|
|
NULL, /* domainSnapshotNum */
|
|
|
|
NULL, /* domainSnapshotListNames */
|
|
|
|
NULL, /* domainSnapshotLookupByName */
|
|
|
|
NULL, /* domainHasCurrentSnapshot */
|
|
|
|
NULL, /* domainSnapshotCurrent */
|
|
|
|
NULL, /* domainRevertToSnapshot */
|
|
|
|
NULL, /* domainSnapshotDelete */
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
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;
|
2009-11-06 01:28:05 +00:00
|
|
|
memset(uuid_table->lpars[i]->uuid, 0, VIR_UUID_BUFLEN);
|
2009-11-05 16:18:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (phypUUIDTable_WriteFile(conn) == -1)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (phypUUIDTable_Push(conn) == -1)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(uuid_table->lpars[i]) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
uuid_table->lpars[i]->id = id;
|
2009-11-06 01:28:05 +00:00
|
|
|
memmove(uuid_table->lpars[i]->uuid, uuid, VIR_UUID_BUFLEN);
|
2009-11-05 16:18:07 +00:00
|
|
|
|
|
|
|
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;
|
2009-11-06 01:59:35 +00:00
|
|
|
int id;
|
2009-11-05 16:18:07 +00:00
|
|
|
|
|
|
|
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++) {
|
|
|
|
|
2009-11-06 01:59:35 +00:00
|
|
|
rc = read(fd, &id, sizeof(int));
|
2009-11-05 16:18:07 +00:00
|
|
|
if (rc == sizeof(int)) {
|
2009-11-05 23:19:16 +00:00
|
|
|
if (VIR_ALLOC(uuid_table->lpars[i]) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 23:19:16 +00:00
|
|
|
goto err;
|
|
|
|
}
|
2009-11-06 01:59:35 +00:00
|
|
|
uuid_table->lpars[i]->id = id;
|
2009-11-05 16:18:07 +00:00
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
}
|
2009-11-08 21:08:54 +00:00
|
|
|
} else
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
|
|
|
|
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,
|
2009-11-06 01:59:35 +00:00
|
|
|
sizeof(uuid_table->lpars[i]->id)) !=
|
2009-11-05 16:18:07 +00:00
|
|
|
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;
|
|
|
|
|
2009-11-06 01:15:19 +00:00
|
|
|
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-06 01:15:19 +00:00
|
|
|
/* exit early if there are no domains */
|
|
|
|
if (nids == 0)
|
|
|
|
return 0;
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
if (VIR_ALLOC_N(ids, nids) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
goto err;
|
|
|
|
}
|
2009-07-24 14:17:06 +00:00
|
|
|
|
2009-11-06 01:15:19 +00:00
|
|
|
if ((nids = phypListDomainsGeneric(conn, ids, nids, 1)) < 0)
|
2009-11-05 16:18:07 +00:00
|
|
|
goto err;
|
|
|
|
|
2009-11-06 01:15:19 +00:00
|
|
|
/* exit early if there are no domains */
|
|
|
|
/* FIXME: phypNumDomainsGeneric() returned > 0 but phypListDomainsGeneric()
|
|
|
|
* returned 0. indicates this an error condition?
|
|
|
|
* an even stricter check would be to treat
|
|
|
|
*
|
|
|
|
* phypNumDomainsGeneric() != phypListDomainsGeneric()
|
|
|
|
*
|
|
|
|
* as an error */
|
|
|
|
if (nids == 0) {
|
|
|
|
VIR_FREE(ids);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-11-05 16:18:07 +00:00
|
|
|
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) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
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]);
|
|
|
|
}
|
2009-11-08 21:08:54 +00:00
|
|
|
} else {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-05 16:18:07 +00:00
|
|
|
goto err;
|
2009-11-08 21:08:54 +00:00
|
|
|
}
|
2009-11-05 16:18:07 +00:00
|
|
|
|
|
|
|
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) {
|
2009-11-06 01:59:35 +00:00
|
|
|
if (feof(fd)) {
|
|
|
|
/* end of file */
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
VIR_ERROR("Failed to read from '%s'", local_file);
|
|
|
|
goto err;
|
|
|
|
}
|
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;
|
2009-11-06 01:59:35 +00:00
|
|
|
} else if (rc > 0) {
|
2009-11-05 16:18:07 +00:00
|
|
|
/* rc indicates how many bytes were written this time */
|
|
|
|
sent += rc;
|
|
|
|
}
|
2010-03-01 20:26:59 +00:00
|
|
|
ptr += sent;
|
|
|
|
nread -= sent;
|
2009-11-05 16:18:07 +00:00
|
|
|
} while (rc > 0 && sent < nread);
|
|
|
|
} while (1);
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2009-11-11 10:53:16 +00:00
|
|
|
timeout.tv_sec = 0;
|
|
|
|
timeout.tv_usec = 1000;
|
2009-09-04 10:08:47 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|