提交 89144534 编写于 作者: E Eric Blake

phyp: reduce scope of driver functions

Several phyp functions are not namespace clean, and had no reason
to be exported since no one outside the phyp driver needed to use
them.  Rather than do lots of forward declarations, I was able
to topologically sort the file.  So, this patch looks huge, but
is really just a matter of marking things static and dealing with
the compiler fallout.

* src/phyp/phyp_driver.h (PHYP_DRIVER_H): Add include guard.
(phypCheckSPFreeSapce): Delete unused declaration.
(phypGetSystemType, phypGetVIOSPartitionID, phypCapsInit)
(phypBuildLpar, phypUUIDTable_WriteFile, phypUUIDTable_ReadFile)
(phypUUIDTable_AddLpar, phypUUIDTable_RemLpar, phypUUIDTable_Pull)
(phypUUIDTable_Push, phypUUIDTable_Init, phypUUIDTable_Free)
(escape_specialcharacters, waitsocket, phypGetLparUUID)
(phypGetLparMem, phypGetLparCPU, phypGetLparCPUGeneric)
(phypGetRemoteSlot, phypGetBackingDevice, phypDiskType)
(openSSHSession): Move declarations to phyp_driver.c and make static.
* src/phyp/phyp_driver.c: Rearrange file contents to provide
topological sorting of newly-static funtions (no semantic changes
other than reduced scope).
(phypGetBackingDevice, phypDiskType): Mark unused, for now.
上级 f9a92146
...@@ -66,477 +66,340 @@ ...@@ -66,477 +66,340 @@
virReportErrorHelper(NULL, VIR_FROM_PHYP, code, __FILE__, __FUNCTION__, \ virReportErrorHelper(NULL, VIR_FROM_PHYP, code, __FILE__, __FUNCTION__, \
__LINE__, __VA_ARGS__) __LINE__, __VA_ARGS__)
static unsigned const int HMC = 0;
static unsigned const int IVM = 127;
/* /*
* URI: phyp://user@[hmc|ivm]/managed_system * URI: phyp://user@[hmc|ivm]/managed_system
* */ * */
static virDrvOpenStatus static unsigned const int HMC = 0;
phypOpen(virConnectPtr conn, static unsigned const int IVM = 127;
virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
static int
waitsocket(int socket_fd, LIBSSH2_SESSION * session)
{ {
LIBSSH2_SESSION *session = NULL; struct timeval timeout;
ConnectionData *connection_data = NULL; int rc;
char *string = NULL; fd_set fd;
size_t len = 0; fd_set *writefd = NULL;
int internal_socket; fd_set *readfd = NULL;
uuid_tablePtr uuid_table = NULL; int dir;
phyp_driverPtr phyp_driver = NULL;
char *char_ptr;
char *managed_system = NULL;
if (!conn || !conn->uri) timeout.tv_sec = 0;
return VIR_DRV_OPEN_DECLINED; timeout.tv_usec = 1000;
if (conn->uri->scheme == NULL || STRNEQ(conn->uri->scheme, "phyp")) FD_ZERO(&fd);
return VIR_DRV_OPEN_DECLINED;
if (conn->uri->server == NULL) { FD_SET(socket_fd, &fd);
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
"%s", _("Missing server name in phyp:// URI"));
return VIR_DRV_OPEN_ERROR;
}
if (VIR_ALLOC(phyp_driver) < 0) { /* now make sure we wait in the correct direction */
virReportOOMError(); dir = libssh2_session_block_directions(session);
goto failure;
}
if (VIR_ALLOC(uuid_table) < 0) { if (dir & LIBSSH2_SESSION_BLOCK_INBOUND)
virReportOOMError(); readfd = &fd;
goto failure;
}
if (VIR_ALLOC(connection_data) < 0) { if (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
virReportOOMError(); writefd = &fd;
goto failure;
}
if (conn->uri->path) { rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);
len = strlen(conn->uri->path) + 1;
if (VIR_ALLOC_N(string, len) < 0) { return rc;
virReportOOMError(); }
goto failure;
}
/* need to shift one byte in order to remove the first "/" of URI component */ /* this function is the layer that manipulates the ssh channel itself
if (conn->uri->path[0] == '/') * and executes the commands on the remote machine */
managed_system = strdup(conn->uri->path + 1); static char *
else phypExec(LIBSSH2_SESSION * session, char *cmd, int *exit_status,
managed_system = strdup(conn->uri->path); virConnectPtr conn)
{
LIBSSH2_CHANNEL *channel;
ConnectionData *connection_data = conn->networkPrivateData;
virBuffer tex_ret = VIR_BUFFER_INITIALIZER;
char buffer[0x4000] = { 0 };
int exitcode;
int bytecount = 0;
int sock = connection_data->sock;
int rc = 0;
if (!managed_system) { /* Exec non-blocking on the remove host */
virReportOOMError(); while ((channel = libssh2_channel_open_session(session)) == NULL &&
goto failure; libssh2_session_last_error(session, NULL, NULL, 0) ==
LIBSSH2_ERROR_EAGAIN) {
waitsocket(sock, session);
} }
/* here we are handling only the first component of the path, if (channel == NULL) {
* so skipping the second: goto err;
* */
char_ptr = strchr(managed_system, '/');
if (char_ptr)
*char_ptr = '\0';
if (escape_specialcharacters(conn->uri->path, string, len) == -1) {
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
"%s",
_("Error parsing 'path'. Invalid characters."));
goto failure;
}
} }
if ((session = openSSHSession(conn, auth, &internal_socket)) == NULL) { while ((rc = libssh2_channel_exec(channel, cmd)) ==
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR, LIBSSH2_ERROR_EAGAIN) {
"%s", _("Error while opening SSH session.")); waitsocket(sock, session);
goto failure;
} }
connection_data->session = session; if (rc != 0) {
goto err;
uuid_table->nlpars = 0;
uuid_table->lpars = NULL;
if (conn->uri->path)
phyp_driver->managed_system = managed_system;
phyp_driver->uuid_table = uuid_table;
if ((phyp_driver->caps = phypCapsInit()) == NULL) {
virReportOOMError();
goto failure;
} }
conn->privateData = phyp_driver; for (;;) {
conn->networkPrivateData = connection_data; /* loop until we block */
do {
if ((phyp_driver->system_type = phypGetSystemType(conn)) == -1) rc = libssh2_channel_read(channel, buffer, sizeof(buffer));
goto failure; if (rc > 0) {
bytecount += rc;
if (phypUUIDTable_Init(conn) == -1) virBufferVSprintf(&tex_ret, "%s", buffer);
goto failure; }
}
while (rc > 0);
if (phyp_driver->system_type == HMC) { /* this is due to blocking that would occur otherwise so we loop on
if ((phyp_driver->vios_id = phypGetVIOSPartitionID(conn)) == -1) * this condition */
goto failure; if (rc == LIBSSH2_ERROR_EAGAIN) {
waitsocket(sock, session);
} else {
break;
}
} }
return VIR_DRV_OPEN_SUCCESS; exitcode = 127;
failure: while ((rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN) {
if (phyp_driver != NULL) { waitsocket(sock, session);
virCapabilitiesFree(phyp_driver->caps);
VIR_FREE(phyp_driver->managed_system);
VIR_FREE(phyp_driver);
} }
phypUUIDTable_Free(uuid_table); if (rc == 0) {
exitcode = libssh2_channel_get_exit_status(channel);
if (session != NULL) {
libssh2_session_disconnect(session, "Disconnecting...");
libssh2_session_free(session);
} }
VIR_FREE(connection_data); (*exit_status) = exitcode;
VIR_FREE(string); libssh2_channel_free(channel);
channel = NULL;
goto exit;
return VIR_DRV_OPEN_ERROR; err:
(*exit_status) = SSH_CMD_ERR;
virBufferFreeAndReset(&tex_ret);
return NULL;
exit:
if (virBufferError(&tex_ret)) {
virBufferFreeAndReset(&tex_ret);
virReportOOMError();
return NULL;
}
return virBufferContentAndReset(&tex_ret);
} }
static int static int
phypClose(virConnectPtr conn) phypGetSystemType(virConnectPtr conn)
{ {
ConnectionData *connection_data = conn->networkPrivateData; ConnectionData *connection_data = conn->networkPrivateData;
phyp_driverPtr phyp_driver = conn->privateData;
LIBSSH2_SESSION *session = connection_data->session; LIBSSH2_SESSION *session = connection_data->session;
char *cmd = NULL;
char *ret = NULL;
int exit_status = 0;
libssh2_session_disconnect(session, "Disconnecting..."); if (virAsprintf(&cmd, "lshmc -V") < 0) {
libssh2_session_free(session); virReportOOMError();
exit_status = -1;
}
ret = phypExec(session, cmd, &exit_status, conn);
virCapabilitiesFree(phyp_driver->caps); VIR_FREE(cmd);
phypUUIDTable_Free(phyp_driver->uuid_table); VIR_FREE(ret);
VIR_FREE(phyp_driver->managed_system); return exit_status;
VIR_FREE(phyp_driver);
VIR_FREE(connection_data);
return 0;
} }
static int static int
phypIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED) phypGetVIOSPartitionID(virConnectPtr conn)
{ {
/* Phyp uses an SSH tunnel, so is always encrypted */ ConnectionData *connection_data = conn->networkPrivateData;
return 1; phyp_driverPtr phyp_driver = conn->privateData;
} LIBSSH2_SESSION *session = connection_data->session;
int system_type = phyp_driver->system_type;
char *cmd = NULL;
char *ret = NULL;
int exit_status = 0;
int id = -1;
char *char_ptr;
char *managed_system = phyp_driver->managed_system;
virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferAddLit(&buf, "lssyscfg");
if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferAddLit(&buf, " -r lpar -F lpar_id,lpar_env|grep "
"vioserver|sed -s 's/,.*$//'");
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
return -1;
}
cmd = virBufferContentAndReset(&buf);
static int ret = phypExec(session, cmd, &exit_status, conn);
phypIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
{
/* Phyp uses an SSH tunnel, so is always secure */
return 1;
}
if (exit_status < 0 || ret == NULL)
goto err;
LIBSSH2_SESSION * if (virStrToLong_i(ret, &char_ptr, 10, &id) == -1)
openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
int *internal_socket)
{
LIBSSH2_SESSION *session;
const char *hostname = conn->uri->server;
char *username = NULL;
char *password = NULL;
int sock;
int rc;
struct addrinfo *ai = NULL, *cur;
struct addrinfo hints;
int ret;
char *pubkey = NULL;
char *pvtkey = NULL;
char *userhome = virGetUserDirectory(geteuid());
struct stat pvt_stat, pub_stat;
if (userhome == NULL)
goto err;
if (virAsprintf(&pubkey, "%s/.ssh/id_rsa.pub", userhome) < 0) {
virReportOOMError();
goto err;
}
if (virAsprintf(&pvtkey, "%s/.ssh/id_rsa", userhome) < 0) {
virReportOOMError();
goto err; goto err;
}
if (conn->uri->user != NULL) { VIR_FREE(cmd);
username = strdup(conn->uri->user); VIR_FREE(ret);
return id;
if (username == NULL) {
virReportOOMError();
goto err;
}
} else {
if (auth == NULL || auth->cb == NULL) {
PHYP_ERROR(VIR_ERR_AUTH_FAILED,
"%s", _("No authentication callback provided."));
goto err;
}
username = virRequestUsername(auth, NULL, conn->uri->server); err:
VIR_FREE(cmd);
VIR_FREE(ret);
return -1;
}
if (username == NULL) { static virCapsPtr
PHYP_ERROR(VIR_ERR_AUTH_FAILED, "%s", phypCapsInit(void)
_("Username request failed")); {
goto err; struct utsname utsname;
} virCapsPtr caps;
} virCapsGuestPtr guest;
memset(&hints, 0, sizeof(hints)); uname(&utsname);
hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
ret = getaddrinfo(hostname, "22", &hints, &ai); if ((caps = virCapabilitiesNew(utsname.machine, 0, 0)) == NULL)
if (ret != 0) { goto no_memory;
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Error while getting %s address info"), hostname);
goto err;
}
cur = ai; /* Some machines have problematic NUMA toplogy causing
while (cur != NULL) { * unexpected failures. We don't want to break the QEMU
sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); * driver in this scenario, so log errors & carry on
if (sock >= 0) { */
if (connect(sock, cur->ai_addr, cur->ai_addrlen) == 0) { if (nodeCapsInitNUMA(caps) < 0) {
goto connected; virCapabilitiesFreeNUMAInfo(caps);
} VIR_WARN0
close(sock); ("Failed to query host NUMA topology, disabling NUMA capabilities");
}
cur = cur->ai_next;
} }
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR, /* XXX shouldn't 'borrow' KVM's prefix */
_("Failed to connect to %s"), hostname); virCapabilitiesSetMacPrefix(caps, (unsigned char[]) {
freeaddrinfo(ai); 0x52, 0x54, 0x00});
goto err;
connected:
(*internal_socket) = sock;
/* Create a session instance */ if ((guest = virCapabilitiesAddGuest(caps,
session = libssh2_session_init(); "linux",
if (!session) utsname.machine,
goto err; sizeof(int) == 4 ? 32 : 8,
NULL, NULL, 0, NULL)) == NULL)
goto no_memory;
/* tell libssh2 we want it all done non-blocking */ if (virCapabilitiesAddGuestDomain(guest,
libssh2_session_set_blocking(session, 0); "phyp", NULL, NULL, 0, NULL) == NULL)
goto no_memory;
while ((rc = libssh2_session_startup(session, sock)) == return caps;
LIBSSH2_ERROR_EAGAIN) ;
if (rc) {
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
"%s", _("Failure establishing SSH session."));
goto disconnect;
}
/* Trying authentication by pubkey */ no_memory:
if (stat(pvtkey, &pvt_stat) || stat(pubkey, &pub_stat)) { virCapabilitiesFree(caps);
rc = LIBSSH2_ERROR_SOCKET_NONE; return NULL;
goto keyboard_interactive; }
}
while ((rc = /* This is a generic function that won't be used directly by
libssh2_userauth_publickey_fromfile(session, username, * libvirt api. The function returns the number of domains
pubkey, * in different states: Running, Not Activated and all:
pvtkey, *
NULL)) == * type: 0 - Running
LIBSSH2_ERROR_EAGAIN) ; * 1 - Not Activated
* * - All
* */
static int
phypNumDomainsGeneric(virConnectPtr conn, unsigned int type)
{
ConnectionData *connection_data = conn->networkPrivateData;
phyp_driverPtr phyp_driver = conn->privateData;
LIBSSH2_SESSION *session = connection_data->session;
int system_type = phyp_driver->system_type;
int exit_status = 0;
int ndom = 0;
char *char_ptr;
char *cmd = NULL;
char *ret = NULL;
char *managed_system = phyp_driver->managed_system;
const char *state;
virBuffer buf = VIR_BUFFER_INITIALIZER;
keyboard_interactive: if (type == 0)
if (rc == LIBSSH2_ERROR_SOCKET_NONE state = "|grep Running";
|| rc == LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED else if (type == 1) {
|| rc == LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED) { if (system_type == HMC) {
if (auth == NULL || auth->cb == NULL) { state = "|grep \"Not Activated\"";
PHYP_ERROR(VIR_ERR_AUTH_FAILED, } else {
"%s", _("No authentication callback provided.")); state = "|grep \"Open Firmware\"";
goto disconnect;
} }
} else
state = " ";
password = virRequestPassword(auth, username, conn->uri->server); virBufferAddLit(&buf, "lssyscfg -r lpar");
if (system_type == HMC)
if (password == NULL) { virBufferVSprintf(&buf, " -m %s", managed_system);
PHYP_ERROR(VIR_ERR_AUTH_FAILED, "%s", virBufferVSprintf(&buf, " -F lpar_id,state %s |grep -c '^[0-9]*'",
_("Password request failed")); state);
goto disconnect; if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
return -1;
} }
cmd = virBufferContentAndReset(&buf);
while ((rc = ret = phypExec(session, cmd, &exit_status, conn);
libssh2_userauth_password(session, username,
password)) ==
LIBSSH2_ERROR_EAGAIN) ;
if (rc) {
PHYP_ERROR(VIR_ERR_AUTH_FAILED,
"%s", _("Authentication failed"));
goto disconnect;
} else
goto exit;
} else if (rc == LIBSSH2_ERROR_NONE) { if (exit_status < 0 || ret == NULL)
goto exit; goto err;
} else if (rc == LIBSSH2_ERROR_ALLOC || rc == LIBSSH2_ERROR_SOCKET_SEND if (virStrToLong_i(ret, &char_ptr, 10, &ndom) == -1)
|| rc == LIBSSH2_ERROR_SOCKET_TIMEOUT) {
goto err; goto err;
}
disconnect: VIR_FREE(cmd);
libssh2_session_disconnect(session, "Disconnecting..."); VIR_FREE(ret);
libssh2_session_free(session); return ndom;
err:
VIR_FREE(userhome);
VIR_FREE(pubkey);
VIR_FREE(pvtkey);
VIR_FREE(username);
VIR_FREE(password);
return NULL;
exit: err:
VIR_FREE(userhome); VIR_FREE(cmd);
VIR_FREE(pubkey); VIR_FREE(ret);
VIR_FREE(pvtkey); return -1;
VIR_FREE(username);
VIR_FREE(password);
return session;
} }
/* this functions is the layer that manipulates the ssh channel itself /* This is a generic function that won't be used directly by
* and executes the commands on the remote machine */ * libvirt api. The function returns the ids of domains
static char * * in different states: Running, and all:
phypExec(LIBSSH2_SESSION * session, char *cmd, int *exit_status, *
virConnectPtr conn) * type: 0 - Running
* 1 - all
* */
static int
phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids,
unsigned int type)
{ {
LIBSSH2_CHANNEL *channel;
ConnectionData *connection_data = conn->networkPrivateData; ConnectionData *connection_data = conn->networkPrivateData;
virBuffer tex_ret = VIR_BUFFER_INITIALIZER;
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);
}
if (channel == NULL) {
goto err;
}
while ((rc = libssh2_channel_exec(channel, cmd)) ==
LIBSSH2_ERROR_EAGAIN) {
waitsocket(sock, session);
}
if (rc != 0) {
goto err;
}
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;
}
}
exitcode = 127;
while ((rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN) {
waitsocket(sock, session);
}
if (rc == 0) {
exitcode = libssh2_channel_get_exit_status(channel);
}
(*exit_status) = exitcode;
libssh2_channel_free(channel);
channel = NULL;
goto exit;
err:
(*exit_status) = SSH_CMD_ERR;
virBufferFreeAndReset(&tex_ret);
return NULL;
exit:
if (virBufferError(&tex_ret)) {
virBufferFreeAndReset(&tex_ret);
virReportOOMError();
return NULL;
}
return virBufferContentAndReset(&tex_ret);
}
int
phypGetSystemType(virConnectPtr conn)
{
ConnectionData *connection_data = conn->networkPrivateData;
LIBSSH2_SESSION *session = connection_data->session;
char *cmd = NULL;
char *ret = NULL;
int exit_status = 0;
if (virAsprintf(&cmd, "lshmc -V") < 0) {
virReportOOMError();
exit_status = -1;
}
ret = phypExec(session, cmd, &exit_status, conn);
VIR_FREE(cmd);
VIR_FREE(ret);
return exit_status;
}
/* return the lpar_id given a name and a managed system name */
static int
phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system,
const char *name, virConnectPtr conn)
{
phyp_driverPtr phyp_driver = conn->privateData; phyp_driverPtr phyp_driver = conn->privateData;
LIBSSH2_SESSION *session = connection_data->session;
int system_type = phyp_driver->system_type; int system_type = phyp_driver->system_type;
char *managed_system = phyp_driver->managed_system;
int exit_status = 0; int exit_status = 0;
int lpar_id = 0; int got = 0;
char *char_ptr; char *char_ptr;
unsigned int i = 0, j = 0;
char id_c[10];
char *cmd = NULL; char *cmd = NULL;
char *ret = NULL; char *ret = NULL;
const char *state;
virBuffer buf = VIR_BUFFER_INITIALIZER; virBuffer buf = VIR_BUFFER_INITIALIZER;
if (type == 0)
state = "|grep Running";
else
state = " ";
memset(id_c, 0, 10);
virBufferAddLit(&buf, "lssyscfg -r lpar"); virBufferAddLit(&buf, "lssyscfg -r lpar");
if (system_type == HMC) if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " --filter lpar_names=%s -F lpar_id", name); virBufferVSprintf(&buf, " -F lpar_id,state %s | sed -e 's/,.*$//'",
state);
if (virBufferError(&buf)) { if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf); virBufferFreeAndReset(&buf);
virReportOOMError(); virReportOOMError();
...@@ -546,15 +409,32 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system, ...@@ -546,15 +409,32 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system,
ret = phypExec(session, cmd, &exit_status, conn); ret = phypExec(session, cmd, &exit_status, conn);
/* I need to parse the textual return in order to get the ret */
if (exit_status < 0 || ret == NULL) if (exit_status < 0 || ret == NULL)
goto err; goto err;
else {
if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) while (got < nids) {
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; goto err;
}
memset(id_c, 0, 10);
j = 0;
got++;
} else {
id_c[j] = ret[i];
j++;
}
i++;
}
}
VIR_FREE(cmd); VIR_FREE(cmd);
VIR_FREE(ret); VIR_FREE(ret);
return lpar_id; return got;
err: err:
VIR_FREE(cmd); VIR_FREE(cmd);
...@@ -562,829 +442,863 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system, ...@@ -562,829 +442,863 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system,
return -1; return -1;
} }
/* return the lpar name given a lpar_id and a managed system name */ static int
static char * phypUUIDTable_WriteFile(virConnectPtr conn)
phypGetLparNAME(LIBSSH2_SESSION * session, const char *managed_system,
unsigned int lpar_id, virConnectPtr conn)
{
phyp_driverPtr phyp_driver = conn->privateData;
int system_type = phyp_driver->system_type;
char *cmd = NULL;
char *ret = NULL;
int exit_status = 0;
virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferAddLit(&buf, "lssyscfg -r lpar");
if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " --filter lpar_ids=%d -F name", lpar_id);
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
return NULL;
}
cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, conn);
if (exit_status < 0 || ret == NULL)
goto err;
char *char_ptr = strchr(ret, '\n');
if (char_ptr)
*char_ptr = '\0';
VIR_FREE(cmd);
return ret;
err:
VIR_FREE(cmd);
VIR_FREE(ret);
return NULL;
}
/* Search into the uuid_table for a lpar_uuid given a lpar_id
* and a managed system name
*
* return: 0 - record found
* -1 - not found
* */
int
phypGetLparUUID(unsigned char *uuid, int lpar_id, virConnectPtr conn)
{ {
phyp_driverPtr phyp_driver = conn->privateData; phyp_driverPtr phyp_driver = conn->privateData;
uuid_tablePtr uuid_table = phyp_driver->uuid_table; uuid_tablePtr uuid_table = phyp_driver->uuid_table;
lparPtr *lpars = uuid_table->lpars;
unsigned int i = 0; 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++) { for (i = 0; i < uuid_table->nlpars; i++) {
if (lpars[i]->id == lpar_id) { if (safewrite(fd, &uuid_table->lpars[i]->id,
memmove(uuid, lpars[i]->uuid, VIR_UUID_BUFLEN); sizeof(uuid_table->lpars[i]->id)) !=
return 0; sizeof(uuid_table->lpars[i]->id)) {
VIR_ERROR0(_("Unable to write information to local file."));
goto err;
}
if (safewrite(fd, uuid_table->lpars[i]->uuid, VIR_UUID_BUFLEN) !=
VIR_UUID_BUFLEN) {
VIR_ERROR0(_("Unable to write information to local file."));
goto err;
} }
} }
close(fd);
return 0;
err:
close(fd);
return -1; return -1;
} }
/* static int
* type: phypUUIDTable_Push(virConnectPtr conn)
* 0 - maxmem
* 1 - memory
* */
unsigned long
phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id,
int type)
{ {
ConnectionData *connection_data = conn->networkPrivateData; ConnectionData *connection_data = conn->networkPrivateData;
LIBSSH2_SESSION *session = connection_data->session; LIBSSH2_SESSION *session = connection_data->session;
phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_CHANNEL *channel = NULL;
int system_type = phyp_driver->system_type; virBuffer username = VIR_BUFFER_INITIALIZER;
char *cmd = NULL; struct stat local_fileinfo;
char *ret = NULL; char buffer[1024];
char *char_ptr; int rc = 0;
int memory = 0; FILE *fd;
int exit_status = 0; size_t nread, sent;
virBuffer buf = VIR_BUFFER_INITIALIZER; char *ptr;
char local_file[] = "./uuid_table";
char *remote_file = NULL;
if (type != 1 && type != 0) if (conn->uri->user != NULL) {
return 0; virBufferVSprintf(&username, "%s", conn->uri->user);
virBufferAddLit(&buf, "lshwres"); if (virBufferError(&username)) {
if (system_type == HMC) virBufferFreeAndReset(&username);
virBufferVSprintf(&buf, " -m %s", managed_system); virReportOOMError();
virBufferVSprintf(&buf, goto err;
" -r mem --level lpar -F %s --filter lpar_ids=%d", }
type ? "curr_mem" : "curr_max_mem", lpar_id);
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
return 0;
} }
cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, conn); if (virAsprintf
(&remote_file, "/home/%s/libvirt_uuid_table",
virBufferContentAndReset(&username))
< 0) {
virReportOOMError();
goto err;
}
if (exit_status < 0 || ret == NULL) if (stat(local_file, &local_fileinfo) == -1) {
VIR_WARN0("Unable to stat local file.");
goto err; goto err;
}
char_ptr = strchr(ret, '\n'); if (!(fd = fopen(local_file, "rb"))) {
VIR_WARN0("Unable to open local file.");
goto err;
}
if (char_ptr) do {
*char_ptr = '\0'; channel =
libssh2_scp_send(session, remote_file,
0x1FF & local_fileinfo.st_mode,
(unsigned long) local_fileinfo.st_size);
if (virStrToLong_i(ret, &char_ptr, 10, &memory) == -1) if ((!channel) && (libssh2_session_last_errno(session) !=
LIBSSH2_ERROR_EAGAIN))
goto err; goto err;
} while (!channel);
VIR_FREE(cmd); do {
VIR_FREE(ret); nread = fread(buffer, 1, sizeof(buffer), fd);
return memory; if (nread <= 0) {
if (feof(fd)) {
/* end of file */
break;
} else {
VIR_ERROR(_("Failed to read from %s"), local_file);
goto err;
}
}
ptr = buffer;
sent = 0;
err: do {
VIR_FREE(cmd); /* write the same data over and over, until error or completion */
VIR_FREE(ret); rc = libssh2_channel_write(channel, ptr, nread);
return 0; if (LIBSSH2_ERROR_EAGAIN == rc) { /* must loop around */
continue;
} else if (rc > 0) {
/* rc indicates how many bytes were written this time */
sent += rc;
}
ptr += sent;
nread -= sent;
} 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;
}
virBufferFreeAndReset(&username);
return 0;
unsigned long err:
phypGetLparCPU(virConnectPtr conn, const char *managed_system, int lpar_id) if (channel) {
{ libssh2_channel_send_eof(channel);
return phypGetLparCPUGeneric(conn, managed_system, lpar_id, 0); libssh2_channel_wait_eof(channel);
libssh2_channel_wait_closed(channel);
libssh2_channel_free(channel);
channel = NULL;
}
return -1;
} }
static int static int
phypGetLparCPUMAX(virDomainPtr dom) phypUUIDTable_RemLpar(virConnectPtr conn, int id)
{
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)
{ {
ConnectionData *connection_data = conn->networkPrivateData;
LIBSSH2_SESSION *session = connection_data->session;
phyp_driverPtr phyp_driver = conn->privateData; phyp_driverPtr phyp_driver = conn->privateData;
int system_type = phyp_driver->system_type; uuid_tablePtr uuid_table = phyp_driver->uuid_table;
char *cmd = NULL; unsigned int i = 0;
char *ret = NULL;
char *char_ptr;
int exit_status = 0;
int vcpus = 0;
virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferAddLit(&buf, "lshwres"); for (i = 0; i <= uuid_table->nlpars; i++) {
if (system_type == HMC) if (uuid_table->lpars[i]->id == id) {
virBufferVSprintf(&buf, " -m %s", managed_system); uuid_table->lpars[i]->id = -1;
virBufferVSprintf(&buf, memset(uuid_table->lpars[i]->uuid, 0, VIR_UUID_BUFLEN);
" -r proc --level lpar -F %s --filter lpar_ids=%d", }
type ? "curr_max_procs" : "curr_procs", lpar_id);
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
return 0;
} }
cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, conn);
if (exit_status < 0 || ret == NULL) if (phypUUIDTable_WriteFile(conn) == -1)
goto err; goto err;
char_ptr = strchr(ret, '\n'); if (phypUUIDTable_Push(conn) == -1)
if (char_ptr)
*char_ptr = '\0';
if (virStrToLong_i(ret, &char_ptr, 10, &vcpus) == -1)
goto err; goto err;
VIR_FREE(cmd); return 0;
VIR_FREE(ret);
return (unsigned long) vcpus;
err: err:
VIR_FREE(cmd); return -1;
VIR_FREE(ret);
return 0;
} }
int static int
phypGetRemoteSlot(virConnectPtr conn, const char *managed_system, phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id)
const char *lpar_name)
{ {
ConnectionData *connection_data = conn->networkPrivateData;
LIBSSH2_SESSION *session = connection_data->session;
phyp_driverPtr phyp_driver = conn->privateData; phyp_driverPtr phyp_driver = conn->privateData;
int system_type = phyp_driver->system_type; uuid_tablePtr uuid_table = phyp_driver->uuid_table;
char *cmd = NULL;
char *ret = NULL;
char *char_ptr;
int remote_slot = 0;
int exit_status = 0;
virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferAddLit(&buf, "lshwres"); uuid_table->nlpars++;
if (system_type == HMC) unsigned int i = uuid_table->nlpars;
virBufferVSprintf(&buf, " -m %s", managed_system); i--;
virBufferVSprintf(&buf, " -r virtualio --rsubtype scsi -F "
"remote_slot_num --filter lpar_names=%s", lpar_name); if (VIR_REALLOC_N(uuid_table->lpars, uuid_table->nlpars) < 0) {
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError(); virReportOOMError();
return -1; goto err;
} }
cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, conn);
if (exit_status < 0 || ret == NULL) if (VIR_ALLOC(uuid_table->lpars[i]) < 0) {
virReportOOMError();
goto err; goto err;
}
char_ptr = strchr(ret, '\n'); uuid_table->lpars[i]->id = id;
memmove(uuid_table->lpars[i]->uuid, uuid, VIR_UUID_BUFLEN);
if (char_ptr) if (phypUUIDTable_WriteFile(conn) == -1)
*char_ptr = '\0'; goto err;
if (virStrToLong_i(ret, &char_ptr, 10, &remote_slot) == -1) if (phypUUIDTable_Push(conn) == -1)
goto err; goto err;
VIR_FREE(cmd); return 0;
VIR_FREE(ret);
return remote_slot;
err: err:
VIR_FREE(cmd);
VIR_FREE(ret);
return -1; return -1;
} }
char * static int
phypGetBackingDevice(virConnectPtr conn, const char *managed_system, phypUUIDTable_ReadFile(virConnectPtr conn)
char *lpar_name)
{ {
ConnectionData *connection_data = conn->networkPrivateData;
LIBSSH2_SESSION *session = connection_data->session;
phyp_driverPtr phyp_driver = conn->privateData; phyp_driverPtr phyp_driver = conn->privateData;
int system_type = phyp_driver->system_type; uuid_tablePtr uuid_table = phyp_driver->uuid_table;
char *cmd = NULL; unsigned int i = 0;
char *ret = NULL; int fd = -1;
int remote_slot = 0; char local_file[] = "./uuid_table";
int exit_status = 0; int rc = 0;
char *char_ptr; int id;
char *backing_device = NULL;
virBuffer buf = VIR_BUFFER_INITIALIZER;
if ((remote_slot =
phypGetRemoteSlot(conn, managed_system, lpar_name)) == -1)
return NULL;
virBufferAddLit(&buf, "lshwres"); if ((fd = open(local_file, O_RDONLY)) == -1) {
if (system_type == HMC) VIR_WARN0("Unable to write information to local file.");
virBufferVSprintf(&buf, " -m %s", managed_system); goto err;
virBufferVSprintf(&buf, " -r virtualio --rsubtype scsi -F "
"backing_devices --filter slots=%d", remote_slot);
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
return NULL;
} }
cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, conn); /* 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++) {
if (exit_status < 0 || ret == NULL) rc = read(fd, &id, sizeof(int));
if (rc == sizeof(int)) {
if (VIR_ALLOC(uuid_table->lpars[i]) < 0) {
virReportOOMError();
goto err;
}
uuid_table->lpars[i]->id = id;
} else {
VIR_WARN0
("Unable to read from information to local file.");
goto err; goto err;
}
/* here is a little trick to deal returns of this kind: rc = read(fd, uuid_table->lpars[i]->uuid, VIR_UUID_BUFLEN);
* if (rc != VIR_UUID_BUFLEN) {
* 0x8100000000000000//lv01 VIR_WARN0("Unable to read information to local file.");
*
* the information we really need is only lv01, so we
* need to skip a lot of things on the string.
* */
char_ptr = strchr(ret, '/');
if (char_ptr) {
char_ptr++;
if (char_ptr[0] == '/')
char_ptr++;
else
goto err;
backing_device = strdup(char_ptr);
if (backing_device == NULL) {
virReportOOMError();
goto err; goto err;
} }
} else {
backing_device = ret;
ret = NULL;
} }
} else
virReportOOMError();
char_ptr = strchr(backing_device, '\n'); close(fd);
return 0;
if (char_ptr)
*char_ptr = '\0';
VIR_FREE(cmd);
VIR_FREE(ret);
return backing_device;
err: err:
VIR_FREE(cmd); close(fd);
VIR_FREE(ret); return -1;
return NULL;
} }
int static int
phypGetLparState(virConnectPtr conn, unsigned int lpar_id) phypUUIDTable_Pull(virConnectPtr conn)
{ {
ConnectionData *connection_data = conn->networkPrivateData; ConnectionData *connection_data = conn->networkPrivateData;
phyp_driverPtr phyp_driver = conn->privateData;
LIBSSH2_SESSION *session = connection_data->session; LIBSSH2_SESSION *session = connection_data->session;
int system_type = phyp_driver->system_type; LIBSSH2_CHANNEL *channel = NULL;
char *cmd = NULL; virBuffer username = VIR_BUFFER_INITIALIZER;
char *ret = NULL; struct stat fileinfo;
int exit_status = 0; char buffer[1024];
char *char_ptr = NULL; int rc = 0;
char *managed_system = phyp_driver->managed_system; int fd;
int state = VIR_DOMAIN_NOSTATE; int got = 0;
virBuffer buf = VIR_BUFFER_INITIALIZER; int amount = 0;
int total = 0;
int sock = 0;
char local_file[] = "./uuid_table";
char *remote_file = NULL;
virBufferAddLit(&buf, "lssyscfg -r lpar"); if (conn->uri->user != NULL) {
if (system_type == HMC) virBufferVSprintf(&username, "%s", conn->uri->user);
virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " -F state --filter lpar_ids=%d", lpar_id); if (virBufferError(&username)) {
if (virBufferError(&buf)) { virBufferFreeAndReset(&username);
virBufferFreeAndReset(&buf);
virReportOOMError(); virReportOOMError();
return state; goto err;
}
} }
cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, conn); if (virAsprintf
(&remote_file, "/home/%s/libvirt_uuid_table",
virBufferContentAndReset(&username))
< 0) {
virReportOOMError();
goto err;
}
if (exit_status < 0 || ret == NULL) /* Trying to stat the remote file. */
goto cleanup; do {
channel = libssh2_scp_recv(session, remote_file, &fileinfo);
char_ptr = strchr(ret, '\n'); if (!channel) {
if (libssh2_session_last_errno(session) !=
LIBSSH2_ERROR_EAGAIN) {
goto err;;
} else {
waitsocket(sock, session);
}
}
} while (!channel);
if (char_ptr) /* Creating a new data base based on remote file */
*char_ptr = '\0'; if ((fd = creat(local_file, 0755)) == -1)
goto err;
if (STREQ(ret, "Running")) /* Request a file via SCP */
state = VIR_DOMAIN_RUNNING; while (got < fileinfo.st_size) {
else if (STREQ(ret, "Not Activated")) do {
state = VIR_DOMAIN_SHUTOFF; amount = sizeof(buffer);
else if (STREQ(ret, "Shutting Down"))
state = VIR_DOMAIN_SHUTDOWN;
cleanup: if ((fileinfo.st_size - got) < amount) {
VIR_FREE(cmd); amount = fileinfo.st_size - got;
VIR_FREE(ret); }
return state;
}
int rc = libssh2_channel_read(channel, buffer, amount);
phypGetVIOSPartitionID(virConnectPtr conn) if (rc > 0) {
{ if (safewrite(fd, buffer, rc) != rc)
ConnectionData *connection_data = conn->networkPrivateData; VIR_WARN0
phyp_driverPtr phyp_driver = conn->privateData; ("Unable to write information to local file.");
LIBSSH2_SESSION *session = connection_data->session;
int system_type = phyp_driver->system_type;
char *cmd = NULL;
char *ret = NULL;
int exit_status = 0;
int id = -1;
char *char_ptr;
char *managed_system = phyp_driver->managed_system;
virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferAddLit(&buf, "lssyscfg"); got += rc;
if (system_type == HMC) total += rc;
virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferAddLit(&buf, " -r lpar -F lpar_id,lpar_env|grep "
"vioserver|sed -s 's/,.*$//'");
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
return -1;
} }
cmd = virBufferContentAndReset(&buf); } while (rc > 0);
ret = phypExec(session, cmd, &exit_status, conn);
if (exit_status < 0 || ret == NULL) if ((rc == LIBSSH2_ERROR_EAGAIN)
goto err; && (got < fileinfo.st_size)) {
/* this is due to blocking that would occur otherwise
* so we loop on this condition */
if (virStrToLong_i(ret, &char_ptr, 10, &id) == -1) waitsocket(sock, session); /* now we wait */
goto err; continue;
}
break;
}
close(fd);
goto exit;
VIR_FREE(cmd); exit:
VIR_FREE(ret); if (channel) {
return id; libssh2_channel_send_eof(channel);
libssh2_channel_wait_eof(channel);
libssh2_channel_wait_closed(channel);
libssh2_channel_free(channel);
channel = NULL;
}
virBufferFreeAndReset(&username);
return 0;
err: err:
VIR_FREE(cmd); if (channel) {
VIR_FREE(ret); libssh2_channel_send_eof(channel);
libssh2_channel_wait_eof(channel);
libssh2_channel_wait_closed(channel);
libssh2_channel_free(channel);
channel = NULL;
}
return -1; return -1;
} }
int static int
phypDiskType(virConnectPtr conn, char *backing_device) phypUUIDTable_Init(virConnectPtr conn)
{ {
phyp_driverPtr phyp_driver = conn->privateData; uuid_tablePtr uuid_table;
ConnectionData *connection_data = conn->networkPrivateData; phyp_driverPtr phyp_driver;
LIBSSH2_SESSION *session = connection_data->session; int nids_numdomains = 0;
int system_type = phyp_driver->system_type; int nids_listdomains = 0;
char *cmd = NULL; int *ids = NULL;
char *ret = NULL; unsigned int i = 0;
int exit_status = 0;
char *char_ptr;
char *managed_system = phyp_driver->managed_system;
int vios_id = phyp_driver->vios_id;
int disk_type = -1;
virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferAddLit(&buf, "viosvrcmd"); if ((nids_numdomains = phypNumDomainsGeneric(conn, 2)) < 0)
if (system_type == HMC) goto err;
virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " -p %d -c \"lssp -field name type " if (VIR_ALLOC_N(ids, nids_numdomains) < 0) {
"-fmt , -all|grep %s|sed -e 's/^.*,//'\"",
vios_id, backing_device);
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError(); virReportOOMError();
return disk_type; goto err;
} }
cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, conn);
if (exit_status < 0 || ret == NULL) if ((nids_listdomains =
goto cleanup; phypListDomainsGeneric(conn, ids, nids_numdomains, 1)) < 0)
goto err;
char_ptr = strchr(ret, '\n'); /* exit early if there are no domains */
if (nids_numdomains == 0 && nids_listdomains == 0)
goto exit;
else if (nids_numdomains != nids_listdomains) {
VIR_ERROR0(_("Unable to determine number of domains."));
goto err;
}
if (char_ptr) phyp_driver = conn->privateData;
*char_ptr = '\0'; uuid_table = phyp_driver->uuid_table;
uuid_table->nlpars = nids_listdomains;
if (STREQ(ret, "LVPOOL")) /* try to get the table from server */
disk_type = VIR_DOMAIN_DISK_TYPE_BLOCK; if (phypUUIDTable_Pull(conn) == -1) {
else if (STREQ(ret, "FBPOOL")) /* file not found in the server, creating a new one */
disk_type = VIR_DOMAIN_DISK_TYPE_FILE; if (VIR_ALLOC_N(uuid_table->lpars, uuid_table->nlpars) >= 0) {
for (i = 0; i < uuid_table->nlpars; i++) {
cleanup: if (VIR_ALLOC(uuid_table->lpars[i]) < 0) {
VIR_FREE(cmd); virReportOOMError();
VIR_FREE(ret); goto err;
return disk_type;
}
/* 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;
phyp_driverPtr phyp_driver = conn->privateData;
LIBSSH2_SESSION *session = connection_data->session;
int system_type = phyp_driver->system_type;
int exit_status = 0;
int ndom = 0;
char *char_ptr;
char *cmd = NULL;
char *ret = NULL;
char *managed_system = phyp_driver->managed_system;
const char *state;
virBuffer buf = VIR_BUFFER_INITIALIZER;
if (type == 0)
state = "|grep Running";
else if (type == 1) {
if (system_type == HMC) {
state = "|grep \"Not Activated\"";
} else {
state = "|grep \"Open Firmware\"";
} }
} else uuid_table->lpars[i]->id = ids[i];
state = " ";
virBufferAddLit(&buf, "lssyscfg -r lpar"); if (virUUIDGenerate(uuid_table->lpars[i]->uuid) < 0)
if (system_type == HMC) VIR_WARN("Unable to generate UUID for domain %d",
virBufferVSprintf(&buf, " -m %s", managed_system); ids[i]);
virBufferVSprintf(&buf, " -F lpar_id,state %s |grep -c '^[0-9]*'", }
state); } else {
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError(); virReportOOMError();
return -1; goto err;
} }
cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, conn);
if (exit_status < 0 || ret == NULL) if (phypUUIDTable_WriteFile(conn) == -1)
goto err; goto err;
if (virStrToLong_i(ret, &char_ptr, 10, &ndom) == -1) if (phypUUIDTable_Push(conn) == -1)
goto err;
} else {
if (phypUUIDTable_ReadFile(conn) == -1)
goto err; goto err;
goto exit;
}
VIR_FREE(cmd); exit:
VIR_FREE(ret); VIR_FREE(ids);
return ndom; return 0;
err: err:
VIR_FREE(cmd); VIR_FREE(ids);
VIR_FREE(ret);
return -1; return -1;
} }
static int static void
phypNumDefinedDomains(virConnectPtr conn) phypUUIDTable_Free(uuid_tablePtr uuid_table)
{ {
return phypNumDomainsGeneric(conn, 1); 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);
} }
static int static int
phypNumDomains(virConnectPtr conn) escape_specialcharacters(char *src, char *dst, size_t dstlen)
{ {
return phypNumDomainsGeneric(conn, 0); size_t len = strlen(src);
char temp_buffer[len];
unsigned int i = 0, j = 0;
if (len == 0)
return -1;
for (i = 0; i < len; i++) {
switch (src[i]) {
case '&':
case ';':
case '`':
case '@':
case '"':
case '|':
case '*':
case '?':
case '~':
case '<':
case '>':
case '^':
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
case '$':
case '%':
case '#':
case '\\':
case '\n':
case '\r':
case '\t':
continue;
default:
temp_buffer[j] = src[i];
j++;
}
}
temp_buffer[j] = '\0';
if (virStrcpy(dst, temp_buffer, dstlen) == NULL)
return -1;
return 0;
} }
/* This is a generic function that won't be used directly by static LIBSSH2_SESSION *
* libvirt api. The function returns the ids of domains openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
* in different states: Running, and all: int *internal_socket)
*
* type: 0 - Running
* 1 - all
* */
static int
phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids,
unsigned int type)
{ {
ConnectionData *connection_data = conn->networkPrivateData; LIBSSH2_SESSION *session;
phyp_driverPtr phyp_driver = conn->privateData; const char *hostname = conn->uri->server;
LIBSSH2_SESSION *session = connection_data->session; char *username = NULL;
int system_type = phyp_driver->system_type; char *password = NULL;
char *managed_system = phyp_driver->managed_system; int sock;
int exit_status = 0; int rc;
int got = 0; struct addrinfo *ai = NULL, *cur;
char *char_ptr; struct addrinfo hints;
unsigned int i = 0, j = 0; int ret;
char id_c[10]; char *pubkey = NULL;
char *cmd = NULL; char *pvtkey = NULL;
char *ret = NULL; char *userhome = virGetUserDirectory(geteuid());
const char *state; struct stat pvt_stat, pub_stat;
virBuffer buf = VIR_BUFFER_INITIALIZER;
if (type == 0) if (userhome == NULL)
state = "|grep Running"; goto err;
else
state = " ";
memset(id_c, 0, 10); if (virAsprintf(&pubkey, "%s/.ssh/id_rsa.pub", userhome) < 0) {
virReportOOMError();
goto err;
}
virBufferAddLit(&buf, "lssyscfg -r lpar"); if (virAsprintf(&pvtkey, "%s/.ssh/id_rsa", userhome) < 0) {
if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " -F lpar_id,state %s | sed -e 's/,.*$//'",
state);
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError(); virReportOOMError();
return -1; goto err;
} }
cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, conn); if (conn->uri->user != NULL) {
username = strdup(conn->uri->user);
/* I need to parse the textual return in order to get the ret */ if (username == NULL) {
if (exit_status < 0 || ret == NULL) virReportOOMError();
goto err;
else {
while (got < nids) {
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; goto err;
} }
memset(id_c, 0, 10);
j = 0;
got++;
} else { } else {
id_c[j] = ret[i]; if (auth == NULL || auth->cb == NULL) {
j++; PHYP_ERROR(VIR_ERR_AUTH_FAILED,
"%s", _("No authentication callback provided."));
goto err;
} }
i++;
username = virRequestUsername(auth, NULL, conn->uri->server);
if (username == NULL) {
PHYP_ERROR(VIR_ERR_AUTH_FAILED, "%s",
_("Username request failed"));
goto err;
} }
} }
VIR_FREE(cmd); memset(&hints, 0, sizeof(hints));
VIR_FREE(ret); hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
return got; hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
err:
VIR_FREE(cmd);
VIR_FREE(ret);
return -1;
}
static int ret = getaddrinfo(hostname, "22", &hints, &ai);
phypListDomains(virConnectPtr conn, int *ids, int nids) if (ret != 0) {
{ PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
return phypListDomainsGeneric(conn, ids, nids, 0); _("Error while getting %s address info"), hostname);
}
static int
phypListDefinedDomains(virConnectPtr conn, char **const names, int nnames)
{
ConnectionData *connection_data = conn->networkPrivateData;
phyp_driverPtr phyp_driver = conn->privateData;
LIBSSH2_SESSION *session = connection_data->session;
int system_type = phyp_driver->system_type;
char *managed_system = phyp_driver->managed_system;
int exit_status = 0;
int got = 0;
int i;
char *cmd = NULL;
char *ret = NULL;
char *domains = NULL;
char *char_ptr2 = NULL;
virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferAddLit(&buf, "lssyscfg -r lpar");
if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " -F name,state | grep \"Not Activated\" | "
"sed -e 's/,.*$//'");
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
return -1;
}
cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, conn);
/* I need to parse the textual return in order to get the domains */
if (exit_status < 0 || ret == NULL)
goto err; goto err;
else { }
domains = ret;
while (got < nnames) {
char_ptr2 = strchr(domains, '\n');
if (char_ptr2) { cur = ai;
*char_ptr2 = '\0'; while (cur != NULL) {
if ((names[got++] = strdup(domains)) == NULL) { sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
virReportOOMError(); if (sock >= 0) {
goto err; if (connect(sock, cur->ai_addr, cur->ai_addrlen) == 0) {
goto connected;
} }
char_ptr2++; close(sock);
domains = char_ptr2;
} else
break;
} }
cur = cur->ai_next;
} }
VIR_FREE(cmd); PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
VIR_FREE(ret); _("Failed to connect to %s"), hostname);
return got; freeaddrinfo(ai);
goto err;
err: connected:
for (i = 0; i < got; i++)
VIR_FREE(names[i]);
VIR_FREE(cmd);
VIR_FREE(ret);
return -1;
}
static virDomainPtr (*internal_socket) = sock;
phypDomainLookupByName(virConnectPtr conn, const char *lpar_name)
{
ConnectionData *connection_data = conn->networkPrivateData;
phyp_driverPtr phyp_driver = conn->privateData;
LIBSSH2_SESSION *session = connection_data->session;
virDomainPtr dom = NULL;
int lpar_id = 0;
char *managed_system = phyp_driver->managed_system;
unsigned char lpar_uuid[VIR_UUID_BUFLEN];
lpar_id = phypGetLparID(session, managed_system, lpar_name, conn); /* Create a session instance */
if (lpar_id == -1) session = libssh2_session_init();
return NULL; if (!session)
goto err;
if (phypGetLparUUID(lpar_uuid, lpar_id, conn) == -1) /* tell libssh2 we want it all done non-blocking */
return NULL; libssh2_session_set_blocking(session, 0);
dom = virGetDomain(conn, lpar_name, lpar_uuid); while ((rc = libssh2_session_startup(session, sock)) ==
LIBSSH2_ERROR_EAGAIN) ;
if (rc) {
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
"%s", _("Failure establishing SSH session."));
goto disconnect;
}
if (dom) /* Trying authentication by pubkey */
dom->id = lpar_id; if (stat(pvtkey, &pvt_stat) || stat(pubkey, &pub_stat)) {
rc = LIBSSH2_ERROR_SOCKET_NONE;
goto keyboard_interactive;
}
return dom; while ((rc =
} libssh2_userauth_publickey_fromfile(session, username,
pubkey,
pvtkey,
NULL)) ==
LIBSSH2_ERROR_EAGAIN) ;
static virDomainPtr keyboard_interactive:
phypDomainLookupByID(virConnectPtr conn, int lpar_id) if (rc == LIBSSH2_ERROR_SOCKET_NONE
{ || rc == LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED
ConnectionData *connection_data = conn->networkPrivateData; || rc == LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED) {
phyp_driverPtr phyp_driver = conn->privateData; if (auth == NULL || auth->cb == NULL) {
LIBSSH2_SESSION *session = connection_data->session; PHYP_ERROR(VIR_ERR_AUTH_FAILED,
virDomainPtr dom = NULL; "%s", _("No authentication callback provided."));
char *managed_system = phyp_driver->managed_system; goto disconnect;
int exit_status = 0; }
unsigned char lpar_uuid[VIR_UUID_BUFLEN];
char *lpar_name = phypGetLparNAME(session, managed_system, lpar_id, password = virRequestPassword(auth, username, conn->uri->server);
conn);
if (phypGetLparUUID(lpar_uuid, lpar_id, conn) == -1) if (password == NULL) {
goto err; PHYP_ERROR(VIR_ERR_AUTH_FAILED, "%s",
_("Password request failed"));
goto disconnect;
}
if (exit_status < 0) while ((rc =
goto err; libssh2_userauth_password(session, username,
password)) ==
LIBSSH2_ERROR_EAGAIN) ;
dom = virGetDomain(conn, lpar_name, lpar_uuid); if (rc) {
PHYP_ERROR(VIR_ERR_AUTH_FAILED,
"%s", _("Authentication failed"));
goto disconnect;
} else
goto exit;
if (dom) } else if (rc == LIBSSH2_ERROR_NONE) {
dom->id = lpar_id; goto exit;
VIR_FREE(lpar_name); } else if (rc == LIBSSH2_ERROR_ALLOC || rc == LIBSSH2_ERROR_SOCKET_SEND
return dom; || rc == LIBSSH2_ERROR_SOCKET_TIMEOUT) {
goto err;
}
disconnect:
libssh2_session_disconnect(session, "Disconnecting...");
libssh2_session_free(session);
err: err:
VIR_FREE(lpar_name); VIR_FREE(userhome);
VIR_FREE(pubkey);
VIR_FREE(pvtkey);
VIR_FREE(username);
VIR_FREE(password);
return NULL; return NULL;
exit:
VIR_FREE(userhome);
VIR_FREE(pubkey);
VIR_FREE(pvtkey);
VIR_FREE(username);
VIR_FREE(password);
return session;
} }
static char * static virDrvOpenStatus
phypDomainDumpXML(virDomainPtr dom, int flags) phypOpen(virConnectPtr conn,
virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
{ {
ConnectionData *connection_data = dom->conn->networkPrivateData; LIBSSH2_SESSION *session = NULL;
phyp_driverPtr phyp_driver = dom->conn->privateData; ConnectionData *connection_data = NULL;
LIBSSH2_SESSION *session = connection_data->session; char *string = NULL;
virDomainDef def; size_t len = 0;
char *managed_system = phyp_driver->managed_system; int internal_socket;
uuid_tablePtr uuid_table = NULL;
memset(&def, 0, sizeof(virDomainDef)); phyp_driverPtr phyp_driver = NULL;
char *char_ptr;
char *managed_system = NULL;
def.virtType = VIR_DOMAIN_VIRT_PHYP; if (!conn || !conn->uri)
def.id = dom->id; return VIR_DRV_OPEN_DECLINED;
char *lpar_name = phypGetLparNAME(session, managed_system, def.id, if (conn->uri->scheme == NULL || STRNEQ(conn->uri->scheme, "phyp"))
dom->conn); return VIR_DRV_OPEN_DECLINED;
if (lpar_name == NULL) { if (conn->uri->server == NULL) {
VIR_ERROR0(_("Unable to determine domain's name.")); PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
goto err; "%s", _("Missing server name in phyp:// URI"));
return VIR_DRV_OPEN_ERROR;
} }
if (phypGetLparUUID(def.uuid, dom->id, dom->conn) == -1) { if (VIR_ALLOC(phyp_driver) < 0) {
VIR_ERROR0(_("Unable to generate random uuid.")); virReportOOMError();
goto err; goto failure;
} }
if ((def.maxmem = if (VIR_ALLOC(uuid_table) < 0) {
phypGetLparMem(dom->conn, managed_system, dom->id, 0)) == 0) { virReportOOMError();
VIR_ERROR0(_("Unable to determine domain's max memory.")); goto failure;
goto err;
} }
if ((def.memory = if (VIR_ALLOC(connection_data) < 0) {
phypGetLparMem(dom->conn, managed_system, dom->id, 1)) == 0) { virReportOOMError();
VIR_ERROR0(_("Unable to determine domain's memory.")); goto failure;
goto err;
} }
if ((def.vcpus = if (conn->uri->path) {
phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0) { len = strlen(conn->uri->path) + 1;
VIR_ERROR0(_("Unable to determine domain's CPU."));
goto err;
}
return virDomainDefFormat(&def, flags); if (VIR_ALLOC_N(string, len) < 0) {
virReportOOMError();
goto failure;
}
err: /* need to shift one byte in order to remove the first "/" of URI component */
return NULL; if (conn->uri->path[0] == '/')
managed_system = strdup(conn->uri->path + 1);
else
managed_system = strdup(conn->uri->path);
if (!managed_system) {
virReportOOMError();
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';
if (escape_specialcharacters(conn->uri->path, string, len) == -1) {
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
"%s",
_("Error parsing 'path'. Invalid characters."));
goto failure;
}
}
if ((session = openSSHSession(conn, auth, &internal_socket)) == NULL) {
PHYP_ERROR(VIR_ERR_INTERNAL_ERROR,
"%s", _("Error while opening SSH session."));
goto failure;
}
connection_data->session = session;
uuid_table->nlpars = 0;
uuid_table->lpars = NULL;
if (conn->uri->path)
phyp_driver->managed_system = managed_system;
phyp_driver->uuid_table = uuid_table;
if ((phyp_driver->caps = phypCapsInit()) == NULL) {
virReportOOMError();
goto failure;
}
conn->privateData = phyp_driver;
conn->networkPrivateData = connection_data;
if ((phyp_driver->system_type = phypGetSystemType(conn)) == -1)
goto failure;
if (phypUUIDTable_Init(conn) == -1)
goto failure;
if (phyp_driver->system_type == HMC) {
if ((phyp_driver->vios_id = phypGetVIOSPartitionID(conn)) == -1)
goto failure;
}
return VIR_DRV_OPEN_SUCCESS;
failure:
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);
}
VIR_FREE(connection_data);
VIR_FREE(string);
return VIR_DRV_OPEN_ERROR;
} }
static int static int
phypDomainResume(virDomainPtr dom) phypClose(virConnectPtr conn)
{ {
ConnectionData *connection_data = dom->conn->networkPrivateData; ConnectionData *connection_data = conn->networkPrivateData;
phyp_driverPtr phyp_driver = dom->conn->privateData; phyp_driverPtr phyp_driver = conn->privateData;
LIBSSH2_SESSION *session = connection_data->session; LIBSSH2_SESSION *session = connection_data->session;
libssh2_session_disconnect(session, "Disconnecting...");
libssh2_session_free(session);
virCapabilitiesFree(phyp_driver->caps);
phypUUIDTable_Free(phyp_driver->uuid_table);
VIR_FREE(phyp_driver->managed_system);
VIR_FREE(phyp_driver);
VIR_FREE(connection_data);
return 0;
}
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;
}
/* return the lpar_id given a name and a managed system name */
static int
phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system,
const char *name, virConnectPtr conn)
{
phyp_driverPtr phyp_driver = conn->privateData;
int system_type = phyp_driver->system_type; int system_type = phyp_driver->system_type;
char *managed_system = phyp_driver->managed_system;
int exit_status = 0; int exit_status = 0;
int lpar_id = 0;
char *char_ptr;
char *cmd = NULL; char *cmd = NULL;
char *ret = NULL; char *ret = NULL;
virBuffer buf = VIR_BUFFER_INITIALIZER; virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferAddLit(&buf, "chsysstate"); virBufferAddLit(&buf, "lssyscfg -r lpar");
if (system_type == HMC) if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " -r lpar -o on --id %d -f %s", virBufferVSprintf(&buf, " --filter lpar_names=%s -F lpar_id", name);
dom->id, dom->name);
if (virBufferError(&buf)) { if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf); virBufferFreeAndReset(&buf);
virReportOOMError(); virReportOOMError();
...@@ -1392,14 +1306,17 @@ phypDomainResume(virDomainPtr dom) ...@@ -1392,14 +1306,17 @@ phypDomainResume(virDomainPtr dom)
} }
cmd = virBufferContentAndReset(&buf); cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, dom->conn); ret = phypExec(session, cmd, &exit_status, conn);
if (exit_status < 0) if (exit_status < 0 || ret == NULL)
goto err;
if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1)
goto err; goto err;
VIR_FREE(cmd); VIR_FREE(cmd);
VIR_FREE(ret); VIR_FREE(ret);
return 0; return lpar_id;
err: err:
VIR_FREE(cmd); VIR_FREE(cmd);
...@@ -1407,959 +1324,1046 @@ phypDomainResume(virDomainPtr dom) ...@@ -1407,959 +1324,1046 @@ phypDomainResume(virDomainPtr dom)
return -1; return -1;
} }
static int /* return the lpar name given a lpar_id and a managed system name */
phypDomainShutdown(virDomainPtr dom) static char *
phypGetLparNAME(LIBSSH2_SESSION * session, const char *managed_system,
unsigned int lpar_id, virConnectPtr conn)
{ {
ConnectionData *connection_data = dom->conn->networkPrivateData;
virConnectPtr conn = dom->conn;
LIBSSH2_SESSION *session = connection_data->session;
phyp_driverPtr phyp_driver = conn->privateData; phyp_driverPtr phyp_driver = conn->privateData;
int system_type = phyp_driver->system_type; int system_type = phyp_driver->system_type;
char *managed_system = phyp_driver->managed_system;
int exit_status = 0;
char *cmd = NULL; char *cmd = NULL;
char *ret = NULL; char *ret = NULL;
int exit_status = 0;
virBuffer buf = VIR_BUFFER_INITIALIZER; virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferAddLit(&buf, "chsysstate"); virBufferAddLit(&buf, "lssyscfg -r lpar");
if (system_type == HMC) if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " -r lpar -o shutdown --id %d", dom->id); virBufferVSprintf(&buf, " --filter lpar_ids=%d -F name", lpar_id);
if (virBufferError(&buf)) { if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf); virBufferFreeAndReset(&buf);
virReportOOMError(); virReportOOMError();
return 0; return NULL;
} }
cmd = virBufferContentAndReset(&buf); cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, dom->conn); ret = phypExec(session, cmd, &exit_status, conn);
if (exit_status < 0) if (exit_status < 0 || ret == NULL)
goto err; goto err;
char *char_ptr = strchr(ret, '\n');
if (char_ptr)
*char_ptr = '\0';
VIR_FREE(cmd); VIR_FREE(cmd);
VIR_FREE(ret); return ret;
return 0;
err: err:
VIR_FREE(cmd); VIR_FREE(cmd);
VIR_FREE(ret); VIR_FREE(ret);
return 0; return NULL;
} }
/* Search into the uuid_table for a lpar_uuid given a lpar_id
* and a managed system name
*
* return: 0 - record found
* -1 - not found
* */
static int static int
phypDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) phypGetLparUUID(unsigned char *uuid, int lpar_id, virConnectPtr conn)
{ {
phyp_driverPtr phyp_driver = dom->conn->privateData; phyp_driverPtr phyp_driver = conn->privateData;
char *managed_system = phyp_driver->managed_system; uuid_tablePtr uuid_table = phyp_driver->uuid_table;
lparPtr *lpars = uuid_table->lpars;
info->state = phypGetLparState(dom->conn, dom->id); unsigned int i = 0;
if ((info->maxMem =
phypGetLparMem(dom->conn, managed_system, dom->id, 0)) == 0)
VIR_WARN0("Unable to determine domain's max memory.");
if ((info->memory =
phypGetLparMem(dom->conn, managed_system, dom->id, 1)) == 0)
VIR_WARN0("Unable to determine domain's memory.");
if ((info->nrVirtCpu =
phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0)
VIR_WARN0("Unable to determine domain's CPU.");
for (i = 0; i < uuid_table->nlpars; i++) {
if (lpars[i]->id == lpar_id) {
memmove(uuid, lpars[i]->uuid, VIR_UUID_BUFLEN);
return 0; return 0;
}
}
return -1;
} }
static int /*
phypDomainDestroy(virDomainPtr dom) * type:
* 0 - maxmem
* 1 - memory
* */
static unsigned long
phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id,
int type)
{ {
ConnectionData *connection_data = dom->conn->networkPrivateData; ConnectionData *connection_data = conn->networkPrivateData;
phyp_driverPtr phyp_driver = dom->conn->privateData;
LIBSSH2_SESSION *session = connection_data->session; LIBSSH2_SESSION *session = connection_data->session;
phyp_driverPtr phyp_driver = conn->privateData;
int system_type = phyp_driver->system_type; int system_type = phyp_driver->system_type;
char *managed_system = phyp_driver->managed_system;
int exit_status = 0;
char *cmd = NULL; char *cmd = NULL;
char *ret = NULL; char *ret = NULL;
char *char_ptr;
int memory = 0;
int exit_status = 0;
virBuffer buf = VIR_BUFFER_INITIALIZER; virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferAddLit(&buf, "rmsyscfg"); if (type != 1 && type != 0)
return 0;
virBufferAddLit(&buf, "lshwres");
if (system_type == HMC) if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " -r lpar --id %d", dom->id); virBufferVSprintf(&buf,
" -r mem --level lpar -F %s --filter lpar_ids=%d",
type ? "curr_mem" : "curr_max_mem", lpar_id);
if (virBufferError(&buf)) { if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf); virBufferFreeAndReset(&buf);
virReportOOMError(); virReportOOMError();
return -1; return 0;
} }
cmd = virBufferContentAndReset(&buf); cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, dom->conn); ret = phypExec(session, cmd, &exit_status, conn);
if (exit_status < 0) if (exit_status < 0 || ret == NULL)
goto err; goto err;
if (phypUUIDTable_RemLpar(dom->conn, dom->id) == -1) char_ptr = strchr(ret, '\n');
if (char_ptr)
*char_ptr = '\0';
if (virStrToLong_i(ret, &char_ptr, 10, &memory) == -1)
goto err; goto err;
VIR_FREE(cmd); VIR_FREE(cmd);
VIR_FREE(ret); VIR_FREE(ret);
return 0; return memory;
err: err:
VIR_FREE(cmd); VIR_FREE(cmd);
VIR_FREE(ret); VIR_FREE(ret);
return -1; return 0;
} }
static virDomainPtr static unsigned long
phypDomainCreateAndStart(virConnectPtr conn, phypGetLparCPUGeneric(virConnectPtr conn, const char *managed_system,
const char *xml, unsigned int flags) int lpar_id, int type)
{ {
ConnectionData *connection_data = conn->networkPrivateData; ConnectionData *connection_data = conn->networkPrivateData;
LIBSSH2_SESSION *session = connection_data->session; LIBSSH2_SESSION *session = connection_data->session;
virDomainDefPtr def = NULL;
virDomainPtr dom = NULL;
phyp_driverPtr phyp_driver = conn->privateData; phyp_driverPtr phyp_driver = conn->privateData;
uuid_tablePtr uuid_table = phyp_driver->uuid_table; int system_type = phyp_driver->system_type;
lparPtr *lpars = uuid_table->lpars; char *cmd = NULL;
unsigned int i = 0; char *ret = NULL;
char *managed_system = phyp_driver->managed_system; char *char_ptr;
int exit_status = 0;
virCheckFlags(0, NULL); int vcpus = 0;
virBuffer buf = VIR_BUFFER_INITIALIZER;
if (!(def = virDomainDefParseString(phyp_driver->caps, xml,
VIR_DOMAIN_XML_SECURE)))
goto err;
/* checking if this name already exists on this system */ virBufferAddLit(&buf, "lshwres");
if (phypGetLparID(session, managed_system, def->name, conn) == -1) { if (system_type == HMC)
VIR_WARN0("LPAR name already exists."); virBufferVSprintf(&buf, " -m %s", managed_system);
goto err; virBufferVSprintf(&buf,
" -r proc --level lpar -F %s --filter lpar_ids=%d",
type ? "curr_max_procs" : "curr_procs", lpar_id);
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
return 0;
} }
cmd = virBufferContentAndReset(&buf);
/* checking if ID or UUID already exists on this system */ ret = phypExec(session, cmd, &exit_status, conn);
for (i = 0; i < uuid_table->nlpars; i++) {
if (lpars[i]->id == def->id || lpars[i]->uuid == def->uuid) {
VIR_WARN0("LPAR ID or UUID already exists.");
goto err;
}
}
if ((dom = virGetDomain(conn, def->name, def->uuid)) == NULL) if (exit_status < 0 || ret == NULL)
goto err; goto err;
if (phypBuildLpar(conn, def) == -1) char_ptr = strchr(ret, '\n');
goto err;
if (phypDomainResume(dom) == -1) if (char_ptr)
*char_ptr = '\0';
if (virStrToLong_i(ret, &char_ptr, 10, &vcpus) == -1)
goto err; goto err;
return dom; VIR_FREE(cmd);
VIR_FREE(ret);
return (unsigned long) vcpus;
err: err:
virDomainDefFree(def); VIR_FREE(cmd);
if (dom) VIR_FREE(ret);
virUnrefDomain(dom); return 0;
return NULL;
} }
static char * static unsigned long
phypConnectGetCapabilities(virConnectPtr conn) phypGetLparCPU(virConnectPtr conn, const char *managed_system, int lpar_id)
{ {
phyp_driverPtr phyp_driver = conn->privateData; return phypGetLparCPUGeneric(conn, managed_system, lpar_id, 0);
char *xml; }
if ((xml = virCapabilitiesFormatXML(phyp_driver->caps)) == NULL) static int
virReportOOMError(); phypGetLparCPUMAX(virDomainPtr dom)
{
phyp_driverPtr phyp_driver = dom->conn->privateData;
char *managed_system = phyp_driver->managed_system;
return xml; return phypGetLparCPUGeneric(dom->conn, managed_system, dom->id, 1);
} }
virCapsPtr static int
phypCapsInit(void) phypGetRemoteSlot(virConnectPtr conn, const char *managed_system,
const char *lpar_name)
{ {
struct utsname utsname; ConnectionData *connection_data = conn->networkPrivateData;
virCapsPtr caps; LIBSSH2_SESSION *session = connection_data->session;
virCapsGuestPtr guest; phyp_driverPtr phyp_driver = conn->privateData;
int system_type = phyp_driver->system_type;
char *cmd = NULL;
char *ret = NULL;
char *char_ptr;
int remote_slot = 0;
int exit_status = 0;
virBuffer buf = VIR_BUFFER_INITIALIZER;
uname(&utsname); virBufferAddLit(&buf, "lshwres");
if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " -r virtualio --rsubtype scsi -F "
"remote_slot_num --filter lpar_names=%s", lpar_name);
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
return -1;
}
cmd = virBufferContentAndReset(&buf);
if ((caps = virCapabilitiesNew(utsname.machine, 0, 0)) == NULL) ret = phypExec(session, cmd, &exit_status, conn);
goto no_memory;
/* Some machines have problematic NUMA toplogy causing if (exit_status < 0 || ret == NULL)
* unexpected failures. We don't want to break the QEMU goto err;
* 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 */ char_ptr = strchr(ret, '\n');
virCapabilitiesSetMacPrefix(caps, (unsigned char[]) {
0x52, 0x54, 0x00});
if ((guest = virCapabilitiesAddGuest(caps, if (char_ptr)
"linux", *char_ptr = '\0';
utsname.machine,
sizeof(int) == 4 ? 32 : 8,
NULL, NULL, 0, NULL)) == NULL)
goto no_memory;
if (virCapabilitiesAddGuestDomain(guest, if (virStrToLong_i(ret, &char_ptr, 10, &remote_slot) == -1)
"phyp", NULL, NULL, 0, NULL) == NULL) goto err;
goto no_memory;
return caps; VIR_FREE(cmd);
VIR_FREE(ret);
return remote_slot;
no_memory: err:
virCapabilitiesFree(caps); VIR_FREE(cmd);
return NULL; VIR_FREE(ret);
return -1;
} }
static int /* XXX - is this needed? */
phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus) static char *phypGetBackingDevice(virConnectPtr, const char *, char *)
ATTRIBUTE_UNUSED;
static char *
phypGetBackingDevice(virConnectPtr conn, const char *managed_system,
char *lpar_name)
{ {
ConnectionData *connection_data = dom->conn->networkPrivateData; ConnectionData *connection_data = conn->networkPrivateData;
phyp_driverPtr phyp_driver = dom->conn->privateData;
LIBSSH2_SESSION *session = connection_data->session; LIBSSH2_SESSION *session = connection_data->session;
phyp_driverPtr phyp_driver = conn->privateData;
int system_type = phyp_driver->system_type; int system_type = phyp_driver->system_type;
char *managed_system = phyp_driver->managed_system;
int exit_status = 0;
char *cmd = NULL; char *cmd = NULL;
char *ret = NULL; char *ret = NULL;
char operation; int remote_slot = 0;
unsigned long ncpus = 0; int exit_status = 0;
unsigned int amount = 0; char *char_ptr;
char *backing_device = NULL;
virBuffer buf = VIR_BUFFER_INITIALIZER; virBuffer buf = VIR_BUFFER_INITIALIZER;
if ((ncpus = phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0) if ((remote_slot =
return 0; phypGetRemoteSlot(conn, managed_system, lpar_name)) == -1)
return NULL;
if (nvcpus > phypGetLparCPUMAX(dom)) {
VIR_ERROR0(_("You are trying to set a number of CPUs bigger than "
"the max possible."));
return 0;
}
if (ncpus > nvcpus) {
operation = 'r';
amount = nvcpus - ncpus;
} else if (ncpus < nvcpus) {
operation = 'a';
amount = nvcpus - ncpus;
} else
return 0;
virBufferAddLit(&buf, "chhwres -r proc"); virBufferAddLit(&buf, "lshwres");
if (system_type == HMC) if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " --id %d -o %c --procunits %d 2>&1 |sed " virBufferVSprintf(&buf, " -r virtualio --rsubtype scsi -F "
"-e 's/^.*\\([0-9][0-9]*.[0-9][0-9]*\\).*$/\\1/'", "backing_devices --filter slots=%d", remote_slot);
dom->id, operation, amount);
if (virBufferError(&buf)) { if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf); virBufferFreeAndReset(&buf);
virReportOOMError(); virReportOOMError();
return 0; return NULL;
} }
cmd = virBufferContentAndReset(&buf); cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, dom->conn); ret = phypExec(session, cmd, &exit_status, conn);
if (exit_status < 0) { if (exit_status < 0 || ret == NULL)
VIR_ERROR0(_ goto err;
("Possibly you don't have IBM Tools installed in your LPAR."
" Contact your support to enable this feature.")); /* here is a little trick to deal returns of this kind:
*
* 0x8100000000000000//lv01
*
* the information we really need is only lv01, so we
* need to skip a lot of things on the string.
* */
char_ptr = strchr(ret, '/');
if (char_ptr) {
char_ptr++;
if (char_ptr[0] == '/')
char_ptr++;
else
goto err;
backing_device = strdup(char_ptr);
if (backing_device == NULL) {
virReportOOMError();
goto err;
}
} else {
backing_device = ret;
ret = NULL;
} }
char_ptr = strchr(backing_device, '\n');
if (char_ptr)
*char_ptr = '\0';
VIR_FREE(cmd); VIR_FREE(cmd);
VIR_FREE(ret); VIR_FREE(ret);
return 0; return backing_device;
err:
VIR_FREE(cmd);
VIR_FREE(ret);
return NULL;
} }
virDriver phypDriver = { static int
VIR_DRV_PHYP, "PHYP", phypOpen, /* open */ phypGetLparState(virConnectPtr conn, unsigned int lpar_id)
phypClose, /* close */
NULL, /* supports_feature */
NULL, /* type */
NULL, /* version */
NULL, /* libvirtVersion (impl. in libvirt.c) */
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 */
phypDomainGetInfo, /* domainGetInfo */
NULL, /* domainSave */
NULL, /* domainRestore */
NULL, /* domainCoreDump */
phypDomainSetCPU, /* domainSetVcpus */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
phypGetLparCPUMAX, /* domainGetMaxVcpus */
NULL, /* domainGetSecurityLabel */
NULL, /* nodeGetSecurityModel */
phypDomainDumpXML, /* domainDumpXML */
NULL, /* domainXMLFromNative */
NULL, /* domainXMLToNative */
phypListDefinedDomains, /* listDefinedDomains */
phypNumDefinedDomains, /* numOfDefinedDomains */
NULL, /* domainCreate */
NULL, /* domainCreateWithFlags */
NULL, /* domainDefineXML */
NULL, /* domainUndefine */
NULL, /* domainAttachDevice */
NULL, /* domainAttachDeviceFlags */
NULL, /* domainDetachDevice */
NULL, /* domainDetachDeviceFlags */
NULL, /* domainUpdateDeviceFlags */
NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */
NULL, /* domainGetSchedulerType */
NULL, /* domainGetSchedulerParameters */
NULL, /* domainSetSchedulerParameters */
NULL, /* domainMigratePrepare */
NULL, /* domainMigratePerform */
NULL, /* domainMigrateFinish */
NULL, /* domainBlockStats */
NULL, /* domainInterfaceStats */
NULL, /* domainMemoryStats */
NULL, /* domainBlockPeek */
NULL, /* domainMemoryPeek */
NULL, /* domainGetBlockInfo */
NULL, /* nodeGetCellsFreeMemory */
NULL, /* getFreeMemory */
NULL, /* domainEventRegister */
NULL, /* domainEventDeregister */
NULL, /* domainMigratePrepare2 */
NULL, /* domainMigrateFinish2 */
NULL, /* nodeDeviceDettach */
NULL, /* nodeDeviceReAttach */
NULL, /* nodeDeviceReset */
NULL, /* domainMigratePrepareTunnel */
phypIsEncrypted, /* isEncrypted */
phypIsSecure, /* isSecure */
NULL, /* domainIsActive */
NULL, /* domainIsPersistent */
NULL, /* cpuCompare */
NULL, /* cpuBaseline */
NULL, /* domainGetJobInfo */
NULL, /* domainAbortJob */
NULL, /* domainMigrateSetMaxDowntime */
NULL, /* domainEventRegisterAny */
NULL, /* domainEventDeregisterAny */
NULL, /* domainManagedSave */
NULL, /* domainHasManagedSaveImage */
NULL, /* domainManagedSaveRemove */
NULL, /* domainSnapshotCreateXML */
NULL, /* domainSnapshotDumpXML */
NULL, /* domainSnapshotNum */
NULL, /* domainSnapshotListNames */
NULL, /* domainSnapshotLookupByName */
NULL, /* domainHasCurrentSnapshot */
NULL, /* domainSnapshotCurrent */
NULL, /* domainRevertToSnapshot */
NULL, /* domainSnapshotDelete */
};
int
phypBuildLpar(virConnectPtr conn, virDomainDefPtr def)
{ {
ConnectionData *connection_data = conn->networkPrivateData; ConnectionData *connection_data = conn->networkPrivateData;
phyp_driverPtr phyp_driver = conn->privateData; phyp_driverPtr phyp_driver = conn->privateData;
LIBSSH2_SESSION *session = connection_data->session; LIBSSH2_SESSION *session = connection_data->session;
int system_type = phyp_driver->system_type; int system_type = phyp_driver->system_type;
char *managed_system = phyp_driver->managed_system;
char *cmd = NULL; char *cmd = NULL;
char *ret = NULL; char *ret = NULL;
int exit_status = 0; int exit_status = 0;
char *char_ptr = NULL;
char *managed_system = phyp_driver->managed_system;
int state = VIR_DOMAIN_NOSTATE;
virBuffer buf = VIR_BUFFER_INITIALIZER; virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferAddLit(&buf, "mksyscfg"); virBufferAddLit(&buf, "lssyscfg -r lpar");
if (system_type == HMC) if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " -r lpar -p %s -i min_mem=%d,desired_mem=%d," virBufferVSprintf(&buf, " -F state --filter lpar_ids=%d", lpar_id);
"max_mem=%d,desired_procs=%d,virtual_scsi_adapters=%s",
def->name, (int) def->memory, (int) def->memory,
(int) def->maxmem, (int) def->vcpus, def->disks[0]->src);
if (virBufferError(&buf)) { if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf); virBufferFreeAndReset(&buf);
virReportOOMError(); virReportOOMError();
return -1; return state;
} }
cmd = virBufferContentAndReset(&buf); cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, conn); ret = phypExec(session, cmd, &exit_status, conn);
if (exit_status < 0) { if (exit_status < 0 || ret == NULL)
VIR_ERROR(_("Unable to create LPAR. Reason: '%s'"), ret); goto cleanup;
goto err;
}
if (phypUUIDTable_AddLpar(conn, def->uuid, def->id) == -1) { char_ptr = strchr(ret, '\n');
VIR_ERROR0(_("Unable to add LPAR to the table"));
goto err;
}
VIR_FREE(cmd); if (char_ptr)
VIR_FREE(ret); *char_ptr = '\0';
return 0;
err: if (STREQ(ret, "Running"))
state = VIR_DOMAIN_RUNNING;
else if (STREQ(ret, "Not Activated"))
state = VIR_DOMAIN_SHUTOFF;
else if (STREQ(ret, "Shutting Down"))
state = VIR_DOMAIN_SHUTDOWN;
cleanup:
VIR_FREE(cmd); VIR_FREE(cmd);
VIR_FREE(ret); VIR_FREE(ret);
return -1; return state;
} }
int /* XXX - is this needed? */
phypUUIDTable_RemLpar(virConnectPtr conn, int id) static int phypDiskType(virConnectPtr, char *) ATTRIBUTE_UNUSED;
static int
phypDiskType(virConnectPtr conn, char *backing_device)
{ {
phyp_driverPtr phyp_driver = conn->privateData; phyp_driverPtr phyp_driver = conn->privateData;
uuid_tablePtr uuid_table = phyp_driver->uuid_table; ConnectionData *connection_data = conn->networkPrivateData;
unsigned int i = 0; LIBSSH2_SESSION *session = connection_data->session;
int system_type = phyp_driver->system_type;
char *cmd = NULL;
char *ret = NULL;
int exit_status = 0;
char *char_ptr;
char *managed_system = phyp_driver->managed_system;
int vios_id = phyp_driver->vios_id;
int disk_type = -1;
virBuffer buf = VIR_BUFFER_INITIALIZER;
for (i = 0; i <= uuid_table->nlpars; i++) { virBufferAddLit(&buf, "viosvrcmd");
if (uuid_table->lpars[i]->id == id) { if (system_type == HMC)
uuid_table->lpars[i]->id = -1; virBufferVSprintf(&buf, " -m %s", managed_system);
memset(uuid_table->lpars[i]->uuid, 0, VIR_UUID_BUFLEN); virBufferVSprintf(&buf, " -p %d -c \"lssp -field name type "
} "-fmt , -all|grep %s|sed -e 's/^.*,//'\"",
vios_id, backing_device);
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
return disk_type;
} }
cmd = virBufferContentAndReset(&buf);
if (phypUUIDTable_WriteFile(conn) == -1) ret = phypExec(session, cmd, &exit_status, conn);
goto err;
if (phypUUIDTable_Push(conn) == -1) if (exit_status < 0 || ret == NULL)
goto err; goto cleanup;
return 0; char_ptr = strchr(ret, '\n');
err: if (char_ptr)
return -1; *char_ptr = '\0';
if (STREQ(ret, "LVPOOL"))
disk_type = VIR_DOMAIN_DISK_TYPE_BLOCK;
else if (STREQ(ret, "FBPOOL"))
disk_type = VIR_DOMAIN_DISK_TYPE_FILE;
cleanup:
VIR_FREE(cmd);
VIR_FREE(ret);
return disk_type;
} }
int static int
phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id) phypNumDefinedDomains(virConnectPtr conn)
{ {
phyp_driverPtr phyp_driver = conn->privateData; return phypNumDomainsGeneric(conn, 1);
uuid_tablePtr uuid_table = phyp_driver->uuid_table; }
uuid_table->nlpars++; static int
unsigned int i = uuid_table->nlpars; phypNumDomains(virConnectPtr conn)
i--; {
return phypNumDomainsGeneric(conn, 0);
}
if (VIR_REALLOC_N(uuid_table->lpars, uuid_table->nlpars) < 0) { static int
virReportOOMError(); phypListDomains(virConnectPtr conn, int *ids, int nids)
goto err; {
} return phypListDomainsGeneric(conn, ids, nids, 0);
}
if (VIR_ALLOC(uuid_table->lpars[i]) < 0) { static int
phypListDefinedDomains(virConnectPtr conn, char **const names, int nnames)
{
ConnectionData *connection_data = conn->networkPrivateData;
phyp_driverPtr phyp_driver = conn->privateData;
LIBSSH2_SESSION *session = connection_data->session;
int system_type = phyp_driver->system_type;
char *managed_system = phyp_driver->managed_system;
int exit_status = 0;
int got = 0;
int i;
char *cmd = NULL;
char *ret = NULL;
char *domains = NULL;
char *char_ptr2 = NULL;
virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferAddLit(&buf, "lssyscfg -r lpar");
if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " -F name,state | grep \"Not Activated\" | "
"sed -e 's/,.*$//'");
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError(); virReportOOMError();
goto err; return -1;
} }
cmd = virBufferContentAndReset(&buf);
uuid_table->lpars[i]->id = id; ret = phypExec(session, cmd, &exit_status, conn);
memmove(uuid_table->lpars[i]->uuid, uuid, VIR_UUID_BUFLEN);
if (phypUUIDTable_WriteFile(conn) == -1)
goto err;
if (phypUUIDTable_Push(conn) == -1) /* I need to parse the textual return in order to get the domains */
if (exit_status < 0 || ret == NULL)
goto err; goto err;
else {
domains = ret;
return 0; while (got < nnames) {
char_ptr2 = strchr(domains, '\n');
if (char_ptr2) {
*char_ptr2 = '\0';
if ((names[got++] = strdup(domains)) == NULL) {
virReportOOMError();
goto err;
}
char_ptr2++;
domains = char_ptr2;
} else
break;
}
}
VIR_FREE(cmd);
VIR_FREE(ret);
return got;
err: err:
for (i = 0; i < got; i++)
VIR_FREE(names[i]);
VIR_FREE(cmd);
VIR_FREE(ret);
return -1; return -1;
} }
int static virDomainPtr
phypUUIDTable_ReadFile(virConnectPtr conn) phypDomainLookupByName(virConnectPtr conn, const char *lpar_name)
{ {
ConnectionData *connection_data = conn->networkPrivateData;
phyp_driverPtr phyp_driver = conn->privateData; phyp_driverPtr phyp_driver = conn->privateData;
uuid_tablePtr uuid_table = phyp_driver->uuid_table; LIBSSH2_SESSION *session = connection_data->session;
unsigned int i = 0; virDomainPtr dom = NULL;
int fd = -1; int lpar_id = 0;
char local_file[] = "./uuid_table"; char *managed_system = phyp_driver->managed_system;
int rc = 0; unsigned char lpar_uuid[VIR_UUID_BUFLEN];
int id;
if ((fd = open(local_file, O_RDONLY)) == -1) {
VIR_WARN0("Unable to write information to local file.");
goto err;
}
/* Creating a new data base and writing to local file */ lpar_id = phypGetLparID(session, managed_system, lpar_name, conn);
if (VIR_ALLOC_N(uuid_table->lpars, uuid_table->nlpars) >= 0) { if (lpar_id == -1)
for (i = 0; i < uuid_table->nlpars; i++) { return NULL;
rc = read(fd, &id, sizeof(int)); if (phypGetLparUUID(lpar_uuid, lpar_id, conn) == -1)
if (rc == sizeof(int)) { return NULL;
if (VIR_ALLOC(uuid_table->lpars[i]) < 0) {
virReportOOMError();
goto err;
}
uuid_table->lpars[i]->id = id;
} else {
VIR_WARN0
("Unable to read from information to local file.");
goto err;
}
rc = read(fd, uuid_table->lpars[i]->uuid, VIR_UUID_BUFLEN); dom = virGetDomain(conn, lpar_name, lpar_uuid);
if (rc != VIR_UUID_BUFLEN) {
VIR_WARN0("Unable to read information to local file.");
goto err;
}
}
} else
virReportOOMError();
close(fd); if (dom)
return 0; dom->id = lpar_id;
err: return dom;
close(fd);
return -1;
} }
int static virDomainPtr
phypUUIDTable_WriteFile(virConnectPtr conn) phypDomainLookupByID(virConnectPtr conn, int lpar_id)
{ {
ConnectionData *connection_data = conn->networkPrivateData;
phyp_driverPtr phyp_driver = conn->privateData; phyp_driverPtr phyp_driver = conn->privateData;
uuid_tablePtr uuid_table = phyp_driver->uuid_table; LIBSSH2_SESSION *session = connection_data->session;
unsigned int i = 0; virDomainPtr dom = NULL;
int fd = -1; char *managed_system = phyp_driver->managed_system;
char local_file[] = "./uuid_table"; int exit_status = 0;
unsigned char lpar_uuid[VIR_UUID_BUFLEN];
if ((fd = creat(local_file, 0755)) == -1) char *lpar_name = phypGetLparNAME(session, managed_system, lpar_id,
goto err; conn);
for (i = 0; i < uuid_table->nlpars; i++) { if (phypGetLparUUID(lpar_uuid, lpar_id, conn) == -1)
if (safewrite(fd, &uuid_table->lpars[i]->id,
sizeof(uuid_table->lpars[i]->id)) !=
sizeof(uuid_table->lpars[i]->id)) {
VIR_ERROR0(_("Unable to write information to local file."));
goto err; goto err;
}
if (safewrite(fd, uuid_table->lpars[i]->uuid, VIR_UUID_BUFLEN) != if (exit_status < 0)
VIR_UUID_BUFLEN) {
VIR_ERROR0(_("Unable to write information to local file."));
goto err; goto err;
}
}
close(fd); dom = virGetDomain(conn, lpar_name, lpar_uuid);
return 0;
if (dom)
dom->id = lpar_id;
VIR_FREE(lpar_name);
return dom;
err: err:
close(fd); VIR_FREE(lpar_name);
return -1; return NULL;
} }
int static char *
phypUUIDTable_Init(virConnectPtr conn) phypDomainDumpXML(virDomainPtr dom, int flags)
{ {
uuid_tablePtr uuid_table; ConnectionData *connection_data = dom->conn->networkPrivateData;
phyp_driverPtr phyp_driver; phyp_driverPtr phyp_driver = dom->conn->privateData;
int nids_numdomains = 0; LIBSSH2_SESSION *session = connection_data->session;
int nids_listdomains = 0; virDomainDef def;
int *ids = NULL; char *managed_system = phyp_driver->managed_system;
unsigned int i = 0;
if ((nids_numdomains = phypNumDomainsGeneric(conn, 2)) < 0) memset(&def, 0, sizeof(virDomainDef));
goto err;
if (VIR_ALLOC_N(ids, nids_numdomains) < 0) { def.virtType = VIR_DOMAIN_VIRT_PHYP;
virReportOOMError(); def.id = dom->id;
goto err;
}
if ((nids_listdomains = char *lpar_name = phypGetLparNAME(session, managed_system, def.id,
phypListDomainsGeneric(conn, ids, nids_numdomains, 1)) < 0) dom->conn);
goto err;
/* exit early if there are no domains */ if (lpar_name == NULL) {
if (nids_numdomains == 0 && nids_listdomains == 0) VIR_ERROR0(_("Unable to determine domain's name."));
goto exit;
else if (nids_numdomains != nids_listdomains) {
VIR_ERROR0(_("Unable to determine number of domains."));
goto err; goto err;
} }
phyp_driver = conn->privateData; if (phypGetLparUUID(def.uuid, dom->id, dom->conn) == -1) {
uuid_table = phyp_driver->uuid_table; VIR_ERROR0(_("Unable to generate random uuid."));
uuid_table->nlpars = nids_listdomains;
/* 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();
goto err; goto err;
} }
uuid_table->lpars[i]->id = ids[i];
if (virUUIDGenerate(uuid_table->lpars[i]->uuid) < 0) if ((def.maxmem =
VIR_WARN("Unable to generate UUID for domain %d", phypGetLparMem(dom->conn, managed_system, dom->id, 0)) == 0) {
ids[i]); VIR_ERROR0(_("Unable to determine domain's max memory."));
}
} else {
virReportOOMError();
goto err; goto err;
} }
if (phypUUIDTable_WriteFile(conn) == -1) if ((def.memory =
phypGetLparMem(dom->conn, managed_system, dom->id, 1)) == 0) {
VIR_ERROR0(_("Unable to determine domain's memory."));
goto err; goto err;
}
if (phypUUIDTable_Push(conn) == -1) if ((def.vcpus =
goto err; phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0) {
} else { VIR_ERROR0(_("Unable to determine domain's CPU."));
if (phypUUIDTable_ReadFile(conn) == -1)
goto err; goto err;
goto exit;
} }
exit: return virDomainDefFormat(&def, flags);
VIR_FREE(ids);
return 0;
err: err:
VIR_FREE(ids); return NULL;
return -1;
} }
void static int
phypUUIDTable_Free(uuid_tablePtr uuid_table) phypDomainResume(virDomainPtr dom)
{ {
int i; ConnectionData *connection_data = dom->conn->networkPrivateData;
phyp_driverPtr phyp_driver = dom->conn->privateData;
LIBSSH2_SESSION *session = connection_data->session;
int system_type = phyp_driver->system_type;
char *managed_system = phyp_driver->managed_system;
int exit_status = 0;
char *cmd = NULL;
char *ret = NULL;
virBuffer buf = VIR_BUFFER_INITIALIZER;
if (uuid_table == NULL) virBufferAddLit(&buf, "chsysstate");
return; if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " -r lpar -o on --id %d -f %s",
dom->id, dom->name);
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
return -1;
}
cmd = virBufferContentAndReset(&buf);
for (i = 0; i < uuid_table->nlpars; i++) ret = phypExec(session, cmd, &exit_status, dom->conn);
VIR_FREE(uuid_table->lpars[i]);
VIR_FREE(uuid_table->lpars); if (exit_status < 0)
VIR_FREE(uuid_table); goto err;
VIR_FREE(cmd);
VIR_FREE(ret);
return 0;
err:
VIR_FREE(cmd);
VIR_FREE(ret);
return -1;
} }
int static int
phypUUIDTable_Push(virConnectPtr conn) phypDomainShutdown(virDomainPtr dom)
{ {
ConnectionData *connection_data = conn->networkPrivateData; ConnectionData *connection_data = dom->conn->networkPrivateData;
virConnectPtr conn = dom->conn;
LIBSSH2_SESSION *session = connection_data->session; LIBSSH2_SESSION *session = connection_data->session;
LIBSSH2_CHANNEL *channel = NULL; phyp_driverPtr phyp_driver = conn->privateData;
virBuffer username = VIR_BUFFER_INITIALIZER; int system_type = phyp_driver->system_type;
struct stat local_fileinfo; char *managed_system = phyp_driver->managed_system;
char buffer[1024]; int exit_status = 0;
int rc = 0; char *cmd = NULL;
FILE *fd; char *ret = NULL;
size_t nread, sent; virBuffer buf = VIR_BUFFER_INITIALIZER;
char *ptr;
char local_file[] = "./uuid_table";
char *remote_file = NULL;
if (conn->uri->user != NULL) {
virBufferVSprintf(&username, "%s", conn->uri->user);
if (virBufferError(&username)) { virBufferAddLit(&buf, "chsysstate");
virBufferFreeAndReset(&username); if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " -r lpar -o shutdown --id %d", dom->id);
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError(); virReportOOMError();
goto err; return 0;
}
} }
cmd = virBufferContentAndReset(&buf);
if (virAsprintf ret = phypExec(session, cmd, &exit_status, dom->conn);
(&remote_file, "/home/%s/libvirt_uuid_table",
virBufferContentAndReset(&username))
< 0) {
virReportOOMError();
goto err;
}
if (stat(local_file, &local_fileinfo) == -1) { if (exit_status < 0)
VIR_WARN0("Unable to stat local file.");
goto err; goto err;
}
if (!(fd = fopen(local_file, "rb"))) { VIR_FREE(cmd);
VIR_WARN0("Unable to open local file."); VIR_FREE(ret);
goto err; return 0;
err:
VIR_FREE(cmd);
VIR_FREE(ret);
return 0;
}
static int
phypDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
{
phyp_driverPtr phyp_driver = dom->conn->privateData;
char *managed_system = phyp_driver->managed_system;
info->state = phypGetLparState(dom->conn, dom->id);
if ((info->maxMem =
phypGetLparMem(dom->conn, managed_system, dom->id, 0)) == 0)
VIR_WARN0("Unable to determine domain's max memory.");
if ((info->memory =
phypGetLparMem(dom->conn, managed_system, dom->id, 1)) == 0)
VIR_WARN0("Unable to determine domain's memory.");
if ((info->nrVirtCpu =
phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0)
VIR_WARN0("Unable to determine domain's CPU.");
return 0;
}
static int
phypDomainDestroy(virDomainPtr dom)
{
ConnectionData *connection_data = dom->conn->networkPrivateData;
phyp_driverPtr phyp_driver = dom->conn->privateData;
LIBSSH2_SESSION *session = connection_data->session;
int system_type = phyp_driver->system_type;
char *managed_system = phyp_driver->managed_system;
int exit_status = 0;
char *cmd = NULL;
char *ret = NULL;
virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferAddLit(&buf, "rmsyscfg");
if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " -r lpar --id %d", dom->id);
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
return -1;
} }
cmd = virBufferContentAndReset(&buf);
do { ret = phypExec(session, cmd, &exit_status, dom->conn);
channel =
libssh2_scp_send(session, remote_file,
0x1FF & local_fileinfo.st_mode,
(unsigned long) local_fileinfo.st_size);
if ((!channel) && (libssh2_session_last_errno(session) != if (exit_status < 0)
LIBSSH2_ERROR_EAGAIN))
goto err; goto err;
} while (!channel);
do { if (phypUUIDTable_RemLpar(dom->conn, dom->id) == -1)
nread = fread(buffer, 1, sizeof(buffer), fd);
if (nread <= 0) {
if (feof(fd)) {
/* end of file */
break;
} else {
VIR_ERROR(_("Failed to read from %s"), local_file);
goto err; goto err;
}
}
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 if (rc > 0) {
/* rc indicates how many bytes were written this time */
sent += rc;
}
ptr += sent;
nread -= sent;
} while (rc > 0 && sent < nread);
} while (1);
if (channel) { VIR_FREE(cmd);
libssh2_channel_send_eof(channel); VIR_FREE(ret);
libssh2_channel_wait_eof(channel);
libssh2_channel_wait_closed(channel);
libssh2_channel_free(channel);
channel = NULL;
}
virBufferFreeAndReset(&username);
return 0; return 0;
err: err:
if (channel) { VIR_FREE(cmd);
libssh2_channel_send_eof(channel); VIR_FREE(ret);
libssh2_channel_wait_eof(channel);
libssh2_channel_wait_closed(channel);
libssh2_channel_free(channel);
channel = NULL;
}
return -1; return -1;
} }
int static int
phypUUIDTable_Pull(virConnectPtr conn) phypBuildLpar(virConnectPtr conn, virDomainDefPtr def)
{ {
ConnectionData *connection_data = conn->networkPrivateData; ConnectionData *connection_data = conn->networkPrivateData;
phyp_driverPtr phyp_driver = conn->privateData;
LIBSSH2_SESSION *session = connection_data->session; LIBSSH2_SESSION *session = connection_data->session;
LIBSSH2_CHANNEL *channel = NULL; int system_type = phyp_driver->system_type;
virBuffer username = VIR_BUFFER_INITIALIZER; char *managed_system = phyp_driver->managed_system;
struct stat fileinfo; char *cmd = NULL;
char buffer[1024]; char *ret = NULL;
int rc = 0; int exit_status = 0;
int fd; virBuffer buf = VIR_BUFFER_INITIALIZER;
int got = 0;
int amount = 0;
int total = 0;
int sock = 0;
char local_file[] = "./uuid_table";
char *remote_file = NULL;
if (conn->uri->user != NULL) {
virBufferVSprintf(&username, "%s", conn->uri->user);
if (virBufferError(&username)) { virBufferAddLit(&buf, "mksyscfg");
virBufferFreeAndReset(&username); if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " -r lpar -p %s -i min_mem=%d,desired_mem=%d,"
"max_mem=%d,desired_procs=%d,virtual_scsi_adapters=%s",
def->name, (int) def->memory, (int) def->memory,
(int) def->maxmem, (int) def->vcpus, def->disks[0]->src);
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError(); virReportOOMError();
goto err; return -1;
} }
cmd = virBufferContentAndReset(&buf);
ret = phypExec(session, cmd, &exit_status, conn);
if (exit_status < 0) {
VIR_ERROR(_("Unable to create LPAR. Reason: '%s'"), ret);
goto err;
} }
if (virAsprintf if (phypUUIDTable_AddLpar(conn, def->uuid, def->id) == -1) {
(&remote_file, "/home/%s/libvirt_uuid_table", VIR_ERROR0(_("Unable to add LPAR to the table"));
virBufferContentAndReset(&username))
< 0) {
virReportOOMError();
goto err; goto err;
} }
/* Trying to stat the remote file. */ VIR_FREE(cmd);
do { VIR_FREE(ret);
channel = libssh2_scp_recv(session, remote_file, &fileinfo); return 0;
if (!channel) { err:
if (libssh2_session_last_errno(session) != VIR_FREE(cmd);
LIBSSH2_ERROR_EAGAIN) { VIR_FREE(ret);
goto err;; return -1;
} else { }
waitsocket(sock, session);
}
}
} while (!channel);
/* Creating a new data base based on remote file */ static virDomainPtr
if ((fd = creat(local_file, 0755)) == -1) phypDomainCreateAndStart(virConnectPtr conn,
goto err; const char *xml, unsigned int flags)
{
/* Request a file via SCP */ ConnectionData *connection_data = conn->networkPrivateData;
while (got < fileinfo.st_size) { LIBSSH2_SESSION *session = connection_data->session;
do { virDomainDefPtr def = NULL;
amount = sizeof(buffer); 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 ((fileinfo.st_size - got) < amount) { virCheckFlags(0, NULL);
amount = fileinfo.st_size - got;
}
rc = libssh2_channel_read(channel, buffer, amount); if (!(def = virDomainDefParseString(phyp_driver->caps, xml,
if (rc > 0) { VIR_DOMAIN_XML_SECURE)))
if (safewrite(fd, buffer, rc) != rc) goto err;
VIR_WARN0
("Unable to write information to local file.");
got += rc; /* checking if this name already exists on this system */
total += rc; if (phypGetLparID(session, managed_system, def->name, conn) == -1) {
VIR_WARN0("LPAR name already exists.");
goto err;
} }
} 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 */ /* checking if ID or UUID already exists on this system */
continue; for (i = 0; i < uuid_table->nlpars; i++) {
if (lpars[i]->id == def->id || lpars[i]->uuid == def->uuid) {
VIR_WARN0("LPAR ID or UUID already exists.");
goto err;
} }
break;
} }
close(fd);
goto exit;
exit: if ((dom = virGetDomain(conn, def->name, def->uuid)) == NULL)
if (channel) { goto err;
libssh2_channel_send_eof(channel);
libssh2_channel_wait_eof(channel); if (phypBuildLpar(conn, def) == -1)
libssh2_channel_wait_closed(channel); goto err;
libssh2_channel_free(channel);
channel = NULL; if (phypDomainResume(dom) == -1)
} goto err;
virBufferFreeAndReset(&username);
return 0; return dom;
err: err:
if (channel) { virDomainDefFree(def);
libssh2_channel_send_eof(channel); if (dom)
libssh2_channel_wait_eof(channel); virUnrefDomain(dom);
libssh2_channel_wait_closed(channel); return NULL;
libssh2_channel_free(channel);
channel = NULL;
}
return -1;
} }
int static char *
escape_specialcharacters(char *src, char *dst, size_t dstlen) phypConnectGetCapabilities(virConnectPtr conn)
{ {
size_t len = strlen(src); phyp_driverPtr phyp_driver = conn->privateData;
char temp_buffer[len]; char *xml;
unsigned int i = 0, j = 0;
if (len == 0)
return -1;
for (i = 0; i < len; i++) {
switch (src[i]) {
case '&':
case ';':
case '`':
case '@':
case '"':
case '|':
case '*':
case '?':
case '~':
case '<':
case '>':
case '^':
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
case '$':
case '%':
case '#':
case '\\':
case '\n':
case '\r':
case '\t':
continue;
default:
temp_buffer[j] = src[i];
j++;
}
}
temp_buffer[j] = '\0';
if (virStrcpy(dst, temp_buffer, dstlen) == NULL) if ((xml = virCapabilitiesFormatXML(phyp_driver->caps)) == NULL)
return -1; virReportOOMError();
return 0; return xml;
} }
int static int
waitsocket(int socket_fd, LIBSSH2_SESSION * session) phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus)
{ {
struct timeval timeout; ConnectionData *connection_data = dom->conn->networkPrivateData;
int rc; phyp_driverPtr phyp_driver = dom->conn->privateData;
fd_set fd; LIBSSH2_SESSION *session = connection_data->session;
fd_set *writefd = NULL; int system_type = phyp_driver->system_type;
fd_set *readfd = NULL; char *managed_system = phyp_driver->managed_system;
int dir; int exit_status = 0;
char *cmd = NULL;
char *ret = NULL;
char operation;
unsigned long ncpus = 0;
unsigned int amount = 0;
virBuffer buf = VIR_BUFFER_INITIALIZER;
timeout.tv_sec = 0; if ((ncpus = phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0)
timeout.tv_usec = 1000; return 0;
FD_ZERO(&fd); if (nvcpus > phypGetLparCPUMAX(dom)) {
VIR_ERROR0(_("You are trying to set a number of CPUs bigger than "
"the max possible."));
return 0;
}
FD_SET(socket_fd, &fd); if (ncpus > nvcpus) {
operation = 'r';
amount = nvcpus - ncpus;
} else if (ncpus < nvcpus) {
operation = 'a';
amount = nvcpus - ncpus;
} else
return 0;
/* now make sure we wait in the correct direction */ virBufferAddLit(&buf, "chhwres -r proc");
dir = libssh2_session_block_directions(session); if (system_type == HMC)
virBufferVSprintf(&buf, " -m %s", managed_system);
virBufferVSprintf(&buf, " --id %d -o %c --procunits %d 2>&1 |sed "
"-e 's/^.*\\([0-9][0-9]*.[0-9][0-9]*\\).*$/\\1/'",
dom->id, operation, amount);
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
return 0;
}
cmd = virBufferContentAndReset(&buf);
if (dir & LIBSSH2_SESSION_BLOCK_INBOUND) ret = phypExec(session, cmd, &exit_status, dom->conn);
readfd = &fd;
if (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) if (exit_status < 0) {
writefd = &fd; VIR_ERROR0(_
("Possibly you don't have IBM Tools installed in your LPAR."
" Contact your support to enable this feature."));
}
rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout); VIR_FREE(cmd);
VIR_FREE(ret);
return 0;
return rc;
} }
static virDriver phypDriver = {
VIR_DRV_PHYP, "PHYP", phypOpen, /* open */
phypClose, /* close */
NULL, /* supports_feature */
NULL, /* type */
NULL, /* version */
NULL, /* libvirtVersion (impl. in libvirt.c) */
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 */
phypDomainGetInfo, /* domainGetInfo */
NULL, /* domainSave */
NULL, /* domainRestore */
NULL, /* domainCoreDump */
phypDomainSetCPU, /* domainSetVcpus */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
phypGetLparCPUMAX, /* domainGetMaxVcpus */
NULL, /* domainGetSecurityLabel */
NULL, /* nodeGetSecurityModel */
phypDomainDumpXML, /* domainDumpXML */
NULL, /* domainXMLFromNative */
NULL, /* domainXMLToNative */
phypListDefinedDomains, /* listDefinedDomains */
phypNumDefinedDomains, /* numOfDefinedDomains */
NULL, /* domainCreate */
NULL, /* domainCreateWithFlags */
NULL, /* domainDefineXML */
NULL, /* domainUndefine */
NULL, /* domainAttachDevice */
NULL, /* domainAttachDeviceFlags */
NULL, /* domainDetachDevice */
NULL, /* domainDetachDeviceFlags */
NULL, /* domainUpdateDeviceFlags */
NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */
NULL, /* domainGetSchedulerType */
NULL, /* domainGetSchedulerParameters */
NULL, /* domainSetSchedulerParameters */
NULL, /* domainMigratePrepare */
NULL, /* domainMigratePerform */
NULL, /* domainMigrateFinish */
NULL, /* domainBlockStats */
NULL, /* domainInterfaceStats */
NULL, /* domainMemoryStats */
NULL, /* domainBlockPeek */
NULL, /* domainMemoryPeek */
NULL, /* domainGetBlockInfo */
NULL, /* nodeGetCellsFreeMemory */
NULL, /* getFreeMemory */
NULL, /* domainEventRegister */
NULL, /* domainEventDeregister */
NULL, /* domainMigratePrepare2 */
NULL, /* domainMigrateFinish2 */
NULL, /* nodeDeviceDettach */
NULL, /* nodeDeviceReAttach */
NULL, /* nodeDeviceReset */
NULL, /* domainMigratePrepareTunnel */
phypIsEncrypted, /* isEncrypted */
phypIsSecure, /* isSecure */
NULL, /* domainIsActive */
NULL, /* domainIsPersistent */
NULL, /* cpuCompare */
NULL, /* cpuBaseline */
NULL, /* domainGetJobInfo */
NULL, /* domainAbortJob */
NULL, /* domainMigrateSetMaxDowntime */
NULL, /* domainEventRegisterAny */
NULL, /* domainEventDeregisterAny */
NULL, /* domainManagedSave */
NULL, /* domainHasManagedSaveImage */
NULL, /* domainManagedSaveRemove */
NULL, /* domainSnapshotCreateXML */
NULL, /* domainSnapshotDumpXML */
NULL, /* domainSnapshotNum */
NULL, /* domainSnapshotListNames */
NULL, /* domainSnapshotLookupByName */
NULL, /* domainHasCurrentSnapshot */
NULL, /* domainSnapshotCurrent */
NULL, /* domainRevertToSnapshot */
NULL, /* domainSnapshotDelete */
};
int int
phypRegister(void) phypRegister(void)
{ {
......
/* /*
* Copyright (C) 2010 Red Hat, Inc.
* Copyright IBM Corp. 2009 * Copyright IBM Corp. 2009
* *
* phyp_driver.c: ssh layer to access Power Hypervisors * phyp_driver.c: ssh layer to access Power Hypervisors
...@@ -22,14 +22,17 @@ ...@@ -22,14 +22,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "conf/capabilities.h" #ifndef PHYP_DRIVER_H
#include "conf/domain_conf.h" # define PHYP_DRIVER_H
#include <config.h>
#include <libssh2.h> # include "conf/capabilities.h"
# include "conf/domain_conf.h"
# include <config.h>
# include <libssh2.h>
#define LPAR_EXEC_ERR -1 # define LPAR_EXEC_ERR -1
#define SSH_CONN_ERR -2 /* error while trying to connect to remote host */ # define SSH_CONN_ERR -2 /* error while trying to connect to remote host */
#define SSH_CMD_ERR -3 /* error while trying to execute the remote cmd */ # define SSH_CMD_ERR -3 /* error while trying to execute the remote cmd */
typedef struct _ConnectionData ConnectionData; typedef struct _ConnectionData ConnectionData;
typedef ConnectionData *ConnectionDataPtr; typedef ConnectionData *ConnectionDataPtr;
...@@ -75,60 +78,6 @@ struct _phyp_driver { ...@@ -75,60 +78,6 @@ struct _phyp_driver {
char *managed_system; char *managed_system;
}; };
int phypCheckSPFreeSapce(virConnectPtr conn, int required_size, char *sp);
int phypGetSystemType(virConnectPtr conn);
int phypGetVIOSPartitionID(virConnectPtr conn);
virCapsPtr phypCapsInit(void);
int phypBuildLpar(virConnectPtr conn, virDomainDefPtr def);
int phypUUIDTable_WriteFile(virConnectPtr conn);
int phypUUIDTable_ReadFile(virConnectPtr conn);
int phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id);
int phypUUIDTable_RemLpar(virConnectPtr conn, int id);
int phypUUIDTable_Pull(virConnectPtr conn);
int phypUUIDTable_Push(virConnectPtr conn);
int phypUUIDTable_Init(virConnectPtr conn);
void phypUUIDTable_Free(uuid_tablePtr uuid_table);
int escape_specialcharacters(char *src, char *dst, size_t dstlen);
int waitsocket(int socket_fd, LIBSSH2_SESSION * session);
int phypGetLparUUID(unsigned char *uuid, int lpar_id, virConnectPtr conn);
int phypRegister(void); int phypRegister(void);
int phypGetLparState(virConnectPtr conn, unsigned int lpar_id); #endif /* PHYP_DRIVER_H */
unsigned long phypGetLparMem(virConnectPtr conn,
const char *managed_system, int lpar_id,
int type);
unsigned long phypGetLparCPU(virConnectPtr conn,
const char *managed_system, int lpar_id);
unsigned long phypGetLparCPUGeneric(virConnectPtr conn,
const char *managed_system,
int lpar_id, int type);
int phypGetRemoteSlot(virConnectPtr conn, const char *managed_system,
const char *lpar_name);
char *phypGetBackingDevice(virConnectPtr conn, const char *managed_system,
char *lpar_name);
int phypDiskType(virConnectPtr conn, char *backing_device);
LIBSSH2_SESSION *openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
int *internal_socket);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册